diff options
| author | Mark Brown <broonie@linaro.org> | 2013-06-17 12:20:28 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2013-06-17 12:20:28 -0400 |
| commit | 5f5eb4efe575734e54f26c34ffffc4b48cdca3aa (patch) | |
| tree | a5cb60c08f3f7100606886a438f2c981a56d3240 | |
| parent | d238ffabc5e97c3e330995cf5e04d47279a8ff94 (diff) | |
| parent | fc09cfbe3e3535897456c12f37fa83024bdab92d (diff) | |
Merge remote-tracking branch 'asoc/topic/spear' into asoc-next
| -rw-r--r-- | sound/soc/Kconfig | 1 | ||||
| -rw-r--r-- | sound/soc/Makefile | 1 | ||||
| -rw-r--r-- | sound/soc/spear/Kconfig | 9 | ||||
| -rw-r--r-- | sound/soc/spear/Makefile | 8 | ||||
| -rw-r--r-- | sound/soc/spear/spdif_in.c | 31 | ||||
| -rw-r--r-- | sound/soc/spear/spdif_out.c | 43 | ||||
| -rw-r--r-- | sound/soc/spear/spear_pcm.c | 152 |
7 files changed, 52 insertions, 193 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 9e675c76436c..45eeaa9f7fec 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
| @@ -51,6 +51,7 @@ source "sound/soc/pxa/Kconfig" | |||
| 51 | source "sound/soc/samsung/Kconfig" | 51 | source "sound/soc/samsung/Kconfig" |
| 52 | source "sound/soc/s6000/Kconfig" | 52 | source "sound/soc/s6000/Kconfig" |
| 53 | source "sound/soc/sh/Kconfig" | 53 | source "sound/soc/sh/Kconfig" |
| 54 | source "sound/soc/spear/Kconfig" | ||
| 54 | source "sound/soc/tegra/Kconfig" | 55 | source "sound/soc/tegra/Kconfig" |
| 55 | source "sound/soc/txx9/Kconfig" | 56 | source "sound/soc/txx9/Kconfig" |
| 56 | source "sound/soc/ux500/Kconfig" | 57 | source "sound/soc/ux500/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 197b6ae54c8d..bc0261476d7a 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
| @@ -29,6 +29,7 @@ obj-$(CONFIG_SND_SOC) += pxa/ | |||
| 29 | obj-$(CONFIG_SND_SOC) += samsung/ | 29 | obj-$(CONFIG_SND_SOC) += samsung/ |
| 30 | obj-$(CONFIG_SND_SOC) += s6000/ | 30 | obj-$(CONFIG_SND_SOC) += s6000/ |
| 31 | obj-$(CONFIG_SND_SOC) += sh/ | 31 | obj-$(CONFIG_SND_SOC) += sh/ |
| 32 | obj-$(CONFIG_SND_SOC) += spear/ | ||
| 32 | obj-$(CONFIG_SND_SOC) += tegra/ | 33 | obj-$(CONFIG_SND_SOC) += tegra/ |
| 33 | obj-$(CONFIG_SND_SOC) += txx9/ | 34 | obj-$(CONFIG_SND_SOC) += txx9/ |
| 34 | obj-$(CONFIG_SND_SOC) += ux500/ | 35 | obj-$(CONFIG_SND_SOC) += ux500/ |
diff --git a/sound/soc/spear/Kconfig b/sound/soc/spear/Kconfig new file mode 100644 index 000000000000..3567d73b218e --- /dev/null +++ b/sound/soc/spear/Kconfig | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | config SND_SPEAR_SOC | ||
| 2 | tristate | ||
| 3 | select SND_SOC_DMAENGINE_PCM | ||
| 4 | |||
| 5 | config SND_SPEAR_SPDIF_OUT | ||
| 6 | tristate | ||
| 7 | |||
| 8 | config SND_SPEAR_SPDIF_IN | ||
| 9 | tristate | ||
diff --git a/sound/soc/spear/Makefile b/sound/soc/spear/Makefile new file mode 100644 index 000000000000..c4ea7161056c --- /dev/null +++ b/sound/soc/spear/Makefile | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | # SPEAR Platform Support | ||
| 2 | snd-soc-spear-pcm-objs := spear_pcm.o | ||
| 3 | snd-soc-spear-spdif-in-objs := spdif_in.o | ||
| 4 | snd-soc-spear-spdif-out-objs := spdif_out.o | ||
| 5 | |||
| 6 | obj-$(CONFIG_SND_SPEAR_SOC) += snd-soc-spear-pcm.o | ||
| 7 | obj-$(CONFIG_SND_SPEAR_SPDIF_IN) += snd-soc-spear-spdif-in.o | ||
| 8 | obj-$(CONFIG_SND_SPEAR_SPDIF_OUT) += snd-soc-spear-spdif-out.o | ||
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c index 14d57e89bcba..63acfeb4b69d 100644 --- a/sound/soc/spear/spdif_in.c +++ b/sound/soc/spear/spdif_in.c | |||
| @@ -49,15 +49,12 @@ static void spdif_in_configure(struct spdif_in_dev *host) | |||
| 49 | writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK); | 49 | writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | static int spdif_in_startup(struct snd_pcm_substream *substream, | 52 | static int spdif_in_dai_probe(struct snd_soc_dai *dai) |
| 53 | struct snd_soc_dai *cpu_dai) | ||
| 54 | { | 53 | { |
| 55 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(cpu_dai); | 54 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai); |
| 56 | 55 | ||
| 57 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) | 56 | dai->capture_dma_data = &host->dma_params; |
| 58 | return -EINVAL; | ||
| 59 | 57 | ||
| 60 | snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params); | ||
| 61 | return 0; | 58 | return 0; |
| 62 | } | 59 | } |
| 63 | 60 | ||
| @@ -70,7 +67,6 @@ static void spdif_in_shutdown(struct snd_pcm_substream *substream, | |||
| 70 | return; | 67 | return; |
| 71 | 68 | ||
| 72 | writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK); | 69 | writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK); |
| 73 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
| 74 | } | 70 | } |
| 75 | 71 | ||
| 76 | static void spdif_in_format(struct spdif_in_dev *host, u32 format) | 72 | static void spdif_in_format(struct spdif_in_dev *host, u32 format) |
| @@ -151,13 +147,13 @@ static int spdif_in_trigger(struct snd_pcm_substream *substream, int cmd, | |||
| 151 | } | 147 | } |
| 152 | 148 | ||
| 153 | static struct snd_soc_dai_ops spdif_in_dai_ops = { | 149 | static struct snd_soc_dai_ops spdif_in_dai_ops = { |
| 154 | .startup = spdif_in_startup, | ||
| 155 | .shutdown = spdif_in_shutdown, | 150 | .shutdown = spdif_in_shutdown, |
| 156 | .trigger = spdif_in_trigger, | 151 | .trigger = spdif_in_trigger, |
| 157 | .hw_params = spdif_in_hw_params, | 152 | .hw_params = spdif_in_hw_params, |
| 158 | }; | 153 | }; |
| 159 | 154 | ||
| 160 | struct snd_soc_dai_driver spdif_in_dai = { | 155 | static struct snd_soc_dai_driver spdif_in_dai = { |
| 156 | .probe = spdif_in_dai_probe, | ||
| 161 | .capture = { | 157 | .capture = { |
| 162 | .channels_min = 2, | 158 | .channels_min = 2, |
| 163 | .channels_max = 2, | 159 | .channels_max = 2, |
| @@ -235,7 +231,7 @@ static int spdif_in_probe(struct platform_device *pdev) | |||
| 235 | if (host->irq < 0) | 231 | if (host->irq < 0) |
| 236 | return -EINVAL; | 232 | return -EINVAL; |
| 237 | 233 | ||
| 238 | host->clk = clk_get(&pdev->dev, NULL); | 234 | host->clk = devm_clk_get(&pdev->dev, NULL); |
| 239 | if (IS_ERR(host->clk)) | 235 | if (IS_ERR(host->clk)) |
| 240 | return PTR_ERR(host->clk); | 236 | return PTR_ERR(host->clk); |
| 241 | 237 | ||
| @@ -257,34 +253,21 @@ static int spdif_in_probe(struct platform_device *pdev) | |||
| 257 | ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0, | 253 | ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0, |
| 258 | "spdif-in", host); | 254 | "spdif-in", host); |
| 259 | if (ret) { | 255 | if (ret) { |
| 260 | clk_put(host->clk); | ||
| 261 | dev_warn(&pdev->dev, "request_irq failed\n"); | 256 | dev_warn(&pdev->dev, "request_irq failed\n"); |
| 262 | return ret; | 257 | return ret; |
| 263 | } | 258 | } |
| 264 | 259 | ||
| 265 | ret = snd_soc_register_component(&pdev->dev, &spdif_in_component, | 260 | return snd_soc_register_component(&pdev->dev, &spdif_in_component, |
| 266 | &spdif_in_dai, 1); | 261 | &spdif_in_dai, 1); |
| 267 | if (ret != 0) { | ||
| 268 | clk_put(host->clk); | ||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | |||
| 272 | return 0; | ||
| 273 | } | 262 | } |
| 274 | 263 | ||
| 275 | static int spdif_in_remove(struct platform_device *pdev) | 264 | static int spdif_in_remove(struct platform_device *pdev) |
| 276 | { | 265 | { |
| 277 | struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev); | ||
| 278 | |||
| 279 | snd_soc_unregister_component(&pdev->dev); | 266 | snd_soc_unregister_component(&pdev->dev); |
| 280 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 281 | |||
| 282 | clk_put(host->clk); | ||
| 283 | 267 | ||
| 284 | return 0; | 268 | return 0; |
| 285 | } | 269 | } |
| 286 | 270 | ||
| 287 | |||
| 288 | static struct platform_driver spdif_in_driver = { | 271 | static struct platform_driver spdif_in_driver = { |
| 289 | .probe = spdif_in_probe, | 272 | .probe = spdif_in_probe, |
| 290 | .remove = spdif_in_remove, | 273 | .remove = spdif_in_remove, |
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index 1e3c3dda3598..2fdf68c98d22 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c | |||
| @@ -62,8 +62,6 @@ static int spdif_out_startup(struct snd_pcm_substream *substream, | |||
| 62 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) | 62 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) |
| 63 | return -EINVAL; | 63 | return -EINVAL; |
| 64 | 64 | ||
| 65 | snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params); | ||
| 66 | |||
| 67 | ret = clk_enable(host->clk); | 65 | ret = clk_enable(host->clk); |
| 68 | if (ret) | 66 | if (ret) |
| 69 | return ret; | 67 | return ret; |
| @@ -84,7 +82,6 @@ static void spdif_out_shutdown(struct snd_pcm_substream *substream, | |||
| 84 | 82 | ||
| 85 | clk_disable(host->clk); | 83 | clk_disable(host->clk); |
| 86 | host->running = false; | 84 | host->running = false; |
| 87 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
| 88 | } | 85 | } |
| 89 | 86 | ||
| 90 | static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq, | 87 | static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq, |
| @@ -243,8 +240,12 @@ static const struct snd_kcontrol_new spdif_out_controls[] = { | |||
| 243 | spdif_mute_get, spdif_mute_put), | 240 | spdif_mute_get, spdif_mute_put), |
| 244 | }; | 241 | }; |
| 245 | 242 | ||
| 246 | int spdif_soc_dai_probe(struct snd_soc_dai *dai) | 243 | static int spdif_soc_dai_probe(struct snd_soc_dai *dai) |
| 247 | { | 244 | { |
| 245 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); | ||
| 246 | |||
| 247 | dai->playback_dma_data = &host->dma_params; | ||
| 248 | |||
| 248 | return snd_soc_add_dai_controls(dai, spdif_out_controls, | 249 | return snd_soc_add_dai_controls(dai, spdif_out_controls, |
| 249 | ARRAY_SIZE(spdif_out_controls)); | 250 | ARRAY_SIZE(spdif_out_controls)); |
| 250 | } | 251 | } |
| @@ -281,30 +282,18 @@ static int spdif_out_probe(struct platform_device *pdev) | |||
| 281 | struct resource *res; | 282 | struct resource *res; |
| 282 | int ret; | 283 | int ret; |
| 283 | 284 | ||
| 284 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 285 | if (!res) | ||
| 286 | return -EINVAL; | ||
| 287 | |||
| 288 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
| 289 | resource_size(res), pdev->name)) { | ||
| 290 | dev_warn(&pdev->dev, "Failed to get memory resourse\n"); | ||
| 291 | return -ENOENT; | ||
| 292 | } | ||
| 293 | |||
| 294 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); | 285 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); |
| 295 | if (!host) { | 286 | if (!host) { |
| 296 | dev_warn(&pdev->dev, "kzalloc fail\n"); | 287 | dev_warn(&pdev->dev, "kzalloc fail\n"); |
| 297 | return -ENOMEM; | 288 | return -ENOMEM; |
| 298 | } | 289 | } |
| 299 | 290 | ||
| 300 | host->io_base = devm_ioremap(&pdev->dev, res->start, | 291 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 301 | resource_size(res)); | 292 | host->io_base = devm_ioremap_resource(&pdev->dev, res); |
| 302 | if (!host->io_base) { | 293 | if (IS_ERR(host->io_base)) |
| 303 | dev_warn(&pdev->dev, "ioremap failed\n"); | 294 | return PTR_ERR(host->io_base); |
| 304 | return -ENOMEM; | ||
| 305 | } | ||
| 306 | 295 | ||
| 307 | host->clk = clk_get(&pdev->dev, NULL); | 296 | host->clk = devm_clk_get(&pdev->dev, NULL); |
| 308 | if (IS_ERR(host->clk)) | 297 | if (IS_ERR(host->clk)) |
| 309 | return PTR_ERR(host->clk); | 298 | return PTR_ERR(host->clk); |
| 310 | 299 | ||
| @@ -320,22 +309,12 @@ static int spdif_out_probe(struct platform_device *pdev) | |||
| 320 | 309 | ||
| 321 | ret = snd_soc_register_component(&pdev->dev, &spdif_out_component, | 310 | ret = snd_soc_register_component(&pdev->dev, &spdif_out_component, |
| 322 | &spdif_out_dai, 1); | 311 | &spdif_out_dai, 1); |
| 323 | if (ret != 0) { | 312 | return ret; |
| 324 | clk_put(host->clk); | ||
| 325 | return ret; | ||
| 326 | } | ||
| 327 | |||
| 328 | return 0; | ||
| 329 | } | 313 | } |
| 330 | 314 | ||
| 331 | static int spdif_out_remove(struct platform_device *pdev) | 315 | static int spdif_out_remove(struct platform_device *pdev) |
| 332 | { | 316 | { |
| 333 | struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev); | ||
| 334 | |||
| 335 | snd_soc_unregister_component(&pdev->dev); | 317 | snd_soc_unregister_component(&pdev->dev); |
| 336 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 337 | |||
| 338 | clk_put(host->clk); | ||
| 339 | 318 | ||
| 340 | return 0; | 319 | return 0; |
| 341 | } | 320 | } |
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c index 2fbd4899d8ef..4707f2b862c3 100644 --- a/sound/soc/spear/spear_pcm.c +++ b/sound/soc/spear/spear_pcm.c | |||
| @@ -13,19 +13,13 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/dmaengine.h> | 15 | #include <linux/dmaengine.h> |
| 16 | #include <linux/dma-mapping.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 19 | #include <linux/scatterlist.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <sound/core.h> | ||
| 22 | #include <sound/dmaengine_pcm.h> | 17 | #include <sound/dmaengine_pcm.h> |
| 23 | #include <sound/pcm.h> | 18 | #include <sound/pcm.h> |
| 24 | #include <sound/pcm_params.h> | ||
| 25 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
| 26 | #include <sound/spear_dma.h> | 20 | #include <sound/spear_dma.h> |
| 27 | 21 | ||
| 28 | static struct snd_pcm_hardware spear_pcm_hardware = { | 22 | static const struct snd_pcm_hardware spear_pcm_hardware = { |
| 29 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 23 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
| 30 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 24 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
| 31 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), | 25 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), |
| @@ -37,149 +31,33 @@ static struct snd_pcm_hardware spear_pcm_hardware = { | |||
| 37 | .fifo_size = 0, /* fifo size in bytes */ | 31 | .fifo_size = 0, /* fifo size in bytes */ |
| 38 | }; | 32 | }; |
| 39 | 33 | ||
| 40 | static int spear_pcm_hw_params(struct snd_pcm_substream *substream, | 34 | static struct dma_chan *spear_pcm_request_chan(struct snd_soc_pcm_runtime *rtd, |
| 41 | struct snd_pcm_hw_params *params) | 35 | struct snd_pcm_substream *substream) |
| 42 | { | 36 | { |
| 43 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 37 | struct spear_dma_data *dma_data; |
| 44 | 38 | ||
| 45 | return 0; | 39 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
| 46 | } | ||
| 47 | |||
| 48 | static int spear_pcm_hw_free(struct snd_pcm_substream *substream) | ||
| 49 | { | ||
| 50 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
| 51 | |||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | static int spear_pcm_open(struct snd_pcm_substream *substream) | ||
| 56 | { | ||
| 57 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 58 | |||
| 59 | struct spear_dma_data *dma_data = (struct spear_dma_data *) | ||
| 60 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
| 61 | int ret; | ||
| 62 | |||
| 63 | ret = snd_soc_set_runtime_hwparams(substream, &spear_pcm_hardware); | ||
| 64 | if (ret) | ||
| 65 | return ret; | ||
| 66 | 40 | ||
| 67 | return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter, | 41 | return snd_dmaengine_pcm_request_channel(dma_data->filter, dma_data); |
| 68 | dma_data); | ||
| 69 | } | 42 | } |
| 70 | 43 | ||
| 71 | static int spear_pcm_mmap(struct snd_pcm_substream *substream, | 44 | static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = { |
| 72 | struct vm_area_struct *vma) | 45 | .pcm_hardware = &spear_pcm_hardware, |
| 73 | { | 46 | .compat_request_channel = spear_pcm_request_chan, |
| 74 | struct snd_pcm_runtime *runtime = substream->runtime; | 47 | .prealloc_buffer_size = 16 * 1024, |
| 75 | |||
| 76 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
| 77 | runtime->dma_area, runtime->dma_addr, | ||
| 78 | runtime->dma_bytes); | ||
| 79 | } | ||
| 80 | |||
| 81 | static struct snd_pcm_ops spear_pcm_ops = { | ||
| 82 | .open = spear_pcm_open, | ||
| 83 | .close = snd_dmaengine_pcm_close_release_chan, | ||
| 84 | .ioctl = snd_pcm_lib_ioctl, | ||
| 85 | .hw_params = spear_pcm_hw_params, | ||
| 86 | .hw_free = spear_pcm_hw_free, | ||
| 87 | .trigger = snd_dmaengine_pcm_trigger, | ||
| 88 | .pointer = snd_dmaengine_pcm_pointer, | ||
| 89 | .mmap = spear_pcm_mmap, | ||
| 90 | }; | ||
| 91 | |||
| 92 | static int | ||
| 93 | spear_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, | ||
| 94 | size_t size) | ||
| 95 | { | ||
| 96 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
| 97 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
| 98 | |||
| 99 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
| 100 | buf->dev.dev = pcm->card->dev; | ||
| 101 | buf->private_data = NULL; | ||
| 102 | |||
| 103 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
| 104 | &buf->addr, GFP_KERNEL); | ||
| 105 | if (!buf->area) | ||
| 106 | return -ENOMEM; | ||
| 107 | |||
| 108 | dev_info(buf->dev.dev, | ||
| 109 | " preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", | ||
| 110 | (void *)buf->area, (void *)buf->addr, size); | ||
| 111 | |||
| 112 | buf->bytes = size; | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static void spear_pcm_free(struct snd_pcm *pcm) | ||
| 117 | { | ||
| 118 | struct snd_pcm_substream *substream; | ||
| 119 | struct snd_dma_buffer *buf; | ||
| 120 | int stream; | ||
| 121 | |||
| 122 | for (stream = 0; stream < 2; stream++) { | ||
| 123 | substream = pcm->streams[stream].substream; | ||
| 124 | if (!substream) | ||
| 125 | continue; | ||
| 126 | |||
| 127 | buf = &substream->dma_buffer; | ||
| 128 | if (!buf || !buf->area) | ||
| 129 | continue; | ||
| 130 | |||
| 131 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
| 132 | buf->area, buf->addr); | ||
| 133 | buf->area = NULL; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | static u64 spear_pcm_dmamask = DMA_BIT_MASK(32); | ||
| 138 | |||
| 139 | static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
| 140 | { | ||
| 141 | struct snd_card *card = rtd->card->snd_card; | ||
| 142 | int ret; | ||
| 143 | |||
| 144 | if (!card->dev->dma_mask) | ||
| 145 | card->dev->dma_mask = &spear_pcm_dmamask; | ||
| 146 | if (!card->dev->coherent_dma_mask) | ||
| 147 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
| 148 | |||
| 149 | if (rtd->cpu_dai->driver->playback.channels_min) { | ||
| 150 | ret = spear_pcm_preallocate_dma_buffer(rtd->pcm, | ||
| 151 | SNDRV_PCM_STREAM_PLAYBACK, | ||
| 152 | spear_pcm_hardware.buffer_bytes_max); | ||
| 153 | if (ret) | ||
| 154 | return ret; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (rtd->cpu_dai->driver->capture.channels_min) { | ||
| 158 | ret = spear_pcm_preallocate_dma_buffer(rtd->pcm, | ||
| 159 | SNDRV_PCM_STREAM_CAPTURE, | ||
| 160 | spear_pcm_hardware.buffer_bytes_max); | ||
| 161 | if (ret) | ||
| 162 | return ret; | ||
| 163 | } | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | static struct snd_soc_platform_driver spear_soc_platform = { | ||
| 169 | .ops = &spear_pcm_ops, | ||
| 170 | .pcm_new = spear_pcm_new, | ||
| 171 | .pcm_free = spear_pcm_free, | ||
| 172 | }; | 48 | }; |
| 173 | 49 | ||
| 174 | static int spear_soc_platform_probe(struct platform_device *pdev) | 50 | static int spear_soc_platform_probe(struct platform_device *pdev) |
| 175 | { | 51 | { |
| 176 | return snd_soc_register_platform(&pdev->dev, &spear_soc_platform); | 52 | return snd_dmaengine_pcm_register(&pdev->dev, |
| 53 | &spear_dmaengine_pcm_config, | ||
| 54 | SND_DMAENGINE_PCM_FLAG_NO_DT | | ||
| 55 | SND_DMAENGINE_PCM_FLAG_COMPAT); | ||
| 177 | } | 56 | } |
| 178 | 57 | ||
| 179 | static int spear_soc_platform_remove(struct platform_device *pdev) | 58 | static int spear_soc_platform_remove(struct platform_device *pdev) |
| 180 | { | 59 | { |
| 181 | snd_soc_unregister_platform(&pdev->dev); | 60 | snd_dmaengine_pcm_unregister(&pdev->dev); |
| 182 | |||
| 183 | return 0; | 61 | return 0; |
| 184 | } | 62 | } |
| 185 | 63 | ||
