diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/ux500-mop500.txt | 22 | ||||
-rw-r--r-- | arch/arm/boot/dts/ste-dbx5x0.dtsi | 5 | ||||
-rw-r--r-- | arch/arm/boot/dts/ste-href.dtsi | 21 | ||||
-rw-r--r-- | arch/arm/boot/dts/ste-snowball.dts | 21 | ||||
-rw-r--r-- | sound/soc/soc-pcm.c | 1 | ||||
-rw-r--r-- | sound/soc/ux500/mop500.c | 177 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_pcm.c | 76 |
7 files changed, 151 insertions, 172 deletions
diff --git a/Documentation/devicetree/bindings/sound/ux500-mop500.txt b/Documentation/devicetree/bindings/sound/ux500-mop500.txt index 48e071c96b46..fab67a19b59b 100644 --- a/Documentation/devicetree/bindings/sound/ux500-mop500.txt +++ b/Documentation/devicetree/bindings/sound/ux500-mop500.txt @@ -6,8 +6,6 @@ Required properties: - compatible : "stericsson,snd-soc-mop500" Non-standard properties: - - stericsson,cpu-dai : Phandle to the CPU-side DAI - - stericsson,audio-codec : Phandle to the Audio CODEC - stericsson,card-name : Over-ride default card name Example: @@ -15,8 +13,24 @@ Example: sound { compatible = "stericsson,snd-soc-mop500"; - stericsson,cpu-dai = <&msp1 &msp3>; - stericsson,audio-codec = <&codec>; + ab8500-codec-playback-dai-link@0 { + link-name = "AB8500 codec playback"; + cpu { + sound-dai = <&msp1>; + }; + codec { + sound-dai = <&codec>; + }; + }; + ab8500-codec-record-dai-link@0 { + link-name = "AB8500 codec record"; + cpu { + sound-dai = <&msp3>; + }; + codec { + sound-dai = <&codec>; + }; + }; }; msp1: msp@80124000 { diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index a8d60f911be7..f5efd922f0af 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -703,6 +703,7 @@ codec: ab8500-codec { compatible = "stericsson,ab8500-codec"; + #sound-dai-cells = <0>; V-AUD-supply = <&ab8500_ldo_audio_reg>; V-AMIC1-supply = <&ab8500_ldo_anamic1_reg>; @@ -1112,6 +1113,7 @@ reg = <0x80123000 0x1000>; interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; v-ape-supply = <&db8500_vape_reg>; + #sound-dai-cells = <0>; dmas = <&dma 31 0 0x12>, /* Logical - DevToMem - HighPrio */ <&dma 31 0 0x10>; /* Logical - MemToDev - HighPrio */ @@ -1128,6 +1130,7 @@ reg = <0x80124000 0x1000>; interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; v-ape-supply = <&db8500_vape_reg>; + #sound-dai-cells = <0>; /* This DMA channel only exist on DB8500 v1 */ dmas = <&dma 30 0 0x10>; /* Logical - MemToDev - HighPrio */ @@ -1145,6 +1148,7 @@ reg = <0x80117000 0x1000>; interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; v-ape-supply = <&db8500_vape_reg>; + #sound-dai-cells = <0>; dmas = <&dma 14 0 0x12>, /* Logical - DevToMem - HighPrio */ <&dma 14 1 0x19>; /* Physical Chan 1 - MemToDev @@ -1162,6 +1166,7 @@ reg = <0x80125000 0x1000>; interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; v-ape-supply = <&db8500_vape_reg>; + #sound-dai-cells = <0>; /* This DMA channel only exist on DB8500 v2 */ dmas = <&dma 30 0 0x12>; /* Logical - DevToMem - HighPrio */ diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi index 312d246b3b11..743bac93b256 100644 --- a/arch/arm/boot/dts/ste-href.dtsi +++ b/arch/arm/boot/dts/ste-href.dtsi @@ -21,10 +21,27 @@ sound { compatible = "stericsson,snd-soc-mop500"; stericsson,card-name = "HREF500-audio"; - stericsson,cpu-dai = <&msp1>, <&msp3>; - stericsson,audio-codec = <&codec>; clocks = <&prcmu_clk PRCMU_SYSCLK>, <&ab8500_clock AB8500_SYSCLK_ULP>, <&ab8500_clock AB8500_SYSCLK_INT>; clock-names = "sysclk", "ulpclk", "intclk"; + + ab8500-codec-playback-dai-link@0 { + link-name = "AB8500 codec playback"; + cpu { + sound-dai = <&msp1>; + }; + codec { + sound-dai = <&codec>; + }; + }; + ab8500-codec-record-dai-link@1 { + link-name = "AB8500 codec record"; + cpu { + sound-dai = <&msp3>; + }; + codec { + sound-dai = <&codec>; + }; + }; }; soc { diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts index 783d0ac4c64a..a4787b8c678b 100644 --- a/arch/arm/boot/dts/ste-snowball.dts +++ b/arch/arm/boot/dts/ste-snowball.dts @@ -97,10 +97,27 @@ sound { compatible = "stericsson,snd-soc-mop500"; stericsson,card-name = "Snowball-audio"; - stericsson,cpu-dai = <&msp1>, <&msp3>; - stericsson,audio-codec = <&codec>; clocks = <&prcmu_clk PRCMU_SYSCLK>, <&ab8500_clock AB8500_SYSCLK_ULP>, <&ab8500_clock AB8500_SYSCLK_INT>; clock-names = "sysclk", "ulpclk", "intclk"; + + ab8500-codec-playback-dai-link@0 { + link-name = "AB8500 codec playback"; + cpu { + sound-dai = <&msp1>; + }; + codec { + sound-dai = <&codec>; + }; + }; + ab8500-codec-record-dai-link@0 { + link-name = "AB8500 codec record"; + cpu { + sound-dai = <&msp3>; + }; + codec { + sound-dai = <&codec>; + }; + }; }; soc { diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 084125463d10..d326c7e0cf48 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -3029,6 +3029,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, num); + dev_info(rtd->card->dev, "call snd_pcm_new(%d) \"%s\" playback=%d, capture=%d\n", num, new_name, playback, capture); ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, capture, &pcm); } diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 461fc39f4601..5a06489450c2 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -23,107 +23,104 @@ #include "ux500_pcm.h" #include "ux500_msp_dai.h" - #include "mop500_ab8500.h" -/* Define the whole MOP500 soundcard, linking platform to the codec-drivers */ -static struct snd_soc_dai_link mop500_dai_links[] = { - { - .name = "ab8500_0", - .stream_name = "ab8500_0", - .codec_dai_name = "ab8500-codec-dai.0", - .init = mop500_ab8500_machine_init, - .ops = mop500_ab8500_ops, - }, - { - .name = "ab8500_1", - .stream_name = "ab8500_1", - .codec_dai_name = "ab8500-codec-dai.1", - .ops = mop500_ab8500_ops, - }, -}; - -static struct snd_soc_card mop500_card = { - .name = "MOP500-card", - .owner = THIS_MODULE, - .probe = NULL, - .dai_link = mop500_dai_links, - .num_links = ARRAY_SIZE(mop500_dai_links), +/** + * struct ux500_sound_data - state container for the sound card + * @card: the card we're providing data for + * @dai_link: the digital audio interface link + */ +struct ux500_sound_data { + struct snd_soc_card *card; + /* This array expands downward to fit the links */ + struct snd_soc_dai_link dai_link[]; }; -static void mop500_of_node_put(void) -{ - int i; - - for (i = 0; i < 2; i++) { - of_node_put(mop500_dai_links[i].cpu_of_node); - of_node_put(mop500_dai_links[i].codec_of_node); - } -} - -static int mop500_of_probe(struct platform_device *pdev, - struct device_node *np) -{ - struct device_node *codec_np, *msp_np[2]; - int i; - - msp_np[0] = of_parse_phandle(np, "stericsson,cpu-dai", 0); - msp_np[1] = of_parse_phandle(np, "stericsson,cpu-dai", 1); - codec_np = of_parse_phandle(np, "stericsson,audio-codec", 0); - - if (!(msp_np[0] && msp_np[1] && codec_np)) { - dev_err(&pdev->dev, "Phandle missing or invalid\n"); - mop500_of_node_put(); - return -EINVAL; - } - - for (i = 0; i < 2; i++) { - mop500_dai_links[i].cpu_of_node = msp_np[i]; - mop500_dai_links[i].cpu_dai_name = NULL; - mop500_dai_links[i].platform_of_node = msp_np[i]; - mop500_dai_links[i].platform_name = NULL; - mop500_dai_links[i].codec_of_node = codec_np; - mop500_dai_links[i].codec_name = NULL; - } - - snd_soc_of_parse_card_name(&mop500_card, "stericsson,card-name"); - - return 0; -} - static int mop500_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; - int ret; - - mop500_card.dev = &pdev->dev; - - ret = mop500_of_probe(pdev, np); + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct device_node *np, *codec, *cpu; + struct snd_soc_card *card; + struct snd_soc_dai_link *link; + struct ux500_sound_data *data; + int ret, num_links; + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + card->dev = dev; + + ret = snd_soc_of_parse_card_name(card, "stericsson,card-name"); if (ret) return ret; - dev_dbg(&pdev->dev, "%s: Card %s: Set platform drvdata.\n", - __func__, mop500_card.name); - - snd_soc_card_set_drvdata(&mop500_card, NULL); - - ret = snd_soc_register_card(&mop500_card); + /* Uses static routes for now */ +#if 0 + ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); if (ret) - dev_err(&pdev->dev, - "Error: snd_soc_register_card failed (%d)!\n", ret); - - return ret; -} - -static int mop500_remove(struct platform_device *pdev) -{ - struct snd_soc_card *mop500_card = platform_get_drvdata(pdev); + return ret; +#endif + + /* Populate DAI links */ + num_links = of_get_child_count(node); + + /* Allocate the private data and the DAI link array */ + data = devm_kzalloc(dev, sizeof(*data) + sizeof(*link) * num_links, + GFP_KERNEL); + if (!data) + return -ENOMEM; + data->card = card; + + card->dai_link = &data->dai_link[0]; + card->num_links = num_links; + link = data->dai_link; + + for_each_child_of_node(node, np) { + cpu = of_get_child_by_name(np, "cpu"); + codec = of_get_child_by_name(np, "codec"); + + if (!cpu || !codec) { + dev_err(dev, "Can't find cpu/codec DT node\n"); + return -EINVAL; + } + + link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); + if (!link->cpu_of_node) { + dev_err(card->dev, "error getting cpu phandle\n"); + return -EINVAL; + } + + ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); + if (ret) { + dev_err(card->dev, "error getting cpu dai name\n"); + return ret; + } + + ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); + if (ret < 0) { + dev_err(card->dev, "error getting codec dai link\n"); + return ret; + } + + link->platform_of_node = link->cpu_of_node; + ret = of_property_read_string(np, "link-name", &link->name); + if (ret) { + dev_err(card->dev, "error getting codec DAI link name\n"); + return ret; + } + + link->stream_name = link->name; + // link->init = ux500_sound_dai_init; + // link->ops = &ux500_sound_ops; + dev_info(dev, "parsed link \"%s\"\n", link->name); + link++; + } - snd_soc_unregister_card(mop500_card); - mop500_ab8500_remove(mop500_card); - mop500_of_node_put(); + platform_set_drvdata(pdev, data); + snd_soc_card_set_drvdata(card, data); - return 0; + return devm_snd_soc_register_card(dev, card); } static const struct of_device_id snd_soc_mop500_match[] = { @@ -138,9 +135,7 @@ static struct platform_driver snd_soc_mop500_driver = { .of_match_table = snd_soc_mop500_match, }, .probe = mop500_probe, - .remove = mop500_remove, }; - module_platform_driver(snd_soc_mop500_driver); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index 0f5ca173e930..1cecaf80da24 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -46,80 +46,10 @@ static const struct snd_pcm_hardware ux500_pcm_hw = { .periods_max = UX500_PLATFORM_PERIODS_MAX, }; -static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) -{ - struct snd_soc_dai *dai = rtd->cpu_dai; - u16 per_data_width, mem_data_width; - struct stedma40_chan_cfg *dma_cfg; - struct ux500_msp_dma_params *dma_params; - - dma_params = snd_soc_dai_get_dma_data(dai, substream); - dma_cfg = dma_params->dma_cfg; - - mem_data_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - - switch (dma_params->data_size) { - case 32: - per_data_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - break; - case 16: - per_data_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - break; - case 8: - per_data_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - break; - default: - per_data_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - dma_cfg->src_info.data_width = mem_data_width; - dma_cfg->dst_info.data_width = per_data_width; - } else { - dma_cfg->src_info.data_width = per_data_width; - dma_cfg->dst_info.data_width = mem_data_width; - } - - return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg); -} - -static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct dma_slave_config *slave_config) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_dmaengine_dai_dma_data *snd_dma_params; - dma_addr_t dma_addr; - int ret; - - snd_dma_params = - snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - dma_addr = snd_dma_params->addr; - - ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); - if (ret) - return ret; - - slave_config->dst_maxburst = 4; - slave_config->src_maxburst = 4; - - slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - slave_config->dst_addr = dma_addr; - else - slave_config->src_addr = dma_addr; - - return 0; -} - static const struct snd_dmaengine_pcm_config ux500_dmaengine_of_pcm_config = { - .pcm_hardware = &ux500_pcm_hw, /* FIXME: from devicetree?? */ - .prealloc_buffer_size = 128 * 1024, /* FIXME: from devicetree ?? */ - .compat_request_channel = ux500_pcm_request_chan, - .prepare_slave_config = ux500_pcm_prepare_slave_config, + .pcm_hardware = &ux500_pcm_hw, + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, + .prealloc_buffer_size = UX500_PLATFORM_BUFFER_BYTES_MAX, }; int ux500_pcm_register_platform(struct platform_device *pdev) |