diff options
Diffstat (limited to 'sound/soc')
269 files changed, 15374 insertions, 3634 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 1d651b8a8957..225bfda414e9 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -57,6 +57,7 @@ source "sound/soc/samsung/Kconfig" | |||
57 | source "sound/soc/sh/Kconfig" | 57 | source "sound/soc/sh/Kconfig" |
58 | source "sound/soc/sirf/Kconfig" | 58 | source "sound/soc/sirf/Kconfig" |
59 | source "sound/soc/spear/Kconfig" | 59 | source "sound/soc/spear/Kconfig" |
60 | source "sound/soc/sti/Kconfig" | ||
60 | source "sound/soc/tegra/Kconfig" | 61 | source "sound/soc/tegra/Kconfig" |
61 | source "sound/soc/txx9/Kconfig" | 62 | source "sound/soc/txx9/Kconfig" |
62 | source "sound/soc/ux500/Kconfig" | 63 | source "sound/soc/ux500/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 669648b41d30..134aca150a50 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -39,6 +39,7 @@ obj-$(CONFIG_SND_SOC) += samsung/ | |||
39 | obj-$(CONFIG_SND_SOC) += sh/ | 39 | obj-$(CONFIG_SND_SOC) += sh/ |
40 | obj-$(CONFIG_SND_SOC) += sirf/ | 40 | obj-$(CONFIG_SND_SOC) += sirf/ |
41 | obj-$(CONFIG_SND_SOC) += spear/ | 41 | obj-$(CONFIG_SND_SOC) += spear/ |
42 | obj-$(CONFIG_SND_SOC) += sti/ | ||
42 | obj-$(CONFIG_SND_SOC) += tegra/ | 43 | obj-$(CONFIG_SND_SOC) += tegra/ |
43 | obj-$(CONFIG_SND_SOC) += txx9/ | 44 | obj-$(CONFIG_SND_SOC) += txx9/ |
44 | obj-$(CONFIG_SND_SOC) += ux500/ | 45 | obj-$(CONFIG_SND_SOC) += ux500/ |
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 841d05946b88..ba8def5665c4 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -290,7 +290,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, | |||
290 | int dir, dir_mask; | 290 | int dir, dir_mask; |
291 | int ret; | 291 | int ret; |
292 | 292 | ||
293 | pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", | 293 | pr_debug("atmel_ssc_startup: SSC_SR=0x%x\n", |
294 | ssc_readl(ssc_p->ssc->regs, SR)); | 294 | ssc_readl(ssc_p->ssc->regs, SR)); |
295 | 295 | ||
296 | /* Enable PMC peripheral clock for this SSC */ | 296 | /* Enable PMC peripheral clock for this SSC */ |
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index dd94fea72d5d..5741c0aa6c03 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c | |||
@@ -344,14 +344,8 @@ static int au1xpsc_pcm_drvprobe(struct platform_device *pdev) | |||
344 | 344 | ||
345 | platform_set_drvdata(pdev, dmadata); | 345 | platform_set_drvdata(pdev, dmadata); |
346 | 346 | ||
347 | return snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); | 347 | return devm_snd_soc_register_platform(&pdev->dev, |
348 | } | 348 | &au1xpsc_soc_platform); |
349 | |||
350 | static int au1xpsc_pcm_drvremove(struct platform_device *pdev) | ||
351 | { | ||
352 | snd_soc_unregister_platform(&pdev->dev); | ||
353 | |||
354 | return 0; | ||
355 | } | 349 | } |
356 | 350 | ||
357 | static struct platform_driver au1xpsc_pcm_driver = { | 351 | static struct platform_driver au1xpsc_pcm_driver = { |
@@ -359,7 +353,6 @@ static struct platform_driver au1xpsc_pcm_driver = { | |||
359 | .name = "au1xpsc-pcm", | 353 | .name = "au1xpsc-pcm", |
360 | }, | 354 | }, |
361 | .probe = au1xpsc_pcm_drvprobe, | 355 | .probe = au1xpsc_pcm_drvprobe, |
362 | .remove = au1xpsc_pcm_drvremove, | ||
363 | }; | 356 | }; |
364 | 357 | ||
365 | module_platform_driver(au1xpsc_pcm_driver); | 358 | module_platform_driver(au1xpsc_pcm_driver); |
diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c index 24cc7f40d87a..fcf5a9adde81 100644 --- a/sound/soc/au1x/dma.c +++ b/sound/soc/au1x/dma.c | |||
@@ -312,14 +312,8 @@ static int alchemy_pcm_drvprobe(struct platform_device *pdev) | |||
312 | 312 | ||
313 | platform_set_drvdata(pdev, ctx); | 313 | platform_set_drvdata(pdev, ctx); |
314 | 314 | ||
315 | return snd_soc_register_platform(&pdev->dev, &alchemy_pcm_soc_platform); | 315 | return devm_snd_soc_register_platform(&pdev->dev, |
316 | } | 316 | &alchemy_pcm_soc_platform); |
317 | |||
318 | static int alchemy_pcm_drvremove(struct platform_device *pdev) | ||
319 | { | ||
320 | snd_soc_unregister_platform(&pdev->dev); | ||
321 | |||
322 | return 0; | ||
323 | } | 317 | } |
324 | 318 | ||
325 | static struct platform_driver alchemy_pcmdma_driver = { | 319 | static struct platform_driver alchemy_pcmdma_driver = { |
@@ -327,7 +321,6 @@ static struct platform_driver alchemy_pcmdma_driver = { | |||
327 | .name = "alchemy-pcm-dma", | 321 | .name = "alchemy-pcm-dma", |
328 | }, | 322 | }, |
329 | .probe = alchemy_pcm_drvprobe, | 323 | .probe = alchemy_pcm_drvprobe, |
330 | .remove = alchemy_pcm_drvremove, | ||
331 | }; | 324 | }; |
332 | 325 | ||
333 | module_platform_driver(alchemy_pcmdma_driver); | 326 | module_platform_driver(alchemy_pcmdma_driver); |
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index e742ef668496..38e853add96e 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c | |||
@@ -305,19 +305,9 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
305 | return -ENOMEM; | 305 | return -ENOMEM; |
306 | 306 | ||
307 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 307 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
308 | if (!iores) | 308 | wd->mmio = devm_ioremap_resource(&pdev->dev, iores); |
309 | return -ENODEV; | 309 | if (IS_ERR(wd->mmio)) |
310 | 310 | return PTR_ERR(wd->mmio); | |
311 | ret = -EBUSY; | ||
312 | if (!devm_request_mem_region(&pdev->dev, iores->start, | ||
313 | resource_size(iores), | ||
314 | pdev->name)) | ||
315 | return -EBUSY; | ||
316 | |||
317 | wd->mmio = devm_ioremap(&pdev->dev, iores->start, | ||
318 | resource_size(iores)); | ||
319 | if (!wd->mmio) | ||
320 | return -EBUSY; | ||
321 | 311 | ||
322 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 312 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
323 | if (!dmares) | 313 | if (!dmares) |
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index 03fa1cbf8ec1..8c435beb263d 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c | |||
@@ -862,6 +862,8 @@ static const struct of_device_id bcm2835_i2s_of_match[] = { | |||
862 | {}, | 862 | {}, |
863 | }; | 863 | }; |
864 | 864 | ||
865 | MODULE_DEVICE_TABLE(of, bcm2835_i2s_of_match); | ||
866 | |||
865 | static struct platform_driver bcm2835_i2s_driver = { | 867 | static struct platform_driver bcm2835_i2s_driver = { |
866 | .probe = bcm2835_i2s_probe, | 868 | .probe = bcm2835_i2s_probe, |
867 | .driver = { | 869 | .driver = { |
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 238913e030e0..02ad2606fa19 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -450,13 +450,8 @@ static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = { | |||
450 | 450 | ||
451 | static int bf5xx_soc_platform_probe(struct platform_device *pdev) | 451 | static int bf5xx_soc_platform_probe(struct platform_device *pdev) |
452 | { | 452 | { |
453 | return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform); | 453 | return devm_snd_soc_register_platform(&pdev->dev, |
454 | } | 454 | &bf5xx_ac97_soc_platform); |
455 | |||
456 | static int bf5xx_soc_platform_remove(struct platform_device *pdev) | ||
457 | { | ||
458 | snd_soc_unregister_platform(&pdev->dev); | ||
459 | return 0; | ||
460 | } | 455 | } |
461 | 456 | ||
462 | static struct platform_driver bf5xx_pcm_driver = { | 457 | static struct platform_driver bf5xx_pcm_driver = { |
@@ -465,7 +460,6 @@ static struct platform_driver bf5xx_pcm_driver = { | |||
465 | }, | 460 | }, |
466 | 461 | ||
467 | .probe = bf5xx_soc_platform_probe, | 462 | .probe = bf5xx_soc_platform_probe, |
468 | .remove = bf5xx_soc_platform_remove, | ||
469 | }; | 463 | }; |
470 | 464 | ||
471 | module_platform_driver(bf5xx_pcm_driver); | 465 | module_platform_driver(bf5xx_pcm_driver); |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index d95477afcc67..6cba211da32e 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -342,13 +342,8 @@ static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = { | |||
342 | 342 | ||
343 | static int bfin_i2s_soc_platform_probe(struct platform_device *pdev) | 343 | static int bfin_i2s_soc_platform_probe(struct platform_device *pdev) |
344 | { | 344 | { |
345 | return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform); | 345 | return devm_snd_soc_register_platform(&pdev->dev, |
346 | } | 346 | &bf5xx_i2s_soc_platform); |
347 | |||
348 | static int bfin_i2s_soc_platform_remove(struct platform_device *pdev) | ||
349 | { | ||
350 | snd_soc_unregister_platform(&pdev->dev); | ||
351 | return 0; | ||
352 | } | 347 | } |
353 | 348 | ||
354 | static struct platform_driver bfin_i2s_pcm_driver = { | 349 | static struct platform_driver bfin_i2s_pcm_driver = { |
@@ -357,7 +352,6 @@ static struct platform_driver bfin_i2s_pcm_driver = { | |||
357 | }, | 352 | }, |
358 | 353 | ||
359 | .probe = bfin_i2s_soc_platform_probe, | 354 | .probe = bfin_i2s_soc_platform_probe, |
360 | .remove = bfin_i2s_soc_platform_remove, | ||
361 | }; | 355 | }; |
362 | 356 | ||
363 | module_platform_driver(bfin_i2s_pcm_driver); | 357 | module_platform_driver(bfin_i2s_pcm_driver); |
diff --git a/sound/soc/blackfin/bfin-eval-adau1x61.c b/sound/soc/blackfin/bfin-eval-adau1x61.c index 4229f76daec9..fddfe00c9d69 100644 --- a/sound/soc/blackfin/bfin-eval-adau1x61.c +++ b/sound/soc/blackfin/bfin-eval-adau1x61.c | |||
@@ -108,6 +108,7 @@ static struct snd_soc_dai_link bfin_eval_adau1x61_dai = { | |||
108 | 108 | ||
109 | static struct snd_soc_card bfin_eval_adau1x61 = { | 109 | static struct snd_soc_card bfin_eval_adau1x61 = { |
110 | .name = "bfin-eval-adau1x61", | 110 | .name = "bfin-eval-adau1x61", |
111 | .owner = THIS_MODULE, | ||
111 | .driver_name = "eval-adau1x61", | 112 | .driver_name = "eval-adau1x61", |
112 | .dai_link = &bfin_eval_adau1x61_dai, | 113 | .dai_link = &bfin_eval_adau1x61_dai, |
113 | .num_links = 1, | 114 | .num_links = 1, |
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 38b3dad9d48a..e8bed6b0c9db 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -156,33 +156,29 @@ static const DECLARE_TLV_DB_SCALE(dpga_tlv, -9450, 150, 1); | |||
156 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -900, 300, 0); | 156 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -900, 300, 0); |
157 | 157 | ||
158 | /* {-23, -17, -13.5, -11, -9, -6, -3, 0}dB */ | 158 | /* {-23, -17, -13.5, -11, -9, -6, -3, 0}dB */ |
159 | static const unsigned int mic_tlv[] = { | 159 | static const DECLARE_TLV_DB_RANGE(mic_tlv, |
160 | TLV_DB_RANGE_HEAD(5), | ||
161 | 0, 0, TLV_DB_SCALE_ITEM(-2300, 0, 0), | 160 | 0, 0, TLV_DB_SCALE_ITEM(-2300, 0, 0), |
162 | 1, 1, TLV_DB_SCALE_ITEM(-1700, 0, 0), | 161 | 1, 1, TLV_DB_SCALE_ITEM(-1700, 0, 0), |
163 | 2, 2, TLV_DB_SCALE_ITEM(-1350, 0, 0), | 162 | 2, 2, TLV_DB_SCALE_ITEM(-1350, 0, 0), |
164 | 3, 3, TLV_DB_SCALE_ITEM(-1100, 0, 0), | 163 | 3, 3, TLV_DB_SCALE_ITEM(-1100, 0, 0), |
165 | 4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0), | 164 | 4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0) |
166 | }; | 165 | ); |
167 | 166 | ||
168 | /* {0, 0, 0, -6, 0, 6, 12, 18}dB */ | 167 | /* {0, 0, 0, -6, 0, 6, 12, 18}dB */ |
169 | static const unsigned int aux_tlv[] = { | 168 | static const DECLARE_TLV_DB_RANGE(aux_tlv, |
170 | TLV_DB_RANGE_HEAD(2), | ||
171 | 0, 2, TLV_DB_SCALE_ITEM(0, 0, 0), | 169 | 0, 2, TLV_DB_SCALE_ITEM(0, 0, 0), |
172 | 3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0), | 170 | 3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0) |
173 | }; | 171 | ); |
174 | 172 | ||
175 | /* {-16, -13, -10, -7, -5.2, -3,3, -2.2, 0}dB, mute instead of -16dB */ | 173 | /* {-16, -13, -10, -7, -5.2, -3,3, -2.2, 0}dB, mute instead of -16dB */ |
176 | static const unsigned int out_tlv[] = { | 174 | static const DECLARE_TLV_DB_RANGE(out_tlv, |
177 | TLV_DB_RANGE_HEAD(4), | ||
178 | 0, 3, TLV_DB_SCALE_ITEM(-1600, 300, 1), | 175 | 0, 3, TLV_DB_SCALE_ITEM(-1600, 300, 1), |
179 | 4, 4, TLV_DB_SCALE_ITEM(-520, 0, 0), | 176 | 4, 4, TLV_DB_SCALE_ITEM(-520, 0, 0), |
180 | 5, 5, TLV_DB_SCALE_ITEM(-330, 0, 0), | 177 | 5, 5, TLV_DB_SCALE_ITEM(-330, 0, 0), |
181 | 6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0), | 178 | 6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0) |
182 | }; | 179 | ); |
183 | 180 | ||
184 | static const unsigned int st_tlv[] = { | 181 | static const DECLARE_TLV_DB_RANGE(st_tlv, |
185 | TLV_DB_RANGE_HEAD(8), | ||
186 | 0, 1, TLV_DB_SCALE_ITEM(-12041, 602, 0), | 182 | 0, 1, TLV_DB_SCALE_ITEM(-12041, 602, 0), |
187 | 2, 3, TLV_DB_SCALE_ITEM(-11087, 250, 0), | 183 | 2, 3, TLV_DB_SCALE_ITEM(-11087, 250, 0), |
188 | 4, 5, TLV_DB_SCALE_ITEM(-10643, 158, 0), | 184 | 4, 5, TLV_DB_SCALE_ITEM(-10643, 158, 0), |
@@ -190,8 +186,8 @@ static const unsigned int st_tlv[] = { | |||
190 | 8, 9, TLV_DB_SCALE_ITEM(-10133, 92, 0), | 186 | 8, 9, TLV_DB_SCALE_ITEM(-10133, 92, 0), |
191 | 10, 13, TLV_DB_SCALE_ITEM(-9958, 70, 0), | 187 | 10, 13, TLV_DB_SCALE_ITEM(-9958, 70, 0), |
192 | 14, 17, TLV_DB_SCALE_ITEM(-9689, 53, 0), | 188 | 14, 17, TLV_DB_SCALE_ITEM(-9689, 53, 0), |
193 | 18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0), | 189 | 18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0) |
194 | }; | 190 | ); |
195 | 191 | ||
196 | /* Sidetone Gain = M * 2^(-5-N) */ | 192 | /* Sidetone Gain = M * 2^(-5-N) */ |
197 | struct st_gain { | 193 | struct st_gain { |
@@ -1028,10 +1024,8 @@ static int pm860x_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
1028 | 1024 | ||
1029 | if (dir == PM860X_CLK_DIR_OUT) | 1025 | if (dir == PM860X_CLK_DIR_OUT) |
1030 | pm860x->dir = PM860X_CLK_DIR_OUT; | 1026 | pm860x->dir = PM860X_CLK_DIR_OUT; |
1031 | else { | 1027 | else /* Slave mode is not supported */ |
1032 | pm860x->dir = PM860X_CLK_DIR_IN; | ||
1033 | return -EINVAL; | 1028 | return -EINVAL; |
1034 | } | ||
1035 | 1029 | ||
1036 | return 0; | 1030 | return 0; |
1037 | } | 1031 | } |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index efaafce8ba38..0c9733ecd17f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -53,6 +53,7 @@ config SND_SOC_ALL_CODECS | |||
53 | select SND_SOC_CS4271_I2C if I2C | 53 | select SND_SOC_CS4271_I2C if I2C |
54 | select SND_SOC_CS4271_SPI if SPI_MASTER | 54 | select SND_SOC_CS4271_SPI if SPI_MASTER |
55 | select SND_SOC_CS42XX8_I2C if I2C | 55 | select SND_SOC_CS42XX8_I2C if I2C |
56 | select SND_SOC_CS4349 if I2C | ||
56 | select SND_SOC_CX20442 if TTY | 57 | select SND_SOC_CX20442 if TTY |
57 | select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI | 58 | select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI |
58 | select SND_SOC_DA7213 if I2C | 59 | select SND_SOC_DA7213 if I2C |
@@ -62,6 +63,8 @@ config SND_SOC_ALL_CODECS | |||
62 | select SND_SOC_BT_SCO | 63 | select SND_SOC_BT_SCO |
63 | select SND_SOC_ES8328_SPI if SPI_MASTER | 64 | select SND_SOC_ES8328_SPI if SPI_MASTER |
64 | select SND_SOC_ES8328_I2C if I2C | 65 | select SND_SOC_ES8328_I2C if I2C |
66 | select SND_SOC_GTM601 | ||
67 | select SND_SOC_ICS43432 | ||
65 | select SND_SOC_ISABELLE if I2C | 68 | select SND_SOC_ISABELLE if I2C |
66 | select SND_SOC_JZ4740_CODEC | 69 | select SND_SOC_JZ4740_CODEC |
67 | select SND_SOC_LM4857 if I2C | 70 | select SND_SOC_LM4857 if I2C |
@@ -83,6 +86,7 @@ config SND_SOC_ALL_CODECS | |||
83 | select SND_SOC_PCM512x_I2C if I2C | 86 | select SND_SOC_PCM512x_I2C if I2C |
84 | select SND_SOC_PCM512x_SPI if SPI_MASTER | 87 | select SND_SOC_PCM512x_SPI if SPI_MASTER |
85 | select SND_SOC_RT286 if I2C | 88 | select SND_SOC_RT286 if I2C |
89 | select SND_SOC_RT298 if I2C | ||
86 | select SND_SOC_RT5631 if I2C | 90 | select SND_SOC_RT5631 if I2C |
87 | select SND_SOC_RT5640 if I2C | 91 | select SND_SOC_RT5640 if I2C |
88 | select SND_SOC_RT5645 if I2C | 92 | select SND_SOC_RT5645 if I2C |
@@ -102,6 +106,7 @@ config SND_SOC_ALL_CODECS | |||
102 | select SND_SOC_STA350 if I2C | 106 | select SND_SOC_STA350 if I2C |
103 | select SND_SOC_STA529 if I2C | 107 | select SND_SOC_STA529 if I2C |
104 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 108 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
109 | select SND_SOC_STI_SAS | ||
105 | select SND_SOC_TAS2552 if I2C | 110 | select SND_SOC_TAS2552 if I2C |
106 | select SND_SOC_TAS5086 if I2C | 111 | select SND_SOC_TAS5086 if I2C |
107 | select SND_SOC_TAS571X if I2C | 112 | select SND_SOC_TAS571X if I2C |
@@ -403,6 +408,11 @@ config SND_SOC_CS42XX8_I2C | |||
403 | select SND_SOC_CS42XX8 | 408 | select SND_SOC_CS42XX8 |
404 | select REGMAP_I2C | 409 | select REGMAP_I2C |
405 | 410 | ||
411 | # Cirrus Logic CS4349 HiFi DAC | ||
412 | config SND_SOC_CS4349 | ||
413 | tristate "Cirrus Logic CS4349 CODEC" | ||
414 | depends on I2C | ||
415 | |||
406 | config SND_SOC_CX20442 | 416 | config SND_SOC_CX20442 |
407 | tristate | 417 | tristate |
408 | depends on TTY | 418 | depends on TTY |
@@ -446,6 +456,12 @@ config SND_SOC_ES8328_SPI | |||
446 | tristate | 456 | tristate |
447 | select SND_SOC_ES8328 | 457 | select SND_SOC_ES8328 |
448 | 458 | ||
459 | config SND_SOC_GTM601 | ||
460 | tristate 'GTM601 UMTS modem audio codec' | ||
461 | |||
462 | config SND_SOC_ICS43432 | ||
463 | tristate | ||
464 | |||
449 | config SND_SOC_ISABELLE | 465 | config SND_SOC_ISABELLE |
450 | tristate | 466 | tristate |
451 | 467 | ||
@@ -512,12 +528,18 @@ config SND_SOC_RL6231 | |||
512 | config SND_SOC_RL6347A | 528 | config SND_SOC_RL6347A |
513 | tristate | 529 | tristate |
514 | default y if SND_SOC_RT286=y | 530 | default y if SND_SOC_RT286=y |
531 | default y if SND_SOC_RT298=y | ||
515 | default m if SND_SOC_RT286=m | 532 | default m if SND_SOC_RT286=m |
533 | default m if SND_SOC_RT298=m | ||
516 | 534 | ||
517 | config SND_SOC_RT286 | 535 | config SND_SOC_RT286 |
518 | tristate | 536 | tristate |
519 | depends on I2C | 537 | depends on I2C |
520 | 538 | ||
539 | config SND_SOC_RT298 | ||
540 | tristate | ||
541 | depends on I2C | ||
542 | |||
521 | config SND_SOC_RT5631 | 543 | config SND_SOC_RT5631 |
522 | tristate "Realtek ALC5631/RT5631 CODEC" | 544 | tristate "Realtek ALC5631/RT5631 CODEC" |
523 | depends on I2C | 545 | depends on I2C |
@@ -610,6 +632,9 @@ config SND_SOC_STA529 | |||
610 | config SND_SOC_STAC9766 | 632 | config SND_SOC_STAC9766 |
611 | tristate | 633 | tristate |
612 | 634 | ||
635 | config SND_SOC_STI_SAS | ||
636 | tristate "codec Audio support for STI SAS codec" | ||
637 | |||
613 | config SND_SOC_TAS2552 | 638 | config SND_SOC_TAS2552 |
614 | tristate "Texas Instruments TAS2552 Mono Audio amplifier" | 639 | tristate "Texas Instruments TAS2552 Mono Audio amplifier" |
615 | depends on I2C | 640 | depends on I2C |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index cf160d972cb3..4a32077954ae 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -45,6 +45,7 @@ snd-soc-cs4271-i2c-objs := cs4271-i2c.o | |||
45 | snd-soc-cs4271-spi-objs := cs4271-spi.o | 45 | snd-soc-cs4271-spi-objs := cs4271-spi.o |
46 | snd-soc-cs42xx8-objs := cs42xx8.o | 46 | snd-soc-cs42xx8-objs := cs42xx8.o |
47 | snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o | 47 | snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o |
48 | snd-soc-cs4349-objs := cs4349.o | ||
48 | snd-soc-cx20442-objs := cx20442.o | 49 | snd-soc-cx20442-objs := cx20442.o |
49 | snd-soc-da7210-objs := da7210.o | 50 | snd-soc-da7210-objs := da7210.o |
50 | snd-soc-da7213-objs := da7213.o | 51 | snd-soc-da7213-objs := da7213.o |
@@ -55,6 +56,8 @@ snd-soc-dmic-objs := dmic.o | |||
55 | snd-soc-es8328-objs := es8328.o | 56 | snd-soc-es8328-objs := es8328.o |
56 | snd-soc-es8328-i2c-objs := es8328-i2c.o | 57 | snd-soc-es8328-i2c-objs := es8328-i2c.o |
57 | snd-soc-es8328-spi-objs := es8328-spi.o | 58 | snd-soc-es8328-spi-objs := es8328-spi.o |
59 | snd-soc-gtm601-objs := gtm601.o | ||
60 | snd-soc-ics43432-objs := ics43432.o | ||
58 | snd-soc-isabelle-objs := isabelle.o | 61 | snd-soc-isabelle-objs := isabelle.o |
59 | snd-soc-jz4740-codec-objs := jz4740.o | 62 | snd-soc-jz4740-codec-objs := jz4740.o |
60 | snd-soc-l3-objs := l3.o | 63 | snd-soc-l3-objs := l3.o |
@@ -79,6 +82,7 @@ snd-soc-pcm512x-spi-objs := pcm512x-spi.o | |||
79 | snd-soc-rl6231-objs := rl6231.o | 82 | snd-soc-rl6231-objs := rl6231.o |
80 | snd-soc-rl6347a-objs := rl6347a.o | 83 | snd-soc-rl6347a-objs := rl6347a.o |
81 | snd-soc-rt286-objs := rt286.o | 84 | snd-soc-rt286-objs := rt286.o |
85 | snd-soc-rt298-objs := rt298.o | ||
82 | snd-soc-rt5631-objs := rt5631.o | 86 | snd-soc-rt5631-objs := rt5631.o |
83 | snd-soc-rt5640-objs := rt5640.o | 87 | snd-soc-rt5640-objs := rt5640.o |
84 | snd-soc-rt5645-objs := rt5645.o | 88 | snd-soc-rt5645-objs := rt5645.o |
@@ -106,6 +110,7 @@ snd-soc-sta32x-objs := sta32x.o | |||
106 | snd-soc-sta350-objs := sta350.o | 110 | snd-soc-sta350-objs := sta350.o |
107 | snd-soc-sta529-objs := sta529.o | 111 | snd-soc-sta529-objs := sta529.o |
108 | snd-soc-stac9766-objs := stac9766.o | 112 | snd-soc-stac9766-objs := stac9766.o |
113 | snd-soc-sti-sas-objs := sti-sas.o | ||
109 | snd-soc-tas5086-objs := tas5086.o | 114 | snd-soc-tas5086-objs := tas5086.o |
110 | snd-soc-tas571x-objs := tas571x.o | 115 | snd-soc-tas571x-objs := tas571x.o |
111 | snd-soc-tfa9879-objs := tfa9879.o | 116 | snd-soc-tfa9879-objs := tfa9879.o |
@@ -232,6 +237,7 @@ obj-$(CONFIG_SND_SOC_CS4271_I2C) += snd-soc-cs4271-i2c.o | |||
232 | obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o | 237 | obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o |
233 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o | 238 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o |
234 | obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o | 239 | obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o |
240 | obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o | ||
235 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 241 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
236 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | 242 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
237 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o | 243 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o |
@@ -242,6 +248,8 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | |||
242 | obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o | 248 | obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o |
243 | obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o | 249 | obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o |
244 | obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o | 250 | obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o |
251 | obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o | ||
252 | obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o | ||
245 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o | 253 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o |
246 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o | 254 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
247 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 255 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
@@ -266,6 +274,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o | |||
266 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o | 274 | obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o |
267 | obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o | 275 | obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o |
268 | obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o | 276 | obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o |
277 | obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o | ||
269 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 278 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
270 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o | 279 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o |
271 | obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o | 280 | obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o |
@@ -289,6 +298,7 @@ obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | |||
289 | obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o | 298 | obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o |
290 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | 299 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o |
291 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 300 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
301 | obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o | ||
292 | obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o | 302 | obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o |
293 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o | 303 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o |
294 | obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o | 304 | obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index c7d243db010a..affb192238a4 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -1335,11 +1335,10 @@ static DECLARE_TLV_DB_SCALE(dax_dig_gain_tlv, -6300, 100, 1); | |||
1335 | static DECLARE_TLV_DB_SCALE(hs_ear_dig_gain_tlv, -100, 100, 1); | 1335 | static DECLARE_TLV_DB_SCALE(hs_ear_dig_gain_tlv, -100, 100, 1); |
1336 | /* -1dB = Mute */ | 1336 | /* -1dB = Mute */ |
1337 | 1337 | ||
1338 | static const unsigned int hs_gain_tlv[] = { | 1338 | static const DECLARE_TLV_DB_RANGE(hs_gain_tlv, |
1339 | TLV_DB_RANGE_HEAD(2), | ||
1340 | 0, 3, TLV_DB_SCALE_ITEM(-3200, 400, 0), | 1339 | 0, 3, TLV_DB_SCALE_ITEM(-3200, 400, 0), |
1341 | 4, 15, TLV_DB_SCALE_ITEM(-1800, 200, 0), | 1340 | 4, 15, TLV_DB_SCALE_ITEM(-1800, 200, 0) |
1342 | }; | 1341 | ); |
1343 | 1342 | ||
1344 | static DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0); | 1343 | static DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0); |
1345 | 1344 | ||
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 3cc69a626454..9ef20dbccbe3 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -202,19 +202,21 @@ static struct snd_soc_dai_driver ad1980_dai = { | |||
202 | .formats = SND_SOC_STD_AC97_FMTS, }, | 202 | .formats = SND_SOC_STD_AC97_FMTS, }, |
203 | }; | 203 | }; |
204 | 204 | ||
205 | #define AD1980_VENDOR_ID 0x41445300 | ||
206 | #define AD1980_VENDOR_MASK 0xffffff00 | ||
207 | |||
205 | static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) | 208 | static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) |
206 | { | 209 | { |
207 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | 210 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
208 | unsigned int retry_cnt = 0; | 211 | unsigned int retry_cnt = 0; |
212 | int ret; | ||
209 | 213 | ||
210 | do { | 214 | do { |
211 | if (try_warm && soc_ac97_ops->warm_reset) { | 215 | ret = snd_ac97_reset(ac97, true, AD1980_VENDOR_ID, |
212 | soc_ac97_ops->warm_reset(ac97); | 216 | AD1980_VENDOR_MASK); |
213 | if (snd_soc_read(codec, AC97_RESET) == 0x0090) | 217 | if (ret >= 0) |
214 | return 1; | 218 | return 0; |
215 | } | ||
216 | 219 | ||
217 | soc_ac97_ops->reset(ac97); | ||
218 | /* | 220 | /* |
219 | * Set bit 16slot in register 74h, then every slot will has only | 221 | * Set bit 16slot in register 74h, then every slot will has only |
220 | * 16 bits. This command is sent out in 20bit mode, in which | 222 | * 16 bits. This command is sent out in 20bit mode, in which |
@@ -223,8 +225,6 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) | |||
223 | */ | 225 | */ |
224 | snd_soc_write(codec, AC97_AD_SERIAL_CFG, 0x9900); | 226 | snd_soc_write(codec, AC97_AD_SERIAL_CFG, 0x9900); |
225 | 227 | ||
226 | if (snd_soc_read(codec, AC97_RESET) == 0x0090) | ||
227 | return 0; | ||
228 | } while (retry_cnt++ < 10); | 228 | } while (retry_cnt++ < 10); |
229 | 229 | ||
230 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | 230 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); |
@@ -240,7 +240,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) | |||
240 | u16 vendor_id2; | 240 | u16 vendor_id2; |
241 | u16 ext_status; | 241 | u16 ext_status; |
242 | 242 | ||
243 | ac97 = snd_soc_new_ac97_codec(codec); | 243 | ac97 = snd_soc_new_ac97_codec(codec, 0, 0); |
244 | if (IS_ERR(ac97)) { | 244 | if (IS_ERR(ac97)) { |
245 | ret = PTR_ERR(ac97); | 245 | ret = PTR_ERR(ac97); |
246 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); | 246 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); |
@@ -260,22 +260,10 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) | |||
260 | if (ret < 0) | 260 | if (ret < 0) |
261 | goto reset_err; | 261 | goto reset_err; |
262 | 262 | ||
263 | /* Read out vendor ID to make sure it is ad1980 */ | ||
264 | if (snd_soc_read(codec, AC97_VENDOR_ID1) != 0x4144) { | ||
265 | ret = -ENODEV; | ||
266 | goto reset_err; | ||
267 | } | ||
268 | |||
269 | vendor_id2 = snd_soc_read(codec, AC97_VENDOR_ID2); | 263 | vendor_id2 = snd_soc_read(codec, AC97_VENDOR_ID2); |
270 | 264 | if (vendor_id2 == 0x5374) { | |
271 | if (vendor_id2 != 0x5370) { | 265 | dev_warn(codec->dev, |
272 | if (vendor_id2 != 0x5374) { | 266 | "Found AD1981 - only 2/2 IN/OUT Channels supported\n"); |
273 | ret = -ENODEV; | ||
274 | goto reset_err; | ||
275 | } else { | ||
276 | dev_warn(codec->dev, | ||
277 | "Found AD1981 - only 2/2 IN/OUT Channels supported\n"); | ||
278 | } | ||
279 | } | 267 | } |
280 | 268 | ||
281 | /* unmute captures and playbacks volume */ | 269 | /* unmute captures and playbacks volume */ |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index a43160254929..fe1353a797b9 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -320,13 +320,12 @@ static const struct reg_default adau1373_reg_defaults[] = { | |||
320 | { ADAU1373_DIGEN, 0x00 }, | 320 | { ADAU1373_DIGEN, 0x00 }, |
321 | }; | 321 | }; |
322 | 322 | ||
323 | static const unsigned int adau1373_out_tlv[] = { | 323 | static const DECLARE_TLV_DB_RANGE(adau1373_out_tlv, |
324 | TLV_DB_RANGE_HEAD(4), | ||
325 | 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), | 324 | 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), |
326 | 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), | 325 | 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), |
327 | 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), | 326 | 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), |
328 | 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), | 327 | 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0) |
329 | }; | 328 | ); |
330 | 329 | ||
331 | static const DECLARE_TLV_DB_MINMAX(adau1373_digital_tlv, -9563, 0); | 330 | static const DECLARE_TLV_DB_MINMAX(adau1373_digital_tlv, -9563, 0); |
332 | static const DECLARE_TLV_DB_SCALE(adau1373_in_pga_tlv, -1300, 100, 1); | 331 | static const DECLARE_TLV_DB_SCALE(adau1373_in_pga_tlv, -1300, 100, 1); |
@@ -381,12 +380,11 @@ static const char *adau1373_bass_hpf_cutoff_text[] = { | |||
381 | "158Hz", "232Hz", "347Hz", "520Hz", | 380 | "158Hz", "232Hz", "347Hz", "520Hz", |
382 | }; | 381 | }; |
383 | 382 | ||
384 | static const unsigned int adau1373_bass_tlv[] = { | 383 | static const DECLARE_TLV_DB_RANGE(adau1373_bass_tlv, |
385 | TLV_DB_RANGE_HEAD(3), | ||
386 | 0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1), | 384 | 0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1), |
387 | 3, 4, TLV_DB_SCALE_ITEM(950, 250, 0), | 385 | 3, 4, TLV_DB_SCALE_ITEM(950, 250, 0), |
388 | 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), | 386 | 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0) |
389 | }; | 387 | ); |
390 | 388 | ||
391 | static SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, | 389 | static SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, |
392 | ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); | 390 | ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); |
@@ -414,11 +412,10 @@ static SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, | |||
414 | static SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, | 412 | static SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, |
415 | ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); | 413 | ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); |
416 | 414 | ||
417 | static const unsigned int adau1373_3d_tlv[] = { | 415 | static const DECLARE_TLV_DB_RANGE(adau1373_3d_tlv, |
418 | TLV_DB_RANGE_HEAD(2), | ||
419 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 416 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
420 | 1, 7, TLV_DB_LINEAR_ITEM(-1800, -120), | 417 | 1, 7, TLV_DB_LINEAR_ITEM(-1800, -120) |
421 | }; | 418 | ); |
422 | 419 | ||
423 | static const char *adau1373_lr_mux_text[] = { | 420 | static const char *adau1373_lr_mux_text[] = { |
424 | "Mute", | 421 | "Mute", |
@@ -1534,7 +1531,6 @@ MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id); | |||
1534 | static struct i2c_driver adau1373_i2c_driver = { | 1531 | static struct i2c_driver adau1373_i2c_driver = { |
1535 | .driver = { | 1532 | .driver = { |
1536 | .name = "adau1373", | 1533 | .name = "adau1373", |
1537 | .owner = THIS_MODULE, | ||
1538 | }, | 1534 | }, |
1539 | .probe = adau1373_i2c_probe, | 1535 | .probe = adau1373_i2c_probe, |
1540 | .remove = adau1373_i2c_remove, | 1536 | .remove = adau1373_i2c_remove, |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index ff7f846e3b76..de53c0d7bf10 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -915,7 +915,6 @@ MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); | |||
915 | static struct i2c_driver adau1701_i2c_driver = { | 915 | static struct i2c_driver adau1701_i2c_driver = { |
916 | .driver = { | 916 | .driver = { |
917 | .name = "adau1701", | 917 | .name = "adau1701", |
918 | .owner = THIS_MODULE, | ||
919 | .of_match_table = of_match_ptr(adau1701_dt_ids), | 918 | .of_match_table = of_match_ptr(adau1701_dt_ids), |
920 | }, | 919 | }, |
921 | .probe = adau1701_i2c_probe, | 920 | .probe = adau1701_i2c_probe, |
diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c index 862796dec693..348ccb17d3cc 100644 --- a/sound/soc/codecs/adau1761-i2c.c +++ b/sound/soc/codecs/adau1761-i2c.c | |||
@@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(i2c, adau1761_i2c_ids); | |||
47 | static struct i2c_driver adau1761_i2c_driver = { | 47 | static struct i2c_driver adau1761_i2c_driver = { |
48 | .driver = { | 48 | .driver = { |
49 | .name = "adau1761", | 49 | .name = "adau1761", |
50 | .owner = THIS_MODULE, | ||
51 | }, | 50 | }, |
52 | .probe = adau1761_i2c_probe, | 51 | .probe = adau1761_i2c_probe, |
53 | .remove = adau1761_i2c_remove, | 52 | .remove = adau1761_i2c_remove, |
diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c index 2ce4362ccec1..0e32bba92339 100644 --- a/sound/soc/codecs/adau1781-i2c.c +++ b/sound/soc/codecs/adau1781-i2c.c | |||
@@ -45,7 +45,6 @@ MODULE_DEVICE_TABLE(i2c, adau1781_i2c_ids); | |||
45 | static struct i2c_driver adau1781_i2c_driver = { | 45 | static struct i2c_driver adau1781_i2c_driver = { |
46 | .driver = { | 46 | .driver = { |
47 | .name = "adau1781", | 47 | .name = "adau1781", |
48 | .owner = THIS_MODULE, | ||
49 | }, | 48 | }, |
50 | .probe = adau1781_i2c_probe, | 49 | .probe = adau1781_i2c_probe, |
51 | .remove = adau1781_i2c_remove, | 50 | .remove = adau1781_i2c_remove, |
diff --git a/sound/soc/codecs/adau1977-i2c.c b/sound/soc/codecs/adau1977-i2c.c index 9700e8c838c9..21e7394a972a 100644 --- a/sound/soc/codecs/adau1977-i2c.c +++ b/sound/soc/codecs/adau1977-i2c.c | |||
@@ -46,7 +46,6 @@ MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids); | |||
46 | static struct i2c_driver adau1977_i2c_driver = { | 46 | static struct i2c_driver adau1977_i2c_driver = { |
47 | .driver = { | 47 | .driver = { |
48 | .name = "adau1977", | 48 | .name = "adau1977", |
49 | .owner = THIS_MODULE, | ||
50 | }, | 49 | }, |
51 | .probe = adau1977_i2c_probe, | 50 | .probe = adau1977_i2c_probe, |
52 | .remove = adau1977_i2c_remove, | 51 | .remove = adau1977_i2c_remove, |
diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c index 66d9fce34e62..52881faedcf6 100644 --- a/sound/soc/codecs/adav803.c +++ b/sound/soc/codecs/adav803.c | |||
@@ -36,7 +36,6 @@ static int adav803_remove(struct i2c_client *client) | |||
36 | static struct i2c_driver adav803_driver = { | 36 | static struct i2c_driver adav803_driver = { |
37 | .driver = { | 37 | .driver = { |
38 | .name = "adav803", | 38 | .name = "adav803", |
39 | .owner = THIS_MODULE, | ||
40 | }, | 39 | }, |
41 | .probe = adav803_probe, | 40 | .probe = adav803_probe, |
42 | .remove = adav803_remove, | 41 | .remove = adav803_remove, |
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 36d842570745..198c924551b7 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -113,7 +113,7 @@ | |||
113 | 113 | ||
114 | #define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x)) | 114 | #define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x)) |
115 | 115 | ||
116 | static struct reg_default adav80x_reg_defaults[] = { | 116 | static const struct reg_default adav80x_reg_defaults[] = { |
117 | { ADAV80X_PLAYBACK_CTRL, 0x01 }, | 117 | { ADAV80X_PLAYBACK_CTRL, 0x01 }, |
118 | { ADAV80X_AUX_IN_CTRL, 0x01 }, | 118 | { ADAV80X_AUX_IN_CTRL, 0x01 }, |
119 | { ADAV80X_REC_CTRL, 0x02 }, | 119 | { ADAV80X_REC_CTRL, 0x02 }, |
@@ -865,7 +865,6 @@ const struct regmap_config adav80x_regmap_config = { | |||
865 | .val_bits = 8, | 865 | .val_bits = 8, |
866 | .pad_bits = 1, | 866 | .pad_bits = 1, |
867 | .reg_bits = 7, | 867 | .reg_bits = 7, |
868 | .read_flag_mask = 0x01, | ||
869 | 868 | ||
870 | .max_register = ADAV80X_PLL_OUTE, | 869 | .max_register = ADAV80X_PLL_OUTE, |
871 | 870 | ||
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 8670861e5bec..54428c64387b 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -444,7 +444,6 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id); | |||
444 | static struct i2c_driver ak4535_i2c_driver = { | 444 | static struct i2c_driver ak4535_i2c_driver = { |
445 | .driver = { | 445 | .driver = { |
446 | .name = "ak4535", | 446 | .name = "ak4535", |
447 | .owner = THIS_MODULE, | ||
448 | }, | 447 | }, |
449 | .probe = ak4535_i2c_probe, | 448 | .probe = ak4535_i2c_probe, |
450 | .remove = ak4535_i2c_remove, | 449 | .remove = ak4535_i2c_remove, |
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 2d0ff4595ea0..b14176f8d884 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c | |||
@@ -609,7 +609,6 @@ MODULE_DEVICE_TABLE(i2c, ak4641_i2c_id); | |||
609 | static struct i2c_driver ak4641_i2c_driver = { | 609 | static struct i2c_driver ak4641_i2c_driver = { |
610 | .driver = { | 610 | .driver = { |
611 | .name = "ak4641", | 611 | .name = "ak4641", |
612 | .owner = THIS_MODULE, | ||
613 | }, | 612 | }, |
614 | .probe = ak4641_i2c_probe, | 613 | .probe = ak4641_i2c_probe, |
615 | .remove = ak4641_i2c_remove, | 614 | .remove = ak4641_i2c_remove, |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 7c0f6552c229..4a90143d0e90 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -64,12 +64,15 @@ | |||
64 | #define FIL1_0 0x1c | 64 | #define FIL1_0 0x1c |
65 | #define FIL1_1 0x1d | 65 | #define FIL1_1 0x1d |
66 | #define FIL1_2 0x1e | 66 | #define FIL1_2 0x1e |
67 | #define FIL1_3 0x1f | 67 | #define FIL1_3 0x1f /* The maximum valid register for ak4642 */ |
68 | #define PW_MGMT4 0x20 | 68 | #define PW_MGMT4 0x20 |
69 | #define MD_CTL5 0x21 | 69 | #define MD_CTL5 0x21 |
70 | #define LO_MS 0x22 | 70 | #define LO_MS 0x22 |
71 | #define HP_MS 0x23 | 71 | #define HP_MS 0x23 |
72 | #define SPK_MS 0x24 | 72 | #define SPK_MS 0x24 /* The maximum valid register for ak4643 */ |
73 | #define EQ_FBEQAB 0x25 | ||
74 | #define EQ_FBEQCD 0x26 | ||
75 | #define EQ_FBEQE 0x27 /* The maximum valid register for ak4648 */ | ||
73 | 76 | ||
74 | /* PW_MGMT1*/ | 77 | /* PW_MGMT1*/ |
75 | #define PMVCM (1 << 6) /* VCOM Power Management */ | 78 | #define PMVCM (1 << 6) /* VCOM Power Management */ |
@@ -241,7 +244,7 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = { | |||
241 | /* | 244 | /* |
242 | * ak4642 register cache | 245 | * ak4642 register cache |
243 | */ | 246 | */ |
244 | static const struct reg_default ak4642_reg[] = { | 247 | static const struct reg_default ak4643_reg[] = { |
245 | { 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 }, | 248 | { 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 }, |
246 | { 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 }, | 249 | { 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 }, |
247 | { 8, 0xe1 }, { 9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 }, | 250 | { 8, 0xe1 }, { 9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 }, |
@@ -254,6 +257,14 @@ static const struct reg_default ak4642_reg[] = { | |||
254 | { 36, 0x00 }, | 257 | { 36, 0x00 }, |
255 | }; | 258 | }; |
256 | 259 | ||
260 | /* The default settings for 0x0 ~ 0x1f registers are the same for ak4642 | ||
261 | and ak4643. So we reuse the ak4643 reg_default for ak4642. | ||
262 | The valid registers for ak4642 are 0x0 ~ 0x1f which is a subset of ak4643, | ||
263 | so define NUM_AK4642_REG_DEFAULTS for ak4642. | ||
264 | */ | ||
265 | #define ak4642_reg ak4643_reg | ||
266 | #define NUM_AK4642_REG_DEFAULTS (FIL1_3 + 1) | ||
267 | |||
257 | static const struct reg_default ak4648_reg[] = { | 268 | static const struct reg_default ak4648_reg[] = { |
258 | { 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 }, | 269 | { 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 }, |
259 | { 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 }, | 270 | { 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 }, |
@@ -535,15 +546,23 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { | |||
535 | static const struct regmap_config ak4642_regmap = { | 546 | static const struct regmap_config ak4642_regmap = { |
536 | .reg_bits = 8, | 547 | .reg_bits = 8, |
537 | .val_bits = 8, | 548 | .val_bits = 8, |
538 | .max_register = ARRAY_SIZE(ak4642_reg) + 1, | 549 | .max_register = FIL1_3, |
539 | .reg_defaults = ak4642_reg, | 550 | .reg_defaults = ak4642_reg, |
540 | .num_reg_defaults = ARRAY_SIZE(ak4642_reg), | 551 | .num_reg_defaults = NUM_AK4642_REG_DEFAULTS, |
552 | }; | ||
553 | |||
554 | static const struct regmap_config ak4643_regmap = { | ||
555 | .reg_bits = 8, | ||
556 | .val_bits = 8, | ||
557 | .max_register = SPK_MS, | ||
558 | .reg_defaults = ak4643_reg, | ||
559 | .num_reg_defaults = ARRAY_SIZE(ak4643_reg), | ||
541 | }; | 560 | }; |
542 | 561 | ||
543 | static const struct regmap_config ak4648_regmap = { | 562 | static const struct regmap_config ak4648_regmap = { |
544 | .reg_bits = 8, | 563 | .reg_bits = 8, |
545 | .val_bits = 8, | 564 | .val_bits = 8, |
546 | .max_register = ARRAY_SIZE(ak4648_reg) + 1, | 565 | .max_register = EQ_FBEQE, |
547 | .reg_defaults = ak4648_reg, | 566 | .reg_defaults = ak4648_reg, |
548 | .num_reg_defaults = ARRAY_SIZE(ak4648_reg), | 567 | .num_reg_defaults = ARRAY_SIZE(ak4648_reg), |
549 | }; | 568 | }; |
@@ -553,7 +572,7 @@ static const struct ak4642_drvdata ak4642_drvdata = { | |||
553 | }; | 572 | }; |
554 | 573 | ||
555 | static const struct ak4642_drvdata ak4643_drvdata = { | 574 | static const struct ak4642_drvdata ak4643_drvdata = { |
556 | .regmap_config = &ak4642_regmap, | 575 | .regmap_config = &ak4643_regmap, |
557 | }; | 576 | }; |
558 | 577 | ||
559 | static const struct ak4642_drvdata ak4648_drvdata = { | 578 | static const struct ak4642_drvdata ak4648_drvdata = { |
@@ -626,7 +645,6 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); | |||
626 | static struct i2c_driver ak4642_i2c_driver = { | 645 | static struct i2c_driver ak4642_i2c_driver = { |
627 | .driver = { | 646 | .driver = { |
628 | .name = "ak4642-codec", | 647 | .name = "ak4642-codec", |
629 | .owner = THIS_MODULE, | ||
630 | .of_match_table = ak4642_of_match, | 648 | .of_match_table = ak4642_of_match, |
631 | }, | 649 | }, |
632 | .probe = ak4642_i2c_probe, | 650 | .probe = ak4642_i2c_probe, |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 0e59063aeb6f..c73a9f6914b6 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -663,7 +663,6 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id); | |||
663 | static struct i2c_driver ak4671_i2c_driver = { | 663 | static struct i2c_driver ak4671_i2c_driver = { |
664 | .driver = { | 664 | .driver = { |
665 | .name = "ak4671-codec", | 665 | .name = "ak4671-codec", |
666 | .owner = THIS_MODULE, | ||
667 | }, | 666 | }, |
668 | .probe = ak4671_i2c_probe, | 667 | .probe = ak4671_i2c_probe, |
669 | .remove = ak4671_i2c_remove, | 668 | .remove = ak4671_i2c_remove, |
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index 0fc24e0d518c..d2e3a3ef7499 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c | |||
@@ -82,12 +82,11 @@ static int amp_mixer_event(struct snd_soc_dapm_widget *w, | |||
82 | static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0); | 82 | static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0); |
83 | static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0); | 83 | static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0); |
84 | static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0); | 84 | static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0); |
85 | static const unsigned int boost_tlv[] = { | 85 | static const DECLARE_TLV_DB_RANGE(boost_tlv, |
86 | TLV_DB_RANGE_HEAD(3), | ||
87 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 86 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
88 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | 87 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), |
89 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), | 88 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0) |
90 | }; | 89 | ); |
91 | static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0); | 90 | static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0); |
92 | 91 | ||
93 | static const struct snd_kcontrol_new alc5621_vol_snd_controls[] = { | 92 | static const struct snd_kcontrol_new alc5621_vol_snd_controls[] = { |
@@ -1085,7 +1084,6 @@ MODULE_DEVICE_TABLE(of, alc5623_of_match); | |||
1085 | static struct i2c_driver alc5623_i2c_driver = { | 1084 | static struct i2c_driver alc5623_i2c_driver = { |
1086 | .driver = { | 1085 | .driver = { |
1087 | .name = "alc562x-codec", | 1086 | .name = "alc562x-codec", |
1088 | .owner = THIS_MODULE, | ||
1089 | .of_match_table = of_match_ptr(alc5623_of_match), | 1087 | .of_match_table = of_match_ptr(alc5623_of_match), |
1090 | }, | 1088 | }, |
1091 | .probe = alc5623_i2c_probe, | 1089 | .probe = alc5623_i2c_probe, |
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index 607a63b9705f..4d3ba33eb6f9 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c | |||
@@ -35,7 +35,7 @@ | |||
35 | /* | 35 | /* |
36 | * ALC5632 register cache | 36 | * ALC5632 register cache |
37 | */ | 37 | */ |
38 | static struct reg_default alc5632_reg_defaults[] = { | 38 | static const struct reg_default alc5632_reg_defaults[] = { |
39 | { 2, 0x8080 }, /* R2 - Speaker Output Volume */ | 39 | { 2, 0x8080 }, /* R2 - Speaker Output Volume */ |
40 | { 4, 0x8080 }, /* R4 - Headphone Output Volume */ | 40 | { 4, 0x8080 }, /* R4 - Headphone Output Volume */ |
41 | { 6, 0x8080 }, /* R6 - AUXOUT Volume */ | 41 | { 6, 0x8080 }, /* R6 - AUXOUT Volume */ |
@@ -146,11 +146,10 @@ static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0); | |||
146 | static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0); | 146 | static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0); |
147 | /* -16.5db min scale, 1.5db steps, no mute */ | 147 | /* -16.5db min scale, 1.5db steps, no mute */ |
148 | static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0); | 148 | static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0); |
149 | static const unsigned int boost_tlv[] = { | 149 | static const DECLARE_TLV_DB_RANGE(boost_tlv, |
150 | TLV_DB_RANGE_HEAD(2), | ||
151 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), | 150 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), |
152 | 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0), | 151 | 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0) |
153 | }; | 152 | ); |
154 | /* 0db min scale, 6 db steps, no mute */ | 153 | /* 0db min scale, 6 db steps, no mute */ |
155 | static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0); | 154 | static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0); |
156 | /* 0db min scalem 0.75db steps, no mute */ | 155 | /* 0db min scalem 0.75db steps, no mute */ |
@@ -1183,7 +1182,6 @@ MODULE_DEVICE_TABLE(of, alc5632_of_match); | |||
1183 | static struct i2c_driver alc5632_i2c_driver = { | 1182 | static struct i2c_driver alc5632_i2c_driver = { |
1184 | .driver = { | 1183 | .driver = { |
1185 | .name = "alc5632", | 1184 | .name = "alc5632", |
1186 | .owner = THIS_MODULE, | ||
1187 | .of_match_table = of_match_ptr(alc5632_of_match), | 1185 | .of_match_table = of_match_ptr(alc5632_of_match), |
1188 | }, | 1186 | }, |
1189 | .probe = alc5632_i2c_probe, | 1187 | .probe = alc5632_i2c_probe, |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 802e05eae3e9..8a2221ab3d10 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -1366,7 +1366,7 @@ static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec, | |||
1366 | { | 1366 | { |
1367 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 1367 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
1368 | struct arizona *arizona = priv->arizona; | 1368 | struct arizona *arizona = priv->arizona; |
1369 | struct reg_default dac_comp[] = { | 1369 | struct reg_sequence dac_comp[] = { |
1370 | { 0x80, 0x3 }, | 1370 | { 0x80, 0x3 }, |
1371 | { ARIZONA_DAC_COMP_1, 0 }, | 1371 | { ARIZONA_DAC_COMP_1, 0 }, |
1372 | { ARIZONA_DAC_COMP_2, 0 }, | 1372 | { ARIZONA_DAC_COMP_2, 0 }, |
@@ -1504,7 +1504,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
1504 | else | 1504 | else |
1505 | rates = &arizona_48k_bclk_rates[0]; | 1505 | rates = &arizona_48k_bclk_rates[0]; |
1506 | 1506 | ||
1507 | wl = snd_pcm_format_width(params_format(params)); | 1507 | wl = params_width(params); |
1508 | 1508 | ||
1509 | if (tdm_slots) { | 1509 | if (tdm_slots) { |
1510 | arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n", | 1510 | arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n", |
@@ -1756,17 +1756,6 @@ int arizona_init_dai(struct arizona_priv *priv, int id) | |||
1756 | } | 1756 | } |
1757 | EXPORT_SYMBOL_GPL(arizona_init_dai); | 1757 | EXPORT_SYMBOL_GPL(arizona_init_dai); |
1758 | 1758 | ||
1759 | static irqreturn_t arizona_fll_clock_ok(int irq, void *data) | ||
1760 | { | ||
1761 | struct arizona_fll *fll = data; | ||
1762 | |||
1763 | arizona_fll_dbg(fll, "clock OK\n"); | ||
1764 | |||
1765 | complete(&fll->ok); | ||
1766 | |||
1767 | return IRQ_HANDLED; | ||
1768 | } | ||
1769 | |||
1770 | static struct { | 1759 | static struct { |
1771 | unsigned int min; | 1760 | unsigned int min; |
1772 | unsigned int max; | 1761 | unsigned int max; |
@@ -2048,17 +2037,18 @@ static int arizona_is_enabled_fll(struct arizona_fll *fll) | |||
2048 | static int arizona_enable_fll(struct arizona_fll *fll) | 2037 | static int arizona_enable_fll(struct arizona_fll *fll) |
2049 | { | 2038 | { |
2050 | struct arizona *arizona = fll->arizona; | 2039 | struct arizona *arizona = fll->arizona; |
2051 | unsigned long time_left; | ||
2052 | bool use_sync = false; | 2040 | bool use_sync = false; |
2053 | int already_enabled = arizona_is_enabled_fll(fll); | 2041 | int already_enabled = arizona_is_enabled_fll(fll); |
2054 | struct arizona_fll_cfg cfg; | 2042 | struct arizona_fll_cfg cfg; |
2043 | int i; | ||
2044 | unsigned int val; | ||
2055 | 2045 | ||
2056 | if (already_enabled < 0) | 2046 | if (already_enabled < 0) |
2057 | return already_enabled; | 2047 | return already_enabled; |
2058 | 2048 | ||
2059 | if (already_enabled) { | 2049 | if (already_enabled) { |
2060 | /* Facilitate smooth refclk across the transition */ | 2050 | /* Facilitate smooth refclk across the transition */ |
2061 | regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7, | 2051 | regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9, |
2062 | ARIZONA_FLL1_GAIN_MASK, 0); | 2052 | ARIZONA_FLL1_GAIN_MASK, 0); |
2063 | regmap_update_bits_async(fll->arizona->regmap, fll->base + 1, | 2053 | regmap_update_bits_async(fll->arizona->regmap, fll->base + 1, |
2064 | ARIZONA_FLL1_FREERUN, | 2054 | ARIZONA_FLL1_FREERUN, |
@@ -2110,9 +2100,6 @@ static int arizona_enable_fll(struct arizona_fll *fll) | |||
2110 | if (!already_enabled) | 2100 | if (!already_enabled) |
2111 | pm_runtime_get(arizona->dev); | 2101 | pm_runtime_get(arizona->dev); |
2112 | 2102 | ||
2113 | /* Clear any pending completions */ | ||
2114 | try_wait_for_completion(&fll->ok); | ||
2115 | |||
2116 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | 2103 | regmap_update_bits_async(arizona->regmap, fll->base + 1, |
2117 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); | 2104 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); |
2118 | if (use_sync) | 2105 | if (use_sync) |
@@ -2124,10 +2111,24 @@ static int arizona_enable_fll(struct arizona_fll *fll) | |||
2124 | regmap_update_bits_async(arizona->regmap, fll->base + 1, | 2111 | regmap_update_bits_async(arizona->regmap, fll->base + 1, |
2125 | ARIZONA_FLL1_FREERUN, 0); | 2112 | ARIZONA_FLL1_FREERUN, 0); |
2126 | 2113 | ||
2127 | time_left = wait_for_completion_timeout(&fll->ok, | 2114 | arizona_fll_dbg(fll, "Waiting for FLL lock...\n"); |
2128 | msecs_to_jiffies(250)); | 2115 | val = 0; |
2129 | if (time_left == 0) | 2116 | for (i = 0; i < 15; i++) { |
2117 | if (i < 5) | ||
2118 | usleep_range(200, 400); | ||
2119 | else | ||
2120 | msleep(20); | ||
2121 | |||
2122 | regmap_read(arizona->regmap, | ||
2123 | ARIZONA_INTERRUPT_RAW_STATUS_5, | ||
2124 | &val); | ||
2125 | if (val & (ARIZONA_FLL1_CLOCK_OK_STS << (fll->id - 1))) | ||
2126 | break; | ||
2127 | } | ||
2128 | if (i == 15) | ||
2130 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); | 2129 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); |
2130 | else | ||
2131 | arizona_fll_dbg(fll, "FLL locked (%d polls)\n", i); | ||
2131 | 2132 | ||
2132 | return 0; | 2133 | return 0; |
2133 | } | 2134 | } |
@@ -2212,11 +2213,8 @@ EXPORT_SYMBOL_GPL(arizona_set_fll); | |||
2212 | int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, | 2213 | int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, |
2213 | int ok_irq, struct arizona_fll *fll) | 2214 | int ok_irq, struct arizona_fll *fll) |
2214 | { | 2215 | { |
2215 | int ret; | ||
2216 | unsigned int val; | 2216 | unsigned int val; |
2217 | 2217 | ||
2218 | init_completion(&fll->ok); | ||
2219 | |||
2220 | fll->id = id; | 2218 | fll->id = id; |
2221 | fll->base = base; | 2219 | fll->base = base; |
2222 | fll->arizona = arizona; | 2220 | fll->arizona = arizona; |
@@ -2238,13 +2236,6 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, | |||
2238 | snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), | 2236 | snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), |
2239 | "FLL%d clock OK", id); | 2237 | "FLL%d clock OK", id); |
2240 | 2238 | ||
2241 | ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name, | ||
2242 | arizona_fll_clock_ok, fll); | ||
2243 | if (ret != 0) { | ||
2244 | dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n", | ||
2245 | id, ret); | ||
2246 | } | ||
2247 | |||
2248 | regmap_update_bits(arizona->regmap, fll->base + 1, | 2239 | regmap_update_bits(arizona->regmap, fll->base + 1, |
2249 | ARIZONA_FLL1_FREERUN, 0); | 2240 | ARIZONA_FLL1_FREERUN, 0); |
2250 | 2241 | ||
@@ -2313,6 +2304,82 @@ const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = { | |||
2313 | }; | 2304 | }; |
2314 | EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls); | 2305 | EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls); |
2315 | 2306 | ||
2307 | static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b) | ||
2308 | { | ||
2309 | s16 a = be16_to_cpu(_a); | ||
2310 | s16 b = be16_to_cpu(_b); | ||
2311 | |||
2312 | if (!mode) { | ||
2313 | return abs(a) >= 4096; | ||
2314 | } else { | ||
2315 | if (abs(b) >= 4096) | ||
2316 | return true; | ||
2317 | |||
2318 | return (abs((a << 16) / (4096 - b)) >= 4096 << 4); | ||
2319 | } | ||
2320 | } | ||
2321 | |||
2322 | int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol, | ||
2323 | struct snd_ctl_elem_value *ucontrol) | ||
2324 | { | ||
2325 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
2326 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
2327 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
2328 | unsigned int val; | ||
2329 | __be16 *data; | ||
2330 | int len; | ||
2331 | int ret; | ||
2332 | |||
2333 | len = params->num_regs * regmap_get_val_bytes(arizona->regmap); | ||
2334 | |||
2335 | data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); | ||
2336 | if (!data) | ||
2337 | return -ENOMEM; | ||
2338 | |||
2339 | data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE); | ||
2340 | |||
2341 | if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) || | ||
2342 | arizona_eq_filter_unstable(true, data[4], data[5]) || | ||
2343 | arizona_eq_filter_unstable(true, data[8], data[9]) || | ||
2344 | arizona_eq_filter_unstable(true, data[12], data[13]) || | ||
2345 | arizona_eq_filter_unstable(false, data[16], data[17])) { | ||
2346 | dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n"); | ||
2347 | ret = -EINVAL; | ||
2348 | goto out; | ||
2349 | } | ||
2350 | |||
2351 | ret = regmap_read(arizona->regmap, params->base, &val); | ||
2352 | if (ret != 0) | ||
2353 | goto out; | ||
2354 | |||
2355 | val &= ~ARIZONA_EQ1_B1_MODE; | ||
2356 | data[0] |= cpu_to_be16(val); | ||
2357 | |||
2358 | ret = regmap_raw_write(arizona->regmap, params->base, data, len); | ||
2359 | |||
2360 | out: | ||
2361 | kfree(data); | ||
2362 | return ret; | ||
2363 | } | ||
2364 | EXPORT_SYMBOL_GPL(arizona_eq_coeff_put); | ||
2365 | |||
2366 | int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol, | ||
2367 | struct snd_ctl_elem_value *ucontrol) | ||
2368 | { | ||
2369 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
2370 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
2371 | __be16 *data = (__be16 *)ucontrol->value.bytes.data; | ||
2372 | s16 val = be16_to_cpu(*data); | ||
2373 | |||
2374 | if (abs(val) >= 4096) { | ||
2375 | dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n"); | ||
2376 | return -EINVAL; | ||
2377 | } | ||
2378 | |||
2379 | return snd_soc_bytes_put(kcontrol, ucontrol); | ||
2380 | } | ||
2381 | EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put); | ||
2382 | |||
2316 | MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); | 2383 | MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); |
2317 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 2384 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
2318 | MODULE_LICENSE("GPL"); | 2385 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 43deb0462309..ada0a418ff4b 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -194,6 +194,20 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |||
194 | ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \ | 194 | ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \ |
195 | ARIZONA_MIXER_ROUTES(name " Preloader", name "R") | 195 | ARIZONA_MIXER_ROUTES(name " Preloader", name "R") |
196 | 196 | ||
197 | #define ARIZONA_EQ_CONTROL(xname, xbase) \ | ||
198 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
199 | .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \ | ||
200 | .put = arizona_eq_coeff_put, .private_value = \ | ||
201 | ((unsigned long)&(struct soc_bytes) { .base = xbase, \ | ||
202 | .num_regs = 20, .mask = ~ARIZONA_EQ1_B1_MODE }) } | ||
203 | |||
204 | #define ARIZONA_LHPF_CONTROL(xname, xbase) \ | ||
205 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
206 | .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \ | ||
207 | .put = arizona_lhpf_coeff_put, .private_value = \ | ||
208 | ((unsigned long)&(struct soc_bytes) { .base = xbase, \ | ||
209 | .num_regs = 1 }) } | ||
210 | |||
197 | #define ARIZONA_RATE_ENUM_SIZE 4 | 211 | #define ARIZONA_RATE_ENUM_SIZE 4 |
198 | extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; | 212 | extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; |
199 | extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; | 213 | extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; |
@@ -229,6 +243,11 @@ extern int arizona_hp_ev(struct snd_soc_dapm_widget *w, | |||
229 | struct snd_kcontrol *kcontrol, | 243 | struct snd_kcontrol *kcontrol, |
230 | int event); | 244 | int event); |
231 | 245 | ||
246 | extern int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol, | ||
247 | struct snd_ctl_elem_value *ucontrol); | ||
248 | extern int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol, | ||
249 | struct snd_ctl_elem_value *ucontrol); | ||
250 | |||
232 | extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | 251 | extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
233 | int source, unsigned int freq, int dir); | 252 | int source, unsigned int freq, int dir); |
234 | 253 | ||
@@ -242,7 +261,6 @@ struct arizona_fll { | |||
242 | int id; | 261 | int id; |
243 | unsigned int base; | 262 | unsigned int base; |
244 | unsigned int vco_mult; | 263 | unsigned int vco_mult; |
245 | struct completion ok; | ||
246 | 264 | ||
247 | unsigned int fout; | 265 | unsigned int fout; |
248 | int sync_src; | 266 | int sync_src; |
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 8f40025b7e7c..44c30fe3e315 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c | |||
@@ -74,33 +74,8 @@ static const struct reg_default cs35l32_reg_defaults[] = { | |||
74 | static bool cs35l32_readable_register(struct device *dev, unsigned int reg) | 74 | static bool cs35l32_readable_register(struct device *dev, unsigned int reg) |
75 | { | 75 | { |
76 | switch (reg) { | 76 | switch (reg) { |
77 | case CS35L32_DEVID_AB: | 77 | case CS35L32_DEVID_AB ... CS35L32_AUDIO_LED_MNGR: |
78 | case CS35L32_DEVID_CD: | 78 | case CS35L32_ADSP_CTL ... CS35L32_FLASH_INHIBIT: |
79 | case CS35L32_DEVID_E: | ||
80 | case CS35L32_FAB_ID: | ||
81 | case CS35L32_REV_ID: | ||
82 | case CS35L32_PWRCTL1: | ||
83 | case CS35L32_PWRCTL2: | ||
84 | case CS35L32_CLK_CTL: | ||
85 | case CS35L32_BATT_THRESHOLD: | ||
86 | case CS35L32_VMON: | ||
87 | case CS35L32_BST_CPCP_CTL: | ||
88 | case CS35L32_IMON_SCALING: | ||
89 | case CS35L32_AUDIO_LED_MNGR: | ||
90 | case CS35L32_ADSP_CTL: | ||
91 | case CS35L32_CLASSD_CTL: | ||
92 | case CS35L32_PROTECT_CTL: | ||
93 | case CS35L32_INT_MASK_1: | ||
94 | case CS35L32_INT_MASK_2: | ||
95 | case CS35L32_INT_MASK_3: | ||
96 | case CS35L32_INT_STATUS_1: | ||
97 | case CS35L32_INT_STATUS_2: | ||
98 | case CS35L32_INT_STATUS_3: | ||
99 | case CS35L32_LED_STATUS: | ||
100 | case CS35L32_FLASH_MODE: | ||
101 | case CS35L32_MOVIE_MODE: | ||
102 | case CS35L32_FLASH_TIMER: | ||
103 | case CS35L32_FLASH_INHIBIT: | ||
104 | return true; | 79 | return true; |
105 | default: | 80 | default: |
106 | return false; | 81 | return false; |
@@ -110,15 +85,8 @@ static bool cs35l32_readable_register(struct device *dev, unsigned int reg) | |||
110 | static bool cs35l32_volatile_register(struct device *dev, unsigned int reg) | 85 | static bool cs35l32_volatile_register(struct device *dev, unsigned int reg) |
111 | { | 86 | { |
112 | switch (reg) { | 87 | switch (reg) { |
113 | case CS35L32_DEVID_AB: | 88 | case CS35L32_DEVID_AB ... CS35L32_REV_ID: |
114 | case CS35L32_DEVID_CD: | 89 | case CS35L32_INT_STATUS_1 ... CS35L32_LED_STATUS: |
115 | case CS35L32_DEVID_E: | ||
116 | case CS35L32_FAB_ID: | ||
117 | case CS35L32_REV_ID: | ||
118 | case CS35L32_INT_STATUS_1: | ||
119 | case CS35L32_INT_STATUS_2: | ||
120 | case CS35L32_INT_STATUS_3: | ||
121 | case CS35L32_LED_STATUS: | ||
122 | return true; | 90 | return true; |
123 | default: | 91 | default: |
124 | return false; | 92 | return false; |
@@ -128,10 +96,7 @@ static bool cs35l32_volatile_register(struct device *dev, unsigned int reg) | |||
128 | static bool cs35l32_precious_register(struct device *dev, unsigned int reg) | 96 | static bool cs35l32_precious_register(struct device *dev, unsigned int reg) |
129 | { | 97 | { |
130 | switch (reg) { | 98 | switch (reg) { |
131 | case CS35L32_INT_STATUS_1: | 99 | case CS35L32_INT_STATUS_1 ... CS35L32_LED_STATUS: |
132 | case CS35L32_INT_STATUS_2: | ||
133 | case CS35L32_INT_STATUS_3: | ||
134 | case CS35L32_LED_STATUS: | ||
135 | return true; | 100 | return true; |
136 | default: | 101 | default: |
137 | return false; | 102 | return false; |
@@ -276,7 +241,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = { | |||
276 | }; | 241 | }; |
277 | 242 | ||
278 | /* Current and threshold powerup sequence Pg37 in datasheet */ | 243 | /* Current and threshold powerup sequence Pg37 in datasheet */ |
279 | static const struct reg_default cs35l32_monitor_patch[] = { | 244 | static const struct reg_sequence cs35l32_monitor_patch[] = { |
280 | 245 | ||
281 | { 0x00, 0x99 }, | 246 | { 0x00, 0x99 }, |
282 | { 0x48, 0x17 }, | 247 | { 0x48, 0x17 }, |
@@ -441,8 +406,7 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client, | |||
441 | if (IS_ERR(cs35l32->reset_gpio)) | 406 | if (IS_ERR(cs35l32->reset_gpio)) |
442 | return PTR_ERR(cs35l32->reset_gpio); | 407 | return PTR_ERR(cs35l32->reset_gpio); |
443 | 408 | ||
444 | if (cs35l32->reset_gpio) | 409 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 1); |
445 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 1); | ||
446 | 410 | ||
447 | /* initialize codec */ | 411 | /* initialize codec */ |
448 | ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, ®); | 412 | ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, ®); |
@@ -536,8 +500,7 @@ static int cs35l32_i2c_remove(struct i2c_client *i2c_client) | |||
536 | snd_soc_unregister_codec(&i2c_client->dev); | 500 | snd_soc_unregister_codec(&i2c_client->dev); |
537 | 501 | ||
538 | /* Hold down reset */ | 502 | /* Hold down reset */ |
539 | if (cs35l32->reset_gpio) | 503 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); |
540 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); | ||
541 | 504 | ||
542 | return 0; | 505 | return 0; |
543 | } | 506 | } |
@@ -551,8 +514,7 @@ static int cs35l32_runtime_suspend(struct device *dev) | |||
551 | regcache_mark_dirty(cs35l32->regmap); | 514 | regcache_mark_dirty(cs35l32->regmap); |
552 | 515 | ||
553 | /* Hold down reset */ | 516 | /* Hold down reset */ |
554 | if (cs35l32->reset_gpio) | 517 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); |
555 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); | ||
556 | 518 | ||
557 | /* remove power */ | 519 | /* remove power */ |
558 | regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies), | 520 | regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies), |
@@ -575,8 +537,7 @@ static int cs35l32_runtime_resume(struct device *dev) | |||
575 | return ret; | 537 | return ret; |
576 | } | 538 | } |
577 | 539 | ||
578 | if (cs35l32->reset_gpio) | 540 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 1); |
579 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 1); | ||
580 | 541 | ||
581 | regcache_cache_only(cs35l32->regmap, false); | 542 | regcache_cache_only(cs35l32->regmap, false); |
582 | regcache_sync(cs35l32->regmap); | 543 | regcache_sync(cs35l32->regmap); |
@@ -607,7 +568,6 @@ MODULE_DEVICE_TABLE(i2c, cs35l32_id); | |||
607 | static struct i2c_driver cs35l32_i2c_driver = { | 568 | static struct i2c_driver cs35l32_i2c_driver = { |
608 | .driver = { | 569 | .driver = { |
609 | .name = "cs35l32", | 570 | .name = "cs35l32", |
610 | .owner = THIS_MODULE, | ||
611 | .pm = &cs35l32_runtime_pm, | 571 | .pm = &cs35l32_runtime_pm, |
612 | .of_match_table = cs35l32_of_match, | 572 | .of_match_table = cs35l32_of_match, |
613 | }, | 573 | }, |
diff --git a/sound/soc/codecs/cs35l32.h b/sound/soc/codecs/cs35l32.h index 31ab804a22bc..1d6c2508cd41 100644 --- a/sound/soc/codecs/cs35l32.h +++ b/sound/soc/codecs/cs35l32.h | |||
@@ -80,7 +80,7 @@ struct cs35l32_platform_data { | |||
80 | #define CS35L32_GAIN_MGR_MASK 0x08 | 80 | #define CS35L32_GAIN_MGR_MASK 0x08 |
81 | #define CS35L32_ADSP_SHARE_MASK 0x08 | 81 | #define CS35L32_ADSP_SHARE_MASK 0x08 |
82 | #define CS35L32_ADSP_DATACFG_MASK 0x30 | 82 | #define CS35L32_ADSP_DATACFG_MASK 0x30 |
83 | #define CS35L32_SDOUT_3ST 0x80 | 83 | #define CS35L32_SDOUT_3ST 0x08 |
84 | #define CS35L32_BATT_REC_MASK 0x0E | 84 | #define CS35L32_BATT_REC_MASK 0x0E |
85 | #define CS35L32_BATT_THRESH_MASK 0x30 | 85 | #define CS35L32_BATT_THRESH_MASK 0x30 |
86 | 86 | ||
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 8e36198474d9..55db19ddc5ff 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c | |||
@@ -60,23 +60,7 @@ static const struct reg_default cs4265_reg_defaults[] = { | |||
60 | static bool cs4265_readable_register(struct device *dev, unsigned int reg) | 60 | static bool cs4265_readable_register(struct device *dev, unsigned int reg) |
61 | { | 61 | { |
62 | switch (reg) { | 62 | switch (reg) { |
63 | case CS4265_PWRCTL: | 63 | case CS4265_CHIP_ID ... CS4265_SPDIF_CTL2: |
64 | case CS4265_DAC_CTL: | ||
65 | case CS4265_ADC_CTL: | ||
66 | case CS4265_MCLK_FREQ: | ||
67 | case CS4265_SIG_SEL: | ||
68 | case CS4265_CHB_PGA_CTL: | ||
69 | case CS4265_CHA_PGA_CTL: | ||
70 | case CS4265_ADC_CTL2: | ||
71 | case CS4265_DAC_CHA_VOL: | ||
72 | case CS4265_DAC_CHB_VOL: | ||
73 | case CS4265_DAC_CTL2: | ||
74 | case CS4265_SPDIF_CTL1: | ||
75 | case CS4265_SPDIF_CTL2: | ||
76 | case CS4265_INT_MASK: | ||
77 | case CS4265_STATUS_MODE_MSB: | ||
78 | case CS4265_STATUS_MODE_LSB: | ||
79 | case CS4265_CHIP_ID: | ||
80 | return true; | 64 | return true; |
81 | default: | 65 | default: |
82 | return false; | 66 | return false; |
@@ -658,7 +642,6 @@ MODULE_DEVICE_TABLE(i2c, cs4265_id); | |||
658 | static struct i2c_driver cs4265_i2c_driver = { | 642 | static struct i2c_driver cs4265_i2c_driver = { |
659 | .driver = { | 643 | .driver = { |
660 | .name = "cs4265", | 644 | .name = "cs4265", |
661 | .owner = THIS_MODULE, | ||
662 | .of_match_table = cs4265_of_match, | 645 | .of_match_table = cs4265_of_match, |
663 | }, | 646 | }, |
664 | .id_table = cs4265_id, | 647 | .id_table = cs4265_id, |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index e6d4ff9fd992..e07807d96b68 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -751,7 +751,6 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id); | |||
751 | static struct i2c_driver cs4270_i2c_driver = { | 751 | static struct i2c_driver cs4270_i2c_driver = { |
752 | .driver = { | 752 | .driver = { |
753 | .name = "cs4270", | 753 | .name = "cs4270", |
754 | .owner = THIS_MODULE, | ||
755 | .of_match_table = cs4270_of_match, | 754 | .of_match_table = cs4270_of_match, |
756 | }, | 755 | }, |
757 | .id_table = cs4270_id, | 756 | .id_table = cs4270_id, |
diff --git a/sound/soc/codecs/cs4271-i2c.c b/sound/soc/codecs/cs4271-i2c.c index b264da030340..dcb3223d7d8f 100644 --- a/sound/soc/codecs/cs4271-i2c.c +++ b/sound/soc/codecs/cs4271-i2c.c | |||
@@ -48,7 +48,6 @@ MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); | |||
48 | static struct i2c_driver cs4271_i2c_driver = { | 48 | static struct i2c_driver cs4271_i2c_driver = { |
49 | .driver = { | 49 | .driver = { |
50 | .name = "cs4271", | 50 | .name = "cs4271", |
51 | .owner = THIS_MODULE, | ||
52 | .of_match_table = of_match_ptr(cs4271_dt_ids), | 51 | .of_match_table = of_match_ptr(cs4271_dt_ids), |
53 | }, | 52 | }, |
54 | .probe = cs4271_i2c_probe, | 53 | .probe = cs4271_i2c_probe, |
diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c index c40428f25ba5..9bad478474fa 100644 --- a/sound/soc/codecs/cs42l51-i2c.c +++ b/sound/soc/codecs/cs42l51-i2c.c | |||
@@ -45,7 +45,6 @@ static int cs42l51_i2c_remove(struct i2c_client *i2c) | |||
45 | static struct i2c_driver cs42l51_i2c_driver = { | 45 | static struct i2c_driver cs42l51_i2c_driver = { |
46 | .driver = { | 46 | .driver = { |
47 | .name = "cs42l51", | 47 | .name = "cs42l51", |
48 | .owner = THIS_MODULE, | ||
49 | .of_match_table = cs42l51_of_match, | 48 | .of_match_table = cs42l51_of_match, |
50 | }, | 49 | }, |
51 | .probe = cs42l51_i2c_probe, | 50 | .probe = cs42l51_i2c_probe, |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 4de52c9957ac..47b97fcefb0b 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -110,58 +110,7 @@ static const struct reg_default cs42l52_reg_defaults[] = { | |||
110 | static bool cs42l52_readable_register(struct device *dev, unsigned int reg) | 110 | static bool cs42l52_readable_register(struct device *dev, unsigned int reg) |
111 | { | 111 | { |
112 | switch (reg) { | 112 | switch (reg) { |
113 | case CS42L52_CHIP: | 113 | case CS42L52_CHIP ... CS42L52_CHARGE_PUMP: |
114 | case CS42L52_PWRCTL1: | ||
115 | case CS42L52_PWRCTL2: | ||
116 | case CS42L52_PWRCTL3: | ||
117 | case CS42L52_CLK_CTL: | ||
118 | case CS42L52_IFACE_CTL1: | ||
119 | case CS42L52_IFACE_CTL2: | ||
120 | case CS42L52_ADC_PGA_A: | ||
121 | case CS42L52_ADC_PGA_B: | ||
122 | case CS42L52_ANALOG_HPF_CTL: | ||
123 | case CS42L52_ADC_HPF_FREQ: | ||
124 | case CS42L52_ADC_MISC_CTL: | ||
125 | case CS42L52_PB_CTL1: | ||
126 | case CS42L52_MISC_CTL: | ||
127 | case CS42L52_PB_CTL2: | ||
128 | case CS42L52_MICA_CTL: | ||
129 | case CS42L52_MICB_CTL: | ||
130 | case CS42L52_PGAA_CTL: | ||
131 | case CS42L52_PGAB_CTL: | ||
132 | case CS42L52_PASSTHRUA_VOL: | ||
133 | case CS42L52_PASSTHRUB_VOL: | ||
134 | case CS42L52_ADCA_VOL: | ||
135 | case CS42L52_ADCB_VOL: | ||
136 | case CS42L52_ADCA_MIXER_VOL: | ||
137 | case CS42L52_ADCB_MIXER_VOL: | ||
138 | case CS42L52_PCMA_MIXER_VOL: | ||
139 | case CS42L52_PCMB_MIXER_VOL: | ||
140 | case CS42L52_BEEP_FREQ: | ||
141 | case CS42L52_BEEP_VOL: | ||
142 | case CS42L52_BEEP_TONE_CTL: | ||
143 | case CS42L52_TONE_CTL: | ||
144 | case CS42L52_MASTERA_VOL: | ||
145 | case CS42L52_MASTERB_VOL: | ||
146 | case CS42L52_HPA_VOL: | ||
147 | case CS42L52_HPB_VOL: | ||
148 | case CS42L52_SPKA_VOL: | ||
149 | case CS42L52_SPKB_VOL: | ||
150 | case CS42L52_ADC_PCM_MIXER: | ||
151 | case CS42L52_LIMITER_CTL1: | ||
152 | case CS42L52_LIMITER_CTL2: | ||
153 | case CS42L52_LIMITER_AT_RATE: | ||
154 | case CS42L52_ALC_CTL: | ||
155 | case CS42L52_ALC_RATE: | ||
156 | case CS42L52_ALC_THRESHOLD: | ||
157 | case CS42L52_NOISE_GATE_CTL: | ||
158 | case CS42L52_CLK_STATUS: | ||
159 | case CS42L52_BATT_COMPEN: | ||
160 | case CS42L52_BATT_LEVEL: | ||
161 | case CS42L52_SPK_STATUS: | ||
162 | case CS42L52_TEM_CTL: | ||
163 | case CS42L52_THE_FOLDBACK: | ||
164 | case CS42L52_CHARGE_PUMP: | ||
165 | return true; | 114 | return true; |
166 | default: | 115 | default: |
167 | return false; | 116 | return false; |
@@ -196,11 +145,10 @@ static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0); | |||
196 | 145 | ||
197 | static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0); | 146 | static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0); |
198 | 147 | ||
199 | static const unsigned int limiter_tlv[] = { | 148 | static const DECLARE_TLV_DB_RANGE(limiter_tlv, |
200 | TLV_DB_RANGE_HEAD(2), | ||
201 | 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), | 149 | 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), |
202 | 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0), | 150 | 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0) |
203 | }; | 151 | ); |
204 | 152 | ||
205 | static const char * const cs42l52_adca_text[] = { | 153 | static const char * const cs42l52_adca_text[] = { |
206 | "Input1A", "Input2A", "Input3A", "Input4A", "PGA Input Left"}; | 154 | "Input1A", "Input2A", "Input3A", "Input4A", "PGA Input Left"}; |
@@ -919,7 +867,7 @@ static int cs42l52_set_bias_level(struct snd_soc_codec *codec, | |||
919 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ | 867 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ |
920 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE) | 868 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE) |
921 | 869 | ||
922 | static struct snd_soc_dai_ops cs42l52_ops = { | 870 | static const struct snd_soc_dai_ops cs42l52_ops = { |
923 | .hw_params = cs42l52_pcm_hw_params, | 871 | .hw_params = cs42l52_pcm_hw_params, |
924 | .digital_mute = cs42l52_digital_mute, | 872 | .digital_mute = cs42l52_digital_mute, |
925 | .set_fmt = cs42l52_set_fmt, | 873 | .set_fmt = cs42l52_set_fmt, |
@@ -1118,7 +1066,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = { | |||
1118 | }; | 1066 | }; |
1119 | 1067 | ||
1120 | /* Current and threshold powerup sequence Pg37 */ | 1068 | /* Current and threshold powerup sequence Pg37 */ |
1121 | static const struct reg_default cs42l52_threshold_patch[] = { | 1069 | static const struct reg_sequence cs42l52_threshold_patch[] = { |
1122 | 1070 | ||
1123 | { 0x00, 0x99 }, | 1071 | { 0x00, 0x99 }, |
1124 | { 0x3E, 0xBA }, | 1072 | { 0x3E, 0xBA }, |
@@ -1285,7 +1233,6 @@ MODULE_DEVICE_TABLE(i2c, cs42l52_id); | |||
1285 | static struct i2c_driver cs42l52_i2c_driver = { | 1233 | static struct i2c_driver cs42l52_i2c_driver = { |
1286 | .driver = { | 1234 | .driver = { |
1287 | .name = "cs42l52", | 1235 | .name = "cs42l52", |
1288 | .owner = THIS_MODULE, | ||
1289 | .of_match_table = cs42l52_of_match, | 1236 | .of_match_table = cs42l52_of_match, |
1290 | }, | 1237 | }, |
1291 | .id_table = cs42l52_id, | 1238 | .id_table = cs42l52_id, |
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index 1e11ba45a79f..7cd5f769bb61 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c | |||
@@ -115,52 +115,7 @@ static const struct reg_default cs42l56_reg_defaults[] = { | |||
115 | static bool cs42l56_readable_register(struct device *dev, unsigned int reg) | 115 | static bool cs42l56_readable_register(struct device *dev, unsigned int reg) |
116 | { | 116 | { |
117 | switch (reg) { | 117 | switch (reg) { |
118 | case CS42L56_CHIP_ID_1: | 118 | case CS42L56_CHIP_ID_1 ... CS42L56_LIM_ATTACK_RATE: |
119 | case CS42L56_CHIP_ID_2: | ||
120 | case CS42L56_PWRCTL_1: | ||
121 | case CS42L56_PWRCTL_2: | ||
122 | case CS42L56_CLKCTL_1: | ||
123 | case CS42L56_CLKCTL_2: | ||
124 | case CS42L56_SERIAL_FMT: | ||
125 | case CS42L56_CLASSH_CTL: | ||
126 | case CS42L56_MISC_CTL: | ||
127 | case CS42L56_INT_STATUS: | ||
128 | case CS42L56_PLAYBACK_CTL: | ||
129 | case CS42L56_DSP_MUTE_CTL: | ||
130 | case CS42L56_ADCA_MIX_VOLUME: | ||
131 | case CS42L56_ADCB_MIX_VOLUME: | ||
132 | case CS42L56_PCMA_MIX_VOLUME: | ||
133 | case CS42L56_PCMB_MIX_VOLUME: | ||
134 | case CS42L56_ANAINPUT_ADV_VOLUME: | ||
135 | case CS42L56_DIGINPUT_ADV_VOLUME: | ||
136 | case CS42L56_MASTER_A_VOLUME: | ||
137 | case CS42L56_MASTER_B_VOLUME: | ||
138 | case CS42L56_BEEP_FREQ_ONTIME: | ||
139 | case CS42L56_BEEP_FREQ_OFFTIME: | ||
140 | case CS42L56_BEEP_TONE_CFG: | ||
141 | case CS42L56_TONE_CTL: | ||
142 | case CS42L56_CHAN_MIX_SWAP: | ||
143 | case CS42L56_AIN_REFCFG_ADC_MUX: | ||
144 | case CS42L56_HPF_CTL: | ||
145 | case CS42L56_MISC_ADC_CTL: | ||
146 | case CS42L56_GAIN_BIAS_CTL: | ||
147 | case CS42L56_PGAA_MUX_VOLUME: | ||
148 | case CS42L56_PGAB_MUX_VOLUME: | ||
149 | case CS42L56_ADCA_ATTENUATOR: | ||
150 | case CS42L56_ADCB_ATTENUATOR: | ||
151 | case CS42L56_ALC_EN_ATTACK_RATE: | ||
152 | case CS42L56_ALC_RELEASE_RATE: | ||
153 | case CS42L56_ALC_THRESHOLD: | ||
154 | case CS42L56_NOISE_GATE_CTL: | ||
155 | case CS42L56_ALC_LIM_SFT_ZC: | ||
156 | case CS42L56_AMUTE_HPLO_MUX: | ||
157 | case CS42L56_HPA_VOLUME: | ||
158 | case CS42L56_HPB_VOLUME: | ||
159 | case CS42L56_LOA_VOLUME: | ||
160 | case CS42L56_LOB_VOLUME: | ||
161 | case CS42L56_LIM_THRESHOLD_CTL: | ||
162 | case CS42L56_LIM_CTL_RELEASE_RATE: | ||
163 | case CS42L56_LIM_ATTACK_RATE: | ||
164 | return true; | 119 | return true; |
165 | default: | 120 | default: |
166 | return false; | 121 | return false; |
@@ -185,21 +140,18 @@ static DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); | |||
185 | static DECLARE_TLV_DB_SCALE(preamp_tlv, 0, 1000, 0); | 140 | static DECLARE_TLV_DB_SCALE(preamp_tlv, 0, 1000, 0); |
186 | static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0); | 141 | static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0); |
187 | 142 | ||
188 | static const unsigned int ngnb_tlv[] = { | 143 | static const DECLARE_TLV_DB_RANGE(ngnb_tlv, |
189 | TLV_DB_RANGE_HEAD(2), | ||
190 | 0, 1, TLV_DB_SCALE_ITEM(-8200, 600, 0), | 144 | 0, 1, TLV_DB_SCALE_ITEM(-8200, 600, 0), |
191 | 2, 5, TLV_DB_SCALE_ITEM(-7600, 300, 0), | 145 | 2, 5, TLV_DB_SCALE_ITEM(-7600, 300, 0) |
192 | }; | 146 | ); |
193 | static const unsigned int ngb_tlv[] = { | 147 | static const DECLARE_TLV_DB_RANGE(ngb_tlv, |
194 | TLV_DB_RANGE_HEAD(2), | ||
195 | 0, 2, TLV_DB_SCALE_ITEM(-6400, 600, 0), | 148 | 0, 2, TLV_DB_SCALE_ITEM(-6400, 600, 0), |
196 | 3, 7, TLV_DB_SCALE_ITEM(-4600, 300, 0), | 149 | 3, 7, TLV_DB_SCALE_ITEM(-4600, 300, 0) |
197 | }; | 150 | ); |
198 | static const unsigned int alc_tlv[] = { | 151 | static const DECLARE_TLV_DB_RANGE(alc_tlv, |
199 | TLV_DB_RANGE_HEAD(2), | ||
200 | 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), | 152 | 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), |
201 | 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0), | 153 | 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0) |
202 | }; | 154 | ); |
203 | 155 | ||
204 | static const char * const beep_config_text[] = { | 156 | static const char * const beep_config_text[] = { |
205 | "Off", "Single", "Multiple", "Continuous" | 157 | "Off", "Single", "Multiple", "Continuous" |
@@ -989,7 +941,7 @@ static int cs42l56_set_bias_level(struct snd_soc_codec *codec, | |||
989 | SNDRV_PCM_FMTBIT_S32_LE) | 941 | SNDRV_PCM_FMTBIT_S32_LE) |
990 | 942 | ||
991 | 943 | ||
992 | static struct snd_soc_dai_ops cs42l56_ops = { | 944 | static const struct snd_soc_dai_ops cs42l56_ops = { |
993 | .hw_params = cs42l56_pcm_hw_params, | 945 | .hw_params = cs42l56_pcm_hw_params, |
994 | .digital_mute = cs42l56_digital_mute, | 946 | .digital_mute = cs42l56_digital_mute, |
995 | .set_fmt = cs42l56_set_dai_fmt, | 947 | .set_fmt = cs42l56_set_dai_fmt, |
@@ -1408,7 +1360,6 @@ MODULE_DEVICE_TABLE(i2c, cs42l56_id); | |||
1408 | static struct i2c_driver cs42l56_i2c_driver = { | 1360 | static struct i2c_driver cs42l56_i2c_driver = { |
1409 | .driver = { | 1361 | .driver = { |
1410 | .name = "cs42l56", | 1362 | .name = "cs42l56", |
1411 | .owner = THIS_MODULE, | ||
1412 | .of_match_table = cs42l56_of_match, | 1363 | .of_match_table = cs42l56_of_match, |
1413 | }, | 1364 | }, |
1414 | .id_table = cs42l56_id, | 1365 | .id_table = cs42l56_id, |
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index b7853b9d3a60..42a8fd4e1f9b 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -153,111 +153,18 @@ static bool cs42l73_volatile_register(struct device *dev, unsigned int reg) | |||
153 | static bool cs42l73_readable_register(struct device *dev, unsigned int reg) | 153 | static bool cs42l73_readable_register(struct device *dev, unsigned int reg) |
154 | { | 154 | { |
155 | switch (reg) { | 155 | switch (reg) { |
156 | case CS42L73_DEVID_AB: | 156 | case CS42L73_DEVID_AB ... CS42L73_DEVID_E: |
157 | case CS42L73_DEVID_CD: | 157 | case CS42L73_REVID ... CS42L73_IM2: |
158 | case CS42L73_DEVID_E: | ||
159 | case CS42L73_REVID: | ||
160 | case CS42L73_PWRCTL1: | ||
161 | case CS42L73_PWRCTL2: | ||
162 | case CS42L73_PWRCTL3: | ||
163 | case CS42L73_CPFCHC: | ||
164 | case CS42L73_OLMBMSDC: | ||
165 | case CS42L73_DMMCC: | ||
166 | case CS42L73_XSPC: | ||
167 | case CS42L73_XSPMMCC: | ||
168 | case CS42L73_ASPC: | ||
169 | case CS42L73_ASPMMCC: | ||
170 | case CS42L73_VSPC: | ||
171 | case CS42L73_VSPMMCC: | ||
172 | case CS42L73_VXSPFS: | ||
173 | case CS42L73_MIOPC: | ||
174 | case CS42L73_ADCIPC: | ||
175 | case CS42L73_MICAPREPGAAVOL: | ||
176 | case CS42L73_MICBPREPGABVOL: | ||
177 | case CS42L73_IPADVOL: | ||
178 | case CS42L73_IPBDVOL: | ||
179 | case CS42L73_PBDC: | ||
180 | case CS42L73_HLADVOL: | ||
181 | case CS42L73_HLBDVOL: | ||
182 | case CS42L73_SPKDVOL: | ||
183 | case CS42L73_ESLDVOL: | ||
184 | case CS42L73_HPAAVOL: | ||
185 | case CS42L73_HPBAVOL: | ||
186 | case CS42L73_LOAAVOL: | ||
187 | case CS42L73_LOBAVOL: | ||
188 | case CS42L73_STRINV: | ||
189 | case CS42L73_XSPINV: | ||
190 | case CS42L73_ASPINV: | ||
191 | case CS42L73_VSPINV: | ||
192 | case CS42L73_LIMARATEHL: | ||
193 | case CS42L73_LIMRRATEHL: | ||
194 | case CS42L73_LMAXHL: | ||
195 | case CS42L73_LIMARATESPK: | ||
196 | case CS42L73_LIMRRATESPK: | ||
197 | case CS42L73_LMAXSPK: | ||
198 | case CS42L73_LIMARATEESL: | ||
199 | case CS42L73_LIMRRATEESL: | ||
200 | case CS42L73_LMAXESL: | ||
201 | case CS42L73_ALCARATE: | ||
202 | case CS42L73_ALCRRATE: | ||
203 | case CS42L73_ALCMINMAX: | ||
204 | case CS42L73_NGCAB: | ||
205 | case CS42L73_ALCNGMC: | ||
206 | case CS42L73_MIXERCTL: | ||
207 | case CS42L73_HLAIPAA: | ||
208 | case CS42L73_HLBIPBA: | ||
209 | case CS42L73_HLAXSPAA: | ||
210 | case CS42L73_HLBXSPBA: | ||
211 | case CS42L73_HLAASPAA: | ||
212 | case CS42L73_HLBASPBA: | ||
213 | case CS42L73_HLAVSPMA: | ||
214 | case CS42L73_HLBVSPMA: | ||
215 | case CS42L73_XSPAIPAA: | ||
216 | case CS42L73_XSPBIPBA: | ||
217 | case CS42L73_XSPAXSPAA: | ||
218 | case CS42L73_XSPBXSPBA: | ||
219 | case CS42L73_XSPAASPAA: | ||
220 | case CS42L73_XSPAASPBA: | ||
221 | case CS42L73_XSPAVSPMA: | ||
222 | case CS42L73_XSPBVSPMA: | ||
223 | case CS42L73_ASPAIPAA: | ||
224 | case CS42L73_ASPBIPBA: | ||
225 | case CS42L73_ASPAXSPAA: | ||
226 | case CS42L73_ASPBXSPBA: | ||
227 | case CS42L73_ASPAASPAA: | ||
228 | case CS42L73_ASPBASPBA: | ||
229 | case CS42L73_ASPAVSPMA: | ||
230 | case CS42L73_ASPBVSPMA: | ||
231 | case CS42L73_VSPAIPAA: | ||
232 | case CS42L73_VSPBIPBA: | ||
233 | case CS42L73_VSPAXSPAA: | ||
234 | case CS42L73_VSPBXSPBA: | ||
235 | case CS42L73_VSPAASPAA: | ||
236 | case CS42L73_VSPBASPBA: | ||
237 | case CS42L73_VSPAVSPMA: | ||
238 | case CS42L73_VSPBVSPMA: | ||
239 | case CS42L73_MMIXCTL: | ||
240 | case CS42L73_SPKMIPMA: | ||
241 | case CS42L73_SPKMXSPA: | ||
242 | case CS42L73_SPKMASPA: | ||
243 | case CS42L73_SPKMVSPMA: | ||
244 | case CS42L73_ESLMIPMA: | ||
245 | case CS42L73_ESLMXSPA: | ||
246 | case CS42L73_ESLMASPA: | ||
247 | case CS42L73_ESLMVSPMA: | ||
248 | case CS42L73_IM1: | ||
249 | case CS42L73_IM2: | ||
250 | return true; | 158 | return true; |
251 | default: | 159 | default: |
252 | return false; | 160 | return false; |
253 | } | 161 | } |
254 | } | 162 | } |
255 | 163 | ||
256 | static const unsigned int hpaloa_tlv[] = { | 164 | static const DECLARE_TLV_DB_RANGE(hpaloa_tlv, |
257 | TLV_DB_RANGE_HEAD(2), | ||
258 | 0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0), | 165 | 0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0), |
259 | 14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0), | 166 | 14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0) |
260 | }; | 167 | ); |
261 | 168 | ||
262 | static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2500, 0); | 169 | static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2500, 0); |
263 | 170 | ||
@@ -267,11 +174,10 @@ static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0); | |||
267 | 174 | ||
268 | static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0); | 175 | static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0); |
269 | 176 | ||
270 | static const unsigned int limiter_tlv[] = { | 177 | static const DECLARE_TLV_DB_RANGE(limiter_tlv, |
271 | TLV_DB_RANGE_HEAD(2), | ||
272 | 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), | 178 | 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), |
273 | 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0), | 179 | 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0) |
274 | }; | 180 | ); |
275 | 181 | ||
276 | static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1); | 182 | static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1); |
277 | 183 | ||
@@ -1236,8 +1142,8 @@ static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate) | |||
1236 | struct snd_soc_codec *codec = dai->codec; | 1142 | struct snd_soc_codec *codec = dai->codec; |
1237 | int id = dai->id; | 1143 | int id = dai->id; |
1238 | 1144 | ||
1239 | return snd_soc_update_bits(codec, CS42L73_SPC(id), | 1145 | return snd_soc_update_bits(codec, CS42L73_SPC(id), CS42L73_SP_3ST, |
1240 | 0x7F, tristate << 7); | 1146 | tristate << 7); |
1241 | } | 1147 | } |
1242 | 1148 | ||
1243 | static const struct snd_pcm_hw_constraint_list constraints_12_24 = { | 1149 | static const struct snd_pcm_hw_constraint_list constraints_12_24 = { |
@@ -1491,7 +1397,6 @@ MODULE_DEVICE_TABLE(i2c, cs42l73_id); | |||
1491 | static struct i2c_driver cs42l73_i2c_driver = { | 1397 | static struct i2c_driver cs42l73_i2c_driver = { |
1492 | .driver = { | 1398 | .driver = { |
1493 | .name = "cs42l73", | 1399 | .name = "cs42l73", |
1494 | .owner = THIS_MODULE, | ||
1495 | .of_match_table = cs42l73_of_match, | 1400 | .of_match_table = cs42l73_of_match, |
1496 | }, | 1401 | }, |
1497 | .id_table = cs42l73_id, | 1402 | .id_table = cs42l73_id, |
diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c index 657dce27eade..800c1d549347 100644 --- a/sound/soc/codecs/cs42xx8-i2c.c +++ b/sound/soc/codecs/cs42xx8-i2c.c | |||
@@ -20,7 +20,7 @@ | |||
20 | static int cs42xx8_i2c_probe(struct i2c_client *i2c, | 20 | static int cs42xx8_i2c_probe(struct i2c_client *i2c, |
21 | const struct i2c_device_id *id) | 21 | const struct i2c_device_id *id) |
22 | { | 22 | { |
23 | u32 ret = cs42xx8_probe(&i2c->dev, | 23 | int ret = cs42xx8_probe(&i2c->dev, |
24 | devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config)); | 24 | devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config)); |
25 | if (ret) | 25 | if (ret) |
26 | return ret; | 26 | return ret; |
@@ -49,8 +49,8 @@ MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id); | |||
49 | static struct i2c_driver cs42xx8_i2c_driver = { | 49 | static struct i2c_driver cs42xx8_i2c_driver = { |
50 | .driver = { | 50 | .driver = { |
51 | .name = "cs42xx8", | 51 | .name = "cs42xx8", |
52 | .owner = THIS_MODULE, | ||
53 | .pm = &cs42xx8_pm, | 52 | .pm = &cs42xx8_pm, |
53 | .of_match_table = cs42xx8_of_match, | ||
54 | }, | 54 | }, |
55 | .probe = cs42xx8_i2c_probe, | 55 | .probe = cs42xx8_i2c_probe, |
56 | .remove = cs42xx8_i2c_remove, | 56 | .remove = cs42xx8_i2c_remove, |
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index e1d46862e81f..d562e1b9a5d1 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c | |||
@@ -425,7 +425,7 @@ const struct cs42xx8_driver_data cs42888_data = { | |||
425 | }; | 425 | }; |
426 | EXPORT_SYMBOL_GPL(cs42888_data); | 426 | EXPORT_SYMBOL_GPL(cs42888_data); |
427 | 427 | ||
428 | static const struct of_device_id cs42xx8_of_match[] = { | 428 | const struct of_device_id cs42xx8_of_match[] = { |
429 | { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, | 429 | { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, |
430 | { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, | 430 | { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, |
431 | { /* sentinel */ } | 431 | { /* sentinel */ } |
@@ -435,16 +435,24 @@ EXPORT_SYMBOL_GPL(cs42xx8_of_match); | |||
435 | 435 | ||
436 | int cs42xx8_probe(struct device *dev, struct regmap *regmap) | 436 | int cs42xx8_probe(struct device *dev, struct regmap *regmap) |
437 | { | 437 | { |
438 | const struct of_device_id *of_id = of_match_device(cs42xx8_of_match, dev); | 438 | const struct of_device_id *of_id; |
439 | struct cs42xx8_priv *cs42xx8; | 439 | struct cs42xx8_priv *cs42xx8; |
440 | int ret, val, i; | 440 | int ret, val, i; |
441 | 441 | ||
442 | if (IS_ERR(regmap)) { | ||
443 | ret = PTR_ERR(regmap); | ||
444 | dev_err(dev, "failed to allocate regmap: %d\n", ret); | ||
445 | return ret; | ||
446 | } | ||
447 | |||
442 | cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL); | 448 | cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL); |
443 | if (cs42xx8 == NULL) | 449 | if (cs42xx8 == NULL) |
444 | return -ENOMEM; | 450 | return -ENOMEM; |
445 | 451 | ||
452 | cs42xx8->regmap = regmap; | ||
446 | dev_set_drvdata(dev, cs42xx8); | 453 | dev_set_drvdata(dev, cs42xx8); |
447 | 454 | ||
455 | of_id = of_match_device(cs42xx8_of_match, dev); | ||
448 | if (of_id) | 456 | if (of_id) |
449 | cs42xx8->drvdata = of_id->data; | 457 | cs42xx8->drvdata = of_id->data; |
450 | 458 | ||
@@ -482,13 +490,6 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap) | |||
482 | /* Make sure hardware reset done */ | 490 | /* Make sure hardware reset done */ |
483 | msleep(5); | 491 | msleep(5); |
484 | 492 | ||
485 | cs42xx8->regmap = regmap; | ||
486 | if (IS_ERR(cs42xx8->regmap)) { | ||
487 | ret = PTR_ERR(cs42xx8->regmap); | ||
488 | dev_err(dev, "failed to allocate regmap: %d\n", ret); | ||
489 | goto err_enable; | ||
490 | } | ||
491 | |||
492 | /* | 493 | /* |
493 | * We haven't marked the chip revision as volatile due to | 494 | * We haven't marked the chip revision as volatile due to |
494 | * sharing a register with the right input volume; explicitly | 495 | * sharing a register with the right input volume; explicitly |
diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h index b2c10e537ef6..d36c61b6df74 100644 --- a/sound/soc/codecs/cs42xx8.h +++ b/sound/soc/codecs/cs42xx8.h | |||
@@ -22,6 +22,7 @@ extern const struct dev_pm_ops cs42xx8_pm; | |||
22 | extern const struct cs42xx8_driver_data cs42448_data; | 22 | extern const struct cs42xx8_driver_data cs42448_data; |
23 | extern const struct cs42xx8_driver_data cs42888_data; | 23 | extern const struct cs42xx8_driver_data cs42888_data; |
24 | extern const struct regmap_config cs42xx8_regmap_config; | 24 | extern const struct regmap_config cs42xx8_regmap_config; |
25 | extern const struct of_device_id cs42xx8_of_match[]; | ||
25 | int cs42xx8_probe(struct device *dev, struct regmap *regmap); | 26 | int cs42xx8_probe(struct device *dev, struct regmap *regmap); |
26 | 27 | ||
27 | /* CS42888 register map */ | 28 | /* CS42888 register map */ |
diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c new file mode 100644 index 000000000000..0ac8fc5ed4ae --- /dev/null +++ b/sound/soc/codecs/cs4349.c | |||
@@ -0,0 +1,392 @@ | |||
1 | /* | ||
2 | * cs4349.c -- CS4349 ALSA Soc Audio driver | ||
3 | * | ||
4 | * Copyright 2015 Cirrus Logic, Inc. | ||
5 | * | ||
6 | * Authors: Tim Howe <Tim.Howe@cirrus.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/gpio/consumer.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/pm.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/of_device.h> | ||
24 | #include <linux/regmap.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/pcm_params.h> | ||
29 | #include <sound/soc.h> | ||
30 | #include <sound/soc-dapm.h> | ||
31 | #include <sound/initval.h> | ||
32 | #include <sound/tlv.h> | ||
33 | #include "cs4349.h" | ||
34 | |||
35 | |||
36 | static const struct reg_default cs4349_reg_defaults[] = { | ||
37 | { 2, 0x00 }, /* r02 - Mode Control */ | ||
38 | { 3, 0x09 }, /* r03 - Volume, Mixing and Inversion Control */ | ||
39 | { 4, 0x81 }, /* r04 - Mute Control */ | ||
40 | { 5, 0x00 }, /* r05 - Channel A Volume Control */ | ||
41 | { 6, 0x00 }, /* r06 - Channel B Volume Control */ | ||
42 | { 7, 0xB1 }, /* r07 - Ramp and Filter Control */ | ||
43 | { 8, 0x1C }, /* r08 - Misc. Control */ | ||
44 | }; | ||
45 | |||
46 | /* Private data for the CS4349 */ | ||
47 | struct cs4349_private { | ||
48 | struct regmap *regmap; | ||
49 | struct gpio_desc *reset_gpio; | ||
50 | unsigned int mode; | ||
51 | int rate; | ||
52 | }; | ||
53 | |||
54 | static bool cs4349_readable_register(struct device *dev, unsigned int reg) | ||
55 | { | ||
56 | switch (reg) { | ||
57 | case CS4349_CHIPID ... CS4349_MISC: | ||
58 | return true; | ||
59 | default: | ||
60 | return false; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | static bool cs4349_writeable_register(struct device *dev, unsigned int reg) | ||
65 | { | ||
66 | switch (reg) { | ||
67 | case CS4349_MODE ... CS4349_MISC: | ||
68 | return true; | ||
69 | default: | ||
70 | return false; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | static int cs4349_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
75 | unsigned int format) | ||
76 | { | ||
77 | struct snd_soc_codec *codec = codec_dai->codec; | ||
78 | struct cs4349_private *cs4349 = snd_soc_codec_get_drvdata(codec); | ||
79 | unsigned int fmt; | ||
80 | |||
81 | fmt = format & SND_SOC_DAIFMT_FORMAT_MASK; | ||
82 | |||
83 | switch (fmt) { | ||
84 | case SND_SOC_DAIFMT_I2S: | ||
85 | case SND_SOC_DAIFMT_LEFT_J: | ||
86 | case SND_SOC_DAIFMT_RIGHT_J: | ||
87 | cs4349->mode = format & SND_SOC_DAIFMT_FORMAT_MASK; | ||
88 | break; | ||
89 | default: | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int cs4349_pcm_hw_params(struct snd_pcm_substream *substream, | ||
97 | struct snd_pcm_hw_params *params, | ||
98 | struct snd_soc_dai *dai) | ||
99 | { | ||
100 | struct snd_soc_codec *codec = dai->codec; | ||
101 | struct cs4349_private *cs4349 = snd_soc_codec_get_drvdata(codec); | ||
102 | int fmt, ret; | ||
103 | |||
104 | cs4349->rate = params_rate(params); | ||
105 | |||
106 | switch (cs4349->mode) { | ||
107 | case SND_SOC_DAIFMT_I2S: | ||
108 | fmt = DIF_I2S; | ||
109 | break; | ||
110 | case SND_SOC_DAIFMT_LEFT_J: | ||
111 | fmt = DIF_LEFT_JST; | ||
112 | break; | ||
113 | case SND_SOC_DAIFMT_RIGHT_J: | ||
114 | switch (params_width(params)) { | ||
115 | case 16: | ||
116 | fmt = DIF_RGHT_JST16; | ||
117 | break; | ||
118 | case 24: | ||
119 | fmt = DIF_RGHT_JST24; | ||
120 | break; | ||
121 | default: | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | break; | ||
125 | default: | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | ret = snd_soc_update_bits(codec, CS4349_MODE, DIF_MASK, | ||
130 | MODE_FORMAT(fmt)); | ||
131 | if (ret < 0) | ||
132 | return ret; | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int cs4349_digital_mute(struct snd_soc_dai *dai, int mute) | ||
138 | { | ||
139 | struct snd_soc_codec *codec = dai->codec; | ||
140 | int reg; | ||
141 | |||
142 | reg = 0; | ||
143 | if (mute) | ||
144 | reg = MUTE_AB_MASK; | ||
145 | |||
146 | return snd_soc_update_bits(codec, CS4349_MUTE, MUTE_AB_MASK, reg); | ||
147 | } | ||
148 | |||
149 | static DECLARE_TLV_DB_SCALE(dig_tlv, -12750, 50, 0); | ||
150 | |||
151 | static const char * const chan_mix_texts[] = { | ||
152 | "Mute", "MuteA", "MuteA SwapB", "MuteA MonoB", "SwapA MuteB", | ||
153 | "BothR", "Swap", "SwapA MonoB", "MuteB", "Normal", "BothL", | ||
154 | "MonoB", "MonoA MuteB", "MonoA", "MonoA SwapB", "Mono", | ||
155 | /*Normal == Channel A = Left, Channel B = Right*/ | ||
156 | }; | ||
157 | |||
158 | static const char * const fm_texts[] = { | ||
159 | "Auto", "Single", "Double", "Quad", | ||
160 | }; | ||
161 | |||
162 | static const char * const deemph_texts[] = { | ||
163 | "None", "44.1k", "48k", "32k", | ||
164 | }; | ||
165 | |||
166 | static const char * const softr_zeroc_texts[] = { | ||
167 | "Immediate", "Zero Cross", "Soft Ramp", "SR on ZC", | ||
168 | }; | ||
169 | |||
170 | static int deemph_values[] = { | ||
171 | 0, 4, 8, 12, | ||
172 | }; | ||
173 | |||
174 | static int softr_zeroc_values[] = { | ||
175 | 0, 64, 128, 192, | ||
176 | }; | ||
177 | |||
178 | static const struct soc_enum chan_mix_enum = | ||
179 | SOC_ENUM_SINGLE(CS4349_VMI, 0, | ||
180 | ARRAY_SIZE(chan_mix_texts), | ||
181 | chan_mix_texts); | ||
182 | |||
183 | static const struct soc_enum fm_mode_enum = | ||
184 | SOC_ENUM_SINGLE(CS4349_MODE, 0, | ||
185 | ARRAY_SIZE(fm_texts), | ||
186 | fm_texts); | ||
187 | |||
188 | static SOC_VALUE_ENUM_SINGLE_DECL(deemph_enum, CS4349_MODE, 0, DEM_MASK, | ||
189 | deemph_texts, deemph_values); | ||
190 | |||
191 | static SOC_VALUE_ENUM_SINGLE_DECL(softr_zeroc_enum, CS4349_RMPFLT, 0, | ||
192 | SR_ZC_MASK, softr_zeroc_texts, | ||
193 | softr_zeroc_values); | ||
194 | |||
195 | static const struct snd_kcontrol_new cs4349_snd_controls[] = { | ||
196 | SOC_DOUBLE_R_TLV("Master Playback Volume", | ||
197 | CS4349_VOLA, CS4349_VOLB, 0, 0xFF, 1, dig_tlv), | ||
198 | SOC_ENUM("Functional Mode", fm_mode_enum), | ||
199 | SOC_ENUM("De-Emphasis Control", deemph_enum), | ||
200 | SOC_ENUM("Soft Ramp Zero Cross Control", softr_zeroc_enum), | ||
201 | SOC_ENUM("Channel Mixer", chan_mix_enum), | ||
202 | SOC_SINGLE("VolA = VolB Switch", CS4349_VMI, 7, 1, 0), | ||
203 | SOC_SINGLE("InvertA Switch", CS4349_VMI, 6, 1, 0), | ||
204 | SOC_SINGLE("InvertB Switch", CS4349_VMI, 5, 1, 0), | ||
205 | SOC_SINGLE("Auto-Mute Switch", CS4349_MUTE, 7, 1, 0), | ||
206 | SOC_SINGLE("MUTEC A = B Switch", CS4349_MUTE, 5, 1, 0), | ||
207 | SOC_SINGLE("Soft Ramp Up Switch", CS4349_RMPFLT, 5, 1, 0), | ||
208 | SOC_SINGLE("Soft Ramp Down Switch", CS4349_RMPFLT, 4, 1, 0), | ||
209 | SOC_SINGLE("Slow Roll Off Filter Switch", CS4349_RMPFLT, 2, 1, 0), | ||
210 | SOC_SINGLE("Freeze Switch", CS4349_MISC, 5, 1, 0), | ||
211 | SOC_SINGLE("Popguard Switch", CS4349_MISC, 4, 1, 0), | ||
212 | }; | ||
213 | |||
214 | static const struct snd_soc_dapm_widget cs4349_dapm_widgets[] = { | ||
215 | SND_SOC_DAPM_DAC("HiFi DAC", NULL, SND_SOC_NOPM, 0, 0), | ||
216 | |||
217 | SND_SOC_DAPM_OUTPUT("OutputA"), | ||
218 | SND_SOC_DAPM_OUTPUT("OutputB"), | ||
219 | }; | ||
220 | |||
221 | static const struct snd_soc_dapm_route cs4349_routes[] = { | ||
222 | {"DAC Playback", NULL, "OutputA"}, | ||
223 | {"DAC Playback", NULL, "OutputB"}, | ||
224 | |||
225 | {"OutputA", NULL, "HiFi DAC"}, | ||
226 | {"OutputB", NULL, "HiFi DAC"}, | ||
227 | }; | ||
228 | |||
229 | #define CS4349_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ | ||
230 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
231 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ | ||
232 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ | ||
233 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ | ||
234 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \ | ||
235 | SNDRV_PCM_FMTBIT_S32_LE) | ||
236 | |||
237 | #define CS4349_PCM_RATES SNDRV_PCM_RATE_8000_192000 | ||
238 | |||
239 | static const struct snd_soc_dai_ops cs4349_dai_ops = { | ||
240 | .hw_params = cs4349_pcm_hw_params, | ||
241 | .set_fmt = cs4349_set_dai_fmt, | ||
242 | .digital_mute = cs4349_digital_mute, | ||
243 | }; | ||
244 | |||
245 | static struct snd_soc_dai_driver cs4349_dai = { | ||
246 | .name = "cs4349_hifi", | ||
247 | .playback = { | ||
248 | .stream_name = "DAC Playback", | ||
249 | .channels_min = 1, | ||
250 | .channels_max = 2, | ||
251 | .rates = CS4349_PCM_RATES, | ||
252 | .formats = CS4349_PCM_FORMATS, | ||
253 | }, | ||
254 | .ops = &cs4349_dai_ops, | ||
255 | .symmetric_rates = 1, | ||
256 | }; | ||
257 | |||
258 | static struct snd_soc_codec_driver soc_codec_dev_cs4349 = { | ||
259 | .controls = cs4349_snd_controls, | ||
260 | .num_controls = ARRAY_SIZE(cs4349_snd_controls), | ||
261 | |||
262 | .dapm_widgets = cs4349_dapm_widgets, | ||
263 | .num_dapm_widgets = ARRAY_SIZE(cs4349_dapm_widgets), | ||
264 | .dapm_routes = cs4349_routes, | ||
265 | .num_dapm_routes = ARRAY_SIZE(cs4349_routes), | ||
266 | }; | ||
267 | |||
268 | static const struct regmap_config cs4349_regmap = { | ||
269 | .reg_bits = 8, | ||
270 | .val_bits = 8, | ||
271 | |||
272 | .max_register = CS4349_MISC, | ||
273 | .reg_defaults = cs4349_reg_defaults, | ||
274 | .num_reg_defaults = ARRAY_SIZE(cs4349_reg_defaults), | ||
275 | .readable_reg = cs4349_readable_register, | ||
276 | .writeable_reg = cs4349_writeable_register, | ||
277 | .cache_type = REGCACHE_RBTREE, | ||
278 | }; | ||
279 | |||
280 | static int cs4349_i2c_probe(struct i2c_client *client, | ||
281 | const struct i2c_device_id *id) | ||
282 | { | ||
283 | struct cs4349_private *cs4349; | ||
284 | int ret; | ||
285 | |||
286 | cs4349 = devm_kzalloc(&client->dev, sizeof(*cs4349), GFP_KERNEL); | ||
287 | if (!cs4349) | ||
288 | return -ENOMEM; | ||
289 | |||
290 | cs4349->regmap = devm_regmap_init_i2c(client, &cs4349_regmap); | ||
291 | if (IS_ERR(cs4349->regmap)) { | ||
292 | ret = PTR_ERR(cs4349->regmap); | ||
293 | dev_err(&client->dev, "regmap_init() failed: %d\n", ret); | ||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | /* Reset the Device */ | ||
298 | cs4349->reset_gpio = devm_gpiod_get_optional(&client->dev, | ||
299 | "reset", GPIOD_OUT_LOW); | ||
300 | if (IS_ERR(cs4349->reset_gpio)) | ||
301 | return PTR_ERR(cs4349->reset_gpio); | ||
302 | |||
303 | gpiod_set_value_cansleep(cs4349->reset_gpio, 1); | ||
304 | |||
305 | i2c_set_clientdata(client, cs4349); | ||
306 | |||
307 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4349, | ||
308 | &cs4349_dai, 1); | ||
309 | } | ||
310 | |||
311 | static int cs4349_i2c_remove(struct i2c_client *client) | ||
312 | { | ||
313 | struct cs4349_private *cs4349 = i2c_get_clientdata(client); | ||
314 | |||
315 | snd_soc_unregister_codec(&client->dev); | ||
316 | |||
317 | /* Hold down reset */ | ||
318 | gpiod_set_value_cansleep(cs4349->reset_gpio, 0); | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | #ifdef CONFIG_PM | ||
324 | static int cs4349_runtime_suspend(struct device *dev) | ||
325 | { | ||
326 | struct cs4349_private *cs4349 = dev_get_drvdata(dev); | ||
327 | int ret; | ||
328 | |||
329 | ret = regmap_update_bits(cs4349->regmap, CS4349_MISC, PWR_DWN, PWR_DWN); | ||
330 | if (ret < 0) | ||
331 | return ret; | ||
332 | |||
333 | regcache_cache_only(cs4349->regmap, true); | ||
334 | |||
335 | /* Hold down reset */ | ||
336 | gpiod_set_value_cansleep(cs4349->reset_gpio, 0); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static int cs4349_runtime_resume(struct device *dev) | ||
342 | { | ||
343 | struct cs4349_private *cs4349 = dev_get_drvdata(dev); | ||
344 | int ret; | ||
345 | |||
346 | ret = regmap_update_bits(cs4349->regmap, CS4349_MISC, PWR_DWN, 0); | ||
347 | if (ret < 0) | ||
348 | return ret; | ||
349 | |||
350 | gpiod_set_value_cansleep(cs4349->reset_gpio, 1); | ||
351 | |||
352 | regcache_cache_only(cs4349->regmap, false); | ||
353 | regcache_sync(cs4349->regmap); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | #endif | ||
358 | |||
359 | static const struct dev_pm_ops cs4349_runtime_pm = { | ||
360 | SET_RUNTIME_PM_OPS(cs4349_runtime_suspend, cs4349_runtime_resume, | ||
361 | NULL) | ||
362 | }; | ||
363 | |||
364 | static const struct of_device_id cs4349_of_match[] = { | ||
365 | { .compatible = "cirrus,cs4349", }, | ||
366 | {}, | ||
367 | }; | ||
368 | |||
369 | MODULE_DEVICE_TABLE(of, cs4349_of_match); | ||
370 | |||
371 | static const struct i2c_device_id cs4349_i2c_id[] = { | ||
372 | {"cs4349", 0}, | ||
373 | {} | ||
374 | }; | ||
375 | |||
376 | MODULE_DEVICE_TABLE(i2c, cs4349_i2c_id); | ||
377 | |||
378 | static struct i2c_driver cs4349_i2c_driver = { | ||
379 | .driver = { | ||
380 | .name = "cs4349", | ||
381 | .of_match_table = cs4349_of_match, | ||
382 | }, | ||
383 | .id_table = cs4349_i2c_id, | ||
384 | .probe = cs4349_i2c_probe, | ||
385 | .remove = cs4349_i2c_remove, | ||
386 | }; | ||
387 | |||
388 | module_i2c_driver(cs4349_i2c_driver); | ||
389 | |||
390 | MODULE_AUTHOR("Tim Howe <tim.howe@cirrus.com>"); | ||
391 | MODULE_DESCRIPTION("Cirrus Logic CS4349 ALSA SoC Codec Driver"); | ||
392 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs4349.h b/sound/soc/codecs/cs4349.h new file mode 100644 index 000000000000..d58c06a25358 --- /dev/null +++ b/sound/soc/codecs/cs4349.h | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * ALSA SoC CS4349 codec driver | ||
3 | * | ||
4 | * Copyright 2015 Cirrus Logic, Inc. | ||
5 | * | ||
6 | * Author: Tim Howe <Tim.Howe@cirrus.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef __CS4349_H__ | ||
20 | #define __CS4349_H__ | ||
21 | |||
22 | /* CS4349 registers addresses */ | ||
23 | #define CS4349_CHIPID 0x01 /* Device and Rev ID, Read Only */ | ||
24 | #define CS4349_MODE 0x02 /* Mode Control */ | ||
25 | #define CS4349_VMI 0x03 /* Volume, Mixing, Inversion Control */ | ||
26 | #define CS4349_MUTE 0x04 /* Mute Control */ | ||
27 | #define CS4349_VOLA 0x05 /* DAC Channel A Volume Control */ | ||
28 | #define CS4349_VOLB 0x06 /* DAC Channel B Volume Control */ | ||
29 | #define CS4349_RMPFLT 0x07 /* Ramp and Filter Control */ | ||
30 | #define CS4349_MISC 0x08 /* Power Down,Freeze Control,Pop Stop*/ | ||
31 | |||
32 | #define CS4349_I2C_INCR 0x80 | ||
33 | |||
34 | |||
35 | /* Device and Revision ID */ | ||
36 | #define CS4349_REVA 0xF0 /* Rev A */ | ||
37 | #define CS4349_REVB 0xF1 /* Rev B */ | ||
38 | #define CS4349_REVC2 0xFF /* Rev C2 */ | ||
39 | |||
40 | |||
41 | /* PDN_DONE Poll Maximum | ||
42 | * If soft ramp is set it will take much longer to power down | ||
43 | * the system. | ||
44 | */ | ||
45 | #define PDN_POLL_MAX 900 | ||
46 | |||
47 | |||
48 | /* Bitfield Definitions */ | ||
49 | |||
50 | /* CS4349_MODE */ | ||
51 | /* (Digital Interface Format, De-Emphasis Control, Functional Mode */ | ||
52 | #define DIF2 (1 << 6) | ||
53 | #define DIF1 (1 << 5) | ||
54 | #define DIF0 (1 << 4) | ||
55 | #define DEM1 (1 << 3) | ||
56 | #define DEM0 (1 << 2) | ||
57 | #define FM1 (1 << 1) | ||
58 | #define DIF_LEFT_JST 0x00 | ||
59 | #define DIF_I2S 0x01 | ||
60 | #define DIF_RGHT_JST16 0x02 | ||
61 | #define DIF_RGHT_JST24 0x03 | ||
62 | #define DIF_TDM0 0x04 | ||
63 | #define DIF_TDM1 0x05 | ||
64 | #define DIF_TDM2 0x06 | ||
65 | #define DIF_TDM3 0x07 | ||
66 | #define DIF_MASK 0x70 | ||
67 | #define MODE_FORMAT(x) (((x)&7)<<4) | ||
68 | #define DEM_MASK 0x0C | ||
69 | #define NO_DEM 0x00 | ||
70 | #define DEM_441 0x04 | ||
71 | #define DEM_48K 0x08 | ||
72 | #define DEM_32K 0x0C | ||
73 | #define FM_AUTO 0x00 | ||
74 | #define FM_SNGL 0x01 | ||
75 | #define FM_DBL 0x02 | ||
76 | #define FM_QUAD 0x03 | ||
77 | #define FM_SNGL_MIN 30000 | ||
78 | #define FM_SNGL_MAX 54000 | ||
79 | #define FM_DBL_MAX 108000 | ||
80 | #define FM_QUAD_MAX 216000 | ||
81 | #define FM_MASK 0x03 | ||
82 | |||
83 | /* CS4349_VMI (VMI = Volume, Mixing and Inversion Controls) */ | ||
84 | #define VOLBISA (1 << 7) | ||
85 | #define VOLAISB (1 << 7) | ||
86 | /* INVERT_A only available for Left Jstfd, Right Jstfd16 and Right Jstfd24 */ | ||
87 | #define INVERT_A (1 << 6) | ||
88 | /* INVERT_B only available for Left Jstfd, Right Jstfd16 and Right Jstfd24 */ | ||
89 | #define INVERT_B (1 << 5) | ||
90 | #define ATAPI3 (1 << 3) | ||
91 | #define ATAPI2 (1 << 2) | ||
92 | #define ATAPI1 (1 << 1) | ||
93 | #define ATAPI0 (1 << 0) | ||
94 | #define MUTEAB 0x00 | ||
95 | #define MUTEA_RIGHTB 0x01 | ||
96 | #define MUTEA_LEFTB 0x02 | ||
97 | #define MUTEA_SUMLRDIV2B 0x03 | ||
98 | #define RIGHTA_MUTEB 0x04 | ||
99 | #define RIGHTA_RIGHTB 0x05 | ||
100 | #define RIGHTA_LEFTB 0x06 | ||
101 | #define RIGHTA_SUMLRDIV2B 0x07 | ||
102 | #define LEFTA_MUTEB 0x08 | ||
103 | #define LEFTA_RIGHTB 0x09 /* Default */ | ||
104 | #define LEFTA_LEFTB 0x0A | ||
105 | #define LEFTA_SUMLRDIV2B 0x0B | ||
106 | #define SUMLRDIV2A_MUTEB 0x0C | ||
107 | #define SUMLRDIV2A_RIGHTB 0x0D | ||
108 | #define SUMLRDIV2A_LEFTB 0x0E | ||
109 | #define SUMLRDIV2_AB 0x0F | ||
110 | #define CHMIX_MASK 0x0F | ||
111 | |||
112 | /* CS4349_MUTE */ | ||
113 | #define AUTOMUTE (1 << 7) | ||
114 | #define MUTEC_AB (1 << 5) | ||
115 | #define MUTE_A (1 << 4) | ||
116 | #define MUTE_B (1 << 3) | ||
117 | #define MUTE_AB_MASK 0x18 | ||
118 | |||
119 | /* CS4349_RMPFLT (Ramp and Filter Control) */ | ||
120 | #define SCZ1 (1 << 7) | ||
121 | #define SCZ0 (1 << 6) | ||
122 | #define RMP_UP (1 << 5) | ||
123 | #define RMP_DN (1 << 4) | ||
124 | #define FILT_SEL (1 << 2) | ||
125 | #define IMMDT_CHNG 0x31 | ||
126 | #define ZEROCRSS 0x71 | ||
127 | #define SOFT_RMP 0xB1 | ||
128 | #define SFTRMP_ZEROCRSS 0xF1 | ||
129 | #define SR_ZC_MASK 0xC0 | ||
130 | |||
131 | /* CS4349_MISC */ | ||
132 | #define PWR_DWN (1 << 7) | ||
133 | #define FREEZE (1 << 5) | ||
134 | #define POPG_EN (1 << 4) | ||
135 | |||
136 | #endif /* __CS4349_H__ */ | ||
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 21810e5f3321..7dc52fe67c80 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -267,33 +267,29 @@ enum clk_src { | |||
267 | * | 267 | * |
268 | * Reserved area are considered as "mute". | 268 | * Reserved area are considered as "mute". |
269 | */ | 269 | */ |
270 | static const unsigned int hp_out_tlv[] = { | 270 | static const DECLARE_TLV_DB_RANGE(hp_out_tlv, |
271 | TLV_DB_RANGE_HEAD(2), | ||
272 | 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | 271 | 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), |
273 | /* -54 dB to +15 dB */ | 272 | /* -54 dB to +15 dB */ |
274 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0), | 273 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0) |
275 | }; | 274 | ); |
276 | 275 | ||
277 | static const unsigned int lineout_vol_tlv[] = { | 276 | static const DECLARE_TLV_DB_RANGE(lineout_vol_tlv, |
278 | TLV_DB_RANGE_HEAD(2), | ||
279 | 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | 277 | 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), |
280 | /* -54dB to 15dB */ | 278 | /* -54dB to 15dB */ |
281 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0) | 279 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0) |
282 | }; | 280 | ); |
283 | 281 | ||
284 | static const unsigned int mono_vol_tlv[] = { | 282 | static const DECLARE_TLV_DB_RANGE(mono_vol_tlv, |
285 | TLV_DB_RANGE_HEAD(2), | ||
286 | 0x0, 0x2, TLV_DB_SCALE_ITEM(-1800, 0, 1), | 283 | 0x0, 0x2, TLV_DB_SCALE_ITEM(-1800, 0, 1), |
287 | /* -18dB to 6dB */ | 284 | /* -18dB to 6dB */ |
288 | 0x3, 0x7, TLV_DB_SCALE_ITEM(-1800, 600, 0) | 285 | 0x3, 0x7, TLV_DB_SCALE_ITEM(-1800, 600, 0) |
289 | }; | 286 | ); |
290 | 287 | ||
291 | static const unsigned int aux1_vol_tlv[] = { | 288 | static const DECLARE_TLV_DB_RANGE(aux1_vol_tlv, |
292 | TLV_DB_RANGE_HEAD(2), | ||
293 | 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | 289 | 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), |
294 | /* -48dB to 21dB */ | 290 | /* -48dB to 21dB */ |
295 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-4800, 150, 0) | 291 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-4800, 150, 0) |
296 | }; | 292 | ); |
297 | 293 | ||
298 | static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0); | 294 | static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0); |
299 | static const DECLARE_TLV_DB_SCALE(adc_eq_master_gain_tlv, -1800, 600, 1); | 295 | static const DECLARE_TLV_DB_SCALE(adc_eq_master_gain_tlv, -1800, 600, 1); |
@@ -680,7 +676,7 @@ struct da7210_priv { | |||
680 | int master; | 676 | int master; |
681 | }; | 677 | }; |
682 | 678 | ||
683 | static struct reg_default da7210_reg_defaults[] = { | 679 | static const struct reg_default da7210_reg_defaults[] = { |
684 | { 0x00, 0x00 }, | 680 | { 0x00, 0x00 }, |
685 | { 0x01, 0x11 }, | 681 | { 0x01, 0x11 }, |
686 | { 0x03, 0x00 }, | 682 | { 0x03, 0x00 }, |
@@ -1182,7 +1178,7 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = { | |||
1182 | 1178 | ||
1183 | #if IS_ENABLED(CONFIG_I2C) | 1179 | #if IS_ENABLED(CONFIG_I2C) |
1184 | 1180 | ||
1185 | static struct reg_default da7210_regmap_i2c_patch[] = { | 1181 | static const struct reg_sequence da7210_regmap_i2c_patch[] = { |
1186 | 1182 | ||
1187 | /* System controller master disable */ | 1183 | /* System controller master disable */ |
1188 | { DA7210_STARTUP1, 0x00 }, | 1184 | { DA7210_STARTUP1, 0x00 }, |
@@ -1259,7 +1255,6 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id); | |||
1259 | static struct i2c_driver da7210_i2c_driver = { | 1255 | static struct i2c_driver da7210_i2c_driver = { |
1260 | .driver = { | 1256 | .driver = { |
1261 | .name = "da7210", | 1257 | .name = "da7210", |
1262 | .owner = THIS_MODULE, | ||
1263 | }, | 1258 | }, |
1264 | .probe = da7210_i2c_probe, | 1259 | .probe = da7210_i2c_probe, |
1265 | .remove = da7210_i2c_remove, | 1260 | .remove = da7210_i2c_remove, |
@@ -1269,7 +1264,7 @@ static struct i2c_driver da7210_i2c_driver = { | |||
1269 | 1264 | ||
1270 | #if defined(CONFIG_SPI_MASTER) | 1265 | #if defined(CONFIG_SPI_MASTER) |
1271 | 1266 | ||
1272 | static struct reg_default da7210_regmap_spi_patch[] = { | 1267 | static const struct reg_sequence da7210_regmap_spi_patch[] = { |
1273 | /* Dummy read to give two pulses over nCS for SPI */ | 1268 | /* Dummy read to give two pulses over nCS for SPI */ |
1274 | { DA7210_AUX2, 0x00 }, | 1269 | { DA7210_AUX2, 0x00 }, |
1275 | { DA7210_AUX2, 0x00 }, | 1270 | { DA7210_AUX2, 0x00 }, |
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 238e48a3a4fe..a9c86efb3187 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c | |||
@@ -28,27 +28,24 @@ | |||
28 | 28 | ||
29 | 29 | ||
30 | /* Gain and Volume */ | 30 | /* Gain and Volume */ |
31 | static const unsigned int aux_vol_tlv[] = { | 31 | static const DECLARE_TLV_DB_RANGE(aux_vol_tlv, |
32 | TLV_DB_RANGE_HEAD(2), | ||
33 | /* -54dB */ | 32 | /* -54dB */ |
34 | 0x0, 0x11, TLV_DB_SCALE_ITEM(-5400, 0, 0), | 33 | 0x0, 0x11, TLV_DB_SCALE_ITEM(-5400, 0, 0), |
35 | /* -52.5dB to 15dB */ | 34 | /* -52.5dB to 15dB */ |
36 | 0x12, 0x3f, TLV_DB_SCALE_ITEM(-5250, 150, 0) | 35 | 0x12, 0x3f, TLV_DB_SCALE_ITEM(-5250, 150, 0) |
37 | }; | 36 | ); |
38 | 37 | ||
39 | static const unsigned int digital_gain_tlv[] = { | 38 | static const DECLARE_TLV_DB_RANGE(digital_gain_tlv, |
40 | TLV_DB_RANGE_HEAD(2), | ||
41 | 0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | 39 | 0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), |
42 | /* -78dB to 12dB */ | 40 | /* -78dB to 12dB */ |
43 | 0x08, 0x7f, TLV_DB_SCALE_ITEM(-7800, 75, 0) | 41 | 0x08, 0x7f, TLV_DB_SCALE_ITEM(-7800, 75, 0) |
44 | }; | 42 | ); |
45 | 43 | ||
46 | static const unsigned int alc_analog_gain_tlv[] = { | 44 | static const DECLARE_TLV_DB_RANGE(alc_analog_gain_tlv, |
47 | TLV_DB_RANGE_HEAD(2), | ||
48 | 0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | 45 | 0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), |
49 | /* 0dB to 36dB */ | 46 | /* 0dB to 36dB */ |
50 | 0x01, 0x07, TLV_DB_SCALE_ITEM(0, 600, 0) | 47 | 0x01, 0x07, TLV_DB_SCALE_ITEM(0, 600, 0) |
51 | }; | 48 | ); |
52 | 49 | ||
53 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0); | 50 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0); |
54 | static const DECLARE_TLV_DB_SCALE(mixin_gain_tlv, -450, 150, 0); | 51 | static const DECLARE_TLV_DB_SCALE(mixin_gain_tlv, -450, 150, 0); |
@@ -954,7 +951,7 @@ static const struct snd_soc_dapm_route da7213_audio_map[] = { | |||
954 | {"LINE", NULL, "Lineout PGA"}, | 951 | {"LINE", NULL, "Lineout PGA"}, |
955 | }; | 952 | }; |
956 | 953 | ||
957 | static struct reg_default da7213_reg_defaults[] = { | 954 | static const struct reg_default da7213_reg_defaults[] = { |
958 | { DA7213_DIG_ROUTING_DAI, 0x10 }, | 955 | { DA7213_DIG_ROUTING_DAI, 0x10 }, |
959 | { DA7213_SR, 0x0A }, | 956 | { DA7213_SR, 0x0A }, |
960 | { DA7213_REFERENCES, 0x80 }, | 957 | { DA7213_REFERENCES, 0x80 }, |
@@ -1585,7 +1582,6 @@ MODULE_DEVICE_TABLE(i2c, da7213_i2c_id); | |||
1585 | static struct i2c_driver da7213_i2c_driver = { | 1582 | static struct i2c_driver da7213_i2c_driver = { |
1586 | .driver = { | 1583 | .driver = { |
1587 | .name = "da7213", | 1584 | .name = "da7213", |
1588 | .owner = THIS_MODULE, | ||
1589 | }, | 1585 | }, |
1590 | .probe = da7213_i2c_probe, | 1586 | .probe = da7213_i2c_probe, |
1591 | .remove = da7213_remove, | 1587 | .remove = da7213_remove, |
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 207523686bd5..1d5a89c5164b 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c | |||
@@ -43,7 +43,7 @@ struct da732x_priv { | |||
43 | /* | 43 | /* |
44 | * da732x register cache - default settings | 44 | * da732x register cache - default settings |
45 | */ | 45 | */ |
46 | static struct reg_default da732x_reg_cache[] = { | 46 | static const struct reg_default da732x_reg_cache[] = { |
47 | { DA732X_REG_REF1 , 0x02 }, | 47 | { DA732X_REG_REF1 , 0x02 }, |
48 | { DA732X_REG_BIAS_EN , 0x80 }, | 48 | { DA732X_REG_BIAS_EN , 0x80 }, |
49 | { DA732X_REG_BIAS1 , 0x00 }, | 49 | { DA732X_REG_BIAS1 , 0x00 }, |
@@ -1196,13 +1196,7 @@ static int da732x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
1196 | #define DA732X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 1196 | #define DA732X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
1197 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 1197 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
1198 | 1198 | ||
1199 | static struct snd_soc_dai_ops da732x_dai1_ops = { | 1199 | static const struct snd_soc_dai_ops da732x_dai_ops = { |
1200 | .hw_params = da732x_hw_params, | ||
1201 | .set_fmt = da732x_set_dai_fmt, | ||
1202 | .set_sysclk = da732x_set_dai_sysclk, | ||
1203 | }; | ||
1204 | |||
1205 | static struct snd_soc_dai_ops da732x_dai2_ops = { | ||
1206 | .hw_params = da732x_hw_params, | 1200 | .hw_params = da732x_hw_params, |
1207 | .set_fmt = da732x_set_dai_fmt, | 1201 | .set_fmt = da732x_set_dai_fmt, |
1208 | .set_sysclk = da732x_set_dai_sysclk, | 1202 | .set_sysclk = da732x_set_dai_sysclk, |
@@ -1227,7 +1221,7 @@ static struct snd_soc_dai_driver da732x_dai[] = { | |||
1227 | .rates = DA732X_RATES, | 1221 | .rates = DA732X_RATES, |
1228 | .formats = DA732X_FORMATS, | 1222 | .formats = DA732X_FORMATS, |
1229 | }, | 1223 | }, |
1230 | .ops = &da732x_dai1_ops, | 1224 | .ops = &da732x_dai_ops, |
1231 | }, | 1225 | }, |
1232 | { | 1226 | { |
1233 | .name = "DA732X_AIFB", | 1227 | .name = "DA732X_AIFB", |
@@ -1247,7 +1241,7 @@ static struct snd_soc_dai_driver da732x_dai[] = { | |||
1247 | .rates = DA732X_RATES, | 1241 | .rates = DA732X_RATES, |
1248 | .formats = DA732X_FORMATS, | 1242 | .formats = DA732X_FORMATS, |
1249 | }, | 1243 | }, |
1250 | .ops = &da732x_dai2_ops, | 1244 | .ops = &da732x_dai_ops, |
1251 | }, | 1245 | }, |
1252 | }; | 1246 | }; |
1253 | 1247 | ||
@@ -1572,7 +1566,6 @@ MODULE_DEVICE_TABLE(i2c, da732x_i2c_id); | |||
1572 | static struct i2c_driver da732x_i2c_driver = { | 1566 | static struct i2c_driver da732x_i2c_driver = { |
1573 | .driver = { | 1567 | .driver = { |
1574 | .name = "da7320", | 1568 | .name = "da7320", |
1575 | .owner = THIS_MODULE, | ||
1576 | }, | 1569 | }, |
1577 | .probe = da732x_i2c_probe, | 1570 | .probe = da732x_i2c_probe, |
1578 | .remove = da732x_i2c_remove, | 1571 | .remove = da732x_i2c_remove, |
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 66bb446473b8..0b2ede8db978 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c | |||
@@ -289,26 +289,23 @@ enum clk_src { | |||
289 | 289 | ||
290 | /* Gain and Volume */ | 290 | /* Gain and Volume */ |
291 | 291 | ||
292 | static const unsigned int aux_vol_tlv[] = { | 292 | static const DECLARE_TLV_DB_RANGE(aux_vol_tlv, |
293 | TLV_DB_RANGE_HEAD(2), | ||
294 | 0x0, 0x10, TLV_DB_SCALE_ITEM(-5400, 0, 0), | 293 | 0x0, 0x10, TLV_DB_SCALE_ITEM(-5400, 0, 0), |
295 | /* -54dB to 15dB */ | 294 | /* -54dB to 15dB */ |
296 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0) | 295 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0) |
297 | }; | 296 | ); |
298 | 297 | ||
299 | static const unsigned int digital_gain_tlv[] = { | 298 | static const DECLARE_TLV_DB_RANGE(digital_gain_tlv, |
300 | TLV_DB_RANGE_HEAD(2), | ||
301 | 0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | 299 | 0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), |
302 | /* -78dB to 12dB */ | 300 | /* -78dB to 12dB */ |
303 | 0x08, 0x7f, TLV_DB_SCALE_ITEM(-7800, 75, 0) | 301 | 0x08, 0x7f, TLV_DB_SCALE_ITEM(-7800, 75, 0) |
304 | }; | 302 | ); |
305 | 303 | ||
306 | static const unsigned int alc_analog_gain_tlv[] = { | 304 | static const DECLARE_TLV_DB_RANGE(alc_analog_gain_tlv, |
307 | TLV_DB_RANGE_HEAD(2), | ||
308 | 0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | 305 | 0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), |
309 | /* 0dB to 36dB */ | 306 | /* 0dB to 36dB */ |
310 | 0x01, 0x07, TLV_DB_SCALE_ITEM(0, 600, 0) | 307 | 0x01, 0x07, TLV_DB_SCALE_ITEM(0, 600, 0) |
311 | }; | 308 | ); |
312 | 309 | ||
313 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0); | 310 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0); |
314 | static const DECLARE_TLV_DB_SCALE(mixin_gain_tlv, -450, 150, 0); | 311 | static const DECLARE_TLV_DB_SCALE(mixin_gain_tlv, -450, 150, 0); |
@@ -948,7 +945,7 @@ struct da9055_priv { | |||
948 | struct da9055_platform_data *pdata; | 945 | struct da9055_platform_data *pdata; |
949 | }; | 946 | }; |
950 | 947 | ||
951 | static struct reg_default da9055_reg_defaults[] = { | 948 | static const struct reg_default da9055_reg_defaults[] = { |
952 | { 0x21, 0x10 }, | 949 | { 0x21, 0x10 }, |
953 | { 0x22, 0x0A }, | 950 | { 0x22, 0x0A }, |
954 | { 0x23, 0x00 }, | 951 | { 0x23, 0x00 }, |
@@ -1533,12 +1530,12 @@ static const struct of_device_id da9055_of_match[] = { | |||
1533 | { .compatible = "dlg,da9055-codec", }, | 1530 | { .compatible = "dlg,da9055-codec", }, |
1534 | { } | 1531 | { } |
1535 | }; | 1532 | }; |
1533 | MODULE_DEVICE_TABLE(of, da9055_of_match); | ||
1536 | 1534 | ||
1537 | /* I2C codec control layer */ | 1535 | /* I2C codec control layer */ |
1538 | static struct i2c_driver da9055_i2c_driver = { | 1536 | static struct i2c_driver da9055_i2c_driver = { |
1539 | .driver = { | 1537 | .driver = { |
1540 | .name = "da9055-codec", | 1538 | .name = "da9055-codec", |
1541 | .owner = THIS_MODULE, | ||
1542 | .of_match_table = of_match_ptr(da9055_of_match), | 1539 | .of_match_table = of_match_ptr(da9055_of_match), |
1543 | }, | 1540 | }, |
1544 | .probe = da9055_i2c_probe, | 1541 | .probe = da9055_i2c_probe, |
diff --git a/sound/soc/codecs/gtm601.c b/sound/soc/codecs/gtm601.c new file mode 100644 index 000000000000..0b80052996d3 --- /dev/null +++ b/sound/soc/codecs/gtm601.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * This is a simple driver for the GTM601 Voice PCM interface | ||
3 | * | ||
4 | * Copyright (C) 2015 Goldelico GmbH | ||
5 | * | ||
6 | * Author: Marek Belisko <marek@goldelico.com> | ||
7 | * | ||
8 | * Based on wm8727.c driver | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/ac97_codec.h> | ||
23 | #include <sound/initval.h> | ||
24 | #include <sound/soc.h> | ||
25 | |||
26 | static const struct snd_soc_dapm_widget gtm601_dapm_widgets[] = { | ||
27 | SND_SOC_DAPM_OUTPUT("AOUT"), | ||
28 | SND_SOC_DAPM_INPUT("AIN"), | ||
29 | }; | ||
30 | |||
31 | static const struct snd_soc_dapm_route gtm601_dapm_routes[] = { | ||
32 | { "AOUT", NULL, "Playback" }, | ||
33 | { "Capture", NULL, "AIN" }, | ||
34 | }; | ||
35 | |||
36 | static struct snd_soc_dai_driver gtm601_dai = { | ||
37 | .name = "gtm601", | ||
38 | .playback = { | ||
39 | .stream_name = "Playback", | ||
40 | .channels_min = 1, | ||
41 | .channels_max = 1, | ||
42 | .rates = SNDRV_PCM_RATE_8000, | ||
43 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
44 | }, | ||
45 | .capture = { | ||
46 | .stream_name = "Capture", | ||
47 | .channels_min = 1, | ||
48 | .channels_max = 1, | ||
49 | .rates = SNDRV_PCM_RATE_8000, | ||
50 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
51 | }, | ||
52 | }; | ||
53 | |||
54 | static const struct snd_soc_codec_driver soc_codec_dev_gtm601 = { | ||
55 | .dapm_widgets = gtm601_dapm_widgets, | ||
56 | .num_dapm_widgets = ARRAY_SIZE(gtm601_dapm_widgets), | ||
57 | .dapm_routes = gtm601_dapm_routes, | ||
58 | .num_dapm_routes = ARRAY_SIZE(gtm601_dapm_routes), | ||
59 | }; | ||
60 | |||
61 | static int gtm601_platform_probe(struct platform_device *pdev) | ||
62 | { | ||
63 | return snd_soc_register_codec(&pdev->dev, | ||
64 | &soc_codec_dev_gtm601, >m601_dai, 1); | ||
65 | } | ||
66 | |||
67 | static int gtm601_platform_remove(struct platform_device *pdev) | ||
68 | { | ||
69 | snd_soc_unregister_codec(&pdev->dev); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | #if defined(CONFIG_OF) | ||
74 | static const struct of_device_id gtm601_codec_of_match[] = { | ||
75 | { .compatible = "option,gtm601", }, | ||
76 | {}, | ||
77 | }; | ||
78 | MODULE_DEVICE_TABLE(of, gtm601_codec_of_match); | ||
79 | #endif | ||
80 | |||
81 | static struct platform_driver gtm601_codec_driver = { | ||
82 | .driver = { | ||
83 | .name = "gtm601", | ||
84 | .of_match_table = of_match_ptr(gtm601_codec_of_match), | ||
85 | }, | ||
86 | .probe = gtm601_platform_probe, | ||
87 | .remove = gtm601_platform_remove, | ||
88 | }; | ||
89 | |||
90 | module_platform_driver(gtm601_codec_driver); | ||
91 | |||
92 | MODULE_DESCRIPTION("ASoC gtm601 driver"); | ||
93 | MODULE_AUTHOR("Marek Belisko <marek@goldelico.com>"); | ||
94 | MODULE_LICENSE("GPL"); | ||
95 | MODULE_ALIAS("platform:gtm601"); | ||
diff --git a/sound/soc/codecs/ics43432.c b/sound/soc/codecs/ics43432.c new file mode 100644 index 000000000000..dd850b93938d --- /dev/null +++ b/sound/soc/codecs/ics43432.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * I2S MEMS microphone driver for InvenSense ICS-43432 | ||
3 | * | ||
4 | * - Non configurable. | ||
5 | * - I2S interface, 64 BCLs per frame, 32 bits per channel, 24 bit data | ||
6 | * | ||
7 | * Copyright (c) 2015 Axis Communications AB | ||
8 | * | ||
9 | * Licensed under GPL v2. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/initval.h> | ||
20 | #include <sound/tlv.h> | ||
21 | |||
22 | #define ICS43432_RATE_MIN 7190 /* Hz, from data sheet */ | ||
23 | #define ICS43432_RATE_MAX 52800 /* Hz, from data sheet */ | ||
24 | |||
25 | #define ICS43432_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32) | ||
26 | |||
27 | static struct snd_soc_dai_driver ics43432_dai = { | ||
28 | .name = "ics43432-hifi", | ||
29 | .capture = { | ||
30 | .stream_name = "Capture", | ||
31 | .channels_min = 1, | ||
32 | .channels_max = 2, | ||
33 | .rate_min = ICS43432_RATE_MIN, | ||
34 | .rate_max = ICS43432_RATE_MAX, | ||
35 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
36 | .formats = ICS43432_FORMATS, | ||
37 | }, | ||
38 | }; | ||
39 | |||
40 | static struct snd_soc_codec_driver ics43432_codec_driver = { | ||
41 | }; | ||
42 | |||
43 | static int ics43432_probe(struct platform_device *pdev) | ||
44 | { | ||
45 | return snd_soc_register_codec(&pdev->dev, &ics43432_codec_driver, | ||
46 | &ics43432_dai, 1); | ||
47 | } | ||
48 | |||
49 | static int ics43432_remove(struct platform_device *pdev) | ||
50 | { | ||
51 | snd_soc_unregister_codec(&pdev->dev); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | #ifdef CONFIG_OF | ||
56 | static const struct of_device_id ics43432_ids[] = { | ||
57 | { .compatible = "invensense,ics43432", }, | ||
58 | { } | ||
59 | }; | ||
60 | MODULE_DEVICE_TABLE(of, ics43432_ids); | ||
61 | #endif | ||
62 | |||
63 | static struct platform_driver ics43432_driver = { | ||
64 | .driver = { | ||
65 | .name = "ics43432", | ||
66 | .of_match_table = of_match_ptr(ics43432_ids), | ||
67 | }, | ||
68 | .probe = ics43432_probe, | ||
69 | .remove = ics43432_remove, | ||
70 | }; | ||
71 | |||
72 | module_platform_driver(ics43432_driver); | ||
73 | |||
74 | MODULE_DESCRIPTION("ASoC ICS43432 driver"); | ||
75 | MODULE_AUTHOR("Ricard Wanderlof <ricardw@axis.com>"); | ||
76 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index ebd90283c960..be448373d39a 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c | |||
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | 34 | ||
35 | /* Register default values for ISABELLE driver. */ | 35 | /* Register default values for ISABELLE driver. */ |
36 | static struct reg_default isabelle_reg_defs[] = { | 36 | static const struct reg_default isabelle_reg_defs[] = { |
37 | { 0, 0x00 }, | 37 | { 0, 0x00 }, |
38 | { 1, 0x00 }, | 38 | { 1, 0x00 }, |
39 | { 2, 0x00 }, | 39 | { 2, 0x00 }, |
@@ -1016,25 +1016,25 @@ static int isabelle_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | |||
1016 | #define ISABELLE_FORMATS (SNDRV_PCM_FMTBIT_S20_3LE |\ | 1016 | #define ISABELLE_FORMATS (SNDRV_PCM_FMTBIT_S20_3LE |\ |
1017 | SNDRV_PCM_FMTBIT_S32_LE) | 1017 | SNDRV_PCM_FMTBIT_S32_LE) |
1018 | 1018 | ||
1019 | static struct snd_soc_dai_ops isabelle_hs_dai_ops = { | 1019 | static const struct snd_soc_dai_ops isabelle_hs_dai_ops = { |
1020 | .hw_params = isabelle_hw_params, | 1020 | .hw_params = isabelle_hw_params, |
1021 | .set_fmt = isabelle_set_dai_fmt, | 1021 | .set_fmt = isabelle_set_dai_fmt, |
1022 | .digital_mute = isabelle_hs_mute, | 1022 | .digital_mute = isabelle_hs_mute, |
1023 | }; | 1023 | }; |
1024 | 1024 | ||
1025 | static struct snd_soc_dai_ops isabelle_hf_dai_ops = { | 1025 | static const struct snd_soc_dai_ops isabelle_hf_dai_ops = { |
1026 | .hw_params = isabelle_hw_params, | 1026 | .hw_params = isabelle_hw_params, |
1027 | .set_fmt = isabelle_set_dai_fmt, | 1027 | .set_fmt = isabelle_set_dai_fmt, |
1028 | .digital_mute = isabelle_hf_mute, | 1028 | .digital_mute = isabelle_hf_mute, |
1029 | }; | 1029 | }; |
1030 | 1030 | ||
1031 | static struct snd_soc_dai_ops isabelle_line_dai_ops = { | 1031 | static const struct snd_soc_dai_ops isabelle_line_dai_ops = { |
1032 | .hw_params = isabelle_hw_params, | 1032 | .hw_params = isabelle_hw_params, |
1033 | .set_fmt = isabelle_set_dai_fmt, | 1033 | .set_fmt = isabelle_set_dai_fmt, |
1034 | .digital_mute = isabelle_line_mute, | 1034 | .digital_mute = isabelle_line_mute, |
1035 | }; | 1035 | }; |
1036 | 1036 | ||
1037 | static struct snd_soc_dai_ops isabelle_ul_dai_ops = { | 1037 | static const struct snd_soc_dai_ops isabelle_ul_dai_ops = { |
1038 | .hw_params = isabelle_hw_params, | 1038 | .hw_params = isabelle_hw_params, |
1039 | .set_fmt = isabelle_set_dai_fmt, | 1039 | .set_fmt = isabelle_set_dai_fmt, |
1040 | }; | 1040 | }; |
@@ -1149,7 +1149,6 @@ MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id); | |||
1149 | static struct i2c_driver isabelle_i2c_driver = { | 1149 | static struct i2c_driver isabelle_i2c_driver = { |
1150 | .driver = { | 1150 | .driver = { |
1151 | .name = "isabelle", | 1151 | .name = "isabelle", |
1152 | .owner = THIS_MODULE, | ||
1153 | }, | 1152 | }, |
1154 | .probe = isabelle_i2c_probe, | 1153 | .probe = isabelle_i2c_probe, |
1155 | .remove = isabelle_i2c_remove, | 1154 | .remove = isabelle_i2c_remove, |
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 9363fdbca9cd..1f5ab99956ed 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c | |||
@@ -78,11 +78,10 @@ struct jz4740_codec { | |||
78 | struct regmap *regmap; | 78 | struct regmap *regmap; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static const unsigned int jz4740_mic_tlv[] = { | 81 | static const DECLARE_TLV_DB_RANGE(jz4740_mic_tlv, |
82 | TLV_DB_RANGE_HEAD(2), | ||
83 | 0, 2, TLV_DB_SCALE_ITEM(0, 600, 0), | 82 | 0, 2, TLV_DB_SCALE_ITEM(0, 600, 0), |
84 | 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0), | 83 | 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0) |
85 | }; | 84 | ); |
86 | 85 | ||
87 | static const DECLARE_TLV_DB_SCALE(jz4740_out_tlv, 0, 200, 0); | 86 | static const DECLARE_TLV_DB_SCALE(jz4740_out_tlv, 0, 200, 0); |
88 | static const DECLARE_TLV_DB_SCALE(jz4740_in_tlv, -3450, 150, 0); | 87 | static const DECLARE_TLV_DB_SCALE(jz4740_in_tlv, -3450, 150, 0); |
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 99ffc49aa779..558de1053f73 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c | |||
@@ -142,7 +142,6 @@ MODULE_DEVICE_TABLE(i2c, lm4857_i2c_id); | |||
142 | static struct i2c_driver lm4857_i2c_driver = { | 142 | static struct i2c_driver lm4857_i2c_driver = { |
143 | .driver = { | 143 | .driver = { |
144 | .name = "lm4857", | 144 | .name = "lm4857", |
145 | .owner = THIS_MODULE, | ||
146 | }, | 145 | }, |
147 | .probe = lm4857_i2c_probe, | 146 | .probe = lm4857_i2c_probe, |
148 | .id_table = lm4857_i2c_id, | 147 | .id_table = lm4857_i2c_id, |
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 6600aa0a33dc..9af5640e3446 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <asm/div64.h> | 30 | #include <asm/div64.h> |
31 | #include "lm49453.h" | 31 | #include "lm49453.h" |
32 | 32 | ||
33 | static struct reg_default lm49453_reg_defs[] = { | 33 | static const struct reg_default lm49453_reg_defs[] = { |
34 | { 0, 0x00 }, | 34 | { 0, 0x00 }, |
35 | { 1, 0x00 }, | 35 | { 1, 0x00 }, |
36 | { 2, 0x00 }, | 36 | { 2, 0x00 }, |
@@ -188,7 +188,6 @@ static struct reg_default lm49453_reg_defs[] = { | |||
188 | /* codec private data */ | 188 | /* codec private data */ |
189 | struct lm49453_priv { | 189 | struct lm49453_priv { |
190 | struct regmap *regmap; | 190 | struct regmap *regmap; |
191 | int fs_rate; | ||
192 | }; | 191 | }; |
193 | 192 | ||
194 | /* capture path controls */ | 193 | /* capture path controls */ |
@@ -1112,13 +1111,10 @@ static int lm49453_hw_params(struct snd_pcm_substream *substream, | |||
1112 | struct snd_soc_dai *dai) | 1111 | struct snd_soc_dai *dai) |
1113 | { | 1112 | { |
1114 | struct snd_soc_codec *codec = dai->codec; | 1113 | struct snd_soc_codec *codec = dai->codec; |
1115 | struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec); | ||
1116 | u16 clk_div = 0; | 1114 | u16 clk_div = 0; |
1117 | 1115 | ||
1118 | lm49453->fs_rate = params_rate(params); | ||
1119 | |||
1120 | /* Setting DAC clock dividers based on substream sample rate. */ | 1116 | /* Setting DAC clock dividers based on substream sample rate. */ |
1121 | switch (lm49453->fs_rate) { | 1117 | switch (params_rate(params)) { |
1122 | case 8000: | 1118 | case 8000: |
1123 | case 16000: | 1119 | case 16000: |
1124 | case 32000: | 1120 | case 32000: |
@@ -1291,35 +1287,35 @@ static int lm49453_set_bias_level(struct snd_soc_codec *codec, | |||
1291 | #define LM49453_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 1287 | #define LM49453_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
1292 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 1288 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
1293 | 1289 | ||
1294 | static struct snd_soc_dai_ops lm49453_headset_dai_ops = { | 1290 | static const struct snd_soc_dai_ops lm49453_headset_dai_ops = { |
1295 | .hw_params = lm49453_hw_params, | 1291 | .hw_params = lm49453_hw_params, |
1296 | .set_sysclk = lm49453_set_dai_sysclk, | 1292 | .set_sysclk = lm49453_set_dai_sysclk, |
1297 | .set_fmt = lm49453_set_dai_fmt, | 1293 | .set_fmt = lm49453_set_dai_fmt, |
1298 | .digital_mute = lm49453_hp_mute, | 1294 | .digital_mute = lm49453_hp_mute, |
1299 | }; | 1295 | }; |
1300 | 1296 | ||
1301 | static struct snd_soc_dai_ops lm49453_speaker_dai_ops = { | 1297 | static const struct snd_soc_dai_ops lm49453_speaker_dai_ops = { |
1302 | .hw_params = lm49453_hw_params, | 1298 | .hw_params = lm49453_hw_params, |
1303 | .set_sysclk = lm49453_set_dai_sysclk, | 1299 | .set_sysclk = lm49453_set_dai_sysclk, |
1304 | .set_fmt = lm49453_set_dai_fmt, | 1300 | .set_fmt = lm49453_set_dai_fmt, |
1305 | .digital_mute = lm49453_ls_mute, | 1301 | .digital_mute = lm49453_ls_mute, |
1306 | }; | 1302 | }; |
1307 | 1303 | ||
1308 | static struct snd_soc_dai_ops lm49453_haptic_dai_ops = { | 1304 | static const struct snd_soc_dai_ops lm49453_haptic_dai_ops = { |
1309 | .hw_params = lm49453_hw_params, | 1305 | .hw_params = lm49453_hw_params, |
1310 | .set_sysclk = lm49453_set_dai_sysclk, | 1306 | .set_sysclk = lm49453_set_dai_sysclk, |
1311 | .set_fmt = lm49453_set_dai_fmt, | 1307 | .set_fmt = lm49453_set_dai_fmt, |
1312 | .digital_mute = lm49453_ha_mute, | 1308 | .digital_mute = lm49453_ha_mute, |
1313 | }; | 1309 | }; |
1314 | 1310 | ||
1315 | static struct snd_soc_dai_ops lm49453_ep_dai_ops = { | 1311 | static const struct snd_soc_dai_ops lm49453_ep_dai_ops = { |
1316 | .hw_params = lm49453_hw_params, | 1312 | .hw_params = lm49453_hw_params, |
1317 | .set_sysclk = lm49453_set_dai_sysclk, | 1313 | .set_sysclk = lm49453_set_dai_sysclk, |
1318 | .set_fmt = lm49453_set_dai_fmt, | 1314 | .set_fmt = lm49453_set_dai_fmt, |
1319 | .digital_mute = lm49453_ep_mute, | 1315 | .digital_mute = lm49453_ep_mute, |
1320 | }; | 1316 | }; |
1321 | 1317 | ||
1322 | static struct snd_soc_dai_ops lm49453_lineout_dai_ops = { | 1318 | static const struct snd_soc_dai_ops lm49453_lineout_dai_ops = { |
1323 | .hw_params = lm49453_hw_params, | 1319 | .hw_params = lm49453_hw_params, |
1324 | .set_sysclk = lm49453_set_dai_sysclk, | 1320 | .set_sysclk = lm49453_set_dai_sysclk, |
1325 | .set_fmt = lm49453_set_dai_fmt, | 1321 | .set_fmt = lm49453_set_dai_fmt, |
@@ -1460,7 +1456,6 @@ MODULE_DEVICE_TABLE(i2c, lm49453_i2c_id); | |||
1460 | static struct i2c_driver lm49453_i2c_driver = { | 1456 | static struct i2c_driver lm49453_i2c_driver = { |
1461 | .driver = { | 1457 | .driver = { |
1462 | .name = "lm49453", | 1458 | .name = "lm49453", |
1463 | .owner = THIS_MODULE, | ||
1464 | }, | 1459 | }, |
1465 | .probe = lm49453_i2c_probe, | 1460 | .probe = lm49453_i2c_probe, |
1466 | .remove = lm49453_i2c_remove, | 1461 | .remove = lm49453_i2c_remove, |
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index e1c196a41930..5b82e26cd5d1 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c | |||
@@ -35,7 +35,7 @@ struct max9768 { | |||
35 | u32 flags; | 35 | u32 flags; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static struct reg_default max9768_default_regs[] = { | 38 | static const struct reg_default max9768_default_regs[] = { |
39 | { 0, 0 }, | 39 | { 0, 0 }, |
40 | { 3, MAX9768_CTRL_FILTERLESS}, | 40 | { 3, MAX9768_CTRL_FILTERLESS}, |
41 | }; | 41 | }; |
@@ -43,8 +43,8 @@ static struct reg_default max9768_default_regs[] = { | |||
43 | static int max9768_get_gpio(struct snd_kcontrol *kcontrol, | 43 | static int max9768_get_gpio(struct snd_kcontrol *kcontrol, |
44 | struct snd_ctl_elem_value *ucontrol) | 44 | struct snd_ctl_elem_value *ucontrol) |
45 | { | 45 | { |
46 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 46 | struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); |
47 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); | 47 | struct max9768 *max9768 = snd_soc_component_get_drvdata(c); |
48 | int val = gpio_get_value_cansleep(max9768->mute_gpio); | 48 | int val = gpio_get_value_cansleep(max9768->mute_gpio); |
49 | 49 | ||
50 | ucontrol->value.integer.value[0] = !val; | 50 | ucontrol->value.integer.value[0] = !val; |
@@ -55,16 +55,15 @@ static int max9768_get_gpio(struct snd_kcontrol *kcontrol, | |||
55 | static int max9768_set_gpio(struct snd_kcontrol *kcontrol, | 55 | static int max9768_set_gpio(struct snd_kcontrol *kcontrol, |
56 | struct snd_ctl_elem_value *ucontrol) | 56 | struct snd_ctl_elem_value *ucontrol) |
57 | { | 57 | { |
58 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 58 | struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); |
59 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); | 59 | struct max9768 *max9768 = snd_soc_component_get_drvdata(c); |
60 | 60 | ||
61 | gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]); | 61 | gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]); |
62 | 62 | ||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | static const unsigned int volume_tlv[] = { | 66 | static const DECLARE_TLV_DB_RANGE(volume_tlv, |
67 | TLV_DB_RANGE_HEAD(43), | ||
68 | 0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0), | 67 | 0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0), |
69 | 1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0), | 68 | 1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0), |
70 | 2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0), | 69 | 2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0), |
@@ -107,8 +106,8 @@ static const unsigned int volume_tlv[] = { | |||
107 | 51, 57, TLV_DB_SCALE_ITEM(290, 50, 0), | 106 | 51, 57, TLV_DB_SCALE_ITEM(290, 50, 0), |
108 | 58, 58, TLV_DB_SCALE_ITEM(650, 0, 0), | 107 | 58, 58, TLV_DB_SCALE_ITEM(650, 0, 0), |
109 | 59, 62, TLV_DB_SCALE_ITEM(700, 60, 0), | 108 | 59, 62, TLV_DB_SCALE_ITEM(700, 60, 0), |
110 | 63, 63, TLV_DB_SCALE_ITEM(950, 0, 0), | 109 | 63, 63, TLV_DB_SCALE_ITEM(950, 0, 0) |
111 | }; | 110 | ); |
112 | 111 | ||
113 | static const struct snd_kcontrol_new max9768_volume[] = { | 112 | static const struct snd_kcontrol_new max9768_volume[] = { |
114 | SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv), | 113 | SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv), |
@@ -130,19 +129,20 @@ static const struct snd_soc_dapm_route max9768_dapm_routes[] = { | |||
130 | { "OUT-", NULL, "IN" }, | 129 | { "OUT-", NULL, "IN" }, |
131 | }; | 130 | }; |
132 | 131 | ||
133 | static int max9768_probe(struct snd_soc_codec *codec) | 132 | static int max9768_probe(struct snd_soc_component *component) |
134 | { | 133 | { |
135 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); | 134 | struct max9768 *max9768 = snd_soc_component_get_drvdata(component); |
136 | int ret; | 135 | int ret; |
137 | 136 | ||
138 | if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) { | 137 | if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) { |
139 | ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM); | 138 | ret = regmap_write(max9768->regmap, MAX9768_CTRL, |
139 | MAX9768_CTRL_PWM); | ||
140 | if (ret) | 140 | if (ret) |
141 | return ret; | 141 | return ret; |
142 | } | 142 | } |
143 | 143 | ||
144 | if (gpio_is_valid(max9768->mute_gpio)) { | 144 | if (gpio_is_valid(max9768->mute_gpio)) { |
145 | ret = snd_soc_add_codec_controls(codec, max9768_mute, | 145 | ret = snd_soc_add_component_controls(component, max9768_mute, |
146 | ARRAY_SIZE(max9768_mute)); | 146 | ARRAY_SIZE(max9768_mute)); |
147 | if (ret) | 147 | if (ret) |
148 | return ret; | 148 | return ret; |
@@ -151,7 +151,7 @@ static int max9768_probe(struct snd_soc_codec *codec) | |||
151 | return 0; | 151 | return 0; |
152 | } | 152 | } |
153 | 153 | ||
154 | static struct snd_soc_codec_driver max9768_codec_driver = { | 154 | static struct snd_soc_component_driver max9768_component_driver = { |
155 | .probe = max9768_probe, | 155 | .probe = max9768_probe, |
156 | .controls = max9768_volume, | 156 | .controls = max9768_volume, |
157 | .num_controls = ARRAY_SIZE(max9768_volume), | 157 | .num_controls = ARRAY_SIZE(max9768_volume), |
@@ -183,11 +183,13 @@ static int max9768_i2c_probe(struct i2c_client *client, | |||
183 | 183 | ||
184 | if (pdata) { | 184 | if (pdata) { |
185 | /* Mute on powerup to avoid clicks */ | 185 | /* Mute on powerup to avoid clicks */ |
186 | err = gpio_request_one(pdata->mute_gpio, GPIOF_INIT_HIGH, "MAX9768 Mute"); | 186 | err = devm_gpio_request_one(&client->dev, pdata->mute_gpio, |
187 | GPIOF_INIT_HIGH, "MAX9768 Mute"); | ||
187 | max9768->mute_gpio = err ?: pdata->mute_gpio; | 188 | max9768->mute_gpio = err ?: pdata->mute_gpio; |
188 | 189 | ||
189 | /* Activate chip by releasing shutdown, enables I2C */ | 190 | /* Activate chip by releasing shutdown, enables I2C */ |
190 | err = gpio_request_one(pdata->shdn_gpio, GPIOF_INIT_HIGH, "MAX9768 Shutdown"); | 191 | err = devm_gpio_request_one(&client->dev, pdata->shdn_gpio, |
192 | GPIOF_INIT_HIGH, "MAX9768 Shutdown"); | ||
191 | max9768->shdn_gpio = err ?: pdata->shdn_gpio; | 193 | max9768->shdn_gpio = err ?: pdata->shdn_gpio; |
192 | 194 | ||
193 | max9768->flags = pdata->flags; | 195 | max9768->flags = pdata->flags; |
@@ -199,38 +201,11 @@ static int max9768_i2c_probe(struct i2c_client *client, | |||
199 | i2c_set_clientdata(client, max9768); | 201 | i2c_set_clientdata(client, max9768); |
200 | 202 | ||
201 | max9768->regmap = devm_regmap_init_i2c(client, &max9768_i2c_regmap_config); | 203 | max9768->regmap = devm_regmap_init_i2c(client, &max9768_i2c_regmap_config); |
202 | if (IS_ERR(max9768->regmap)) { | 204 | if (IS_ERR(max9768->regmap)) |
203 | err = PTR_ERR(max9768->regmap); | 205 | return PTR_ERR(max9768->regmap); |
204 | goto err_gpio_free; | ||
205 | } | ||
206 | 206 | ||
207 | err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0); | 207 | return devm_snd_soc_register_component(&client->dev, |
208 | if (err) | 208 | &max9768_component_driver, NULL, 0); |
209 | goto err_gpio_free; | ||
210 | |||
211 | return 0; | ||
212 | |||
213 | err_gpio_free: | ||
214 | if (gpio_is_valid(max9768->shdn_gpio)) | ||
215 | gpio_free(max9768->shdn_gpio); | ||
216 | if (gpio_is_valid(max9768->mute_gpio)) | ||
217 | gpio_free(max9768->mute_gpio); | ||
218 | |||
219 | return err; | ||
220 | } | ||
221 | |||
222 | static int max9768_i2c_remove(struct i2c_client *client) | ||
223 | { | ||
224 | struct max9768 *max9768 = i2c_get_clientdata(client); | ||
225 | |||
226 | snd_soc_unregister_codec(&client->dev); | ||
227 | |||
228 | if (gpio_is_valid(max9768->shdn_gpio)) | ||
229 | gpio_free(max9768->shdn_gpio); | ||
230 | if (gpio_is_valid(max9768->mute_gpio)) | ||
231 | gpio_free(max9768->mute_gpio); | ||
232 | |||
233 | return 0; | ||
234 | } | 209 | } |
235 | 210 | ||
236 | static const struct i2c_device_id max9768_i2c_id[] = { | 211 | static const struct i2c_device_id max9768_i2c_id[] = { |
@@ -242,10 +217,8 @@ MODULE_DEVICE_TABLE(i2c, max9768_i2c_id); | |||
242 | static struct i2c_driver max9768_i2c_driver = { | 217 | static struct i2c_driver max9768_i2c_driver = { |
243 | .driver = { | 218 | .driver = { |
244 | .name = "max9768", | 219 | .name = "max9768", |
245 | .owner = THIS_MODULE, | ||
246 | }, | 220 | }, |
247 | .probe = max9768_i2c_probe, | 221 | .probe = max9768_i2c_probe, |
248 | .remove = max9768_i2c_remove, | ||
249 | .id_table = max9768_i2c_id, | 222 | .id_table = max9768_i2c_id, |
250 | }; | 223 | }; |
251 | module_i2c_driver(max9768_i2c_driver); | 224 | module_i2c_driver(max9768_i2c_driver); |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index d0f45348bfbb..20dcc496d39c 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -258,292 +258,36 @@ static const struct reg_default max98088_reg[] = { | |||
258 | { 0xc9, 0x00 }, /* C9 DAI2 biquad */ | 258 | { 0xc9, 0x00 }, /* C9 DAI2 biquad */ |
259 | }; | 259 | }; |
260 | 260 | ||
261 | static struct { | ||
262 | int readable; | ||
263 | int writable; | ||
264 | int vol; | ||
265 | } max98088_access[M98088_REG_CNT] = { | ||
266 | { 0xFF, 0xFF, 1 }, /* 00 IRQ status */ | ||
267 | { 0xFF, 0x00, 1 }, /* 01 MIC status */ | ||
268 | { 0xFF, 0x00, 1 }, /* 02 jack status */ | ||
269 | { 0x1F, 0x1F, 1 }, /* 03 battery voltage */ | ||
270 | { 0xFF, 0xFF, 0 }, /* 04 */ | ||
271 | { 0xFF, 0xFF, 0 }, /* 05 */ | ||
272 | { 0xFF, 0xFF, 0 }, /* 06 */ | ||
273 | { 0xFF, 0xFF, 0 }, /* 07 */ | ||
274 | { 0xFF, 0xFF, 0 }, /* 08 */ | ||
275 | { 0xFF, 0xFF, 0 }, /* 09 */ | ||
276 | { 0xFF, 0xFF, 0 }, /* 0A */ | ||
277 | { 0xFF, 0xFF, 0 }, /* 0B */ | ||
278 | { 0xFF, 0xFF, 0 }, /* 0C */ | ||
279 | { 0xFF, 0xFF, 0 }, /* 0D */ | ||
280 | { 0xFF, 0xFF, 0 }, /* 0E */ | ||
281 | { 0xFF, 0xFF, 0 }, /* 0F interrupt enable */ | ||
282 | |||
283 | { 0xFF, 0xFF, 0 }, /* 10 master clock */ | ||
284 | { 0xFF, 0xFF, 0 }, /* 11 DAI1 clock mode */ | ||
285 | { 0xFF, 0xFF, 0 }, /* 12 DAI1 clock control */ | ||
286 | { 0xFF, 0xFF, 0 }, /* 13 DAI1 clock control */ | ||
287 | { 0xFF, 0xFF, 0 }, /* 14 DAI1 format */ | ||
288 | { 0xFF, 0xFF, 0 }, /* 15 DAI1 clock */ | ||
289 | { 0xFF, 0xFF, 0 }, /* 16 DAI1 config */ | ||
290 | { 0xFF, 0xFF, 0 }, /* 17 DAI1 TDM */ | ||
291 | { 0xFF, 0xFF, 0 }, /* 18 DAI1 filters */ | ||
292 | { 0xFF, 0xFF, 0 }, /* 19 DAI2 clock mode */ | ||
293 | { 0xFF, 0xFF, 0 }, /* 1A DAI2 clock control */ | ||
294 | { 0xFF, 0xFF, 0 }, /* 1B DAI2 clock control */ | ||
295 | { 0xFF, 0xFF, 0 }, /* 1C DAI2 format */ | ||
296 | { 0xFF, 0xFF, 0 }, /* 1D DAI2 clock */ | ||
297 | { 0xFF, 0xFF, 0 }, /* 1E DAI2 config */ | ||
298 | { 0xFF, 0xFF, 0 }, /* 1F DAI2 TDM */ | ||
299 | |||
300 | { 0xFF, 0xFF, 0 }, /* 20 DAI2 filters */ | ||
301 | { 0xFF, 0xFF, 0 }, /* 21 data config */ | ||
302 | { 0xFF, 0xFF, 0 }, /* 22 DAC mixer */ | ||
303 | { 0xFF, 0xFF, 0 }, /* 23 left ADC mixer */ | ||
304 | { 0xFF, 0xFF, 0 }, /* 24 right ADC mixer */ | ||
305 | { 0xFF, 0xFF, 0 }, /* 25 left HP mixer */ | ||
306 | { 0xFF, 0xFF, 0 }, /* 26 right HP mixer */ | ||
307 | { 0xFF, 0xFF, 0 }, /* 27 HP control */ | ||
308 | { 0xFF, 0xFF, 0 }, /* 28 left REC mixer */ | ||
309 | { 0xFF, 0xFF, 0 }, /* 29 right REC mixer */ | ||
310 | { 0xFF, 0xFF, 0 }, /* 2A REC control */ | ||
311 | { 0xFF, 0xFF, 0 }, /* 2B left SPK mixer */ | ||
312 | { 0xFF, 0xFF, 0 }, /* 2C right SPK mixer */ | ||
313 | { 0xFF, 0xFF, 0 }, /* 2D SPK control */ | ||
314 | { 0xFF, 0xFF, 0 }, /* 2E sidetone */ | ||
315 | { 0xFF, 0xFF, 0 }, /* 2F DAI1 playback level */ | ||
316 | |||
317 | { 0xFF, 0xFF, 0 }, /* 30 DAI1 playback level */ | ||
318 | { 0xFF, 0xFF, 0 }, /* 31 DAI2 playback level */ | ||
319 | { 0xFF, 0xFF, 0 }, /* 32 DAI2 playbakc level */ | ||
320 | { 0xFF, 0xFF, 0 }, /* 33 left ADC level */ | ||
321 | { 0xFF, 0xFF, 0 }, /* 34 right ADC level */ | ||
322 | { 0xFF, 0xFF, 0 }, /* 35 MIC1 level */ | ||
323 | { 0xFF, 0xFF, 0 }, /* 36 MIC2 level */ | ||
324 | { 0xFF, 0xFF, 0 }, /* 37 INA level */ | ||
325 | { 0xFF, 0xFF, 0 }, /* 38 INB level */ | ||
326 | { 0xFF, 0xFF, 0 }, /* 39 left HP volume */ | ||
327 | { 0xFF, 0xFF, 0 }, /* 3A right HP volume */ | ||
328 | { 0xFF, 0xFF, 0 }, /* 3B left REC volume */ | ||
329 | { 0xFF, 0xFF, 0 }, /* 3C right REC volume */ | ||
330 | { 0xFF, 0xFF, 0 }, /* 3D left SPK volume */ | ||
331 | { 0xFF, 0xFF, 0 }, /* 3E right SPK volume */ | ||
332 | { 0xFF, 0xFF, 0 }, /* 3F MIC config */ | ||
333 | |||
334 | { 0xFF, 0xFF, 0 }, /* 40 MIC threshold */ | ||
335 | { 0xFF, 0xFF, 0 }, /* 41 excursion limiter filter */ | ||
336 | { 0xFF, 0xFF, 0 }, /* 42 excursion limiter threshold */ | ||
337 | { 0xFF, 0xFF, 0 }, /* 43 ALC */ | ||
338 | { 0xFF, 0xFF, 0 }, /* 44 power limiter threshold */ | ||
339 | { 0xFF, 0xFF, 0 }, /* 45 power limiter config */ | ||
340 | { 0xFF, 0xFF, 0 }, /* 46 distortion limiter config */ | ||
341 | { 0xFF, 0xFF, 0 }, /* 47 audio input */ | ||
342 | { 0xFF, 0xFF, 0 }, /* 48 microphone */ | ||
343 | { 0xFF, 0xFF, 0 }, /* 49 level control */ | ||
344 | { 0xFF, 0xFF, 0 }, /* 4A bypass switches */ | ||
345 | { 0xFF, 0xFF, 0 }, /* 4B jack detect */ | ||
346 | { 0xFF, 0xFF, 0 }, /* 4C input enable */ | ||
347 | { 0xFF, 0xFF, 0 }, /* 4D output enable */ | ||
348 | { 0xFF, 0xFF, 0 }, /* 4E bias control */ | ||
349 | { 0xFF, 0xFF, 0 }, /* 4F DAC power */ | ||
350 | |||
351 | { 0xFF, 0xFF, 0 }, /* 50 DAC power */ | ||
352 | { 0xFF, 0xFF, 0 }, /* 51 system */ | ||
353 | { 0xFF, 0xFF, 0 }, /* 52 DAI1 EQ1 */ | ||
354 | { 0xFF, 0xFF, 0 }, /* 53 DAI1 EQ1 */ | ||
355 | { 0xFF, 0xFF, 0 }, /* 54 DAI1 EQ1 */ | ||
356 | { 0xFF, 0xFF, 0 }, /* 55 DAI1 EQ1 */ | ||
357 | { 0xFF, 0xFF, 0 }, /* 56 DAI1 EQ1 */ | ||
358 | { 0xFF, 0xFF, 0 }, /* 57 DAI1 EQ1 */ | ||
359 | { 0xFF, 0xFF, 0 }, /* 58 DAI1 EQ1 */ | ||
360 | { 0xFF, 0xFF, 0 }, /* 59 DAI1 EQ1 */ | ||
361 | { 0xFF, 0xFF, 0 }, /* 5A DAI1 EQ1 */ | ||
362 | { 0xFF, 0xFF, 0 }, /* 5B DAI1 EQ1 */ | ||
363 | { 0xFF, 0xFF, 0 }, /* 5C DAI1 EQ2 */ | ||
364 | { 0xFF, 0xFF, 0 }, /* 5D DAI1 EQ2 */ | ||
365 | { 0xFF, 0xFF, 0 }, /* 5E DAI1 EQ2 */ | ||
366 | { 0xFF, 0xFF, 0 }, /* 5F DAI1 EQ2 */ | ||
367 | |||
368 | { 0xFF, 0xFF, 0 }, /* 60 DAI1 EQ2 */ | ||
369 | { 0xFF, 0xFF, 0 }, /* 61 DAI1 EQ2 */ | ||
370 | { 0xFF, 0xFF, 0 }, /* 62 DAI1 EQ2 */ | ||
371 | { 0xFF, 0xFF, 0 }, /* 63 DAI1 EQ2 */ | ||
372 | { 0xFF, 0xFF, 0 }, /* 64 DAI1 EQ2 */ | ||
373 | { 0xFF, 0xFF, 0 }, /* 65 DAI1 EQ2 */ | ||
374 | { 0xFF, 0xFF, 0 }, /* 66 DAI1 EQ3 */ | ||
375 | { 0xFF, 0xFF, 0 }, /* 67 DAI1 EQ3 */ | ||
376 | { 0xFF, 0xFF, 0 }, /* 68 DAI1 EQ3 */ | ||
377 | { 0xFF, 0xFF, 0 }, /* 69 DAI1 EQ3 */ | ||
378 | { 0xFF, 0xFF, 0 }, /* 6A DAI1 EQ3 */ | ||
379 | { 0xFF, 0xFF, 0 }, /* 6B DAI1 EQ3 */ | ||
380 | { 0xFF, 0xFF, 0 }, /* 6C DAI1 EQ3 */ | ||
381 | { 0xFF, 0xFF, 0 }, /* 6D DAI1 EQ3 */ | ||
382 | { 0xFF, 0xFF, 0 }, /* 6E DAI1 EQ3 */ | ||
383 | { 0xFF, 0xFF, 0 }, /* 6F DAI1 EQ3 */ | ||
384 | |||
385 | { 0xFF, 0xFF, 0 }, /* 70 DAI1 EQ4 */ | ||
386 | { 0xFF, 0xFF, 0 }, /* 71 DAI1 EQ4 */ | ||
387 | { 0xFF, 0xFF, 0 }, /* 72 DAI1 EQ4 */ | ||
388 | { 0xFF, 0xFF, 0 }, /* 73 DAI1 EQ4 */ | ||
389 | { 0xFF, 0xFF, 0 }, /* 74 DAI1 EQ4 */ | ||
390 | { 0xFF, 0xFF, 0 }, /* 75 DAI1 EQ4 */ | ||
391 | { 0xFF, 0xFF, 0 }, /* 76 DAI1 EQ4 */ | ||
392 | { 0xFF, 0xFF, 0 }, /* 77 DAI1 EQ4 */ | ||
393 | { 0xFF, 0xFF, 0 }, /* 78 DAI1 EQ4 */ | ||
394 | { 0xFF, 0xFF, 0 }, /* 79 DAI1 EQ4 */ | ||
395 | { 0xFF, 0xFF, 0 }, /* 7A DAI1 EQ5 */ | ||
396 | { 0xFF, 0xFF, 0 }, /* 7B DAI1 EQ5 */ | ||
397 | { 0xFF, 0xFF, 0 }, /* 7C DAI1 EQ5 */ | ||
398 | { 0xFF, 0xFF, 0 }, /* 7D DAI1 EQ5 */ | ||
399 | { 0xFF, 0xFF, 0 }, /* 7E DAI1 EQ5 */ | ||
400 | { 0xFF, 0xFF, 0 }, /* 7F DAI1 EQ5 */ | ||
401 | |||
402 | { 0xFF, 0xFF, 0 }, /* 80 DAI1 EQ5 */ | ||
403 | { 0xFF, 0xFF, 0 }, /* 81 DAI1 EQ5 */ | ||
404 | { 0xFF, 0xFF, 0 }, /* 82 DAI1 EQ5 */ | ||
405 | { 0xFF, 0xFF, 0 }, /* 83 DAI1 EQ5 */ | ||
406 | { 0xFF, 0xFF, 0 }, /* 84 DAI2 EQ1 */ | ||
407 | { 0xFF, 0xFF, 0 }, /* 85 DAI2 EQ1 */ | ||
408 | { 0xFF, 0xFF, 0 }, /* 86 DAI2 EQ1 */ | ||
409 | { 0xFF, 0xFF, 0 }, /* 87 DAI2 EQ1 */ | ||
410 | { 0xFF, 0xFF, 0 }, /* 88 DAI2 EQ1 */ | ||
411 | { 0xFF, 0xFF, 0 }, /* 89 DAI2 EQ1 */ | ||
412 | { 0xFF, 0xFF, 0 }, /* 8A DAI2 EQ1 */ | ||
413 | { 0xFF, 0xFF, 0 }, /* 8B DAI2 EQ1 */ | ||
414 | { 0xFF, 0xFF, 0 }, /* 8C DAI2 EQ1 */ | ||
415 | { 0xFF, 0xFF, 0 }, /* 8D DAI2 EQ1 */ | ||
416 | { 0xFF, 0xFF, 0 }, /* 8E DAI2 EQ2 */ | ||
417 | { 0xFF, 0xFF, 0 }, /* 8F DAI2 EQ2 */ | ||
418 | |||
419 | { 0xFF, 0xFF, 0 }, /* 90 DAI2 EQ2 */ | ||
420 | { 0xFF, 0xFF, 0 }, /* 91 DAI2 EQ2 */ | ||
421 | { 0xFF, 0xFF, 0 }, /* 92 DAI2 EQ2 */ | ||
422 | { 0xFF, 0xFF, 0 }, /* 93 DAI2 EQ2 */ | ||
423 | { 0xFF, 0xFF, 0 }, /* 94 DAI2 EQ2 */ | ||
424 | { 0xFF, 0xFF, 0 }, /* 95 DAI2 EQ2 */ | ||
425 | { 0xFF, 0xFF, 0 }, /* 96 DAI2 EQ2 */ | ||
426 | { 0xFF, 0xFF, 0 }, /* 97 DAI2 EQ2 */ | ||
427 | { 0xFF, 0xFF, 0 }, /* 98 DAI2 EQ3 */ | ||
428 | { 0xFF, 0xFF, 0 }, /* 99 DAI2 EQ3 */ | ||
429 | { 0xFF, 0xFF, 0 }, /* 9A DAI2 EQ3 */ | ||
430 | { 0xFF, 0xFF, 0 }, /* 9B DAI2 EQ3 */ | ||
431 | { 0xFF, 0xFF, 0 }, /* 9C DAI2 EQ3 */ | ||
432 | { 0xFF, 0xFF, 0 }, /* 9D DAI2 EQ3 */ | ||
433 | { 0xFF, 0xFF, 0 }, /* 9E DAI2 EQ3 */ | ||
434 | { 0xFF, 0xFF, 0 }, /* 9F DAI2 EQ3 */ | ||
435 | |||
436 | { 0xFF, 0xFF, 0 }, /* A0 DAI2 EQ3 */ | ||
437 | { 0xFF, 0xFF, 0 }, /* A1 DAI2 EQ3 */ | ||
438 | { 0xFF, 0xFF, 0 }, /* A2 DAI2 EQ4 */ | ||
439 | { 0xFF, 0xFF, 0 }, /* A3 DAI2 EQ4 */ | ||
440 | { 0xFF, 0xFF, 0 }, /* A4 DAI2 EQ4 */ | ||
441 | { 0xFF, 0xFF, 0 }, /* A5 DAI2 EQ4 */ | ||
442 | { 0xFF, 0xFF, 0 }, /* A6 DAI2 EQ4 */ | ||
443 | { 0xFF, 0xFF, 0 }, /* A7 DAI2 EQ4 */ | ||
444 | { 0xFF, 0xFF, 0 }, /* A8 DAI2 EQ4 */ | ||
445 | { 0xFF, 0xFF, 0 }, /* A9 DAI2 EQ4 */ | ||
446 | { 0xFF, 0xFF, 0 }, /* AA DAI2 EQ4 */ | ||
447 | { 0xFF, 0xFF, 0 }, /* AB DAI2 EQ4 */ | ||
448 | { 0xFF, 0xFF, 0 }, /* AC DAI2 EQ5 */ | ||
449 | { 0xFF, 0xFF, 0 }, /* AD DAI2 EQ5 */ | ||
450 | { 0xFF, 0xFF, 0 }, /* AE DAI2 EQ5 */ | ||
451 | { 0xFF, 0xFF, 0 }, /* AF DAI2 EQ5 */ | ||
452 | |||
453 | { 0xFF, 0xFF, 0 }, /* B0 DAI2 EQ5 */ | ||
454 | { 0xFF, 0xFF, 0 }, /* B1 DAI2 EQ5 */ | ||
455 | { 0xFF, 0xFF, 0 }, /* B2 DAI2 EQ5 */ | ||
456 | { 0xFF, 0xFF, 0 }, /* B3 DAI2 EQ5 */ | ||
457 | { 0xFF, 0xFF, 0 }, /* B4 DAI2 EQ5 */ | ||
458 | { 0xFF, 0xFF, 0 }, /* B5 DAI2 EQ5 */ | ||
459 | { 0xFF, 0xFF, 0 }, /* B6 DAI1 biquad */ | ||
460 | { 0xFF, 0xFF, 0 }, /* B7 DAI1 biquad */ | ||
461 | { 0xFF, 0xFF, 0 }, /* B8 DAI1 biquad */ | ||
462 | { 0xFF, 0xFF, 0 }, /* B9 DAI1 biquad */ | ||
463 | { 0xFF, 0xFF, 0 }, /* BA DAI1 biquad */ | ||
464 | { 0xFF, 0xFF, 0 }, /* BB DAI1 biquad */ | ||
465 | { 0xFF, 0xFF, 0 }, /* BC DAI1 biquad */ | ||
466 | { 0xFF, 0xFF, 0 }, /* BD DAI1 biquad */ | ||
467 | { 0xFF, 0xFF, 0 }, /* BE DAI1 biquad */ | ||
468 | { 0xFF, 0xFF, 0 }, /* BF DAI1 biquad */ | ||
469 | |||
470 | { 0xFF, 0xFF, 0 }, /* C0 DAI2 biquad */ | ||
471 | { 0xFF, 0xFF, 0 }, /* C1 DAI2 biquad */ | ||
472 | { 0xFF, 0xFF, 0 }, /* C2 DAI2 biquad */ | ||
473 | { 0xFF, 0xFF, 0 }, /* C3 DAI2 biquad */ | ||
474 | { 0xFF, 0xFF, 0 }, /* C4 DAI2 biquad */ | ||
475 | { 0xFF, 0xFF, 0 }, /* C5 DAI2 biquad */ | ||
476 | { 0xFF, 0xFF, 0 }, /* C6 DAI2 biquad */ | ||
477 | { 0xFF, 0xFF, 0 }, /* C7 DAI2 biquad */ | ||
478 | { 0xFF, 0xFF, 0 }, /* C8 DAI2 biquad */ | ||
479 | { 0xFF, 0xFF, 0 }, /* C9 DAI2 biquad */ | ||
480 | { 0x00, 0x00, 0 }, /* CA */ | ||
481 | { 0x00, 0x00, 0 }, /* CB */ | ||
482 | { 0x00, 0x00, 0 }, /* CC */ | ||
483 | { 0x00, 0x00, 0 }, /* CD */ | ||
484 | { 0x00, 0x00, 0 }, /* CE */ | ||
485 | { 0x00, 0x00, 0 }, /* CF */ | ||
486 | |||
487 | { 0x00, 0x00, 0 }, /* D0 */ | ||
488 | { 0x00, 0x00, 0 }, /* D1 */ | ||
489 | { 0x00, 0x00, 0 }, /* D2 */ | ||
490 | { 0x00, 0x00, 0 }, /* D3 */ | ||
491 | { 0x00, 0x00, 0 }, /* D4 */ | ||
492 | { 0x00, 0x00, 0 }, /* D5 */ | ||
493 | { 0x00, 0x00, 0 }, /* D6 */ | ||
494 | { 0x00, 0x00, 0 }, /* D7 */ | ||
495 | { 0x00, 0x00, 0 }, /* D8 */ | ||
496 | { 0x00, 0x00, 0 }, /* D9 */ | ||
497 | { 0x00, 0x00, 0 }, /* DA */ | ||
498 | { 0x00, 0x00, 0 }, /* DB */ | ||
499 | { 0x00, 0x00, 0 }, /* DC */ | ||
500 | { 0x00, 0x00, 0 }, /* DD */ | ||
501 | { 0x00, 0x00, 0 }, /* DE */ | ||
502 | { 0x00, 0x00, 0 }, /* DF */ | ||
503 | |||
504 | { 0x00, 0x00, 0 }, /* E0 */ | ||
505 | { 0x00, 0x00, 0 }, /* E1 */ | ||
506 | { 0x00, 0x00, 0 }, /* E2 */ | ||
507 | { 0x00, 0x00, 0 }, /* E3 */ | ||
508 | { 0x00, 0x00, 0 }, /* E4 */ | ||
509 | { 0x00, 0x00, 0 }, /* E5 */ | ||
510 | { 0x00, 0x00, 0 }, /* E6 */ | ||
511 | { 0x00, 0x00, 0 }, /* E7 */ | ||
512 | { 0x00, 0x00, 0 }, /* E8 */ | ||
513 | { 0x00, 0x00, 0 }, /* E9 */ | ||
514 | { 0x00, 0x00, 0 }, /* EA */ | ||
515 | { 0x00, 0x00, 0 }, /* EB */ | ||
516 | { 0x00, 0x00, 0 }, /* EC */ | ||
517 | { 0x00, 0x00, 0 }, /* ED */ | ||
518 | { 0x00, 0x00, 0 }, /* EE */ | ||
519 | { 0x00, 0x00, 0 }, /* EF */ | ||
520 | |||
521 | { 0x00, 0x00, 0 }, /* F0 */ | ||
522 | { 0x00, 0x00, 0 }, /* F1 */ | ||
523 | { 0x00, 0x00, 0 }, /* F2 */ | ||
524 | { 0x00, 0x00, 0 }, /* F3 */ | ||
525 | { 0x00, 0x00, 0 }, /* F4 */ | ||
526 | { 0x00, 0x00, 0 }, /* F5 */ | ||
527 | { 0x00, 0x00, 0 }, /* F6 */ | ||
528 | { 0x00, 0x00, 0 }, /* F7 */ | ||
529 | { 0x00, 0x00, 0 }, /* F8 */ | ||
530 | { 0x00, 0x00, 0 }, /* F9 */ | ||
531 | { 0x00, 0x00, 0 }, /* FA */ | ||
532 | { 0x00, 0x00, 0 }, /* FB */ | ||
533 | { 0x00, 0x00, 0 }, /* FC */ | ||
534 | { 0x00, 0x00, 0 }, /* FD */ | ||
535 | { 0x00, 0x00, 0 }, /* FE */ | ||
536 | { 0xFF, 0x00, 1 }, /* FF */ | ||
537 | }; | ||
538 | |||
539 | static bool max98088_readable_register(struct device *dev, unsigned int reg) | 261 | static bool max98088_readable_register(struct device *dev, unsigned int reg) |
540 | { | 262 | { |
541 | return max98088_access[reg].readable; | 263 | switch (reg) { |
264 | case M98088_REG_00_IRQ_STATUS ... 0xC9: | ||
265 | case M98088_REG_FF_REV_ID: | ||
266 | return true; | ||
267 | default: | ||
268 | return false; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | static bool max98088_writeable_register(struct device *dev, unsigned int reg) | ||
273 | { | ||
274 | switch (reg) { | ||
275 | case M98088_REG_03_BATTERY_VOLTAGE ... 0xC9: | ||
276 | return true; | ||
277 | default: | ||
278 | return false; | ||
279 | } | ||
542 | } | 280 | } |
543 | 281 | ||
544 | static bool max98088_volatile_register(struct device *dev, unsigned int reg) | 282 | static bool max98088_volatile_register(struct device *dev, unsigned int reg) |
545 | { | 283 | { |
546 | return max98088_access[reg].vol; | 284 | switch (reg) { |
285 | case M98088_REG_00_IRQ_STATUS ... M98088_REG_03_BATTERY_VOLTAGE: | ||
286 | case M98088_REG_FF_REV_ID: | ||
287 | return true; | ||
288 | default: | ||
289 | return false; | ||
290 | } | ||
547 | } | 291 | } |
548 | 292 | ||
549 | static const struct regmap_config max98088_regmap = { | 293 | static const struct regmap_config max98088_regmap = { |
@@ -551,6 +295,7 @@ static const struct regmap_config max98088_regmap = { | |||
551 | .val_bits = 8, | 295 | .val_bits = 8, |
552 | 296 | ||
553 | .readable_reg = max98088_readable_register, | 297 | .readable_reg = max98088_readable_register, |
298 | .writeable_reg = max98088_writeable_register, | ||
554 | .volatile_reg = max98088_volatile_register, | 299 | .volatile_reg = max98088_volatile_register, |
555 | .max_register = 0xff, | 300 | .max_register = 0xff, |
556 | 301 | ||
@@ -680,29 +425,26 @@ static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol, | |||
680 | return 0; | 425 | return 0; |
681 | } | 426 | } |
682 | 427 | ||
683 | static const unsigned int max98088_micboost_tlv[] = { | 428 | static const DECLARE_TLV_DB_RANGE(max98088_micboost_tlv, |
684 | TLV_DB_RANGE_HEAD(2), | 429 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), |
685 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), | 430 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0) |
686 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), | 431 | ); |
687 | }; | ||
688 | 432 | ||
689 | static const unsigned int max98088_hp_tlv[] = { | 433 | static const DECLARE_TLV_DB_RANGE(max98088_hp_tlv, |
690 | TLV_DB_RANGE_HEAD(5), | ||
691 | 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), | 434 | 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), |
692 | 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), | 435 | 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), |
693 | 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), | 436 | 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), |
694 | 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), | 437 | 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), |
695 | 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0), | 438 | 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0) |
696 | }; | 439 | ); |
697 | 440 | ||
698 | static const unsigned int max98088_spk_tlv[] = { | 441 | static const DECLARE_TLV_DB_RANGE(max98088_spk_tlv, |
699 | TLV_DB_RANGE_HEAD(5), | ||
700 | 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), | 442 | 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), |
701 | 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), | 443 | 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), |
702 | 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), | 444 | 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), |
703 | 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), | 445 | 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), |
704 | 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0), | 446 | 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0) |
705 | }; | 447 | ); |
706 | 448 | ||
707 | static const struct snd_kcontrol_new max98088_snd_controls[] = { | 449 | static const struct snd_kcontrol_new max98088_snd_controls[] = { |
708 | 450 | ||
@@ -2011,7 +1753,6 @@ MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); | |||
2011 | static struct i2c_driver max98088_i2c_driver = { | 1753 | static struct i2c_driver max98088_i2c_driver = { |
2012 | .driver = { | 1754 | .driver = { |
2013 | .name = "max98088", | 1755 | .name = "max98088", |
2014 | .owner = THIS_MODULE, | ||
2015 | }, | 1756 | }, |
2016 | .probe = max98088_i2c_probe, | 1757 | .probe = max98088_i2c_probe, |
2017 | .remove = max98088_i2c_remove, | 1758 | .remove = max98088_i2c_remove, |
diff --git a/sound/soc/codecs/max98088.h b/sound/soc/codecs/max98088.h index be89a4f4aab8..efa39bf46742 100644 --- a/sound/soc/codecs/max98088.h +++ b/sound/soc/codecs/max98088.h | |||
@@ -16,7 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | #define M98088_REG_00_IRQ_STATUS 0x00 | 17 | #define M98088_REG_00_IRQ_STATUS 0x00 |
18 | #define M98088_REG_01_MIC_STATUS 0x01 | 18 | #define M98088_REG_01_MIC_STATUS 0x01 |
19 | #define M98088_REG_02_JACK_STAUS 0x02 | 19 | #define M98088_REG_02_JACK_STATUS 0x02 |
20 | #define M98088_REG_03_BATTERY_VOLTAGE 0x03 | 20 | #define M98088_REG_03_BATTERY_VOLTAGE 0x03 |
21 | #define M98088_REG_0F_IRQ_ENABLE 0x0F | 21 | #define M98088_REG_0F_IRQ_ENABLE 0x0F |
22 | #define M98088_REG_10_SYS_CLK 0x10 | 22 | #define M98088_REG_10_SYS_CLK 0x10 |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 78268f0514e9..584aab83e478 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -267,75 +267,8 @@ static bool max98090_volatile_register(struct device *dev, unsigned int reg) | |||
267 | static bool max98090_readable_register(struct device *dev, unsigned int reg) | 267 | static bool max98090_readable_register(struct device *dev, unsigned int reg) |
268 | { | 268 | { |
269 | switch (reg) { | 269 | switch (reg) { |
270 | case M98090_REG_DEVICE_STATUS: | 270 | case M98090_REG_DEVICE_STATUS ... M98090_REG_INTERRUPT_S: |
271 | case M98090_REG_JACK_STATUS: | 271 | case M98090_REG_LINE_INPUT_CONFIG ... 0xD1: |
272 | case M98090_REG_INTERRUPT_S: | ||
273 | case M98090_REG_RESERVED: | ||
274 | case M98090_REG_LINE_INPUT_CONFIG: | ||
275 | case M98090_REG_LINE_INPUT_LEVEL: | ||
276 | case M98090_REG_INPUT_MODE: | ||
277 | case M98090_REG_MIC1_INPUT_LEVEL: | ||
278 | case M98090_REG_MIC2_INPUT_LEVEL: | ||
279 | case M98090_REG_MIC_BIAS_VOLTAGE: | ||
280 | case M98090_REG_DIGITAL_MIC_ENABLE: | ||
281 | case M98090_REG_DIGITAL_MIC_CONFIG: | ||
282 | case M98090_REG_LEFT_ADC_MIXER: | ||
283 | case M98090_REG_RIGHT_ADC_MIXER: | ||
284 | case M98090_REG_LEFT_ADC_LEVEL: | ||
285 | case M98090_REG_RIGHT_ADC_LEVEL: | ||
286 | case M98090_REG_ADC_BIQUAD_LEVEL: | ||
287 | case M98090_REG_ADC_SIDETONE: | ||
288 | case M98090_REG_SYSTEM_CLOCK: | ||
289 | case M98090_REG_CLOCK_MODE: | ||
290 | case M98090_REG_CLOCK_RATIO_NI_MSB: | ||
291 | case M98090_REG_CLOCK_RATIO_NI_LSB: | ||
292 | case M98090_REG_CLOCK_RATIO_MI_MSB: | ||
293 | case M98090_REG_CLOCK_RATIO_MI_LSB: | ||
294 | case M98090_REG_MASTER_MODE: | ||
295 | case M98090_REG_INTERFACE_FORMAT: | ||
296 | case M98090_REG_TDM_CONTROL: | ||
297 | case M98090_REG_TDM_FORMAT: | ||
298 | case M98090_REG_IO_CONFIGURATION: | ||
299 | case M98090_REG_FILTER_CONFIG: | ||
300 | case M98090_REG_DAI_PLAYBACK_LEVEL: | ||
301 | case M98090_REG_DAI_PLAYBACK_LEVEL_EQ: | ||
302 | case M98090_REG_LEFT_HP_MIXER: | ||
303 | case M98090_REG_RIGHT_HP_MIXER: | ||
304 | case M98090_REG_HP_CONTROL: | ||
305 | case M98090_REG_LEFT_HP_VOLUME: | ||
306 | case M98090_REG_RIGHT_HP_VOLUME: | ||
307 | case M98090_REG_LEFT_SPK_MIXER: | ||
308 | case M98090_REG_RIGHT_SPK_MIXER: | ||
309 | case M98090_REG_SPK_CONTROL: | ||
310 | case M98090_REG_LEFT_SPK_VOLUME: | ||
311 | case M98090_REG_RIGHT_SPK_VOLUME: | ||
312 | case M98090_REG_DRC_TIMING: | ||
313 | case M98090_REG_DRC_COMPRESSOR: | ||
314 | case M98090_REG_DRC_EXPANDER: | ||
315 | case M98090_REG_DRC_GAIN: | ||
316 | case M98090_REG_RCV_LOUTL_MIXER: | ||
317 | case M98090_REG_RCV_LOUTL_CONTROL: | ||
318 | case M98090_REG_RCV_LOUTL_VOLUME: | ||
319 | case M98090_REG_LOUTR_MIXER: | ||
320 | case M98090_REG_LOUTR_CONTROL: | ||
321 | case M98090_REG_LOUTR_VOLUME: | ||
322 | case M98090_REG_JACK_DETECT: | ||
323 | case M98090_REG_INPUT_ENABLE: | ||
324 | case M98090_REG_OUTPUT_ENABLE: | ||
325 | case M98090_REG_LEVEL_CONTROL: | ||
326 | case M98090_REG_DSP_FILTER_ENABLE: | ||
327 | case M98090_REG_BIAS_CONTROL: | ||
328 | case M98090_REG_DAC_CONTROL: | ||
329 | case M98090_REG_ADC_CONTROL: | ||
330 | case M98090_REG_DEVICE_SHUTDOWN: | ||
331 | case M98090_REG_EQUALIZER_BASE ... M98090_REG_EQUALIZER_BASE + 0x68: | ||
332 | case M98090_REG_RECORD_BIQUAD_BASE ... M98090_REG_RECORD_BIQUAD_BASE + 0x0E: | ||
333 | case M98090_REG_DMIC3_VOLUME: | ||
334 | case M98090_REG_DMIC4_VOLUME: | ||
335 | case M98090_REG_DMIC34_BQ_PREATTEN: | ||
336 | case M98090_REG_RECORD_TDM_SLOT: | ||
337 | case M98090_REG_SAMPLE_RATE: | ||
338 | case M98090_REG_DMIC34_BIQUAD_BASE ... M98090_REG_DMIC34_BIQUAD_BASE + 0x0E: | ||
339 | case M98090_REG_REVISION_ID: | 272 | case M98090_REG_REVISION_ID: |
340 | return true; | 273 | return true; |
341 | default: | 274 | default: |
@@ -360,22 +293,20 @@ static int max98090_reset(struct max98090_priv *max98090) | |||
360 | return ret; | 293 | return ret; |
361 | } | 294 | } |
362 | 295 | ||
363 | static const unsigned int max98090_micboost_tlv[] = { | 296 | static const DECLARE_TLV_DB_RANGE(max98090_micboost_tlv, |
364 | TLV_DB_RANGE_HEAD(2), | ||
365 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), | 297 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), |
366 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), | 298 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0) |
367 | }; | 299 | ); |
368 | 300 | ||
369 | static const DECLARE_TLV_DB_SCALE(max98090_mic_tlv, 0, 100, 0); | 301 | static const DECLARE_TLV_DB_SCALE(max98090_mic_tlv, 0, 100, 0); |
370 | 302 | ||
371 | static const DECLARE_TLV_DB_SCALE(max98090_line_single_ended_tlv, | 303 | static const DECLARE_TLV_DB_SCALE(max98090_line_single_ended_tlv, |
372 | -600, 600, 0); | 304 | -600, 600, 0); |
373 | 305 | ||
374 | static const unsigned int max98090_line_tlv[] = { | 306 | static const DECLARE_TLV_DB_RANGE(max98090_line_tlv, |
375 | TLV_DB_RANGE_HEAD(2), | ||
376 | 0, 3, TLV_DB_SCALE_ITEM(-600, 300, 0), | 307 | 0, 3, TLV_DB_SCALE_ITEM(-600, 300, 0), |
377 | 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0), | 308 | 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0) |
378 | }; | 309 | ); |
379 | 310 | ||
380 | static const DECLARE_TLV_DB_SCALE(max98090_avg_tlv, 0, 600, 0); | 311 | static const DECLARE_TLV_DB_SCALE(max98090_avg_tlv, 0, 600, 0); |
381 | static const DECLARE_TLV_DB_SCALE(max98090_av_tlv, -1200, 100, 0); | 312 | static const DECLARE_TLV_DB_SCALE(max98090_av_tlv, -1200, 100, 0); |
@@ -391,38 +322,34 @@ static const DECLARE_TLV_DB_SCALE(max98090_alccomp_tlv, -3100, 100, 0); | |||
391 | static const DECLARE_TLV_DB_SCALE(max98090_drcexp_tlv, -6600, 100, 0); | 322 | static const DECLARE_TLV_DB_SCALE(max98090_drcexp_tlv, -6600, 100, 0); |
392 | static const DECLARE_TLV_DB_SCALE(max98090_sdg_tlv, 50, 200, 0); | 323 | static const DECLARE_TLV_DB_SCALE(max98090_sdg_tlv, 50, 200, 0); |
393 | 324 | ||
394 | static const unsigned int max98090_mixout_tlv[] = { | 325 | static const DECLARE_TLV_DB_RANGE(max98090_mixout_tlv, |
395 | TLV_DB_RANGE_HEAD(2), | ||
396 | 0, 1, TLV_DB_SCALE_ITEM(-1200, 250, 0), | 326 | 0, 1, TLV_DB_SCALE_ITEM(-1200, 250, 0), |
397 | 2, 3, TLV_DB_SCALE_ITEM(-600, 600, 0), | 327 | 2, 3, TLV_DB_SCALE_ITEM(-600, 600, 0) |
398 | }; | 328 | ); |
399 | 329 | ||
400 | static const unsigned int max98090_hp_tlv[] = { | 330 | static const DECLARE_TLV_DB_RANGE(max98090_hp_tlv, |
401 | TLV_DB_RANGE_HEAD(5), | ||
402 | 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), | 331 | 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), |
403 | 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), | 332 | 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), |
404 | 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), | 333 | 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), |
405 | 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), | 334 | 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), |
406 | 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0), | 335 | 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0) |
407 | }; | 336 | ); |
408 | 337 | ||
409 | static const unsigned int max98090_spk_tlv[] = { | 338 | static const DECLARE_TLV_DB_RANGE(max98090_spk_tlv, |
410 | TLV_DB_RANGE_HEAD(5), | ||
411 | 0, 4, TLV_DB_SCALE_ITEM(-4800, 400, 0), | 339 | 0, 4, TLV_DB_SCALE_ITEM(-4800, 400, 0), |
412 | 5, 10, TLV_DB_SCALE_ITEM(-2900, 300, 0), | 340 | 5, 10, TLV_DB_SCALE_ITEM(-2900, 300, 0), |
413 | 11, 14, TLV_DB_SCALE_ITEM(-1200, 200, 0), | 341 | 11, 14, TLV_DB_SCALE_ITEM(-1200, 200, 0), |
414 | 15, 29, TLV_DB_SCALE_ITEM(-500, 100, 0), | 342 | 15, 29, TLV_DB_SCALE_ITEM(-500, 100, 0), |
415 | 30, 39, TLV_DB_SCALE_ITEM(950, 50, 0), | 343 | 30, 39, TLV_DB_SCALE_ITEM(950, 50, 0) |
416 | }; | 344 | ); |
417 | 345 | ||
418 | static const unsigned int max98090_rcv_lout_tlv[] = { | 346 | static const DECLARE_TLV_DB_RANGE(max98090_rcv_lout_tlv, |
419 | TLV_DB_RANGE_HEAD(5), | ||
420 | 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), | 347 | 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), |
421 | 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), | 348 | 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), |
422 | 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), | 349 | 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), |
423 | 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), | 350 | 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), |
424 | 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0), | 351 | 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0) |
425 | }; | 352 | ); |
426 | 353 | ||
427 | static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol, | 354 | static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol, |
428 | struct snd_ctl_elem_value *ucontrol) | 355 | struct snd_ctl_elem_value *ucontrol) |
@@ -850,6 +777,19 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, | |||
850 | return 0; | 777 | return 0; |
851 | } | 778 | } |
852 | 779 | ||
780 | static int max98090_shdn_event(struct snd_soc_dapm_widget *w, | ||
781 | struct snd_kcontrol *kcontrol, int event) | ||
782 | { | ||
783 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
784 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | ||
785 | |||
786 | if (event & SND_SOC_DAPM_POST_PMU) | ||
787 | max98090->shdn_pending = true; | ||
788 | |||
789 | return 0; | ||
790 | |||
791 | } | ||
792 | |||
853 | static const char *mic1_mux_text[] = { "IN12", "IN56" }; | 793 | static const char *mic1_mux_text[] = { "IN12", "IN56" }; |
854 | 794 | ||
855 | static SOC_ENUM_SINGLE_DECL(mic1_mux_enum, | 795 | static SOC_ENUM_SINGLE_DECL(mic1_mux_enum, |
@@ -1158,9 +1098,11 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { | |||
1158 | SND_SOC_DAPM_SUPPLY("SDOEN", M98090_REG_IO_CONFIGURATION, | 1098 | SND_SOC_DAPM_SUPPLY("SDOEN", M98090_REG_IO_CONFIGURATION, |
1159 | M98090_SDOEN_SHIFT, 0, NULL, 0), | 1099 | M98090_SDOEN_SHIFT, 0, NULL, 0), |
1160 | SND_SOC_DAPM_SUPPLY("DMICL_ENA", M98090_REG_DIGITAL_MIC_ENABLE, | 1100 | SND_SOC_DAPM_SUPPLY("DMICL_ENA", M98090_REG_DIGITAL_MIC_ENABLE, |
1161 | M98090_DIGMICL_SHIFT, 0, NULL, 0), | 1101 | M98090_DIGMICL_SHIFT, 0, max98090_shdn_event, |
1102 | SND_SOC_DAPM_POST_PMU), | ||
1162 | SND_SOC_DAPM_SUPPLY("DMICR_ENA", M98090_REG_DIGITAL_MIC_ENABLE, | 1103 | SND_SOC_DAPM_SUPPLY("DMICR_ENA", M98090_REG_DIGITAL_MIC_ENABLE, |
1163 | M98090_DIGMICR_SHIFT, 0, NULL, 0), | 1104 | M98090_DIGMICR_SHIFT, 0, max98090_shdn_event, |
1105 | SND_SOC_DAPM_POST_PMU), | ||
1164 | SND_SOC_DAPM_SUPPLY("AHPF", M98090_REG_FILTER_CONFIG, | 1106 | SND_SOC_DAPM_SUPPLY("AHPF", M98090_REG_FILTER_CONFIG, |
1165 | M98090_AHPF_SHIFT, 0, NULL, 0), | 1107 | M98090_AHPF_SHIFT, 0, NULL, 0), |
1166 | 1108 | ||
@@ -1205,10 +1147,12 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { | |||
1205 | &max98090_right_adc_mixer_controls[0], | 1147 | &max98090_right_adc_mixer_controls[0], |
1206 | ARRAY_SIZE(max98090_right_adc_mixer_controls)), | 1148 | ARRAY_SIZE(max98090_right_adc_mixer_controls)), |
1207 | 1149 | ||
1208 | SND_SOC_DAPM_ADC("ADCL", NULL, M98090_REG_INPUT_ENABLE, | 1150 | SND_SOC_DAPM_ADC_E("ADCL", NULL, M98090_REG_INPUT_ENABLE, |
1209 | M98090_ADLEN_SHIFT, 0), | 1151 | M98090_ADLEN_SHIFT, 0, max98090_shdn_event, |
1210 | SND_SOC_DAPM_ADC("ADCR", NULL, M98090_REG_INPUT_ENABLE, | 1152 | SND_SOC_DAPM_POST_PMU), |
1211 | M98090_ADREN_SHIFT, 0), | 1153 | SND_SOC_DAPM_ADC_E("ADCR", NULL, M98090_REG_INPUT_ENABLE, |
1154 | M98090_ADREN_SHIFT, 0, max98090_shdn_event, | ||
1155 | SND_SOC_DAPM_POST_PMU), | ||
1212 | 1156 | ||
1213 | SND_SOC_DAPM_AIF_OUT("AIFOUTL", "HiFi Capture", 0, | 1157 | SND_SOC_DAPM_AIF_OUT("AIFOUTL", "HiFi Capture", 0, |
1214 | SND_SOC_NOPM, 0, 0), | 1158 | SND_SOC_NOPM, 0, 0), |
@@ -1801,10 +1745,13 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, | |||
1801 | if (IS_ERR(max98090->mclk)) | 1745 | if (IS_ERR(max98090->mclk)) |
1802 | break; | 1746 | break; |
1803 | 1747 | ||
1804 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) | 1748 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) { |
1805 | clk_disable_unprepare(max98090->mclk); | 1749 | clk_disable_unprepare(max98090->mclk); |
1806 | else | 1750 | } else { |
1807 | clk_prepare_enable(max98090->mclk); | 1751 | ret = clk_prepare_enable(max98090->mclk); |
1752 | if (ret) | ||
1753 | return ret; | ||
1754 | } | ||
1808 | break; | 1755 | break; |
1809 | 1756 | ||
1810 | case SND_SOC_BIAS_STANDBY: | 1757 | case SND_SOC_BIAS_STANDBY: |
@@ -2383,7 +2330,7 @@ EXPORT_SYMBOL_GPL(max98090_mic_detect); | |||
2383 | #define MAX98090_RATES SNDRV_PCM_RATE_8000_96000 | 2330 | #define MAX98090_RATES SNDRV_PCM_RATE_8000_96000 |
2384 | #define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) | 2331 | #define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) |
2385 | 2332 | ||
2386 | static struct snd_soc_dai_ops max98090_dai_ops = { | 2333 | static const struct snd_soc_dai_ops max98090_dai_ops = { |
2387 | .set_sysclk = max98090_dai_set_sysclk, | 2334 | .set_sysclk = max98090_dai_set_sysclk, |
2388 | .set_fmt = max98090_dai_set_fmt, | 2335 | .set_fmt = max98090_dai_set_fmt, |
2389 | .set_tdm_slot = max98090_set_tdm_slot, | 2336 | .set_tdm_slot = max98090_set_tdm_slot, |
@@ -2536,9 +2483,26 @@ static int max98090_remove(struct snd_soc_codec *codec) | |||
2536 | return 0; | 2483 | return 0; |
2537 | } | 2484 | } |
2538 | 2485 | ||
2486 | static void max98090_seq_notifier(struct snd_soc_dapm_context *dapm, | ||
2487 | enum snd_soc_dapm_type event, int subseq) | ||
2488 | { | ||
2489 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
2490 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | ||
2491 | |||
2492 | if (max98090->shdn_pending) { | ||
2493 | snd_soc_update_bits(codec, M98090_REG_DEVICE_SHUTDOWN, | ||
2494 | M98090_SHDNN_MASK, 0); | ||
2495 | msleep(40); | ||
2496 | snd_soc_update_bits(codec, M98090_REG_DEVICE_SHUTDOWN, | ||
2497 | M98090_SHDNN_MASK, M98090_SHDNN_MASK); | ||
2498 | max98090->shdn_pending = false; | ||
2499 | } | ||
2500 | } | ||
2501 | |||
2539 | static struct snd_soc_codec_driver soc_codec_dev_max98090 = { | 2502 | static struct snd_soc_codec_driver soc_codec_dev_max98090 = { |
2540 | .probe = max98090_probe, | 2503 | .probe = max98090_probe, |
2541 | .remove = max98090_remove, | 2504 | .remove = max98090_remove, |
2505 | .seq_notifier = max98090_seq_notifier, | ||
2542 | .set_bias_level = max98090_set_bias_level, | 2506 | .set_bias_level = max98090_set_bias_level, |
2543 | }; | 2507 | }; |
2544 | 2508 | ||
@@ -2714,7 +2678,6 @@ MODULE_DEVICE_TABLE(acpi, max98090_acpi_match); | |||
2714 | static struct i2c_driver max98090_i2c_driver = { | 2678 | static struct i2c_driver max98090_i2c_driver = { |
2715 | .driver = { | 2679 | .driver = { |
2716 | .name = "max98090", | 2680 | .name = "max98090", |
2717 | .owner = THIS_MODULE, | ||
2718 | .pm = &max98090_pm, | 2681 | .pm = &max98090_pm, |
2719 | .of_match_table = of_match_ptr(max98090_of_match), | 2682 | .of_match_table = of_match_ptr(max98090_of_match), |
2720 | .acpi_match_table = ACPI_PTR(max98090_acpi_match), | 2683 | .acpi_match_table = ACPI_PTR(max98090_acpi_match), |
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h index 21ff743f5af2..bc610d9a9ecb 100644 --- a/sound/soc/codecs/max98090.h +++ b/sound/soc/codecs/max98090.h | |||
@@ -1543,6 +1543,7 @@ struct max98090_priv { | |||
1543 | unsigned int pa2en; | 1543 | unsigned int pa2en; |
1544 | unsigned int sidetone; | 1544 | unsigned int sidetone; |
1545 | bool master; | 1545 | bool master; |
1546 | bool shdn_pending; | ||
1546 | }; | 1547 | }; |
1547 | 1548 | ||
1548 | int max98090_mic_detect(struct snd_soc_codec *codec, | 1549 | int max98090_mic_detect(struct snd_soc_codec *codec, |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 9a46d3dcf703..1fedac50355e 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -202,300 +202,36 @@ static const struct reg_default max98095_reg_def[] = { | |||
202 | { 0xff, 0x00 }, /* FF */ | 202 | { 0xff, 0x00 }, /* FF */ |
203 | }; | 203 | }; |
204 | 204 | ||
205 | static struct { | ||
206 | int readable; | ||
207 | int writable; | ||
208 | } max98095_access[M98095_REG_CNT] = { | ||
209 | { 0x00, 0x00 }, /* 00 */ | ||
210 | { 0xFF, 0x00 }, /* 01 */ | ||
211 | { 0xFF, 0x00 }, /* 02 */ | ||
212 | { 0xFF, 0x00 }, /* 03 */ | ||
213 | { 0xFF, 0x00 }, /* 04 */ | ||
214 | { 0xFF, 0x00 }, /* 05 */ | ||
215 | { 0xFF, 0x00 }, /* 06 */ | ||
216 | { 0xFF, 0x00 }, /* 07 */ | ||
217 | { 0xFF, 0x00 }, /* 08 */ | ||
218 | { 0xFF, 0x00 }, /* 09 */ | ||
219 | { 0xFF, 0x00 }, /* 0A */ | ||
220 | { 0xFF, 0x00 }, /* 0B */ | ||
221 | { 0xFF, 0x00 }, /* 0C */ | ||
222 | { 0xFF, 0x00 }, /* 0D */ | ||
223 | { 0xFF, 0x00 }, /* 0E */ | ||
224 | { 0xFF, 0x9F }, /* 0F */ | ||
225 | { 0xFF, 0xFF }, /* 10 */ | ||
226 | { 0xFF, 0xFF }, /* 11 */ | ||
227 | { 0xFF, 0xFF }, /* 12 */ | ||
228 | { 0xFF, 0xFF }, /* 13 */ | ||
229 | { 0xFF, 0xFF }, /* 14 */ | ||
230 | { 0xFF, 0xFF }, /* 15 */ | ||
231 | { 0xFF, 0xFF }, /* 16 */ | ||
232 | { 0xFF, 0xFF }, /* 17 */ | ||
233 | { 0xFF, 0xFF }, /* 18 */ | ||
234 | { 0xFF, 0xFF }, /* 19 */ | ||
235 | { 0xFF, 0xFF }, /* 1A */ | ||
236 | { 0xFF, 0xFF }, /* 1B */ | ||
237 | { 0xFF, 0xFF }, /* 1C */ | ||
238 | { 0xFF, 0xFF }, /* 1D */ | ||
239 | { 0xFF, 0x77 }, /* 1E */ | ||
240 | { 0xFF, 0x77 }, /* 1F */ | ||
241 | { 0xFF, 0x77 }, /* 20 */ | ||
242 | { 0xFF, 0x77 }, /* 21 */ | ||
243 | { 0xFF, 0x77 }, /* 22 */ | ||
244 | { 0xFF, 0x77 }, /* 23 */ | ||
245 | { 0xFF, 0xFF }, /* 24 */ | ||
246 | { 0xFF, 0x7F }, /* 25 */ | ||
247 | { 0xFF, 0x31 }, /* 26 */ | ||
248 | { 0xFF, 0xFF }, /* 27 */ | ||
249 | { 0xFF, 0xFF }, /* 28 */ | ||
250 | { 0xFF, 0xFF }, /* 29 */ | ||
251 | { 0xFF, 0xF7 }, /* 2A */ | ||
252 | { 0xFF, 0x2F }, /* 2B */ | ||
253 | { 0xFF, 0xEF }, /* 2C */ | ||
254 | { 0xFF, 0xFF }, /* 2D */ | ||
255 | { 0xFF, 0xFF }, /* 2E */ | ||
256 | { 0xFF, 0xFF }, /* 2F */ | ||
257 | { 0xFF, 0xFF }, /* 30 */ | ||
258 | { 0xFF, 0xFF }, /* 31 */ | ||
259 | { 0xFF, 0xFF }, /* 32 */ | ||
260 | { 0xFF, 0xFF }, /* 33 */ | ||
261 | { 0xFF, 0xF7 }, /* 34 */ | ||
262 | { 0xFF, 0x2F }, /* 35 */ | ||
263 | { 0xFF, 0xCF }, /* 36 */ | ||
264 | { 0xFF, 0xFF }, /* 37 */ | ||
265 | { 0xFF, 0xFF }, /* 38 */ | ||
266 | { 0xFF, 0xFF }, /* 39 */ | ||
267 | { 0xFF, 0xFF }, /* 3A */ | ||
268 | { 0xFF, 0xFF }, /* 3B */ | ||
269 | { 0xFF, 0xFF }, /* 3C */ | ||
270 | { 0xFF, 0xFF }, /* 3D */ | ||
271 | { 0xFF, 0xF7 }, /* 3E */ | ||
272 | { 0xFF, 0x2F }, /* 3F */ | ||
273 | { 0xFF, 0xCF }, /* 40 */ | ||
274 | { 0xFF, 0xFF }, /* 41 */ | ||
275 | { 0xFF, 0x77 }, /* 42 */ | ||
276 | { 0xFF, 0xFF }, /* 43 */ | ||
277 | { 0xFF, 0xFF }, /* 44 */ | ||
278 | { 0xFF, 0xFF }, /* 45 */ | ||
279 | { 0xFF, 0xFF }, /* 46 */ | ||
280 | { 0xFF, 0xFF }, /* 47 */ | ||
281 | { 0xFF, 0xFF }, /* 48 */ | ||
282 | { 0xFF, 0x0F }, /* 49 */ | ||
283 | { 0xFF, 0xFF }, /* 4A */ | ||
284 | { 0xFF, 0xFF }, /* 4B */ | ||
285 | { 0xFF, 0x3F }, /* 4C */ | ||
286 | { 0xFF, 0x3F }, /* 4D */ | ||
287 | { 0xFF, 0x3F }, /* 4E */ | ||
288 | { 0xFF, 0xFF }, /* 4F */ | ||
289 | { 0xFF, 0x7F }, /* 50 */ | ||
290 | { 0xFF, 0x7F }, /* 51 */ | ||
291 | { 0xFF, 0x0F }, /* 52 */ | ||
292 | { 0xFF, 0x3F }, /* 53 */ | ||
293 | { 0xFF, 0x3F }, /* 54 */ | ||
294 | { 0xFF, 0x3F }, /* 55 */ | ||
295 | { 0xFF, 0xFF }, /* 56 */ | ||
296 | { 0xFF, 0xFF }, /* 57 */ | ||
297 | { 0xFF, 0xBF }, /* 58 */ | ||
298 | { 0xFF, 0x1F }, /* 59 */ | ||
299 | { 0xFF, 0xBF }, /* 5A */ | ||
300 | { 0xFF, 0x1F }, /* 5B */ | ||
301 | { 0xFF, 0xBF }, /* 5C */ | ||
302 | { 0xFF, 0x3F }, /* 5D */ | ||
303 | { 0xFF, 0x3F }, /* 5E */ | ||
304 | { 0xFF, 0x7F }, /* 5F */ | ||
305 | { 0xFF, 0x7F }, /* 60 */ | ||
306 | { 0xFF, 0x47 }, /* 61 */ | ||
307 | { 0xFF, 0x9F }, /* 62 */ | ||
308 | { 0xFF, 0x9F }, /* 63 */ | ||
309 | { 0xFF, 0x9F }, /* 64 */ | ||
310 | { 0xFF, 0x9F }, /* 65 */ | ||
311 | { 0xFF, 0x9F }, /* 66 */ | ||
312 | { 0xFF, 0xBF }, /* 67 */ | ||
313 | { 0xFF, 0xBF }, /* 68 */ | ||
314 | { 0xFF, 0xFF }, /* 69 */ | ||
315 | { 0xFF, 0xFF }, /* 6A */ | ||
316 | { 0xFF, 0x7F }, /* 6B */ | ||
317 | { 0xFF, 0xF7 }, /* 6C */ | ||
318 | { 0xFF, 0xFF }, /* 6D */ | ||
319 | { 0xFF, 0xFF }, /* 6E */ | ||
320 | { 0xFF, 0x1F }, /* 6F */ | ||
321 | { 0xFF, 0xF7 }, /* 70 */ | ||
322 | { 0xFF, 0xFF }, /* 71 */ | ||
323 | { 0xFF, 0xFF }, /* 72 */ | ||
324 | { 0xFF, 0x1F }, /* 73 */ | ||
325 | { 0xFF, 0xF7 }, /* 74 */ | ||
326 | { 0xFF, 0xFF }, /* 75 */ | ||
327 | { 0xFF, 0xFF }, /* 76 */ | ||
328 | { 0xFF, 0x1F }, /* 77 */ | ||
329 | { 0xFF, 0xF7 }, /* 78 */ | ||
330 | { 0xFF, 0xFF }, /* 79 */ | ||
331 | { 0xFF, 0xFF }, /* 7A */ | ||
332 | { 0xFF, 0x1F }, /* 7B */ | ||
333 | { 0xFF, 0xF7 }, /* 7C */ | ||
334 | { 0xFF, 0xFF }, /* 7D */ | ||
335 | { 0xFF, 0xFF }, /* 7E */ | ||
336 | { 0xFF, 0x1F }, /* 7F */ | ||
337 | { 0xFF, 0xF7 }, /* 80 */ | ||
338 | { 0xFF, 0xFF }, /* 81 */ | ||
339 | { 0xFF, 0xFF }, /* 82 */ | ||
340 | { 0xFF, 0x1F }, /* 83 */ | ||
341 | { 0xFF, 0x7F }, /* 84 */ | ||
342 | { 0xFF, 0x0F }, /* 85 */ | ||
343 | { 0xFF, 0xD8 }, /* 86 */ | ||
344 | { 0xFF, 0xFF }, /* 87 */ | ||
345 | { 0xFF, 0xEF }, /* 88 */ | ||
346 | { 0xFF, 0xFE }, /* 89 */ | ||
347 | { 0xFF, 0xFE }, /* 8A */ | ||
348 | { 0xFF, 0xFF }, /* 8B */ | ||
349 | { 0xFF, 0xFF }, /* 8C */ | ||
350 | { 0xFF, 0x3F }, /* 8D */ | ||
351 | { 0xFF, 0xFF }, /* 8E */ | ||
352 | { 0xFF, 0x3F }, /* 8F */ | ||
353 | { 0xFF, 0x8F }, /* 90 */ | ||
354 | { 0xFF, 0xFF }, /* 91 */ | ||
355 | { 0xFF, 0x3F }, /* 92 */ | ||
356 | { 0xFF, 0xFF }, /* 93 */ | ||
357 | { 0xFF, 0xFF }, /* 94 */ | ||
358 | { 0xFF, 0x0F }, /* 95 */ | ||
359 | { 0xFF, 0x3F }, /* 96 */ | ||
360 | { 0xFF, 0x8C }, /* 97 */ | ||
361 | { 0x00, 0x00 }, /* 98 */ | ||
362 | { 0x00, 0x00 }, /* 99 */ | ||
363 | { 0x00, 0x00 }, /* 9A */ | ||
364 | { 0x00, 0x00 }, /* 9B */ | ||
365 | { 0x00, 0x00 }, /* 9C */ | ||
366 | { 0x00, 0x00 }, /* 9D */ | ||
367 | { 0x00, 0x00 }, /* 9E */ | ||
368 | { 0x00, 0x00 }, /* 9F */ | ||
369 | { 0x00, 0x00 }, /* A0 */ | ||
370 | { 0x00, 0x00 }, /* A1 */ | ||
371 | { 0x00, 0x00 }, /* A2 */ | ||
372 | { 0x00, 0x00 }, /* A3 */ | ||
373 | { 0x00, 0x00 }, /* A4 */ | ||
374 | { 0x00, 0x00 }, /* A5 */ | ||
375 | { 0x00, 0x00 }, /* A6 */ | ||
376 | { 0x00, 0x00 }, /* A7 */ | ||
377 | { 0x00, 0x00 }, /* A8 */ | ||
378 | { 0x00, 0x00 }, /* A9 */ | ||
379 | { 0x00, 0x00 }, /* AA */ | ||
380 | { 0x00, 0x00 }, /* AB */ | ||
381 | { 0x00, 0x00 }, /* AC */ | ||
382 | { 0x00, 0x00 }, /* AD */ | ||
383 | { 0x00, 0x00 }, /* AE */ | ||
384 | { 0x00, 0x00 }, /* AF */ | ||
385 | { 0x00, 0x00 }, /* B0 */ | ||
386 | { 0x00, 0x00 }, /* B1 */ | ||
387 | { 0x00, 0x00 }, /* B2 */ | ||
388 | { 0x00, 0x00 }, /* B3 */ | ||
389 | { 0x00, 0x00 }, /* B4 */ | ||
390 | { 0x00, 0x00 }, /* B5 */ | ||
391 | { 0x00, 0x00 }, /* B6 */ | ||
392 | { 0x00, 0x00 }, /* B7 */ | ||
393 | { 0x00, 0x00 }, /* B8 */ | ||
394 | { 0x00, 0x00 }, /* B9 */ | ||
395 | { 0x00, 0x00 }, /* BA */ | ||
396 | { 0x00, 0x00 }, /* BB */ | ||
397 | { 0x00, 0x00 }, /* BC */ | ||
398 | { 0x00, 0x00 }, /* BD */ | ||
399 | { 0x00, 0x00 }, /* BE */ | ||
400 | { 0x00, 0x00 }, /* BF */ | ||
401 | { 0x00, 0x00 }, /* C0 */ | ||
402 | { 0x00, 0x00 }, /* C1 */ | ||
403 | { 0x00, 0x00 }, /* C2 */ | ||
404 | { 0x00, 0x00 }, /* C3 */ | ||
405 | { 0x00, 0x00 }, /* C4 */ | ||
406 | { 0x00, 0x00 }, /* C5 */ | ||
407 | { 0x00, 0x00 }, /* C6 */ | ||
408 | { 0x00, 0x00 }, /* C7 */ | ||
409 | { 0x00, 0x00 }, /* C8 */ | ||
410 | { 0x00, 0x00 }, /* C9 */ | ||
411 | { 0x00, 0x00 }, /* CA */ | ||
412 | { 0x00, 0x00 }, /* CB */ | ||
413 | { 0x00, 0x00 }, /* CC */ | ||
414 | { 0x00, 0x00 }, /* CD */ | ||
415 | { 0x00, 0x00 }, /* CE */ | ||
416 | { 0x00, 0x00 }, /* CF */ | ||
417 | { 0x00, 0x00 }, /* D0 */ | ||
418 | { 0x00, 0x00 }, /* D1 */ | ||
419 | { 0x00, 0x00 }, /* D2 */ | ||
420 | { 0x00, 0x00 }, /* D3 */ | ||
421 | { 0x00, 0x00 }, /* D4 */ | ||
422 | { 0x00, 0x00 }, /* D5 */ | ||
423 | { 0x00, 0x00 }, /* D6 */ | ||
424 | { 0x00, 0x00 }, /* D7 */ | ||
425 | { 0x00, 0x00 }, /* D8 */ | ||
426 | { 0x00, 0x00 }, /* D9 */ | ||
427 | { 0x00, 0x00 }, /* DA */ | ||
428 | { 0x00, 0x00 }, /* DB */ | ||
429 | { 0x00, 0x00 }, /* DC */ | ||
430 | { 0x00, 0x00 }, /* DD */ | ||
431 | { 0x00, 0x00 }, /* DE */ | ||
432 | { 0x00, 0x00 }, /* DF */ | ||
433 | { 0x00, 0x00 }, /* E0 */ | ||
434 | { 0x00, 0x00 }, /* E1 */ | ||
435 | { 0x00, 0x00 }, /* E2 */ | ||
436 | { 0x00, 0x00 }, /* E3 */ | ||
437 | { 0x00, 0x00 }, /* E4 */ | ||
438 | { 0x00, 0x00 }, /* E5 */ | ||
439 | { 0x00, 0x00 }, /* E6 */ | ||
440 | { 0x00, 0x00 }, /* E7 */ | ||
441 | { 0x00, 0x00 }, /* E8 */ | ||
442 | { 0x00, 0x00 }, /* E9 */ | ||
443 | { 0x00, 0x00 }, /* EA */ | ||
444 | { 0x00, 0x00 }, /* EB */ | ||
445 | { 0x00, 0x00 }, /* EC */ | ||
446 | { 0x00, 0x00 }, /* ED */ | ||
447 | { 0x00, 0x00 }, /* EE */ | ||
448 | { 0x00, 0x00 }, /* EF */ | ||
449 | { 0x00, 0x00 }, /* F0 */ | ||
450 | { 0x00, 0x00 }, /* F1 */ | ||
451 | { 0x00, 0x00 }, /* F2 */ | ||
452 | { 0x00, 0x00 }, /* F3 */ | ||
453 | { 0x00, 0x00 }, /* F4 */ | ||
454 | { 0x00, 0x00 }, /* F5 */ | ||
455 | { 0x00, 0x00 }, /* F6 */ | ||
456 | { 0x00, 0x00 }, /* F7 */ | ||
457 | { 0x00, 0x00 }, /* F8 */ | ||
458 | { 0x00, 0x00 }, /* F9 */ | ||
459 | { 0x00, 0x00 }, /* FA */ | ||
460 | { 0x00, 0x00 }, /* FB */ | ||
461 | { 0x00, 0x00 }, /* FC */ | ||
462 | { 0x00, 0x00 }, /* FD */ | ||
463 | { 0x00, 0x00 }, /* FE */ | ||
464 | { 0xFF, 0x00 }, /* FF */ | ||
465 | }; | ||
466 | |||
467 | static bool max98095_readable(struct device *dev, unsigned int reg) | 205 | static bool max98095_readable(struct device *dev, unsigned int reg) |
468 | { | 206 | { |
469 | if (reg >= M98095_REG_CNT) | 207 | switch (reg) { |
470 | return 0; | 208 | case M98095_001_HOST_INT_STS ... M98095_097_PWR_SYS: |
471 | return max98095_access[reg].readable != 0; | 209 | case M98095_0FF_REV_ID: |
210 | return true; | ||
211 | default: | ||
212 | return false; | ||
213 | } | ||
472 | } | 214 | } |
473 | 215 | ||
474 | static bool max98095_volatile(struct device *dev, unsigned int reg) | 216 | static bool max98095_writeable(struct device *dev, unsigned int reg) |
475 | { | 217 | { |
476 | if (reg > M98095_REG_MAX_CACHED) | ||
477 | return 1; | ||
478 | |||
479 | switch (reg) { | 218 | switch (reg) { |
480 | case M98095_000_HOST_DATA: | 219 | case M98095_00F_HOST_CFG ... M98095_097_PWR_SYS: |
481 | case M98095_001_HOST_INT_STS: | 220 | return true; |
482 | case M98095_002_HOST_RSP_STS: | 221 | default: |
483 | case M98095_003_HOST_CMD_STS: | 222 | return false; |
484 | case M98095_004_CODEC_STS: | ||
485 | case M98095_005_DAI1_ALC_STS: | ||
486 | case M98095_006_DAI2_ALC_STS: | ||
487 | case M98095_007_JACK_AUTO_STS: | ||
488 | case M98095_008_JACK_MANUAL_STS: | ||
489 | case M98095_009_JACK_VBAT_STS: | ||
490 | case M98095_00A_ACC_ADC_STS: | ||
491 | case M98095_00B_MIC_NG_AGC_STS: | ||
492 | case M98095_00C_SPK_L_VOLT_STS: | ||
493 | case M98095_00D_SPK_R_VOLT_STS: | ||
494 | case M98095_00E_TEMP_SENSOR_STS: | ||
495 | return 1; | ||
496 | } | 223 | } |
224 | } | ||
497 | 225 | ||
498 | return 0; | 226 | static bool max98095_volatile(struct device *dev, unsigned int reg) |
227 | { | ||
228 | switch (reg) { | ||
229 | case M98095_000_HOST_DATA ... M98095_00E_TEMP_SENSOR_STS: | ||
230 | case M98095_REG_MAX_CACHED + 1 ... M98095_0FF_REV_ID: | ||
231 | return true; | ||
232 | default: | ||
233 | return false; | ||
234 | } | ||
499 | } | 235 | } |
500 | 236 | ||
501 | static const struct regmap_config max98095_regmap = { | 237 | static const struct regmap_config max98095_regmap = { |
@@ -508,6 +244,7 @@ static const struct regmap_config max98095_regmap = { | |||
508 | .cache_type = REGCACHE_RBTREE, | 244 | .cache_type = REGCACHE_RBTREE, |
509 | 245 | ||
510 | .readable_reg = max98095_readable, | 246 | .readable_reg = max98095_readable, |
247 | .writeable_reg = max98095_writeable, | ||
511 | .volatile_reg = max98095_volatile, | 248 | .volatile_reg = max98095_volatile, |
512 | }; | 249 | }; |
513 | 250 | ||
@@ -661,48 +398,43 @@ static int max98095_mic2pre_get(struct snd_kcontrol *kcontrol, | |||
661 | return 0; | 398 | return 0; |
662 | } | 399 | } |
663 | 400 | ||
664 | static const unsigned int max98095_micboost_tlv[] = { | 401 | static const DECLARE_TLV_DB_RANGE(max98095_micboost_tlv, |
665 | TLV_DB_RANGE_HEAD(2), | ||
666 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), | 402 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), |
667 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), | 403 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0) |
668 | }; | 404 | ); |
669 | 405 | ||
670 | static const DECLARE_TLV_DB_SCALE(max98095_mic_tlv, 0, 100, 0); | 406 | static const DECLARE_TLV_DB_SCALE(max98095_mic_tlv, 0, 100, 0); |
671 | static const DECLARE_TLV_DB_SCALE(max98095_adc_tlv, -1200, 100, 0); | 407 | static const DECLARE_TLV_DB_SCALE(max98095_adc_tlv, -1200, 100, 0); |
672 | static const DECLARE_TLV_DB_SCALE(max98095_adcboost_tlv, 0, 600, 0); | 408 | static const DECLARE_TLV_DB_SCALE(max98095_adcboost_tlv, 0, 600, 0); |
673 | 409 | ||
674 | static const unsigned int max98095_hp_tlv[] = { | 410 | static const DECLARE_TLV_DB_RANGE(max98095_hp_tlv, |
675 | TLV_DB_RANGE_HEAD(5), | ||
676 | 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), | 411 | 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), |
677 | 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), | 412 | 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), |
678 | 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), | 413 | 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), |
679 | 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), | 414 | 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), |
680 | 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0), | 415 | 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0) |
681 | }; | 416 | ); |
682 | 417 | ||
683 | static const unsigned int max98095_spk_tlv[] = { | 418 | static const DECLARE_TLV_DB_RANGE(max98095_spk_tlv, |
684 | TLV_DB_RANGE_HEAD(4), | ||
685 | 0, 10, TLV_DB_SCALE_ITEM(-5900, 400, 0), | 419 | 0, 10, TLV_DB_SCALE_ITEM(-5900, 400, 0), |
686 | 11, 18, TLV_DB_SCALE_ITEM(-1700, 200, 0), | 420 | 11, 18, TLV_DB_SCALE_ITEM(-1700, 200, 0), |
687 | 19, 27, TLV_DB_SCALE_ITEM(-200, 100, 0), | 421 | 19, 27, TLV_DB_SCALE_ITEM(-200, 100, 0), |
688 | 28, 39, TLV_DB_SCALE_ITEM(650, 50, 0), | 422 | 28, 39, TLV_DB_SCALE_ITEM(650, 50, 0) |
689 | }; | 423 | ); |
690 | 424 | ||
691 | static const unsigned int max98095_rcv_lout_tlv[] = { | 425 | static const DECLARE_TLV_DB_RANGE(max98095_rcv_lout_tlv, |
692 | TLV_DB_RANGE_HEAD(5), | ||
693 | 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), | 426 | 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), |
694 | 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), | 427 | 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), |
695 | 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), | 428 | 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), |
696 | 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), | 429 | 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), |
697 | 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0), | 430 | 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0) |
698 | }; | 431 | ); |
699 | 432 | ||
700 | static const unsigned int max98095_lin_tlv[] = { | 433 | static const DECLARE_TLV_DB_RANGE(max98095_lin_tlv, |
701 | TLV_DB_RANGE_HEAD(3), | ||
702 | 0, 2, TLV_DB_SCALE_ITEM(-600, 300, 0), | 434 | 0, 2, TLV_DB_SCALE_ITEM(-600, 300, 0), |
703 | 3, 3, TLV_DB_SCALE_ITEM(300, 1100, 0), | 435 | 3, 3, TLV_DB_SCALE_ITEM(300, 1100, 0), |
704 | 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0), | 436 | 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0) |
705 | }; | 437 | ); |
706 | 438 | ||
707 | static const struct snd_kcontrol_new max98095_snd_controls[] = { | 439 | static const struct snd_kcontrol_new max98095_snd_controls[] = { |
708 | 440 | ||
@@ -1653,10 +1385,13 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec, | |||
1653 | if (IS_ERR(max98095->mclk)) | 1385 | if (IS_ERR(max98095->mclk)) |
1654 | break; | 1386 | break; |
1655 | 1387 | ||
1656 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) | 1388 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) { |
1657 | clk_disable_unprepare(max98095->mclk); | 1389 | clk_disable_unprepare(max98095->mclk); |
1658 | else | 1390 | } else { |
1659 | clk_prepare_enable(max98095->mclk); | 1391 | ret = clk_prepare_enable(max98095->mclk); |
1392 | if (ret) | ||
1393 | return ret; | ||
1394 | } | ||
1660 | break; | 1395 | break; |
1661 | 1396 | ||
1662 | case SND_SOC_BIAS_STANDBY: | 1397 | case SND_SOC_BIAS_STANDBY: |
@@ -2431,7 +2166,6 @@ MODULE_DEVICE_TABLE(of, max98095_of_match); | |||
2431 | static struct i2c_driver max98095_i2c_driver = { | 2166 | static struct i2c_driver max98095_i2c_driver = { |
2432 | .driver = { | 2167 | .driver = { |
2433 | .name = "max98095", | 2168 | .name = "max98095", |
2434 | .owner = THIS_MODULE, | ||
2435 | .of_match_table = of_match_ptr(max98095_of_match), | 2169 | .of_match_table = of_match_ptr(max98095_of_match), |
2436 | }, | 2170 | }, |
2437 | .probe = max98095_i2c_probe, | 2171 | .probe = max98095_i2c_probe, |
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index 3a2fda08a893..f5e3dce2633a 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c | |||
@@ -31,6 +31,9 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, | |||
31 | { | 31 | { |
32 | struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai); | 32 | struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai); |
33 | 33 | ||
34 | if (!sdmode) | ||
35 | return 0; | ||
36 | |||
34 | switch (cmd) { | 37 | switch (cmd) { |
35 | case SNDRV_PCM_TRIGGER_START: | 38 | case SNDRV_PCM_TRIGGER_START: |
36 | case SNDRV_PCM_TRIGGER_RESUME: | 39 | case SNDRV_PCM_TRIGGER_RESUME: |
@@ -48,24 +51,21 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, | |||
48 | } | 51 | } |
49 | 52 | ||
50 | static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = { | 53 | static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = { |
51 | SND_SOC_DAPM_DAC("SDMode", NULL, SND_SOC_NOPM, 0, 0), | ||
52 | SND_SOC_DAPM_OUTPUT("Speaker"), | 54 | SND_SOC_DAPM_OUTPUT("Speaker"), |
53 | }; | 55 | }; |
54 | 56 | ||
55 | static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { | 57 | static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { |
56 | {"Speaker", NULL, "SDMode"}, | 58 | {"Speaker", NULL, "HiFi Playback"}, |
57 | }; | 59 | }; |
58 | 60 | ||
59 | static int max98357a_codec_probe(struct snd_soc_codec *codec) | 61 | static int max98357a_codec_probe(struct snd_soc_codec *codec) |
60 | { | 62 | { |
61 | struct gpio_desc *sdmode; | 63 | struct gpio_desc *sdmode; |
62 | 64 | ||
63 | sdmode = devm_gpiod_get(codec->dev, "sdmode", GPIOD_OUT_LOW); | 65 | sdmode = devm_gpiod_get_optional(codec->dev, "sdmode", GPIOD_OUT_LOW); |
64 | if (IS_ERR(sdmode)) { | 66 | if (IS_ERR(sdmode)) |
65 | dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n", | ||
66 | __func__, PTR_ERR(sdmode)); | ||
67 | return PTR_ERR(sdmode); | 67 | return PTR_ERR(sdmode); |
68 | } | 68 | |
69 | snd_soc_codec_set_drvdata(codec, sdmode); | 69 | snd_soc_codec_set_drvdata(codec, sdmode); |
70 | 70 | ||
71 | return 0; | 71 | return 0; |
@@ -79,7 +79,7 @@ static struct snd_soc_codec_driver max98357a_codec_driver = { | |||
79 | .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), | 79 | .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static struct snd_soc_dai_ops max98357a_dai_ops = { | 82 | static const struct snd_soc_dai_ops max98357a_dai_ops = { |
83 | .trigger = max98357a_daiops_trigger, | 83 | .trigger = max98357a_daiops_trigger, |
84 | }; | 84 | }; |
85 | 85 | ||
@@ -104,15 +104,8 @@ static struct snd_soc_dai_driver max98357a_dai_driver = { | |||
104 | 104 | ||
105 | static int max98357a_platform_probe(struct platform_device *pdev) | 105 | static int max98357a_platform_probe(struct platform_device *pdev) |
106 | { | 106 | { |
107 | int ret; | 107 | return snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver, |
108 | |||
109 | ret = snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver, | ||
110 | &max98357a_dai_driver, 1); | 108 | &max98357a_dai_driver, 1); |
111 | if (ret) | ||
112 | dev_err(&pdev->dev, "%s() error registering codec driver: %d\n", | ||
113 | __func__, ret); | ||
114 | |||
115 | return ret; | ||
116 | } | 109 | } |
117 | 110 | ||
118 | static int max98357a_platform_remove(struct platform_device *pdev) | 111 | static int max98357a_platform_remove(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 481d58f1cb3f..c14a79d026a1 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c | |||
@@ -67,13 +67,12 @@ static const struct regmap_config max9850_regmap = { | |||
67 | .cache_type = REGCACHE_RBTREE, | 67 | .cache_type = REGCACHE_RBTREE, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | static const unsigned int max9850_tlv[] = { | 70 | static const DECLARE_TLV_DB_RANGE(max9850_tlv, |
71 | TLV_DB_RANGE_HEAD(4), | ||
72 | 0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0), | 71 | 0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0), |
73 | 0x20, 0x33, TLV_DB_SCALE_ITEM(-4150, 200, 0), | 72 | 0x20, 0x33, TLV_DB_SCALE_ITEM(-4150, 200, 0), |
74 | 0x34, 0x37, TLV_DB_SCALE_ITEM(-150, 100, 0), | 73 | 0x34, 0x37, TLV_DB_SCALE_ITEM(-150, 100, 0), |
75 | 0x38, 0x3f, TLV_DB_SCALE_ITEM(250, 50, 0), | 74 | 0x38, 0x3f, TLV_DB_SCALE_ITEM(250, 50, 0) |
76 | }; | 75 | ); |
77 | 76 | ||
78 | static const struct snd_kcontrol_new max9850_controls[] = { | 77 | static const struct snd_kcontrol_new max9850_controls[] = { |
79 | SOC_SINGLE_TLV("Headphone Volume", MAX9850_VOLUME, 0, 0x3f, 1, max9850_tlv), | 78 | SOC_SINGLE_TLV("Headphone Volume", MAX9850_VOLUME, 0, 0x3f, 1, max9850_tlv), |
@@ -352,7 +351,6 @@ MODULE_DEVICE_TABLE(i2c, max9850_i2c_id); | |||
352 | static struct i2c_driver max9850_i2c_driver = { | 351 | static struct i2c_driver max9850_i2c_driver = { |
353 | .driver = { | 352 | .driver = { |
354 | .name = "max9850", | 353 | .name = "max9850", |
355 | .owner = THIS_MODULE, | ||
356 | }, | 354 | }, |
357 | .probe = max9850_i2c_probe, | 355 | .probe = max9850_i2c_probe, |
358 | .remove = max9850_i2c_remove, | 356 | .remove = max9850_i2c_remove, |
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 29549cdbf4c1..61cc18e35efb 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c | |||
@@ -20,9 +20,7 @@ | |||
20 | 20 | ||
21 | #include "max9877.h" | 21 | #include "max9877.h" |
22 | 22 | ||
23 | static struct regmap *regmap; | 23 | static const struct reg_default max9877_regs[] = { |
24 | |||
25 | static struct reg_default max9877_regs[] = { | ||
26 | { 0, 0x40 }, | 24 | { 0, 0x40 }, |
27 | { 1, 0x00 }, | 25 | { 1, 0x00 }, |
28 | { 2, 0x00 }, | 26 | { 2, 0x00 }, |
@@ -30,19 +28,17 @@ static struct reg_default max9877_regs[] = { | |||
30 | { 4, 0x49 }, | 28 | { 4, 0x49 }, |
31 | }; | 29 | }; |
32 | 30 | ||
33 | static const unsigned int max9877_pgain_tlv[] = { | 31 | static const DECLARE_TLV_DB_RANGE(max9877_pgain_tlv, |
34 | TLV_DB_RANGE_HEAD(2), | ||
35 | 0, 1, TLV_DB_SCALE_ITEM(0, 900, 0), | 32 | 0, 1, TLV_DB_SCALE_ITEM(0, 900, 0), |
36 | 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0), | 33 | 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0) |
37 | }; | 34 | ); |
38 | 35 | ||
39 | static const unsigned int max9877_output_tlv[] = { | 36 | static const DECLARE_TLV_DB_RANGE(max9877_output_tlv, |
40 | TLV_DB_RANGE_HEAD(4), | ||
41 | 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), | 37 | 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), |
42 | 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), | 38 | 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), |
43 | 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), | 39 | 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), |
44 | 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), | 40 | 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0) |
45 | }; | 41 | ); |
46 | 42 | ||
47 | static const char *max9877_out_mode[] = { | 43 | static const char *max9877_out_mode[] = { |
48 | "INA -> SPK", | 44 | "INA -> SPK", |
@@ -123,7 +119,7 @@ static const struct snd_soc_dapm_route max9877_dapm_routes[] = { | |||
123 | { "HPR", NULL, "SHDN" }, | 119 | { "HPR", NULL, "SHDN" }, |
124 | }; | 120 | }; |
125 | 121 | ||
126 | static const struct snd_soc_codec_driver max9877_codec = { | 122 | static const struct snd_soc_component_driver max9877_component_driver = { |
127 | .controls = max9877_controls, | 123 | .controls = max9877_controls, |
128 | .num_controls = ARRAY_SIZE(max9877_controls), | 124 | .num_controls = ARRAY_SIZE(max9877_controls), |
129 | 125 | ||
@@ -145,6 +141,7 @@ static const struct regmap_config max9877_regmap = { | |||
145 | static int max9877_i2c_probe(struct i2c_client *client, | 141 | static int max9877_i2c_probe(struct i2c_client *client, |
146 | const struct i2c_device_id *id) | 142 | const struct i2c_device_id *id) |
147 | { | 143 | { |
144 | struct regmap *regmap; | ||
148 | int i; | 145 | int i; |
149 | 146 | ||
150 | regmap = devm_regmap_init_i2c(client, &max9877_regmap); | 147 | regmap = devm_regmap_init_i2c(client, &max9877_regmap); |
@@ -155,14 +152,8 @@ static int max9877_i2c_probe(struct i2c_client *client, | |||
155 | for (i = 0; i < ARRAY_SIZE(max9877_regs); i++) | 152 | for (i = 0; i < ARRAY_SIZE(max9877_regs); i++) |
156 | regmap_write(regmap, max9877_regs[i].reg, max9877_regs[i].def); | 153 | regmap_write(regmap, max9877_regs[i].reg, max9877_regs[i].def); |
157 | 154 | ||
158 | return snd_soc_register_codec(&client->dev, &max9877_codec, NULL, 0); | 155 | return devm_snd_soc_register_component(&client->dev, |
159 | } | 156 | &max9877_component_driver, NULL, 0); |
160 | |||
161 | static int max9877_i2c_remove(struct i2c_client *client) | ||
162 | { | ||
163 | snd_soc_unregister_codec(&client->dev); | ||
164 | |||
165 | return 0; | ||
166 | } | 157 | } |
167 | 158 | ||
168 | static const struct i2c_device_id max9877_i2c_id[] = { | 159 | static const struct i2c_device_id max9877_i2c_id[] = { |
@@ -174,10 +165,8 @@ MODULE_DEVICE_TABLE(i2c, max9877_i2c_id); | |||
174 | static struct i2c_driver max9877_i2c_driver = { | 165 | static struct i2c_driver max9877_i2c_driver = { |
175 | .driver = { | 166 | .driver = { |
176 | .name = "max9877", | 167 | .name = "max9877", |
177 | .owner = THIS_MODULE, | ||
178 | }, | 168 | }, |
179 | .probe = max9877_i2c_probe, | 169 | .probe = max9877_i2c_probe, |
180 | .remove = max9877_i2c_remove, | ||
181 | .id_table = max9877_i2c_id, | 170 | .id_table = max9877_i2c_id, |
182 | }; | 171 | }; |
183 | 172 | ||
diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c index aad664225dc3..5990de317999 100644 --- a/sound/soc/codecs/max98925.c +++ b/sound/soc/codecs/max98925.c | |||
@@ -271,8 +271,6 @@ static inline int max98925_rate_value(struct snd_soc_codec *codec, | |||
271 | break; | 271 | break; |
272 | } | 272 | } |
273 | } | 273 | } |
274 | dev_dbg(codec->dev, "%s: sample rate is %d, returning %d\n", | ||
275 | __func__, rate_table[i].rate, *value); | ||
276 | return ret; | 274 | return ret; |
277 | } | 275 | } |
278 | 276 | ||
@@ -432,7 +430,7 @@ static int max98925_dai_hw_params(struct snd_pcm_substream *substream, | |||
432 | struct snd_soc_codec *codec = dai->codec; | 430 | struct snd_soc_codec *codec = dai->codec; |
433 | struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec); | 431 | struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec); |
434 | 432 | ||
435 | switch (snd_pcm_format_width(params_format(params))) { | 433 | switch (params_width(params)) { |
436 | case 16: | 434 | case 16: |
437 | regmap_update_bits(max98925->regmap, | 435 | regmap_update_bits(max98925->regmap, |
438 | MAX98925_FORMAT, | 436 | MAX98925_FORMAT, |
@@ -523,7 +521,6 @@ static int max98925_probe(struct snd_soc_codec *codec) | |||
523 | struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec); | 521 | struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec); |
524 | 522 | ||
525 | max98925->codec = codec; | 523 | max98925->codec = codec; |
526 | codec->control_data = max98925->regmap; | ||
527 | regmap_write(max98925->regmap, MAX98925_GLOBAL_ENABLE, 0x00); | 524 | regmap_write(max98925->regmap, MAX98925_GLOBAL_ENABLE, 0x00); |
528 | /* It's not the default but we need to set DAI_DLY */ | 525 | /* It's not the default but we need to set DAI_DLY */ |
529 | regmap_write(max98925->regmap, | 526 | regmap_write(max98925->regmap, |
@@ -639,7 +636,6 @@ MODULE_DEVICE_TABLE(of, max98925_of_match); | |||
639 | static struct i2c_driver max98925_i2c_driver = { | 636 | static struct i2c_driver max98925_i2c_driver = { |
640 | .driver = { | 637 | .driver = { |
641 | .name = "max98925", | 638 | .name = "max98925", |
642 | .owner = THIS_MODULE, | ||
643 | .of_match_table = of_match_ptr(max98925_of_match), | 639 | .of_match_table = of_match_ptr(max98925_of_match), |
644 | .pm = NULL, | 640 | .pm = NULL, |
645 | }, | 641 | }, |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 3d44fc50e4d0..3e770cbe7f0f 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -650,14 +650,14 @@ static int mc13783_remove(struct snd_soc_codec *codec) | |||
650 | #define MC13783_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 650 | #define MC13783_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
651 | SNDRV_PCM_FMTBIT_S24_LE) | 651 | SNDRV_PCM_FMTBIT_S24_LE) |
652 | 652 | ||
653 | static struct snd_soc_dai_ops mc13783_ops_dac = { | 653 | static const struct snd_soc_dai_ops mc13783_ops_dac = { |
654 | .hw_params = mc13783_pcm_hw_params_dac, | 654 | .hw_params = mc13783_pcm_hw_params_dac, |
655 | .set_fmt = mc13783_set_fmt_async, | 655 | .set_fmt = mc13783_set_fmt_async, |
656 | .set_sysclk = mc13783_set_sysclk_dac, | 656 | .set_sysclk = mc13783_set_sysclk_dac, |
657 | .set_tdm_slot = mc13783_set_tdm_slot_dac, | 657 | .set_tdm_slot = mc13783_set_tdm_slot_dac, |
658 | }; | 658 | }; |
659 | 659 | ||
660 | static struct snd_soc_dai_ops mc13783_ops_codec = { | 660 | static const struct snd_soc_dai_ops mc13783_ops_codec = { |
661 | .hw_params = mc13783_pcm_hw_params_codec, | 661 | .hw_params = mc13783_pcm_hw_params_codec, |
662 | .set_fmt = mc13783_set_fmt_async, | 662 | .set_fmt = mc13783_set_fmt_async, |
663 | .set_sysclk = mc13783_set_sysclk_codec, | 663 | .set_sysclk = mc13783_set_sysclk_codec, |
@@ -698,7 +698,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = { | |||
698 | }, | 698 | }, |
699 | }; | 699 | }; |
700 | 700 | ||
701 | static struct snd_soc_dai_ops mc13783_ops_sync = { | 701 | static const struct snd_soc_dai_ops mc13783_ops_sync = { |
702 | .hw_params = mc13783_pcm_hw_params_sync, | 702 | .hw_params = mc13783_pcm_hw_params_sync, |
703 | .set_fmt = mc13783_set_fmt_sync, | 703 | .set_fmt = mc13783_set_fmt_sync, |
704 | .set_sysclk = mc13783_set_sysclk_sync, | 704 | .set_sysclk = mc13783_set_sysclk_sync, |
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index b74118e019fb..f561c78b9e0e 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c | |||
@@ -199,7 +199,7 @@ static const struct clk_coeff coeff_div[] = { | |||
199 | {12288000, 48000, 0xc, 0x0, 0x30, 0x0, 0x4}, | 199 | {12288000, 48000, 0xc, 0x0, 0x30, 0x0, 0x4}, |
200 | }; | 200 | }; |
201 | 201 | ||
202 | static struct reg_default ml26124_reg[] = { | 202 | static const struct reg_default ml26124_reg[] = { |
203 | /* CLOCK control Register */ | 203 | /* CLOCK control Register */ |
204 | {0x00, 0x00 }, /* Sampling Rate */ | 204 | {0x00, 0x00 }, /* Sampling Rate */ |
205 | {0x02, 0x00}, /* PLL NL */ | 205 | {0x02, 0x00}, /* PLL NL */ |
@@ -597,7 +597,6 @@ MODULE_DEVICE_TABLE(i2c, ml26124_i2c_id); | |||
597 | static struct i2c_driver ml26124_i2c_driver = { | 597 | static struct i2c_driver ml26124_i2c_driver = { |
598 | .driver = { | 598 | .driver = { |
599 | .name = "ml26124", | 599 | .name = "ml26124", |
600 | .owner = THIS_MODULE, | ||
601 | }, | 600 | }, |
602 | .probe = ml26124_i2c_probe, | 601 | .probe = ml26124_i2c_probe, |
603 | .remove = ml26124_i2c_remove, | 602 | .remove = ml26124_i2c_remove, |
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index e7ba557979cb..58325234285c 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c | |||
@@ -95,17 +95,22 @@ static int pcm1681_set_deemph(struct snd_soc_codec *codec) | |||
95 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); | 95 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); |
96 | int i = 0, val = -1, enable = 0; | 96 | int i = 0, val = -1, enable = 0; |
97 | 97 | ||
98 | if (priv->deemph) | 98 | if (priv->deemph) { |
99 | for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++) | 99 | for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++) { |
100 | if (pcm1681_deemph[i] == priv->rate) | 100 | if (pcm1681_deemph[i] == priv->rate) { |
101 | val = i; | 101 | val = i; |
102 | break; | ||
103 | } | ||
104 | } | ||
105 | } | ||
102 | 106 | ||
103 | if (val != -1) { | 107 | if (val != -1) { |
104 | regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, | 108 | regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, |
105 | PCM1681_DEEMPH_RATE_MASK, val << 3); | 109 | PCM1681_DEEMPH_RATE_MASK, val << 3); |
106 | enable = 1; | 110 | enable = 1; |
107 | } else | 111 | } else { |
108 | enable = 0; | 112 | enable = 0; |
113 | } | ||
109 | 114 | ||
110 | /* enable/disable deemphasis functionality */ | 115 | /* enable/disable deemphasis functionality */ |
111 | return regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, | 116 | return regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, |
@@ -330,7 +335,6 @@ static int pcm1681_i2c_remove(struct i2c_client *client) | |||
330 | static struct i2c_driver pcm1681_i2c_driver = { | 335 | static struct i2c_driver pcm1681_i2c_driver = { |
331 | .driver = { | 336 | .driver = { |
332 | .name = "pcm1681", | 337 | .name = "pcm1681", |
333 | .owner = THIS_MODULE, | ||
334 | .of_match_table = of_match_ptr(pcm1681_dt_ids), | 338 | .of_match_table = of_match_ptr(pcm1681_dt_ids), |
335 | }, | 339 | }, |
336 | .id_table = pcm1681_i2c_id, | 340 | .id_table = pcm1681_i2c_id, |
diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c index dcdfac0ffeb1..dbff416e38be 100644 --- a/sound/soc/codecs/pcm512x-i2c.c +++ b/sound/soc/codecs/pcm512x-i2c.c | |||
@@ -67,7 +67,6 @@ static struct i2c_driver pcm512x_i2c_driver = { | |||
67 | .id_table = pcm512x_i2c_id, | 67 | .id_table = pcm512x_i2c_id, |
68 | .driver = { | 68 | .driver = { |
69 | .name = "pcm512x", | 69 | .name = "pcm512x", |
70 | .owner = THIS_MODULE, | ||
71 | .of_match_table = pcm512x_of_match, | 70 | .of_match_table = pcm512x_of_match, |
72 | .pm = &pcm512x_pm_ops, | 71 | .pm = &pcm512x_pm_ops, |
73 | }, | 72 | }, |
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index de16429f0a43..047c48953a20 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c | |||
@@ -1117,7 +1117,7 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream, | |||
1117 | params_rate(params), | 1117 | params_rate(params), |
1118 | params_channels(params)); | 1118 | params_channels(params)); |
1119 | 1119 | ||
1120 | switch (snd_pcm_format_width(params_format(params))) { | 1120 | switch (params_width(params)) { |
1121 | case 16: | 1121 | case 16: |
1122 | alen = PCM512x_ALEN_16; | 1122 | alen = PCM512x_ALEN_16; |
1123 | break; | 1123 | break; |
@@ -1132,7 +1132,7 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream, | |||
1132 | break; | 1132 | break; |
1133 | default: | 1133 | default: |
1134 | dev_err(codec->dev, "Bad frame size: %d\n", | 1134 | dev_err(codec->dev, "Bad frame size: %d\n", |
1135 | snd_pcm_format_width(params_format(params))); | 1135 | params_width(params)); |
1136 | return -EINVAL; | 1136 | return -EINVAL; |
1137 | } | 1137 | } |
1138 | 1138 | ||
diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c index 56650d6c2f53..aca479fa7670 100644 --- a/sound/soc/codecs/rl6231.c +++ b/sound/soc/codecs/rl6231.c | |||
@@ -11,38 +11,98 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/regmap.h> | ||
14 | 15 | ||
15 | #include "rl6231.h" | 16 | #include "rl6231.h" |
16 | 17 | ||
17 | /** | 18 | /** |
18 | * rl6231_calc_dmic_clk - Calculate the parameter of dmic. | 19 | * rl6231_get_pre_div - Return the value of pre divider. |
20 | * | ||
21 | * @map: map for setting. | ||
22 | * @reg: register. | ||
23 | * @sft: shift. | ||
24 | * | ||
25 | * Return the value of pre divider from given register value. | ||
26 | * Return negative error code for unexpected register value. | ||
27 | */ | ||
28 | int rl6231_get_pre_div(struct regmap *map, unsigned int reg, int sft) | ||
29 | { | ||
30 | int pd, val; | ||
31 | |||
32 | regmap_read(map, reg, &val); | ||
33 | |||
34 | val = (val >> sft) & 0x7; | ||
35 | |||
36 | switch (val) { | ||
37 | case 0: | ||
38 | case 1: | ||
39 | case 2: | ||
40 | case 3: | ||
41 | pd = val + 1; | ||
42 | break; | ||
43 | case 4: | ||
44 | pd = 6; | ||
45 | break; | ||
46 | case 5: | ||
47 | pd = 8; | ||
48 | break; | ||
49 | case 6: | ||
50 | pd = 12; | ||
51 | break; | ||
52 | case 7: | ||
53 | pd = 16; | ||
54 | break; | ||
55 | default: | ||
56 | pd = -EINVAL; | ||
57 | break; | ||
58 | } | ||
59 | |||
60 | return pd; | ||
61 | } | ||
62 | EXPORT_SYMBOL_GPL(rl6231_get_pre_div); | ||
63 | |||
64 | /** | ||
65 | * rl6231_calc_dmic_clk - Calculate the frequency divider parameter of dmic. | ||
19 | * | 66 | * |
20 | * @rate: base clock rate. | 67 | * @rate: base clock rate. |
21 | * | 68 | * |
22 | * Choose dmic clock between 1MHz and 3MHz. | 69 | * Choose divider parameter that gives the highest possible DMIC frequency in |
23 | * It is better for clock to approximate 3MHz. | 70 | * 1MHz - 3MHz range. |
24 | */ | 71 | */ |
25 | int rl6231_calc_dmic_clk(int rate) | 72 | int rl6231_calc_dmic_clk(int rate) |
26 | { | 73 | { |
27 | int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL; | 74 | int div[] = {2, 3, 4, 6, 8, 12}; |
28 | int i, red, bound, temp; | 75 | int i; |
76 | |||
77 | if (rate < 1000000 * div[0]) { | ||
78 | pr_warn("Base clock rate %d is too low\n", rate); | ||
79 | return -EINVAL; | ||
80 | } | ||
29 | 81 | ||
30 | red = 3000000 * 12; | ||
31 | for (i = 0; i < ARRAY_SIZE(div); i++) { | 82 | for (i = 0; i < ARRAY_SIZE(div); i++) { |
32 | bound = div[i] * 3000000; | 83 | /* find divider that gives DMIC frequency below 3MHz */ |
33 | if (rate > bound) | 84 | if (3000000 * div[i] >= rate) |
34 | continue; | 85 | return i; |
35 | temp = bound - rate; | ||
36 | if (temp < red) { | ||
37 | red = temp; | ||
38 | idx = i; | ||
39 | } | ||
40 | } | 86 | } |
41 | 87 | ||
42 | return idx; | 88 | pr_warn("Base clock rate %d is too high\n", rate); |
89 | return -EINVAL; | ||
43 | } | 90 | } |
44 | EXPORT_SYMBOL_GPL(rl6231_calc_dmic_clk); | 91 | EXPORT_SYMBOL_GPL(rl6231_calc_dmic_clk); |
45 | 92 | ||
93 | struct pll_calc_map { | ||
94 | unsigned int pll_in; | ||
95 | unsigned int pll_out; | ||
96 | int k; | ||
97 | int n; | ||
98 | int m; | ||
99 | bool m_bp; | ||
100 | }; | ||
101 | |||
102 | static const struct pll_calc_map pll_preset_table[] = { | ||
103 | {19200000, 24576000, 3, 30, 3, false}, | ||
104 | }; | ||
105 | |||
46 | /** | 106 | /** |
47 | * rl6231_pll_calc - Calcualte PLL M/N/K code. | 107 | * rl6231_pll_calc - Calcualte PLL M/N/K code. |
48 | * @freq_in: external clock provided to codec. | 108 | * @freq_in: external clock provided to codec. |
@@ -57,7 +117,7 @@ int rl6231_pll_calc(const unsigned int freq_in, | |||
57 | const unsigned int freq_out, struct rl6231_pll_code *pll_code) | 117 | const unsigned int freq_out, struct rl6231_pll_code *pll_code) |
58 | { | 118 | { |
59 | int max_n = RL6231_PLL_N_MAX, max_m = RL6231_PLL_M_MAX; | 119 | int max_n = RL6231_PLL_N_MAX, max_m = RL6231_PLL_M_MAX; |
60 | int k, red, n_t, pll_out, in_t, out_t; | 120 | int i, k, red, n_t, pll_out, in_t, out_t; |
61 | int n = 0, m = 0, m_t = 0; | 121 | int n = 0, m = 0, m_t = 0; |
62 | int red_t = abs(freq_out - freq_in); | 122 | int red_t = abs(freq_out - freq_in); |
63 | bool bypass = false; | 123 | bool bypass = false; |
@@ -65,6 +125,18 @@ int rl6231_pll_calc(const unsigned int freq_in, | |||
65 | if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in) | 125 | if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in) |
66 | return -EINVAL; | 126 | return -EINVAL; |
67 | 127 | ||
128 | for (i = 0; i < ARRAY_SIZE(pll_preset_table); i++) { | ||
129 | if (freq_in == pll_preset_table[i].pll_in && | ||
130 | freq_out == pll_preset_table[i].pll_out) { | ||
131 | k = pll_preset_table[i].k; | ||
132 | m = pll_preset_table[i].m; | ||
133 | n = pll_preset_table[i].n; | ||
134 | bypass = pll_preset_table[i].m_bp; | ||
135 | pr_debug("Use preset PLL parameter table\n"); | ||
136 | goto code_find; | ||
137 | } | ||
138 | } | ||
139 | |||
68 | k = 100000000 / freq_out - 2; | 140 | k = 100000000 / freq_out - 2; |
69 | if (k > RL6231_PLL_K_MAX) | 141 | if (k > RL6231_PLL_K_MAX) |
70 | k = RL6231_PLL_K_MAX; | 142 | k = RL6231_PLL_K_MAX; |
diff --git a/sound/soc/codecs/rl6231.h b/sound/soc/codecs/rl6231.h index 0f7b057ed736..4c77b441fba2 100644 --- a/sound/soc/codecs/rl6231.h +++ b/sound/soc/codecs/rl6231.h | |||
@@ -30,5 +30,6 @@ int rl6231_calc_dmic_clk(int rate); | |||
30 | int rl6231_pll_calc(const unsigned int freq_in, | 30 | int rl6231_pll_calc(const unsigned int freq_in, |
31 | const unsigned int freq_out, struct rl6231_pll_code *pll_code); | 31 | const unsigned int freq_out, struct rl6231_pll_code *pll_code); |
32 | int rl6231_get_clk_info(int sclk, int rate); | 32 | int rl6231_get_clk_info(int sclk, int rate); |
33 | int rl6231_get_pre_div(struct regmap *map, unsigned int reg, int sft); | ||
33 | 34 | ||
34 | #endif /* __RL6231_H__ */ | 35 | #endif /* __RL6231_H__ */ |
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 5c43e263b2c1..bd9365885f73 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #define RT288_VENDOR_ID 0x10ec0288 | 38 | #define RT288_VENDOR_ID 0x10ec0288 |
39 | 39 | ||
40 | struct rt286_priv { | 40 | struct rt286_priv { |
41 | struct reg_default *index_cache; | 41 | const struct reg_default *index_cache; |
42 | int index_cache_size; | 42 | int index_cache_size; |
43 | struct regmap *regmap; | 43 | struct regmap *regmap; |
44 | struct snd_soc_codec *codec; | 44 | struct snd_soc_codec *codec; |
@@ -50,7 +50,7 @@ struct rt286_priv { | |||
50 | int clk_id; | 50 | int clk_id; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | static struct reg_default rt286_index_def[] = { | 53 | static const struct reg_default rt286_index_def[] = { |
54 | { 0x01, 0xaaaa }, | 54 | { 0x01, 0xaaaa }, |
55 | { 0x02, 0x8aaa }, | 55 | { 0x02, 0x8aaa }, |
56 | { 0x03, 0x0002 }, | 56 | { 0x03, 0x0002 }, |
@@ -1108,7 +1108,7 @@ static const struct acpi_device_id rt286_acpi_match[] = { | |||
1108 | }; | 1108 | }; |
1109 | MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); | 1109 | MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); |
1110 | 1110 | ||
1111 | static struct dmi_system_id force_combo_jack_table[] = { | 1111 | static const struct dmi_system_id force_combo_jack_table[] = { |
1112 | { | 1112 | { |
1113 | .ident = "Intel Wilson Beach", | 1113 | .ident = "Intel Wilson Beach", |
1114 | .matches = { | 1114 | .matches = { |
@@ -1118,7 +1118,7 @@ static struct dmi_system_id force_combo_jack_table[] = { | |||
1118 | { } | 1118 | { } |
1119 | }; | 1119 | }; |
1120 | 1120 | ||
1121 | static struct dmi_system_id dmi_dell_dino[] = { | 1121 | static const struct dmi_system_id dmi_dell_dino[] = { |
1122 | { | 1122 | { |
1123 | .ident = "Dell Dino", | 1123 | .ident = "Dell Dino", |
1124 | .matches = { | 1124 | .matches = { |
@@ -1157,7 +1157,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1157 | } | 1157 | } |
1158 | if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) { | 1158 | if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) { |
1159 | dev_err(&i2c->dev, | 1159 | dev_err(&i2c->dev, |
1160 | "Device with ID register %x is not rt286\n", val); | 1160 | "Device with ID register %#x is not rt286\n", val); |
1161 | return -ENODEV; | 1161 | return -ENODEV; |
1162 | } | 1162 | } |
1163 | 1163 | ||
@@ -1259,7 +1259,6 @@ static int rt286_i2c_remove(struct i2c_client *i2c) | |||
1259 | static struct i2c_driver rt286_i2c_driver = { | 1259 | static struct i2c_driver rt286_i2c_driver = { |
1260 | .driver = { | 1260 | .driver = { |
1261 | .name = "rt286", | 1261 | .name = "rt286", |
1262 | .owner = THIS_MODULE, | ||
1263 | .acpi_match_table = ACPI_PTR(rt286_acpi_match), | 1262 | .acpi_match_table = ACPI_PTR(rt286_acpi_match), |
1264 | }, | 1263 | }, |
1265 | .probe = rt286_i2c_probe, | 1264 | .probe = rt286_i2c_probe, |
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c new file mode 100644 index 000000000000..3c2f0f8d6266 --- /dev/null +++ b/sound/soc/codecs/rt298.c | |||
@@ -0,0 +1,1271 @@ | |||
1 | /* | ||
2 | * rt298.c -- RT298 ALSA SoC audio codec driver | ||
3 | * | ||
4 | * Copyright 2015 Realtek Semiconductor Corp. | ||
5 | * Author: Bard Liao <bardliao@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/acpi.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | #include <sound/jack.h> | ||
29 | #include <linux/workqueue.h> | ||
30 | #include <sound/rt298.h> | ||
31 | #include <sound/hda_verbs.h> | ||
32 | |||
33 | #include "rl6347a.h" | ||
34 | #include "rt298.h" | ||
35 | |||
36 | #define RT298_VENDOR_ID 0x10ec0298 | ||
37 | |||
38 | struct rt298_priv { | ||
39 | struct reg_default *index_cache; | ||
40 | int index_cache_size; | ||
41 | struct regmap *regmap; | ||
42 | struct snd_soc_codec *codec; | ||
43 | struct rt298_platform_data pdata; | ||
44 | struct i2c_client *i2c; | ||
45 | struct snd_soc_jack *jack; | ||
46 | struct delayed_work jack_detect_work; | ||
47 | int sys_clk; | ||
48 | int clk_id; | ||
49 | int is_hp_in; | ||
50 | }; | ||
51 | |||
52 | static struct reg_default rt298_index_def[] = { | ||
53 | { 0x01, 0xaaaa }, | ||
54 | { 0x02, 0x8aaa }, | ||
55 | { 0x03, 0x0002 }, | ||
56 | { 0x04, 0xaf01 }, | ||
57 | { 0x08, 0x000d }, | ||
58 | { 0x09, 0xd810 }, | ||
59 | { 0x0a, 0x0120 }, | ||
60 | { 0x0b, 0x0000 }, | ||
61 | { 0x0d, 0x2800 }, | ||
62 | { 0x0f, 0x0000 }, | ||
63 | { 0x19, 0x0a17 }, | ||
64 | { 0x20, 0x0020 }, | ||
65 | { 0x33, 0x0208 }, | ||
66 | { 0x46, 0x0300 }, | ||
67 | { 0x49, 0x0004 }, | ||
68 | { 0x4f, 0x50e9 }, | ||
69 | { 0x50, 0x2000 }, | ||
70 | { 0x63, 0x2902 }, | ||
71 | { 0x67, 0x1111 }, | ||
72 | { 0x68, 0x1016 }, | ||
73 | { 0x69, 0x273f }, | ||
74 | }; | ||
75 | #define INDEX_CACHE_SIZE ARRAY_SIZE(rt298_index_def) | ||
76 | |||
77 | static const struct reg_default rt298_reg[] = { | ||
78 | { 0x00170500, 0x00000400 }, | ||
79 | { 0x00220000, 0x00000031 }, | ||
80 | { 0x00239000, 0x0000007f }, | ||
81 | { 0x0023a000, 0x0000007f }, | ||
82 | { 0x00270500, 0x00000400 }, | ||
83 | { 0x00370500, 0x00000400 }, | ||
84 | { 0x00870500, 0x00000400 }, | ||
85 | { 0x00920000, 0x00000031 }, | ||
86 | { 0x00935000, 0x000000c3 }, | ||
87 | { 0x00936000, 0x000000c3 }, | ||
88 | { 0x00970500, 0x00000400 }, | ||
89 | { 0x00b37000, 0x00000097 }, | ||
90 | { 0x00b37200, 0x00000097 }, | ||
91 | { 0x00b37300, 0x00000097 }, | ||
92 | { 0x00c37000, 0x00000000 }, | ||
93 | { 0x00c37100, 0x00000080 }, | ||
94 | { 0x01270500, 0x00000400 }, | ||
95 | { 0x01370500, 0x00000400 }, | ||
96 | { 0x01371f00, 0x411111f0 }, | ||
97 | { 0x01439000, 0x00000080 }, | ||
98 | { 0x0143a000, 0x00000080 }, | ||
99 | { 0x01470700, 0x00000000 }, | ||
100 | { 0x01470500, 0x00000400 }, | ||
101 | { 0x01470c00, 0x00000000 }, | ||
102 | { 0x01470100, 0x00000000 }, | ||
103 | { 0x01837000, 0x00000000 }, | ||
104 | { 0x01870500, 0x00000400 }, | ||
105 | { 0x02050000, 0x00000000 }, | ||
106 | { 0x02139000, 0x00000080 }, | ||
107 | { 0x0213a000, 0x00000080 }, | ||
108 | { 0x02170100, 0x00000000 }, | ||
109 | { 0x02170500, 0x00000400 }, | ||
110 | { 0x02170700, 0x00000000 }, | ||
111 | { 0x02270100, 0x00000000 }, | ||
112 | { 0x02370100, 0x00000000 }, | ||
113 | { 0x01870700, 0x00000020 }, | ||
114 | { 0x00830000, 0x000000c3 }, | ||
115 | { 0x00930000, 0x000000c3 }, | ||
116 | { 0x01270700, 0x00000000 }, | ||
117 | }; | ||
118 | |||
119 | static bool rt298_volatile_register(struct device *dev, unsigned int reg) | ||
120 | { | ||
121 | switch (reg) { | ||
122 | case 0 ... 0xff: | ||
123 | case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): | ||
124 | case RT298_GET_HP_SENSE: | ||
125 | case RT298_GET_MIC1_SENSE: | ||
126 | case RT298_PROC_COEF: | ||
127 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0): | ||
128 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0): | ||
129 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0): | ||
130 | return true; | ||
131 | default: | ||
132 | return true; | ||
133 | } | ||
134 | |||
135 | |||
136 | } | ||
137 | |||
138 | static bool rt298_readable_register(struct device *dev, unsigned int reg) | ||
139 | { | ||
140 | switch (reg) { | ||
141 | case 0 ... 0xff: | ||
142 | case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): | ||
143 | case RT298_GET_HP_SENSE: | ||
144 | case RT298_GET_MIC1_SENSE: | ||
145 | case RT298_SET_AUDIO_POWER: | ||
146 | case RT298_SET_HPO_POWER: | ||
147 | case RT298_SET_SPK_POWER: | ||
148 | case RT298_SET_DMIC1_POWER: | ||
149 | case RT298_SPK_MUX: | ||
150 | case RT298_HPO_MUX: | ||
151 | case RT298_ADC0_MUX: | ||
152 | case RT298_ADC1_MUX: | ||
153 | case RT298_SET_MIC1: | ||
154 | case RT298_SET_PIN_HPO: | ||
155 | case RT298_SET_PIN_SPK: | ||
156 | case RT298_SET_PIN_DMIC1: | ||
157 | case RT298_SPK_EAPD: | ||
158 | case RT298_SET_AMP_GAIN_HPO: | ||
159 | case RT298_SET_DMIC2_DEFAULT: | ||
160 | case RT298_DACL_GAIN: | ||
161 | case RT298_DACR_GAIN: | ||
162 | case RT298_ADCL_GAIN: | ||
163 | case RT298_ADCR_GAIN: | ||
164 | case RT298_MIC_GAIN: | ||
165 | case RT298_SPOL_GAIN: | ||
166 | case RT298_SPOR_GAIN: | ||
167 | case RT298_HPOL_GAIN: | ||
168 | case RT298_HPOR_GAIN: | ||
169 | case RT298_F_DAC_SWITCH: | ||
170 | case RT298_F_RECMIX_SWITCH: | ||
171 | case RT298_REC_MIC_SWITCH: | ||
172 | case RT298_REC_I2S_SWITCH: | ||
173 | case RT298_REC_LINE_SWITCH: | ||
174 | case RT298_REC_BEEP_SWITCH: | ||
175 | case RT298_DAC_FORMAT: | ||
176 | case RT298_ADC_FORMAT: | ||
177 | case RT298_COEF_INDEX: | ||
178 | case RT298_PROC_COEF: | ||
179 | case RT298_SET_AMP_GAIN_ADC_IN1: | ||
180 | case RT298_SET_AMP_GAIN_ADC_IN2: | ||
181 | case RT298_SET_POWER(RT298_DAC_OUT1): | ||
182 | case RT298_SET_POWER(RT298_DAC_OUT2): | ||
183 | case RT298_SET_POWER(RT298_ADC_IN1): | ||
184 | case RT298_SET_POWER(RT298_ADC_IN2): | ||
185 | case RT298_SET_POWER(RT298_DMIC2): | ||
186 | case RT298_SET_POWER(RT298_MIC1): | ||
187 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0): | ||
188 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0): | ||
189 | case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0): | ||
190 | return true; | ||
191 | default: | ||
192 | return false; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | #ifdef CONFIG_PM | ||
197 | static void rt298_index_sync(struct snd_soc_codec *codec) | ||
198 | { | ||
199 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
200 | int i; | ||
201 | |||
202 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { | ||
203 | snd_soc_write(codec, rt298->index_cache[i].reg, | ||
204 | rt298->index_cache[i].def); | ||
205 | } | ||
206 | } | ||
207 | #endif | ||
208 | |||
209 | static int rt298_support_power_controls[] = { | ||
210 | RT298_DAC_OUT1, | ||
211 | RT298_DAC_OUT2, | ||
212 | RT298_ADC_IN1, | ||
213 | RT298_ADC_IN2, | ||
214 | RT298_MIC1, | ||
215 | RT298_DMIC1, | ||
216 | RT298_DMIC2, | ||
217 | RT298_SPK_OUT, | ||
218 | RT298_HP_OUT, | ||
219 | }; | ||
220 | #define RT298_POWER_REG_LEN ARRAY_SIZE(rt298_support_power_controls) | ||
221 | |||
222 | static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic) | ||
223 | { | ||
224 | struct snd_soc_dapm_context *dapm; | ||
225 | unsigned int val, buf; | ||
226 | |||
227 | *hp = false; | ||
228 | *mic = false; | ||
229 | |||
230 | if (!rt298->codec) | ||
231 | return -EINVAL; | ||
232 | |||
233 | dapm = snd_soc_codec_get_dapm(rt298->codec); | ||
234 | |||
235 | if (rt298->pdata.cbj_en) { | ||
236 | regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); | ||
237 | *hp = buf & 0x80000000; | ||
238 | if (*hp == rt298->is_hp_in) | ||
239 | return -1; | ||
240 | rt298->is_hp_in = *hp; | ||
241 | if (*hp) { | ||
242 | /* power on HV,VERF */ | ||
243 | regmap_update_bits(rt298->regmap, | ||
244 | RT298_DC_GAIN, 0x200, 0x200); | ||
245 | |||
246 | snd_soc_dapm_force_enable_pin(dapm, "HV"); | ||
247 | snd_soc_dapm_force_enable_pin(dapm, "VREF"); | ||
248 | /* power LDO1 */ | ||
249 | snd_soc_dapm_force_enable_pin(dapm, "LDO1"); | ||
250 | snd_soc_dapm_sync(dapm); | ||
251 | |||
252 | regmap_write(rt298->regmap, RT298_SET_MIC1, 0x24); | ||
253 | msleep(50); | ||
254 | |||
255 | regmap_update_bits(rt298->regmap, | ||
256 | RT298_CBJ_CTRL1, 0xfcc0, 0xd400); | ||
257 | msleep(300); | ||
258 | regmap_read(rt298->regmap, RT298_CBJ_CTRL2, &val); | ||
259 | |||
260 | if (0x0070 == (val & 0x0070)) { | ||
261 | *mic = true; | ||
262 | } else { | ||
263 | regmap_update_bits(rt298->regmap, | ||
264 | RT298_CBJ_CTRL1, 0xfcc0, 0xe400); | ||
265 | msleep(300); | ||
266 | regmap_read(rt298->regmap, | ||
267 | RT298_CBJ_CTRL2, &val); | ||
268 | if (0x0070 == (val & 0x0070)) | ||
269 | *mic = true; | ||
270 | else | ||
271 | *mic = false; | ||
272 | } | ||
273 | regmap_update_bits(rt298->regmap, | ||
274 | RT298_DC_GAIN, 0x200, 0x0); | ||
275 | |||
276 | } else { | ||
277 | *mic = false; | ||
278 | regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20); | ||
279 | } | ||
280 | } else { | ||
281 | regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); | ||
282 | *hp = buf & 0x80000000; | ||
283 | regmap_read(rt298->regmap, RT298_GET_MIC1_SENSE, &buf); | ||
284 | *mic = buf & 0x80000000; | ||
285 | } | ||
286 | |||
287 | snd_soc_dapm_disable_pin(dapm, "HV"); | ||
288 | snd_soc_dapm_disable_pin(dapm, "VREF"); | ||
289 | if (!*hp) | ||
290 | snd_soc_dapm_disable_pin(dapm, "LDO1"); | ||
291 | snd_soc_dapm_sync(dapm); | ||
292 | |||
293 | pr_debug("*hp = %d *mic = %d\n", *hp, *mic); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static void rt298_jack_detect_work(struct work_struct *work) | ||
299 | { | ||
300 | struct rt298_priv *rt298 = | ||
301 | container_of(work, struct rt298_priv, jack_detect_work.work); | ||
302 | int status = 0; | ||
303 | bool hp = false; | ||
304 | bool mic = false; | ||
305 | |||
306 | if (rt298_jack_detect(rt298, &hp, &mic) < 0) | ||
307 | return; | ||
308 | |||
309 | if (hp == true) | ||
310 | status |= SND_JACK_HEADPHONE; | ||
311 | |||
312 | if (mic == true) | ||
313 | status |= SND_JACK_MICROPHONE; | ||
314 | |||
315 | snd_soc_jack_report(rt298->jack, status, | ||
316 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
317 | } | ||
318 | |||
319 | int rt298_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | ||
320 | { | ||
321 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
322 | |||
323 | rt298->jack = jack; | ||
324 | |||
325 | /* Send an initial empty report */ | ||
326 | snd_soc_jack_report(rt298->jack, 0, | ||
327 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | EXPORT_SYMBOL_GPL(rt298_mic_detect); | ||
332 | |||
333 | static int is_mclk_mode(struct snd_soc_dapm_widget *source, | ||
334 | struct snd_soc_dapm_widget *sink) | ||
335 | { | ||
336 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
337 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
338 | |||
339 | if (rt298->clk_id == RT298_SCLK_S_MCLK) | ||
340 | return 1; | ||
341 | else | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); | ||
346 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); | ||
347 | |||
348 | static const struct snd_kcontrol_new rt298_snd_controls[] = { | ||
349 | SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT298_DACL_GAIN, | ||
350 | RT298_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), | ||
351 | SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT298_ADCL_GAIN, | ||
352 | RT298_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), | ||
353 | SOC_SINGLE_TLV("AMIC Volume", RT298_MIC_GAIN, | ||
354 | 0, 0x3, 0, mic_vol_tlv), | ||
355 | SOC_DOUBLE_R("Speaker Playback Switch", RT298_SPOL_GAIN, | ||
356 | RT298_SPOR_GAIN, RT298_MUTE_SFT, 1, 1), | ||
357 | }; | ||
358 | |||
359 | /* Digital Mixer */ | ||
360 | static const struct snd_kcontrol_new rt298_front_mix[] = { | ||
361 | SOC_DAPM_SINGLE("DAC Switch", RT298_F_DAC_SWITCH, | ||
362 | RT298_MUTE_SFT, 1, 1), | ||
363 | SOC_DAPM_SINGLE("RECMIX Switch", RT298_F_RECMIX_SWITCH, | ||
364 | RT298_MUTE_SFT, 1, 1), | ||
365 | }; | ||
366 | |||
367 | /* Analog Input Mixer */ | ||
368 | static const struct snd_kcontrol_new rt298_rec_mix[] = { | ||
369 | SOC_DAPM_SINGLE("Mic1 Switch", RT298_REC_MIC_SWITCH, | ||
370 | RT298_MUTE_SFT, 1, 1), | ||
371 | SOC_DAPM_SINGLE("I2S Switch", RT298_REC_I2S_SWITCH, | ||
372 | RT298_MUTE_SFT, 1, 1), | ||
373 | SOC_DAPM_SINGLE("Line1 Switch", RT298_REC_LINE_SWITCH, | ||
374 | RT298_MUTE_SFT, 1, 1), | ||
375 | SOC_DAPM_SINGLE("Beep Switch", RT298_REC_BEEP_SWITCH, | ||
376 | RT298_MUTE_SFT, 1, 1), | ||
377 | }; | ||
378 | |||
379 | static const struct snd_kcontrol_new spo_enable_control = | ||
380 | SOC_DAPM_SINGLE("Switch", RT298_SET_PIN_SPK, | ||
381 | RT298_SET_PIN_SFT, 1, 0); | ||
382 | |||
383 | static const struct snd_kcontrol_new hpol_enable_control = | ||
384 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOL_GAIN, | ||
385 | RT298_MUTE_SFT, 1, 1); | ||
386 | |||
387 | static const struct snd_kcontrol_new hpor_enable_control = | ||
388 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOR_GAIN, | ||
389 | RT298_MUTE_SFT, 1, 1); | ||
390 | |||
391 | /* ADC0 source */ | ||
392 | static const char * const rt298_adc_src[] = { | ||
393 | "Mic", "RECMIX", "Dmic" | ||
394 | }; | ||
395 | |||
396 | static const int rt298_adc_values[] = { | ||
397 | 0, 4, 5, | ||
398 | }; | ||
399 | |||
400 | static SOC_VALUE_ENUM_SINGLE_DECL( | ||
401 | rt298_adc0_enum, RT298_ADC0_MUX, RT298_ADC_SEL_SFT, | ||
402 | RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values); | ||
403 | |||
404 | static const struct snd_kcontrol_new rt298_adc0_mux = | ||
405 | SOC_DAPM_ENUM("ADC 0 source", rt298_adc0_enum); | ||
406 | |||
407 | static SOC_VALUE_ENUM_SINGLE_DECL( | ||
408 | rt298_adc1_enum, RT298_ADC1_MUX, RT298_ADC_SEL_SFT, | ||
409 | RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values); | ||
410 | |||
411 | static const struct snd_kcontrol_new rt298_adc1_mux = | ||
412 | SOC_DAPM_ENUM("ADC 1 source", rt298_adc1_enum); | ||
413 | |||
414 | static const char * const rt298_dac_src[] = { | ||
415 | "Front", "Surround" | ||
416 | }; | ||
417 | /* HP-OUT source */ | ||
418 | static SOC_ENUM_SINGLE_DECL(rt298_hpo_enum, RT298_HPO_MUX, | ||
419 | 0, rt298_dac_src); | ||
420 | |||
421 | static const struct snd_kcontrol_new rt298_hpo_mux = | ||
422 | SOC_DAPM_ENUM("HPO source", rt298_hpo_enum); | ||
423 | |||
424 | /* SPK-OUT source */ | ||
425 | static SOC_ENUM_SINGLE_DECL(rt298_spo_enum, RT298_SPK_MUX, | ||
426 | 0, rt298_dac_src); | ||
427 | |||
428 | static const struct snd_kcontrol_new rt298_spo_mux = | ||
429 | SOC_DAPM_ENUM("SPO source", rt298_spo_enum); | ||
430 | |||
431 | static int rt298_spk_event(struct snd_soc_dapm_widget *w, | ||
432 | struct snd_kcontrol *kcontrol, int event) | ||
433 | { | ||
434 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
435 | |||
436 | switch (event) { | ||
437 | case SND_SOC_DAPM_POST_PMU: | ||
438 | snd_soc_write(codec, | ||
439 | RT298_SPK_EAPD, RT298_SET_EAPD_HIGH); | ||
440 | break; | ||
441 | case SND_SOC_DAPM_PRE_PMD: | ||
442 | snd_soc_write(codec, | ||
443 | RT298_SPK_EAPD, RT298_SET_EAPD_LOW); | ||
444 | break; | ||
445 | |||
446 | default: | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static int rt298_set_dmic1_event(struct snd_soc_dapm_widget *w, | ||
454 | struct snd_kcontrol *kcontrol, int event) | ||
455 | { | ||
456 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
457 | |||
458 | switch (event) { | ||
459 | case SND_SOC_DAPM_POST_PMU: | ||
460 | snd_soc_write(codec, RT298_SET_PIN_DMIC1, 0x20); | ||
461 | break; | ||
462 | case SND_SOC_DAPM_PRE_PMD: | ||
463 | snd_soc_write(codec, RT298_SET_PIN_DMIC1, 0); | ||
464 | break; | ||
465 | default: | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static int rt298_adc_event(struct snd_soc_dapm_widget *w, | ||
473 | struct snd_kcontrol *kcontrol, int event) | ||
474 | { | ||
475 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
476 | unsigned int nid; | ||
477 | |||
478 | nid = (w->reg >> 20) & 0xff; | ||
479 | |||
480 | switch (event) { | ||
481 | case SND_SOC_DAPM_POST_PMU: | ||
482 | snd_soc_update_bits(codec, | ||
483 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
484 | 0x7080, 0x7000); | ||
485 | break; | ||
486 | case SND_SOC_DAPM_PRE_PMD: | ||
487 | snd_soc_update_bits(codec, | ||
488 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
489 | 0x7080, 0x7080); | ||
490 | break; | ||
491 | default: | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | static int rt298_mic1_event(struct snd_soc_dapm_widget *w, | ||
499 | struct snd_kcontrol *kcontrol, int event) | ||
500 | { | ||
501 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
502 | |||
503 | switch (event) { | ||
504 | case SND_SOC_DAPM_PRE_PMU: | ||
505 | snd_soc_update_bits(codec, | ||
506 | RT298_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
507 | snd_soc_update_bits(codec, | ||
508 | RT298_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
509 | break; | ||
510 | case SND_SOC_DAPM_POST_PMD: | ||
511 | snd_soc_update_bits(codec, | ||
512 | RT298_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
513 | snd_soc_update_bits(codec, | ||
514 | RT298_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
515 | break; | ||
516 | default: | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | static int rt298_vref_event(struct snd_soc_dapm_widget *w, | ||
524 | struct snd_kcontrol *kcontrol, int event) | ||
525 | { | ||
526 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
527 | |||
528 | switch (event) { | ||
529 | case SND_SOC_DAPM_PRE_PMU: | ||
530 | snd_soc_update_bits(codec, | ||
531 | RT298_CBJ_CTRL1, 0x0400, 0x0000); | ||
532 | mdelay(50); | ||
533 | break; | ||
534 | default: | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | static const struct snd_soc_dapm_widget rt298_dapm_widgets[] = { | ||
542 | |||
543 | SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1, | ||
544 | 12, 1, NULL, 0), | ||
545 | SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1, | ||
546 | 0, 1, rt298_vref_event, SND_SOC_DAPM_PRE_PMU), | ||
547 | SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2, | ||
548 | 1, 0, NULL, 0), | ||
549 | SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2, | ||
550 | 2, 0, NULL, 0), | ||
551 | SND_SOC_DAPM_SUPPLY_S("LDO2", 1, RT298_POWER_CTRL2, | ||
552 | 3, 0, NULL, 0), | ||
553 | SND_SOC_DAPM_SUPPLY_S("VREF1", 1, RT298_POWER_CTRL2, | ||
554 | 4, 1, NULL, 0), | ||
555 | SND_SOC_DAPM_SUPPLY_S("LV", 2, RT298_POWER_CTRL1, | ||
556 | 13, 1, NULL, 0), | ||
557 | |||
558 | |||
559 | SND_SOC_DAPM_SUPPLY("MCLK MODE", RT298_PLL_CTRL1, | ||
560 | 5, 0, NULL, 0), | ||
561 | SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM, | ||
562 | 0, 0, rt298_mic1_event, SND_SOC_DAPM_PRE_PMU | | ||
563 | SND_SOC_DAPM_POST_PMD), | ||
564 | |||
565 | /* Input Lines */ | ||
566 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), | ||
567 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), | ||
568 | SND_SOC_DAPM_INPUT("MIC1"), | ||
569 | SND_SOC_DAPM_INPUT("LINE1"), | ||
570 | SND_SOC_DAPM_INPUT("Beep"), | ||
571 | |||
572 | /* DMIC */ | ||
573 | SND_SOC_DAPM_PGA_E("DMIC1", RT298_SET_POWER(RT298_DMIC1), 0, 1, | ||
574 | NULL, 0, rt298_set_dmic1_event, | ||
575 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
576 | SND_SOC_DAPM_PGA("DMIC2", RT298_SET_POWER(RT298_DMIC2), 0, 1, | ||
577 | NULL, 0), | ||
578 | SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM, | ||
579 | 0, 0, NULL, 0), | ||
580 | |||
581 | /* REC Mixer */ | ||
582 | SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0, | ||
583 | rt298_rec_mix, ARRAY_SIZE(rt298_rec_mix)), | ||
584 | |||
585 | /* ADCs */ | ||
586 | SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0), | ||
587 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
588 | |||
589 | /* ADC Mux */ | ||
590 | SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT298_SET_POWER(RT298_ADC_IN1), 0, 1, | ||
591 | &rt298_adc0_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
592 | SND_SOC_DAPM_POST_PMU), | ||
593 | SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT298_SET_POWER(RT298_ADC_IN2), 0, 1, | ||
594 | &rt298_adc1_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
595 | SND_SOC_DAPM_POST_PMU), | ||
596 | |||
597 | /* Audio Interface */ | ||
598 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
599 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
600 | SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
601 | SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
602 | |||
603 | /* Output Side */ | ||
604 | /* DACs */ | ||
605 | SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0), | ||
606 | SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0), | ||
607 | |||
608 | /* Output Mux */ | ||
609 | SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt298_spo_mux), | ||
610 | SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt298_hpo_mux), | ||
611 | |||
612 | SND_SOC_DAPM_SUPPLY("HP Power", RT298_SET_PIN_HPO, | ||
613 | RT298_SET_PIN_SFT, 0, NULL, 0), | ||
614 | |||
615 | /* Output Mixer */ | ||
616 | SND_SOC_DAPM_MIXER("Front", RT298_SET_POWER(RT298_DAC_OUT1), 0, 1, | ||
617 | rt298_front_mix, ARRAY_SIZE(rt298_front_mix)), | ||
618 | SND_SOC_DAPM_PGA("Surround", RT298_SET_POWER(RT298_DAC_OUT2), 0, 1, | ||
619 | NULL, 0), | ||
620 | |||
621 | /* Output Pga */ | ||
622 | SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0, | ||
623 | &spo_enable_control, rt298_spk_event, | ||
624 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
625 | SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0, | ||
626 | &hpol_enable_control), | ||
627 | SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0, | ||
628 | &hpor_enable_control), | ||
629 | |||
630 | /* Output Lines */ | ||
631 | SND_SOC_DAPM_OUTPUT("SPOL"), | ||
632 | SND_SOC_DAPM_OUTPUT("SPOR"), | ||
633 | SND_SOC_DAPM_OUTPUT("HPO Pin"), | ||
634 | SND_SOC_DAPM_OUTPUT("SPDIF"), | ||
635 | }; | ||
636 | |||
637 | static const struct snd_soc_dapm_route rt298_dapm_routes[] = { | ||
638 | |||
639 | {"ADC 0", NULL, "MCLK MODE", is_mclk_mode}, | ||
640 | {"ADC 1", NULL, "MCLK MODE", is_mclk_mode}, | ||
641 | {"Front", NULL, "MCLK MODE", is_mclk_mode}, | ||
642 | {"Surround", NULL, "MCLK MODE", is_mclk_mode}, | ||
643 | |||
644 | {"HP Power", NULL, "LDO1"}, | ||
645 | {"HP Power", NULL, "LDO2"}, | ||
646 | {"HP Power", NULL, "LV"}, | ||
647 | {"HP Power", NULL, "VREF1"}, | ||
648 | {"HP Power", NULL, "BG_MBIAS"}, | ||
649 | |||
650 | {"MIC1", NULL, "LDO1"}, | ||
651 | {"MIC1", NULL, "LDO2"}, | ||
652 | {"MIC1", NULL, "HV"}, | ||
653 | {"MIC1", NULL, "LV"}, | ||
654 | {"MIC1", NULL, "VREF"}, | ||
655 | {"MIC1", NULL, "VREF1"}, | ||
656 | {"MIC1", NULL, "BG_MBIAS"}, | ||
657 | {"MIC1", NULL, "MIC1 Input Buffer"}, | ||
658 | |||
659 | {"SPO", NULL, "LDO1"}, | ||
660 | {"SPO", NULL, "LDO2"}, | ||
661 | {"SPO", NULL, "HV"}, | ||
662 | {"SPO", NULL, "LV"}, | ||
663 | {"SPO", NULL, "VREF"}, | ||
664 | {"SPO", NULL, "VREF1"}, | ||
665 | {"SPO", NULL, "BG_MBIAS"}, | ||
666 | |||
667 | {"DMIC1", NULL, "DMIC1 Pin"}, | ||
668 | {"DMIC2", NULL, "DMIC2 Pin"}, | ||
669 | {"DMIC1", NULL, "DMIC Receiver"}, | ||
670 | {"DMIC2", NULL, "DMIC Receiver"}, | ||
671 | |||
672 | {"RECMIX", "Beep Switch", "Beep"}, | ||
673 | {"RECMIX", "Line1 Switch", "LINE1"}, | ||
674 | {"RECMIX", "Mic1 Switch", "MIC1"}, | ||
675 | |||
676 | {"ADC 0 Mux", "Dmic", "DMIC1"}, | ||
677 | {"ADC 0 Mux", "RECMIX", "RECMIX"}, | ||
678 | {"ADC 0 Mux", "Mic", "MIC1"}, | ||
679 | {"ADC 1 Mux", "Dmic", "DMIC2"}, | ||
680 | {"ADC 1 Mux", "RECMIX", "RECMIX"}, | ||
681 | {"ADC 1 Mux", "Mic", "MIC1"}, | ||
682 | |||
683 | {"ADC 0", NULL, "ADC 0 Mux"}, | ||
684 | {"ADC 1", NULL, "ADC 1 Mux"}, | ||
685 | |||
686 | {"AIF1TX", NULL, "ADC 0"}, | ||
687 | {"AIF2TX", NULL, "ADC 1"}, | ||
688 | |||
689 | {"DAC 0", NULL, "AIF1RX"}, | ||
690 | {"DAC 1", NULL, "AIF2RX"}, | ||
691 | |||
692 | {"Front", "DAC Switch", "DAC 0"}, | ||
693 | {"Front", "RECMIX Switch", "RECMIX"}, | ||
694 | |||
695 | {"Surround", NULL, "DAC 1"}, | ||
696 | |||
697 | {"SPK Mux", "Front", "Front"}, | ||
698 | {"SPK Mux", "Surround", "Surround"}, | ||
699 | |||
700 | {"HPO Mux", "Front", "Front"}, | ||
701 | {"HPO Mux", "Surround", "Surround"}, | ||
702 | |||
703 | {"SPO", "Switch", "SPK Mux"}, | ||
704 | {"HPO L", "Switch", "HPO Mux"}, | ||
705 | {"HPO R", "Switch", "HPO Mux"}, | ||
706 | {"HPO L", NULL, "HP Power"}, | ||
707 | {"HPO R", NULL, "HP Power"}, | ||
708 | |||
709 | {"SPOL", NULL, "SPO"}, | ||
710 | {"SPOR", NULL, "SPO"}, | ||
711 | {"HPO Pin", NULL, "HPO L"}, | ||
712 | {"HPO Pin", NULL, "HPO R"}, | ||
713 | }; | ||
714 | |||
715 | static int rt298_hw_params(struct snd_pcm_substream *substream, | ||
716 | struct snd_pcm_hw_params *params, | ||
717 | struct snd_soc_dai *dai) | ||
718 | { | ||
719 | struct snd_soc_codec *codec = dai->codec; | ||
720 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
721 | unsigned int val = 0; | ||
722 | int d_len_code; | ||
723 | |||
724 | switch (params_rate(params)) { | ||
725 | /* bit 14 0:48K 1:44.1K */ | ||
726 | case 44100: | ||
727 | case 48000: | ||
728 | break; | ||
729 | default: | ||
730 | dev_err(codec->dev, "Unsupported sample rate %d\n", | ||
731 | params_rate(params)); | ||
732 | return -EINVAL; | ||
733 | } | ||
734 | switch (rt298->sys_clk) { | ||
735 | case 12288000: | ||
736 | case 24576000: | ||
737 | if (params_rate(params) != 48000) { | ||
738 | dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n", | ||
739 | params_rate(params), rt298->sys_clk); | ||
740 | return -EINVAL; | ||
741 | } | ||
742 | break; | ||
743 | case 11289600: | ||
744 | case 22579200: | ||
745 | if (params_rate(params) != 44100) { | ||
746 | dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n", | ||
747 | params_rate(params), rt298->sys_clk); | ||
748 | return -EINVAL; | ||
749 | } | ||
750 | break; | ||
751 | } | ||
752 | |||
753 | if (params_channels(params) <= 16) { | ||
754 | /* bit 3:0 Number of Channel */ | ||
755 | val |= (params_channels(params) - 1); | ||
756 | } else { | ||
757 | dev_err(codec->dev, "Unsupported channels %d\n", | ||
758 | params_channels(params)); | ||
759 | return -EINVAL; | ||
760 | } | ||
761 | |||
762 | d_len_code = 0; | ||
763 | switch (params_width(params)) { | ||
764 | /* bit 6:4 Bits per Sample */ | ||
765 | case 16: | ||
766 | d_len_code = 0; | ||
767 | val |= (0x1 << 4); | ||
768 | break; | ||
769 | case 32: | ||
770 | d_len_code = 2; | ||
771 | val |= (0x4 << 4); | ||
772 | break; | ||
773 | case 20: | ||
774 | d_len_code = 1; | ||
775 | val |= (0x2 << 4); | ||
776 | break; | ||
777 | case 24: | ||
778 | d_len_code = 2; | ||
779 | val |= (0x3 << 4); | ||
780 | break; | ||
781 | case 8: | ||
782 | d_len_code = 3; | ||
783 | break; | ||
784 | default: | ||
785 | return -EINVAL; | ||
786 | } | ||
787 | |||
788 | snd_soc_update_bits(codec, | ||
789 | RT298_I2S_CTRL1, 0x0018, d_len_code << 3); | ||
790 | dev_dbg(codec->dev, "format val = 0x%x\n", val); | ||
791 | |||
792 | snd_soc_update_bits(codec, RT298_DAC_FORMAT, 0x407f, val); | ||
793 | snd_soc_update_bits(codec, RT298_ADC_FORMAT, 0x407f, val); | ||
794 | |||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | static int rt298_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
799 | { | ||
800 | struct snd_soc_codec *codec = dai->codec; | ||
801 | |||
802 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
803 | case SND_SOC_DAIFMT_CBM_CFM: | ||
804 | snd_soc_update_bits(codec, | ||
805 | RT298_I2S_CTRL1, 0x800, 0x800); | ||
806 | break; | ||
807 | case SND_SOC_DAIFMT_CBS_CFS: | ||
808 | snd_soc_update_bits(codec, | ||
809 | RT298_I2S_CTRL1, 0x800, 0x0); | ||
810 | break; | ||
811 | default: | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
815 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
816 | case SND_SOC_DAIFMT_I2S: | ||
817 | snd_soc_update_bits(codec, | ||
818 | RT298_I2S_CTRL1, 0x300, 0x0); | ||
819 | break; | ||
820 | case SND_SOC_DAIFMT_LEFT_J: | ||
821 | snd_soc_update_bits(codec, | ||
822 | RT298_I2S_CTRL1, 0x300, 0x1 << 8); | ||
823 | break; | ||
824 | case SND_SOC_DAIFMT_DSP_A: | ||
825 | snd_soc_update_bits(codec, | ||
826 | RT298_I2S_CTRL1, 0x300, 0x2 << 8); | ||
827 | break; | ||
828 | case SND_SOC_DAIFMT_DSP_B: | ||
829 | snd_soc_update_bits(codec, | ||
830 | RT298_I2S_CTRL1, 0x300, 0x3 << 8); | ||
831 | break; | ||
832 | default: | ||
833 | return -EINVAL; | ||
834 | } | ||
835 | /* bit 15 Stream Type 0:PCM 1:Non-PCM */ | ||
836 | snd_soc_update_bits(codec, RT298_DAC_FORMAT, 0x8000, 0); | ||
837 | snd_soc_update_bits(codec, RT298_ADC_FORMAT, 0x8000, 0); | ||
838 | |||
839 | return 0; | ||
840 | } | ||
841 | |||
842 | static int rt298_set_dai_sysclk(struct snd_soc_dai *dai, | ||
843 | int clk_id, unsigned int freq, int dir) | ||
844 | { | ||
845 | struct snd_soc_codec *codec = dai->codec; | ||
846 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
847 | |||
848 | dev_dbg(codec->dev, "%s freq=%d\n", __func__, freq); | ||
849 | |||
850 | if (RT298_SCLK_S_MCLK == clk_id) { | ||
851 | snd_soc_update_bits(codec, | ||
852 | RT298_I2S_CTRL2, 0x0100, 0x0); | ||
853 | snd_soc_update_bits(codec, | ||
854 | RT298_PLL_CTRL1, 0x20, 0x20); | ||
855 | } else { | ||
856 | snd_soc_update_bits(codec, | ||
857 | RT298_I2S_CTRL2, 0x0100, 0x0100); | ||
858 | snd_soc_update_bits(codec, | ||
859 | RT298_PLL_CTRL, 0x4, 0x4); | ||
860 | snd_soc_update_bits(codec, | ||
861 | RT298_PLL_CTRL1, 0x20, 0x0); | ||
862 | } | ||
863 | |||
864 | switch (freq) { | ||
865 | case 19200000: | ||
866 | if (RT298_SCLK_S_MCLK == clk_id) { | ||
867 | dev_err(codec->dev, "Should not use MCLK\n"); | ||
868 | return -EINVAL; | ||
869 | } | ||
870 | snd_soc_update_bits(codec, | ||
871 | RT298_I2S_CTRL2, 0x40, 0x40); | ||
872 | break; | ||
873 | case 24000000: | ||
874 | if (RT298_SCLK_S_MCLK == clk_id) { | ||
875 | dev_err(codec->dev, "Should not use MCLK\n"); | ||
876 | return -EINVAL; | ||
877 | } | ||
878 | snd_soc_update_bits(codec, | ||
879 | RT298_I2S_CTRL2, 0x40, 0x0); | ||
880 | break; | ||
881 | case 12288000: | ||
882 | case 11289600: | ||
883 | snd_soc_update_bits(codec, | ||
884 | RT298_I2S_CTRL2, 0x8, 0x0); | ||
885 | snd_soc_update_bits(codec, | ||
886 | RT298_CLK_DIV, 0xfc1e, 0x0004); | ||
887 | break; | ||
888 | case 24576000: | ||
889 | case 22579200: | ||
890 | snd_soc_update_bits(codec, | ||
891 | RT298_I2S_CTRL2, 0x8, 0x8); | ||
892 | snd_soc_update_bits(codec, | ||
893 | RT298_CLK_DIV, 0xfc1e, 0x5406); | ||
894 | break; | ||
895 | default: | ||
896 | dev_err(codec->dev, "Unsupported system clock\n"); | ||
897 | return -EINVAL; | ||
898 | } | ||
899 | |||
900 | rt298->sys_clk = freq; | ||
901 | rt298->clk_id = clk_id; | ||
902 | |||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | static int rt298_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) | ||
907 | { | ||
908 | struct snd_soc_codec *codec = dai->codec; | ||
909 | |||
910 | dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio); | ||
911 | if (50 == ratio) | ||
912 | snd_soc_update_bits(codec, | ||
913 | RT298_I2S_CTRL1, 0x1000, 0x1000); | ||
914 | else | ||
915 | snd_soc_update_bits(codec, | ||
916 | RT298_I2S_CTRL1, 0x1000, 0x0); | ||
917 | |||
918 | |||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | static int rt298_set_bias_level(struct snd_soc_codec *codec, | ||
923 | enum snd_soc_bias_level level) | ||
924 | { | ||
925 | switch (level) { | ||
926 | case SND_SOC_BIAS_PREPARE: | ||
927 | if (SND_SOC_BIAS_STANDBY == | ||
928 | snd_soc_codec_get_bias_level(codec)) { | ||
929 | snd_soc_write(codec, | ||
930 | RT298_SET_AUDIO_POWER, AC_PWRST_D0); | ||
931 | snd_soc_update_bits(codec, 0x0d, 0x200, 0x200); | ||
932 | snd_soc_update_bits(codec, 0x52, 0x80, 0x0); | ||
933 | mdelay(20); | ||
934 | snd_soc_update_bits(codec, 0x0d, 0x200, 0x0); | ||
935 | snd_soc_update_bits(codec, 0x52, 0x80, 0x80); | ||
936 | } | ||
937 | break; | ||
938 | |||
939 | case SND_SOC_BIAS_ON: | ||
940 | mdelay(30); | ||
941 | snd_soc_update_bits(codec, | ||
942 | RT298_CBJ_CTRL1, 0x0400, 0x0400); | ||
943 | |||
944 | break; | ||
945 | |||
946 | case SND_SOC_BIAS_STANDBY: | ||
947 | snd_soc_write(codec, | ||
948 | RT298_SET_AUDIO_POWER, AC_PWRST_D3); | ||
949 | snd_soc_update_bits(codec, | ||
950 | RT298_CBJ_CTRL1, 0x0400, 0x0000); | ||
951 | break; | ||
952 | |||
953 | default: | ||
954 | break; | ||
955 | } | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | static irqreturn_t rt298_irq(int irq, void *data) | ||
961 | { | ||
962 | struct rt298_priv *rt298 = data; | ||
963 | bool hp = false; | ||
964 | bool mic = false; | ||
965 | int ret, status = 0; | ||
966 | |||
967 | ret = rt298_jack_detect(rt298, &hp, &mic); | ||
968 | |||
969 | /* Clear IRQ */ | ||
970 | regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x1, 0x1); | ||
971 | |||
972 | if (ret == 0) { | ||
973 | if (hp == true) | ||
974 | status |= SND_JACK_HEADPHONE; | ||
975 | |||
976 | if (mic == true) | ||
977 | status |= SND_JACK_MICROPHONE; | ||
978 | |||
979 | snd_soc_jack_report(rt298->jack, status, | ||
980 | SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); | ||
981 | |||
982 | pm_wakeup_event(&rt298->i2c->dev, 300); | ||
983 | } | ||
984 | |||
985 | return IRQ_HANDLED; | ||
986 | } | ||
987 | |||
988 | static int rt298_probe(struct snd_soc_codec *codec) | ||
989 | { | ||
990 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
991 | |||
992 | rt298->codec = codec; | ||
993 | |||
994 | if (rt298->i2c->irq) { | ||
995 | regmap_update_bits(rt298->regmap, | ||
996 | RT298_IRQ_CTRL, 0x2, 0x2); | ||
997 | |||
998 | INIT_DELAYED_WORK(&rt298->jack_detect_work, | ||
999 | rt298_jack_detect_work); | ||
1000 | schedule_delayed_work(&rt298->jack_detect_work, | ||
1001 | msecs_to_jiffies(1250)); | ||
1002 | } | ||
1003 | |||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | static int rt298_remove(struct snd_soc_codec *codec) | ||
1008 | { | ||
1009 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
1010 | |||
1011 | cancel_delayed_work_sync(&rt298->jack_detect_work); | ||
1012 | |||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | #ifdef CONFIG_PM | ||
1017 | static int rt298_suspend(struct snd_soc_codec *codec) | ||
1018 | { | ||
1019 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
1020 | |||
1021 | rt298->is_hp_in = -1; | ||
1022 | regcache_cache_only(rt298->regmap, true); | ||
1023 | regcache_mark_dirty(rt298->regmap); | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | static int rt298_resume(struct snd_soc_codec *codec) | ||
1029 | { | ||
1030 | struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec); | ||
1031 | |||
1032 | regcache_cache_only(rt298->regmap, false); | ||
1033 | rt298_index_sync(codec); | ||
1034 | regcache_sync(rt298->regmap); | ||
1035 | |||
1036 | return 0; | ||
1037 | } | ||
1038 | #else | ||
1039 | #define rt298_suspend NULL | ||
1040 | #define rt298_resume NULL | ||
1041 | #endif | ||
1042 | |||
1043 | #define RT298_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | ||
1044 | #define RT298_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1045 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | ||
1046 | |||
1047 | static const struct snd_soc_dai_ops rt298_aif_dai_ops = { | ||
1048 | .hw_params = rt298_hw_params, | ||
1049 | .set_fmt = rt298_set_dai_fmt, | ||
1050 | .set_sysclk = rt298_set_dai_sysclk, | ||
1051 | .set_bclk_ratio = rt298_set_bclk_ratio, | ||
1052 | }; | ||
1053 | |||
1054 | static struct snd_soc_dai_driver rt298_dai[] = { | ||
1055 | { | ||
1056 | .name = "rt298-aif1", | ||
1057 | .id = RT298_AIF1, | ||
1058 | .playback = { | ||
1059 | .stream_name = "AIF1 Playback", | ||
1060 | .channels_min = 1, | ||
1061 | .channels_max = 2, | ||
1062 | .rates = RT298_STEREO_RATES, | ||
1063 | .formats = RT298_FORMATS, | ||
1064 | }, | ||
1065 | .capture = { | ||
1066 | .stream_name = "AIF1 Capture", | ||
1067 | .channels_min = 1, | ||
1068 | .channels_max = 2, | ||
1069 | .rates = RT298_STEREO_RATES, | ||
1070 | .formats = RT298_FORMATS, | ||
1071 | }, | ||
1072 | .ops = &rt298_aif_dai_ops, | ||
1073 | .symmetric_rates = 1, | ||
1074 | }, | ||
1075 | { | ||
1076 | .name = "rt298-aif2", | ||
1077 | .id = RT298_AIF2, | ||
1078 | .playback = { | ||
1079 | .stream_name = "AIF2 Playback", | ||
1080 | .channels_min = 1, | ||
1081 | .channels_max = 2, | ||
1082 | .rates = RT298_STEREO_RATES, | ||
1083 | .formats = RT298_FORMATS, | ||
1084 | }, | ||
1085 | .capture = { | ||
1086 | .stream_name = "AIF2 Capture", | ||
1087 | .channels_min = 1, | ||
1088 | .channels_max = 2, | ||
1089 | .rates = RT298_STEREO_RATES, | ||
1090 | .formats = RT298_FORMATS, | ||
1091 | }, | ||
1092 | .ops = &rt298_aif_dai_ops, | ||
1093 | .symmetric_rates = 1, | ||
1094 | }, | ||
1095 | |||
1096 | }; | ||
1097 | |||
1098 | static struct snd_soc_codec_driver soc_codec_dev_rt298 = { | ||
1099 | .probe = rt298_probe, | ||
1100 | .remove = rt298_remove, | ||
1101 | .suspend = rt298_suspend, | ||
1102 | .resume = rt298_resume, | ||
1103 | .set_bias_level = rt298_set_bias_level, | ||
1104 | .idle_bias_off = true, | ||
1105 | .controls = rt298_snd_controls, | ||
1106 | .num_controls = ARRAY_SIZE(rt298_snd_controls), | ||
1107 | .dapm_widgets = rt298_dapm_widgets, | ||
1108 | .num_dapm_widgets = ARRAY_SIZE(rt298_dapm_widgets), | ||
1109 | .dapm_routes = rt298_dapm_routes, | ||
1110 | .num_dapm_routes = ARRAY_SIZE(rt298_dapm_routes), | ||
1111 | }; | ||
1112 | |||
1113 | static const struct regmap_config rt298_regmap = { | ||
1114 | .reg_bits = 32, | ||
1115 | .val_bits = 32, | ||
1116 | .max_register = 0x02370100, | ||
1117 | .volatile_reg = rt298_volatile_register, | ||
1118 | .readable_reg = rt298_readable_register, | ||
1119 | .reg_write = rl6347a_hw_write, | ||
1120 | .reg_read = rl6347a_hw_read, | ||
1121 | .cache_type = REGCACHE_RBTREE, | ||
1122 | .reg_defaults = rt298_reg, | ||
1123 | .num_reg_defaults = ARRAY_SIZE(rt298_reg), | ||
1124 | }; | ||
1125 | |||
1126 | static const struct i2c_device_id rt298_i2c_id[] = { | ||
1127 | {"rt298", 0}, | ||
1128 | {} | ||
1129 | }; | ||
1130 | MODULE_DEVICE_TABLE(i2c, rt298_i2c_id); | ||
1131 | |||
1132 | static const struct acpi_device_id rt298_acpi_match[] = { | ||
1133 | { "INT343A", 0 }, | ||
1134 | {}, | ||
1135 | }; | ||
1136 | MODULE_DEVICE_TABLE(acpi, rt298_acpi_match); | ||
1137 | |||
1138 | static int rt298_i2c_probe(struct i2c_client *i2c, | ||
1139 | const struct i2c_device_id *id) | ||
1140 | { | ||
1141 | struct rt298_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
1142 | struct rt298_priv *rt298; | ||
1143 | struct device *dev = &i2c->dev; | ||
1144 | const struct acpi_device_id *acpiid; | ||
1145 | int i, ret; | ||
1146 | |||
1147 | rt298 = devm_kzalloc(&i2c->dev, sizeof(*rt298), | ||
1148 | GFP_KERNEL); | ||
1149 | if (NULL == rt298) | ||
1150 | return -ENOMEM; | ||
1151 | |||
1152 | rt298->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt298_regmap); | ||
1153 | if (IS_ERR(rt298->regmap)) { | ||
1154 | ret = PTR_ERR(rt298->regmap); | ||
1155 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
1156 | ret); | ||
1157 | return ret; | ||
1158 | } | ||
1159 | |||
1160 | regmap_read(rt298->regmap, | ||
1161 | RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); | ||
1162 | if (ret != RT298_VENDOR_ID) { | ||
1163 | dev_err(&i2c->dev, | ||
1164 | "Device with ID register %#x is not rt298\n", ret); | ||
1165 | return -ENODEV; | ||
1166 | } | ||
1167 | |||
1168 | rt298->index_cache = rt298_index_def; | ||
1169 | rt298->index_cache_size = INDEX_CACHE_SIZE; | ||
1170 | rt298->i2c = i2c; | ||
1171 | i2c_set_clientdata(i2c, rt298); | ||
1172 | |||
1173 | /* restore codec default */ | ||
1174 | for (i = 0; i < INDEX_CACHE_SIZE; i++) | ||
1175 | regmap_write(rt298->regmap, rt298->index_cache[i].reg, | ||
1176 | rt298->index_cache[i].def); | ||
1177 | for (i = 0; i < ARRAY_SIZE(rt298_reg); i++) | ||
1178 | regmap_write(rt298->regmap, rt298_reg[i].reg, | ||
1179 | rt298_reg[i].def); | ||
1180 | |||
1181 | if (pdata) | ||
1182 | rt298->pdata = *pdata; | ||
1183 | |||
1184 | /* enable jack combo mode on supported devices */ | ||
1185 | acpiid = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
1186 | if (acpiid) { | ||
1187 | rt298->pdata = *(struct rt298_platform_data *) | ||
1188 | acpiid->driver_data; | ||
1189 | } | ||
1190 | |||
1191 | /* VREF Charging */ | ||
1192 | regmap_update_bits(rt298->regmap, 0x04, 0x80, 0x80); | ||
1193 | regmap_update_bits(rt298->regmap, 0x1b, 0x860, 0x860); | ||
1194 | /* Vref2 */ | ||
1195 | regmap_update_bits(rt298->regmap, 0x08, 0x20, 0x20); | ||
1196 | |||
1197 | regmap_write(rt298->regmap, RT298_SET_AUDIO_POWER, AC_PWRST_D3); | ||
1198 | |||
1199 | for (i = 0; i < RT298_POWER_REG_LEN; i++) | ||
1200 | regmap_write(rt298->regmap, | ||
1201 | RT298_SET_POWER(rt298_support_power_controls[i]), | ||
1202 | AC_PWRST_D1); | ||
1203 | |||
1204 | if (!rt298->pdata.cbj_en) { | ||
1205 | regmap_write(rt298->regmap, RT298_CBJ_CTRL2, 0x0000); | ||
1206 | regmap_write(rt298->regmap, RT298_MIC1_DET_CTRL, 0x0816); | ||
1207 | regmap_update_bits(rt298->regmap, | ||
1208 | RT298_CBJ_CTRL1, 0xf000, 0xb000); | ||
1209 | } else { | ||
1210 | regmap_update_bits(rt298->regmap, | ||
1211 | RT298_CBJ_CTRL1, 0xf000, 0x5000); | ||
1212 | } | ||
1213 | |||
1214 | mdelay(10); | ||
1215 | |||
1216 | if (!rt298->pdata.gpio2_en) | ||
1217 | regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x4000); | ||
1218 | else | ||
1219 | regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0); | ||
1220 | |||
1221 | mdelay(10); | ||
1222 | |||
1223 | regmap_write(rt298->regmap, RT298_MISC_CTRL1, 0x0000); | ||
1224 | regmap_update_bits(rt298->regmap, | ||
1225 | RT298_WIND_FILTER_CTRL, 0x0082, 0x0082); | ||
1226 | regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x2); | ||
1227 | rt298->is_hp_in = -1; | ||
1228 | |||
1229 | if (rt298->i2c->irq) { | ||
1230 | ret = request_threaded_irq(rt298->i2c->irq, NULL, rt298_irq, | ||
1231 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt298", rt298); | ||
1232 | if (ret != 0) { | ||
1233 | dev_err(&i2c->dev, | ||
1234 | "Failed to reguest IRQ: %d\n", ret); | ||
1235 | return ret; | ||
1236 | } | ||
1237 | } | ||
1238 | |||
1239 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt298, | ||
1240 | rt298_dai, ARRAY_SIZE(rt298_dai)); | ||
1241 | |||
1242 | return ret; | ||
1243 | } | ||
1244 | |||
1245 | static int rt298_i2c_remove(struct i2c_client *i2c) | ||
1246 | { | ||
1247 | struct rt298_priv *rt298 = i2c_get_clientdata(i2c); | ||
1248 | |||
1249 | if (i2c->irq) | ||
1250 | free_irq(i2c->irq, rt298); | ||
1251 | snd_soc_unregister_codec(&i2c->dev); | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | |||
1257 | static struct i2c_driver rt298_i2c_driver = { | ||
1258 | .driver = { | ||
1259 | .name = "rt298", | ||
1260 | .acpi_match_table = ACPI_PTR(rt298_acpi_match), | ||
1261 | }, | ||
1262 | .probe = rt298_i2c_probe, | ||
1263 | .remove = rt298_i2c_remove, | ||
1264 | .id_table = rt298_i2c_id, | ||
1265 | }; | ||
1266 | |||
1267 | module_i2c_driver(rt298_i2c_driver); | ||
1268 | |||
1269 | MODULE_DESCRIPTION("ASoC RT298 driver"); | ||
1270 | MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); | ||
1271 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/rt298.h b/sound/soc/codecs/rt298.h new file mode 100644 index 000000000000..31da16265f2b --- /dev/null +++ b/sound/soc/codecs/rt298.h | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * rt298.h -- RT298 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2011 Realtek Microelectronics | ||
5 | * Author: Johnny Hsu <johnnyhsu@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __RT298_H__ | ||
13 | #define __RT298_H__ | ||
14 | |||
15 | #define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D) | ||
16 | |||
17 | #define RT298_AUDIO_FUNCTION_GROUP 0x01 | ||
18 | #define RT298_DAC_OUT1 0x02 | ||
19 | #define RT298_DAC_OUT2 0x03 | ||
20 | #define RT298_DIG_CVT 0x06 | ||
21 | #define RT298_ADC_IN1 0x09 | ||
22 | #define RT298_ADC_IN2 0x08 | ||
23 | #define RT298_MIXER_IN 0x0b | ||
24 | #define RT298_MIXER_OUT1 0x0c | ||
25 | #define RT298_MIXER_OUT2 0x0d | ||
26 | #define RT298_DMIC1 0x12 | ||
27 | #define RT298_DMIC2 0x13 | ||
28 | #define RT298_SPK_OUT 0x14 | ||
29 | #define RT298_MIC1 0x18 | ||
30 | #define RT298_LINE1 0x1a | ||
31 | #define RT298_BEEP 0x1d | ||
32 | #define RT298_SPDIF 0x1e | ||
33 | #define RT298_VENDOR_REGISTERS 0x20 | ||
34 | #define RT298_HP_OUT 0x21 | ||
35 | #define RT298_MIXER_IN1 0x22 | ||
36 | #define RT298_MIXER_IN2 0x23 | ||
37 | |||
38 | #define RT298_SET_PIN_SFT 6 | ||
39 | #define RT298_SET_PIN_ENABLE 0x40 | ||
40 | #define RT298_SET_PIN_DISABLE 0 | ||
41 | #define RT298_SET_EAPD_HIGH 0x2 | ||
42 | #define RT298_SET_EAPD_LOW 0 | ||
43 | |||
44 | #define RT298_MUTE_SFT 7 | ||
45 | |||
46 | /* Verb commands */ | ||
47 | #define RT298_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM) | ||
48 | #define RT298_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0) | ||
49 | #define RT298_SET_AUDIO_POWER RT298_SET_POWER(RT298_AUDIO_FUNCTION_GROUP) | ||
50 | #define RT298_SET_HPO_POWER RT298_SET_POWER(RT298_HP_OUT) | ||
51 | #define RT298_SET_SPK_POWER RT298_SET_POWER(RT298_SPK_OUT) | ||
52 | #define RT298_SET_DMIC1_POWER RT298_SET_POWER(RT298_DMIC1) | ||
53 | #define RT298_SPK_MUX\ | ||
54 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_SPK_OUT, 0) | ||
55 | #define RT298_HPO_MUX\ | ||
56 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_HP_OUT, 0) | ||
57 | #define RT298_ADC0_MUX\ | ||
58 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_MIXER_IN1, 0) | ||
59 | #define RT298_ADC1_MUX\ | ||
60 | VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_MIXER_IN2, 0) | ||
61 | #define RT298_SET_MIC1\ | ||
62 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_MIC1, 0) | ||
63 | #define RT298_SET_PIN_HPO\ | ||
64 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_HP_OUT, 0) | ||
65 | #define RT298_SET_PIN_SPK\ | ||
66 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_SPK_OUT, 0) | ||
67 | #define RT298_SET_PIN_DMIC1\ | ||
68 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_DMIC1, 0) | ||
69 | #define RT298_SET_PIN_SPDIF\ | ||
70 | VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_SPDIF, 0) | ||
71 | #define RT298_SET_PIN_DIG_CVT\ | ||
72 | VERB_CMD(AC_VERB_SET_DIGI_CONVERT_1, RT298_DIG_CVT, 0) | ||
73 | #define RT298_SPK_EAPD\ | ||
74 | VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT298_SPK_OUT, 0) | ||
75 | #define RT298_SET_AMP_GAIN_HPO\ | ||
76 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0) | ||
77 | #define RT298_SET_AMP_GAIN_ADC_IN1\ | ||
78 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0) | ||
79 | #define RT298_SET_AMP_GAIN_ADC_IN2\ | ||
80 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN2, 0) | ||
81 | #define RT298_GET_HP_SENSE\ | ||
82 | VERB_CMD(AC_VERB_GET_PIN_SENSE, RT298_HP_OUT, 0) | ||
83 | #define RT298_GET_MIC1_SENSE\ | ||
84 | VERB_CMD(AC_VERB_GET_PIN_SENSE, RT298_MIC1, 0) | ||
85 | #define RT298_SET_DMIC2_DEFAULT\ | ||
86 | VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT298_DMIC2, 0) | ||
87 | #define RT298_SET_SPDIF_DEFAULT\ | ||
88 | VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT298_SPDIF, 0) | ||
89 | #define RT298_DACL_GAIN\ | ||
90 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_DAC_OUT1, 0xa000) | ||
91 | #define RT298_DACR_GAIN\ | ||
92 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_DAC_OUT1, 0x9000) | ||
93 | #define RT298_ADCL_GAIN\ | ||
94 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0x6000) | ||
95 | #define RT298_ADCR_GAIN\ | ||
96 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0x5000) | ||
97 | #define RT298_MIC_GAIN\ | ||
98 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIC1, 0x7000) | ||
99 | #define RT298_SPOL_GAIN\ | ||
100 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_SPK_OUT, 0xa000) | ||
101 | #define RT298_SPOR_GAIN\ | ||
102 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_SPK_OUT, 0x9000) | ||
103 | #define RT298_HPOL_GAIN\ | ||
104 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0xa000) | ||
105 | #define RT298_HPOR_GAIN\ | ||
106 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0x9000) | ||
107 | #define RT298_F_DAC_SWITCH\ | ||
108 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_OUT1, 0x7000) | ||
109 | #define RT298_F_RECMIX_SWITCH\ | ||
110 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_OUT1, 0x7100) | ||
111 | #define RT298_REC_MIC_SWITCH\ | ||
112 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7000) | ||
113 | #define RT298_REC_I2S_SWITCH\ | ||
114 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7100) | ||
115 | #define RT298_REC_LINE_SWITCH\ | ||
116 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7200) | ||
117 | #define RT298_REC_BEEP_SWITCH\ | ||
118 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7300) | ||
119 | #define RT298_DAC_FORMAT\ | ||
120 | VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT298_DAC_OUT1, 0) | ||
121 | #define RT298_ADC_FORMAT\ | ||
122 | VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT298_ADC_IN1, 0) | ||
123 | #define RT298_COEF_INDEX\ | ||
124 | VERB_CMD(AC_VERB_SET_COEF_INDEX, RT298_VENDOR_REGISTERS, 0) | ||
125 | #define RT298_PROC_COEF\ | ||
126 | VERB_CMD(AC_VERB_SET_PROC_COEF, RT298_VENDOR_REGISTERS, 0) | ||
127 | |||
128 | /* Index registers */ | ||
129 | #define RT298_A_BIAS_CTRL1 0x01 | ||
130 | #define RT298_A_BIAS_CTRL2 0x02 | ||
131 | #define RT298_POWER_CTRL1 0x03 | ||
132 | #define RT298_A_BIAS_CTRL3 0x04 | ||
133 | #define RT298_POWER_CTRL2 0x08 | ||
134 | #define RT298_I2S_CTRL1 0x09 | ||
135 | #define RT298_I2S_CTRL2 0x0a | ||
136 | #define RT298_CLK_DIV 0x0b | ||
137 | #define RT298_DC_GAIN 0x0d | ||
138 | #define RT298_POWER_CTRL3 0x0f | ||
139 | #define RT298_MIC1_DET_CTRL 0x19 | ||
140 | #define RT298_MISC_CTRL1 0x20 | ||
141 | #define RT298_IRQ_CTRL 0x33 | ||
142 | #define RT298_WIND_FILTER_CTRL 0x46 | ||
143 | #define RT298_PLL_CTRL1 0x49 | ||
144 | #define RT298_CBJ_CTRL1 0x4f | ||
145 | #define RT298_CBJ_CTRL2 0x50 | ||
146 | #define RT298_PLL_CTRL 0x63 | ||
147 | #define RT298_DEPOP_CTRL1 0x66 | ||
148 | #define RT298_DEPOP_CTRL2 0x67 | ||
149 | #define RT298_DEPOP_CTRL3 0x68 | ||
150 | #define RT298_DEPOP_CTRL4 0x69 | ||
151 | |||
152 | /* SPDIF (0x06) */ | ||
153 | #define RT298_SPDIF_SEL_SFT 0 | ||
154 | #define RT298_SPDIF_SEL_PCM0 0 | ||
155 | #define RT298_SPDIF_SEL_PCM1 1 | ||
156 | #define RT298_SPDIF_SEL_SPOUT 2 | ||
157 | #define RT298_SPDIF_SEL_PP 3 | ||
158 | |||
159 | /* RECMIX (0x0b) */ | ||
160 | #define RT298_M_REC_BEEP_SFT 0 | ||
161 | #define RT298_M_REC_LINE1_SFT 1 | ||
162 | #define RT298_M_REC_MIC1_SFT 2 | ||
163 | #define RT298_M_REC_I2S_SFT 3 | ||
164 | |||
165 | /* Front (0x0c) */ | ||
166 | #define RT298_M_FRONT_DAC_SFT 0 | ||
167 | #define RT298_M_FRONT_REC_SFT 1 | ||
168 | |||
169 | /* SPK-OUT (0x14) */ | ||
170 | #define RT298_M_SPK_MUX_SFT 14 | ||
171 | #define RT298_SPK_SEL_MASK 0x1 | ||
172 | #define RT298_SPK_SEL_SFT 0 | ||
173 | #define RT298_SPK_SEL_F 0 | ||
174 | #define RT298_SPK_SEL_S 1 | ||
175 | |||
176 | /* HP-OUT (0x21) */ | ||
177 | #define RT298_M_HP_MUX_SFT 14 | ||
178 | #define RT298_HP_SEL_MASK 0x1 | ||
179 | #define RT298_HP_SEL_SFT 0 | ||
180 | #define RT298_HP_SEL_F 0 | ||
181 | #define RT298_HP_SEL_S 1 | ||
182 | |||
183 | /* ADC (0x22) (0x23) */ | ||
184 | #define RT298_ADC_SEL_MASK 0x7 | ||
185 | #define RT298_ADC_SEL_SFT 0 | ||
186 | #define RT298_ADC_SEL_SURR 0 | ||
187 | #define RT298_ADC_SEL_FRONT 1 | ||
188 | #define RT298_ADC_SEL_DMIC 2 | ||
189 | #define RT298_ADC_SEL_BEEP 4 | ||
190 | #define RT298_ADC_SEL_LINE1 5 | ||
191 | #define RT298_ADC_SEL_I2S 6 | ||
192 | #define RT298_ADC_SEL_MIC1 7 | ||
193 | |||
194 | #define RT298_SCLK_S_MCLK 0 | ||
195 | #define RT298_SCLK_S_PLL 1 | ||
196 | |||
197 | enum { | ||
198 | RT298_AIF1, | ||
199 | RT298_AIF2, | ||
200 | RT298_AIFS, | ||
201 | }; | ||
202 | |||
203 | int rt298_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack); | ||
204 | |||
205 | #endif /* __RT298_H__ */ | ||
206 | |||
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 058167c80d71..1be2bab7dee3 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c | |||
@@ -174,16 +174,15 @@ static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); | |||
174 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0); | 174 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0); |
175 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); | 175 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); |
176 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */ | 176 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */ |
177 | static unsigned int mic_bst_tlv[] = { | 177 | static const DECLARE_TLV_DB_RANGE(mic_bst_tlv, |
178 | TLV_DB_RANGE_HEAD(7), | ||
179 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 178 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
180 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | 179 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), |
181 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | 180 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), |
182 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), | 181 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), |
183 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), | 182 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), |
184 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), | 183 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), |
185 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | 184 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0) |
186 | }; | 185 | ); |
187 | 186 | ||
188 | static int rt5631_dmic_get(struct snd_kcontrol *kcontrol, | 187 | static int rt5631_dmic_get(struct snd_kcontrol *kcontrol, |
189 | struct snd_ctl_elem_value *ucontrol) | 188 | struct snd_ctl_elem_value *ucontrol) |
@@ -1725,7 +1724,6 @@ static int rt5631_i2c_remove(struct i2c_client *client) | |||
1725 | static struct i2c_driver rt5631_i2c_driver = { | 1724 | static struct i2c_driver rt5631_i2c_driver = { |
1726 | .driver = { | 1725 | .driver = { |
1727 | .name = "rt5631", | 1726 | .name = "rt5631", |
1728 | .owner = THIS_MODULE, | ||
1729 | .of_match_table = of_match_ptr(rt5631_i2c_dt_ids), | 1727 | .of_match_table = of_match_ptr(rt5631_i2c_dt_ids), |
1730 | }, | 1728 | }, |
1731 | .probe = rt5631_i2c_probe, | 1729 | .probe = rt5631_i2c_probe, |
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 9bc78e57513d..e1ceeb885f7d 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
@@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5640_ranges[] = { | |||
51 | .window_len = 0x1, }, | 51 | .window_len = 0x1, }, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static const struct reg_default init_list[] = { | 54 | static const struct reg_sequence init_list[] = { |
55 | {RT5640_PR_BASE + 0x3d, 0x3600}, | 55 | {RT5640_PR_BASE + 0x3d, 0x3600}, |
56 | {RT5640_PR_BASE + 0x12, 0x0aa8}, | 56 | {RT5640_PR_BASE + 0x12, 0x0aa8}, |
57 | {RT5640_PR_BASE + 0x14, 0x0aaa}, | 57 | {RT5640_PR_BASE + 0x14, 0x0aaa}, |
@@ -347,16 +347,15 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | |||
347 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | 347 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); |
348 | 348 | ||
349 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | 349 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ |
350 | static unsigned int bst_tlv[] = { | 350 | static const DECLARE_TLV_DB_RANGE(bst_tlv, |
351 | TLV_DB_RANGE_HEAD(7), | ||
352 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 351 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
353 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | 352 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), |
354 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | 353 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), |
355 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), | 354 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), |
356 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), | 355 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), |
357 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), | 356 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), |
358 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | 357 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0) |
359 | }; | 358 | ); |
360 | 359 | ||
361 | /* Interface data select */ | 360 | /* Interface data select */ |
362 | static const char * const rt5640_data_select[] = { | 361 | static const char * const rt5640_data_select[] = { |
@@ -459,10 +458,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
459 | { | 458 | { |
460 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | 459 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
461 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | 460 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); |
462 | int idx = -EINVAL; | 461 | int idx, rate; |
463 | |||
464 | idx = rl6231_calc_dmic_clk(rt5640->sysclk); | ||
465 | 462 | ||
463 | rate = rt5640->sysclk / rl6231_get_pre_div(rt5640->regmap, | ||
464 | RT5640_ADDA_CLK1, RT5640_I2S_PD1_SFT); | ||
465 | idx = rl6231_calc_dmic_clk(rate); | ||
466 | if (idx < 0) | 466 | if (idx < 0) |
467 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | 467 | dev_err(codec->dev, "Failed to set DMIC clock\n"); |
468 | else | 468 | else |
@@ -984,6 +984,35 @@ static int rt5640_hp_event(struct snd_soc_dapm_widget *w, | |||
984 | return 0; | 984 | return 0; |
985 | } | 985 | } |
986 | 986 | ||
987 | static int rt5640_lout_event(struct snd_soc_dapm_widget *w, | ||
988 | struct snd_kcontrol *kcontrol, int event) | ||
989 | { | ||
990 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
991 | |||
992 | switch (event) { | ||
993 | case SND_SOC_DAPM_POST_PMU: | ||
994 | hp_amp_power_on(codec); | ||
995 | snd_soc_update_bits(codec, RT5640_PWR_ANLG1, | ||
996 | RT5640_PWR_LM, RT5640_PWR_LM); | ||
997 | snd_soc_update_bits(codec, RT5640_OUTPUT, | ||
998 | RT5640_L_MUTE | RT5640_R_MUTE, 0); | ||
999 | break; | ||
1000 | |||
1001 | case SND_SOC_DAPM_PRE_PMD: | ||
1002 | snd_soc_update_bits(codec, RT5640_OUTPUT, | ||
1003 | RT5640_L_MUTE | RT5640_R_MUTE, | ||
1004 | RT5640_L_MUTE | RT5640_R_MUTE); | ||
1005 | snd_soc_update_bits(codec, RT5640_PWR_ANLG1, | ||
1006 | RT5640_PWR_LM, 0); | ||
1007 | break; | ||
1008 | |||
1009 | default: | ||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
987 | static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w, | 1016 | static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w, |
988 | struct snd_kcontrol *kcontrol, int event) | 1017 | struct snd_kcontrol *kcontrol, int event) |
989 | { | 1018 | { |
@@ -1179,13 +1208,16 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = { | |||
1179 | 0, rt5640_spo_l_mix, ARRAY_SIZE(rt5640_spo_l_mix)), | 1208 | 0, rt5640_spo_l_mix, ARRAY_SIZE(rt5640_spo_l_mix)), |
1180 | SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0, | 1209 | SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0, |
1181 | 0, rt5640_spo_r_mix, ARRAY_SIZE(rt5640_spo_r_mix)), | 1210 | 0, rt5640_spo_r_mix, ARRAY_SIZE(rt5640_spo_r_mix)), |
1182 | SND_SOC_DAPM_MIXER("LOUT MIX", RT5640_PWR_ANLG1, RT5640_PWR_LM_BIT, 0, | 1211 | SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0, |
1183 | rt5640_lout_mix, ARRAY_SIZE(rt5640_lout_mix)), | 1212 | rt5640_lout_mix, ARRAY_SIZE(rt5640_lout_mix)), |
1184 | SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM, | 1213 | SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM, |
1185 | 0, 0, rt5640_hp_power_event, SND_SOC_DAPM_POST_PMU), | 1214 | 0, 0, rt5640_hp_power_event, SND_SOC_DAPM_POST_PMU), |
1186 | SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, | 1215 | SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, |
1187 | rt5640_hp_event, | 1216 | rt5640_hp_event, |
1188 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 1217 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
1218 | SND_SOC_DAPM_PGA_S("LOUT amp", 1, SND_SOC_NOPM, 0, 0, | ||
1219 | rt5640_lout_event, | ||
1220 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
1189 | SND_SOC_DAPM_SUPPLY("HP L Amp", RT5640_PWR_ANLG1, | 1221 | SND_SOC_DAPM_SUPPLY("HP L Amp", RT5640_PWR_ANLG1, |
1190 | RT5640_PWR_HP_L_BIT, 0, NULL, 0), | 1222 | RT5640_PWR_HP_L_BIT, 0, NULL, 0), |
1191 | SND_SOC_DAPM_SUPPLY("HP R Amp", RT5640_PWR_ANLG1, | 1223 | SND_SOC_DAPM_SUPPLY("HP R Amp", RT5640_PWR_ANLG1, |
@@ -1500,8 +1532,10 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = { | |||
1500 | {"HP R Playback", "Switch", "HP Amp"}, | 1532 | {"HP R Playback", "Switch", "HP Amp"}, |
1501 | {"HPOL", NULL, "HP L Playback"}, | 1533 | {"HPOL", NULL, "HP L Playback"}, |
1502 | {"HPOR", NULL, "HP R Playback"}, | 1534 | {"HPOR", NULL, "HP R Playback"}, |
1503 | {"LOUTL", NULL, "LOUT MIX"}, | 1535 | |
1504 | {"LOUTR", NULL, "LOUT MIX"}, | 1536 | {"LOUT amp", NULL, "LOUT MIX"}, |
1537 | {"LOUTL", NULL, "LOUT amp"}, | ||
1538 | {"LOUTR", NULL, "LOUT amp"}, | ||
1505 | }; | 1539 | }; |
1506 | 1540 | ||
1507 | static const struct snd_soc_dapm_route rt5640_specific_dapm_routes[] = { | 1541 | static const struct snd_soc_dapm_route rt5640_specific_dapm_routes[] = { |
@@ -2207,7 +2241,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c, | |||
2207 | regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val); | 2241 | regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val); |
2208 | if (val != RT5640_DEVICE_ID) { | 2242 | if (val != RT5640_DEVICE_ID) { |
2209 | dev_err(&i2c->dev, | 2243 | dev_err(&i2c->dev, |
2210 | "Device with ID register %x is not rt5640/39\n", val); | 2244 | "Device with ID register %#x is not rt5640/39\n", val); |
2211 | return -ENODEV; | 2245 | return -ENODEV; |
2212 | } | 2246 | } |
2213 | 2247 | ||
@@ -2242,7 +2276,6 @@ static int rt5640_i2c_remove(struct i2c_client *i2c) | |||
2242 | static struct i2c_driver rt5640_i2c_driver = { | 2276 | static struct i2c_driver rt5640_i2c_driver = { |
2243 | .driver = { | 2277 | .driver = { |
2244 | .name = "rt5640", | 2278 | .name = "rt5640", |
2245 | .owner = THIS_MODULE, | ||
2246 | .acpi_match_table = ACPI_PTR(rt5640_acpi_match), | 2279 | .acpi_match_table = ACPI_PTR(rt5640_acpi_match), |
2247 | .of_match_table = of_match_ptr(rt5640_of_match), | 2280 | .of_match_table = of_match_ptr(rt5640_of_match), |
2248 | }, | 2281 | }, |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 961bd7e5877e..4972bf3efa91 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/gpio/consumer.h> | 21 | #include <linux/gpio/consumer.h> |
22 | #include <linux/acpi.h> | 22 | #include <linux/acpi.h> |
23 | #include <linux/dmi.h> | 23 | #include <linux/dmi.h> |
24 | #include <linux/regulator/consumer.h> | ||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
26 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
@@ -54,7 +55,7 @@ static const struct regmap_range_cfg rt5645_ranges[] = { | |||
54 | }, | 55 | }, |
55 | }; | 56 | }; |
56 | 57 | ||
57 | static const struct reg_default init_list[] = { | 58 | static const struct reg_sequence init_list[] = { |
58 | {RT5645_PR_BASE + 0x3d, 0x3600}, | 59 | {RT5645_PR_BASE + 0x3d, 0x3600}, |
59 | {RT5645_PR_BASE + 0x1c, 0xfd20}, | 60 | {RT5645_PR_BASE + 0x1c, 0xfd20}, |
60 | {RT5645_PR_BASE + 0x20, 0x611f}, | 61 | {RT5645_PR_BASE + 0x20, 0x611f}, |
@@ -63,7 +64,7 @@ static const struct reg_default init_list[] = { | |||
63 | }; | 64 | }; |
64 | #define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list) | 65 | #define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list) |
65 | 66 | ||
66 | static const struct reg_default rt5650_init_list[] = { | 67 | static const struct reg_sequence rt5650_init_list[] = { |
67 | {0xf6, 0x0100}, | 68 | {0xf6, 0x0100}, |
68 | }; | 69 | }; |
69 | 70 | ||
@@ -223,6 +224,39 @@ static const struct reg_default rt5645_reg[] = { | |||
223 | { 0xff, 0x6308 }, | 224 | { 0xff, 0x6308 }, |
224 | }; | 225 | }; |
225 | 226 | ||
227 | static const char *const rt5645_supply_names[] = { | ||
228 | "avdd", | ||
229 | "cpvdd", | ||
230 | }; | ||
231 | |||
232 | struct rt5645_priv { | ||
233 | struct snd_soc_codec *codec; | ||
234 | struct rt5645_platform_data pdata; | ||
235 | struct regmap *regmap; | ||
236 | struct i2c_client *i2c; | ||
237 | struct gpio_desc *gpiod_hp_det; | ||
238 | struct snd_soc_jack *hp_jack; | ||
239 | struct snd_soc_jack *mic_jack; | ||
240 | struct snd_soc_jack *btn_jack; | ||
241 | struct delayed_work jack_detect_work; | ||
242 | struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)]; | ||
243 | |||
244 | int codec_type; | ||
245 | int sysclk; | ||
246 | int sysclk_src; | ||
247 | int lrck[RT5645_AIFS]; | ||
248 | int bclk[RT5645_AIFS]; | ||
249 | int master[RT5645_AIFS]; | ||
250 | |||
251 | int pll_src; | ||
252 | int pll_in; | ||
253 | int pll_out; | ||
254 | |||
255 | int jack_type; | ||
256 | bool en_button_func; | ||
257 | bool hp_on; | ||
258 | }; | ||
259 | |||
226 | static int rt5645_reset(struct snd_soc_codec *codec) | 260 | static int rt5645_reset(struct snd_soc_codec *codec) |
227 | { | 261 | { |
228 | return snd_soc_write(codec, RT5645_RESET, 0); | 262 | return snd_soc_write(codec, RT5645_RESET, 0); |
@@ -360,6 +394,7 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg) | |||
360 | case RT5645_DEPOP_M1: | 394 | case RT5645_DEPOP_M1: |
361 | case RT5645_DEPOP_M2: | 395 | case RT5645_DEPOP_M2: |
362 | case RT5645_DEPOP_M3: | 396 | case RT5645_DEPOP_M3: |
397 | case RT5645_CHARGE_PUMP: | ||
363 | case RT5645_MICBIAS: | 398 | case RT5645_MICBIAS: |
364 | case RT5645_A_JD_CTRL1: | 399 | case RT5645_A_JD_CTRL1: |
365 | case RT5645_VAD_CTRL4: | 400 | case RT5645_VAD_CTRL4: |
@@ -424,16 +459,15 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); | |||
424 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | 459 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); |
425 | 460 | ||
426 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | 461 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ |
427 | static unsigned int bst_tlv[] = { | 462 | static const DECLARE_TLV_DB_RANGE(bst_tlv, |
428 | TLV_DB_RANGE_HEAD(7), | ||
429 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 463 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
430 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | 464 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), |
431 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | 465 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), |
432 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), | 466 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), |
433 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), | 467 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), |
434 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), | 468 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), |
435 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | 469 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0) |
436 | }; | 470 | ); |
437 | 471 | ||
438 | static const struct snd_kcontrol_new rt5645_snd_controls[] = { | 472 | static const struct snd_kcontrol_new rt5645_snd_controls[] = { |
439 | /* Speaker Output Volume */ | 473 | /* Speaker Output Volume */ |
@@ -510,10 +544,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
510 | { | 544 | { |
511 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | 545 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
512 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 546 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
513 | int idx = -EINVAL; | 547 | int idx, rate; |
514 | |||
515 | idx = rl6231_calc_dmic_clk(rt5645->sysclk); | ||
516 | 548 | ||
549 | rate = rt5645->sysclk / rl6231_get_pre_div(rt5645->regmap, | ||
550 | RT5645_ADDA_CLK1, RT5645_I2S_PD1_SFT); | ||
551 | idx = rl6231_calc_dmic_clk(rate); | ||
517 | if (idx < 0) | 552 | if (idx < 0) |
518 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | 553 | dev_err(codec->dev, "Failed to set DMIC clock\n"); |
519 | else | 554 | else |
@@ -1331,15 +1366,23 @@ static void hp_amp_power(struct snd_soc_codec *codec, int on) | |||
1331 | if (on) { | 1366 | if (on) { |
1332 | if (hp_amp_power_count <= 0) { | 1367 | if (hp_amp_power_count <= 0) { |
1333 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { | 1368 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { |
1369 | snd_soc_write(codec, RT5645_DEPOP_M2, 0x3100); | ||
1334 | snd_soc_write(codec, RT5645_CHARGE_PUMP, | 1370 | snd_soc_write(codec, RT5645_CHARGE_PUMP, |
1335 | 0x0e06); | 1371 | 0x0e06); |
1336 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x001d); | 1372 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x000d); |
1373 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | ||
1374 | RT5645_HP_DCC_INT1, 0x9f01); | ||
1375 | msleep(20); | ||
1376 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | ||
1377 | RT5645_HP_CO_MASK, RT5645_HP_CO_EN); | ||
1337 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | 1378 | regmap_write(rt5645->regmap, RT5645_PR_BASE + |
1338 | 0x3e, 0x7400); | 1379 | 0x3e, 0x7400); |
1339 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); | 1380 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); |
1340 | regmap_write(rt5645->regmap, RT5645_PR_BASE + | 1381 | regmap_write(rt5645->regmap, RT5645_PR_BASE + |
1341 | RT5645_MAMP_INT_REG2, 0xfc00); | 1382 | RT5645_MAMP_INT_REG2, 0xfc00); |
1342 | snd_soc_write(codec, RT5645_DEPOP_M2, 0x1140); | 1383 | snd_soc_write(codec, RT5645_DEPOP_M2, 0x1140); |
1384 | mdelay(5); | ||
1385 | rt5645->hp_on = true; | ||
1343 | } else { | 1386 | } else { |
1344 | /* depop parameters */ | 1387 | /* depop parameters */ |
1345 | snd_soc_update_bits(codec, RT5645_DEPOP_M2, | 1388 | snd_soc_update_bits(codec, RT5645_DEPOP_M2, |
@@ -1553,6 +1596,27 @@ static int rt5645_bst2_event(struct snd_soc_dapm_widget *w, | |||
1553 | return 0; | 1596 | return 0; |
1554 | } | 1597 | } |
1555 | 1598 | ||
1599 | static int rt5650_hp_event(struct snd_soc_dapm_widget *w, | ||
1600 | struct snd_kcontrol *k, int event) | ||
1601 | { | ||
1602 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
1603 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | ||
1604 | |||
1605 | switch (event) { | ||
1606 | case SND_SOC_DAPM_POST_PMU: | ||
1607 | if (rt5645->hp_on) { | ||
1608 | msleep(100); | ||
1609 | rt5645->hp_on = false; | ||
1610 | } | ||
1611 | break; | ||
1612 | |||
1613 | default: | ||
1614 | return 0; | ||
1615 | } | ||
1616 | |||
1617 | return 0; | ||
1618 | } | ||
1619 | |||
1556 | static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { | 1620 | static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { |
1557 | SND_SOC_DAPM_SUPPLY("LDO2", RT5645_PWR_MIXER, | 1621 | SND_SOC_DAPM_SUPPLY("LDO2", RT5645_PWR_MIXER, |
1558 | RT5645_PWR_LDO2_BIT, 0, NULL, 0), | 1622 | RT5645_PWR_LDO2_BIT, 0, NULL, 0), |
@@ -1697,15 +1761,6 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { | |||
1697 | SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), | 1761 | SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), |
1698 | 1762 | ||
1699 | /* IF1 2 Mux */ | 1763 | /* IF1 2 Mux */ |
1700 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC1 Swap Mux", SND_SOC_NOPM, | ||
1701 | 0, 0, &rt5645_if1_adc1_in_mux), | ||
1702 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC2 Swap Mux", SND_SOC_NOPM, | ||
1703 | 0, 0, &rt5645_if1_adc2_in_mux), | ||
1704 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC3 Swap Mux", SND_SOC_NOPM, | ||
1705 | 0, 0, &rt5645_if1_adc3_in_mux), | ||
1706 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC Mux", SND_SOC_NOPM, | ||
1707 | 0, 0, &rt5645_if1_adc_in_mux), | ||
1708 | |||
1709 | SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM, | 1764 | SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM, |
1710 | 0, 0, &rt5645_if2_adc_in_mux), | 1765 | 0, 0, &rt5645_if2_adc_in_mux), |
1711 | 1766 | ||
@@ -1716,14 +1771,6 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { | |||
1716 | SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0), | 1771 | SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0), |
1717 | SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0), | 1772 | SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0), |
1718 | SND_SOC_DAPM_PGA("IF1 DAC3", SND_SOC_NOPM, 0, 0, NULL, 0), | 1773 | SND_SOC_DAPM_PGA("IF1 DAC3", SND_SOC_NOPM, 0, 0, NULL, 0), |
1719 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 L Mux", SND_SOC_NOPM, 0, 0, | ||
1720 | &rt5645_if1_dac0_tdm_sel_mux), | ||
1721 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 R Mux", SND_SOC_NOPM, 0, 0, | ||
1722 | &rt5645_if1_dac1_tdm_sel_mux), | ||
1723 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 L Mux", SND_SOC_NOPM, 0, 0, | ||
1724 | &rt5645_if1_dac2_tdm_sel_mux), | ||
1725 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 R Mux", SND_SOC_NOPM, 0, 0, | ||
1726 | &rt5645_if1_dac3_tdm_sel_mux), | ||
1727 | SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | 1774 | SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), |
1728 | SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), | 1775 | SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), |
1729 | SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), | 1776 | SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), |
@@ -1854,6 +1901,26 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { | |||
1854 | SND_SOC_DAPM_OUTPUT("PDM1R"), | 1901 | SND_SOC_DAPM_OUTPUT("PDM1R"), |
1855 | SND_SOC_DAPM_OUTPUT("SPOL"), | 1902 | SND_SOC_DAPM_OUTPUT("SPOL"), |
1856 | SND_SOC_DAPM_OUTPUT("SPOR"), | 1903 | SND_SOC_DAPM_OUTPUT("SPOR"), |
1904 | SND_SOC_DAPM_POST("DAPM_POST", rt5650_hp_event), | ||
1905 | }; | ||
1906 | |||
1907 | static const struct snd_soc_dapm_widget rt5645_specific_dapm_widgets[] = { | ||
1908 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 L Mux", SND_SOC_NOPM, 0, 0, | ||
1909 | &rt5645_if1_dac0_tdm_sel_mux), | ||
1910 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 R Mux", SND_SOC_NOPM, 0, 0, | ||
1911 | &rt5645_if1_dac1_tdm_sel_mux), | ||
1912 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 L Mux", SND_SOC_NOPM, 0, 0, | ||
1913 | &rt5645_if1_dac2_tdm_sel_mux), | ||
1914 | SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 R Mux", SND_SOC_NOPM, 0, 0, | ||
1915 | &rt5645_if1_dac3_tdm_sel_mux), | ||
1916 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC Mux", SND_SOC_NOPM, | ||
1917 | 0, 0, &rt5645_if1_adc_in_mux), | ||
1918 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC1 Swap Mux", SND_SOC_NOPM, | ||
1919 | 0, 0, &rt5645_if1_adc1_in_mux), | ||
1920 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC2 Swap Mux", SND_SOC_NOPM, | ||
1921 | 0, 0, &rt5645_if1_adc2_in_mux), | ||
1922 | SND_SOC_DAPM_MUX("RT5645 IF1 ADC3 Swap Mux", SND_SOC_NOPM, | ||
1923 | 0, 0, &rt5645_if1_adc3_in_mux), | ||
1857 | }; | 1924 | }; |
1858 | 1925 | ||
1859 | static const struct snd_soc_dapm_widget rt5650_specific_dapm_widgets[] = { | 1926 | static const struct snd_soc_dapm_widget rt5650_specific_dapm_widgets[] = { |
@@ -2642,7 +2709,7 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, | |||
2642 | 2709 | ||
2643 | switch (level) { | 2710 | switch (level) { |
2644 | case SND_SOC_BIAS_PREPARE: | 2711 | case SND_SOC_BIAS_PREPARE: |
2645 | if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { | 2712 | if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) { |
2646 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, | 2713 | snd_soc_update_bits(codec, RT5645_PWR_ANLG1, |
2647 | RT5645_PWR_VREF1 | RT5645_PWR_MB | | 2714 | RT5645_PWR_VREF1 | RT5645_PWR_MB | |
2648 | RT5645_PWR_BG | RT5645_PWR_VREF2, | 2715 | RT5645_PWR_BG | RT5645_PWR_VREF2, |
@@ -2686,94 +2753,15 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, | |||
2686 | return 0; | 2753 | return 0; |
2687 | } | 2754 | } |
2688 | 2755 | ||
2689 | static int rt5650_calibration(struct rt5645_priv *rt5645) | ||
2690 | { | ||
2691 | int val, i; | ||
2692 | int ret = -1; | ||
2693 | |||
2694 | regcache_cache_bypass(rt5645->regmap, true); | ||
2695 | regmap_write(rt5645->regmap, RT5645_RESET, 0); | ||
2696 | regmap_write(rt5645->regmap, RT5645_GEN_CTRL3, 0x0800); | ||
2697 | regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_CHOP_DAC_ADC, | ||
2698 | 0x3600); | ||
2699 | regmap_write(rt5645->regmap, RT5645_PR_BASE + 0x25, 0x7000); | ||
2700 | regmap_write(rt5645->regmap, RT5645_I2S1_SDP, 0x8008); | ||
2701 | /* headset type */ | ||
2702 | regmap_write(rt5645->regmap, RT5645_GEN_CTRL1, 0x2061); | ||
2703 | regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0006); | ||
2704 | regmap_write(rt5645->regmap, RT5645_PWR_ANLG1, 0x2012); | ||
2705 | regmap_write(rt5645->regmap, RT5645_PWR_MIXER, 0x0002); | ||
2706 | regmap_write(rt5645->regmap, RT5645_PWR_VOL, 0x0020); | ||
2707 | regmap_write(rt5645->regmap, RT5645_JD_CTRL3, 0x00f0); | ||
2708 | regmap_write(rt5645->regmap, RT5645_IN1_CTRL1, 0x0006); | ||
2709 | regmap_write(rt5645->regmap, RT5645_IN1_CTRL2, 0x1827); | ||
2710 | regmap_write(rt5645->regmap, RT5645_IN1_CTRL2, 0x0827); | ||
2711 | msleep(400); | ||
2712 | /* Inline command */ | ||
2713 | regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x0001); | ||
2714 | regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD2, 0xc000); | ||
2715 | regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD1, 0x0008); | ||
2716 | /* Calbration */ | ||
2717 | regmap_write(rt5645->regmap, RT5645_GLB_CLK, 0x8000); | ||
2718 | regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x0000); | ||
2719 | regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD2, 0xc000); | ||
2720 | regmap_write(rt5645->regmap, RT5650_4BTN_IL_CMD1, 0x0008); | ||
2721 | regmap_write(rt5645->regmap, RT5645_PWR_DIG2, 0x8800); | ||
2722 | regmap_write(rt5645->regmap, RT5645_PWR_ANLG1, 0xe8fa); | ||
2723 | regmap_write(rt5645->regmap, RT5645_PWR_ANLG2, 0x8c04); | ||
2724 | regmap_write(rt5645->regmap, RT5645_DEPOP_M2, 0x3100); | ||
2725 | regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0e06); | ||
2726 | regmap_write(rt5645->regmap, RT5645_BASS_BACK, 0x8a13); | ||
2727 | regmap_write(rt5645->regmap, RT5645_GEN_CTRL3, 0x0820); | ||
2728 | regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x000d); | ||
2729 | /* Power on and Calbration */ | ||
2730 | regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_HP_DCC_INT1, | ||
2731 | 0x9f01); | ||
2732 | msleep(200); | ||
2733 | for (i = 0; i < 5; i++) { | ||
2734 | regmap_read(rt5645->regmap, RT5645_PR_BASE + 0x7a, &val); | ||
2735 | if (val != 0 && val != 0x3f3f) { | ||
2736 | ret = 0; | ||
2737 | break; | ||
2738 | } | ||
2739 | msleep(50); | ||
2740 | } | ||
2741 | pr_debug("%s: PR-7A = 0x%x\n", __func__, val); | ||
2742 | |||
2743 | /* mute */ | ||
2744 | regmap_write(rt5645->regmap, RT5645_PR_BASE + 0x3e, 0x7400); | ||
2745 | regmap_write(rt5645->regmap, RT5645_DEPOP_M3, 0x0737); | ||
2746 | regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_MAMP_INT_REG2, | ||
2747 | 0xfc00); | ||
2748 | regmap_write(rt5645->regmap, RT5645_DEPOP_M2, 0x1140); | ||
2749 | regmap_write(rt5645->regmap, RT5645_DEPOP_M1, 0x0000); | ||
2750 | regmap_write(rt5645->regmap, RT5645_GEN_CTRL2, 0x4020); | ||
2751 | regmap_write(rt5645->regmap, RT5645_PWR_ANLG2, 0x0006); | ||
2752 | regmap_write(rt5645->regmap, RT5645_PWR_DIG2, 0x0000); | ||
2753 | msleep(350); | ||
2754 | |||
2755 | regcache_cache_bypass(rt5645->regmap, false); | ||
2756 | |||
2757 | return ret; | ||
2758 | } | ||
2759 | |||
2760 | static void rt5645_enable_push_button_irq(struct snd_soc_codec *codec, | 2756 | static void rt5645_enable_push_button_irq(struct snd_soc_codec *codec, |
2761 | bool enable) | 2757 | bool enable) |
2762 | { | 2758 | { |
2763 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 2759 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
2764 | 2760 | ||
2765 | if (enable) { | 2761 | if (enable) { |
2766 | snd_soc_dapm_mutex_lock(&codec->dapm); | 2762 | snd_soc_dapm_force_enable_pin(dapm, "ADC L power"); |
2767 | snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, | 2763 | snd_soc_dapm_force_enable_pin(dapm, "ADC R power"); |
2768 | "ADC L power"); | 2764 | snd_soc_dapm_sync(dapm); |
2769 | snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, | ||
2770 | "ADC R power"); | ||
2771 | snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, | ||
2772 | "LDO2"); | ||
2773 | snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, | ||
2774 | "Mic Det Power"); | ||
2775 | snd_soc_dapm_sync_unlocked(&codec->dapm); | ||
2776 | snd_soc_dapm_mutex_unlock(&codec->dapm); | ||
2777 | 2765 | ||
2778 | snd_soc_update_bits(codec, | 2766 | snd_soc_update_bits(codec, |
2779 | RT5645_INT_IRQ_ST, 0x8, 0x8); | 2767 | RT5645_INT_IRQ_ST, 0x8, 0x8); |
@@ -2786,36 +2774,26 @@ static void rt5645_enable_push_button_irq(struct snd_soc_codec *codec, | |||
2786 | snd_soc_update_bits(codec, RT5650_4BTN_IL_CMD2, 0x8000, 0x0); | 2774 | snd_soc_update_bits(codec, RT5650_4BTN_IL_CMD2, 0x8000, 0x0); |
2787 | snd_soc_update_bits(codec, RT5645_INT_IRQ_ST, 0x8, 0x0); | 2775 | snd_soc_update_bits(codec, RT5645_INT_IRQ_ST, 0x8, 0x0); |
2788 | 2776 | ||
2789 | snd_soc_dapm_mutex_lock(&codec->dapm); | 2777 | snd_soc_dapm_disable_pin(dapm, "ADC L power"); |
2790 | snd_soc_dapm_disable_pin_unlocked(&codec->dapm, | 2778 | snd_soc_dapm_disable_pin(dapm, "ADC R power"); |
2791 | "ADC L power"); | 2779 | snd_soc_dapm_sync(dapm); |
2792 | snd_soc_dapm_disable_pin_unlocked(&codec->dapm, | ||
2793 | "ADC R power"); | ||
2794 | if (rt5645->pdata.jd_mode == 0) | ||
2795 | snd_soc_dapm_disable_pin_unlocked(&codec->dapm, | ||
2796 | "LDO2"); | ||
2797 | snd_soc_dapm_disable_pin_unlocked(&codec->dapm, | ||
2798 | "Mic Det Power"); | ||
2799 | snd_soc_dapm_sync_unlocked(&codec->dapm); | ||
2800 | snd_soc_dapm_mutex_unlock(&codec->dapm); | ||
2801 | } | 2780 | } |
2802 | } | 2781 | } |
2803 | 2782 | ||
2804 | static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) | 2783 | static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) |
2805 | { | 2784 | { |
2785 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
2806 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 2786 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
2807 | unsigned int val; | 2787 | unsigned int val; |
2808 | 2788 | ||
2809 | if (jack_insert) { | 2789 | if (jack_insert) { |
2810 | regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0006); | 2790 | regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0006); |
2811 | 2791 | ||
2812 | if (codec->component.card->instantiated) { | 2792 | /* for jack type detect */ |
2813 | /* for jack type detect */ | 2793 | snd_soc_dapm_force_enable_pin(dapm, "LDO2"); |
2814 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | 2794 | snd_soc_dapm_force_enable_pin(dapm, "Mic Det Power"); |
2815 | snd_soc_dapm_force_enable_pin(&codec->dapm, | 2795 | snd_soc_dapm_sync(dapm); |
2816 | "Mic Det Power"); | 2796 | if (!dapm->card->instantiated) { |
2817 | snd_soc_dapm_sync(&codec->dapm); | ||
2818 | } else { | ||
2819 | /* Power up necessary bits for JD if dapm is | 2797 | /* Power up necessary bits for JD if dapm is |
2820 | not ready yet */ | 2798 | not ready yet */ |
2821 | regmap_update_bits(rt5645->regmap, RT5645_PWR_ANLG1, | 2799 | regmap_update_bits(rt5645->regmap, RT5645_PWR_ANLG1, |
@@ -2828,14 +2806,15 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) | |||
2828 | } | 2806 | } |
2829 | 2807 | ||
2830 | regmap_write(rt5645->regmap, RT5645_JD_CTRL3, 0x00f0); | 2808 | regmap_write(rt5645->regmap, RT5645_JD_CTRL3, 0x00f0); |
2831 | regmap_write(rt5645->regmap, RT5645_IN1_CTRL1, 0x0006); | 2809 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2, |
2832 | regmap_update_bits(rt5645->regmap, | 2810 | RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD); |
2833 | RT5645_IN1_CTRL2, 0x1000, 0x1000); | 2811 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, |
2812 | RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN); | ||
2834 | msleep(100); | 2813 | msleep(100); |
2835 | regmap_update_bits(rt5645->regmap, | 2814 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2, |
2836 | RT5645_IN1_CTRL2, 0x1000, 0x0000); | 2815 | RT5645_CBJ_MN_JD, 0); |
2837 | 2816 | ||
2838 | msleep(450); | 2817 | msleep(600); |
2839 | regmap_read(rt5645->regmap, RT5645_IN1_CTRL3, &val); | 2818 | regmap_read(rt5645->regmap, RT5645_IN1_CTRL3, &val); |
2840 | val &= 0x7; | 2819 | val &= 0x7; |
2841 | dev_dbg(codec->dev, "val = %d\n", val); | 2820 | dev_dbg(codec->dev, "val = %d\n", val); |
@@ -2846,43 +2825,46 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) | |||
2846 | rt5645_enable_push_button_irq(codec, true); | 2825 | rt5645_enable_push_button_irq(codec, true); |
2847 | } | 2826 | } |
2848 | } else { | 2827 | } else { |
2849 | if (codec->component.card->instantiated) { | 2828 | snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); |
2850 | snd_soc_dapm_disable_pin(&codec->dapm, | 2829 | snd_soc_dapm_sync(dapm); |
2851 | "Mic Det Power"); | ||
2852 | snd_soc_dapm_sync(&codec->dapm); | ||
2853 | } else | ||
2854 | regmap_update_bits(rt5645->regmap, | ||
2855 | RT5645_PWR_VOL, RT5645_PWR_MIC_DET, 0); | ||
2856 | rt5645->jack_type = SND_JACK_HEADPHONE; | 2830 | rt5645->jack_type = SND_JACK_HEADPHONE; |
2857 | } | 2831 | } |
2858 | 2832 | ||
2833 | snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200); | ||
2834 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x001d); | ||
2835 | snd_soc_write(codec, RT5645_DEPOP_M1, 0x0001); | ||
2859 | } else { /* jack out */ | 2836 | } else { /* jack out */ |
2860 | rt5645->jack_type = 0; | 2837 | rt5645->jack_type = 0; |
2838 | |||
2839 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2, | ||
2840 | RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD); | ||
2841 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, | ||
2842 | RT5645_CBJ_BST1_EN, 0); | ||
2843 | |||
2861 | if (rt5645->en_button_func) | 2844 | if (rt5645->en_button_func) |
2862 | rt5645_enable_push_button_irq(codec, false); | 2845 | rt5645_enable_push_button_irq(codec, false); |
2863 | else { | 2846 | |
2864 | if (codec->component.card->instantiated) { | 2847 | if (rt5645->pdata.jd_mode == 0) |
2865 | if (rt5645->pdata.jd_mode == 0) | 2848 | snd_soc_dapm_disable_pin(dapm, "LDO2"); |
2866 | snd_soc_dapm_disable_pin(&codec->dapm, | 2849 | snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); |
2867 | "LDO2"); | 2850 | snd_soc_dapm_sync(dapm); |
2868 | snd_soc_dapm_disable_pin(&codec->dapm, | ||
2869 | "Mic Det Power"); | ||
2870 | snd_soc_dapm_sync(&codec->dapm); | ||
2871 | } else { | ||
2872 | if (rt5645->pdata.jd_mode == 0) | ||
2873 | regmap_update_bits(rt5645->regmap, | ||
2874 | RT5645_PWR_MIXER, | ||
2875 | RT5645_PWR_LDO2, 0); | ||
2876 | regmap_update_bits(rt5645->regmap, | ||
2877 | RT5645_PWR_VOL, RT5645_PWR_MIC_DET, 0); | ||
2878 | } | ||
2879 | } | ||
2880 | } | 2851 | } |
2881 | 2852 | ||
2882 | return rt5645->jack_type; | 2853 | return rt5645->jack_type; |
2883 | } | 2854 | } |
2884 | 2855 | ||
2885 | static int rt5645_irq_detection(struct rt5645_priv *rt5645); | 2856 | static int rt5645_button_detect(struct snd_soc_codec *codec) |
2857 | { | ||
2858 | int btn_type, val; | ||
2859 | |||
2860 | val = snd_soc_read(codec, RT5650_4BTN_IL_CMD1); | ||
2861 | pr_debug("val=0x%x\n", val); | ||
2862 | btn_type = val & 0xfff0; | ||
2863 | snd_soc_write(codec, RT5650_4BTN_IL_CMD1, val); | ||
2864 | |||
2865 | return btn_type; | ||
2866 | } | ||
2867 | |||
2886 | static irqreturn_t rt5645_irq(int irq, void *data); | 2868 | static irqreturn_t rt5645_irq(int irq, void *data); |
2887 | 2869 | ||
2888 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | 2870 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, |
@@ -2913,38 +2895,10 @@ static void rt5645_jack_detect_work(struct work_struct *work) | |||
2913 | { | 2895 | { |
2914 | struct rt5645_priv *rt5645 = | 2896 | struct rt5645_priv *rt5645 = |
2915 | container_of(work, struct rt5645_priv, jack_detect_work.work); | 2897 | container_of(work, struct rt5645_priv, jack_detect_work.work); |
2916 | |||
2917 | rt5645_irq_detection(rt5645); | ||
2918 | } | ||
2919 | |||
2920 | static irqreturn_t rt5645_irq(int irq, void *data) | ||
2921 | { | ||
2922 | struct rt5645_priv *rt5645 = data; | ||
2923 | |||
2924 | queue_delayed_work(system_power_efficient_wq, | ||
2925 | &rt5645->jack_detect_work, msecs_to_jiffies(250)); | ||
2926 | |||
2927 | return IRQ_HANDLED; | ||
2928 | } | ||
2929 | |||
2930 | static int rt5645_button_detect(struct snd_soc_codec *codec) | ||
2931 | { | ||
2932 | int btn_type, val; | ||
2933 | |||
2934 | val = snd_soc_read(codec, RT5650_4BTN_IL_CMD1); | ||
2935 | pr_debug("val=0x%x\n", val); | ||
2936 | btn_type = val & 0xfff0; | ||
2937 | snd_soc_write(codec, RT5650_4BTN_IL_CMD1, val); | ||
2938 | |||
2939 | return btn_type; | ||
2940 | } | ||
2941 | |||
2942 | static int rt5645_irq_detection(struct rt5645_priv *rt5645) | ||
2943 | { | ||
2944 | int val, btn_type, gpio_state = 0, report = 0; | 2898 | int val, btn_type, gpio_state = 0, report = 0; |
2945 | 2899 | ||
2946 | if (!rt5645->codec) | 2900 | if (!rt5645->codec) |
2947 | return -EINVAL; | 2901 | return; |
2948 | 2902 | ||
2949 | switch (rt5645->pdata.jd_mode) { | 2903 | switch (rt5645->pdata.jd_mode) { |
2950 | case 0: /* Not using rt5645 JD */ | 2904 | case 0: /* Not using rt5645 JD */ |
@@ -2958,7 +2912,7 @@ static int rt5645_irq_detection(struct rt5645_priv *rt5645) | |||
2958 | report, SND_JACK_HEADPHONE); | 2912 | report, SND_JACK_HEADPHONE); |
2959 | snd_soc_jack_report(rt5645->mic_jack, | 2913 | snd_soc_jack_report(rt5645->mic_jack, |
2960 | report, SND_JACK_MICROPHONE); | 2914 | report, SND_JACK_MICROPHONE); |
2961 | return report; | 2915 | return; |
2962 | case 1: /* 2 port */ | 2916 | case 1: /* 2 port */ |
2963 | val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0070; | 2917 | val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0070; |
2964 | break; | 2918 | break; |
@@ -3040,27 +2994,39 @@ static int rt5645_irq_detection(struct rt5645_priv *rt5645) | |||
3040 | snd_soc_jack_report(rt5645->btn_jack, | 2994 | snd_soc_jack_report(rt5645->btn_jack, |
3041 | report, SND_JACK_BTN_0 | SND_JACK_BTN_1 | | 2995 | report, SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
3042 | SND_JACK_BTN_2 | SND_JACK_BTN_3); | 2996 | SND_JACK_BTN_2 | SND_JACK_BTN_3); |
2997 | } | ||
2998 | |||
2999 | static irqreturn_t rt5645_irq(int irq, void *data) | ||
3000 | { | ||
3001 | struct rt5645_priv *rt5645 = data; | ||
3002 | |||
3003 | queue_delayed_work(system_power_efficient_wq, | ||
3004 | &rt5645->jack_detect_work, msecs_to_jiffies(250)); | ||
3043 | 3005 | ||
3044 | return report; | 3006 | return IRQ_HANDLED; |
3045 | } | 3007 | } |
3046 | 3008 | ||
3047 | static int rt5645_probe(struct snd_soc_codec *codec) | 3009 | static int rt5645_probe(struct snd_soc_codec *codec) |
3048 | { | 3010 | { |
3011 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
3049 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 3012 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
3050 | 3013 | ||
3051 | rt5645->codec = codec; | 3014 | rt5645->codec = codec; |
3052 | 3015 | ||
3053 | switch (rt5645->codec_type) { | 3016 | switch (rt5645->codec_type) { |
3054 | case CODEC_TYPE_RT5645: | 3017 | case CODEC_TYPE_RT5645: |
3055 | snd_soc_dapm_add_routes(&codec->dapm, | 3018 | snd_soc_dapm_new_controls(dapm, |
3019 | rt5645_specific_dapm_widgets, | ||
3020 | ARRAY_SIZE(rt5645_specific_dapm_widgets)); | ||
3021 | snd_soc_dapm_add_routes(dapm, | ||
3056 | rt5645_specific_dapm_routes, | 3022 | rt5645_specific_dapm_routes, |
3057 | ARRAY_SIZE(rt5645_specific_dapm_routes)); | 3023 | ARRAY_SIZE(rt5645_specific_dapm_routes)); |
3058 | break; | 3024 | break; |
3059 | case CODEC_TYPE_RT5650: | 3025 | case CODEC_TYPE_RT5650: |
3060 | snd_soc_dapm_new_controls(&codec->dapm, | 3026 | snd_soc_dapm_new_controls(dapm, |
3061 | rt5650_specific_dapm_widgets, | 3027 | rt5650_specific_dapm_widgets, |
3062 | ARRAY_SIZE(rt5650_specific_dapm_widgets)); | 3028 | ARRAY_SIZE(rt5650_specific_dapm_widgets)); |
3063 | snd_soc_dapm_add_routes(&codec->dapm, | 3029 | snd_soc_dapm_add_routes(dapm, |
3064 | rt5650_specific_dapm_routes, | 3030 | rt5650_specific_dapm_routes, |
3065 | ARRAY_SIZE(rt5650_specific_dapm_routes)); | 3031 | ARRAY_SIZE(rt5650_specific_dapm_routes)); |
3066 | break; | 3032 | break; |
@@ -3070,9 +3036,9 @@ static int rt5645_probe(struct snd_soc_codec *codec) | |||
3070 | 3036 | ||
3071 | /* for JD function */ | 3037 | /* for JD function */ |
3072 | if (rt5645->pdata.jd_mode) { | 3038 | if (rt5645->pdata.jd_mode) { |
3073 | snd_soc_dapm_force_enable_pin(&codec->dapm, "JD Power"); | 3039 | snd_soc_dapm_force_enable_pin(dapm, "JD Power"); |
3074 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | 3040 | snd_soc_dapm_force_enable_pin(dapm, "LDO2"); |
3075 | snd_soc_dapm_sync(&codec->dapm); | 3041 | snd_soc_dapm_sync(dapm); |
3076 | } | 3042 | } |
3077 | 3043 | ||
3078 | return 0; | 3044 | return 0; |
@@ -3113,7 +3079,7 @@ static int rt5645_resume(struct snd_soc_codec *codec) | |||
3113 | #define RT5645_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 3079 | #define RT5645_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
3114 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | 3080 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) |
3115 | 3081 | ||
3116 | static struct snd_soc_dai_ops rt5645_aif_dai_ops = { | 3082 | static const struct snd_soc_dai_ops rt5645_aif_dai_ops = { |
3117 | .hw_params = rt5645_hw_params, | 3083 | .hw_params = rt5645_hw_params, |
3118 | .set_fmt = rt5645_set_dai_fmt, | 3084 | .set_fmt = rt5645_set_dai_fmt, |
3119 | .set_sysclk = rt5645_set_dai_sysclk, | 3085 | .set_sysclk = rt5645_set_dai_sysclk, |
@@ -3224,7 +3190,7 @@ static int strago_quirk_cb(const struct dmi_system_id *id) | |||
3224 | return 1; | 3190 | return 1; |
3225 | } | 3191 | } |
3226 | 3192 | ||
3227 | static struct dmi_system_id dmi_platform_intel_braswell[] = { | 3193 | static const struct dmi_system_id dmi_platform_intel_braswell[] = { |
3228 | { | 3194 | { |
3229 | .ident = "Intel Strago", | 3195 | .ident = "Intel Strago", |
3230 | .callback = strago_quirk_cb, | 3196 | .callback = strago_quirk_cb, |
@@ -3232,6 +3198,13 @@ static struct dmi_system_id dmi_platform_intel_braswell[] = { | |||
3232 | DMI_MATCH(DMI_PRODUCT_NAME, "Strago"), | 3198 | DMI_MATCH(DMI_PRODUCT_NAME, "Strago"), |
3233 | }, | 3199 | }, |
3234 | }, | 3200 | }, |
3201 | { | ||
3202 | .ident = "Google Celes", | ||
3203 | .callback = strago_quirk_cb, | ||
3204 | .matches = { | ||
3205 | DMI_MATCH(DMI_PRODUCT_NAME, "Celes"), | ||
3206 | }, | ||
3207 | }, | ||
3235 | { } | 3208 | { } |
3236 | }; | 3209 | }; |
3237 | 3210 | ||
@@ -3254,7 +3227,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3254 | { | 3227 | { |
3255 | struct rt5645_platform_data *pdata = dev_get_platdata(&i2c->dev); | 3228 | struct rt5645_platform_data *pdata = dev_get_platdata(&i2c->dev); |
3256 | struct rt5645_priv *rt5645; | 3229 | struct rt5645_priv *rt5645; |
3257 | int ret; | 3230 | int ret, i; |
3258 | unsigned int val; | 3231 | unsigned int val; |
3259 | 3232 | ||
3260 | rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv), | 3233 | rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv), |
@@ -3288,6 +3261,24 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3288 | return ret; | 3261 | return ret; |
3289 | } | 3262 | } |
3290 | 3263 | ||
3264 | for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++) | ||
3265 | rt5645->supplies[i].supply = rt5645_supply_names[i]; | ||
3266 | |||
3267 | ret = devm_regulator_bulk_get(&i2c->dev, | ||
3268 | ARRAY_SIZE(rt5645->supplies), | ||
3269 | rt5645->supplies); | ||
3270 | if (ret) { | ||
3271 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
3272 | return ret; | ||
3273 | } | ||
3274 | |||
3275 | ret = regulator_bulk_enable(ARRAY_SIZE(rt5645->supplies), | ||
3276 | rt5645->supplies); | ||
3277 | if (ret) { | ||
3278 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
3279 | return ret; | ||
3280 | } | ||
3281 | |||
3291 | regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val); | 3282 | regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val); |
3292 | 3283 | ||
3293 | switch (val) { | 3284 | switch (val) { |
@@ -3299,16 +3290,10 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3299 | break; | 3290 | break; |
3300 | default: | 3291 | default: |
3301 | dev_err(&i2c->dev, | 3292 | dev_err(&i2c->dev, |
3302 | "Device with ID register %x is not rt5645 or rt5650\n", | 3293 | "Device with ID register %#x is not rt5645 or rt5650\n", |
3303 | val); | 3294 | val); |
3304 | return -ENODEV; | 3295 | ret = -ENODEV; |
3305 | } | 3296 | goto err_enable; |
3306 | |||
3307 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { | ||
3308 | ret = rt5650_calibration(rt5645); | ||
3309 | |||
3310 | if (ret < 0) | ||
3311 | pr_err("calibration failed!\n"); | ||
3312 | } | 3297 | } |
3313 | 3298 | ||
3314 | regmap_write(rt5645->regmap, RT5645_RESET, 0); | 3299 | regmap_write(rt5645->regmap, RT5645_RESET, 0); |
@@ -3398,8 +3383,6 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3398 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, | 3383 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, |
3399 | RT5645_IRQ_CLK_GATE_CTRL, | 3384 | RT5645_IRQ_CLK_GATE_CTRL, |
3400 | RT5645_IRQ_CLK_GATE_CTRL); | 3385 | RT5645_IRQ_CLK_GATE_CTRL); |
3401 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, | ||
3402 | RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN); | ||
3403 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, | 3386 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, |
3404 | RT5645_IRQ_CLK_INT, RT5645_IRQ_CLK_INT); | 3387 | RT5645_IRQ_CLK_INT, RT5645_IRQ_CLK_INT); |
3405 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | 3388 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, |
@@ -3439,12 +3422,25 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3439 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, | 3422 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, |
3440 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 3423 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
3441 | | IRQF_ONESHOT, "rt5645", rt5645); | 3424 | | IRQF_ONESHOT, "rt5645", rt5645); |
3442 | if (ret) | 3425 | if (ret) { |
3443 | dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); | 3426 | dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); |
3427 | goto err_enable; | ||
3428 | } | ||
3444 | } | 3429 | } |
3445 | 3430 | ||
3446 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, | 3431 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, |
3447 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); | 3432 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); |
3433 | if (ret) | ||
3434 | goto err_irq; | ||
3435 | |||
3436 | return 0; | ||
3437 | |||
3438 | err_irq: | ||
3439 | if (rt5645->i2c->irq) | ||
3440 | free_irq(rt5645->i2c->irq, rt5645); | ||
3441 | err_enable: | ||
3442 | regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); | ||
3443 | return ret; | ||
3448 | } | 3444 | } |
3449 | 3445 | ||
3450 | static int rt5645_i2c_remove(struct i2c_client *i2c) | 3446 | static int rt5645_i2c_remove(struct i2c_client *i2c) |
@@ -3457,18 +3453,31 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) | |||
3457 | cancel_delayed_work_sync(&rt5645->jack_detect_work); | 3453 | cancel_delayed_work_sync(&rt5645->jack_detect_work); |
3458 | 3454 | ||
3459 | snd_soc_unregister_codec(&i2c->dev); | 3455 | snd_soc_unregister_codec(&i2c->dev); |
3456 | regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); | ||
3460 | 3457 | ||
3461 | return 0; | 3458 | return 0; |
3462 | } | 3459 | } |
3463 | 3460 | ||
3461 | static void rt5645_i2c_shutdown(struct i2c_client *i2c) | ||
3462 | { | ||
3463 | struct rt5645_priv *rt5645 = i2c_get_clientdata(i2c); | ||
3464 | |||
3465 | regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, | ||
3466 | RT5645_RING2_SLEEVE_GND, RT5645_RING2_SLEEVE_GND); | ||
3467 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2, RT5645_CBJ_MN_JD, | ||
3468 | RT5645_CBJ_MN_JD); | ||
3469 | regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, RT5645_CBJ_BST1_EN, | ||
3470 | 0); | ||
3471 | } | ||
3472 | |||
3464 | static struct i2c_driver rt5645_i2c_driver = { | 3473 | static struct i2c_driver rt5645_i2c_driver = { |
3465 | .driver = { | 3474 | .driver = { |
3466 | .name = "rt5645", | 3475 | .name = "rt5645", |
3467 | .owner = THIS_MODULE, | ||
3468 | .acpi_match_table = ACPI_PTR(rt5645_acpi_match), | 3476 | .acpi_match_table = ACPI_PTR(rt5645_acpi_match), |
3469 | }, | 3477 | }, |
3470 | .probe = rt5645_i2c_probe, | 3478 | .probe = rt5645_i2c_probe, |
3471 | .remove = rt5645_i2c_remove, | 3479 | .remove = rt5645_i2c_remove, |
3480 | .shutdown = rt5645_i2c_shutdown, | ||
3472 | .id_table = rt5645_i2c_id, | 3481 | .id_table = rt5645_i2c_id, |
3473 | }; | 3482 | }; |
3474 | module_i2c_driver(rt5645_i2c_driver); | 3483 | module_i2c_driver(rt5645_i2c_driver); |
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index 278bb9f464c4..0e4cfc6ac649 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h | |||
@@ -2115,6 +2115,7 @@ enum { | |||
2115 | #define RT5645_JD_PSV_MODE (0x1 << 12) | 2115 | #define RT5645_JD_PSV_MODE (0x1 << 12) |
2116 | #define RT5645_IRQ_CLK_GATE_CTRL (0x1 << 11) | 2116 | #define RT5645_IRQ_CLK_GATE_CTRL (0x1 << 11) |
2117 | #define RT5645_MICINDET_MANU (0x1 << 7) | 2117 | #define RT5645_MICINDET_MANU (0x1 << 7) |
2118 | #define RT5645_RING2_SLEEVE_GND (0x1 << 5) | ||
2118 | 2119 | ||
2119 | /* Vendor ID (0xfd) */ | 2120 | /* Vendor ID (0xfd) */ |
2120 | #define RT5645_VER_C 0x2 | 2121 | #define RT5645_VER_C 0x2 |
@@ -2181,32 +2182,6 @@ enum { | |||
2181 | int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec, | 2182 | int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec, |
2182 | unsigned int filter_mask, unsigned int clk_src); | 2183 | unsigned int filter_mask, unsigned int clk_src); |
2183 | 2184 | ||
2184 | struct rt5645_priv { | ||
2185 | struct snd_soc_codec *codec; | ||
2186 | struct rt5645_platform_data pdata; | ||
2187 | struct regmap *regmap; | ||
2188 | struct i2c_client *i2c; | ||
2189 | struct gpio_desc *gpiod_hp_det; | ||
2190 | struct snd_soc_jack *hp_jack; | ||
2191 | struct snd_soc_jack *mic_jack; | ||
2192 | struct snd_soc_jack *btn_jack; | ||
2193 | struct delayed_work jack_detect_work; | ||
2194 | |||
2195 | int codec_type; | ||
2196 | int sysclk; | ||
2197 | int sysclk_src; | ||
2198 | int lrck[RT5645_AIFS]; | ||
2199 | int bclk[RT5645_AIFS]; | ||
2200 | int master[RT5645_AIFS]; | ||
2201 | |||
2202 | int pll_src; | ||
2203 | int pll_in; | ||
2204 | int pll_out; | ||
2205 | |||
2206 | int jack_type; | ||
2207 | bool en_button_func; | ||
2208 | }; | ||
2209 | |||
2210 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | 2185 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, |
2211 | struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack, | 2186 | struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack, |
2212 | struct snd_soc_jack *btn_jack); | 2187 | struct snd_soc_jack *btn_jack); |
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index a3506e193abc..1d4031818966 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c | |||
@@ -46,7 +46,7 @@ static const struct regmap_range_cfg rt5651_ranges[] = { | |||
46 | .window_len = 0x1, }, | 46 | .window_len = 0x1, }, |
47 | }; | 47 | }; |
48 | 48 | ||
49 | static struct reg_default init_list[] = { | 49 | static const struct reg_sequence init_list[] = { |
50 | {RT5651_PR_BASE + 0x3d, 0x3e00}, | 50 | {RT5651_PR_BASE + 0x3d, 0x3e00}, |
51 | }; | 51 | }; |
52 | 52 | ||
@@ -292,16 +292,15 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | |||
292 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | 292 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); |
293 | 293 | ||
294 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | 294 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ |
295 | static unsigned int bst_tlv[] = { | 295 | static const DECLARE_TLV_DB_RANGE(bst_tlv, |
296 | TLV_DB_RANGE_HEAD(7), | ||
297 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 296 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
298 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | 297 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), |
299 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | 298 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), |
300 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), | 299 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), |
301 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), | 300 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), |
302 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), | 301 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), |
303 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | 302 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0) |
304 | }; | 303 | ); |
305 | 304 | ||
306 | /* Interface data select */ | 305 | /* Interface data select */ |
307 | static const char * const rt5651_data_select[] = { | 306 | static const char * const rt5651_data_select[] = { |
@@ -378,10 +377,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
378 | { | 377 | { |
379 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | 378 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
380 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); | 379 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); |
381 | int idx = -EINVAL; | 380 | int idx, rate; |
382 | |||
383 | idx = rl6231_calc_dmic_clk(rt5651->sysclk); | ||
384 | 381 | ||
382 | rate = rt5651->sysclk / rl6231_get_pre_div(rt5651->regmap, | ||
383 | RT5651_ADDA_CLK1, RT5651_I2S_PD1_SFT); | ||
384 | idx = rl6231_calc_dmic_clk(rate); | ||
385 | if (idx < 0) | 385 | if (idx < 0) |
386 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | 386 | dev_err(codec->dev, "Failed to set DMIC clock\n"); |
387 | else | 387 | else |
@@ -1769,7 +1769,7 @@ static int rt5651_i2c_probe(struct i2c_client *i2c, | |||
1769 | regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret); | 1769 | regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret); |
1770 | if (ret != RT5651_DEVICE_ID_VALUE) { | 1770 | if (ret != RT5651_DEVICE_ID_VALUE) { |
1771 | dev_err(&i2c->dev, | 1771 | dev_err(&i2c->dev, |
1772 | "Device with ID register %x is not rt5651\n", ret); | 1772 | "Device with ID register %#x is not rt5651\n", ret); |
1773 | return -ENODEV; | 1773 | return -ENODEV; |
1774 | } | 1774 | } |
1775 | 1775 | ||
@@ -1806,7 +1806,6 @@ static int rt5651_i2c_remove(struct i2c_client *i2c) | |||
1806 | static struct i2c_driver rt5651_i2c_driver = { | 1806 | static struct i2c_driver rt5651_i2c_driver = { |
1807 | .driver = { | 1807 | .driver = { |
1808 | .name = "rt5651", | 1808 | .name = "rt5651", |
1809 | .owner = THIS_MODULE, | ||
1810 | }, | 1809 | }, |
1811 | .probe = rt5651_i2c_probe, | 1810 | .probe = rt5651_i2c_probe, |
1812 | .remove = rt5651_i2c_remove, | 1811 | .remove = rt5651_i2c_remove, |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index a9123d414178..49a9e7049e2b 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5670_ranges[] = { | |||
51 | .window_len = 0x1, }, | 51 | .window_len = 0x1, }, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static const struct reg_default init_list[] = { | 54 | static const struct reg_sequence init_list[] = { |
55 | { RT5670_PR_BASE + 0x14, 0x9a8a }, | 55 | { RT5670_PR_BASE + 0x14, 0x9a8a }, |
56 | { RT5670_PR_BASE + 0x38, 0x3ba1 }, | 56 | { RT5670_PR_BASE + 0x38, 0x3ba1 }, |
57 | { RT5670_PR_BASE + 0x3d, 0x3640 }, | 57 | { RT5670_PR_BASE + 0x3d, 0x3640 }, |
@@ -592,16 +592,15 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | |||
592 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | 592 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); |
593 | 593 | ||
594 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | 594 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ |
595 | static unsigned int bst_tlv[] = { | 595 | static const DECLARE_TLV_DB_RANGE(bst_tlv, |
596 | TLV_DB_RANGE_HEAD(7), | ||
597 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 596 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
598 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | 597 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), |
599 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | 598 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), |
600 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), | 599 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), |
601 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), | 600 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), |
602 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), | 601 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), |
603 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | 602 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0) |
604 | }; | 603 | ); |
605 | 604 | ||
606 | /* Interface data select */ | 605 | /* Interface data select */ |
607 | static const char * const rt5670_data_select[] = { | 606 | static const char * const rt5670_data_select[] = { |
@@ -683,10 +682,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
683 | { | 682 | { |
684 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | 683 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
685 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 684 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
686 | int idx = -EINVAL; | 685 | int idx, rate; |
687 | |||
688 | idx = rl6231_calc_dmic_clk(rt5670->sysclk); | ||
689 | 686 | ||
687 | rate = rt5670->sysclk / rl6231_get_pre_div(rt5670->regmap, | ||
688 | RT5670_ADDA_CLK1, RT5670_I2S_PD1_SFT); | ||
689 | idx = rl6231_calc_dmic_clk(rate); | ||
690 | if (idx < 0) | 690 | if (idx < 0) |
691 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | 691 | dev_err(codec->dev, "Failed to set DMIC clock\n"); |
692 | else | 692 | else |
@@ -2720,7 +2720,7 @@ static int rt5670_resume(struct snd_soc_codec *codec) | |||
2720 | #define RT5670_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 2720 | #define RT5670_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
2721 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | 2721 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) |
2722 | 2722 | ||
2723 | static struct snd_soc_dai_ops rt5670_aif_dai_ops = { | 2723 | static const struct snd_soc_dai_ops rt5670_aif_dai_ops = { |
2724 | .hw_params = rt5670_hw_params, | 2724 | .hw_params = rt5670_hw_params, |
2725 | .set_fmt = rt5670_set_dai_fmt, | 2725 | .set_fmt = rt5670_set_dai_fmt, |
2726 | .set_sysclk = rt5670_set_dai_sysclk, | 2726 | .set_sysclk = rt5670_set_dai_sysclk, |
@@ -2863,7 +2863,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2863 | regmap_read(rt5670->regmap, RT5670_VENDOR_ID2, &val); | 2863 | regmap_read(rt5670->regmap, RT5670_VENDOR_ID2, &val); |
2864 | if (val != RT5670_DEVICE_ID) { | 2864 | if (val != RT5670_DEVICE_ID) { |
2865 | dev_err(&i2c->dev, | 2865 | dev_err(&i2c->dev, |
2866 | "Device with ID register %x is not rt5670/72\n", val); | 2866 | "Device with ID register %#x is not rt5670/72\n", val); |
2867 | return -ENODEV; | 2867 | return -ENODEV; |
2868 | } | 2868 | } |
2869 | 2869 | ||
@@ -3043,7 +3043,6 @@ static int rt5670_i2c_remove(struct i2c_client *i2c) | |||
3043 | static struct i2c_driver rt5670_i2c_driver = { | 3043 | static struct i2c_driver rt5670_i2c_driver = { |
3044 | .driver = { | 3044 | .driver = { |
3045 | .name = "rt5670", | 3045 | .name = "rt5670", |
3046 | .owner = THIS_MODULE, | ||
3047 | .acpi_match_table = ACPI_PTR(rt5670_acpi_match), | 3046 | .acpi_match_table = ACPI_PTR(rt5670_acpi_match), |
3048 | }, | 3047 | }, |
3049 | .probe = rt5670_i2c_probe, | 3048 | .probe = rt5670_i2c_probe, |
diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index ef6348cb9157..3505aafbade4 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c | |||
@@ -31,84 +31,197 @@ | |||
31 | 31 | ||
32 | #include "rt5677-spi.h" | 32 | #include "rt5677-spi.h" |
33 | 33 | ||
34 | #define RT5677_SPI_BURST_LEN 240 | ||
35 | #define RT5677_SPI_HEADER 5 | ||
36 | #define RT5677_SPI_FREQ 6000000 | ||
37 | |||
38 | /* The AddressPhase and DataPhase of SPI commands are MSB first on the wire. | ||
39 | * DataPhase word size of 16-bit commands is 2 bytes. | ||
40 | * DataPhase word size of 32-bit commands is 4 bytes. | ||
41 | * DataPhase word size of burst commands is 8 bytes. | ||
42 | * The DSP CPU is little-endian. | ||
43 | */ | ||
44 | #define RT5677_SPI_WRITE_BURST 0x5 | ||
45 | #define RT5677_SPI_READ_BURST 0x4 | ||
46 | #define RT5677_SPI_WRITE_32 0x3 | ||
47 | #define RT5677_SPI_READ_32 0x2 | ||
48 | #define RT5677_SPI_WRITE_16 0x1 | ||
49 | #define RT5677_SPI_READ_16 0x0 | ||
50 | |||
34 | static struct spi_device *g_spi; | 51 | static struct spi_device *g_spi; |
52 | static DEFINE_MUTEX(spi_mutex); | ||
35 | 53 | ||
36 | /** | 54 | /* Select a suitable transfer command for the next transfer to ensure |
37 | * rt5677_spi_write - Write data to SPI. | 55 | * the transfer address is always naturally aligned while minimizing |
38 | * @txbuf: Data Buffer for writing. | 56 | * the total number of transfers required. |
39 | * @len: Data length. | 57 | * |
58 | * 3 transfer commands are available: | ||
59 | * RT5677_SPI_READ/WRITE_16: Transfer 2 bytes | ||
60 | * RT5677_SPI_READ/WRITE_32: Transfer 4 bytes | ||
61 | * RT5677_SPI_READ/WRITE_BURST: Transfer any multiples of 8 bytes | ||
62 | * | ||
63 | * For example, reading 260 bytes at 0x60030002 uses the following commands: | ||
64 | * 0x60030002 RT5677_SPI_READ_16 2 bytes | ||
65 | * 0x60030004 RT5677_SPI_READ_32 4 bytes | ||
66 | * 0x60030008 RT5677_SPI_READ_BURST 240 bytes | ||
67 | * 0x600300F8 RT5677_SPI_READ_BURST 8 bytes | ||
68 | * 0x60030100 RT5677_SPI_READ_32 4 bytes | ||
69 | * 0x60030104 RT5677_SPI_READ_16 2 bytes | ||
40 | * | 70 | * |
71 | * Input: | ||
72 | * @read: true for read commands; false for write commands | ||
73 | * @align: alignment of the next transfer address | ||
74 | * @remain: number of bytes remaining to transfer | ||
41 | * | 75 | * |
42 | * Returns true for success. | 76 | * Output: |
77 | * @len: number of bytes to transfer with the selected command | ||
78 | * Returns the selected command | ||
43 | */ | 79 | */ |
44 | int rt5677_spi_write(u8 *txbuf, size_t len) | 80 | static u8 rt5677_spi_select_cmd(bool read, u32 align, u32 remain, u32 *len) |
45 | { | 81 | { |
46 | int status; | 82 | u8 cmd; |
47 | 83 | ||
48 | status = spi_write(g_spi, txbuf, len); | 84 | if (align == 2 || align == 6 || remain == 2) { |
49 | 85 | cmd = RT5677_SPI_READ_16; | |
50 | if (status) | 86 | *len = 2; |
51 | dev_err(&g_spi->dev, "rt5677_spi_write error %d\n", status); | 87 | } else if (align == 4 || remain <= 6) { |
52 | 88 | cmd = RT5677_SPI_READ_32; | |
53 | return status; | 89 | *len = 4; |
90 | } else { | ||
91 | cmd = RT5677_SPI_READ_BURST; | ||
92 | *len = min_t(u32, remain & ~7, RT5677_SPI_BURST_LEN); | ||
93 | } | ||
94 | return read ? cmd : cmd + 1; | ||
54 | } | 95 | } |
55 | EXPORT_SYMBOL_GPL(rt5677_spi_write); | ||
56 | 96 | ||
57 | /** | 97 | /* Copy dstlen bytes from src to dst, while reversing byte order for each word. |
58 | * rt5677_spi_burst_write - Write data to SPI by rt5677 dsp memory address. | 98 | * If srclen < dstlen, zeros are padded. |
59 | * @addr: Start address. | ||
60 | * @txbuf: Data Buffer for writng. | ||
61 | * @len: Data length, it must be a multiple of 8. | ||
62 | * | ||
63 | * | ||
64 | * Returns true for success. | ||
65 | */ | 99 | */ |
66 | int rt5677_spi_burst_write(u32 addr, const struct firmware *fw) | 100 | static void rt5677_spi_reverse(u8 *dst, u32 dstlen, const u8 *src, u32 srclen) |
67 | { | 101 | { |
68 | u8 spi_cmd = RT5677_SPI_CMD_BURST_WRITE; | 102 | u32 w, i, si; |
69 | u8 *write_buf; | 103 | u32 word_size = min_t(u32, dstlen, 8); |
70 | unsigned int i, end, offset = 0; | 104 | |
71 | 105 | for (w = 0; w < dstlen; w += word_size) { | |
72 | write_buf = kmalloc(RT5677_SPI_BUF_LEN + 6, GFP_KERNEL); | 106 | for (i = 0; i < word_size; i++) { |
73 | 107 | si = w + word_size - i - 1; | |
74 | if (write_buf == NULL) | 108 | dst[w + i] = si < srclen ? src[si] : 0; |
75 | return -ENOMEM; | ||
76 | |||
77 | while (offset < fw->size) { | ||
78 | if (offset + RT5677_SPI_BUF_LEN <= fw->size) | ||
79 | end = RT5677_SPI_BUF_LEN; | ||
80 | else | ||
81 | end = fw->size % RT5677_SPI_BUF_LEN; | ||
82 | |||
83 | write_buf[0] = spi_cmd; | ||
84 | write_buf[1] = ((addr + offset) & 0xff000000) >> 24; | ||
85 | write_buf[2] = ((addr + offset) & 0x00ff0000) >> 16; | ||
86 | write_buf[3] = ((addr + offset) & 0x0000ff00) >> 8; | ||
87 | write_buf[4] = ((addr + offset) & 0x000000ff) >> 0; | ||
88 | |||
89 | for (i = 0; i < end; i += 8) { | ||
90 | write_buf[i + 12] = fw->data[offset + i + 0]; | ||
91 | write_buf[i + 11] = fw->data[offset + i + 1]; | ||
92 | write_buf[i + 10] = fw->data[offset + i + 2]; | ||
93 | write_buf[i + 9] = fw->data[offset + i + 3]; | ||
94 | write_buf[i + 8] = fw->data[offset + i + 4]; | ||
95 | write_buf[i + 7] = fw->data[offset + i + 5]; | ||
96 | write_buf[i + 6] = fw->data[offset + i + 6]; | ||
97 | write_buf[i + 5] = fw->data[offset + i + 7]; | ||
98 | } | 109 | } |
110 | } | ||
111 | } | ||
99 | 112 | ||
100 | write_buf[end + 5] = spi_cmd; | 113 | /* Read DSP address space using SPI. addr and len have to be 2-byte aligned. */ |
114 | int rt5677_spi_read(u32 addr, void *rxbuf, size_t len) | ||
115 | { | ||
116 | u32 offset; | ||
117 | int status = 0; | ||
118 | struct spi_transfer t[2]; | ||
119 | struct spi_message m; | ||
120 | /* +4 bytes is for the DummyPhase following the AddressPhase */ | ||
121 | u8 header[RT5677_SPI_HEADER + 4]; | ||
122 | u8 body[RT5677_SPI_BURST_LEN]; | ||
123 | u8 spi_cmd; | ||
124 | u8 *cb = rxbuf; | ||
125 | |||
126 | if (!g_spi) | ||
127 | return -ENODEV; | ||
128 | |||
129 | if ((addr & 1) || (len & 1)) { | ||
130 | dev_err(&g_spi->dev, "Bad read align 0x%x(%zu)\n", addr, len); | ||
131 | return -EACCES; | ||
132 | } | ||
101 | 133 | ||
102 | rt5677_spi_write(write_buf, end + 6); | 134 | memset(t, 0, sizeof(t)); |
135 | t[0].tx_buf = header; | ||
136 | t[0].len = sizeof(header); | ||
137 | t[0].speed_hz = RT5677_SPI_FREQ; | ||
138 | t[1].rx_buf = body; | ||
139 | t[1].speed_hz = RT5677_SPI_FREQ; | ||
140 | spi_message_init_with_transfers(&m, t, ARRAY_SIZE(t)); | ||
141 | |||
142 | for (offset = 0; offset < len; offset += t[1].len) { | ||
143 | spi_cmd = rt5677_spi_select_cmd(true, (addr + offset) & 7, | ||
144 | len - offset, &t[1].len); | ||
145 | |||
146 | /* Construct SPI message header */ | ||
147 | header[0] = spi_cmd; | ||
148 | header[1] = ((addr + offset) & 0xff000000) >> 24; | ||
149 | header[2] = ((addr + offset) & 0x00ff0000) >> 16; | ||
150 | header[3] = ((addr + offset) & 0x0000ff00) >> 8; | ||
151 | header[4] = ((addr + offset) & 0x000000ff) >> 0; | ||
152 | |||
153 | mutex_lock(&spi_mutex); | ||
154 | status |= spi_sync(g_spi, &m); | ||
155 | mutex_unlock(&spi_mutex); | ||
156 | |||
157 | /* Copy data back to caller buffer */ | ||
158 | rt5677_spi_reverse(cb + offset, t[1].len, body, t[1].len); | ||
159 | } | ||
160 | return status; | ||
161 | } | ||
162 | EXPORT_SYMBOL_GPL(rt5677_spi_read); | ||
103 | 163 | ||
104 | offset += RT5677_SPI_BUF_LEN; | 164 | /* Write DSP address space using SPI. addr has to be 2-byte aligned. |
165 | * If len is not 2-byte aligned, an extra byte of zero is written at the end | ||
166 | * as padding. | ||
167 | */ | ||
168 | int rt5677_spi_write(u32 addr, const void *txbuf, size_t len) | ||
169 | { | ||
170 | u32 offset, len_with_pad = len; | ||
171 | int status = 0; | ||
172 | struct spi_transfer t; | ||
173 | struct spi_message m; | ||
174 | /* +1 byte is for the DummyPhase following the DataPhase */ | ||
175 | u8 buf[RT5677_SPI_HEADER + RT5677_SPI_BURST_LEN + 1]; | ||
176 | u8 *body = buf + RT5677_SPI_HEADER; | ||
177 | u8 spi_cmd; | ||
178 | const u8 *cb = txbuf; | ||
179 | |||
180 | if (!g_spi) | ||
181 | return -ENODEV; | ||
182 | |||
183 | if (addr & 1) { | ||
184 | dev_err(&g_spi->dev, "Bad write align 0x%x(%zu)\n", addr, len); | ||
185 | return -EACCES; | ||
105 | } | 186 | } |
106 | 187 | ||
107 | kfree(write_buf); | 188 | if (len & 1) |
189 | len_with_pad = len + 1; | ||
190 | |||
191 | memset(&t, 0, sizeof(t)); | ||
192 | t.tx_buf = buf; | ||
193 | t.speed_hz = RT5677_SPI_FREQ; | ||
194 | spi_message_init_with_transfers(&m, &t, 1); | ||
195 | |||
196 | for (offset = 0; offset < len_with_pad;) { | ||
197 | spi_cmd = rt5677_spi_select_cmd(false, (addr + offset) & 7, | ||
198 | len_with_pad - offset, &t.len); | ||
199 | |||
200 | /* Construct SPI message header */ | ||
201 | buf[0] = spi_cmd; | ||
202 | buf[1] = ((addr + offset) & 0xff000000) >> 24; | ||
203 | buf[2] = ((addr + offset) & 0x00ff0000) >> 16; | ||
204 | buf[3] = ((addr + offset) & 0x0000ff00) >> 8; | ||
205 | buf[4] = ((addr + offset) & 0x000000ff) >> 0; | ||
206 | |||
207 | /* Fetch data from caller buffer */ | ||
208 | rt5677_spi_reverse(body, t.len, cb + offset, len - offset); | ||
209 | offset += t.len; | ||
210 | t.len += RT5677_SPI_HEADER + 1; | ||
211 | |||
212 | mutex_lock(&spi_mutex); | ||
213 | status |= spi_sync(g_spi, &m); | ||
214 | mutex_unlock(&spi_mutex); | ||
215 | } | ||
216 | return status; | ||
217 | } | ||
218 | EXPORT_SYMBOL_GPL(rt5677_spi_write); | ||
108 | 219 | ||
109 | return 0; | 220 | int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw) |
221 | { | ||
222 | return rt5677_spi_write(addr, fw->data, fw->size); | ||
110 | } | 223 | } |
111 | EXPORT_SYMBOL_GPL(rt5677_spi_burst_write); | 224 | EXPORT_SYMBOL_GPL(rt5677_spi_write_firmware); |
112 | 225 | ||
113 | static int rt5677_spi_probe(struct spi_device *spi) | 226 | static int rt5677_spi_probe(struct spi_device *spi) |
114 | { | 227 | { |
diff --git a/sound/soc/codecs/rt5677-spi.h b/sound/soc/codecs/rt5677-spi.h index ec41b2b3b2ca..662db16cfb6a 100644 --- a/sound/soc/codecs/rt5677-spi.h +++ b/sound/soc/codecs/rt5677-spi.h | |||
@@ -12,10 +12,8 @@ | |||
12 | #ifndef __RT5677_SPI_H__ | 12 | #ifndef __RT5677_SPI_H__ |
13 | #define __RT5677_SPI_H__ | 13 | #define __RT5677_SPI_H__ |
14 | 14 | ||
15 | #define RT5677_SPI_BUF_LEN 240 | 15 | int rt5677_spi_read(u32 addr, void *rxbuf, size_t len); |
16 | #define RT5677_SPI_CMD_BURST_WRITE 0x05 | 16 | int rt5677_spi_write(u32 addr, const void *txbuf, size_t len); |
17 | 17 | int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw); | |
18 | int rt5677_spi_write(u8 *txbuf, size_t len); | ||
19 | int rt5677_spi_burst_write(u32 addr, const struct firmware *fw); | ||
20 | 18 | ||
21 | #endif /* __RT5677_SPI_H__ */ | 19 | #endif /* __RT5677_SPI_H__ */ |
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 31d969ac1192..b4cd7e3bf5f8 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -15,13 +15,12 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/of_gpio.h> | ||
19 | #include <linux/regmap.h> | 18 | #include <linux/regmap.h> |
20 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
21 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
23 | #include <linux/firmware.h> | 22 | #include <linux/firmware.h> |
24 | #include <linux/gpio.h> | 23 | #include <linux/property.h> |
25 | #include <sound/core.h> | 24 | #include <sound/core.h> |
26 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
27 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -54,7 +53,7 @@ static const struct regmap_range_cfg rt5677_ranges[] = { | |||
54 | }, | 53 | }, |
55 | }; | 54 | }; |
56 | 55 | ||
57 | static const struct reg_default init_list[] = { | 56 | static const struct reg_sequence init_list[] = { |
58 | {RT5677_ASRC_12, 0x0018}, | 57 | {RT5677_ASRC_12, 0x0018}, |
59 | {RT5677_PR_BASE + 0x3d, 0x364d}, | 58 | {RT5677_PR_BASE + 0x3d, 0x364d}, |
60 | {RT5677_PR_BASE + 0x17, 0x4fc0}, | 59 | {RT5677_PR_BASE + 0x17, 0x4fc0}, |
@@ -746,14 +745,14 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on) | |||
746 | ret = request_firmware(&rt5677->fw1, RT5677_FIRMWARE1, | 745 | ret = request_firmware(&rt5677->fw1, RT5677_FIRMWARE1, |
747 | codec->dev); | 746 | codec->dev); |
748 | if (ret == 0) { | 747 | if (ret == 0) { |
749 | rt5677_spi_burst_write(0x50000000, rt5677->fw1); | 748 | rt5677_spi_write_firmware(0x50000000, rt5677->fw1); |
750 | release_firmware(rt5677->fw1); | 749 | release_firmware(rt5677->fw1); |
751 | } | 750 | } |
752 | 751 | ||
753 | ret = request_firmware(&rt5677->fw2, RT5677_FIRMWARE2, | 752 | ret = request_firmware(&rt5677->fw2, RT5677_FIRMWARE2, |
754 | codec->dev); | 753 | codec->dev); |
755 | if (ret == 0) { | 754 | if (ret == 0) { |
756 | rt5677_spi_burst_write(0x60000000, rt5677->fw2); | 755 | rt5677_spi_write_firmware(0x60000000, rt5677->fw2); |
757 | release_firmware(rt5677->fw2); | 756 | release_firmware(rt5677->fw2); |
758 | } | 757 | } |
759 | 758 | ||
@@ -789,16 +788,15 @@ static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | |||
789 | static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0); | 788 | static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0); |
790 | 789 | ||
791 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | 790 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ |
792 | static unsigned int bst_tlv[] = { | 791 | static const DECLARE_TLV_DB_RANGE(bst_tlv, |
793 | TLV_DB_RANGE_HEAD(7), | ||
794 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 792 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
795 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | 793 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), |
796 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | 794 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), |
797 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), | 795 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), |
798 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), | 796 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), |
799 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), | 797 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), |
800 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | 798 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0) |
801 | }; | 799 | ); |
802 | 800 | ||
803 | static int rt5677_dsp_vad_get(struct snd_kcontrol *kcontrol, | 801 | static int rt5677_dsp_vad_get(struct snd_kcontrol *kcontrol, |
804 | struct snd_ctl_elem_value *ucontrol) | 802 | struct snd_ctl_elem_value *ucontrol) |
@@ -917,8 +915,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
917 | { | 915 | { |
918 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | 916 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
919 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 917 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
920 | int idx = rl6231_calc_dmic_clk(rt5677->lrck[RT5677_AIF1] << 8); | 918 | int idx, rate; |
921 | 919 | ||
920 | rate = rt5677->sysclk / rl6231_get_pre_div(rt5677->regmap, | ||
921 | RT5677_CLK_TREE_CTRL1, RT5677_I2S_PD1_SFT); | ||
922 | idx = rl6231_calc_dmic_clk(rate); | ||
922 | if (idx < 0) | 923 | if (idx < 0) |
923 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | 924 | dev_err(codec->dev, "Failed to set DMIC clock\n"); |
924 | else | 925 | else |
@@ -4764,10 +4765,8 @@ static int rt5677_remove(struct snd_soc_codec *codec) | |||
4764 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 4765 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
4765 | 4766 | ||
4766 | regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec); | 4767 | regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec); |
4767 | if (gpio_is_valid(rt5677->pow_ldo2)) | 4768 | gpiod_set_value_cansleep(rt5677->pow_ldo2, 0); |
4768 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); | 4769 | gpiod_set_value_cansleep(rt5677->reset_pin, 0); |
4769 | if (gpio_is_valid(rt5677->reset_pin)) | ||
4770 | gpio_set_value_cansleep(rt5677->reset_pin, 0); | ||
4771 | 4770 | ||
4772 | return 0; | 4771 | return 0; |
4773 | } | 4772 | } |
@@ -4781,10 +4780,8 @@ static int rt5677_suspend(struct snd_soc_codec *codec) | |||
4781 | regcache_cache_only(rt5677->regmap, true); | 4780 | regcache_cache_only(rt5677->regmap, true); |
4782 | regcache_mark_dirty(rt5677->regmap); | 4781 | regcache_mark_dirty(rt5677->regmap); |
4783 | 4782 | ||
4784 | if (gpio_is_valid(rt5677->pow_ldo2)) | 4783 | gpiod_set_value_cansleep(rt5677->pow_ldo2, 0); |
4785 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); | 4784 | gpiod_set_value_cansleep(rt5677->reset_pin, 0); |
4786 | if (gpio_is_valid(rt5677->reset_pin)) | ||
4787 | gpio_set_value_cansleep(rt5677->reset_pin, 0); | ||
4788 | } | 4785 | } |
4789 | 4786 | ||
4790 | return 0; | 4787 | return 0; |
@@ -4795,12 +4792,9 @@ static int rt5677_resume(struct snd_soc_codec *codec) | |||
4795 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 4792 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
4796 | 4793 | ||
4797 | if (!rt5677->dsp_vad_en) { | 4794 | if (!rt5677->dsp_vad_en) { |
4798 | if (gpio_is_valid(rt5677->pow_ldo2)) | 4795 | gpiod_set_value_cansleep(rt5677->pow_ldo2, 1); |
4799 | gpio_set_value_cansleep(rt5677->pow_ldo2, 1); | 4796 | gpiod_set_value_cansleep(rt5677->reset_pin, 1); |
4800 | if (gpio_is_valid(rt5677->reset_pin)) | 4797 | if (rt5677->pow_ldo2 || rt5677->reset_pin) |
4801 | gpio_set_value_cansleep(rt5677->reset_pin, 1); | ||
4802 | if (gpio_is_valid(rt5677->pow_ldo2) || | ||
4803 | gpio_is_valid(rt5677->reset_pin)) | ||
4804 | msleep(10); | 4798 | msleep(10); |
4805 | 4799 | ||
4806 | regcache_cache_only(rt5677->regmap, false); | 4800 | regcache_cache_only(rt5677->regmap, false); |
@@ -4863,7 +4857,7 @@ static int rt5677_write(void *context, unsigned int reg, unsigned int val) | |||
4863 | #define RT5677_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 4857 | #define RT5677_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
4864 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | 4858 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) |
4865 | 4859 | ||
4866 | static struct snd_soc_dai_ops rt5677_aif_dai_ops = { | 4860 | static const struct snd_soc_dai_ops rt5677_aif_dai_ops = { |
4867 | .hw_params = rt5677_hw_params, | 4861 | .hw_params = rt5677_hw_params, |
4868 | .set_fmt = rt5677_set_dai_fmt, | 4862 | .set_fmt = rt5677_set_dai_fmt, |
4869 | .set_sysclk = rt5677_set_dai_sysclk, | 4863 | .set_sysclk = rt5677_set_dai_sysclk, |
@@ -5024,45 +5018,29 @@ static const struct i2c_device_id rt5677_i2c_id[] = { | |||
5024 | }; | 5018 | }; |
5025 | MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); | 5019 | MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); |
5026 | 5020 | ||
5027 | static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np) | 5021 | static void rt5677_read_device_properties(struct rt5677_priv *rt5677, |
5022 | struct device *dev) | ||
5028 | { | 5023 | { |
5029 | rt5677->pdata.in1_diff = of_property_read_bool(np, | 5024 | rt5677->pdata.in1_diff = device_property_read_bool(dev, |
5030 | "realtek,in1-differential"); | 5025 | "realtek,in1-differential"); |
5031 | rt5677->pdata.in2_diff = of_property_read_bool(np, | 5026 | rt5677->pdata.in2_diff = device_property_read_bool(dev, |
5032 | "realtek,in2-differential"); | 5027 | "realtek,in2-differential"); |
5033 | rt5677->pdata.lout1_diff = of_property_read_bool(np, | 5028 | rt5677->pdata.lout1_diff = device_property_read_bool(dev, |
5034 | "realtek,lout1-differential"); | 5029 | "realtek,lout1-differential"); |
5035 | rt5677->pdata.lout2_diff = of_property_read_bool(np, | 5030 | rt5677->pdata.lout2_diff = device_property_read_bool(dev, |
5036 | "realtek,lout2-differential"); | 5031 | "realtek,lout2-differential"); |
5037 | rt5677->pdata.lout3_diff = of_property_read_bool(np, | 5032 | rt5677->pdata.lout3_diff = device_property_read_bool(dev, |
5038 | "realtek,lout3-differential"); | 5033 | "realtek,lout3-differential"); |
5039 | 5034 | ||
5040 | rt5677->pow_ldo2 = of_get_named_gpio(np, | 5035 | device_property_read_u8_array(dev, "realtek,gpio-config", |
5041 | "realtek,pow-ldo2-gpio", 0); | 5036 | rt5677->pdata.gpio_config, RT5677_GPIO_NUM); |
5042 | rt5677->reset_pin = of_get_named_gpio(np, | 5037 | |
5043 | "realtek,reset-gpio", 0); | 5038 | device_property_read_u32(dev, "realtek,jd1-gpio", |
5044 | 5039 | &rt5677->pdata.jd1_gpio); | |
5045 | /* | 5040 | device_property_read_u32(dev, "realtek,jd2-gpio", |
5046 | * POW_LDO2 is optional (it may be statically tied on the board). | 5041 | &rt5677->pdata.jd2_gpio); |
5047 | * -ENOENT means that the property doesn't exist, i.e. there is no | 5042 | device_property_read_u32(dev, "realtek,jd3-gpio", |
5048 | * GPIO, so is not an error. Any other error code means the property | 5043 | &rt5677->pdata.jd3_gpio); |
5049 | * exists, but could not be parsed. | ||
5050 | */ | ||
5051 | if (!gpio_is_valid(rt5677->pow_ldo2) && | ||
5052 | (rt5677->pow_ldo2 != -ENOENT)) | ||
5053 | return rt5677->pow_ldo2; | ||
5054 | if (!gpio_is_valid(rt5677->reset_pin) && | ||
5055 | (rt5677->reset_pin != -ENOENT)) | ||
5056 | return rt5677->reset_pin; | ||
5057 | |||
5058 | of_property_read_u8_array(np, "realtek,gpio-config", | ||
5059 | rt5677->pdata.gpio_config, RT5677_GPIO_NUM); | ||
5060 | |||
5061 | of_property_read_u32(np, "realtek,jd1-gpio", &rt5677->pdata.jd1_gpio); | ||
5062 | of_property_read_u32(np, "realtek,jd2-gpio", &rt5677->pdata.jd2_gpio); | ||
5063 | of_property_read_u32(np, "realtek,jd3-gpio", &rt5677->pdata.jd3_gpio); | ||
5064 | |||
5065 | return 0; | ||
5066 | } | 5044 | } |
5067 | 5045 | ||
5068 | static struct regmap_irq rt5677_irqs[] = { | 5046 | static struct regmap_irq rt5677_irqs[] = { |
@@ -5145,43 +5123,29 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
5145 | 5123 | ||
5146 | if (pdata) | 5124 | if (pdata) |
5147 | rt5677->pdata = *pdata; | 5125 | rt5677->pdata = *pdata; |
5126 | else | ||
5127 | rt5677_read_device_properties(rt5677, &i2c->dev); | ||
5148 | 5128 | ||
5149 | if (i2c->dev.of_node) { | 5129 | /* pow-ldo2 and reset are optional. The codec pins may be statically |
5150 | ret = rt5677_parse_dt(rt5677, i2c->dev.of_node); | 5130 | * connected on the board without gpios. If the gpio device property |
5151 | if (ret) { | 5131 | * isn't specified, devm_gpiod_get_optional returns NULL. |
5152 | dev_err(&i2c->dev, "Failed to parse device tree: %d\n", | 5132 | */ |
5153 | ret); | 5133 | rt5677->pow_ldo2 = devm_gpiod_get_optional(&i2c->dev, |
5154 | return ret; | 5134 | "realtek,pow-ldo2", GPIOD_OUT_HIGH); |
5155 | } | 5135 | if (IS_ERR(rt5677->pow_ldo2)) { |
5156 | } else { | 5136 | ret = PTR_ERR(rt5677->pow_ldo2); |
5157 | rt5677->pow_ldo2 = -EINVAL; | 5137 | dev_err(&i2c->dev, "Failed to request POW_LDO2: %d\n", ret); |
5158 | rt5677->reset_pin = -EINVAL; | 5138 | return ret; |
5159 | } | ||
5160 | |||
5161 | if (gpio_is_valid(rt5677->pow_ldo2)) { | ||
5162 | ret = devm_gpio_request_one(&i2c->dev, rt5677->pow_ldo2, | ||
5163 | GPIOF_OUT_INIT_HIGH, | ||
5164 | "RT5677 POW_LDO2"); | ||
5165 | if (ret < 0) { | ||
5166 | dev_err(&i2c->dev, "Failed to request POW_LDO2 %d: %d\n", | ||
5167 | rt5677->pow_ldo2, ret); | ||
5168 | return ret; | ||
5169 | } | ||
5170 | } | 5139 | } |
5171 | 5140 | rt5677->reset_pin = devm_gpiod_get_optional(&i2c->dev, | |
5172 | if (gpio_is_valid(rt5677->reset_pin)) { | 5141 | "realtek,reset", GPIOD_OUT_HIGH); |
5173 | ret = devm_gpio_request_one(&i2c->dev, rt5677->reset_pin, | 5142 | if (IS_ERR(rt5677->reset_pin)) { |
5174 | GPIOF_OUT_INIT_HIGH, | 5143 | ret = PTR_ERR(rt5677->reset_pin); |
5175 | "RT5677 RESET"); | 5144 | dev_err(&i2c->dev, "Failed to request RESET: %d\n", ret); |
5176 | if (ret < 0) { | 5145 | return ret; |
5177 | dev_err(&i2c->dev, "Failed to request RESET %d: %d\n", | ||
5178 | rt5677->reset_pin, ret); | ||
5179 | return ret; | ||
5180 | } | ||
5181 | } | 5146 | } |
5182 | 5147 | ||
5183 | if (gpio_is_valid(rt5677->pow_ldo2) || | 5148 | if (rt5677->pow_ldo2 || rt5677->reset_pin) { |
5184 | gpio_is_valid(rt5677->reset_pin)) { | ||
5185 | /* Wait a while until I2C bus becomes available. The datasheet | 5149 | /* Wait a while until I2C bus becomes available. The datasheet |
5186 | * does not specify the exact we should wait but startup | 5150 | * does not specify the exact we should wait but startup |
5187 | * sequence mentiones at least a few milliseconds. | 5151 | * sequence mentiones at least a few milliseconds. |
@@ -5209,7 +5173,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
5209 | regmap_read(rt5677->regmap, RT5677_VENDOR_ID2, &val); | 5173 | regmap_read(rt5677->regmap, RT5677_VENDOR_ID2, &val); |
5210 | if (val != RT5677_DEVICE_ID) { | 5174 | if (val != RT5677_DEVICE_ID) { |
5211 | dev_err(&i2c->dev, | 5175 | dev_err(&i2c->dev, |
5212 | "Device with ID register %x is not rt5677\n", val); | 5176 | "Device with ID register %#x is not rt5677\n", val); |
5213 | return -ENODEV; | 5177 | return -ENODEV; |
5214 | } | 5178 | } |
5215 | 5179 | ||
@@ -5273,7 +5237,6 @@ static int rt5677_i2c_remove(struct i2c_client *i2c) | |||
5273 | static struct i2c_driver rt5677_i2c_driver = { | 5237 | static struct i2c_driver rt5677_i2c_driver = { |
5274 | .driver = { | 5238 | .driver = { |
5275 | .name = "rt5677", | 5239 | .name = "rt5677", |
5276 | .owner = THIS_MODULE, | ||
5277 | }, | 5240 | }, |
5278 | .probe = rt5677_i2c_probe, | 5241 | .probe = rt5677_i2c_probe, |
5279 | .remove = rt5677_i2c_remove, | 5242 | .remove = rt5677_i2c_remove, |
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 7eca38a23255..d46855a42c40 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <sound/rt5677.h> | 15 | #include <sound/rt5677.h> |
16 | #include <linux/gpio/driver.h> | 16 | #include <linux/gpio/driver.h> |
17 | #include <linux/gpio/consumer.h> | ||
17 | 18 | ||
18 | /* Info */ | 19 | /* Info */ |
19 | #define RT5677_RESET 0x00 | 20 | #define RT5677_RESET 0x00 |
@@ -1775,8 +1776,8 @@ struct rt5677_priv { | |||
1775 | int pll_src; | 1776 | int pll_src; |
1776 | int pll_in; | 1777 | int pll_in; |
1777 | int pll_out; | 1778 | int pll_out; |
1778 | int pow_ldo2; /* POW_LDO2 pin */ | 1779 | struct gpio_desc *pow_ldo2; /* POW_LDO2 pin */ |
1779 | int reset_pin; /* RESET pin */ | 1780 | struct gpio_desc *reset_pin; /* RESET pin */ |
1780 | enum rt5677_type type; | 1781 | enum rt5677_type type; |
1781 | #ifdef CONFIG_GPIOLIB | 1782 | #ifdef CONFIG_GPIOLIB |
1782 | struct gpio_chip gpio_chip; | 1783 | struct gpio_chip gpio_chip; |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index e673f6ceb521..bfda25ef0dd4 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -406,11 +406,10 @@ static int dac_put_volsw(struct snd_kcontrol *kcontrol, | |||
406 | static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0); | 406 | static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0); |
407 | 407 | ||
408 | /* tlv for mic gain, 0db 20db 30db 40db */ | 408 | /* tlv for mic gain, 0db 20db 30db 40db */ |
409 | static const unsigned int mic_gain_tlv[] = { | 409 | static const DECLARE_TLV_DB_RANGE(mic_gain_tlv, |
410 | TLV_DB_RANGE_HEAD(2), | ||
411 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 410 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
412 | 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0), | 411 | 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0) |
413 | }; | 412 | ); |
414 | 413 | ||
415 | /* tlv for hp volume, -51.5db to 12.0db, step .5db */ | 414 | /* tlv for hp volume, -51.5db to 12.0db, step .5db */ |
416 | static const DECLARE_TLV_DB_SCALE(headphone_volume, -5150, 50, 0); | 415 | static const DECLARE_TLV_DB_SCALE(headphone_volume, -5150, 50, 0); |
@@ -1601,7 +1600,6 @@ MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids); | |||
1601 | static struct i2c_driver sgtl5000_i2c_driver = { | 1600 | static struct i2c_driver sgtl5000_i2c_driver = { |
1602 | .driver = { | 1601 | .driver = { |
1603 | .name = "sgtl5000", | 1602 | .name = "sgtl5000", |
1604 | .owner = THIS_MODULE, | ||
1605 | .of_match_table = sgtl5000_dt_ids, | 1603 | .of_match_table = sgtl5000_dt_ids, |
1606 | }, | 1604 | }, |
1607 | .probe = sgtl5000_i2c_probe, | 1605 | .probe = sgtl5000_i2c_probe, |
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index 3e72964280c6..a8402d0af0ea 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c | |||
@@ -208,7 +208,7 @@ out: | |||
208 | return err; | 208 | return err; |
209 | } | 209 | } |
210 | 210 | ||
211 | static struct snd_soc_dai_ops si476x_dai_ops = { | 211 | static const struct snd_soc_dai_ops si476x_dai_ops = { |
212 | .hw_params = si476x_codec_hw_params, | 212 | .hw_params = si476x_codec_hw_params, |
213 | .set_fmt = si476x_codec_set_dai_fmt, | 213 | .set_fmt = si476x_codec_set_dai_fmt, |
214 | }; | 214 | }; |
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index 29cb44256044..6bfd25c289d1 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c | |||
@@ -370,11 +370,11 @@ static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, | |||
370 | return 0; | 370 | return 0; |
371 | } | 371 | } |
372 | 372 | ||
373 | struct snd_soc_dai_ops sirf_audio_codec_dai_ops = { | 373 | static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = { |
374 | .trigger = sirf_audio_codec_trigger, | 374 | .trigger = sirf_audio_codec_trigger, |
375 | }; | 375 | }; |
376 | 376 | ||
377 | struct snd_soc_dai_driver sirf_audio_codec_dai = { | 377 | static struct snd_soc_dai_driver sirf_audio_codec_dai = { |
378 | .name = "sirf-audio-codec", | 378 | .name = "sirf-audio-codec", |
379 | .playback = { | 379 | .playback = { |
380 | .stream_name = "Playback", | 380 | .stream_name = "Playback", |
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index f30de7639bb9..ddb0203fc649 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c | |||
@@ -806,6 +806,14 @@ static int ssm2518_i2c_remove(struct i2c_client *client) | |||
806 | return 0; | 806 | return 0; |
807 | } | 807 | } |
808 | 808 | ||
809 | #ifdef CONFIG_OF | ||
810 | static const struct of_device_id ssm2518_dt_ids[] = { | ||
811 | { .compatible = "adi,ssm2518", }, | ||
812 | { } | ||
813 | }; | ||
814 | MODULE_DEVICE_TABLE(of, ssm2518_dt_ids); | ||
815 | #endif | ||
816 | |||
809 | static const struct i2c_device_id ssm2518_i2c_ids[] = { | 817 | static const struct i2c_device_id ssm2518_i2c_ids[] = { |
810 | { "ssm2518", 0 }, | 818 | { "ssm2518", 0 }, |
811 | { } | 819 | { } |
@@ -815,7 +823,7 @@ MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids); | |||
815 | static struct i2c_driver ssm2518_driver = { | 823 | static struct i2c_driver ssm2518_driver = { |
816 | .driver = { | 824 | .driver = { |
817 | .name = "ssm2518", | 825 | .name = "ssm2518", |
818 | .owner = THIS_MODULE, | 826 | .of_match_table = of_match_ptr(ssm2518_dt_ids), |
819 | }, | 827 | }, |
820 | .probe = ssm2518_i2c_probe, | 828 | .probe = ssm2518_i2c_probe, |
821 | .remove = ssm2518_i2c_remove, | 829 | .remove = ssm2518_i2c_remove, |
diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c index 0d9779d6bfda..173ba85ff59e 100644 --- a/sound/soc/codecs/ssm2602-i2c.c +++ b/sound/soc/codecs/ssm2602-i2c.c | |||
@@ -52,7 +52,6 @@ MODULE_DEVICE_TABLE(of, ssm2602_of_match); | |||
52 | static struct i2c_driver ssm2602_i2c_driver = { | 52 | static struct i2c_driver ssm2602_i2c_driver = { |
53 | .driver = { | 53 | .driver = { |
54 | .name = "ssm2602", | 54 | .name = "ssm2602", |
55 | .owner = THIS_MODULE, | ||
56 | .of_match_table = ssm2602_of_match, | 55 | .of_match_table = ssm2602_of_match, |
57 | }, | 56 | }, |
58 | .probe = ssm2602_i2c_probe, | 57 | .probe = ssm2602_i2c_probe, |
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 69a773aeb13d..4452fea0b118 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -75,11 +75,10 @@ static const struct soc_enum ssm2602_enum[] = { | |||
75 | ssm2602_deemph), | 75 | ssm2602_deemph), |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static const unsigned int ssm260x_outmix_tlv[] = { | 78 | static const DECLARE_TLV_DB_RANGE(ssm260x_outmix_tlv, |
79 | TLV_DB_RANGE_HEAD(2), | ||
80 | 0, 47, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), | 79 | 0, 47, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), |
81 | 48, 127, TLV_DB_SCALE_ITEM(-7400, 100, 0), | 80 | 48, 127, TLV_DB_SCALE_ITEM(-7400, 100, 0) |
82 | }; | 81 | ); |
83 | 82 | ||
84 | static const DECLARE_TLV_DB_SCALE(ssm260x_inpga_tlv, -3450, 150, 0); | 83 | static const DECLARE_TLV_DB_SCALE(ssm260x_inpga_tlv, -3450, 150, 0); |
85 | static const DECLARE_TLV_DB_SCALE(ssm260x_sidetone_tlv, -1500, 300, 0); | 84 | static const DECLARE_TLV_DB_SCALE(ssm260x_sidetone_tlv, -1500, 300, 0); |
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index 84a4f5ad8064..e619d5651b09 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * Licensed under the GPL-2. | 10 | * Licensed under the GPL-2. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/acpi.h> | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
@@ -173,6 +174,12 @@ static const struct snd_soc_dapm_widget ssm4567_dapm_widgets[] = { | |||
173 | SND_SOC_DAPM_SWITCH("Amplifier Boost", SSM4567_REG_POWER_CTRL, 3, 1, | 174 | SND_SOC_DAPM_SWITCH("Amplifier Boost", SSM4567_REG_POWER_CTRL, 3, 1, |
174 | &ssm4567_amplifier_boost_control), | 175 | &ssm4567_amplifier_boost_control), |
175 | 176 | ||
177 | SND_SOC_DAPM_SIGGEN("Sense"), | ||
178 | |||
179 | SND_SOC_DAPM_PGA("Current Sense", SSM4567_REG_POWER_CTRL, 4, 1, NULL, 0), | ||
180 | SND_SOC_DAPM_PGA("Voltage Sense", SSM4567_REG_POWER_CTRL, 5, 1, NULL, 0), | ||
181 | SND_SOC_DAPM_PGA("VBAT Sense", SSM4567_REG_POWER_CTRL, 6, 1, NULL, 0), | ||
182 | |||
176 | SND_SOC_DAPM_OUTPUT("OUT"), | 183 | SND_SOC_DAPM_OUTPUT("OUT"), |
177 | }; | 184 | }; |
178 | 185 | ||
@@ -180,6 +187,13 @@ static const struct snd_soc_dapm_route ssm4567_routes[] = { | |||
180 | { "OUT", NULL, "Amplifier Boost" }, | 187 | { "OUT", NULL, "Amplifier Boost" }, |
181 | { "Amplifier Boost", "Switch", "DAC" }, | 188 | { "Amplifier Boost", "Switch", "DAC" }, |
182 | { "OUT", NULL, "DAC" }, | 189 | { "OUT", NULL, "DAC" }, |
190 | |||
191 | { "Current Sense", NULL, "Sense" }, | ||
192 | { "Voltage Sense", NULL, "Sense" }, | ||
193 | { "VBAT Sense", NULL, "Sense" }, | ||
194 | { "Capture Sense", NULL, "Current Sense" }, | ||
195 | { "Capture Sense", NULL, "Voltage Sense" }, | ||
196 | { "Capture Sense", NULL, "VBAT Sense" }, | ||
183 | }; | 197 | }; |
184 | 198 | ||
185 | static int ssm4567_hw_params(struct snd_pcm_substream *substream, | 199 | static int ssm4567_hw_params(struct snd_pcm_substream *substream, |
@@ -387,6 +401,14 @@ static struct snd_soc_dai_driver ssm4567_dai = { | |||
387 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | 401 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | |
388 | SNDRV_PCM_FMTBIT_S32, | 402 | SNDRV_PCM_FMTBIT_S32, |
389 | }, | 403 | }, |
404 | .capture = { | ||
405 | .stream_name = "Capture Sense", | ||
406 | .channels_min = 1, | ||
407 | .channels_max = 1, | ||
408 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
409 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
410 | SNDRV_PCM_FMTBIT_S32, | ||
411 | }, | ||
390 | .ops = &ssm4567_dai_ops, | 412 | .ops = &ssm4567_dai_ops, |
391 | }; | 413 | }; |
392 | 414 | ||
@@ -456,10 +478,20 @@ static const struct i2c_device_id ssm4567_i2c_ids[] = { | |||
456 | }; | 478 | }; |
457 | MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids); | 479 | MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids); |
458 | 480 | ||
481 | #ifdef CONFIG_ACPI | ||
482 | |||
483 | static const struct acpi_device_id ssm4567_acpi_match[] = { | ||
484 | { "INT343B", 0 }, | ||
485 | {}, | ||
486 | }; | ||
487 | MODULE_DEVICE_TABLE(acpi, ssm4567_acpi_match); | ||
488 | |||
489 | #endif | ||
490 | |||
459 | static struct i2c_driver ssm4567_driver = { | 491 | static struct i2c_driver ssm4567_driver = { |
460 | .driver = { | 492 | .driver = { |
461 | .name = "ssm4567", | 493 | .name = "ssm4567", |
462 | .owner = THIS_MODULE, | 494 | .acpi_match_table = ACPI_PTR(ssm4567_acpi_match), |
463 | }, | 495 | }, |
464 | .probe = ssm4567_i2c_probe, | 496 | .probe = ssm4567_i2c_probe, |
465 | .remove = ssm4567_i2c_remove, | 497 | .remove = ssm4567_i2c_remove, |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 60eff36260cb..a9844b2ac829 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -1144,7 +1144,6 @@ MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id); | |||
1144 | static struct i2c_driver sta32x_i2c_driver = { | 1144 | static struct i2c_driver sta32x_i2c_driver = { |
1145 | .driver = { | 1145 | .driver = { |
1146 | .name = "sta32x", | 1146 | .name = "sta32x", |
1147 | .owner = THIS_MODULE, | ||
1148 | .of_match_table = of_match_ptr(st32x_dt_ids), | 1147 | .of_match_table = of_match_ptr(st32x_dt_ids), |
1149 | }, | 1148 | }, |
1150 | .probe = sta32x_i2c_probe, | 1149 | .probe = sta32x_i2c_probe, |
diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index bd819a3f205a..33a4612f0a07 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c | |||
@@ -1264,7 +1264,6 @@ MODULE_DEVICE_TABLE(i2c, sta350_i2c_id); | |||
1264 | static struct i2c_driver sta350_i2c_driver = { | 1264 | static struct i2c_driver sta350_i2c_driver = { |
1265 | .driver = { | 1265 | .driver = { |
1266 | .name = "sta350", | 1266 | .name = "sta350", |
1267 | .owner = THIS_MODULE, | ||
1268 | .of_match_table = of_match_ptr(st350_dt_ids), | 1267 | .of_match_table = of_match_ptr(st350_dt_ids), |
1269 | }, | 1268 | }, |
1270 | .probe = sta350_i2c_probe, | 1269 | .probe = sta350_i2c_probe, |
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 4f70378b2cfb..2cdaca943a8c 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c | |||
@@ -339,9 +339,6 @@ static int sta529_i2c_probe(struct i2c_client *i2c, | |||
339 | struct sta529 *sta529; | 339 | struct sta529 *sta529; |
340 | int ret; | 340 | int ret; |
341 | 341 | ||
342 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
343 | return -EINVAL; | ||
344 | |||
345 | sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL); | 342 | sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL); |
346 | if (!sta529) | 343 | if (!sta529) |
347 | return -ENOMEM; | 344 | return -ENOMEM; |
@@ -379,7 +376,6 @@ MODULE_DEVICE_TABLE(i2c, sta529_i2c_id); | |||
379 | static struct i2c_driver sta529_i2c_driver = { | 376 | static struct i2c_driver sta529_i2c_driver = { |
380 | .driver = { | 377 | .driver = { |
381 | .name = "sta529", | 378 | .name = "sta529", |
382 | .owner = THIS_MODULE, | ||
383 | }, | 379 | }, |
384 | .probe = sta529_i2c_probe, | 380 | .probe = sta529_i2c_probe, |
385 | .remove = sta529_i2c_remove, | 381 | .remove = sta529_i2c_remove, |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index ed4cca7f6779..0945c51df003 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -28,6 +28,9 @@ | |||
28 | 28 | ||
29 | #include "stac9766.h" | 29 | #include "stac9766.h" |
30 | 30 | ||
31 | #define STAC9766_VENDOR_ID 0x83847666 | ||
32 | #define STAC9766_VENDOR_ID_MASK 0xffffffff | ||
33 | |||
31 | /* | 34 | /* |
32 | * STAC9766 register cache | 35 | * STAC9766 register cache |
33 | */ | 36 | */ |
@@ -239,45 +242,12 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec, | |||
239 | return 0; | 242 | return 0; |
240 | } | 243 | } |
241 | 244 | ||
242 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) | ||
243 | { | ||
244 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
245 | |||
246 | if (try_warm && soc_ac97_ops->warm_reset) { | ||
247 | soc_ac97_ops->warm_reset(ac97); | ||
248 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) | ||
249 | return 1; | ||
250 | } | ||
251 | |||
252 | soc_ac97_ops->reset(ac97); | ||
253 | if (soc_ac97_ops->warm_reset) | ||
254 | soc_ac97_ops->warm_reset(ac97); | ||
255 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) | ||
256 | return -EIO; | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int stac9766_codec_resume(struct snd_soc_codec *codec) | 245 | static int stac9766_codec_resume(struct snd_soc_codec *codec) |
261 | { | 246 | { |
262 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | 247 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
263 | u16 id, reset; | ||
264 | 248 | ||
265 | reset = 0; | 249 | return snd_ac97_reset(ac97, true, STAC9766_VENDOR_ID, |
266 | /* give the codec an AC97 warm reset to start the link */ | 250 | STAC9766_VENDOR_ID_MASK); |
267 | reset: | ||
268 | if (reset > 5) { | ||
269 | dev_err(codec->dev, "Failed to resume\n"); | ||
270 | return -EIO; | ||
271 | } | ||
272 | ac97->bus->ops->warm_reset(ac97); | ||
273 | id = soc_ac97_ops->read(ac97, AC97_VENDOR_ID2); | ||
274 | if (id != 0x4c13) { | ||
275 | stac9766_reset(codec, 0); | ||
276 | reset++; | ||
277 | goto reset; | ||
278 | } | ||
279 | |||
280 | return 0; | ||
281 | } | 251 | } |
282 | 252 | ||
283 | static const struct snd_soc_dai_ops stac9766_dai_ops_analog = { | 253 | static const struct snd_soc_dai_ops stac9766_dai_ops_analog = { |
@@ -330,28 +300,15 @@ static struct snd_soc_dai_driver stac9766_dai[] = { | |||
330 | static int stac9766_codec_probe(struct snd_soc_codec *codec) | 300 | static int stac9766_codec_probe(struct snd_soc_codec *codec) |
331 | { | 301 | { |
332 | struct snd_ac97 *ac97; | 302 | struct snd_ac97 *ac97; |
333 | int ret = 0; | ||
334 | 303 | ||
335 | ac97 = snd_soc_new_ac97_codec(codec); | 304 | ac97 = snd_soc_new_ac97_codec(codec, STAC9766_VENDOR_ID, |
305 | STAC9766_VENDOR_ID_MASK); | ||
336 | if (IS_ERR(ac97)) | 306 | if (IS_ERR(ac97)) |
337 | return PTR_ERR(ac97); | 307 | return PTR_ERR(ac97); |
338 | 308 | ||
339 | snd_soc_codec_set_drvdata(codec, ac97); | 309 | snd_soc_codec_set_drvdata(codec, ac97); |
340 | 310 | ||
341 | /* do a cold reset for the controller and then try | ||
342 | * a warm reset followed by an optional cold reset for codec */ | ||
343 | stac9766_reset(codec, 0); | ||
344 | ret = stac9766_reset(codec, 1); | ||
345 | if (ret < 0) { | ||
346 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
347 | goto codec_err; | ||
348 | } | ||
349 | |||
350 | return 0; | 311 | return 0; |
351 | |||
352 | codec_err: | ||
353 | snd_soc_free_ac97_codec(ac97); | ||
354 | return ret; | ||
355 | } | 312 | } |
356 | 313 | ||
357 | static int stac9766_codec_remove(struct snd_soc_codec *codec) | 314 | static int stac9766_codec_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c new file mode 100644 index 000000000000..160d61a66204 --- /dev/null +++ b/sound/soc/codecs/sti-sas.c | |||
@@ -0,0 +1,628 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2015 | ||
3 | * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com> | ||
4 | * for STMicroelectronics. | ||
5 | * License terms: GNU General Public License (GPL), version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/io.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/regmap.h> | ||
11 | #include <linux/reset.h> | ||
12 | #include <linux/mfd/syscon.h> | ||
13 | |||
14 | #include <sound/soc.h> | ||
15 | #include <sound/soc-dapm.h> | ||
16 | |||
17 | /* chipID supported */ | ||
18 | #define CHIPID_STIH416 0 | ||
19 | #define CHIPID_STIH407 1 | ||
20 | |||
21 | /* DAC definitions */ | ||
22 | |||
23 | /* stih416 DAC registers */ | ||
24 | /* sysconf 2517: Audio-DAC-Control */ | ||
25 | #define STIH416_AUDIO_DAC_CTRL 0x00000814 | ||
26 | /* sysconf 2519: Audio-Gue-Control */ | ||
27 | #define STIH416_AUDIO_GLUE_CTRL 0x0000081C | ||
28 | |||
29 | #define STIH416_DAC_NOT_STANDBY 0x3 | ||
30 | #define STIH416_DAC_SOFTMUTE 0x4 | ||
31 | #define STIH416_DAC_ANA_NOT_PWR 0x5 | ||
32 | #define STIH416_DAC_NOT_PNDBG 0x6 | ||
33 | |||
34 | #define STIH416_DAC_NOT_STANDBY_MASK BIT(STIH416_DAC_NOT_STANDBY) | ||
35 | #define STIH416_DAC_SOFTMUTE_MASK BIT(STIH416_DAC_SOFTMUTE) | ||
36 | #define STIH416_DAC_ANA_NOT_PWR_MASK BIT(STIH416_DAC_ANA_NOT_PWR) | ||
37 | #define STIH416_DAC_NOT_PNDBG_MASK BIT(STIH416_DAC_NOT_PNDBG) | ||
38 | |||
39 | /* stih407 DAC registers */ | ||
40 | /* sysconf 5041: Audio-Gue-Control */ | ||
41 | #define STIH407_AUDIO_GLUE_CTRL 0x000000A4 | ||
42 | /* sysconf 5042: Audio-DAC-Control */ | ||
43 | #define STIH407_AUDIO_DAC_CTRL 0x000000A8 | ||
44 | |||
45 | /* DAC definitions */ | ||
46 | #define STIH407_DAC_SOFTMUTE 0x0 | ||
47 | #define STIH407_DAC_STANDBY_ANA 0x1 | ||
48 | #define STIH407_DAC_STANDBY 0x2 | ||
49 | |||
50 | #define STIH407_DAC_SOFTMUTE_MASK BIT(STIH407_DAC_SOFTMUTE) | ||
51 | #define STIH407_DAC_STANDBY_ANA_MASK BIT(STIH407_DAC_STANDBY_ANA) | ||
52 | #define STIH407_DAC_STANDBY_MASK BIT(STIH407_DAC_STANDBY) | ||
53 | |||
54 | /* SPDIF definitions */ | ||
55 | #define SPDIF_BIPHASE_ENABLE 0x6 | ||
56 | #define SPDIF_BIPHASE_IDLE 0x7 | ||
57 | |||
58 | #define SPDIF_BIPHASE_ENABLE_MASK BIT(SPDIF_BIPHASE_ENABLE) | ||
59 | #define SPDIF_BIPHASE_IDLE_MASK BIT(SPDIF_BIPHASE_IDLE) | ||
60 | |||
61 | enum { | ||
62 | STI_SAS_DAI_SPDIF_OUT, | ||
63 | STI_SAS_DAI_ANALOG_OUT, | ||
64 | }; | ||
65 | |||
66 | static const struct reg_default stih416_sas_reg_defaults[] = { | ||
67 | { STIH407_AUDIO_GLUE_CTRL, 0x00000040 }, | ||
68 | { STIH407_AUDIO_DAC_CTRL, 0x000000000 }, | ||
69 | }; | ||
70 | |||
71 | static const struct reg_default stih407_sas_reg_defaults[] = { | ||
72 | { STIH416_AUDIO_DAC_CTRL, 0x000000000 }, | ||
73 | { STIH416_AUDIO_GLUE_CTRL, 0x00000040 }, | ||
74 | }; | ||
75 | |||
76 | struct sti_dac_audio { | ||
77 | struct regmap *regmap; | ||
78 | struct regmap *virt_regmap; | ||
79 | struct regmap_field **field; | ||
80 | struct reset_control *rst; | ||
81 | int mclk; | ||
82 | }; | ||
83 | |||
84 | struct sti_spdif_audio { | ||
85 | struct regmap *regmap; | ||
86 | struct regmap_field **field; | ||
87 | int mclk; | ||
88 | }; | ||
89 | |||
90 | /* device data structure */ | ||
91 | struct sti_sas_dev_data { | ||
92 | const int chipid; /* IC version */ | ||
93 | const struct regmap_config *regmap; | ||
94 | const struct snd_soc_dai_ops *dac_ops; /* DAC function callbacks */ | ||
95 | const struct snd_soc_dapm_widget *dapm_widgets; /* dapms declaration */ | ||
96 | const int num_dapm_widgets; /* dapms declaration */ | ||
97 | const struct snd_soc_dapm_route *dapm_routes; /* route declaration */ | ||
98 | const int num_dapm_routes; /* route declaration */ | ||
99 | }; | ||
100 | |||
101 | /* driver data structure */ | ||
102 | struct sti_sas_data { | ||
103 | struct device *dev; | ||
104 | const struct sti_sas_dev_data *dev_data; | ||
105 | struct sti_dac_audio dac; | ||
106 | struct sti_spdif_audio spdif; | ||
107 | }; | ||
108 | |||
109 | /* Read a register from the sysconf reg bank */ | ||
110 | static int sti_sas_read_reg(void *context, unsigned int reg, | ||
111 | unsigned int *value) | ||
112 | { | ||
113 | struct sti_sas_data *drvdata = context; | ||
114 | int status; | ||
115 | u32 val; | ||
116 | |||
117 | status = regmap_read(drvdata->dac.regmap, reg, &val); | ||
118 | *value = (unsigned int)val; | ||
119 | |||
120 | return status; | ||
121 | } | ||
122 | |||
123 | /* Read a register from the sysconf reg bank */ | ||
124 | static int sti_sas_write_reg(void *context, unsigned int reg, | ||
125 | unsigned int value) | ||
126 | { | ||
127 | struct sti_sas_data *drvdata = context; | ||
128 | int status; | ||
129 | |||
130 | status = regmap_write(drvdata->dac.regmap, reg, value); | ||
131 | |||
132 | return status; | ||
133 | } | ||
134 | |||
135 | static int sti_sas_init_sas_registers(struct snd_soc_codec *codec, | ||
136 | struct sti_sas_data *data) | ||
137 | { | ||
138 | int ret; | ||
139 | /* | ||
140 | * DAC and SPDIF are activated by default | ||
141 | * put them in IDLE to save power | ||
142 | */ | ||
143 | |||
144 | /* Initialise bi-phase formatter to disabled */ | ||
145 | ret = snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL, | ||
146 | SPDIF_BIPHASE_ENABLE_MASK, 0); | ||
147 | |||
148 | if (!ret) | ||
149 | /* Initialise bi-phase formatter idle value to 0 */ | ||
150 | ret = snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL, | ||
151 | SPDIF_BIPHASE_IDLE_MASK, 0); | ||
152 | if (ret < 0) { | ||
153 | dev_err(codec->dev, "Failed to update SPDIF registers"); | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | /* Init DAC configuration */ | ||
158 | switch (data->dev_data->chipid) { | ||
159 | case CHIPID_STIH407: | ||
160 | /* init configuration */ | ||
161 | ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL, | ||
162 | STIH407_DAC_STANDBY_MASK, | ||
163 | STIH407_DAC_STANDBY_MASK); | ||
164 | |||
165 | if (!ret) | ||
166 | ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL, | ||
167 | STIH407_DAC_STANDBY_ANA_MASK, | ||
168 | STIH407_DAC_STANDBY_ANA_MASK); | ||
169 | if (!ret) | ||
170 | ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL, | ||
171 | STIH407_DAC_SOFTMUTE_MASK, | ||
172 | STIH407_DAC_SOFTMUTE_MASK); | ||
173 | break; | ||
174 | case CHIPID_STIH416: | ||
175 | ret = snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL, | ||
176 | STIH416_DAC_NOT_STANDBY_MASK, 0); | ||
177 | if (!ret) | ||
178 | ret = snd_soc_update_bits(codec, | ||
179 | STIH416_AUDIO_DAC_CTRL, | ||
180 | STIH416_DAC_ANA_NOT_PWR, 0); | ||
181 | if (!ret) | ||
182 | ret = snd_soc_update_bits(codec, | ||
183 | STIH416_AUDIO_DAC_CTRL, | ||
184 | STIH416_DAC_NOT_PNDBG_MASK, | ||
185 | 0); | ||
186 | if (!ret) | ||
187 | ret = snd_soc_update_bits(codec, | ||
188 | STIH416_AUDIO_DAC_CTRL, | ||
189 | STIH416_DAC_SOFTMUTE_MASK, | ||
190 | STIH416_DAC_SOFTMUTE_MASK); | ||
191 | break; | ||
192 | default: | ||
193 | return -EINVAL; | ||
194 | } | ||
195 | |||
196 | if (ret < 0) { | ||
197 | dev_err(codec->dev, "Failed to update DAC registers"); | ||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * DAC | ||
206 | */ | ||
207 | static int sti_sas_dac_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
208 | { | ||
209 | /* Sanity check only */ | ||
210 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { | ||
211 | dev_err(dai->codec->dev, | ||
212 | "%s: ERROR: Unsupporter master mask 0x%x\n", | ||
213 | __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK); | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int stih416_dac_probe(struct snd_soc_dai *dai) | ||
221 | { | ||
222 | struct snd_soc_codec *codec = dai->codec; | ||
223 | struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev); | ||
224 | struct sti_dac_audio *dac = &drvdata->dac; | ||
225 | |||
226 | /* Get reset control */ | ||
227 | dac->rst = devm_reset_control_get(codec->dev, "dac_rst"); | ||
228 | if (IS_ERR(dac->rst)) { | ||
229 | dev_err(dai->codec->dev, | ||
230 | "%s: ERROR: DAC reset control not defined !\n", | ||
231 | __func__); | ||
232 | dac->rst = NULL; | ||
233 | return -EFAULT; | ||
234 | } | ||
235 | /* Put the DAC into reset */ | ||
236 | reset_control_assert(dac->rst); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static const struct snd_soc_dapm_widget stih416_sas_dapm_widgets[] = { | ||
242 | SND_SOC_DAPM_PGA("DAC bandgap", STIH416_AUDIO_DAC_CTRL, | ||
243 | STIH416_DAC_NOT_PNDBG_MASK, 0, NULL, 0), | ||
244 | SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH416_AUDIO_DAC_CTRL, | ||
245 | STIH416_DAC_ANA_NOT_PWR, 0, NULL, 0), | ||
246 | SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH416_AUDIO_DAC_CTRL, | ||
247 | STIH416_DAC_NOT_STANDBY, 0), | ||
248 | SND_SOC_DAPM_OUTPUT("DAC Output"), | ||
249 | }; | ||
250 | |||
251 | static const struct snd_soc_dapm_widget stih407_sas_dapm_widgets[] = { | ||
252 | SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH407_AUDIO_DAC_CTRL, | ||
253 | STIH407_DAC_STANDBY_ANA, 1, NULL, 0), | ||
254 | SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH407_AUDIO_DAC_CTRL, | ||
255 | STIH407_DAC_STANDBY, 1), | ||
256 | SND_SOC_DAPM_OUTPUT("DAC Output"), | ||
257 | }; | ||
258 | |||
259 | static const struct snd_soc_dapm_route stih416_sas_route[] = { | ||
260 | {"DAC Output", NULL, "DAC bandgap"}, | ||
261 | {"DAC Output", NULL, "DAC standby ana"}, | ||
262 | {"DAC standby ana", NULL, "DAC standby"}, | ||
263 | }; | ||
264 | |||
265 | static const struct snd_soc_dapm_route stih407_sas_route[] = { | ||
266 | {"DAC Output", NULL, "DAC standby ana"}, | ||
267 | {"DAC standby ana", NULL, "DAC standby"}, | ||
268 | }; | ||
269 | |||
270 | static int stih416_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream) | ||
271 | { | ||
272 | struct snd_soc_codec *codec = dai->codec; | ||
273 | |||
274 | if (mute) { | ||
275 | return snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL, | ||
276 | STIH416_DAC_SOFTMUTE_MASK, | ||
277 | STIH416_DAC_SOFTMUTE_MASK); | ||
278 | } else { | ||
279 | return snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL, | ||
280 | STIH416_DAC_SOFTMUTE_MASK, 0); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static int stih407_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream) | ||
285 | { | ||
286 | struct snd_soc_codec *codec = dai->codec; | ||
287 | |||
288 | if (mute) { | ||
289 | return snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL, | ||
290 | STIH407_DAC_SOFTMUTE_MASK, | ||
291 | STIH407_DAC_SOFTMUTE_MASK); | ||
292 | } else { | ||
293 | return snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL, | ||
294 | STIH407_DAC_SOFTMUTE_MASK, | ||
295 | 0); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * SPDIF | ||
301 | */ | ||
302 | static int sti_sas_spdif_set_fmt(struct snd_soc_dai *dai, | ||
303 | unsigned int fmt) | ||
304 | { | ||
305 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { | ||
306 | dev_err(dai->codec->dev, | ||
307 | "%s: ERROR: Unsupporter master mask 0x%x\n", | ||
308 | __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK); | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * sti_sas_spdif_trigger: | ||
317 | * Trigger function is used to ensure that BiPhase Formater is disabled | ||
318 | * before CPU dai is stopped. | ||
319 | * This is mandatory to avoid that BPF is stalled | ||
320 | */ | ||
321 | static int sti_sas_spdif_trigger(struct snd_pcm_substream *substream, int cmd, | ||
322 | struct snd_soc_dai *dai) | ||
323 | { | ||
324 | struct snd_soc_codec *codec = dai->codec; | ||
325 | |||
326 | switch (cmd) { | ||
327 | case SNDRV_PCM_TRIGGER_START: | ||
328 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
329 | return snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL, | ||
330 | SPDIF_BIPHASE_ENABLE_MASK, | ||
331 | SPDIF_BIPHASE_ENABLE_MASK); | ||
332 | case SNDRV_PCM_TRIGGER_RESUME: | ||
333 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
334 | case SNDRV_PCM_TRIGGER_STOP: | ||
335 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
336 | return snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL, | ||
337 | SPDIF_BIPHASE_ENABLE_MASK, | ||
338 | 0); | ||
339 | default: | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | static bool sti_sas_volatile_register(struct device *dev, unsigned int reg) | ||
345 | { | ||
346 | if (reg == STIH407_AUDIO_GLUE_CTRL) | ||
347 | return true; | ||
348 | |||
349 | return false; | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * CODEC DAIS | ||
354 | */ | ||
355 | |||
356 | /* | ||
357 | * sti_sas_set_sysclk: | ||
358 | * get MCLK input frequency to check that MCLK-FS ratio is coherent | ||
359 | */ | ||
360 | static int sti_sas_set_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
361 | unsigned int freq, int dir) | ||
362 | { | ||
363 | struct snd_soc_codec *codec = dai->codec; | ||
364 | struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev); | ||
365 | |||
366 | if (dir == SND_SOC_CLOCK_OUT) | ||
367 | return 0; | ||
368 | |||
369 | if (clk_id != 0) | ||
370 | return -EINVAL; | ||
371 | |||
372 | switch (dai->id) { | ||
373 | case STI_SAS_DAI_SPDIF_OUT: | ||
374 | drvdata->spdif.mclk = freq; | ||
375 | break; | ||
376 | |||
377 | case STI_SAS_DAI_ANALOG_OUT: | ||
378 | drvdata->dac.mclk = freq; | ||
379 | break; | ||
380 | } | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static int sti_sas_prepare(struct snd_pcm_substream *substream, | ||
386 | struct snd_soc_dai *dai) | ||
387 | { | ||
388 | struct snd_soc_codec *codec = dai->codec; | ||
389 | struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev); | ||
390 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
391 | |||
392 | switch (dai->id) { | ||
393 | case STI_SAS_DAI_SPDIF_OUT: | ||
394 | if ((drvdata->spdif.mclk / runtime->rate) != 128) { | ||
395 | dev_err(codec->dev, "unexpected mclk-fs ratio"); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | break; | ||
399 | case STI_SAS_DAI_ANALOG_OUT: | ||
400 | if ((drvdata->dac.mclk / runtime->rate) != 256) { | ||
401 | dev_err(codec->dev, "unexpected mclk-fs ratio"); | ||
402 | return -EINVAL; | ||
403 | } | ||
404 | break; | ||
405 | } | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | static const struct snd_soc_dai_ops stih416_dac_ops = { | ||
411 | .set_fmt = sti_sas_dac_set_fmt, | ||
412 | .mute_stream = stih416_sas_dac_mute, | ||
413 | .prepare = sti_sas_prepare, | ||
414 | .set_sysclk = sti_sas_set_sysclk, | ||
415 | }; | ||
416 | |||
417 | static const struct snd_soc_dai_ops stih407_dac_ops = { | ||
418 | .set_fmt = sti_sas_dac_set_fmt, | ||
419 | .mute_stream = stih407_sas_dac_mute, | ||
420 | .prepare = sti_sas_prepare, | ||
421 | .set_sysclk = sti_sas_set_sysclk, | ||
422 | }; | ||
423 | |||
424 | static const struct regmap_config stih407_sas_regmap = { | ||
425 | .reg_bits = 32, | ||
426 | .val_bits = 32, | ||
427 | |||
428 | .max_register = STIH407_AUDIO_DAC_CTRL, | ||
429 | .reg_defaults = stih407_sas_reg_defaults, | ||
430 | .num_reg_defaults = ARRAY_SIZE(stih407_sas_reg_defaults), | ||
431 | .volatile_reg = sti_sas_volatile_register, | ||
432 | .cache_type = REGCACHE_RBTREE, | ||
433 | .reg_read = sti_sas_read_reg, | ||
434 | .reg_write = sti_sas_write_reg, | ||
435 | }; | ||
436 | |||
437 | static const struct regmap_config stih416_sas_regmap = { | ||
438 | .reg_bits = 32, | ||
439 | .val_bits = 32, | ||
440 | |||
441 | .max_register = STIH416_AUDIO_DAC_CTRL, | ||
442 | .reg_defaults = stih416_sas_reg_defaults, | ||
443 | .num_reg_defaults = ARRAY_SIZE(stih416_sas_reg_defaults), | ||
444 | .volatile_reg = sti_sas_volatile_register, | ||
445 | .cache_type = REGCACHE_RBTREE, | ||
446 | .reg_read = sti_sas_read_reg, | ||
447 | .reg_write = sti_sas_write_reg, | ||
448 | }; | ||
449 | |||
450 | static const struct sti_sas_dev_data stih416_data = { | ||
451 | .chipid = CHIPID_STIH416, | ||
452 | .regmap = &stih416_sas_regmap, | ||
453 | .dac_ops = &stih416_dac_ops, | ||
454 | .dapm_widgets = stih416_sas_dapm_widgets, | ||
455 | .num_dapm_widgets = ARRAY_SIZE(stih416_sas_dapm_widgets), | ||
456 | .dapm_routes = stih416_sas_route, | ||
457 | .num_dapm_routes = ARRAY_SIZE(stih416_sas_route), | ||
458 | }; | ||
459 | |||
460 | static const struct sti_sas_dev_data stih407_data = { | ||
461 | .chipid = CHIPID_STIH407, | ||
462 | .regmap = &stih407_sas_regmap, | ||
463 | .dac_ops = &stih407_dac_ops, | ||
464 | .dapm_widgets = stih407_sas_dapm_widgets, | ||
465 | .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets), | ||
466 | .dapm_routes = stih407_sas_route, | ||
467 | .num_dapm_routes = ARRAY_SIZE(stih407_sas_route), | ||
468 | }; | ||
469 | |||
470 | static struct snd_soc_dai_driver sti_sas_dai[] = { | ||
471 | { | ||
472 | .name = "sas-dai-spdif-out", | ||
473 | .id = STI_SAS_DAI_SPDIF_OUT, | ||
474 | .playback = { | ||
475 | .stream_name = "spdif_p", | ||
476 | .channels_min = 2, | ||
477 | .channels_max = 2, | ||
478 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | | ||
479 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | | ||
480 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | | ||
481 | SNDRV_PCM_RATE_192000, | ||
482 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
483 | SNDRV_PCM_FMTBIT_S32_LE, | ||
484 | }, | ||
485 | .ops = (struct snd_soc_dai_ops[]) { | ||
486 | { | ||
487 | .set_fmt = sti_sas_spdif_set_fmt, | ||
488 | .trigger = sti_sas_spdif_trigger, | ||
489 | .set_sysclk = sti_sas_set_sysclk, | ||
490 | .prepare = sti_sas_prepare, | ||
491 | } | ||
492 | }, | ||
493 | }, | ||
494 | { | ||
495 | .name = "sas-dai-dac", | ||
496 | .id = STI_SAS_DAI_ANALOG_OUT, | ||
497 | .playback = { | ||
498 | .stream_name = "dac_p", | ||
499 | .channels_min = 2, | ||
500 | .channels_max = 2, | ||
501 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
502 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
503 | SNDRV_PCM_FMTBIT_S32_LE, | ||
504 | }, | ||
505 | }, | ||
506 | }; | ||
507 | |||
508 | #ifdef CONFIG_PM_SLEEP | ||
509 | static int sti_sas_resume(struct snd_soc_codec *codec) | ||
510 | { | ||
511 | struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev); | ||
512 | |||
513 | return sti_sas_init_sas_registers(codec, drvdata); | ||
514 | } | ||
515 | #else | ||
516 | #define sti_sas_resume NULL | ||
517 | #endif | ||
518 | |||
519 | static int sti_sas_codec_probe(struct snd_soc_codec *codec) | ||
520 | { | ||
521 | struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev); | ||
522 | int ret; | ||
523 | |||
524 | ret = sti_sas_init_sas_registers(codec, drvdata); | ||
525 | |||
526 | return ret; | ||
527 | } | ||
528 | |||
529 | static struct snd_soc_codec_driver sti_sas_driver = { | ||
530 | .probe = sti_sas_codec_probe, | ||
531 | .resume = sti_sas_resume, | ||
532 | }; | ||
533 | |||
534 | static const struct of_device_id sti_sas_dev_match[] = { | ||
535 | { | ||
536 | .compatible = "st,stih416-sas-codec", | ||
537 | .data = &stih416_data, | ||
538 | }, | ||
539 | { | ||
540 | .compatible = "st,stih407-sas-codec", | ||
541 | .data = &stih407_data, | ||
542 | }, | ||
543 | {}, | ||
544 | }; | ||
545 | |||
546 | static int sti_sas_driver_probe(struct platform_device *pdev) | ||
547 | { | ||
548 | struct device_node *pnode = pdev->dev.of_node; | ||
549 | struct sti_sas_data *drvdata; | ||
550 | const struct of_device_id *of_id; | ||
551 | |||
552 | /* Allocate device structure */ | ||
553 | drvdata = devm_kzalloc(&pdev->dev, sizeof(struct sti_sas_data), | ||
554 | GFP_KERNEL); | ||
555 | if (!drvdata) | ||
556 | return -ENOMEM; | ||
557 | |||
558 | /* Populate data structure depending on compatibility */ | ||
559 | of_id = of_match_node(sti_sas_dev_match, pnode); | ||
560 | if (!of_id->data) { | ||
561 | dev_err(&pdev->dev, "data associated to device is missing"); | ||
562 | return -EINVAL; | ||
563 | } | ||
564 | |||
565 | drvdata->dev_data = (struct sti_sas_dev_data *)of_id->data; | ||
566 | |||
567 | /* Initialise device structure */ | ||
568 | drvdata->dev = &pdev->dev; | ||
569 | |||
570 | /* Request the DAC & SPDIF registers memory region */ | ||
571 | drvdata->dac.virt_regmap = devm_regmap_init(&pdev->dev, NULL, drvdata, | ||
572 | drvdata->dev_data->regmap); | ||
573 | if (IS_ERR(drvdata->dac.virt_regmap)) { | ||
574 | dev_err(&pdev->dev, "audio registers not enabled\n"); | ||
575 | return PTR_ERR(drvdata->dac.virt_regmap); | ||
576 | } | ||
577 | |||
578 | /* Request the syscon region */ | ||
579 | drvdata->dac.regmap = | ||
580 | syscon_regmap_lookup_by_phandle(pnode, "st,syscfg"); | ||
581 | if (IS_ERR(drvdata->dac.regmap)) { | ||
582 | dev_err(&pdev->dev, "syscon registers not available\n"); | ||
583 | return PTR_ERR(drvdata->dac.regmap); | ||
584 | } | ||
585 | drvdata->spdif.regmap = drvdata->dac.regmap; | ||
586 | |||
587 | /* Set DAC dai probe */ | ||
588 | if (drvdata->dev_data->chipid == CHIPID_STIH416) | ||
589 | sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].probe = stih416_dac_probe; | ||
590 | |||
591 | sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops; | ||
592 | |||
593 | /* Set dapms*/ | ||
594 | sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets; | ||
595 | sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets; | ||
596 | |||
597 | sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes; | ||
598 | sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes; | ||
599 | |||
600 | /* Store context */ | ||
601 | dev_set_drvdata(&pdev->dev, drvdata); | ||
602 | |||
603 | return snd_soc_register_codec(&pdev->dev, &sti_sas_driver, | ||
604 | sti_sas_dai, | ||
605 | ARRAY_SIZE(sti_sas_dai)); | ||
606 | } | ||
607 | |||
608 | static int sti_sas_driver_remove(struct platform_device *pdev) | ||
609 | { | ||
610 | snd_soc_unregister_codec(&pdev->dev); | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static struct platform_driver sti_sas_platform_driver = { | ||
616 | .driver = { | ||
617 | .name = "sti-sas-codec", | ||
618 | .of_match_table = sti_sas_dev_match, | ||
619 | }, | ||
620 | .probe = sti_sas_driver_probe, | ||
621 | .remove = sti_sas_driver_remove, | ||
622 | }; | ||
623 | |||
624 | module_platform_driver(sti_sas_platform_driver); | ||
625 | |||
626 | MODULE_DESCRIPTION("audio codec for STMicroelectronics sti platforms"); | ||
627 | MODULE_AUTHOR("Arnaud.pouliquen@st.com"); | ||
628 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 4f25a7d0efa2..e3a0bca28bcf 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | #include "tas2552.h" | 39 | #include "tas2552.h" |
40 | 40 | ||
41 | static struct reg_default tas2552_reg_defs[] = { | 41 | static const struct reg_default tas2552_reg_defs[] = { |
42 | {TAS2552_CFG_1, 0x22}, | 42 | {TAS2552_CFG_1, 0x22}, |
43 | {TAS2552_CFG_3, 0x80}, | 43 | {TAS2552_CFG_3, 0x80}, |
44 | {TAS2552_DOUT, 0x00}, | 44 | {TAS2552_DOUT, 0x00}, |
@@ -493,8 +493,7 @@ static int tas2552_runtime_suspend(struct device *dev) | |||
493 | regcache_cache_only(tas2552->regmap, true); | 493 | regcache_cache_only(tas2552->regmap, true); |
494 | regcache_mark_dirty(tas2552->regmap); | 494 | regcache_mark_dirty(tas2552->regmap); |
495 | 495 | ||
496 | if (tas2552->enable_gpio) | 496 | gpiod_set_value(tas2552->enable_gpio, 0); |
497 | gpiod_set_value(tas2552->enable_gpio, 0); | ||
498 | 497 | ||
499 | return 0; | 498 | return 0; |
500 | } | 499 | } |
@@ -503,8 +502,7 @@ static int tas2552_runtime_resume(struct device *dev) | |||
503 | { | 502 | { |
504 | struct tas2552_data *tas2552 = dev_get_drvdata(dev); | 503 | struct tas2552_data *tas2552 = dev_get_drvdata(dev); |
505 | 504 | ||
506 | if (tas2552->enable_gpio) | 505 | gpiod_set_value(tas2552->enable_gpio, 1); |
507 | gpiod_set_value(tas2552->enable_gpio, 1); | ||
508 | 506 | ||
509 | tas2552_sw_shutdown(tas2552, 0); | 507 | tas2552_sw_shutdown(tas2552, 0); |
510 | 508 | ||
@@ -520,7 +518,7 @@ static const struct dev_pm_ops tas2552_pm = { | |||
520 | NULL) | 518 | NULL) |
521 | }; | 519 | }; |
522 | 520 | ||
523 | static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { | 521 | static const struct snd_soc_dai_ops tas2552_speaker_dai_ops = { |
524 | .hw_params = tas2552_hw_params, | 522 | .hw_params = tas2552_hw_params, |
525 | .prepare = tas2552_prepare, | 523 | .prepare = tas2552_prepare, |
526 | .set_sysclk = tas2552_set_dai_sysclk, | 524 | .set_sysclk = tas2552_set_dai_sysclk, |
@@ -585,8 +583,7 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec) | |||
585 | return ret; | 583 | return ret; |
586 | } | 584 | } |
587 | 585 | ||
588 | if (tas2552->enable_gpio) | 586 | gpiod_set_value(tas2552->enable_gpio, 1); |
589 | gpiod_set_value(tas2552->enable_gpio, 1); | ||
590 | 587 | ||
591 | ret = pm_runtime_get_sync(codec->dev); | 588 | ret = pm_runtime_get_sync(codec->dev); |
592 | if (ret < 0) { | 589 | if (ret < 0) { |
@@ -610,8 +607,7 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec) | |||
610 | return 0; | 607 | return 0; |
611 | 608 | ||
612 | probe_fail: | 609 | probe_fail: |
613 | if (tas2552->enable_gpio) | 610 | gpiod_set_value(tas2552->enable_gpio, 0); |
614 | gpiod_set_value(tas2552->enable_gpio, 0); | ||
615 | 611 | ||
616 | regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies), | 612 | regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies), |
617 | tas2552->supplies); | 613 | tas2552->supplies); |
@@ -624,8 +620,7 @@ static int tas2552_codec_remove(struct snd_soc_codec *codec) | |||
624 | 620 | ||
625 | pm_runtime_put(codec->dev); | 621 | pm_runtime_put(codec->dev); |
626 | 622 | ||
627 | if (tas2552->enable_gpio) | 623 | gpiod_set_value(tas2552->enable_gpio, 0); |
628 | gpiod_set_value(tas2552->enable_gpio, 0); | ||
629 | 624 | ||
630 | return 0; | 625 | return 0; |
631 | }; | 626 | }; |
@@ -769,7 +764,6 @@ MODULE_DEVICE_TABLE(of, tas2552_of_match); | |||
769 | static struct i2c_driver tas2552_i2c_driver = { | 764 | static struct i2c_driver tas2552_i2c_driver = { |
770 | .driver = { | 765 | .driver = { |
771 | .name = "tas2552", | 766 | .name = "tas2552", |
772 | .owner = THIS_MODULE, | ||
773 | .of_match_table = of_match_ptr(tas2552_of_match), | 767 | .of_match_table = of_match_ptr(tas2552_of_match), |
774 | .pm = &tas2552_pm, | 768 | .pm = &tas2552_pm, |
775 | }, | 769 | }, |
diff --git a/sound/soc/codecs/tas2552.h b/sound/soc/codecs/tas2552.h index 5746f8fd0afd..e34752b8a299 100644 --- a/sound/soc/codecs/tas2552.h +++ b/sound/soc/codecs/tas2552.h | |||
@@ -42,7 +42,7 @@ | |||
42 | #define TAS2552_BOOST_APT_CTRL 0x14 | 42 | #define TAS2552_BOOST_APT_CTRL 0x14 |
43 | #define TAS2552_VER_NUM 0x16 | 43 | #define TAS2552_VER_NUM 0x16 |
44 | #define TAS2552_VBAT_DATA 0x19 | 44 | #define TAS2552_VBAT_DATA 0x19 |
45 | #define TAS2552_MAX_REG 0x20 | 45 | #define TAS2552_MAX_REG TAS2552_VBAT_DATA |
46 | 46 | ||
47 | /* CFG1 Register Masks */ | 47 | /* CFG1 Register Masks */ |
48 | #define TAS2552_DEV_RESET (1 << 0) | 48 | #define TAS2552_DEV_RESET (1 << 0) |
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index 32942bed34b1..d49d25d51957 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c | |||
@@ -266,10 +266,14 @@ static int tas5086_set_deemph(struct snd_soc_codec *codec) | |||
266 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | 266 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); |
267 | int i, val = 0; | 267 | int i, val = 0; |
268 | 268 | ||
269 | if (priv->deemph) | 269 | if (priv->deemph) { |
270 | for (i = 0; i < ARRAY_SIZE(tas5086_deemph); i++) | 270 | for (i = 0; i < ARRAY_SIZE(tas5086_deemph); i++) { |
271 | if (tas5086_deemph[i] == priv->rate) | 271 | if (tas5086_deemph[i] == priv->rate) { |
272 | val = i; | 272 | val = i; |
273 | break; | ||
274 | } | ||
275 | } | ||
276 | } | ||
273 | 277 | ||
274 | return regmap_update_bits(priv->regmap, TAS5086_SYS_CONTROL_1, | 278 | return regmap_update_bits(priv->regmap, TAS5086_SYS_CONTROL_1, |
275 | TAS5086_DEEMPH_MASK, val); | 279 | TAS5086_DEEMPH_MASK, val); |
@@ -994,7 +998,6 @@ static int tas5086_i2c_remove(struct i2c_client *i2c) | |||
994 | static struct i2c_driver tas5086_i2c_driver = { | 998 | static struct i2c_driver tas5086_i2c_driver = { |
995 | .driver = { | 999 | .driver = { |
996 | .name = "tas5086", | 1000 | .name = "tas5086", |
997 | .owner = THIS_MODULE, | ||
998 | .of_match_table = of_match_ptr(tas5086_dt_ids), | 1001 | .of_match_table = of_match_ptr(tas5086_dt_ids), |
999 | }, | 1002 | }, |
1000 | .id_table = tas5086_i2c_id, | 1003 | .id_table = tas5086_i2c_id, |
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 85bcc374c8e8..39307ad41a34 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c | |||
@@ -179,7 +179,7 @@ static int tas571x_set_bias_level(struct snd_soc_codec *codec, | |||
179 | case SND_SOC_BIAS_PREPARE: | 179 | case SND_SOC_BIAS_PREPARE: |
180 | break; | 180 | break; |
181 | case SND_SOC_BIAS_STANDBY: | 181 | case SND_SOC_BIAS_STANDBY: |
182 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 182 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { |
183 | if (!IS_ERR(priv->mclk)) { | 183 | if (!IS_ERR(priv->mclk)) { |
184 | ret = clk_prepare_enable(priv->mclk); | 184 | ret = clk_prepare_enable(priv->mclk); |
185 | if (ret) { | 185 | if (ret) { |
diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c index aab0af681e8c..cb5310d89c0f 100644 --- a/sound/soc/codecs/tfa9879.c +++ b/sound/soc/codecs/tfa9879.c | |||
@@ -160,7 +160,7 @@ static int tfa9879_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
160 | return 0; | 160 | return 0; |
161 | } | 161 | } |
162 | 162 | ||
163 | static struct reg_default tfa9879_regs[] = { | 163 | static const struct reg_default tfa9879_regs[] = { |
164 | { TFA9879_DEVICE_CONTROL, 0x0000 }, /* 0x00 */ | 164 | { TFA9879_DEVICE_CONTROL, 0x0000 }, /* 0x00 */ |
165 | { TFA9879_SERIAL_INTERFACE_1, 0x0a18 }, /* 0x01 */ | 165 | { TFA9879_SERIAL_INTERFACE_1, 0x0a18 }, /* 0x01 */ |
166 | { TFA9879_PCM_IOM2_FORMAT_1, 0x0007 }, /* 0x02 */ | 166 | { TFA9879_PCM_IOM2_FORMAT_1, 0x0007 }, /* 0x02 */ |
@@ -314,7 +314,6 @@ MODULE_DEVICE_TABLE(i2c, tfa9879_i2c_id); | |||
314 | static struct i2c_driver tfa9879_i2c_driver = { | 314 | static struct i2c_driver tfa9879_i2c_driver = { |
315 | .driver = { | 315 | .driver = { |
316 | .name = "tfa9879", | 316 | .name = "tfa9879", |
317 | .owner = THIS_MODULE, | ||
318 | }, | 317 | }, |
319 | .probe = tfa9879_i2c_probe, | 318 | .probe = tfa9879_i2c_probe, |
320 | .remove = tfa9879_i2c_remove, | 319 | .remove = tfa9879_i2c_remove, |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index c4c960f592a1..ee4def4f819f 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -1121,7 +1121,7 @@ static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { | |||
1121 | .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), | 1121 | .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), |
1122 | }; | 1122 | }; |
1123 | 1123 | ||
1124 | static struct snd_soc_dai_ops aic31xx_dai_ops = { | 1124 | static const struct snd_soc_dai_ops aic31xx_dai_ops = { |
1125 | .hw_params = aic31xx_hw_params, | 1125 | .hw_params = aic31xx_hw_params, |
1126 | .set_sysclk = aic31xx_set_dai_sysclk, | 1126 | .set_sysclk = aic31xx_set_dai_sysclk, |
1127 | .set_fmt = aic31xx_set_dai_fmt, | 1127 | .set_fmt = aic31xx_set_dai_fmt, |
@@ -1283,7 +1283,6 @@ MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); | |||
1283 | static struct i2c_driver aic31xx_i2c_driver = { | 1283 | static struct i2c_driver aic31xx_i2c_driver = { |
1284 | .driver = { | 1284 | .driver = { |
1285 | .name = "tlv320aic31xx-codec", | 1285 | .name = "tlv320aic31xx-codec", |
1286 | .owner = THIS_MODULE, | ||
1287 | .of_match_table = of_match_ptr(tlv320aic31xx_of_match), | 1286 | .of_match_table = of_match_ptr(tlv320aic31xx_of_match), |
1288 | }, | 1287 | }, |
1289 | .probe = aic31xx_i2c_probe, | 1288 | .probe = aic31xx_i2c_probe, |
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index ad6cb90e5f9b..f2d3191961e1 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -871,7 +871,6 @@ MODULE_DEVICE_TABLE(of, aic32x4_of_id); | |||
871 | static struct i2c_driver aic32x4_i2c_driver = { | 871 | static struct i2c_driver aic32x4_i2c_driver = { |
872 | .driver = { | 872 | .driver = { |
873 | .name = "tlv320aic32x4", | 873 | .name = "tlv320aic32x4", |
874 | .owner = THIS_MODULE, | ||
875 | .of_match_table = aic32x4_of_id, | 874 | .of_match_table = aic32x4_of_id, |
876 | }, | 875 | }, |
877 | .probe = aic32x4_i2c_probe, | 876 | .probe = aic32x4_i2c_probe, |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index a7cf19b53fb2..1a82b19b2644 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -1668,7 +1668,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = { | |||
1668 | }; | 1668 | }; |
1669 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); | 1669 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); |
1670 | 1670 | ||
1671 | static const struct reg_default aic3007_class_d[] = { | 1671 | static const struct reg_sequence aic3007_class_d[] = { |
1672 | /* Class-D speaker driver init; datasheet p. 46 */ | 1672 | /* Class-D speaker driver init; datasheet p. 46 */ |
1673 | { AIC3X_PAGE_SELECT, 0x0D }, | 1673 | { AIC3X_PAGE_SELECT, 0x0D }, |
1674 | { 0xD, 0x0D }, | 1674 | { 0xD, 0x0D }, |
@@ -1825,7 +1825,6 @@ MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); | |||
1825 | static struct i2c_driver aic3x_i2c_driver = { | 1825 | static struct i2c_driver aic3x_i2c_driver = { |
1826 | .driver = { | 1826 | .driver = { |
1827 | .name = "tlv320aic3x-codec", | 1827 | .name = "tlv320aic3x-codec", |
1828 | .owner = THIS_MODULE, | ||
1829 | .of_match_table = of_match_ptr(tlv320aic3x_of_match), | 1828 | .of_match_table = of_match_ptr(tlv320aic3x_of_match), |
1830 | }, | 1829 | }, |
1831 | .probe = aic3x_i2c_probe, | 1830 | .probe = aic3x_i2c_probe, |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index d67a311f0e75..781398fb2841 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -1585,7 +1585,6 @@ MODULE_DEVICE_TABLE(i2c, tlv320dac33_i2c_id); | |||
1585 | static struct i2c_driver tlv320dac33_i2c_driver = { | 1585 | static struct i2c_driver tlv320dac33_i2c_driver = { |
1586 | .driver = { | 1586 | .driver = { |
1587 | .name = "tlv320dac33-codec", | 1587 | .name = "tlv320dac33-codec", |
1588 | .owner = THIS_MODULE, | ||
1589 | }, | 1588 | }, |
1590 | .probe = dac33_i2c_probe, | 1589 | .probe = dac33_i2c_probe, |
1591 | .remove = dac33_i2c_remove, | 1590 | .remove = dac33_i2c_remove, |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 6fac9e034c48..11d85c5c787a 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -259,8 +259,7 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, | |||
259 | * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going | 259 | * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going |
260 | * down in gain. | 260 | * down in gain. |
261 | */ | 261 | */ |
262 | static const unsigned int tpa6130_tlv[] = { | 262 | static const DECLARE_TLV_DB_RANGE(tpa6130_tlv, |
263 | TLV_DB_RANGE_HEAD(10), | ||
264 | 0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0), | 263 | 0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0), |
265 | 2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0), | 264 | 2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0), |
266 | 4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0), | 265 | 4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0), |
@@ -270,8 +269,8 @@ static const unsigned int tpa6130_tlv[] = { | |||
270 | 12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0), | 269 | 12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0), |
271 | 14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0), | 270 | 14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0), |
272 | 21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0), | 271 | 21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0), |
273 | 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0), | 272 | 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0) |
274 | }; | 273 | ); |
275 | 274 | ||
276 | static const struct snd_kcontrol_new tpa6130a2_controls[] = { | 275 | static const struct snd_kcontrol_new tpa6130a2_controls[] = { |
277 | SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", | 276 | SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", |
@@ -280,12 +279,11 @@ static const struct snd_kcontrol_new tpa6130a2_controls[] = { | |||
280 | tpa6130_tlv), | 279 | tpa6130_tlv), |
281 | }; | 280 | }; |
282 | 281 | ||
283 | static const unsigned int tpa6140_tlv[] = { | 282 | static const DECLARE_TLV_DB_RANGE(tpa6140_tlv, |
284 | TLV_DB_RANGE_HEAD(3), | ||
285 | 0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0), | 283 | 0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0), |
286 | 9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0), | 284 | 9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0), |
287 | 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0), | 285 | 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0) |
288 | }; | 286 | ); |
289 | 287 | ||
290 | static const struct snd_kcontrol_new tpa6140a2_controls[] = { | 288 | static const struct snd_kcontrol_new tpa6140a2_controls[] = { |
291 | SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume", | 289 | SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume", |
@@ -488,7 +486,6 @@ MODULE_DEVICE_TABLE(of, tpa6130a2_of_match); | |||
488 | static struct i2c_driver tpa6130a2_i2c_driver = { | 486 | static struct i2c_driver tpa6130a2_i2c_driver = { |
489 | .driver = { | 487 | .driver = { |
490 | .name = "tpa6130a2", | 488 | .name = "tpa6130a2", |
491 | .owner = THIS_MODULE, | ||
492 | .of_match_table = of_match_ptr(tpa6130a2_of_match), | 489 | .of_match_table = of_match_ptr(tpa6130a2_of_match), |
493 | }, | 490 | }, |
494 | .probe = tpa6130a2_probe, | 491 | .probe = tpa6130a2_probe, |
diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c index 12232d7db4c5..43568435c208 100644 --- a/sound/soc/codecs/ts3a227e.c +++ b/sound/soc/codecs/ts3a227e.c | |||
@@ -23,11 +23,13 @@ | |||
23 | #include "ts3a227e.h" | 23 | #include "ts3a227e.h" |
24 | 24 | ||
25 | struct ts3a227e { | 25 | struct ts3a227e { |
26 | struct device *dev; | ||
26 | struct regmap *regmap; | 27 | struct regmap *regmap; |
27 | struct snd_soc_jack *jack; | 28 | struct snd_soc_jack *jack; |
28 | bool plugged; | 29 | bool plugged; |
29 | bool mic_present; | 30 | bool mic_present; |
30 | unsigned int buttons_held; | 31 | unsigned int buttons_held; |
32 | int irq; | ||
31 | }; | 33 | }; |
32 | 34 | ||
33 | /* Button values to be reported on the jack */ | 35 | /* Button values to be reported on the jack */ |
@@ -189,16 +191,28 @@ static irqreturn_t ts3a227e_interrupt(int irq, void *data) | |||
189 | struct ts3a227e *ts3a227e = (struct ts3a227e *)data; | 191 | struct ts3a227e *ts3a227e = (struct ts3a227e *)data; |
190 | struct regmap *regmap = ts3a227e->regmap; | 192 | struct regmap *regmap = ts3a227e->regmap; |
191 | unsigned int int_reg, kp_int_reg, acc_reg, i; | 193 | unsigned int int_reg, kp_int_reg, acc_reg, i; |
194 | struct device *dev = ts3a227e->dev; | ||
195 | int ret; | ||
192 | 196 | ||
193 | /* Check for plug/unplug. */ | 197 | /* Check for plug/unplug. */ |
194 | regmap_read(regmap, TS3A227E_REG_INTERRUPT, &int_reg); | 198 | ret = regmap_read(regmap, TS3A227E_REG_INTERRUPT, &int_reg); |
199 | if (ret) { | ||
200 | dev_err(dev, "failed to clear interrupt ret=%d\n", ret); | ||
201 | return IRQ_NONE; | ||
202 | } | ||
203 | |||
195 | if (int_reg & (DETECTION_COMPLETE_EVENT | INS_REM_EVENT)) { | 204 | if (int_reg & (DETECTION_COMPLETE_EVENT | INS_REM_EVENT)) { |
196 | regmap_read(regmap, TS3A227E_REG_ACCESSORY_STATUS, &acc_reg); | 205 | regmap_read(regmap, TS3A227E_REG_ACCESSORY_STATUS, &acc_reg); |
197 | ts3a227e_new_jack_state(ts3a227e, acc_reg); | 206 | ts3a227e_new_jack_state(ts3a227e, acc_reg); |
198 | } | 207 | } |
199 | 208 | ||
200 | /* Report any key events. */ | 209 | /* Report any key events. */ |
201 | regmap_read(regmap, TS3A227E_REG_KP_INTERRUPT, &kp_int_reg); | 210 | ret = regmap_read(regmap, TS3A227E_REG_KP_INTERRUPT, &kp_int_reg); |
211 | if (ret) { | ||
212 | dev_err(dev, "failed to clear key interrupt ret=%d\n", ret); | ||
213 | return IRQ_NONE; | ||
214 | } | ||
215 | |||
202 | for (i = 0; i < TS3A227E_NUM_BUTTONS; i++) { | 216 | for (i = 0; i < TS3A227E_NUM_BUTTONS; i++) { |
203 | if (kp_int_reg & PRESS_MASK(i)) | 217 | if (kp_int_reg & PRESS_MASK(i)) |
204 | ts3a227e->buttons_held |= (1 << i); | 218 | ts3a227e->buttons_held |= (1 << i); |
@@ -283,6 +297,8 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c, | |||
283 | return -ENOMEM; | 297 | return -ENOMEM; |
284 | 298 | ||
285 | i2c_set_clientdata(i2c, ts3a227e); | 299 | i2c_set_clientdata(i2c, ts3a227e); |
300 | ts3a227e->dev = dev; | ||
301 | ts3a227e->irq = i2c->irq; | ||
286 | 302 | ||
287 | ts3a227e->regmap = devm_regmap_init_i2c(i2c, &ts3a227e_regmap_config); | 303 | ts3a227e->regmap = devm_regmap_init_i2c(i2c, &ts3a227e_regmap_config); |
288 | if (IS_ERR(ts3a227e->regmap)) | 304 | if (IS_ERR(ts3a227e->regmap)) |
@@ -320,6 +336,32 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c, | |||
320 | return 0; | 336 | return 0; |
321 | } | 337 | } |
322 | 338 | ||
339 | #ifdef CONFIG_PM_SLEEP | ||
340 | static int ts3a227e_suspend(struct device *dev) | ||
341 | { | ||
342 | struct ts3a227e *ts3a227e = dev_get_drvdata(dev); | ||
343 | |||
344 | dev_dbg(ts3a227e->dev, "suspend disable irq\n"); | ||
345 | disable_irq(ts3a227e->irq); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static int ts3a227e_resume(struct device *dev) | ||
351 | { | ||
352 | struct ts3a227e *ts3a227e = dev_get_drvdata(dev); | ||
353 | |||
354 | dev_dbg(ts3a227e->dev, "resume enable irq\n"); | ||
355 | enable_irq(ts3a227e->irq); | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | #endif | ||
360 | |||
361 | static const struct dev_pm_ops ts3a227e_pm = { | ||
362 | SET_SYSTEM_SLEEP_PM_OPS(ts3a227e_suspend, ts3a227e_resume) | ||
363 | }; | ||
364 | |||
323 | static const struct i2c_device_id ts3a227e_i2c_ids[] = { | 365 | static const struct i2c_device_id ts3a227e_i2c_ids[] = { |
324 | { "ts3a227e", 0 }, | 366 | { "ts3a227e", 0 }, |
325 | { } | 367 | { } |
@@ -335,7 +377,7 @@ MODULE_DEVICE_TABLE(of, ts3a227e_of_match); | |||
335 | static struct i2c_driver ts3a227e_driver = { | 377 | static struct i2c_driver ts3a227e_driver = { |
336 | .driver = { | 378 | .driver = { |
337 | .name = "ts3a227e", | 379 | .name = "ts3a227e", |
338 | .owner = THIS_MODULE, | 380 | .pm = &ts3a227e_pm, |
339 | .of_match_table = of_match_ptr(ts3a227e_of_match), | 381 | .of_match_table = of_match_ptr(ts3a227e_of_match), |
340 | }, | 382 | }, |
341 | .probe = ts3a227e_i2c_probe, | 383 | .probe = ts3a227e_i2c_probe, |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 90f5f04eca2d..2713e1845cbc 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -524,12 +524,11 @@ static const struct snd_kcontrol_new twl4030_dapm_abypassv_control = | |||
524 | SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0); | 524 | SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0); |
525 | 525 | ||
526 | /* Digital bypass gain, mute instead of -30dB */ | 526 | /* Digital bypass gain, mute instead of -30dB */ |
527 | static const unsigned int twl4030_dapm_dbypass_tlv[] = { | 527 | static const DECLARE_TLV_DB_RANGE(twl4030_dapm_dbypass_tlv, |
528 | TLV_DB_RANGE_HEAD(3), | ||
529 | 0, 1, TLV_DB_SCALE_ITEM(-3000, 600, 1), | 528 | 0, 1, TLV_DB_SCALE_ITEM(-3000, 600, 1), |
530 | 2, 3, TLV_DB_SCALE_ITEM(-2400, 0, 0), | 529 | 2, 3, TLV_DB_SCALE_ITEM(-2400, 0, 0), |
531 | 4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0), | 530 | 4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0) |
532 | }; | 531 | ); |
533 | 532 | ||
534 | /* Digital bypass left (TX1L -> RX2L) */ | 533 | /* Digital bypass left (TX1L -> RX2L) */ |
535 | static const struct snd_kcontrol_new twl4030_dapm_dbypassl_control = | 534 | static const struct snd_kcontrol_new twl4030_dapm_dbypassl_control = |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index 913edf283239..e19026380534 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -37,74 +37,53 @@ struct uda134x_priv { | |||
37 | 37 | ||
38 | struct snd_pcm_substream *master_substream; | 38 | struct snd_pcm_substream *master_substream; |
39 | struct snd_pcm_substream *slave_substream; | 39 | struct snd_pcm_substream *slave_substream; |
40 | }; | ||
41 | 40 | ||
42 | /* In-data addresses are hard-coded into the reg-cache values */ | 41 | struct regmap *regmap; |
43 | static const char uda134x_reg[UDA134X_REGS_NUM] = { | 42 | struct uda134x_platform_data *pd; |
44 | /* Extended address registers */ | ||
45 | 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
46 | /* Status, data regs */ | ||
47 | 0x00, 0x83, 0x00, 0x40, 0x80, 0xC0, 0x00, | ||
48 | }; | 43 | }; |
49 | 44 | ||
50 | /* | 45 | static const struct reg_default uda134x_reg_defaults[] = { |
51 | * The codec has no support for reading its registers except for peak level... | 46 | { UDA134X_EA000, 0x04 }, |
52 | */ | 47 | { UDA134X_EA001, 0x04 }, |
53 | static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec, | 48 | { UDA134X_EA010, 0x04 }, |
54 | unsigned int reg) | 49 | { UDA134X_EA011, 0x00 }, |
55 | { | 50 | { UDA134X_EA100, 0x00 }, |
56 | u8 *cache = codec->reg_cache; | 51 | { UDA134X_EA101, 0x00 }, |
57 | 52 | { UDA134X_EA110, 0x00 }, | |
58 | if (reg >= UDA134X_REGS_NUM) | 53 | { UDA134X_EA111, 0x00 }, |
59 | return -1; | 54 | { UDA134X_STATUS0, 0x00 }, |
60 | return cache[reg]; | 55 | { UDA134X_STATUS1, 0x03 }, |
61 | } | 56 | { UDA134X_DATA000, 0x00 }, |
62 | 57 | { UDA134X_DATA001, 0x00 }, | |
63 | /* | 58 | { UDA134X_DATA010, 0x00 }, |
64 | * Write the register cache | 59 | { UDA134X_DATA011, 0x00 }, |
65 | */ | 60 | { UDA134X_DATA1, 0x00 }, |
66 | static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec, | 61 | }; |
67 | u8 reg, unsigned int value) | ||
68 | { | ||
69 | u8 *cache = codec->reg_cache; | ||
70 | |||
71 | if (reg >= UDA134X_REGS_NUM) | ||
72 | return; | ||
73 | cache[reg] = value; | ||
74 | } | ||
75 | 62 | ||
76 | /* | 63 | /* |
77 | * Write to the uda134x registers | 64 | * Write to the uda134x registers |
78 | * | 65 | * |
79 | */ | 66 | */ |
80 | static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg, | 67 | static int uda134x_regmap_write(void *context, unsigned int reg, |
81 | unsigned int value) | 68 | unsigned int value) |
82 | { | 69 | { |
70 | struct uda134x_platform_data *pd = context; | ||
83 | int ret; | 71 | int ret; |
84 | u8 addr; | 72 | u8 addr; |
85 | u8 data = value; | 73 | u8 data = value; |
86 | struct uda134x_platform_data *pd = codec->control_data; | ||
87 | |||
88 | pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value); | ||
89 | |||
90 | if (reg >= UDA134X_REGS_NUM) { | ||
91 | printk(KERN_ERR "%s unknown register: reg: %u", | ||
92 | __func__, reg); | ||
93 | return -EINVAL; | ||
94 | } | ||
95 | |||
96 | uda134x_write_reg_cache(codec, reg, value); | ||
97 | 74 | ||
98 | switch (reg) { | 75 | switch (reg) { |
99 | case UDA134X_STATUS0: | 76 | case UDA134X_STATUS0: |
100 | case UDA134X_STATUS1: | 77 | case UDA134X_STATUS1: |
101 | addr = UDA134X_STATUS_ADDR; | 78 | addr = UDA134X_STATUS_ADDR; |
79 | data |= (reg - UDA134X_STATUS0) << 7; | ||
102 | break; | 80 | break; |
103 | case UDA134X_DATA000: | 81 | case UDA134X_DATA000: |
104 | case UDA134X_DATA001: | 82 | case UDA134X_DATA001: |
105 | case UDA134X_DATA010: | 83 | case UDA134X_DATA010: |
106 | case UDA134X_DATA011: | 84 | case UDA134X_DATA011: |
107 | addr = UDA134X_DATA0_ADDR; | 85 | addr = UDA134X_DATA0_ADDR; |
86 | data |= (reg - UDA134X_DATA000) << 6; | ||
108 | break; | 87 | break; |
109 | case UDA134X_DATA1: | 88 | case UDA134X_DATA1: |
110 | addr = UDA134X_DATA1_ADDR; | 89 | addr = UDA134X_DATA1_ADDR; |
@@ -133,27 +112,28 @@ static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg, | |||
133 | 112 | ||
134 | static inline void uda134x_reset(struct snd_soc_codec *codec) | 113 | static inline void uda134x_reset(struct snd_soc_codec *codec) |
135 | { | 114 | { |
136 | u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0); | 115 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
137 | uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6)); | 116 | unsigned int mask = 1<<6; |
117 | |||
118 | regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, mask); | ||
138 | msleep(1); | 119 | msleep(1); |
139 | uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6)); | 120 | regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, 0); |
140 | } | 121 | } |
141 | 122 | ||
142 | static int uda134x_mute(struct snd_soc_dai *dai, int mute) | 123 | static int uda134x_mute(struct snd_soc_dai *dai, int mute) |
143 | { | 124 | { |
144 | struct snd_soc_codec *codec = dai->codec; | 125 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(dai->codec); |
145 | u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010); | 126 | unsigned int mask = 1<<2; |
127 | unsigned int val; | ||
146 | 128 | ||
147 | pr_debug("%s mute: %d\n", __func__, mute); | 129 | pr_debug("%s mute: %d\n", __func__, mute); |
148 | 130 | ||
149 | if (mute) | 131 | if (mute) |
150 | mute_reg |= (1<<2); | 132 | val = mask; |
151 | else | 133 | else |
152 | mute_reg &= ~(1<<2); | 134 | val = 0; |
153 | 135 | ||
154 | uda134x_write(codec, UDA134X_DATA010, mute_reg); | 136 | return regmap_update_bits(uda134x->regmap, UDA134X_DATA010, mask, val); |
155 | |||
156 | return 0; | ||
157 | } | 137 | } |
158 | 138 | ||
159 | static int uda134x_startup(struct snd_pcm_substream *substream, | 139 | static int uda134x_startup(struct snd_pcm_substream *substream, |
@@ -205,7 +185,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, | |||
205 | { | 185 | { |
206 | struct snd_soc_codec *codec = dai->codec; | 186 | struct snd_soc_codec *codec = dai->codec; |
207 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | 187 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
208 | u8 hw_params; | 188 | unsigned int hw_params = 0; |
209 | 189 | ||
210 | if (substream == uda134x->slave_substream) { | 190 | if (substream == uda134x->slave_substream) { |
211 | pr_debug("%s ignoring hw_params for slave substream\n", | 191 | pr_debug("%s ignoring hw_params for slave substream\n", |
@@ -213,10 +193,6 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, | |||
213 | return 0; | 193 | return 0; |
214 | } | 194 | } |
215 | 195 | ||
216 | hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0); | ||
217 | hw_params &= STATUS0_SYSCLK_MASK; | ||
218 | hw_params &= STATUS0_DAIFMT_MASK; | ||
219 | |||
220 | pr_debug("%s sysclk: %d, rate:%d\n", __func__, | 196 | pr_debug("%s sysclk: %d, rate:%d\n", __func__, |
221 | uda134x->sysclk, params_rate(params)); | 197 | uda134x->sysclk, params_rate(params)); |
222 | 198 | ||
@@ -267,9 +243,8 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, | |||
267 | return -EINVAL; | 243 | return -EINVAL; |
268 | } | 244 | } |
269 | 245 | ||
270 | uda134x_write(codec, UDA134X_STATUS0, hw_params); | 246 | return regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, |
271 | 247 | STATUS0_SYSCLK_MASK | STATUS0_DAIFMT_MASK, hw_params); | |
272 | return 0; | ||
273 | } | 248 | } |
274 | 249 | ||
275 | static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 250 | static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
@@ -324,10 +299,8 @@ static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
324 | static int uda134x_set_bias_level(struct snd_soc_codec *codec, | 299 | static int uda134x_set_bias_level(struct snd_soc_codec *codec, |
325 | enum snd_soc_bias_level level) | 300 | enum snd_soc_bias_level level) |
326 | { | 301 | { |
327 | struct uda134x_platform_data *pd = codec->control_data; | 302 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
328 | int i; | 303 | struct uda134x_platform_data *pd = uda134x->pd; |
329 | u8 *cache = codec->reg_cache; | ||
330 | |||
331 | pr_debug("%s bias level %d\n", __func__, level); | 304 | pr_debug("%s bias level %d\n", __func__, level); |
332 | 305 | ||
333 | switch (level) { | 306 | switch (level) { |
@@ -337,17 +310,17 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec, | |||
337 | /* power on */ | 310 | /* power on */ |
338 | if (pd->power) { | 311 | if (pd->power) { |
339 | pd->power(1); | 312 | pd->power(1); |
340 | /* Sync reg_cache with the hardware */ | 313 | regcache_sync(uda134x->regmap); |
341 | for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) | ||
342 | codec->driver->write(codec, i, *cache++); | ||
343 | } | 314 | } |
344 | break; | 315 | break; |
345 | case SND_SOC_BIAS_STANDBY: | 316 | case SND_SOC_BIAS_STANDBY: |
346 | break; | 317 | break; |
347 | case SND_SOC_BIAS_OFF: | 318 | case SND_SOC_BIAS_OFF: |
348 | /* power off */ | 319 | /* power off */ |
349 | if (pd->power) | 320 | if (pd->power) { |
350 | pd->power(0); | 321 | pd->power(0); |
322 | regcache_mark_dirty(uda134x->regmap); | ||
323 | } | ||
351 | break; | 324 | break; |
352 | } | 325 | } |
353 | return 0; | 326 | return 0; |
@@ -478,21 +451,14 @@ static struct snd_soc_dai_driver uda134x_dai = { | |||
478 | static int uda134x_soc_probe(struct snd_soc_codec *codec) | 451 | static int uda134x_soc_probe(struct snd_soc_codec *codec) |
479 | { | 452 | { |
480 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | 453 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
481 | struct uda134x_priv *uda134x; | 454 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
482 | struct uda134x_platform_data *pd = codec->component.card->dev->platform_data; | 455 | struct uda134x_platform_data *pd = uda134x->pd; |
483 | const struct snd_soc_dapm_widget *widgets; | 456 | const struct snd_soc_dapm_widget *widgets; |
484 | unsigned num_widgets; | 457 | unsigned num_widgets; |
485 | |||
486 | int ret; | 458 | int ret; |
487 | 459 | ||
488 | printk(KERN_INFO "UDA134X SoC Audio Codec\n"); | 460 | printk(KERN_INFO "UDA134X SoC Audio Codec\n"); |
489 | 461 | ||
490 | if (!pd) { | ||
491 | printk(KERN_ERR "UDA134X SoC codec: " | ||
492 | "missing L3 bitbang function\n"); | ||
493 | return -ENODEV; | ||
494 | } | ||
495 | |||
496 | switch (pd->model) { | 462 | switch (pd->model) { |
497 | case UDA134X_UDA1340: | 463 | case UDA134X_UDA1340: |
498 | case UDA134X_UDA1341: | 464 | case UDA134X_UDA1341: |
@@ -506,13 +472,6 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec) | |||
506 | return -EINVAL; | 472 | return -EINVAL; |
507 | } | 473 | } |
508 | 474 | ||
509 | uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); | ||
510 | if (uda134x == NULL) | ||
511 | return -ENOMEM; | ||
512 | snd_soc_codec_set_drvdata(codec, uda134x); | ||
513 | |||
514 | codec->control_data = pd; | ||
515 | |||
516 | if (pd->power) | 475 | if (pd->power) |
517 | pd->power(1); | 476 | pd->power(1); |
518 | 477 | ||
@@ -530,7 +489,6 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec) | |||
530 | if (ret) { | 489 | if (ret) { |
531 | printk(KERN_ERR "%s failed to register dapm controls: %d", | 490 | printk(KERN_ERR "%s failed to register dapm controls: %d", |
532 | __func__, ret); | 491 | __func__, ret); |
533 | kfree(uda134x); | ||
534 | return ret; | 492 | return ret; |
535 | } | 493 | } |
536 | 494 | ||
@@ -551,36 +509,19 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec) | |||
551 | default: | 509 | default: |
552 | printk(KERN_ERR "%s unknown codec type: %d", | 510 | printk(KERN_ERR "%s unknown codec type: %d", |
553 | __func__, pd->model); | 511 | __func__, pd->model); |
554 | kfree(uda134x); | ||
555 | return -EINVAL; | 512 | return -EINVAL; |
556 | } | 513 | } |
557 | 514 | ||
558 | if (ret < 0) { | 515 | if (ret < 0) { |
559 | printk(KERN_ERR "UDA134X: failed to register controls\n"); | 516 | printk(KERN_ERR "UDA134X: failed to register controls\n"); |
560 | kfree(uda134x); | ||
561 | return ret; | 517 | return ret; |
562 | } | 518 | } |
563 | 519 | ||
564 | return 0; | 520 | return 0; |
565 | } | 521 | } |
566 | 522 | ||
567 | /* power down chip */ | ||
568 | static int uda134x_soc_remove(struct snd_soc_codec *codec) | ||
569 | { | ||
570 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | ||
571 | |||
572 | kfree(uda134x); | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static struct snd_soc_codec_driver soc_codec_dev_uda134x = { | 523 | static struct snd_soc_codec_driver soc_codec_dev_uda134x = { |
577 | .probe = uda134x_soc_probe, | 524 | .probe = uda134x_soc_probe, |
578 | .remove = uda134x_soc_remove, | ||
579 | .reg_cache_size = sizeof(uda134x_reg), | ||
580 | .reg_word_size = sizeof(u8), | ||
581 | .reg_cache_default = uda134x_reg, | ||
582 | .reg_cache_step = 1, | ||
583 | .read = uda134x_read_reg_cache, | ||
584 | .set_bias_level = uda134x_set_bias_level, | 525 | .set_bias_level = uda134x_set_bias_level, |
585 | .suspend_bias_off = true, | 526 | .suspend_bias_off = true, |
586 | 527 | ||
@@ -590,8 +531,39 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = { | |||
590 | .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes), | 531 | .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes), |
591 | }; | 532 | }; |
592 | 533 | ||
534 | static const struct regmap_config uda134x_regmap_config = { | ||
535 | .reg_bits = 8, | ||
536 | .val_bits = 8, | ||
537 | .max_register = UDA134X_DATA1, | ||
538 | .reg_defaults = uda134x_reg_defaults, | ||
539 | .num_reg_defaults = ARRAY_SIZE(uda134x_reg_defaults), | ||
540 | .cache_type = REGCACHE_RBTREE, | ||
541 | |||
542 | .reg_write = uda134x_regmap_write, | ||
543 | }; | ||
544 | |||
593 | static int uda134x_codec_probe(struct platform_device *pdev) | 545 | static int uda134x_codec_probe(struct platform_device *pdev) |
594 | { | 546 | { |
547 | struct uda134x_platform_data *pd = pdev->dev.platform_data; | ||
548 | struct uda134x_priv *uda134x; | ||
549 | |||
550 | if (!pd) { | ||
551 | dev_err(&pdev->dev, "Missing L3 bitbang function\n"); | ||
552 | return -ENODEV; | ||
553 | } | ||
554 | |||
555 | uda134x = devm_kzalloc(&pdev->dev, sizeof(*uda134x), GFP_KERNEL); | ||
556 | if (!uda134x) | ||
557 | return -ENOMEM; | ||
558 | |||
559 | uda134x->pd = pd; | ||
560 | platform_set_drvdata(pdev, uda134x); | ||
561 | |||
562 | uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd, | ||
563 | &uda134x_regmap_config); | ||
564 | if (IS_ERR(uda134x->regmap)) | ||
565 | return PTR_ERR(uda134x->regmap); | ||
566 | |||
595 | return snd_soc_register_codec(&pdev->dev, | 567 | return snd_soc_register_codec(&pdev->dev, |
596 | &soc_codec_dev_uda134x, &uda134x_dai, 1); | 568 | &soc_codec_dev_uda134x, &uda134x_dai, 1); |
597 | } | 569 | } |
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h index 9faae06972b3..e41ab38c6f69 100644 --- a/sound/soc/codecs/uda134x.h +++ b/sound/soc/codecs/uda134x.h | |||
@@ -26,8 +26,6 @@ | |||
26 | #define UDA134X_DATA011 13 | 26 | #define UDA134X_DATA011 13 |
27 | #define UDA134X_DATA1 14 | 27 | #define UDA134X_DATA1 14 |
28 | 28 | ||
29 | #define UDA134X_REGS_NUM 15 | ||
30 | |||
31 | #define STATUS0_DAIFMT_MASK (~(7<<1)) | 29 | #define STATUS0_DAIFMT_MASK (~(7<<1)) |
32 | #define STATUS0_SYSCLK_MASK (~(3<<4)) | 30 | #define STATUS0_SYSCLK_MASK (~(3<<4)) |
33 | 31 | ||
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 6e159f59d219..35f0469ebb16 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -269,12 +269,11 @@ static DECLARE_TLV_DB_SCALE(amix_tlv, -4950, 150, 1); | |||
269 | * from -66 dB in 0.5 dB steps (2 dB steps, really) and | 269 | * from -66 dB in 0.5 dB steps (2 dB steps, really) and |
270 | * from -52 dB in 0.25 dB steps | 270 | * from -52 dB in 0.25 dB steps |
271 | */ | 271 | */ |
272 | static const unsigned int mvol_tlv[] = { | 272 | static const DECLARE_TLV_DB_RANGE(mvol_tlv, |
273 | TLV_DB_RANGE_HEAD(3), | ||
274 | 0, 15, TLV_DB_SCALE_ITEM(-8200, 100, 1), | 273 | 0, 15, TLV_DB_SCALE_ITEM(-8200, 100, 1), |
275 | 16, 43, TLV_DB_SCALE_ITEM(-6600, 50, 0), | 274 | 16, 43, TLV_DB_SCALE_ITEM(-6600, 50, 0), |
276 | 44, 252, TLV_DB_SCALE_ITEM(-5200, 25, 0), | 275 | 44, 252, TLV_DB_SCALE_ITEM(-5200, 25, 0) |
277 | }; | 276 | ); |
278 | 277 | ||
279 | /* | 278 | /* |
280 | * from -72 dB in 1.5 dB steps (6 dB steps really), | 279 | * from -72 dB in 1.5 dB steps (6 dB steps really), |
@@ -282,13 +281,12 @@ static const unsigned int mvol_tlv[] = { | |||
282 | * from -60 dB in 0.5 dB steps (2 dB steps really) and | 281 | * from -60 dB in 0.5 dB steps (2 dB steps really) and |
283 | * from -46 dB in 0.25 dB steps | 282 | * from -46 dB in 0.25 dB steps |
284 | */ | 283 | */ |
285 | static const unsigned int vc_tlv[] = { | 284 | static const DECLARE_TLV_DB_RANGE(vc_tlv, |
286 | TLV_DB_RANGE_HEAD(4), | ||
287 | 0, 7, TLV_DB_SCALE_ITEM(-7800, 150, 1), | 285 | 0, 7, TLV_DB_SCALE_ITEM(-7800, 150, 1), |
288 | 8, 15, TLV_DB_SCALE_ITEM(-6600, 75, 0), | 286 | 8, 15, TLV_DB_SCALE_ITEM(-6600, 75, 0), |
289 | 16, 43, TLV_DB_SCALE_ITEM(-6000, 50, 0), | 287 | 16, 43, TLV_DB_SCALE_ITEM(-6000, 50, 0), |
290 | 44, 228, TLV_DB_SCALE_ITEM(-4600, 25, 0), | 288 | 44, 228, TLV_DB_SCALE_ITEM(-4600, 25, 0) |
291 | }; | 289 | ); |
292 | 290 | ||
293 | /* from 0 to 6 dB in 2 dB steps if SPF mode != flat */ | 291 | /* from 0 to 6 dB in 2 dB steps if SPF mode != flat */ |
294 | static DECLARE_TLV_DB_SCALE(tr_tlv, 0, 200, 0); | 292 | static DECLARE_TLV_DB_SCALE(tr_tlv, 0, 200, 0); |
@@ -810,7 +808,6 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); | |||
810 | static struct i2c_driver uda1380_i2c_driver = { | 808 | static struct i2c_driver uda1380_i2c_driver = { |
811 | .driver = { | 809 | .driver = { |
812 | .name = "uda1380-codec", | 810 | .name = "uda1380-codec", |
813 | .owner = THIS_MODULE, | ||
814 | }, | 811 | }, |
815 | .probe = uda1380_i2c_probe, | 812 | .probe = uda1380_i2c_probe, |
816 | .remove = uda1380_i2c_remove, | 813 | .remove = uda1380_i2c_remove, |
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 6560a66b3f35..f2c6ad4b8fde 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
@@ -953,7 +953,7 @@ static int wm0010_spi_probe(struct spi_device *spi) | |||
953 | trigger = IRQF_TRIGGER_FALLING; | 953 | trigger = IRQF_TRIGGER_FALLING; |
954 | trigger |= IRQF_ONESHOT; | 954 | trigger |= IRQF_ONESHOT; |
955 | 955 | ||
956 | ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger | IRQF_ONESHOT, | 956 | ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, |
957 | "wm0010", wm0010); | 957 | "wm0010", wm0010); |
958 | if (ret) { | 958 | if (ret) { |
959 | dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", | 959 | dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", |
@@ -1003,7 +1003,6 @@ static int wm0010_spi_remove(struct spi_device *spi) | |||
1003 | static struct spi_driver wm0010_spi_driver = { | 1003 | static struct spi_driver wm0010_spi_driver = { |
1004 | .driver = { | 1004 | .driver = { |
1005 | .name = "wm0010", | 1005 | .name = "wm0010", |
1006 | .bus = &spi_bus_type, | ||
1007 | .owner = THIS_MODULE, | 1006 | .owner = THIS_MODULE, |
1008 | }, | 1007 | }, |
1009 | .probe = wm0010_spi_probe, | 1008 | .probe = wm0010_spi_probe, |
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index 048f00568260..ec45c5b220b1 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c | |||
@@ -251,7 +251,6 @@ MODULE_DEVICE_TABLE(i2c, wm1250_ev1_i2c_id); | |||
251 | static struct i2c_driver wm1250_ev1_i2c_driver = { | 251 | static struct i2c_driver wm1250_ev1_i2c_driver = { |
252 | .driver = { | 252 | .driver = { |
253 | .name = "wm1250-ev1", | 253 | .name = "wm1250-ev1", |
254 | .owner = THIS_MODULE, | ||
255 | }, | 254 | }, |
256 | .probe = wm1250_ev1_probe, | 255 | .probe = wm1250_ev1_probe, |
257 | .remove = wm1250_ev1_remove, | 256 | .remove = wm1250_ev1_remove, |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 21d5402e343f..786abd02b140 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -942,7 +942,6 @@ MODULE_DEVICE_TABLE(i2c, wm2000_i2c_id); | |||
942 | static struct i2c_driver wm2000_i2c_driver = { | 942 | static struct i2c_driver wm2000_i2c_driver = { |
943 | .driver = { | 943 | .driver = { |
944 | .name = "wm2000", | 944 | .name = "wm2000", |
945 | .owner = THIS_MODULE, | ||
946 | }, | 945 | }, |
947 | .probe = wm2000_i2c_probe, | 946 | .probe = wm2000_i2c_probe, |
948 | .remove = wm2000_i2c_remove, | 947 | .remove = wm2000_i2c_remove, |
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index c83083285e53..fd1439ecb50a 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -166,7 +166,7 @@ static const struct wm_adsp_region wm2200_dsp2_regions[] = { | |||
166 | { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE }, | 166 | { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE }, |
167 | }; | 167 | }; |
168 | 168 | ||
169 | static struct reg_default wm2200_reg_defaults[] = { | 169 | static const struct reg_default wm2200_reg_defaults[] = { |
170 | { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */ | 170 | { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */ |
171 | { 0x0102, 0x0000 }, /* R258 - Clocking 3 */ | 171 | { 0x0102, 0x0000 }, /* R258 - Clocking 3 */ |
172 | { 0x0103, 0x0011 }, /* R259 - Clocking 4 */ | 172 | { 0x0103, 0x0011 }, /* R259 - Clocking 4 */ |
@@ -897,7 +897,7 @@ static bool wm2200_readable_register(struct device *dev, unsigned int reg) | |||
897 | } | 897 | } |
898 | } | 898 | } |
899 | 899 | ||
900 | static const struct reg_default wm2200_reva_patch[] = { | 900 | static const struct reg_sequence wm2200_reva_patch[] = { |
901 | { 0x07, 0x0003 }, | 901 | { 0x07, 0x0003 }, |
902 | { 0x102, 0x0200 }, | 902 | { 0x102, 0x0200 }, |
903 | { 0x203, 0x0084 }, | 903 | { 0x203, 0x0084 }, |
@@ -1702,7 +1702,7 @@ static int wm2200_hw_params(struct snd_pcm_substream *substream, | |||
1702 | int *bclk_rates; | 1702 | int *bclk_rates; |
1703 | 1703 | ||
1704 | /* Data sizes if not using TDM */ | 1704 | /* Data sizes if not using TDM */ |
1705 | wl = snd_pcm_format_width(params_format(params)); | 1705 | wl = params_width(params); |
1706 | if (wl < 0) | 1706 | if (wl < 0) |
1707 | return wl; | 1707 | return wl; |
1708 | fl = snd_soc_params_to_frame_size(params); | 1708 | fl = snd_soc_params_to_frame_size(params); |
@@ -2481,7 +2481,7 @@ static int wm2200_runtime_resume(struct device *dev) | |||
2481 | } | 2481 | } |
2482 | #endif | 2482 | #endif |
2483 | 2483 | ||
2484 | static struct dev_pm_ops wm2200_pm = { | 2484 | static const struct dev_pm_ops wm2200_pm = { |
2485 | SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume, | 2485 | SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume, |
2486 | NULL) | 2486 | NULL) |
2487 | }; | 2487 | }; |
@@ -2495,7 +2495,6 @@ MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id); | |||
2495 | static struct i2c_driver wm2200_i2c_driver = { | 2495 | static struct i2c_driver wm2200_i2c_driver = { |
2496 | .driver = { | 2496 | .driver = { |
2497 | .name = "wm2200", | 2497 | .name = "wm2200", |
2498 | .owner = THIS_MODULE, | ||
2499 | .pm = &wm2200_pm, | 2498 | .pm = &wm2200_pm, |
2500 | }, | 2499 | }, |
2501 | .probe = wm2200_i2c_probe, | 2500 | .probe = wm2200_i2c_probe, |
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 4c10cd88c1af..c2cdcae18ff6 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -1247,7 +1247,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = { | |||
1247 | { "PWM2", NULL, "PWM2 Driver" }, | 1247 | { "PWM2", NULL, "PWM2 Driver" }, |
1248 | }; | 1248 | }; |
1249 | 1249 | ||
1250 | static const struct reg_default wm5100_reva_patches[] = { | 1250 | static const struct reg_sequence wm5100_reva_patches[] = { |
1251 | { WM5100_AUDIO_IF_1_10, 0 }, | 1251 | { WM5100_AUDIO_IF_1_10, 0 }, |
1252 | { WM5100_AUDIO_IF_1_11, 1 }, | 1252 | { WM5100_AUDIO_IF_1_11, 1 }, |
1253 | { WM5100_AUDIO_IF_1_12, 2 }, | 1253 | { WM5100_AUDIO_IF_1_12, 2 }, |
@@ -1408,7 +1408,7 @@ static int wm5100_hw_params(struct snd_pcm_substream *substream, | |||
1408 | base = dai->driver->base; | 1408 | base = dai->driver->base; |
1409 | 1409 | ||
1410 | /* Data sizes if not using TDM */ | 1410 | /* Data sizes if not using TDM */ |
1411 | wl = snd_pcm_format_width(params_format(params)); | 1411 | wl = params_width(params); |
1412 | if (wl < 0) | 1412 | if (wl < 0) |
1413 | return wl; | 1413 | return wl; |
1414 | fl = snd_soc_params_to_frame_size(params); | 1414 | fl = snd_soc_params_to_frame_size(params); |
@@ -2570,13 +2570,11 @@ static int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2570 | 2570 | ||
2571 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) | 2571 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) |
2572 | ret = request_threaded_irq(i2c->irq, NULL, | 2572 | ret = request_threaded_irq(i2c->irq, NULL, |
2573 | wm5100_edge_irq, | 2573 | wm5100_edge_irq, irq_flags, |
2574 | irq_flags | IRQF_ONESHOT, | ||
2575 | "wm5100", wm5100); | 2574 | "wm5100", wm5100); |
2576 | else | 2575 | else |
2577 | ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq, | 2576 | ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq, |
2578 | irq_flags | IRQF_ONESHOT, | 2577 | irq_flags, "wm5100", |
2579 | "wm5100", | ||
2580 | wm5100); | 2578 | wm5100); |
2581 | 2579 | ||
2582 | if (ret != 0) { | 2580 | if (ret != 0) { |
@@ -2708,7 +2706,7 @@ static int wm5100_runtime_resume(struct device *dev) | |||
2708 | } | 2706 | } |
2709 | #endif | 2707 | #endif |
2710 | 2708 | ||
2711 | static struct dev_pm_ops wm5100_pm = { | 2709 | static const struct dev_pm_ops wm5100_pm = { |
2712 | SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume, | 2710 | SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume, |
2713 | NULL) | 2711 | NULL) |
2714 | }; | 2712 | }; |
@@ -2722,7 +2720,6 @@ MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id); | |||
2722 | static struct i2c_driver wm5100_i2c_driver = { | 2720 | static struct i2c_driver wm5100_i2c_driver = { |
2723 | .driver = { | 2721 | .driver = { |
2724 | .name = "wm5100", | 2722 | .name = "wm5100", |
2725 | .owner = THIS_MODULE, | ||
2726 | .pm = &wm5100_pm, | 2723 | .pm = &wm5100_pm, |
2727 | }, | 2724 | }, |
2728 | .probe = wm5100_i2c_probe, | 2725 | .probe = wm5100_i2c_probe, |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index d097f09e50f2..64637d1cf4e5 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -788,8 +788,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | |||
788 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | 788 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), |
789 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | 789 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), |
790 | 790 | ||
791 | SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), | 791 | ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2), |
792 | SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), | ||
793 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | 792 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, |
794 | 24, 0, eq_tlv), | 793 | 24, 0, eq_tlv), |
795 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | 794 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, |
@@ -801,8 +800,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | |||
801 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | 800 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, |
802 | 24, 0, eq_tlv), | 801 | 24, 0, eq_tlv), |
803 | 802 | ||
804 | SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), | 803 | ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2), |
805 | SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), | ||
806 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | 804 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, |
807 | 24, 0, eq_tlv), | 805 | 24, 0, eq_tlv), |
808 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | 806 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, |
@@ -814,8 +812,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | |||
814 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | 812 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, |
815 | 24, 0, eq_tlv), | 813 | 24, 0, eq_tlv), |
816 | 814 | ||
817 | SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), | 815 | ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2), |
818 | SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), | ||
819 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | 816 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, |
820 | 24, 0, eq_tlv), | 817 | 24, 0, eq_tlv), |
821 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | 818 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, |
@@ -827,8 +824,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | |||
827 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | 824 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, |
828 | 24, 0, eq_tlv), | 825 | 24, 0, eq_tlv), |
829 | 826 | ||
830 | SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), | 827 | ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2), |
831 | SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), | ||
832 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | 828 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, |
833 | 24, 0, eq_tlv), | 829 | 24, 0, eq_tlv), |
834 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | 830 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, |
@@ -851,10 +847,10 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), | |||
851 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), | 847 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), |
852 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), | 848 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), |
853 | 849 | ||
854 | SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1), | 850 | ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2), |
855 | SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1), | 851 | ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2), |
856 | SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1), | 852 | ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2), |
857 | SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1), | 853 | ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2), |
858 | 854 | ||
859 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), | 855 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), |
860 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), | 856 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), |
@@ -1883,7 +1879,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) | |||
1883 | ret = snd_soc_add_codec_controls(codec, | 1879 | ret = snd_soc_add_codec_controls(codec, |
1884 | arizona_adsp2_rate_controls, 1); | 1880 | arizona_adsp2_rate_controls, 1); |
1885 | if (ret) | 1881 | if (ret) |
1886 | return ret; | 1882 | goto err_adsp2_codec_probe; |
1887 | 1883 | ||
1888 | arizona_init_spk(codec); | 1884 | arizona_init_spk(codec); |
1889 | arizona_init_gpio(codec); | 1885 | arizona_init_gpio(codec); |
@@ -1893,6 +1889,11 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) | |||
1893 | priv->core.arizona->dapm = dapm; | 1889 | priv->core.arizona->dapm = dapm; |
1894 | 1890 | ||
1895 | return 0; | 1891 | return 0; |
1892 | |||
1893 | err_adsp2_codec_probe: | ||
1894 | wm_adsp2_codec_remove(&priv->core.adsp[0], codec); | ||
1895 | |||
1896 | return ret; | ||
1896 | } | 1897 | } |
1897 | 1898 | ||
1898 | static int wm5102_codec_remove(struct snd_soc_codec *codec) | 1899 | static int wm5102_codec_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 709fcc6169d8..9756578fc752 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -131,6 +131,25 @@ static const struct reg_default wm5110_sysclk_revd_patch[] = { | |||
131 | { 0x33fb, 0xfe00 }, | 131 | { 0x33fb, 0xfe00 }, |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static const struct reg_default wm5110_sysclk_reve_patch[] = { | ||
135 | { 0x3270, 0xE410 }, | ||
136 | { 0x3271, 0x3078 }, | ||
137 | { 0x3272, 0xE410 }, | ||
138 | { 0x3273, 0x3070 }, | ||
139 | { 0x3274, 0xE410 }, | ||
140 | { 0x3275, 0x3066 }, | ||
141 | { 0x3276, 0xE410 }, | ||
142 | { 0x3277, 0x3056 }, | ||
143 | { 0x327A, 0xE414 }, | ||
144 | { 0x327B, 0x3078 }, | ||
145 | { 0x327C, 0xE414 }, | ||
146 | { 0x327D, 0x3070 }, | ||
147 | { 0x327E, 0xE414 }, | ||
148 | { 0x327F, 0x3066 }, | ||
149 | { 0x3280, 0xE414 }, | ||
150 | { 0x3281, 0x3056 }, | ||
151 | }; | ||
152 | |||
134 | static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, | 153 | static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, |
135 | struct snd_kcontrol *kcontrol, int event) | 154 | struct snd_kcontrol *kcontrol, int event) |
136 | { | 155 | { |
@@ -146,7 +165,9 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
146 | patch_size = ARRAY_SIZE(wm5110_sysclk_revd_patch); | 165 | patch_size = ARRAY_SIZE(wm5110_sysclk_revd_patch); |
147 | break; | 166 | break; |
148 | default: | 167 | default: |
149 | return 0; | 168 | patch = wm5110_sysclk_reve_patch; |
169 | patch_size = ARRAY_SIZE(wm5110_sysclk_reve_patch); | ||
170 | break; | ||
150 | } | 171 | } |
151 | 172 | ||
152 | switch (event) { | 173 | switch (event) { |
@@ -164,6 +185,249 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
164 | return 0; | 185 | return 0; |
165 | } | 186 | } |
166 | 187 | ||
188 | static const struct reg_sequence wm5110_no_dre_left_enable[] = { | ||
189 | { 0x3024, 0xE410 }, | ||
190 | { 0x3025, 0x0056 }, | ||
191 | { 0x301B, 0x0224 }, | ||
192 | { 0x301F, 0x4263 }, | ||
193 | { 0x3021, 0x5291 }, | ||
194 | { 0x3030, 0xE410 }, | ||
195 | { 0x3031, 0x3066 }, | ||
196 | { 0x3032, 0xE410 }, | ||
197 | { 0x3033, 0x3070 }, | ||
198 | { 0x3034, 0xE410 }, | ||
199 | { 0x3035, 0x3078 }, | ||
200 | { 0x3036, 0xE410 }, | ||
201 | { 0x3037, 0x3080 }, | ||
202 | { 0x3038, 0xE410 }, | ||
203 | { 0x3039, 0x3080 }, | ||
204 | }; | ||
205 | |||
206 | static const struct reg_sequence wm5110_dre_left_enable[] = { | ||
207 | { 0x3024, 0x0231 }, | ||
208 | { 0x3025, 0x0B00 }, | ||
209 | { 0x301B, 0x0227 }, | ||
210 | { 0x301F, 0x4266 }, | ||
211 | { 0x3021, 0x5294 }, | ||
212 | { 0x3030, 0xE231 }, | ||
213 | { 0x3031, 0x0266 }, | ||
214 | { 0x3032, 0x8231 }, | ||
215 | { 0x3033, 0x4B15 }, | ||
216 | { 0x3034, 0x8231 }, | ||
217 | { 0x3035, 0x0B15 }, | ||
218 | { 0x3036, 0xE231 }, | ||
219 | { 0x3037, 0x5294 }, | ||
220 | { 0x3038, 0x0231 }, | ||
221 | { 0x3039, 0x0B00 }, | ||
222 | }; | ||
223 | |||
224 | static const struct reg_sequence wm5110_no_dre_right_enable[] = { | ||
225 | { 0x3074, 0xE414 }, | ||
226 | { 0x3075, 0x0056 }, | ||
227 | { 0x306B, 0x0224 }, | ||
228 | { 0x306F, 0x4263 }, | ||
229 | { 0x3071, 0x5291 }, | ||
230 | { 0x3080, 0xE414 }, | ||
231 | { 0x3081, 0x3066 }, | ||
232 | { 0x3082, 0xE414 }, | ||
233 | { 0x3083, 0x3070 }, | ||
234 | { 0x3084, 0xE414 }, | ||
235 | { 0x3085, 0x3078 }, | ||
236 | { 0x3086, 0xE414 }, | ||
237 | { 0x3087, 0x3080 }, | ||
238 | { 0x3088, 0xE414 }, | ||
239 | { 0x3089, 0x3080 }, | ||
240 | }; | ||
241 | |||
242 | static const struct reg_sequence wm5110_dre_right_enable[] = { | ||
243 | { 0x3074, 0x0231 }, | ||
244 | { 0x3075, 0x0B00 }, | ||
245 | { 0x306B, 0x0227 }, | ||
246 | { 0x306F, 0x4266 }, | ||
247 | { 0x3071, 0x5294 }, | ||
248 | { 0x3080, 0xE231 }, | ||
249 | { 0x3081, 0x0266 }, | ||
250 | { 0x3082, 0x8231 }, | ||
251 | { 0x3083, 0x4B17 }, | ||
252 | { 0x3084, 0x8231 }, | ||
253 | { 0x3085, 0x0B17 }, | ||
254 | { 0x3086, 0xE231 }, | ||
255 | { 0x3087, 0x5294 }, | ||
256 | { 0x3088, 0x0231 }, | ||
257 | { 0x3089, 0x0B00 }, | ||
258 | }; | ||
259 | |||
260 | static int wm5110_hp_pre_enable(struct snd_soc_dapm_widget *w) | ||
261 | { | ||
262 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
263 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
264 | struct arizona *arizona = priv->arizona; | ||
265 | unsigned int val = snd_soc_read(codec, ARIZONA_DRE_ENABLE); | ||
266 | const struct reg_sequence *wseq; | ||
267 | int nregs; | ||
268 | |||
269 | switch (w->shift) { | ||
270 | case ARIZONA_OUT1L_ENA_SHIFT: | ||
271 | if (val & ARIZONA_DRE1L_ENA_MASK) { | ||
272 | wseq = wm5110_dre_left_enable; | ||
273 | nregs = ARRAY_SIZE(wm5110_dre_left_enable); | ||
274 | } else { | ||
275 | wseq = wm5110_no_dre_left_enable; | ||
276 | nregs = ARRAY_SIZE(wm5110_no_dre_left_enable); | ||
277 | priv->out_up_delay += 10; | ||
278 | } | ||
279 | break; | ||
280 | case ARIZONA_OUT1R_ENA_SHIFT: | ||
281 | if (val & ARIZONA_DRE1R_ENA_MASK) { | ||
282 | wseq = wm5110_dre_right_enable; | ||
283 | nregs = ARRAY_SIZE(wm5110_dre_right_enable); | ||
284 | } else { | ||
285 | wseq = wm5110_no_dre_right_enable; | ||
286 | nregs = ARRAY_SIZE(wm5110_no_dre_right_enable); | ||
287 | priv->out_up_delay += 10; | ||
288 | } | ||
289 | break; | ||
290 | default: | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | return regmap_multi_reg_write(arizona->regmap, wseq, nregs); | ||
295 | } | ||
296 | |||
297 | static int wm5110_hp_pre_disable(struct snd_soc_dapm_widget *w) | ||
298 | { | ||
299 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
300 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
301 | unsigned int val = snd_soc_read(codec, ARIZONA_DRE_ENABLE); | ||
302 | |||
303 | switch (w->shift) { | ||
304 | case ARIZONA_OUT1L_ENA_SHIFT: | ||
305 | if (!(val & ARIZONA_DRE1L_ENA_MASK)) { | ||
306 | snd_soc_update_bits(codec, ARIZONA_SPARE_TRIGGERS, | ||
307 | ARIZONA_WS_TRG1, ARIZONA_WS_TRG1); | ||
308 | snd_soc_update_bits(codec, ARIZONA_SPARE_TRIGGERS, | ||
309 | ARIZONA_WS_TRG1, 0); | ||
310 | priv->out_down_delay += 27; | ||
311 | } | ||
312 | break; | ||
313 | case ARIZONA_OUT1R_ENA_SHIFT: | ||
314 | if (!(val & ARIZONA_DRE1R_ENA_MASK)) { | ||
315 | snd_soc_update_bits(codec, ARIZONA_SPARE_TRIGGERS, | ||
316 | ARIZONA_WS_TRG2, ARIZONA_WS_TRG2); | ||
317 | snd_soc_update_bits(codec, ARIZONA_SPARE_TRIGGERS, | ||
318 | ARIZONA_WS_TRG2, 0); | ||
319 | priv->out_down_delay += 27; | ||
320 | } | ||
321 | break; | ||
322 | default: | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static int wm5110_hp_ev(struct snd_soc_dapm_widget *w, | ||
330 | struct snd_kcontrol *kcontrol, int event) | ||
331 | { | ||
332 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
333 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
334 | |||
335 | switch (priv->arizona->rev) { | ||
336 | case 0 ... 3: | ||
337 | break; | ||
338 | default: | ||
339 | switch (event) { | ||
340 | case SND_SOC_DAPM_PRE_PMU: | ||
341 | wm5110_hp_pre_enable(w); | ||
342 | break; | ||
343 | case SND_SOC_DAPM_PRE_PMD: | ||
344 | wm5110_hp_pre_disable(w); | ||
345 | break; | ||
346 | default: | ||
347 | break; | ||
348 | } | ||
349 | break; | ||
350 | } | ||
351 | |||
352 | return arizona_hp_ev(w, kcontrol, event); | ||
353 | } | ||
354 | |||
355 | static int wm5110_clear_pga_volume(struct arizona *arizona, int output) | ||
356 | { | ||
357 | struct reg_sequence clear_pga = { | ||
358 | ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4, 0x80 | ||
359 | }; | ||
360 | int ret; | ||
361 | |||
362 | ret = regmap_multi_reg_write_bypassed(arizona->regmap, &clear_pga, 1); | ||
363 | if (ret) | ||
364 | dev_err(arizona->dev, "Failed to clear PGA (0x%x): %d\n", | ||
365 | clear_pga.reg, ret); | ||
366 | |||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | static int wm5110_put_dre(struct snd_kcontrol *kcontrol, | ||
371 | struct snd_ctl_elem_value *ucontrol) | ||
372 | { | ||
373 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
374 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
375 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
376 | struct soc_mixer_control *mc = | ||
377 | (struct soc_mixer_control *)kcontrol->private_value; | ||
378 | unsigned int ena, dre; | ||
379 | unsigned int mask = (0x1 << mc->shift) | (0x1 << mc->rshift); | ||
380 | unsigned int lnew = (!!ucontrol->value.integer.value[0]) << mc->shift; | ||
381 | unsigned int rnew = (!!ucontrol->value.integer.value[1]) << mc->rshift; | ||
382 | unsigned int lold, rold; | ||
383 | unsigned int lena, rena; | ||
384 | int ret; | ||
385 | |||
386 | snd_soc_dapm_mutex_lock(dapm); | ||
387 | |||
388 | ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &ena); | ||
389 | if (ret) { | ||
390 | dev_err(arizona->dev, "Failed to read output state: %d\n", ret); | ||
391 | goto err; | ||
392 | } | ||
393 | ret = regmap_read(arizona->regmap, ARIZONA_DRE_ENABLE, &dre); | ||
394 | if (ret) { | ||
395 | dev_err(arizona->dev, "Failed to read DRE state: %d\n", ret); | ||
396 | goto err; | ||
397 | } | ||
398 | |||
399 | lold = dre & (1 << mc->shift); | ||
400 | rold = dre & (1 << mc->rshift); | ||
401 | /* Enables are channel wise swapped from the DRE enables */ | ||
402 | lena = ena & (1 << mc->rshift); | ||
403 | rena = ena & (1 << mc->shift); | ||
404 | |||
405 | if ((lena && lnew != lold) || (rena && rnew != rold)) { | ||
406 | dev_err(arizona->dev, "Can't change DRE on active outputs\n"); | ||
407 | ret = -EBUSY; | ||
408 | goto err; | ||
409 | } | ||
410 | |||
411 | ret = regmap_update_bits(arizona->regmap, ARIZONA_DRE_ENABLE, | ||
412 | mask, lnew | rnew); | ||
413 | if (ret) { | ||
414 | dev_err(arizona->dev, "Failed to set DRE: %d\n", ret); | ||
415 | goto err; | ||
416 | } | ||
417 | |||
418 | /* Force reset of PGA volumes, if turning DRE off */ | ||
419 | if (!lnew && lold) | ||
420 | wm5110_clear_pga_volume(arizona, mc->shift); | ||
421 | |||
422 | if (!rnew && rold) | ||
423 | wm5110_clear_pga_volume(arizona, mc->rshift); | ||
424 | |||
425 | err: | ||
426 | snd_soc_dapm_mutex_unlock(dapm); | ||
427 | |||
428 | return ret; | ||
429 | } | ||
430 | |||
167 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | 431 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); |
168 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 432 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
169 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | 433 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); |
@@ -247,8 +511,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | |||
247 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | 511 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), |
248 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | 512 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), |
249 | 513 | ||
250 | SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), | 514 | ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2), |
251 | SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), | ||
252 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | 515 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, |
253 | 24, 0, eq_tlv), | 516 | 24, 0, eq_tlv), |
254 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | 517 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, |
@@ -260,8 +523,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | |||
260 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | 523 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, |
261 | 24, 0, eq_tlv), | 524 | 24, 0, eq_tlv), |
262 | 525 | ||
263 | SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), | 526 | ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2), |
264 | SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), | ||
265 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | 527 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, |
266 | 24, 0, eq_tlv), | 528 | 24, 0, eq_tlv), |
267 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | 529 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, |
@@ -273,8 +535,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | |||
273 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | 535 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, |
274 | 24, 0, eq_tlv), | 536 | 24, 0, eq_tlv), |
275 | 537 | ||
276 | SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), | 538 | ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2), |
277 | SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), | ||
278 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | 539 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, |
279 | 24, 0, eq_tlv), | 540 | 24, 0, eq_tlv), |
280 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | 541 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, |
@@ -286,8 +547,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | |||
286 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | 547 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, |
287 | 24, 0, eq_tlv), | 548 | 24, 0, eq_tlv), |
288 | 549 | ||
289 | SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), | 550 | ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2), |
290 | SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), | ||
291 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | 551 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, |
292 | 24, 0, eq_tlv), | 552 | 24, 0, eq_tlv), |
293 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | 553 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, |
@@ -314,10 +574,10 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), | |||
314 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), | 574 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), |
315 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), | 575 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), |
316 | 576 | ||
317 | SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1), | 577 | ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2), |
318 | SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1), | 578 | ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2), |
319 | SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1), | 579 | ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2), |
320 | SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1), | 580 | ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2), |
321 | 581 | ||
322 | SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), | 582 | SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), |
323 | SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | 583 | SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), |
@@ -409,12 +669,15 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | |||
409 | SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, | 669 | SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, |
410 | ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), | 670 | ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), |
411 | 671 | ||
412 | SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE, | 672 | SOC_DOUBLE_EXT("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE, |
413 | ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0), | 673 | ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0, |
414 | SOC_DOUBLE("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE, | 674 | snd_soc_get_volsw, wm5110_put_dre), |
415 | ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0), | 675 | SOC_DOUBLE_EXT("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE, |
416 | SOC_DOUBLE("HPOUT3 DRE Switch", ARIZONA_DRE_ENABLE, | 676 | ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0, |
417 | ARIZONA_DRE3L_ENA_SHIFT, ARIZONA_DRE3R_ENA_SHIFT, 1, 0), | 677 | snd_soc_get_volsw, wm5110_put_dre), |
678 | SOC_DOUBLE_EXT("HPOUT3 DRE Switch", ARIZONA_DRE_ENABLE, | ||
679 | ARIZONA_DRE3L_ENA_SHIFT, ARIZONA_DRE3R_ENA_SHIFT, 1, 0, | ||
680 | snd_soc_get_volsw, wm5110_put_dre), | ||
418 | 681 | ||
419 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), | 682 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), |
420 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), | 683 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), |
@@ -904,11 +1167,11 @@ SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | |||
904 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | 1167 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), |
905 | 1168 | ||
906 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, | 1169 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, |
907 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | 1170 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, wm5110_hp_ev, |
908 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | 1171 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
909 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | 1172 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
910 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, | 1173 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, |
911 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | 1174 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, wm5110_hp_ev, |
912 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | 1175 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
913 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | 1176 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
914 | SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, | 1177 | SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, |
@@ -1611,18 +1874,24 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) | |||
1611 | for (i = 0; i < WM5110_NUM_ADSP; ++i) { | 1874 | for (i = 0; i < WM5110_NUM_ADSP; ++i) { |
1612 | ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec); | 1875 | ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec); |
1613 | if (ret) | 1876 | if (ret) |
1614 | return ret; | 1877 | goto err_adsp2_codec_probe; |
1615 | } | 1878 | } |
1616 | 1879 | ||
1617 | ret = snd_soc_add_codec_controls(codec, | 1880 | ret = snd_soc_add_codec_controls(codec, |
1618 | arizona_adsp2_rate_controls, | 1881 | arizona_adsp2_rate_controls, |
1619 | WM5110_NUM_ADSP); | 1882 | WM5110_NUM_ADSP); |
1620 | if (ret) | 1883 | if (ret) |
1621 | return ret; | 1884 | goto err_adsp2_codec_probe; |
1622 | 1885 | ||
1623 | snd_soc_dapm_disable_pin(dapm, "HAPTICS"); | 1886 | snd_soc_dapm_disable_pin(dapm, "HAPTICS"); |
1624 | 1887 | ||
1625 | return 0; | 1888 | return 0; |
1889 | |||
1890 | err_adsp2_codec_probe: | ||
1891 | for (--i; i >= 0; --i) | ||
1892 | wm_adsp2_codec_remove(&priv->core.adsp[i], codec); | ||
1893 | |||
1894 | return ret; | ||
1626 | } | 1895 | } |
1627 | 1896 | ||
1628 | static int wm5110_codec_remove(struct snd_soc_codec *codec) | 1897 | static int wm5110_codec_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 41c62c1e62db..ffbf3df8ae97 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -394,11 +394,10 @@ static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1); | |||
394 | static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1); | 394 | static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1); |
395 | static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1); | 395 | static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1); |
396 | 396 | ||
397 | static const unsigned int capture_sd_tlv[] = { | 397 | static const DECLARE_TLV_DB_RANGE(capture_sd_tlv, |
398 | TLV_DB_RANGE_HEAD(2), | ||
399 | 0, 12, TLV_DB_SCALE_ITEM(-3600, 300, 1), | 398 | 0, 12, TLV_DB_SCALE_ITEM(-3600, 300, 1), |
400 | 13, 15, TLV_DB_SCALE_ITEM(0, 0, 0), | 399 | 13, 15, TLV_DB_SCALE_ITEM(0, 0, 0) |
401 | }; | 400 | ); |
402 | 401 | ||
403 | static const struct snd_kcontrol_new wm8350_snd_controls[] = { | 402 | static const struct snd_kcontrol_new wm8350_snd_controls[] = { |
404 | SOC_ENUM("Playback Deemphasis", wm8350_enum[0]), | 403 | SOC_ENUM("Playback Deemphasis", wm8350_enum[0]), |
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index d7555085e7f4..b1d346aa4696 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -370,10 +370,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, | |||
370 | } | 370 | } |
371 | 371 | ||
372 | /* INMIX dB values */ | 372 | /* INMIX dB values */ |
373 | static const unsigned int in_mix_tlv[] = { | 373 | static const DECLARE_TLV_DB_SCALE(in_mix_tlv, -1200, 600, 0); |
374 | TLV_DB_RANGE_HEAD(1), | ||
375 | 0,7, TLV_DB_SCALE_ITEM(-1200, 600, 0), | ||
376 | }; | ||
377 | 374 | ||
378 | /* Left In PGA Connections */ | 375 | /* Left In PGA Connections */ |
379 | static const struct snd_kcontrol_new wm8400_dapm_lin12_pga_controls[] = { | 376 | static const struct snd_kcontrol_new wm8400_dapm_lin12_pga_controls[] = { |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index dac5beb4d023..b098a83a44d8 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -598,6 +598,7 @@ static const struct of_device_id wm8510_of_match[] = { | |||
598 | { .compatible = "wlf,wm8510" }, | 598 | { .compatible = "wlf,wm8510" }, |
599 | { }, | 599 | { }, |
600 | }; | 600 | }; |
601 | MODULE_DEVICE_TABLE(of, wm8510_of_match); | ||
601 | 602 | ||
602 | static const struct regmap_config wm8510_regmap = { | 603 | static const struct regmap_config wm8510_regmap = { |
603 | .reg_bits = 7, | 604 | .reg_bits = 7, |
@@ -690,7 +691,6 @@ MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); | |||
690 | static struct i2c_driver wm8510_i2c_driver = { | 691 | static struct i2c_driver wm8510_i2c_driver = { |
691 | .driver = { | 692 | .driver = { |
692 | .name = "wm8510", | 693 | .name = "wm8510", |
693 | .owner = THIS_MODULE, | ||
694 | .of_match_table = wm8510_of_match, | 694 | .of_match_table = wm8510_of_match, |
695 | }, | 695 | }, |
696 | .probe = wm8510_i2c_probe, | 696 | .probe = wm8510_i2c_probe, |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 43ea8ae5f871..aa287a3965e7 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -430,6 +430,7 @@ static const struct of_device_id wm8523_of_match[] = { | |||
430 | { .compatible = "wlf,wm8523" }, | 430 | { .compatible = "wlf,wm8523" }, |
431 | { }, | 431 | { }, |
432 | }; | 432 | }; |
433 | MODULE_DEVICE_TABLE(of, wm8523_of_match); | ||
433 | 434 | ||
434 | static const struct regmap_config wm8523_regmap = { | 435 | static const struct regmap_config wm8523_regmap = { |
435 | .reg_bits = 8, | 436 | .reg_bits = 8, |
@@ -534,7 +535,6 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); | |||
534 | static struct i2c_driver wm8523_i2c_driver = { | 535 | static struct i2c_driver wm8523_i2c_driver = { |
535 | .driver = { | 536 | .driver = { |
536 | .name = "wm8523", | 537 | .name = "wm8523", |
537 | .owner = THIS_MODULE, | ||
538 | .of_match_table = wm8523_of_match, | 538 | .of_match_table = wm8523_of_match, |
539 | }, | 539 | }, |
540 | .probe = wm8523_i2c_probe, | 540 | .probe = wm8523_i2c_probe, |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 759a7928ac3e..66602bf02f6e 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -916,6 +916,7 @@ static const struct of_device_id wm8580_of_match[] = { | |||
916 | { .compatible = "wlf,wm8580" }, | 916 | { .compatible = "wlf,wm8580" }, |
917 | { }, | 917 | { }, |
918 | }; | 918 | }; |
919 | MODULE_DEVICE_TABLE(of, wm8580_of_match); | ||
919 | 920 | ||
920 | static const struct regmap_config wm8580_regmap = { | 921 | static const struct regmap_config wm8580_regmap = { |
921 | .reg_bits = 7, | 922 | .reg_bits = 7, |
@@ -978,7 +979,6 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); | |||
978 | static struct i2c_driver wm8580_i2c_driver = { | 979 | static struct i2c_driver wm8580_i2c_driver = { |
979 | .driver = { | 980 | .driver = { |
980 | .name = "wm8580", | 981 | .name = "wm8580", |
981 | .owner = THIS_MODULE, | ||
982 | .of_match_table = wm8580_of_match, | 982 | .of_match_table = wm8580_of_match, |
983 | }, | 983 | }, |
984 | .probe = wm8580_i2c_probe, | 984 | .probe = wm8580_i2c_probe, |
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index cc8251f09f8a..44b9e0ae7451 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -478,7 +478,6 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); | |||
478 | static struct i2c_driver wm8711_i2c_driver = { | 478 | static struct i2c_driver wm8711_i2c_driver = { |
479 | .driver = { | 479 | .driver = { |
480 | .name = "wm8711", | 480 | .name = "wm8711", |
481 | .owner = THIS_MODULE, | ||
482 | .of_match_table = wm8711_of_match, | 481 | .of_match_table = wm8711_of_match, |
483 | }, | 482 | }, |
484 | .probe = wm8711_i2c_probe, | 483 | .probe = wm8711_i2c_probe, |
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index f1a173e6ec33..cd7b02413ccf 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -319,7 +319,6 @@ MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); | |||
319 | static struct i2c_driver wm8728_i2c_driver = { | 319 | static struct i2c_driver wm8728_i2c_driver = { |
320 | .driver = { | 320 | .driver = { |
321 | .name = "wm8728", | 321 | .name = "wm8728", |
322 | .owner = THIS_MODULE, | ||
323 | .of_match_table = wm8728_of_match, | 322 | .of_match_table = wm8728_of_match, |
324 | }, | 323 | }, |
325 | .probe = wm8728_i2c_probe, | 324 | .probe = wm8728_i2c_probe, |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 915ea11ad4b6..ace8645245a0 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -79,12 +79,7 @@ static bool wm8731_volatile(struct device *dev, unsigned int reg) | |||
79 | return reg == WM8731_RESET; | 79 | return reg == WM8731_RESET; |
80 | } | 80 | } |
81 | 81 | ||
82 | static bool wm8731_writeable(struct device *dev, unsigned int reg) | 82 | #define wm8731_reset(m) regmap_write(m, WM8731_RESET, 0) |
83 | { | ||
84 | return reg <= WM8731_RESET; | ||
85 | } | ||
86 | |||
87 | #define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0) | ||
88 | 83 | ||
89 | static const char *wm8731_input_select[] = {"Line In", "Mic"}; | 84 | static const char *wm8731_input_select[] = {"Line In", "Mic"}; |
90 | 85 | ||
@@ -496,8 +491,11 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
496 | 491 | ||
497 | switch (level) { | 492 | switch (level) { |
498 | case SND_SOC_BIAS_ON: | 493 | case SND_SOC_BIAS_ON: |
499 | if (wm8731->mclk) | 494 | if (wm8731->mclk) { |
500 | clk_prepare_enable(wm8731->mclk); | 495 | ret = clk_prepare_enable(wm8731->mclk); |
496 | if (ret) | ||
497 | return ret; | ||
498 | } | ||
501 | break; | 499 | break; |
502 | case SND_SOC_BIAS_PREPARE: | 500 | case SND_SOC_BIAS_PREPARE: |
503 | break; | 501 | break; |
@@ -571,69 +569,63 @@ static struct snd_soc_dai_driver wm8731_dai = { | |||
571 | .symmetric_rates = 1, | 569 | .symmetric_rates = 1, |
572 | }; | 570 | }; |
573 | 571 | ||
574 | static int wm8731_probe(struct snd_soc_codec *codec) | 572 | static int wm8731_request_supplies(struct device *dev, |
573 | struct wm8731_priv *wm8731) | ||
575 | { | 574 | { |
576 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | ||
577 | int ret = 0, i; | 575 | int ret = 0, i; |
578 | 576 | ||
579 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) | 577 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) |
580 | wm8731->supplies[i].supply = wm8731_supply_names[i]; | 578 | wm8731->supplies[i].supply = wm8731_supply_names[i]; |
581 | 579 | ||
582 | ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies), | 580 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(wm8731->supplies), |
583 | wm8731->supplies); | 581 | wm8731->supplies); |
584 | if (ret != 0) { | 582 | if (ret != 0) { |
585 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 583 | dev_err(dev, "Failed to request supplies: %d\n", ret); |
586 | return ret; | 584 | return ret; |
587 | } | 585 | } |
588 | 586 | ||
589 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | 587 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), |
590 | wm8731->supplies); | 588 | wm8731->supplies); |
591 | if (ret != 0) { | 589 | if (ret != 0) { |
592 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 590 | dev_err(dev, "Failed to enable supplies: %d\n", ret); |
593 | return ret; | 591 | return ret; |
594 | } | 592 | } |
595 | 593 | ||
596 | ret = wm8731_reset(codec); | 594 | return 0; |
595 | } | ||
596 | |||
597 | static int wm8731_hw_init(struct device *dev, struct wm8731_priv *wm8731) | ||
598 | { | ||
599 | int ret = 0; | ||
600 | |||
601 | ret = wm8731_reset(wm8731->regmap); | ||
597 | if (ret < 0) { | 602 | if (ret < 0) { |
598 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 603 | dev_err(dev, "Failed to issue reset: %d\n", ret); |
599 | goto err_regulator_enable; | 604 | goto err_regulator_enable; |
600 | } | 605 | } |
601 | 606 | ||
602 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); | 607 | /* Clear POWEROFF, keep everything else disabled */ |
608 | regmap_write(wm8731->regmap, WM8731_PWR, 0x7f); | ||
603 | 609 | ||
604 | /* Latch the update bits */ | 610 | /* Latch the update bits */ |
605 | snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0); | 611 | regmap_update_bits(wm8731->regmap, WM8731_LOUT1V, 0x100, 0); |
606 | snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0); | 612 | regmap_update_bits(wm8731->regmap, WM8731_ROUT1V, 0x100, 0); |
607 | snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0); | 613 | regmap_update_bits(wm8731->regmap, WM8731_LINVOL, 0x100, 0); |
608 | snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0); | 614 | regmap_update_bits(wm8731->regmap, WM8731_RINVOL, 0x100, 0); |
609 | 615 | ||
610 | /* Disable bypass path by default */ | 616 | /* Disable bypass path by default */ |
611 | snd_soc_update_bits(codec, WM8731_APANA, 0x8, 0); | 617 | regmap_update_bits(wm8731->regmap, WM8731_APANA, 0x8, 0); |
612 | 618 | ||
613 | /* Regulators will have been enabled by bias management */ | 619 | regcache_mark_dirty(wm8731->regmap); |
614 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
615 | |||
616 | return 0; | ||
617 | 620 | ||
618 | err_regulator_enable: | 621 | err_regulator_enable: |
622 | /* Regulators will be enabled by bias management */ | ||
619 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 623 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
620 | 624 | ||
621 | return ret; | 625 | return ret; |
622 | } | 626 | } |
623 | 627 | ||
624 | /* power down chip */ | ||
625 | static int wm8731_remove(struct snd_soc_codec *codec) | ||
626 | { | ||
627 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | ||
628 | |||
629 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
630 | |||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { | 628 | static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { |
635 | .probe = wm8731_probe, | ||
636 | .remove = wm8731_remove, | ||
637 | .set_bias_level = wm8731_set_bias_level, | 629 | .set_bias_level = wm8731_set_bias_level, |
638 | .suspend_bias_off = true, | 630 | .suspend_bias_off = true, |
639 | 631 | ||
@@ -658,7 +650,6 @@ static const struct regmap_config wm8731_regmap = { | |||
658 | 650 | ||
659 | .max_register = WM8731_RESET, | 651 | .max_register = WM8731_RESET, |
660 | .volatile_reg = wm8731_volatile, | 652 | .volatile_reg = wm8731_volatile, |
661 | .writeable_reg = wm8731_writeable, | ||
662 | 653 | ||
663 | .cache_type = REGCACHE_RBTREE, | 654 | .cache_type = REGCACHE_RBTREE, |
664 | .reg_defaults = wm8731_reg_defaults, | 655 | .reg_defaults = wm8731_reg_defaults, |
@@ -690,6 +681,12 @@ static int wm8731_spi_probe(struct spi_device *spi) | |||
690 | 681 | ||
691 | mutex_init(&wm8731->lock); | 682 | mutex_init(&wm8731->lock); |
692 | 683 | ||
684 | spi_set_drvdata(spi, wm8731); | ||
685 | |||
686 | ret = wm8731_request_supplies(&spi->dev, wm8731); | ||
687 | if (ret != 0) | ||
688 | return ret; | ||
689 | |||
693 | wm8731->regmap = devm_regmap_init_spi(spi, &wm8731_regmap); | 690 | wm8731->regmap = devm_regmap_init_spi(spi, &wm8731_regmap); |
694 | if (IS_ERR(wm8731->regmap)) { | 691 | if (IS_ERR(wm8731->regmap)) { |
695 | ret = PTR_ERR(wm8731->regmap); | 692 | ret = PTR_ERR(wm8731->regmap); |
@@ -698,7 +695,9 @@ static int wm8731_spi_probe(struct spi_device *spi) | |||
698 | return ret; | 695 | return ret; |
699 | } | 696 | } |
700 | 697 | ||
701 | spi_set_drvdata(spi, wm8731); | 698 | ret = wm8731_hw_init(&spi->dev, wm8731); |
699 | if (ret != 0) | ||
700 | return ret; | ||
702 | 701 | ||
703 | ret = snd_soc_register_codec(&spi->dev, | 702 | ret = snd_soc_register_codec(&spi->dev, |
704 | &soc_codec_dev_wm8731, &wm8731_dai, 1); | 703 | &soc_codec_dev_wm8731, &wm8731_dai, 1); |
@@ -754,6 +753,12 @@ static int wm8731_i2c_probe(struct i2c_client *i2c, | |||
754 | 753 | ||
755 | mutex_init(&wm8731->lock); | 754 | mutex_init(&wm8731->lock); |
756 | 755 | ||
756 | i2c_set_clientdata(i2c, wm8731); | ||
757 | |||
758 | ret = wm8731_request_supplies(&i2c->dev, wm8731); | ||
759 | if (ret != 0) | ||
760 | return ret; | ||
761 | |||
757 | wm8731->regmap = devm_regmap_init_i2c(i2c, &wm8731_regmap); | 762 | wm8731->regmap = devm_regmap_init_i2c(i2c, &wm8731_regmap); |
758 | if (IS_ERR(wm8731->regmap)) { | 763 | if (IS_ERR(wm8731->regmap)) { |
759 | ret = PTR_ERR(wm8731->regmap); | 764 | ret = PTR_ERR(wm8731->regmap); |
@@ -762,7 +767,9 @@ static int wm8731_i2c_probe(struct i2c_client *i2c, | |||
762 | return ret; | 767 | return ret; |
763 | } | 768 | } |
764 | 769 | ||
765 | i2c_set_clientdata(i2c, wm8731); | 770 | ret = wm8731_hw_init(&i2c->dev, wm8731); |
771 | if (ret != 0) | ||
772 | return ret; | ||
766 | 773 | ||
767 | ret = snd_soc_register_codec(&i2c->dev, | 774 | ret = snd_soc_register_codec(&i2c->dev, |
768 | &soc_codec_dev_wm8731, &wm8731_dai, 1); | 775 | &soc_codec_dev_wm8731, &wm8731_dai, 1); |
@@ -789,7 +796,6 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); | |||
789 | static struct i2c_driver wm8731_i2c_driver = { | 796 | static struct i2c_driver wm8731_i2c_driver = { |
790 | .driver = { | 797 | .driver = { |
791 | .name = "wm8731", | 798 | .name = "wm8731", |
792 | .owner = THIS_MODULE, | ||
793 | .of_match_table = wm8731_of_match, | 799 | .of_match_table = wm8731_of_match, |
794 | }, | 800 | }, |
795 | .probe = wm8731_i2c_probe, | 801 | .probe = wm8731_i2c_probe, |
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 6ad606fd8b69..e4a03d98aed4 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c | |||
@@ -79,13 +79,12 @@ static int wm8737_reset(struct snd_soc_codec *codec) | |||
79 | return snd_soc_write(codec, WM8737_RESET, 0); | 79 | return snd_soc_write(codec, WM8737_RESET, 0); |
80 | } | 80 | } |
81 | 81 | ||
82 | static const unsigned int micboost_tlv[] = { | 82 | static const DECLARE_TLV_DB_RANGE(micboost_tlv, |
83 | TLV_DB_RANGE_HEAD(4), | ||
84 | 0, 0, TLV_DB_SCALE_ITEM(1300, 0, 0), | 83 | 0, 0, TLV_DB_SCALE_ITEM(1300, 0, 0), |
85 | 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0), | 84 | 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0), |
86 | 2, 2, TLV_DB_SCALE_ITEM(2800, 0, 0), | 85 | 2, 2, TLV_DB_SCALE_ITEM(2800, 0, 0), |
87 | 3, 3, TLV_DB_SCALE_ITEM(3300, 0, 0), | 86 | 3, 3, TLV_DB_SCALE_ITEM(3300, 0, 0) |
88 | }; | 87 | ); |
89 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -9750, 50, 1); | 88 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -9750, 50, 1); |
90 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -600, 600, 0); | 89 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -600, 600, 0); |
91 | static const DECLARE_TLV_DB_SCALE(ng_tlv, -7800, 600, 0); | 90 | static const DECLARE_TLV_DB_SCALE(ng_tlv, -7800, 600, 0); |
@@ -657,7 +656,6 @@ MODULE_DEVICE_TABLE(i2c, wm8737_i2c_id); | |||
657 | static struct i2c_driver wm8737_i2c_driver = { | 656 | static struct i2c_driver wm8737_i2c_driver = { |
658 | .driver = { | 657 | .driver = { |
659 | .name = "wm8737", | 658 | .name = "wm8737", |
660 | .owner = THIS_MODULE, | ||
661 | .of_match_table = wm8737_of_match, | 659 | .of_match_table = wm8737_of_match, |
662 | }, | 660 | }, |
663 | .probe = wm8737_i2c_probe, | 661 | .probe = wm8737_i2c_probe, |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index b34623786e35..de42c0388772 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -61,25 +61,6 @@ static const struct reg_default wm8741_reg_defaults[] = { | |||
61 | { 32, 0x0002 }, /* R32 - ADDITONAL_CONTROL_1 */ | 61 | { 32, 0x0002 }, /* R32 - ADDITONAL_CONTROL_1 */ |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static bool wm8741_readable(struct device *dev, unsigned int reg) | ||
65 | { | ||
66 | switch (reg) { | ||
67 | case WM8741_DACLLSB_ATTENUATION: | ||
68 | case WM8741_DACLMSB_ATTENUATION: | ||
69 | case WM8741_DACRLSB_ATTENUATION: | ||
70 | case WM8741_DACRMSB_ATTENUATION: | ||
71 | case WM8741_VOLUME_CONTROL: | ||
72 | case WM8741_FORMAT_CONTROL: | ||
73 | case WM8741_FILTER_CONTROL: | ||
74 | case WM8741_MODE_CONTROL_1: | ||
75 | case WM8741_MODE_CONTROL_2: | ||
76 | case WM8741_ADDITIONAL_CONTROL_1: | ||
77 | return true; | ||
78 | default: | ||
79 | return false; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | static int wm8741_reset(struct snd_soc_codec *codec) | 64 | static int wm8741_reset(struct snd_soc_codec *codec) |
84 | { | 65 | { |
85 | return snd_soc_write(codec, WM8741_RESET, 0); | 66 | return snd_soc_write(codec, WM8741_RESET, 0); |
@@ -278,51 +259,38 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
278 | switch (freq) { | 259 | switch (freq) { |
279 | case 0: | 260 | case 0: |
280 | wm8741->sysclk_constraints = NULL; | 261 | wm8741->sysclk_constraints = NULL; |
281 | wm8741->sysclk = freq; | 262 | break; |
282 | return 0; | ||
283 | |||
284 | case 11289600: | 263 | case 11289600: |
285 | wm8741->sysclk_constraints = &constraints_11289; | 264 | wm8741->sysclk_constraints = &constraints_11289; |
286 | wm8741->sysclk = freq; | 265 | break; |
287 | return 0; | ||
288 | |||
289 | case 12288000: | 266 | case 12288000: |
290 | wm8741->sysclk_constraints = &constraints_12288; | 267 | wm8741->sysclk_constraints = &constraints_12288; |
291 | wm8741->sysclk = freq; | 268 | break; |
292 | return 0; | ||
293 | |||
294 | case 16384000: | 269 | case 16384000: |
295 | wm8741->sysclk_constraints = &constraints_16384; | 270 | wm8741->sysclk_constraints = &constraints_16384; |
296 | wm8741->sysclk = freq; | 271 | break; |
297 | return 0; | ||
298 | |||
299 | case 16934400: | 272 | case 16934400: |
300 | wm8741->sysclk_constraints = &constraints_16934; | 273 | wm8741->sysclk_constraints = &constraints_16934; |
301 | wm8741->sysclk = freq; | 274 | break; |
302 | return 0; | ||
303 | |||
304 | case 18432000: | 275 | case 18432000: |
305 | wm8741->sysclk_constraints = &constraints_18432; | 276 | wm8741->sysclk_constraints = &constraints_18432; |
306 | wm8741->sysclk = freq; | 277 | break; |
307 | return 0; | ||
308 | |||
309 | case 22579200: | 278 | case 22579200: |
310 | case 33868800: | 279 | case 33868800: |
311 | wm8741->sysclk_constraints = &constraints_22579; | 280 | wm8741->sysclk_constraints = &constraints_22579; |
312 | wm8741->sysclk = freq; | 281 | break; |
313 | return 0; | ||
314 | |||
315 | case 24576000: | 282 | case 24576000: |
316 | wm8741->sysclk_constraints = &constraints_24576; | 283 | wm8741->sysclk_constraints = &constraints_24576; |
317 | wm8741->sysclk = freq; | 284 | break; |
318 | return 0; | ||
319 | |||
320 | case 36864000: | 285 | case 36864000: |
321 | wm8741->sysclk_constraints = &constraints_36864; | 286 | wm8741->sysclk_constraints = &constraints_36864; |
322 | wm8741->sysclk = freq; | 287 | break; |
323 | return 0; | 288 | default: |
289 | return -EINVAL; | ||
324 | } | 290 | } |
325 | return -EINVAL; | 291 | |
292 | wm8741->sysclk = freq; | ||
293 | return 0; | ||
326 | } | 294 | } |
327 | 295 | ||
328 | static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, | 296 | static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, |
@@ -554,8 +522,6 @@ static const struct regmap_config wm8741_regmap = { | |||
554 | .reg_defaults = wm8741_reg_defaults, | 522 | .reg_defaults = wm8741_reg_defaults, |
555 | .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults), | 523 | .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults), |
556 | .cache_type = REGCACHE_RBTREE, | 524 | .cache_type = REGCACHE_RBTREE, |
557 | |||
558 | .readable_reg = wm8741_readable, | ||
559 | }; | 525 | }; |
560 | 526 | ||
561 | static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741) | 527 | static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741) |
@@ -633,7 +599,6 @@ MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); | |||
633 | static struct i2c_driver wm8741_i2c_driver = { | 599 | static struct i2c_driver wm8741_i2c_driver = { |
634 | .driver = { | 600 | .driver = { |
635 | .name = "wm8741", | 601 | .name = "wm8741", |
636 | .owner = THIS_MODULE, | ||
637 | .of_match_table = wm8741_of_match, | 602 | .of_match_table = wm8741_of_match, |
638 | }, | 603 | }, |
639 | .probe = wm8741_i2c_probe, | 604 | .probe = wm8741_i2c_probe, |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 56d89b0865fa..873933a7966f 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -826,7 +826,6 @@ MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); | |||
826 | static struct i2c_driver wm8750_i2c_driver = { | 826 | static struct i2c_driver wm8750_i2c_driver = { |
827 | .driver = { | 827 | .driver = { |
828 | .name = "wm8750", | 828 | .name = "wm8750", |
829 | .owner = THIS_MODULE, | ||
830 | .of_match_table = wm8750_of_match, | 829 | .of_match_table = wm8750_of_match, |
831 | }, | 830 | }, |
832 | .probe = wm8750_i2c_probe, | 831 | .probe = wm8750_i2c_probe, |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index feb2997a377a..a801c6d75436 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -138,11 +138,6 @@ static bool wm8753_volatile(struct device *dev, unsigned int reg) | |||
138 | return reg == WM8753_RESET; | 138 | return reg == WM8753_RESET; |
139 | } | 139 | } |
140 | 140 | ||
141 | static bool wm8753_writeable(struct device *dev, unsigned int reg) | ||
142 | { | ||
143 | return reg <= WM8753_ADCTL2; | ||
144 | } | ||
145 | |||
146 | /* codec private data */ | 141 | /* codec private data */ |
147 | struct wm8753_priv { | 142 | struct wm8753_priv { |
148 | struct regmap *regmap; | 143 | struct regmap *regmap; |
@@ -276,12 +271,11 @@ static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 300, 0); | |||
276 | static const DECLARE_TLV_DB_SCALE(mic_preamp_tlv, 1200, 600, 0); | 271 | static const DECLARE_TLV_DB_SCALE(mic_preamp_tlv, 1200, 600, 0); |
277 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1); | 272 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1); |
278 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); | 273 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); |
279 | static const unsigned int out_tlv[] = { | 274 | static const DECLARE_TLV_DB_RANGE(out_tlv, |
280 | TLV_DB_RANGE_HEAD(2), | ||
281 | /* 0000000 - 0101111 = "Analogue mute" */ | 275 | /* 0000000 - 0101111 = "Analogue mute" */ |
282 | 0, 48, TLV_DB_SCALE_ITEM(-25500, 0, 0), | 276 | 0, 48, TLV_DB_SCALE_ITEM(-25500, 0, 0), |
283 | 48, 127, TLV_DB_SCALE_ITEM(-7300, 100, 0), | 277 | 48, 127, TLV_DB_SCALE_ITEM(-7300, 100, 0) |
284 | }; | 278 | ); |
285 | static const DECLARE_TLV_DB_SCALE(mix_tlv, -1500, 300, 0); | 279 | static const DECLARE_TLV_DB_SCALE(mix_tlv, -1500, 300, 0); |
286 | static const DECLARE_TLV_DB_SCALE(voice_mix_tlv, -1200, 300, 0); | 280 | static const DECLARE_TLV_DB_SCALE(voice_mix_tlv, -1200, 300, 0); |
287 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); | 281 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); |
@@ -1510,7 +1504,6 @@ static const struct regmap_config wm8753_regmap = { | |||
1510 | .val_bits = 9, | 1504 | .val_bits = 9, |
1511 | 1505 | ||
1512 | .max_register = WM8753_ADCTL2, | 1506 | .max_register = WM8753_ADCTL2, |
1513 | .writeable_reg = wm8753_writeable, | ||
1514 | .volatile_reg = wm8753_volatile, | 1507 | .volatile_reg = wm8753_volatile, |
1515 | 1508 | ||
1516 | .cache_type = REGCACHE_RBTREE, | 1509 | .cache_type = REGCACHE_RBTREE, |
@@ -1609,7 +1602,6 @@ MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); | |||
1609 | static struct i2c_driver wm8753_i2c_driver = { | 1602 | static struct i2c_driver wm8753_i2c_driver = { |
1610 | .driver = { | 1603 | .driver = { |
1611 | .name = "wm8753", | 1604 | .name = "wm8753", |
1612 | .owner = THIS_MODULE, | ||
1613 | .of_match_table = wm8753_of_match, | 1605 | .of_match_table = wm8753_of_match, |
1614 | }, | 1606 | }, |
1615 | .probe = wm8753_i2c_probe, | 1607 | .probe = wm8753_i2c_probe, |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index ece9b4456767..183c9a4966c5 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -265,7 +265,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
265 | } | 265 | } |
266 | 266 | ||
267 | /* Set word length */ | 267 | /* Set word length */ |
268 | switch (snd_pcm_format_width(params_format(params))) { | 268 | switch (params_width(params)) { |
269 | case 16: | 269 | case 16: |
270 | iface = 0; | 270 | iface = 0; |
271 | break; | 271 | break; |
@@ -280,7 +280,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
280 | break; | 280 | break; |
281 | default: | 281 | default: |
282 | dev_err(codec->dev, "Unsupported sample size: %i\n", | 282 | dev_err(codec->dev, "Unsupported sample size: %i\n", |
283 | snd_pcm_format_width(params_format(params))); | 283 | params_width(params)); |
284 | return -EINVAL; | 284 | return -EINVAL; |
285 | } | 285 | } |
286 | 286 | ||
@@ -536,7 +536,6 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); | |||
536 | static struct i2c_driver wm8776_i2c_driver = { | 536 | static struct i2c_driver wm8776_i2c_driver = { |
537 | .driver = { | 537 | .driver = { |
538 | .name = "wm8776", | 538 | .name = "wm8776", |
539 | .owner = THIS_MODULE, | ||
540 | .of_match_table = wm8776_of_match, | 539 | .of_match_table = wm8776_of_match, |
541 | }, | 540 | }, |
542 | .probe = wm8776_i2c_probe, | 541 | .probe = wm8776_i2c_probe, |
diff --git a/sound/soc/codecs/wm8804-i2c.c b/sound/soc/codecs/wm8804-i2c.c index 6596f5f3a0c3..f27464c2c5ba 100644 --- a/sound/soc/codecs/wm8804-i2c.c +++ b/sound/soc/codecs/wm8804-i2c.c | |||
@@ -49,7 +49,6 @@ MODULE_DEVICE_TABLE(of, wm8804_of_match); | |||
49 | static struct i2c_driver wm8804_i2c_driver = { | 49 | static struct i2c_driver wm8804_i2c_driver = { |
50 | .driver = { | 50 | .driver = { |
51 | .name = "wm8804", | 51 | .name = "wm8804", |
52 | .owner = THIS_MODULE, | ||
53 | .pm = &wm8804_pm, | 52 | .pm = &wm8804_pm, |
54 | .of_match_table = wm8804_of_match, | 53 | .of_match_table = wm8804_of_match, |
55 | }, | 54 | }, |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index c195c2e8af07..8d914702cae4 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -98,7 +98,7 @@ WM8804_REGULATOR_EVENT(0) | |||
98 | WM8804_REGULATOR_EVENT(1) | 98 | WM8804_REGULATOR_EVENT(1) |
99 | 99 | ||
100 | static const char *txsrc_text[] = { "S/PDIF RX", "AIF" }; | 100 | static const char *txsrc_text[] = { "S/PDIF RX", "AIF" }; |
101 | static const SOC_ENUM_SINGLE_DECL(txsrc, WM8804_SPDTX4, 6, txsrc_text); | 101 | static SOC_ENUM_SINGLE_DECL(txsrc, WM8804_SPDTX4, 6, txsrc_text); |
102 | 102 | ||
103 | static const struct snd_kcontrol_new wm8804_tx_source_mux[] = { | 103 | static const struct snd_kcontrol_new wm8804_tx_source_mux[] = { |
104 | SOC_DAPM_ENUM_EXT("Input Source", txsrc, | 104 | SOC_DAPM_ENUM_EXT("Input Source", txsrc, |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index f3759ec5a863..98900aa66dc3 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -1312,7 +1312,6 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); | |||
1312 | static struct i2c_driver wm8900_i2c_driver = { | 1312 | static struct i2c_driver wm8900_i2c_driver = { |
1313 | .driver = { | 1313 | .driver = { |
1314 | .name = "wm8900", | 1314 | .name = "wm8900", |
1315 | .owner = THIS_MODULE, | ||
1316 | }, | 1315 | }, |
1317 | .probe = wm8900_i2c_probe, | 1316 | .probe = wm8900_i2c_probe, |
1318 | .remove = wm8900_i2c_remove, | 1317 | .remove = wm8900_i2c_remove, |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index b5322c1544fb..b011253459af 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -2193,7 +2193,6 @@ MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); | |||
2193 | static struct i2c_driver wm8903_i2c_driver = { | 2193 | static struct i2c_driver wm8903_i2c_driver = { |
2194 | .driver = { | 2194 | .driver = { |
2195 | .name = "wm8903", | 2195 | .name = "wm8903", |
2196 | .owner = THIS_MODULE, | ||
2197 | .of_match_table = wm8903_of_match, | 2196 | .of_match_table = wm8903_of_match, |
2198 | }, | 2197 | }, |
2199 | .probe = wm8903_i2c_probe, | 2198 | .probe = wm8903_i2c_probe, |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 265a4a58a2d1..b783743dc97e 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -1837,7 +1837,9 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec, | |||
1837 | 1837 | ||
1838 | switch (level) { | 1838 | switch (level) { |
1839 | case SND_SOC_BIAS_ON: | 1839 | case SND_SOC_BIAS_ON: |
1840 | clk_prepare_enable(wm8904->mclk); | 1840 | ret = clk_prepare_enable(wm8904->mclk); |
1841 | if (ret) | ||
1842 | return ret; | ||
1841 | break; | 1843 | break; |
1842 | 1844 | ||
1843 | case SND_SOC_BIAS_PREPARE: | 1845 | case SND_SOC_BIAS_PREPARE: |
@@ -2292,7 +2294,6 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); | |||
2292 | static struct i2c_driver wm8904_i2c_driver = { | 2294 | static struct i2c_driver wm8904_i2c_driver = { |
2293 | .driver = { | 2295 | .driver = { |
2294 | .name = "wm8904", | 2296 | .name = "wm8904", |
2295 | .owner = THIS_MODULE, | ||
2296 | .of_match_table = of_match_ptr(wm8904_of_match), | 2297 | .of_match_table = of_match_ptr(wm8904_of_match), |
2297 | }, | 2298 | }, |
2298 | .probe = wm8904_i2c_probe, | 2299 | .probe = wm8904_i2c_probe, |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 98ef0ba5c2a4..f6f9395ea38e 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -787,7 +787,6 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id); | |||
787 | static struct i2c_driver wm8940_i2c_driver = { | 787 | static struct i2c_driver wm8940_i2c_driver = { |
788 | .driver = { | 788 | .driver = { |
789 | .name = "wm8940", | 789 | .name = "wm8940", |
790 | .owner = THIS_MODULE, | ||
791 | }, | 790 | }, |
792 | .probe = wm8940_i2c_probe, | 791 | .probe = wm8940_i2c_probe, |
793 | .remove = wm8940_i2c_remove, | 792 | .remove = wm8940_i2c_remove, |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 2d591c24704b..12e4435f00f8 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -1009,7 +1009,6 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id); | |||
1009 | static struct i2c_driver wm8955_i2c_driver = { | 1009 | static struct i2c_driver wm8955_i2c_driver = { |
1010 | .driver = { | 1010 | .driver = { |
1011 | .name = "wm8955", | 1011 | .name = "wm8955", |
1012 | .owner = THIS_MODULE, | ||
1013 | }, | 1012 | }, |
1014 | .probe = wm8955_i2c_probe, | 1013 | .probe = wm8955_i2c_probe, |
1015 | .remove = wm8955_i2c_remove, | 1014 | .remove = wm8955_i2c_remove, |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 94c5c4681ce5..e3b7d0c57411 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -48,6 +48,9 @@ | |||
48 | #define WM8960_DISOP 0x40 | 48 | #define WM8960_DISOP 0x40 |
49 | #define WM8960_DRES_MASK 0x30 | 49 | #define WM8960_DRES_MASK 0x30 |
50 | 50 | ||
51 | static bool is_pll_freq_available(unsigned int source, unsigned int target); | ||
52 | static int wm8960_set_pll(struct snd_soc_codec *codec, | ||
53 | unsigned int freq_in, unsigned int freq_out); | ||
51 | /* | 54 | /* |
52 | * wm8960 register cache | 55 | * wm8960 register cache |
53 | * We can't read the WM8960 register space when we are | 56 | * We can't read the WM8960 register space when we are |
@@ -126,9 +129,12 @@ struct wm8960_priv { | |||
126 | struct snd_soc_dapm_widget *rout1; | 129 | struct snd_soc_dapm_widget *rout1; |
127 | struct snd_soc_dapm_widget *out3; | 130 | struct snd_soc_dapm_widget *out3; |
128 | bool deemph; | 131 | bool deemph; |
129 | int playback_fs; | 132 | int lrclk; |
130 | int bclk; | 133 | int bclk; |
131 | int sysclk; | 134 | int sysclk; |
135 | int clk_id; | ||
136 | int freq_in; | ||
137 | bool is_stream_in_use[2]; | ||
132 | struct wm8960_data pdata; | 138 | struct wm8960_data pdata; |
133 | }; | 139 | }; |
134 | 140 | ||
@@ -164,8 +170,8 @@ static int wm8960_set_deemph(struct snd_soc_codec *codec) | |||
164 | if (wm8960->deemph) { | 170 | if (wm8960->deemph) { |
165 | best = 1; | 171 | best = 1; |
166 | for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { | 172 | for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { |
167 | if (abs(deemph_settings[i] - wm8960->playback_fs) < | 173 | if (abs(deemph_settings[i] - wm8960->lrclk) < |
168 | abs(deemph_settings[best] - wm8960->playback_fs)) | 174 | abs(deemph_settings[best] - wm8960->lrclk)) |
169 | best = i; | 175 | best = i; |
170 | } | 176 | } |
171 | 177 | ||
@@ -565,6 +571,9 @@ static struct { | |||
565 | { 8000, 5 }, | 571 | { 8000, 5 }, |
566 | }; | 572 | }; |
567 | 573 | ||
574 | /* -1 for reserved value */ | ||
575 | static const int sysclk_divs[] = { 1, -1, 2, -1 }; | ||
576 | |||
568 | /* Multiply 256 for internal 256 div */ | 577 | /* Multiply 256 for internal 256 div */ |
569 | static const int dac_divs[] = { 256, 384, 512, 768, 1024, 1408, 1536 }; | 578 | static const int dac_divs[] = { 256, 384, 512, 768, 1024, 1408, 1536 }; |
570 | 579 | ||
@@ -574,61 +583,110 @@ static const int bclk_divs[] = { | |||
574 | 120, 160, 220, 240, 320, 320, 320 | 583 | 120, 160, 220, 240, 320, 320, 320 |
575 | }; | 584 | }; |
576 | 585 | ||
577 | static void wm8960_configure_clocking(struct snd_soc_codec *codec, | 586 | static int wm8960_configure_clocking(struct snd_soc_codec *codec) |
578 | bool tx, int lrclk) | ||
579 | { | 587 | { |
580 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 588 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
589 | int sysclk, bclk, lrclk, freq_out, freq_in; | ||
581 | u16 iface1 = snd_soc_read(codec, WM8960_IFACE1); | 590 | u16 iface1 = snd_soc_read(codec, WM8960_IFACE1); |
582 | u16 iface2 = snd_soc_read(codec, WM8960_IFACE2); | 591 | int i, j, k; |
583 | u32 sysclk; | ||
584 | int i, j; | ||
585 | 592 | ||
586 | if (!(iface1 & (1<<6))) { | 593 | if (!(iface1 & (1<<6))) { |
587 | dev_dbg(codec->dev, | 594 | dev_dbg(codec->dev, |
588 | "Codec is slave mode, no need to configure clock\n"); | 595 | "Codec is slave mode, no need to configure clock\n"); |
589 | return; | 596 | return 0; |
597 | } | ||
598 | |||
599 | if (wm8960->clk_id != WM8960_SYSCLK_MCLK && !wm8960->freq_in) { | ||
600 | dev_err(codec->dev, "No MCLK configured\n"); | ||
601 | return -EINVAL; | ||
590 | } | 602 | } |
591 | 603 | ||
592 | if (!wm8960->sysclk) { | 604 | freq_in = wm8960->freq_in; |
593 | dev_dbg(codec->dev, "No SYSCLK configured\n"); | 605 | bclk = wm8960->bclk; |
594 | return; | 606 | lrclk = wm8960->lrclk; |
607 | /* | ||
608 | * If it's sysclk auto mode, check if the MCLK can provide sysclk or | ||
609 | * not. If MCLK can provide sysclk, using MCLK to provide sysclk | ||
610 | * directly. Otherwise, auto select a available pll out frequency | ||
611 | * and set PLL. | ||
612 | */ | ||
613 | if (wm8960->clk_id == WM8960_SYSCLK_AUTO) { | ||
614 | /* disable the PLL and using MCLK to provide sysclk */ | ||
615 | wm8960_set_pll(codec, 0, 0); | ||
616 | freq_out = freq_in; | ||
617 | } else if (wm8960->sysclk) { | ||
618 | freq_out = wm8960->sysclk; | ||
619 | } else { | ||
620 | dev_err(codec->dev, "No SYSCLK configured\n"); | ||
621 | return -EINVAL; | ||
595 | } | 622 | } |
596 | 623 | ||
597 | if (!wm8960->bclk || !lrclk) { | 624 | /* check if the sysclk frequency is available. */ |
598 | dev_dbg(codec->dev, "No audio clocks configured\n"); | 625 | for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) { |
599 | return; | 626 | if (sysclk_divs[i] == -1) |
627 | continue; | ||
628 | sysclk = freq_out / sysclk_divs[i]; | ||
629 | for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) { | ||
630 | if (sysclk == dac_divs[j] * lrclk) { | ||
631 | for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) | ||
632 | if (sysclk == bclk * bclk_divs[k] / 10) | ||
633 | break; | ||
634 | if (k != ARRAY_SIZE(bclk_divs)) | ||
635 | break; | ||
636 | } | ||
637 | } | ||
638 | if (j != ARRAY_SIZE(dac_divs)) | ||
639 | break; | ||
600 | } | 640 | } |
601 | 641 | ||
602 | for (i = 0; i < ARRAY_SIZE(dac_divs); ++i) { | 642 | if (i != ARRAY_SIZE(sysclk_divs)) { |
603 | if (wm8960->sysclk == lrclk * dac_divs[i]) { | 643 | goto configure_clock; |
604 | for (j = 0; j < ARRAY_SIZE(bclk_divs); ++j) { | 644 | } else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) { |
605 | sysclk = wm8960->bclk * bclk_divs[j] / 10; | 645 | dev_err(codec->dev, "failed to configure clock\n"); |
606 | if (wm8960->sysclk == sysclk) | 646 | return -EINVAL; |
647 | } | ||
648 | /* get a available pll out frequency and set pll */ | ||
649 | for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) { | ||
650 | if (sysclk_divs[i] == -1) | ||
651 | continue; | ||
652 | for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) { | ||
653 | sysclk = lrclk * dac_divs[j]; | ||
654 | freq_out = sysclk * sysclk_divs[i]; | ||
655 | |||
656 | for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) { | ||
657 | if (sysclk == bclk * bclk_divs[k] / 10 && | ||
658 | is_pll_freq_available(freq_in, freq_out)) { | ||
659 | wm8960_set_pll(codec, | ||
660 | freq_in, freq_out); | ||
607 | break; | 661 | break; |
662 | } else { | ||
663 | continue; | ||
664 | } | ||
608 | } | 665 | } |
609 | if(j != ARRAY_SIZE(bclk_divs)) | 666 | if (k != ARRAY_SIZE(bclk_divs)) |
610 | break; | 667 | break; |
611 | } | 668 | } |
669 | if (j != ARRAY_SIZE(dac_divs)) | ||
670 | break; | ||
612 | } | 671 | } |
613 | 672 | ||
614 | if (i == ARRAY_SIZE(dac_divs)) { | 673 | if (i == ARRAY_SIZE(sysclk_divs)) { |
615 | dev_err(codec->dev, "Unsupported sysclk %d\n", wm8960->sysclk); | 674 | dev_err(codec->dev, "failed to configure clock\n"); |
616 | return; | 675 | return -EINVAL; |
617 | } | 676 | } |
618 | 677 | ||
619 | /* | 678 | configure_clock: |
620 | * configure frame clock. If ADCLRC configure as GPIO pin, DACLRC | 679 | /* configure sysclk clock */ |
621 | * pin is used as a frame clock for ADCs and DACs. | 680 | snd_soc_update_bits(codec, WM8960_CLOCK1, 3 << 1, i << 1); |
622 | */ | 681 | |
623 | if (iface2 & (1<<6)) | 682 | /* configure frame clock */ |
624 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3); | 683 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, j << 3); |
625 | else if (tx) | 684 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 6, j << 6); |
626 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3); | ||
627 | else if (!tx) | ||
628 | snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 6, i << 6); | ||
629 | 685 | ||
630 | /* configure bit clock */ | 686 | /* configure bit clock */ |
631 | snd_soc_update_bits(codec, WM8960_CLOCK2, 0xf, j); | 687 | snd_soc_update_bits(codec, WM8960_CLOCK2, 0xf, k); |
688 | |||
689 | return 0; | ||
632 | } | 690 | } |
633 | 691 | ||
634 | static int wm8960_hw_params(struct snd_pcm_substream *substream, | 692 | static int wm8960_hw_params(struct snd_pcm_substream *substream, |
@@ -667,9 +725,9 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
667 | return -EINVAL; | 725 | return -EINVAL; |
668 | } | 726 | } |
669 | 727 | ||
728 | wm8960->lrclk = params_rate(params); | ||
670 | /* Update filters for the new rate */ | 729 | /* Update filters for the new rate */ |
671 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 730 | if (tx) { |
672 | wm8960->playback_fs = params_rate(params); | ||
673 | wm8960_set_deemph(codec); | 731 | wm8960_set_deemph(codec); |
674 | } else { | 732 | } else { |
675 | for (i = 0; i < ARRAY_SIZE(alc_rates); i++) | 733 | for (i = 0; i < ARRAY_SIZE(alc_rates); i++) |
@@ -682,7 +740,23 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
682 | /* set iface */ | 740 | /* set iface */ |
683 | snd_soc_write(codec, WM8960_IFACE1, iface); | 741 | snd_soc_write(codec, WM8960_IFACE1, iface); |
684 | 742 | ||
685 | wm8960_configure_clocking(codec, tx, params_rate(params)); | 743 | wm8960->is_stream_in_use[tx] = true; |
744 | |||
745 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON && | ||
746 | !wm8960->is_stream_in_use[!tx]) | ||
747 | return wm8960_configure_clocking(codec); | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | static int wm8960_hw_free(struct snd_pcm_substream *substream, | ||
753 | struct snd_soc_dai *dai) | ||
754 | { | ||
755 | struct snd_soc_codec *codec = dai->codec; | ||
756 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
757 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
758 | |||
759 | wm8960->is_stream_in_use[tx] = false; | ||
686 | 760 | ||
687 | return 0; | 761 | return 0; |
688 | } | 762 | } |
@@ -702,6 +776,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
702 | enum snd_soc_bias_level level) | 776 | enum snd_soc_bias_level level) |
703 | { | 777 | { |
704 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 778 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
779 | u16 pm2 = snd_soc_read(codec, WM8960_POWER2); | ||
705 | int ret; | 780 | int ret; |
706 | 781 | ||
707 | switch (level) { | 782 | switch (level) { |
@@ -721,11 +796,22 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
721 | } | 796 | } |
722 | } | 797 | } |
723 | 798 | ||
799 | ret = wm8960_configure_clocking(codec); | ||
800 | if (ret) | ||
801 | return ret; | ||
802 | |||
724 | /* Set VMID to 2x50k */ | 803 | /* Set VMID to 2x50k */ |
725 | snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80); | 804 | snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80); |
726 | break; | 805 | break; |
727 | 806 | ||
728 | case SND_SOC_BIAS_ON: | 807 | case SND_SOC_BIAS_ON: |
808 | /* | ||
809 | * If it's sysclk auto mode, and the pll is enabled, | ||
810 | * disable the pll | ||
811 | */ | ||
812 | if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1)) | ||
813 | wm8960_set_pll(codec, 0, 0); | ||
814 | |||
729 | if (!IS_ERR(wm8960->mclk)) | 815 | if (!IS_ERR(wm8960->mclk)) |
730 | clk_disable_unprepare(wm8960->mclk); | 816 | clk_disable_unprepare(wm8960->mclk); |
731 | break; | 817 | break; |
@@ -780,6 +866,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
780 | enum snd_soc_bias_level level) | 866 | enum snd_soc_bias_level level) |
781 | { | 867 | { |
782 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 868 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
869 | u16 pm2 = snd_soc_read(codec, WM8960_POWER2); | ||
783 | int reg, ret; | 870 | int reg, ret; |
784 | 871 | ||
785 | switch (level) { | 872 | switch (level) { |
@@ -831,9 +918,21 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
831 | return ret; | 918 | return ret; |
832 | } | 919 | } |
833 | } | 920 | } |
921 | |||
922 | ret = wm8960_configure_clocking(codec); | ||
923 | if (ret) | ||
924 | return ret; | ||
925 | |||
834 | break; | 926 | break; |
835 | 927 | ||
836 | case SND_SOC_BIAS_ON: | 928 | case SND_SOC_BIAS_ON: |
929 | /* | ||
930 | * If it's sysclk auto mode, and the pll is enabled, | ||
931 | * disable the pll | ||
932 | */ | ||
933 | if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1)) | ||
934 | wm8960_set_pll(codec, 0, 0); | ||
935 | |||
837 | if (!IS_ERR(wm8960->mclk)) | 936 | if (!IS_ERR(wm8960->mclk)) |
838 | clk_disable_unprepare(wm8960->mclk); | 937 | clk_disable_unprepare(wm8960->mclk); |
839 | 938 | ||
@@ -892,6 +991,28 @@ struct _pll_div { | |||
892 | u32 k:24; | 991 | u32 k:24; |
893 | }; | 992 | }; |
894 | 993 | ||
994 | static bool is_pll_freq_available(unsigned int source, unsigned int target) | ||
995 | { | ||
996 | unsigned int Ndiv; | ||
997 | |||
998 | if (source == 0 || target == 0) | ||
999 | return false; | ||
1000 | |||
1001 | /* Scale up target to PLL operating frequency */ | ||
1002 | target *= 4; | ||
1003 | Ndiv = target / source; | ||
1004 | |||
1005 | if (Ndiv < 6) { | ||
1006 | source >>= 1; | ||
1007 | Ndiv = target / source; | ||
1008 | } | ||
1009 | |||
1010 | if ((Ndiv < 6) || (Ndiv > 12)) | ||
1011 | return false; | ||
1012 | |||
1013 | return true; | ||
1014 | } | ||
1015 | |||
895 | /* The size in bits of the pll divide multiplied by 10 | 1016 | /* The size in bits of the pll divide multiplied by 10 |
896 | * to allow rounding later */ | 1017 | * to allow rounding later */ |
897 | #define FIXED_PLL_SIZE ((1 << 24) * 10) | 1018 | #define FIXED_PLL_SIZE ((1 << 24) * 10) |
@@ -943,10 +1064,9 @@ static int pll_factors(unsigned int source, unsigned int target, | |||
943 | return 0; | 1064 | return 0; |
944 | } | 1065 | } |
945 | 1066 | ||
946 | static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | 1067 | static int wm8960_set_pll(struct snd_soc_codec *codec, |
947 | int source, unsigned int freq_in, unsigned int freq_out) | 1068 | unsigned int freq_in, unsigned int freq_out) |
948 | { | 1069 | { |
949 | struct snd_soc_codec *codec = codec_dai->codec; | ||
950 | u16 reg; | 1070 | u16 reg; |
951 | static struct _pll_div pll_div; | 1071 | static struct _pll_div pll_div; |
952 | int ret; | 1072 | int ret; |
@@ -986,6 +1106,20 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | |||
986 | return 0; | 1106 | return 0; |
987 | } | 1107 | } |
988 | 1108 | ||
1109 | static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | ||
1110 | int source, unsigned int freq_in, unsigned int freq_out) | ||
1111 | { | ||
1112 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1113 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
1114 | |||
1115 | wm8960->freq_in = freq_in; | ||
1116 | |||
1117 | if (pll_id == WM8960_SYSCLK_AUTO) | ||
1118 | return 0; | ||
1119 | |||
1120 | return wm8960_set_pll(codec, freq_in, freq_out); | ||
1121 | } | ||
1122 | |||
989 | static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | 1123 | static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, |
990 | int div_id, int div) | 1124 | int div_id, int div) |
991 | { | 1125 | { |
@@ -1043,11 +1177,14 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
1043 | snd_soc_update_bits(codec, WM8960_CLOCK1, | 1177 | snd_soc_update_bits(codec, WM8960_CLOCK1, |
1044 | 0x1, WM8960_SYSCLK_PLL); | 1178 | 0x1, WM8960_SYSCLK_PLL); |
1045 | break; | 1179 | break; |
1180 | case WM8960_SYSCLK_AUTO: | ||
1181 | break; | ||
1046 | default: | 1182 | default: |
1047 | return -EINVAL; | 1183 | return -EINVAL; |
1048 | } | 1184 | } |
1049 | 1185 | ||
1050 | wm8960->sysclk = freq; | 1186 | wm8960->sysclk = freq; |
1187 | wm8960->clk_id = clk_id; | ||
1051 | 1188 | ||
1052 | return 0; | 1189 | return 0; |
1053 | } | 1190 | } |
@@ -1060,6 +1197,7 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
1060 | 1197 | ||
1061 | static const struct snd_soc_dai_ops wm8960_dai_ops = { | 1198 | static const struct snd_soc_dai_ops wm8960_dai_ops = { |
1062 | .hw_params = wm8960_hw_params, | 1199 | .hw_params = wm8960_hw_params, |
1200 | .hw_free = wm8960_hw_free, | ||
1063 | .digital_mute = wm8960_mute, | 1201 | .digital_mute = wm8960_mute, |
1064 | .set_fmt = wm8960_set_dai_fmt, | 1202 | .set_fmt = wm8960_set_dai_fmt, |
1065 | .set_clkdiv = wm8960_set_dai_clkdiv, | 1203 | .set_clkdiv = wm8960_set_dai_clkdiv, |
@@ -1216,7 +1354,6 @@ MODULE_DEVICE_TABLE(of, wm8960_of_match); | |||
1216 | static struct i2c_driver wm8960_i2c_driver = { | 1354 | static struct i2c_driver wm8960_i2c_driver = { |
1217 | .driver = { | 1355 | .driver = { |
1218 | .name = "wm8960", | 1356 | .name = "wm8960", |
1219 | .owner = THIS_MODULE, | ||
1220 | .of_match_table = wm8960_of_match, | 1357 | .of_match_table = wm8960_of_match, |
1221 | }, | 1358 | }, |
1222 | .probe = wm8960_i2c_probe, | 1359 | .probe = wm8960_i2c_probe, |
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h index 2d8163d7004b..ab3220d3411d 100644 --- a/sound/soc/codecs/wm8960.h +++ b/sound/soc/codecs/wm8960.h | |||
@@ -82,6 +82,7 @@ | |||
82 | 82 | ||
83 | #define WM8960_SYSCLK_MCLK (0 << 0) | 83 | #define WM8960_SYSCLK_MCLK (0 << 0) |
84 | #define WM8960_SYSCLK_PLL (1 << 0) | 84 | #define WM8960_SYSCLK_PLL (1 << 0) |
85 | #define WM8960_SYSCLK_AUTO (2 << 0) | ||
85 | 86 | ||
86 | #define WM8960_DAC_DIV_1 (0 << 3) | 87 | #define WM8960_DAC_DIV_1 (0 << 3) |
87 | #define WM8960_DAC_DIV_1_5 (1 << 3) | 88 | #define WM8960_DAC_DIV_1_5 (1 << 3) |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index a057662632ff..e30446a04740 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -331,13 +331,12 @@ static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); | |||
331 | static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); | 331 | static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); |
332 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1); | 332 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1); |
333 | static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); | 333 | static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); |
334 | static unsigned int boost_tlv[] = { | 334 | static const DECLARE_TLV_DB_RANGE(boost_tlv, |
335 | TLV_DB_RANGE_HEAD(4), | ||
336 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | 335 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), |
337 | 1, 1, TLV_DB_SCALE_ITEM(13, 0, 0), | 336 | 1, 1, TLV_DB_SCALE_ITEM(13, 0, 0), |
338 | 2, 2, TLV_DB_SCALE_ITEM(20, 0, 0), | 337 | 2, 2, TLV_DB_SCALE_ITEM(20, 0, 0), |
339 | 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0), | 338 | 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0) |
340 | }; | 339 | ); |
341 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0); | 340 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0); |
342 | 341 | ||
343 | static const struct snd_kcontrol_new wm8961_snd_controls[] = { | 342 | static const struct snd_kcontrol_new wm8961_snd_controls[] = { |
@@ -982,7 +981,6 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id); | |||
982 | static struct i2c_driver wm8961_i2c_driver = { | 981 | static struct i2c_driver wm8961_i2c_driver = { |
983 | .driver = { | 982 | .driver = { |
984 | .name = "wm8961", | 983 | .name = "wm8961", |
985 | .owner = THIS_MODULE, | ||
986 | }, | 984 | }, |
987 | .probe = wm8961_i2c_probe, | 985 | .probe = wm8961_i2c_probe, |
988 | .remove = wm8961_i2c_remove, | 986 | .remove = wm8961_i2c_remove, |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index c5748fd4f296..b4eb975da981 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -113,7 +113,7 @@ WM8962_REGULATOR_EVENT(5) | |||
113 | WM8962_REGULATOR_EVENT(6) | 113 | WM8962_REGULATOR_EVENT(6) |
114 | WM8962_REGULATOR_EVENT(7) | 114 | WM8962_REGULATOR_EVENT(7) |
115 | 115 | ||
116 | static struct reg_default wm8962_reg[] = { | 116 | static const struct reg_default wm8962_reg[] = { |
117 | { 0, 0x009F }, /* R0 - Left Input volume */ | 117 | { 0, 0x009F }, /* R0 - Left Input volume */ |
118 | { 1, 0x049F }, /* R1 - Right Input volume */ | 118 | { 1, 0x049F }, /* R1 - Right Input volume */ |
119 | { 2, 0x0000 }, /* R2 - HPOUTL volume */ | 119 | { 2, 0x0000 }, /* R2 - HPOUTL volume */ |
@@ -1456,14 +1456,13 @@ static int wm8962_reset(struct wm8962_priv *wm8962) | |||
1456 | 1456 | ||
1457 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0); | 1457 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0); |
1458 | static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0); | 1458 | static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0); |
1459 | static const unsigned int mixinpga_tlv[] = { | 1459 | static const DECLARE_TLV_DB_RANGE(mixinpga_tlv, |
1460 | TLV_DB_RANGE_HEAD(5), | ||
1461 | 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0), | 1460 | 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0), |
1462 | 2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0), | 1461 | 2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0), |
1463 | 3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0), | 1462 | 3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0), |
1464 | 5, 5, TLV_DB_SCALE_ITEM(2400, 0, 0), | 1463 | 5, 5, TLV_DB_SCALE_ITEM(2400, 0, 0), |
1465 | 6, 7, TLV_DB_SCALE_ITEM(2700, 300, 0), | 1464 | 6, 7, TLV_DB_SCALE_ITEM(2700, 300, 0) |
1466 | }; | 1465 | ); |
1467 | static const DECLARE_TLV_DB_SCALE(beep_tlv, -9600, 600, 1); | 1466 | static const DECLARE_TLV_DB_SCALE(beep_tlv, -9600, 600, 1); |
1468 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | 1467 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); |
1469 | static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); | 1468 | static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); |
@@ -1471,11 +1470,10 @@ static const DECLARE_TLV_DB_SCALE(inmix_tlv, -600, 600, 0); | |||
1471 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); | 1470 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); |
1472 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); | 1471 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); |
1473 | static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0); | 1472 | static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0); |
1474 | static const unsigned int classd_tlv[] = { | 1473 | static const DECLARE_TLV_DB_RANGE(classd_tlv, |
1475 | TLV_DB_RANGE_HEAD(2), | ||
1476 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), | 1474 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), |
1477 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), | 1475 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0) |
1478 | }; | 1476 | ); |
1479 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 1477 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
1480 | 1478 | ||
1481 | static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) | 1479 | static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) |
@@ -3495,7 +3493,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8962 = { | |||
3495 | }; | 3493 | }; |
3496 | 3494 | ||
3497 | /* Improve power consumption for IN4 DC measurement mode */ | 3495 | /* Improve power consumption for IN4 DC measurement mode */ |
3498 | static const struct reg_default wm8962_dc_measure[] = { | 3496 | static const struct reg_sequence wm8962_dc_measure[] = { |
3499 | { 0xfd, 0x1 }, | 3497 | { 0xfd, 0x1 }, |
3500 | { 0xcc, 0x40 }, | 3498 | { 0xcc, 0x40 }, |
3501 | { 0xfd, 0 }, | 3499 | { 0xfd, 0 }, |
@@ -3859,7 +3857,7 @@ static int wm8962_runtime_suspend(struct device *dev) | |||
3859 | } | 3857 | } |
3860 | #endif | 3858 | #endif |
3861 | 3859 | ||
3862 | static struct dev_pm_ops wm8962_pm = { | 3860 | static const struct dev_pm_ops wm8962_pm = { |
3863 | SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL) | 3861 | SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL) |
3864 | }; | 3862 | }; |
3865 | 3863 | ||
@@ -3878,7 +3876,6 @@ MODULE_DEVICE_TABLE(of, wm8962_of_match); | |||
3878 | static struct i2c_driver wm8962_i2c_driver = { | 3876 | static struct i2c_driver wm8962_i2c_driver = { |
3879 | .driver = { | 3877 | .driver = { |
3880 | .name = "wm8962", | 3878 | .name = "wm8962", |
3881 | .owner = THIS_MODULE, | ||
3882 | .of_match_table = wm8962_of_match, | 3879 | .of_match_table = wm8962_of_match, |
3883 | .pm = &wm8962_pm, | 3880 | .pm = &wm8962_pm, |
3884 | }, | 3881 | }, |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index b51184c4e816..2cdde32c43c6 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -710,7 +710,6 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id); | |||
710 | static struct i2c_driver wm8971_i2c_driver = { | 710 | static struct i2c_driver wm8971_i2c_driver = { |
711 | .driver = { | 711 | .driver = { |
712 | .name = "wm8971", | 712 | .name = "wm8971", |
713 | .owner = THIS_MODULE, | ||
714 | }, | 713 | }, |
715 | .probe = wm8971_i2c_probe, | 714 | .probe = wm8971_i2c_probe, |
716 | .remove = wm8971_i2c_remove, | 715 | .remove = wm8971_i2c_remove, |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 33b16a7ba82e..0a60677397b3 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -634,7 +634,6 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id); | |||
634 | static struct i2c_driver wm8974_i2c_driver = { | 634 | static struct i2c_driver wm8974_i2c_driver = { |
635 | .driver = { | 635 | .driver = { |
636 | .name = "wm8974", | 636 | .name = "wm8974", |
637 | .owner = THIS_MODULE, | ||
638 | }, | 637 | }, |
639 | .probe = wm8974_i2c_probe, | 638 | .probe = wm8974_i2c_probe, |
640 | .remove = wm8974_i2c_remove, | 639 | .remove = wm8974_i2c_remove, |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index cfc8cdf49970..d36d6001fbb7 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -1072,7 +1072,6 @@ MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id); | |||
1072 | static struct i2c_driver wm8978_i2c_driver = { | 1072 | static struct i2c_driver wm8978_i2c_driver = { |
1073 | .driver = { | 1073 | .driver = { |
1074 | .name = "wm8978", | 1074 | .name = "wm8978", |
1075 | .owner = THIS_MODULE, | ||
1076 | }, | 1075 | }, |
1077 | .probe = wm8978_i2c_probe, | 1076 | .probe = wm8978_i2c_probe, |
1078 | .remove = wm8978_i2c_remove, | 1077 | .remove = wm8978_i2c_remove, |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 2fdd2c6cc09d..f3193fb751cc 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c | |||
@@ -84,66 +84,6 @@ static const struct reg_default wm8983_defaults[] = { | |||
84 | { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */ | 84 | { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */ |
85 | }; | 85 | }; |
86 | 86 | ||
87 | static const struct wm8983_reg_access { | ||
88 | u16 read; /* Mask of readable bits */ | ||
89 | u16 write; /* Mask of writable bits */ | ||
90 | } wm8983_access_masks[WM8983_MAX_REGISTER + 1] = { | ||
91 | [0x00] = { 0x0000, 0x01FF }, /* R0 - Software Reset */ | ||
92 | [0x01] = { 0x0000, 0x01FF }, /* R1 - Power management 1 */ | ||
93 | [0x02] = { 0x0000, 0x01FF }, /* R2 - Power management 2 */ | ||
94 | [0x03] = { 0x0000, 0x01EF }, /* R3 - Power management 3 */ | ||
95 | [0x04] = { 0x0000, 0x01FF }, /* R4 - Audio Interface */ | ||
96 | [0x05] = { 0x0000, 0x003F }, /* R5 - Companding control */ | ||
97 | [0x06] = { 0x0000, 0x01FD }, /* R6 - Clock Gen control */ | ||
98 | [0x07] = { 0x0000, 0x000F }, /* R7 - Additional control */ | ||
99 | [0x08] = { 0x0000, 0x003F }, /* R8 - GPIO Control */ | ||
100 | [0x09] = { 0x0000, 0x0070 }, /* R9 - Jack Detect Control 1 */ | ||
101 | [0x0A] = { 0x0000, 0x004F }, /* R10 - DAC Control */ | ||
102 | [0x0B] = { 0x0000, 0x01FF }, /* R11 - Left DAC digital Vol */ | ||
103 | [0x0C] = { 0x0000, 0x01FF }, /* R12 - Right DAC digital vol */ | ||
104 | [0x0D] = { 0x0000, 0x00FF }, /* R13 - Jack Detect Control 2 */ | ||
105 | [0x0E] = { 0x0000, 0x01FB }, /* R14 - ADC Control */ | ||
106 | [0x0F] = { 0x0000, 0x01FF }, /* R15 - Left ADC Digital Vol */ | ||
107 | [0x10] = { 0x0000, 0x01FF }, /* R16 - Right ADC Digital Vol */ | ||
108 | [0x12] = { 0x0000, 0x017F }, /* R18 - EQ1 - low shelf */ | ||
109 | [0x13] = { 0x0000, 0x017F }, /* R19 - EQ2 - peak 1 */ | ||
110 | [0x14] = { 0x0000, 0x017F }, /* R20 - EQ3 - peak 2 */ | ||
111 | [0x15] = { 0x0000, 0x017F }, /* R21 - EQ4 - peak 3 */ | ||
112 | [0x16] = { 0x0000, 0x007F }, /* R22 - EQ5 - high shelf */ | ||
113 | [0x18] = { 0x0000, 0x01FF }, /* R24 - DAC Limiter 1 */ | ||
114 | [0x19] = { 0x0000, 0x007F }, /* R25 - DAC Limiter 2 */ | ||
115 | [0x1B] = { 0x0000, 0x01FF }, /* R27 - Notch Filter 1 */ | ||
116 | [0x1C] = { 0x0000, 0x017F }, /* R28 - Notch Filter 2 */ | ||
117 | [0x1D] = { 0x0000, 0x017F }, /* R29 - Notch Filter 3 */ | ||
118 | [0x1E] = { 0x0000, 0x017F }, /* R30 - Notch Filter 4 */ | ||
119 | [0x20] = { 0x0000, 0x01BF }, /* R32 - ALC control 1 */ | ||
120 | [0x21] = { 0x0000, 0x00FF }, /* R33 - ALC control 2 */ | ||
121 | [0x22] = { 0x0000, 0x01FF }, /* R34 - ALC control 3 */ | ||
122 | [0x23] = { 0x0000, 0x000F }, /* R35 - Noise Gate */ | ||
123 | [0x24] = { 0x0000, 0x001F }, /* R36 - PLL N */ | ||
124 | [0x25] = { 0x0000, 0x003F }, /* R37 - PLL K 1 */ | ||
125 | [0x26] = { 0x0000, 0x01FF }, /* R38 - PLL K 2 */ | ||
126 | [0x27] = { 0x0000, 0x01FF }, /* R39 - PLL K 3 */ | ||
127 | [0x29] = { 0x0000, 0x000F }, /* R41 - 3D control */ | ||
128 | [0x2A] = { 0x0000, 0x01E7 }, /* R42 - OUT4 to ADC */ | ||
129 | [0x2B] = { 0x0000, 0x01BF }, /* R43 - Beep control */ | ||
130 | [0x2C] = { 0x0000, 0x0177 }, /* R44 - Input ctrl */ | ||
131 | [0x2D] = { 0x0000, 0x01FF }, /* R45 - Left INP PGA gain ctrl */ | ||
132 | [0x2E] = { 0x0000, 0x01FF }, /* R46 - Right INP PGA gain ctrl */ | ||
133 | [0x2F] = { 0x0000, 0x0177 }, /* R47 - Left ADC BOOST ctrl */ | ||
134 | [0x30] = { 0x0000, 0x0177 }, /* R48 - Right ADC BOOST ctrl */ | ||
135 | [0x31] = { 0x0000, 0x007F }, /* R49 - Output ctrl */ | ||
136 | [0x32] = { 0x0000, 0x01FF }, /* R50 - Left mixer ctrl */ | ||
137 | [0x33] = { 0x0000, 0x01FF }, /* R51 - Right mixer ctrl */ | ||
138 | [0x34] = { 0x0000, 0x01FF }, /* R52 - LOUT1 (HP) volume ctrl */ | ||
139 | [0x35] = { 0x0000, 0x01FF }, /* R53 - ROUT1 (HP) volume ctrl */ | ||
140 | [0x36] = { 0x0000, 0x01FF }, /* R54 - LOUT2 (SPK) volume ctrl */ | ||
141 | [0x37] = { 0x0000, 0x01FF }, /* R55 - ROUT2 (SPK) volume ctrl */ | ||
142 | [0x38] = { 0x0000, 0x004F }, /* R56 - OUT3 mixer ctrl */ | ||
143 | [0x39] = { 0x0000, 0x00FF }, /* R57 - OUT4 (MONO) mix ctrl */ | ||
144 | [0x3D] = { 0x0000, 0x0100 } /* R61 - BIAS CTRL */ | ||
145 | }; | ||
146 | |||
147 | /* vol/gain update regs */ | 87 | /* vol/gain update regs */ |
148 | static const int vol_update_regs[] = { | 88 | static const int vol_update_regs[] = { |
149 | WM8983_LEFT_DAC_DIGITAL_VOL, | 89 | WM8983_LEFT_DAC_DIGITAL_VOL, |
@@ -605,12 +545,19 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, | |||
605 | return 0; | 545 | return 0; |
606 | } | 546 | } |
607 | 547 | ||
608 | static bool wm8983_readable(struct device *dev, unsigned int reg) | 548 | static bool wm8983_writeable(struct device *dev, unsigned int reg) |
609 | { | 549 | { |
610 | if (reg > WM8983_MAX_REGISTER) | 550 | switch (reg) { |
611 | return 0; | 551 | case WM8983_SOFTWARE_RESET ... WM8983_RIGHT_ADC_DIGITAL_VOL: |
612 | 552 | case WM8983_EQ1_LOW_SHELF ... WM8983_DAC_LIMITER_2: | |
613 | return wm8983_access_masks[reg].read != 0; | 553 | case WM8983_NOTCH_FILTER_1 ... WM8983_NOTCH_FILTER_4: |
554 | case WM8983_ALC_CONTROL_1 ... WM8983_PLL_K_3: | ||
555 | case WM8983_3D_CONTROL ... WM8983_OUT4_MONO_MIX_CTRL: | ||
556 | case WM8983_BIAS_CTRL: | ||
557 | return true; | ||
558 | default: | ||
559 | return false; | ||
560 | } | ||
614 | } | 561 | } |
615 | 562 | ||
616 | static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute) | 563 | static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute) |
@@ -1048,8 +995,9 @@ static const struct regmap_config wm8983_regmap = { | |||
1048 | .reg_defaults = wm8983_defaults, | 995 | .reg_defaults = wm8983_defaults, |
1049 | .num_reg_defaults = ARRAY_SIZE(wm8983_defaults), | 996 | .num_reg_defaults = ARRAY_SIZE(wm8983_defaults), |
1050 | .cache_type = REGCACHE_RBTREE, | 997 | .cache_type = REGCACHE_RBTREE, |
998 | .max_register = WM8983_MAX_REGISTER, | ||
1051 | 999 | ||
1052 | .readable_reg = wm8983_readable, | 1000 | .writeable_reg = wm8983_writeable, |
1053 | }; | 1001 | }; |
1054 | 1002 | ||
1055 | #if defined(CONFIG_SPI_MASTER) | 1003 | #if defined(CONFIG_SPI_MASTER) |
@@ -1133,7 +1081,6 @@ MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id); | |||
1133 | static struct i2c_driver wm8983_i2c_driver = { | 1081 | static struct i2c_driver wm8983_i2c_driver = { |
1134 | .driver = { | 1082 | .driver = { |
1135 | .name = "wm8983", | 1083 | .name = "wm8983", |
1136 | .owner = THIS_MODULE, | ||
1137 | }, | 1084 | }, |
1138 | .probe = wm8983_i2c_probe, | 1085 | .probe = wm8983_i2c_probe, |
1139 | .remove = wm8983_i2c_remove, | 1086 | .remove = wm8983_i2c_remove, |
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 8a85f5004d41..9c3c1517a4f3 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c | |||
@@ -1144,7 +1144,6 @@ MODULE_DEVICE_TABLE(i2c, wm8985_i2c_id); | |||
1144 | static struct i2c_driver wm8985_i2c_driver = { | 1144 | static struct i2c_driver wm8985_i2c_driver = { |
1145 | .driver = { | 1145 | .driver = { |
1146 | .name = "wm8985", | 1146 | .name = "wm8985", |
1147 | .owner = THIS_MODULE, | ||
1148 | }, | 1147 | }, |
1149 | .probe = wm8985_i2c_probe, | 1148 | .probe = wm8985_i2c_probe, |
1150 | .remove = wm8985_i2c_remove, | 1149 | .remove = wm8985_i2c_remove, |
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index f13a995af277..c88ce99ce9e1 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -919,7 +919,6 @@ MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); | |||
919 | static struct i2c_driver wm8988_i2c_driver = { | 919 | static struct i2c_driver wm8988_i2c_driver = { |
920 | .driver = { | 920 | .driver = { |
921 | .name = "wm8988", | 921 | .name = "wm8988", |
922 | .owner = THIS_MODULE, | ||
923 | }, | 922 | }, |
924 | .probe = wm8988_i2c_probe, | 923 | .probe = wm8988_i2c_probe, |
925 | .remove = wm8988_i2c_remove, | 924 | .remove = wm8988_i2c_remove, |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 1993fd2a6f15..23ecd30d8bca 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -418,10 +418,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, | |||
418 | } | 418 | } |
419 | 419 | ||
420 | /* INMIX dB values */ | 420 | /* INMIX dB values */ |
421 | static const unsigned int in_mix_tlv[] = { | 421 | static const DECLARE_TLV_DB_SCALE(in_mix_tlv, -1200, 600, 0); |
422 | TLV_DB_RANGE_HEAD(1), | ||
423 | 0, 7, TLV_DB_SCALE_ITEM(-1200, 600, 0), | ||
424 | }; | ||
425 | 422 | ||
426 | /* Left In PGA Connections */ | 423 | /* Left In PGA Connections */ |
427 | static const struct snd_kcontrol_new wm8990_dapm_lin12_pga_controls[] = { | 424 | static const struct snd_kcontrol_new wm8990_dapm_lin12_pga_controls[] = { |
@@ -1356,7 +1353,6 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id); | |||
1356 | static struct i2c_driver wm8990_i2c_driver = { | 1353 | static struct i2c_driver wm8990_i2c_driver = { |
1357 | .driver = { | 1354 | .driver = { |
1358 | .name = "wm8990", | 1355 | .name = "wm8990", |
1359 | .owner = THIS_MODULE, | ||
1360 | }, | 1356 | }, |
1361 | .probe = wm8990_i2c_probe, | 1357 | .probe = wm8990_i2c_probe, |
1362 | .remove = wm8990_i2c_remove, | 1358 | .remove = wm8990_i2c_remove, |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 44a677720828..c9ee0ac6a654 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -111,45 +111,14 @@ static bool wm8991_volatile(struct device *dev, unsigned int reg) | |||
111 | } | 111 | } |
112 | } | 112 | } |
113 | 113 | ||
114 | static const unsigned int rec_mix_tlv[] = { | 114 | static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); |
115 | TLV_DB_RANGE_HEAD(1), | 115 | static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000); |
116 | 0, 7, TLV_DB_LINEAR_ITEM(-1500, 600), | 116 | static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100); |
117 | }; | 117 | static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600); |
118 | 118 | static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); | |
119 | static const unsigned int in_pga_tlv[] = { | 119 | static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0); |
120 | TLV_DB_RANGE_HEAD(1), | 120 | static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763); |
121 | 0, 0x1F, TLV_DB_LINEAR_ITEM(-1650, 3000), | 121 | static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0); |
122 | }; | ||
123 | |||
124 | static const unsigned int out_mix_tlv[] = { | ||
125 | TLV_DB_RANGE_HEAD(1), | ||
126 | 0, 7, TLV_DB_LINEAR_ITEM(0, -2100), | ||
127 | }; | ||
128 | |||
129 | static const unsigned int out_pga_tlv[] = { | ||
130 | TLV_DB_RANGE_HEAD(1), | ||
131 | 0, 127, TLV_DB_LINEAR_ITEM(-7300, 600), | ||
132 | }; | ||
133 | |||
134 | static const unsigned int out_omix_tlv[] = { | ||
135 | TLV_DB_RANGE_HEAD(1), | ||
136 | 0, 7, TLV_DB_LINEAR_ITEM(-600, 0), | ||
137 | }; | ||
138 | |||
139 | static const unsigned int out_dac_tlv[] = { | ||
140 | TLV_DB_RANGE_HEAD(1), | ||
141 | 0, 255, TLV_DB_LINEAR_ITEM(-7163, 0), | ||
142 | }; | ||
143 | |||
144 | static const unsigned int in_adc_tlv[] = { | ||
145 | TLV_DB_RANGE_HEAD(1), | ||
146 | 0, 255, TLV_DB_LINEAR_ITEM(-7163, 1763), | ||
147 | }; | ||
148 | |||
149 | static const unsigned int out_sidetone_tlv[] = { | ||
150 | TLV_DB_RANGE_HEAD(1), | ||
151 | 0, 31, TLV_DB_LINEAR_ITEM(-3600, 0), | ||
152 | }; | ||
153 | 122 | ||
154 | static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | 123 | static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, |
155 | struct snd_ctl_elem_value *ucontrol) | 124 | struct snd_ctl_elem_value *ucontrol) |
@@ -429,10 +398,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, | |||
429 | } | 398 | } |
430 | 399 | ||
431 | /* INMIX dB values */ | 400 | /* INMIX dB values */ |
432 | static const unsigned int in_mix_tlv[] = { | 401 | static const DECLARE_TLV_DB_LINEAR(in_mix_tlv, -1200, 600); |
433 | TLV_DB_RANGE_HEAD(1), | ||
434 | 0, 7, TLV_DB_LINEAR_ITEM(-1200, 600), | ||
435 | }; | ||
436 | 402 | ||
437 | /* Left In PGA Connections */ | 403 | /* Left In PGA Connections */ |
438 | static const struct snd_kcontrol_new wm8991_dapm_lin12_pga_controls[] = { | 404 | static const struct snd_kcontrol_new wm8991_dapm_lin12_pga_controls[] = { |
@@ -1363,7 +1329,6 @@ MODULE_DEVICE_TABLE(i2c, wm8991_i2c_id); | |||
1363 | static struct i2c_driver wm8991_i2c_driver = { | 1329 | static struct i2c_driver wm8991_i2c_driver = { |
1364 | .driver = { | 1330 | .driver = { |
1365 | .name = "wm8991", | 1331 | .name = "wm8991", |
1366 | .owner = THIS_MODULE, | ||
1367 | }, | 1332 | }, |
1368 | .probe = wm8991_i2c_probe, | 1333 | .probe = wm8991_i2c_probe, |
1369 | .remove = wm8991_i2c_remove, | 1334 | .remove = wm8991_i2c_remove, |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 8a8db8605dc2..8668c4c391b0 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -41,7 +41,7 @@ static const char *wm8993_supply_names[WM8993_NUM_SUPPLIES] = { | |||
41 | "SPKVDD", | 41 | "SPKVDD", |
42 | }; | 42 | }; |
43 | 43 | ||
44 | static struct reg_default wm8993_reg_defaults[] = { | 44 | static const struct reg_default wm8993_reg_defaults[] = { |
45 | { 1, 0x0000 }, /* R1 - Power Management (1) */ | 45 | { 1, 0x0000 }, /* R1 - Power Management (1) */ |
46 | { 2, 0x6000 }, /* R2 - Power Management (2) */ | 46 | { 2, 0x6000 }, /* R2 - Power Management (2) */ |
47 | { 3, 0x0000 }, /* R3 - Power Management (3) */ | 47 | { 3, 0x0000 }, /* R3 - Power Management (3) */ |
@@ -628,11 +628,10 @@ static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); | |||
628 | static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0); | 628 | static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0); |
629 | static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0); | 629 | static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0); |
630 | static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); | 630 | static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); |
631 | static const unsigned int drc_max_tlv[] = { | 631 | static const DECLARE_TLV_DB_RANGE(drc_max_tlv, |
632 | TLV_DB_RANGE_HEAD(2), | ||
633 | 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), | 632 | 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), |
634 | 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0), | 633 | 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0) |
635 | }; | 634 | ); |
636 | static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0); | 635 | static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0); |
637 | static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0); | 636 | static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0); |
638 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 637 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
@@ -1595,7 +1594,7 @@ static int wm8993_resume(struct snd_soc_codec *codec) | |||
1595 | #endif | 1594 | #endif |
1596 | 1595 | ||
1597 | /* Tune DC servo configuration */ | 1596 | /* Tune DC servo configuration */ |
1598 | static struct reg_default wm8993_regmap_patch[] = { | 1597 | static const struct reg_sequence wm8993_regmap_patch[] = { |
1599 | { 0x44, 3 }, | 1598 | { 0x44, 3 }, |
1600 | { 0x56, 3 }, | 1599 | { 0x56, 3 }, |
1601 | { 0x44, 0 }, | 1600 | { 0x44, 0 }, |
@@ -1742,7 +1741,6 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); | |||
1742 | static struct i2c_driver wm8993_i2c_driver = { | 1741 | static struct i2c_driver wm8993_i2c_driver = { |
1743 | .driver = { | 1742 | .driver = { |
1744 | .name = "wm8993", | 1743 | .name = "wm8993", |
1745 | .owner = THIS_MODULE, | ||
1746 | }, | 1744 | }, |
1747 | .probe = wm8993_i2c_probe, | 1745 | .probe = wm8993_i2c_probe, |
1748 | .remove = wm8993_i2c_remove, | 1746 | .remove = wm8993_i2c_remove, |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 962e1d31a629..2ccbb322df77 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -1942,14 +1942,16 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1942 | { "AIF2ADCDAT", NULL, "AIF2ADC Mux" }, | 1942 | { "AIF2ADCDAT", NULL, "AIF2ADC Mux" }, |
1943 | 1943 | ||
1944 | /* AIF3 output */ | 1944 | /* AIF3 output */ |
1945 | { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC1L" }, | 1945 | { "AIF3ADC Mux", "AIF1ADCDAT", "AIF1ADC1L" }, |
1946 | { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC1R" }, | 1946 | { "AIF3ADC Mux", "AIF1ADCDAT", "AIF1ADC1R" }, |
1947 | { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC2L" }, | 1947 | { "AIF3ADC Mux", "AIF1ADCDAT", "AIF1ADC2L" }, |
1948 | { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC2R" }, | 1948 | { "AIF3ADC Mux", "AIF1ADCDAT", "AIF1ADC2R" }, |
1949 | { "AIF3ADCDAT", "AIF2ADCDAT", "AIF2ADCL" }, | 1949 | { "AIF3ADC Mux", "AIF2ADCDAT", "AIF2ADCL" }, |
1950 | { "AIF3ADCDAT", "AIF2ADCDAT", "AIF2ADCR" }, | 1950 | { "AIF3ADC Mux", "AIF2ADCDAT", "AIF2ADCR" }, |
1951 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" }, | 1951 | { "AIF3ADC Mux", "AIF2DACDAT", "AIF2DACL" }, |
1952 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" }, | 1952 | { "AIF3ADC Mux", "AIF2DACDAT", "AIF2DACR" }, |
1953 | |||
1954 | { "AIF3ADCDAT", NULL, "AIF3ADC Mux" }, | ||
1953 | 1955 | ||
1954 | /* Loopback */ | 1956 | /* Loopback */ |
1955 | { "AIF1 Loopback", "ADCDAT", "AIF1ADCDAT" }, | 1957 | { "AIF1 Loopback", "ADCDAT", "AIF1ADCDAT" }, |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 505b65f5734f..eda52a96c1fa 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -2298,7 +2298,6 @@ MODULE_DEVICE_TABLE(i2c, wm8995_i2c_id); | |||
2298 | static struct i2c_driver wm8995_i2c_driver = { | 2298 | static struct i2c_driver wm8995_i2c_driver = { |
2299 | .driver = { | 2299 | .driver = { |
2300 | .name = "wm8995", | 2300 | .name = "wm8995", |
2301 | .owner = THIS_MODULE, | ||
2302 | }, | 2301 | }, |
2303 | .probe = wm8995_i2c_probe, | 2302 | .probe = wm8995_i2c_probe, |
2304 | .remove = wm8995_i2c_remove, | 2303 | .remove = wm8995_i2c_remove, |
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 3dd063f682b2..f7ccd9fc5808 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -117,7 +117,7 @@ WM8996_REGULATOR_EVENT(0) | |||
117 | WM8996_REGULATOR_EVENT(1) | 117 | WM8996_REGULATOR_EVENT(1) |
118 | WM8996_REGULATOR_EVENT(2) | 118 | WM8996_REGULATOR_EVENT(2) |
119 | 119 | ||
120 | static struct reg_default wm8996_reg[] = { | 120 | static const struct reg_default wm8996_reg[] = { |
121 | { WM8996_POWER_MANAGEMENT_1, 0x0 }, | 121 | { WM8996_POWER_MANAGEMENT_1, 0x0 }, |
122 | { WM8996_POWER_MANAGEMENT_2, 0x0 }, | 122 | { WM8996_POWER_MANAGEMENT_2, 0x0 }, |
123 | { WM8996_POWER_MANAGEMENT_3, 0x0 }, | 123 | { WM8996_POWER_MANAGEMENT_3, 0x0 }, |
@@ -1780,7 +1780,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, | |||
1780 | wm8996->rx_rate[dai->id] = params_rate(params); | 1780 | wm8996->rx_rate[dai->id] = params_rate(params); |
1781 | 1781 | ||
1782 | /* Needs looking at for TDM */ | 1782 | /* Needs looking at for TDM */ |
1783 | bits = snd_pcm_format_width(params_format(params)); | 1783 | bits = params_width(params); |
1784 | if (bits < 0) | 1784 | if (bits < 0) |
1785 | return bits; | 1785 | return bits; |
1786 | aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits; | 1786 | aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits; |
@@ -2647,12 +2647,10 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2647 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) | 2647 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) |
2648 | ret = request_threaded_irq(i2c->irq, NULL, | 2648 | ret = request_threaded_irq(i2c->irq, NULL, |
2649 | wm8996_edge_irq, | 2649 | wm8996_edge_irq, |
2650 | irq_flags | IRQF_ONESHOT, | 2650 | irq_flags, "wm8996", codec); |
2651 | "wm8996", codec); | ||
2652 | else | 2651 | else |
2653 | ret = request_threaded_irq(i2c->irq, NULL, wm8996_irq, | 2652 | ret = request_threaded_irq(i2c->irq, NULL, wm8996_irq, |
2654 | irq_flags | IRQF_ONESHOT, | 2653 | irq_flags, "wm8996", codec); |
2655 | "wm8996", codec); | ||
2656 | 2654 | ||
2657 | if (ret == 0) { | 2655 | if (ret == 0) { |
2658 | /* Unmask the interrupt */ | 2656 | /* Unmask the interrupt */ |
@@ -3100,7 +3098,6 @@ MODULE_DEVICE_TABLE(i2c, wm8996_i2c_id); | |||
3100 | static struct i2c_driver wm8996_i2c_driver = { | 3098 | static struct i2c_driver wm8996_i2c_driver = { |
3101 | .driver = { | 3099 | .driver = { |
3102 | .name = "wm8996", | 3100 | .name = "wm8996", |
3103 | .owner = THIS_MODULE, | ||
3104 | }, | 3101 | }, |
3105 | .probe = wm8996_i2c_probe, | 3102 | .probe = wm8996_i2c_probe, |
3106 | .remove = wm8996_i2c_remove, | 3103 | .remove = wm8996_i2c_remove, |
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 4134dc7e1243..b4dba3a02aba 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c | |||
@@ -174,8 +174,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | |||
174 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | 174 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), |
175 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | 175 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), |
176 | 176 | ||
177 | SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), | 177 | ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2), |
178 | SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), | ||
179 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | 178 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, |
180 | 24, 0, eq_tlv), | 179 | 24, 0, eq_tlv), |
181 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | 180 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, |
@@ -187,8 +186,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | |||
187 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | 186 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, |
188 | 24, 0, eq_tlv), | 187 | 24, 0, eq_tlv), |
189 | 188 | ||
190 | SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), | 189 | ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2), |
191 | SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), | ||
192 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | 190 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, |
193 | 24, 0, eq_tlv), | 191 | 24, 0, eq_tlv), |
194 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | 192 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, |
@@ -200,8 +198,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | |||
200 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | 198 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, |
201 | 24, 0, eq_tlv), | 199 | 24, 0, eq_tlv), |
202 | 200 | ||
203 | SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), | 201 | ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2), |
204 | SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), | ||
205 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | 202 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, |
206 | 24, 0, eq_tlv), | 203 | 24, 0, eq_tlv), |
207 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | 204 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, |
@@ -213,8 +210,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | |||
213 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | 210 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, |
214 | 24, 0, eq_tlv), | 211 | 24, 0, eq_tlv), |
215 | 212 | ||
216 | SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), | 213 | ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2), |
217 | SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), | ||
218 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | 214 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, |
219 | 24, 0, eq_tlv), | 215 | 24, 0, eq_tlv), |
220 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | 216 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, |
@@ -242,10 +238,10 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | |||
242 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | 238 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), |
243 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | 239 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), |
244 | 240 | ||
245 | SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1), | 241 | ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2), |
246 | SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1), | 242 | ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2), |
247 | SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1), | 243 | ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2), |
248 | SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1), | 244 | ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2), |
249 | 245 | ||
250 | SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]), | 246 | SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]), |
251 | SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]), | 247 | SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]), |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 8a8b1c0f9142..ccb3b15139ad 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <sound/wm9081.h> | 30 | #include <sound/wm9081.h> |
31 | #include "wm9081.h" | 31 | #include "wm9081.h" |
32 | 32 | ||
33 | static struct reg_default wm9081_reg[] = { | 33 | static const struct reg_default wm9081_reg[] = { |
34 | { 2, 0x00B9 }, /* R2 - Analogue Lineout */ | 34 | { 2, 0x00B9 }, /* R2 - Analogue Lineout */ |
35 | { 3, 0x00B9 }, /* R3 - Analogue Speaker PGA */ | 35 | { 3, 0x00B9 }, /* R3 - Analogue Speaker PGA */ |
36 | { 4, 0x0001 }, /* R4 - VMID Control */ | 36 | { 4, 0x0001 }, /* R4 - VMID Control */ |
@@ -243,13 +243,12 @@ static int wm9081_reset(struct regmap *map) | |||
243 | static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0); | 243 | static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0); |
244 | static const DECLARE_TLV_DB_SCALE(drc_out_tlv, -2250, 75, 0); | 244 | static const DECLARE_TLV_DB_SCALE(drc_out_tlv, -2250, 75, 0); |
245 | static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); | 245 | static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); |
246 | static unsigned int drc_max_tlv[] = { | 246 | static const DECLARE_TLV_DB_RANGE(drc_max_tlv, |
247 | TLV_DB_RANGE_HEAD(4), | ||
248 | 0, 0, TLV_DB_SCALE_ITEM(1200, 0, 0), | 247 | 0, 0, TLV_DB_SCALE_ITEM(1200, 0, 0), |
249 | 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0), | 248 | 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0), |
250 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | 249 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), |
251 | 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0), | 250 | 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0) |
252 | }; | 251 | ); |
253 | static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0); | 252 | static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0); |
254 | static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -300, 50, 0); | 253 | static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -300, 50, 0); |
255 | 254 | ||
@@ -1378,7 +1377,6 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); | |||
1378 | static struct i2c_driver wm9081_i2c_driver = { | 1377 | static struct i2c_driver wm9081_i2c_driver = { |
1379 | .driver = { | 1378 | .driver = { |
1380 | .name = "wm9081", | 1379 | .name = "wm9081", |
1381 | .owner = THIS_MODULE, | ||
1382 | }, | 1380 | }, |
1383 | .probe = wm9081_i2c_probe, | 1381 | .probe = wm9081_i2c_probe, |
1384 | .remove = wm9081_i2c_remove, | 1382 | .remove = wm9081_i2c_remove, |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 13d23fc797db..5d737290f547 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -162,23 +162,20 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec) | |||
162 | dev_err(codec->dev, "Timed out waiting for DC Servo\n"); | 162 | dev_err(codec->dev, "Timed out waiting for DC Servo\n"); |
163 | } | 163 | } |
164 | 164 | ||
165 | static const unsigned int in_tlv[] = { | 165 | static const DECLARE_TLV_DB_RANGE(in_tlv, |
166 | TLV_DB_RANGE_HEAD(3), | ||
167 | 0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0), | 166 | 0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0), |
168 | 1, 3, TLV_DB_SCALE_ITEM(-350, 350, 0), | 167 | 1, 3, TLV_DB_SCALE_ITEM(-350, 350, 0), |
169 | 4, 6, TLV_DB_SCALE_ITEM(600, 600, 0), | 168 | 4, 6, TLV_DB_SCALE_ITEM(600, 600, 0) |
170 | }; | 169 | ); |
171 | static const unsigned int mix_tlv[] = { | 170 | static const DECLARE_TLV_DB_RANGE(mix_tlv, |
172 | TLV_DB_RANGE_HEAD(2), | ||
173 | 0, 2, TLV_DB_SCALE_ITEM(-1200, 300, 0), | 171 | 0, 2, TLV_DB_SCALE_ITEM(-1200, 300, 0), |
174 | 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0), | 172 | 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0) |
175 | }; | 173 | ); |
176 | static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); | 174 | static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); |
177 | static const unsigned int spkboost_tlv[] = { | 175 | static const DECLARE_TLV_DB_RANGE(spkboost_tlv, |
178 | TLV_DB_RANGE_HEAD(2), | ||
179 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), | 176 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), |
180 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), | 177 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0) |
181 | }; | 178 | ); |
182 | 179 | ||
183 | static const struct snd_kcontrol_new wm9090_controls[] = { | 180 | static const struct snd_kcontrol_new wm9090_controls[] = { |
184 | SOC_SINGLE_TLV("IN1A Volume", WM9090_IN1_LINE_INPUT_A_VOLUME, 0, 6, 0, | 181 | SOC_SINGLE_TLV("IN1A Volume", WM9090_IN1_LINE_INPUT_A_VOLUME, 0, 6, 0, |
@@ -636,7 +633,6 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id); | |||
636 | static struct i2c_driver wm9090_i2c_driver = { | 633 | static struct i2c_driver wm9090_i2c_driver = { |
637 | .driver = { | 634 | .driver = { |
638 | .name = "wm9090", | 635 | .name = "wm9090", |
639 | .owner = THIS_MODULE, | ||
640 | }, | 636 | }, |
641 | .probe = wm9090_i2c_probe, | 637 | .probe = wm9090_i2c_probe, |
642 | .remove = wm9090_i2c_remove, | 638 | .remove = wm9090_i2c_remove, |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 5cc457ef8894..744842c76a60 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -22,6 +22,9 @@ | |||
22 | 22 | ||
23 | #include "wm9705.h" | 23 | #include "wm9705.h" |
24 | 24 | ||
25 | #define WM9705_VENDOR_ID 0x574d4c05 | ||
26 | #define WM9705_VENDOR_ID_MASK 0xffffffff | ||
27 | |||
25 | /* | 28 | /* |
26 | * WM9705 register cache | 29 | * WM9705 register cache |
27 | */ | 30 | */ |
@@ -293,21 +296,6 @@ static struct snd_soc_dai_driver wm9705_dai[] = { | |||
293 | } | 296 | } |
294 | }; | 297 | }; |
295 | 298 | ||
296 | static int wm9705_reset(struct snd_soc_codec *codec) | ||
297 | { | ||
298 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
299 | |||
300 | if (soc_ac97_ops->reset) { | ||
301 | soc_ac97_ops->reset(ac97); | ||
302 | if (ac97_read(codec, 0) == wm9705_reg[0]) | ||
303 | return 0; /* Success */ | ||
304 | } | ||
305 | |||
306 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
307 | |||
308 | return -EIO; | ||
309 | } | ||
310 | |||
311 | #ifdef CONFIG_PM | 299 | #ifdef CONFIG_PM |
312 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) | 300 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) |
313 | { | 301 | { |
@@ -324,7 +312,8 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) | |||
324 | int i, ret; | 312 | int i, ret; |
325 | u16 *cache = codec->reg_cache; | 313 | u16 *cache = codec->reg_cache; |
326 | 314 | ||
327 | ret = wm9705_reset(codec); | 315 | ret = snd_ac97_reset(ac97, true, WM9705_VENDOR_ID, |
316 | WM9705_VENDOR_ID_MASK); | ||
328 | if (ret < 0) | 317 | if (ret < 0) |
329 | return ret; | 318 | return ret; |
330 | 319 | ||
@@ -342,30 +331,17 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) | |||
342 | static int wm9705_soc_probe(struct snd_soc_codec *codec) | 331 | static int wm9705_soc_probe(struct snd_soc_codec *codec) |
343 | { | 332 | { |
344 | struct snd_ac97 *ac97; | 333 | struct snd_ac97 *ac97; |
345 | int ret = 0; | ||
346 | 334 | ||
347 | ac97 = snd_soc_alloc_ac97_codec(codec); | 335 | ac97 = snd_soc_new_ac97_codec(codec, WM9705_VENDOR_ID, |
336 | WM9705_VENDOR_ID_MASK); | ||
348 | if (IS_ERR(ac97)) { | 337 | if (IS_ERR(ac97)) { |
349 | ret = PTR_ERR(ac97); | ||
350 | dev_err(codec->dev, "Failed to register AC97 codec\n"); | 338 | dev_err(codec->dev, "Failed to register AC97 codec\n"); |
351 | return ret; | 339 | return PTR_ERR(ac97); |
352 | } | 340 | } |
353 | 341 | ||
354 | ret = wm9705_reset(codec); | ||
355 | if (ret) | ||
356 | goto err_put_device; | ||
357 | |||
358 | ret = device_add(&ac97->dev); | ||
359 | if (ret) | ||
360 | goto err_put_device; | ||
361 | |||
362 | snd_soc_codec_set_drvdata(codec, ac97); | 342 | snd_soc_codec_set_drvdata(codec, ac97); |
363 | 343 | ||
364 | return 0; | 344 | return 0; |
365 | |||
366 | err_put_device: | ||
367 | put_device(&ac97->dev); | ||
368 | return ret; | ||
369 | } | 345 | } |
370 | 346 | ||
371 | static int wm9705_soc_remove(struct snd_soc_codec *codec) | 347 | static int wm9705_soc_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 1fda104dfc45..488a92224249 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -23,6 +23,9 @@ | |||
23 | #include <sound/tlv.h> | 23 | #include <sound/tlv.h> |
24 | #include "wm9712.h" | 24 | #include "wm9712.h" |
25 | 25 | ||
26 | #define WM9712_VENDOR_ID 0x574d4c12 | ||
27 | #define WM9712_VENDOR_ID_MASK 0xffffffff | ||
28 | |||
26 | struct wm9712_priv { | 29 | struct wm9712_priv { |
27 | struct snd_ac97 *ac97; | 30 | struct snd_ac97 *ac97; |
28 | unsigned int hp_mixer[2]; | 31 | unsigned int hp_mixer[2]; |
@@ -613,35 +616,14 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec, | |||
613 | return 0; | 616 | return 0; |
614 | } | 617 | } |
615 | 618 | ||
616 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) | ||
617 | { | ||
618 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
619 | |||
620 | if (try_warm && soc_ac97_ops->warm_reset) { | ||
621 | soc_ac97_ops->warm_reset(wm9712->ac97); | ||
622 | if (ac97_read(codec, 0) == wm9712_reg[0]) | ||
623 | return 1; | ||
624 | } | ||
625 | |||
626 | soc_ac97_ops->reset(wm9712->ac97); | ||
627 | if (soc_ac97_ops->warm_reset) | ||
628 | soc_ac97_ops->warm_reset(wm9712->ac97); | ||
629 | if (ac97_read(codec, 0) != wm9712_reg[0]) | ||
630 | goto err; | ||
631 | return 0; | ||
632 | |||
633 | err: | ||
634 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
635 | return -EIO; | ||
636 | } | ||
637 | |||
638 | static int wm9712_soc_resume(struct snd_soc_codec *codec) | 619 | static int wm9712_soc_resume(struct snd_soc_codec *codec) |
639 | { | 620 | { |
640 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | 621 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); |
641 | int i, ret; | 622 | int i, ret; |
642 | u16 *cache = codec->reg_cache; | 623 | u16 *cache = codec->reg_cache; |
643 | 624 | ||
644 | ret = wm9712_reset(codec, 1); | 625 | ret = snd_ac97_reset(wm9712->ac97, true, WM9712_VENDOR_ID, |
626 | WM9712_VENDOR_ID_MASK); | ||
645 | if (ret < 0) | 627 | if (ret < 0) |
646 | return ret; | 628 | return ret; |
647 | 629 | ||
@@ -663,31 +645,20 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
663 | static int wm9712_soc_probe(struct snd_soc_codec *codec) | 645 | static int wm9712_soc_probe(struct snd_soc_codec *codec) |
664 | { | 646 | { |
665 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | 647 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); |
666 | int ret = 0; | 648 | int ret; |
667 | 649 | ||
668 | wm9712->ac97 = snd_soc_alloc_ac97_codec(codec); | 650 | wm9712->ac97 = snd_soc_new_ac97_codec(codec, WM9712_VENDOR_ID, |
651 | WM9712_VENDOR_ID_MASK); | ||
669 | if (IS_ERR(wm9712->ac97)) { | 652 | if (IS_ERR(wm9712->ac97)) { |
670 | ret = PTR_ERR(wm9712->ac97); | 653 | ret = PTR_ERR(wm9712->ac97); |
671 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); | 654 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); |
672 | return ret; | 655 | return ret; |
673 | } | 656 | } |
674 | 657 | ||
675 | ret = wm9712_reset(codec, 0); | ||
676 | if (ret < 0) | ||
677 | goto err_put_device; | ||
678 | |||
679 | ret = device_add(&wm9712->ac97->dev); | ||
680 | if (ret) | ||
681 | goto err_put_device; | ||
682 | |||
683 | /* set alc mux to none */ | 658 | /* set alc mux to none */ |
684 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); | 659 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); |
685 | 660 | ||
686 | return 0; | 661 | return 0; |
687 | |||
688 | err_put_device: | ||
689 | put_device(&wm9712->ac97->dev); | ||
690 | return ret; | ||
691 | } | 662 | } |
692 | 663 | ||
693 | static int wm9712_soc_remove(struct snd_soc_codec *codec) | 664 | static int wm9712_soc_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 89cd2d6f57c0..4083a5130cbd 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -29,6 +29,9 @@ | |||
29 | 29 | ||
30 | #include "wm9713.h" | 30 | #include "wm9713.h" |
31 | 31 | ||
32 | #define WM9713_VENDOR_ID 0x574d4c13 | ||
33 | #define WM9713_VENDOR_ID_MASK 0xffffffff | ||
34 | |||
32 | struct wm9713_priv { | 35 | struct wm9713_priv { |
33 | struct snd_ac97 *ac97; | 36 | struct snd_ac97 *ac97; |
34 | u32 pll_in; /* PLL input frequency */ | 37 | u32 pll_in; /* PLL input frequency */ |
@@ -116,11 +119,10 @@ SOC_ENUM_SINGLE_VIRT(2, wm9713_micb_select), /* mic selection 19 */ | |||
116 | static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); | 119 | static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); |
117 | static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0); | 120 | static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0); |
118 | static const DECLARE_TLV_DB_SCALE(misc_tlv, -1500, 300, 0); | 121 | static const DECLARE_TLV_DB_SCALE(misc_tlv, -1500, 300, 0); |
119 | static unsigned int mic_tlv[] = { | 122 | static const DECLARE_TLV_DB_RANGE(mic_tlv, |
120 | TLV_DB_RANGE_HEAD(2), | ||
121 | 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), | 123 | 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), |
122 | 3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0), | 124 | 3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0) |
123 | }; | 125 | ); |
124 | 126 | ||
125 | static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = { | 127 | static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = { |
126 | SOC_DOUBLE_TLV("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1, out_tlv), | 128 | SOC_DOUBLE_TLV("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1, out_tlv), |
@@ -1123,28 +1125,6 @@ static struct snd_soc_dai_driver wm9713_dai[] = { | |||
1123 | }, | 1125 | }, |
1124 | }; | 1126 | }; |
1125 | 1127 | ||
1126 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | ||
1127 | { | ||
1128 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
1129 | |||
1130 | if (try_warm && soc_ac97_ops->warm_reset) { | ||
1131 | soc_ac97_ops->warm_reset(wm9713->ac97); | ||
1132 | if (ac97_read(codec, 0) == wm9713_reg[0]) | ||
1133 | return 1; | ||
1134 | } | ||
1135 | |||
1136 | soc_ac97_ops->reset(wm9713->ac97); | ||
1137 | if (soc_ac97_ops->warm_reset) | ||
1138 | soc_ac97_ops->warm_reset(wm9713->ac97); | ||
1139 | if (ac97_read(codec, 0) != wm9713_reg[0]) { | ||
1140 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
1141 | return -EIO; | ||
1142 | } | ||
1143 | |||
1144 | return 0; | ||
1145 | } | ||
1146 | EXPORT_SYMBOL_GPL(wm9713_reset); | ||
1147 | |||
1148 | static int wm9713_set_bias_level(struct snd_soc_codec *codec, | 1128 | static int wm9713_set_bias_level(struct snd_soc_codec *codec, |
1149 | enum snd_soc_bias_level level) | 1129 | enum snd_soc_bias_level level) |
1150 | { | 1130 | { |
@@ -1196,7 +1176,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1196 | int i, ret; | 1176 | int i, ret; |
1197 | u16 *cache = codec->reg_cache; | 1177 | u16 *cache = codec->reg_cache; |
1198 | 1178 | ||
1199 | ret = wm9713_reset(codec, 1); | 1179 | ret = snd_ac97_reset(wm9713->ac97, true, WM9713_VENDOR_ID, |
1180 | WM9713_VENDOR_ID_MASK); | ||
1200 | if (ret < 0) | 1181 | if (ret < 0) |
1201 | return ret; | 1182 | return ret; |
1202 | 1183 | ||
@@ -1222,32 +1203,18 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1222 | static int wm9713_soc_probe(struct snd_soc_codec *codec) | 1203 | static int wm9713_soc_probe(struct snd_soc_codec *codec) |
1223 | { | 1204 | { |
1224 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | 1205 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1225 | int ret = 0, reg; | 1206 | int reg; |
1226 | 1207 | ||
1227 | wm9713->ac97 = snd_soc_alloc_ac97_codec(codec); | 1208 | wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID, |
1209 | WM9713_VENDOR_ID_MASK); | ||
1228 | if (IS_ERR(wm9713->ac97)) | 1210 | if (IS_ERR(wm9713->ac97)) |
1229 | return PTR_ERR(wm9713->ac97); | 1211 | return PTR_ERR(wm9713->ac97); |
1230 | 1212 | ||
1231 | /* do a cold reset for the controller and then try | ||
1232 | * a warm reset followed by an optional cold reset for codec */ | ||
1233 | wm9713_reset(codec, 0); | ||
1234 | ret = wm9713_reset(codec, 1); | ||
1235 | if (ret < 0) | ||
1236 | goto err_put_device; | ||
1237 | |||
1238 | ret = device_add(&wm9713->ac97->dev); | ||
1239 | if (ret) | ||
1240 | goto err_put_device; | ||
1241 | |||
1242 | /* unmute the adc - move to kcontrol */ | 1213 | /* unmute the adc - move to kcontrol */ |
1243 | reg = ac97_read(codec, AC97_CD) & 0x7fff; | 1214 | reg = ac97_read(codec, AC97_CD) & 0x7fff; |
1244 | ac97_write(codec, AC97_CD, reg); | 1215 | ac97_write(codec, AC97_CD, reg); |
1245 | 1216 | ||
1246 | return 0; | 1217 | return 0; |
1247 | |||
1248 | err_put_device: | ||
1249 | put_device(&wm9713->ac97->dev); | ||
1250 | return ret; | ||
1251 | } | 1218 | } |
1252 | 1219 | ||
1253 | static int wm9713_soc_remove(struct snd_soc_codec *codec) | 1220 | static int wm9713_soc_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h index 793da863a03d..53df11b1f727 100644 --- a/sound/soc/codecs/wm9713.h +++ b/sound/soc/codecs/wm9713.h | |||
@@ -45,6 +45,4 @@ | |||
45 | #define WM9713_DAI_AC97_AUX 1 | 45 | #define WM9713_DAI_AC97_AUX 1 |
46 | #define WM9713_DAI_PCM_VOICE 2 | 46 | #define WM9713_DAI_PCM_VOICE 2 |
47 | 47 | ||
48 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm); | ||
49 | |||
50 | #endif | 48 | #endif |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index fd86bd105460..624b3b9cb079 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -38,11 +38,10 @@ static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0); | |||
38 | static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0); | 38 | static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0); |
39 | static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1); | 39 | static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1); |
40 | static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0); | 40 | static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0); |
41 | static const unsigned int spkboost_tlv[] = { | 41 | static const DECLARE_TLV_DB_RANGE(spkboost_tlv, |
42 | TLV_DB_RANGE_HEAD(2), | ||
43 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), | 42 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), |
44 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), | 43 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0) |
45 | }; | 44 | ); |
46 | static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0); | 45 | static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0); |
47 | 46 | ||
48 | static const char *speaker_ref_text[] = { | 47 | static const char *speaker_ref_text[] = { |
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 56cb4d95637d..ec98548a5fc9 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c | |||
@@ -651,23 +651,15 @@ static const struct snd_soc_component_driver davinci_i2s_component = { | |||
651 | static int davinci_i2s_probe(struct platform_device *pdev) | 651 | static int davinci_i2s_probe(struct platform_device *pdev) |
652 | { | 652 | { |
653 | struct davinci_mcbsp_dev *dev; | 653 | struct davinci_mcbsp_dev *dev; |
654 | struct resource *mem, *ioarea, *res; | 654 | struct resource *mem, *res; |
655 | void __iomem *io_base; | ||
655 | int *dma; | 656 | int *dma; |
656 | int ret; | 657 | int ret; |
657 | 658 | ||
658 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 659 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
659 | if (!mem) { | 660 | io_base = devm_ioremap_resource(&pdev->dev, mem); |
660 | dev_err(&pdev->dev, "no mem resource?\n"); | 661 | if (IS_ERR(io_base)) |
661 | return -ENODEV; | 662 | return PTR_ERR(io_base); |
662 | } | ||
663 | |||
664 | ioarea = devm_request_mem_region(&pdev->dev, mem->start, | ||
665 | resource_size(mem), | ||
666 | pdev->name); | ||
667 | if (!ioarea) { | ||
668 | dev_err(&pdev->dev, "McBSP region already claimed\n"); | ||
669 | return -EBUSY; | ||
670 | } | ||
671 | 663 | ||
672 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev), | 664 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev), |
673 | GFP_KERNEL); | 665 | GFP_KERNEL); |
@@ -679,12 +671,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
679 | return -ENODEV; | 671 | return -ENODEV; |
680 | clk_enable(dev->clk); | 672 | clk_enable(dev->clk); |
681 | 673 | ||
682 | dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | 674 | dev->base = io_base; |
683 | if (!dev->base) { | ||
684 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
685 | ret = -ENOMEM; | ||
686 | goto err_release_clk; | ||
687 | } | ||
688 | 675 | ||
689 | dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = | 676 | dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = |
690 | (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); | 677 | (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b960e626dad9..add6bb99661d 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -1613,7 +1613,7 @@ static int davinci_mcasp_get_dma_type(struct davinci_mcasp *mcasp) | |||
1613 | static int davinci_mcasp_probe(struct platform_device *pdev) | 1613 | static int davinci_mcasp_probe(struct platform_device *pdev) |
1614 | { | 1614 | { |
1615 | struct snd_dmaengine_dai_dma_data *dma_data; | 1615 | struct snd_dmaengine_dai_dma_data *dma_data; |
1616 | struct resource *mem, *ioarea, *res, *dat; | 1616 | struct resource *mem, *res, *dat; |
1617 | struct davinci_mcasp_pdata *pdata; | 1617 | struct davinci_mcasp_pdata *pdata; |
1618 | struct davinci_mcasp *mcasp; | 1618 | struct davinci_mcasp *mcasp; |
1619 | char *irq_name; | 1619 | char *irq_name; |
@@ -1648,22 +1648,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1648 | } | 1648 | } |
1649 | } | 1649 | } |
1650 | 1650 | ||
1651 | ioarea = devm_request_mem_region(&pdev->dev, mem->start, | 1651 | mcasp->base = devm_ioremap_resource(&pdev->dev, mem); |
1652 | resource_size(mem), pdev->name); | 1652 | if (IS_ERR(mcasp->base)) |
1653 | if (!ioarea) { | 1653 | return PTR_ERR(mcasp->base); |
1654 | dev_err(&pdev->dev, "Audio region already claimed\n"); | ||
1655 | return -EBUSY; | ||
1656 | } | ||
1657 | 1654 | ||
1658 | pm_runtime_enable(&pdev->dev); | 1655 | pm_runtime_enable(&pdev->dev); |
1659 | 1656 | ||
1660 | mcasp->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | ||
1661 | if (!mcasp->base) { | ||
1662 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
1663 | ret = -ENOMEM; | ||
1664 | goto err; | ||
1665 | } | ||
1666 | |||
1667 | mcasp->op_mode = pdata->op_mode; | 1657 | mcasp->op_mode = pdata->op_mode; |
1668 | /* sanity check for tdm slots parameter */ | 1658 | /* sanity check for tdm slots parameter */ |
1669 | if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { | 1659 | if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { |
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index fabd05f24aeb..c77d9218795a 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c | |||
@@ -231,8 +231,9 @@ static int davinci_vcif_probe(struct platform_device *pdev) | |||
231 | 231 | ||
232 | dev_set_drvdata(&pdev->dev, davinci_vcif_dev); | 232 | dev_set_drvdata(&pdev->dev, davinci_vcif_dev); |
233 | 233 | ||
234 | ret = snd_soc_register_component(&pdev->dev, &davinci_vcif_component, | 234 | ret = devm_snd_soc_register_component(&pdev->dev, |
235 | &davinci_vcif_dai, 1); | 235 | &davinci_vcif_component, |
236 | &davinci_vcif_dai, 1); | ||
236 | if (ret != 0) { | 237 | if (ret != 0) { |
237 | dev_err(&pdev->dev, "could not register dai\n"); | 238 | dev_err(&pdev->dev, "could not register dai\n"); |
238 | return ret; | 239 | return ret; |
@@ -241,23 +242,14 @@ static int davinci_vcif_probe(struct platform_device *pdev) | |||
241 | ret = edma_pcm_platform_register(&pdev->dev); | 242 | ret = edma_pcm_platform_register(&pdev->dev); |
242 | if (ret) { | 243 | if (ret) { |
243 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | 244 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); |
244 | snd_soc_unregister_component(&pdev->dev); | ||
245 | return ret; | 245 | return ret; |
246 | } | 246 | } |
247 | 247 | ||
248 | return 0; | 248 | return 0; |
249 | } | 249 | } |
250 | 250 | ||
251 | static int davinci_vcif_remove(struct platform_device *pdev) | ||
252 | { | ||
253 | snd_soc_unregister_component(&pdev->dev); | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static struct platform_driver davinci_vcif_driver = { | 251 | static struct platform_driver davinci_vcif_driver = { |
259 | .probe = davinci_vcif_probe, | 252 | .probe = davinci_vcif_probe, |
260 | .remove = davinci_vcif_remove, | ||
261 | .driver = { | 253 | .driver = { |
262 | .name = "davinci-vcif", | 254 | .name = "davinci-vcif", |
263 | }, | 255 | }, |
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index e1aa3834b101..883087f2b092 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c | |||
@@ -182,7 +182,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) | |||
182 | ); | 182 | ); |
183 | } else { | 183 | } else { |
184 | if (np) { | 184 | if (np) { |
185 | /* The eukrea,asoc-tlv320 driver was explicitely | 185 | /* The eukrea,asoc-tlv320 driver was explicitly |
186 | * requested (through the device tree). | 186 | * requested (through the device tree). |
187 | */ | 187 | */ |
188 | dev_err(&pdev->dev, | 188 | dev_err(&pdev->dev, |
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index de438871040b..5aeb6ed4827e 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "../codecs/sgtl5000.h" | 24 | #include "../codecs/sgtl5000.h" |
25 | #include "../codecs/wm8962.h" | 25 | #include "../codecs/wm8962.h" |
26 | #include "../codecs/wm8960.h" | ||
26 | 27 | ||
27 | #define RX 0 | 28 | #define RX 0 |
28 | #define TX 1 | 29 | #define TX 1 |
@@ -407,6 +408,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) | |||
407 | struct fsl_asoc_card_priv *priv; | 408 | struct fsl_asoc_card_priv *priv; |
408 | struct i2c_client *codec_dev; | 409 | struct i2c_client *codec_dev; |
409 | struct clk *codec_clk; | 410 | struct clk *codec_clk; |
411 | const char *codec_dai_name; | ||
410 | u32 width; | 412 | u32 width; |
411 | int ret; | 413 | int ret; |
412 | 414 | ||
@@ -459,6 +461,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) | |||
459 | 461 | ||
460 | /* Diversify the card configurations */ | 462 | /* Diversify the card configurations */ |
461 | if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { | 463 | if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { |
464 | codec_dai_name = "cs42888"; | ||
462 | priv->card.set_bias_level = NULL; | 465 | priv->card.set_bias_level = NULL; |
463 | priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv.mclk_freq; | 466 | priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv.mclk_freq; |
464 | priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv.mclk_freq; | 467 | priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv.mclk_freq; |
@@ -467,14 +470,22 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) | |||
467 | priv->cpu_priv.slot_width = 32; | 470 | priv->cpu_priv.slot_width = 32; |
468 | priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; | 471 | priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; |
469 | } else if (of_device_is_compatible(np, "fsl,imx-audio-sgtl5000")) { | 472 | } else if (of_device_is_compatible(np, "fsl,imx-audio-sgtl5000")) { |
473 | codec_dai_name = "sgtl5000"; | ||
470 | priv->codec_priv.mclk_id = SGTL5000_SYSCLK; | 474 | priv->codec_priv.mclk_id = SGTL5000_SYSCLK; |
471 | priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; | 475 | priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; |
472 | } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) { | 476 | } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) { |
477 | codec_dai_name = "wm8962"; | ||
473 | priv->card.set_bias_level = fsl_asoc_card_set_bias_level; | 478 | priv->card.set_bias_level = fsl_asoc_card_set_bias_level; |
474 | priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK; | 479 | priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK; |
475 | priv->codec_priv.fll_id = WM8962_SYSCLK_FLL; | 480 | priv->codec_priv.fll_id = WM8962_SYSCLK_FLL; |
476 | priv->codec_priv.pll_id = WM8962_FLL; | 481 | priv->codec_priv.pll_id = WM8962_FLL; |
477 | priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; | 482 | priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; |
483 | } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) { | ||
484 | codec_dai_name = "wm8960-hifi"; | ||
485 | priv->card.set_bias_level = fsl_asoc_card_set_bias_level; | ||
486 | priv->codec_priv.fll_id = WM8960_SYSCLK_AUTO; | ||
487 | priv->codec_priv.pll_id = WM8960_SYSCLK_AUTO; | ||
488 | priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; | ||
478 | } else { | 489 | } else { |
479 | dev_err(&pdev->dev, "unknown Device Tree compatible\n"); | 490 | dev_err(&pdev->dev, "unknown Device Tree compatible\n"); |
480 | return -EINVAL; | 491 | return -EINVAL; |
@@ -521,7 +532,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) | |||
521 | /* Normal DAI Link */ | 532 | /* Normal DAI Link */ |
522 | priv->dai_link[0].cpu_of_node = cpu_np; | 533 | priv->dai_link[0].cpu_of_node = cpu_np; |
523 | priv->dai_link[0].codec_of_node = codec_np; | 534 | priv->dai_link[0].codec_of_node = codec_np; |
524 | priv->dai_link[0].codec_dai_name = codec_dev->name; | 535 | priv->dai_link[0].codec_dai_name = codec_dai_name; |
525 | priv->dai_link[0].platform_of_node = cpu_np; | 536 | priv->dai_link[0].platform_of_node = cpu_np; |
526 | priv->dai_link[0].dai_fmt = priv->dai_fmt; | 537 | priv->dai_link[0].dai_fmt = priv->dai_fmt; |
527 | priv->card.num_links = 1; | 538 | priv->card.num_links = 1; |
@@ -530,7 +541,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) | |||
530 | /* DPCM DAI Links only if ASRC exsits */ | 541 | /* DPCM DAI Links only if ASRC exsits */ |
531 | priv->dai_link[1].cpu_of_node = asrc_np; | 542 | priv->dai_link[1].cpu_of_node = asrc_np; |
532 | priv->dai_link[1].platform_of_node = asrc_np; | 543 | priv->dai_link[1].platform_of_node = asrc_np; |
533 | priv->dai_link[2].codec_dai_name = codec_dev->name; | 544 | priv->dai_link[2].codec_dai_name = codec_dai_name; |
534 | priv->dai_link[2].codec_of_node = codec_np; | 545 | priv->dai_link[2].codec_of_node = codec_np; |
535 | priv->dai_link[2].cpu_of_node = cpu_np; | 546 | priv->dai_link[2].cpu_of_node = cpu_np; |
536 | priv->dai_link[2].dai_fmt = priv->dai_fmt; | 547 | priv->dai_link[2].dai_fmt = priv->dai_fmt; |
@@ -578,6 +589,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = { | |||
578 | { .compatible = "fsl,imx-audio-cs42888", }, | 589 | { .compatible = "fsl,imx-audio-cs42888", }, |
579 | { .compatible = "fsl,imx-audio-sgtl5000", }, | 590 | { .compatible = "fsl,imx-audio-sgtl5000", }, |
580 | { .compatible = "fsl,imx-audio-wm8962", }, | 591 | { .compatible = "fsl,imx-audio-wm8962", }, |
592 | { .compatible = "fsl,imx-audio-wm8960", }, | ||
581 | {} | 593 | {} |
582 | }; | 594 | }; |
583 | 595 | ||
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index c068494bae30..9f087d4f73ed 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c | |||
@@ -931,14 +931,29 @@ static int fsl_asrc_probe(struct platform_device *pdev) | |||
931 | static int fsl_asrc_runtime_resume(struct device *dev) | 931 | static int fsl_asrc_runtime_resume(struct device *dev) |
932 | { | 932 | { |
933 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); | 933 | struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); |
934 | int i; | 934 | int i, ret; |
935 | 935 | ||
936 | clk_prepare_enable(asrc_priv->mem_clk); | 936 | ret = clk_prepare_enable(asrc_priv->mem_clk); |
937 | clk_prepare_enable(asrc_priv->ipg_clk); | 937 | if (ret) |
938 | for (i = 0; i < ASRC_CLK_MAX_NUM; i++) | 938 | return ret; |
939 | clk_prepare_enable(asrc_priv->asrck_clk[i]); | 939 | ret = clk_prepare_enable(asrc_priv->ipg_clk); |
940 | if (ret) | ||
941 | goto disable_mem_clk; | ||
942 | for (i = 0; i < ASRC_CLK_MAX_NUM; i++) { | ||
943 | ret = clk_prepare_enable(asrc_priv->asrck_clk[i]); | ||
944 | if (ret) | ||
945 | goto disable_asrck_clk; | ||
946 | } | ||
940 | 947 | ||
941 | return 0; | 948 | return 0; |
949 | |||
950 | disable_asrck_clk: | ||
951 | for (i--; i >= 0; i--) | ||
952 | clk_disable_unprepare(asrc_priv->asrck_clk[i]); | ||
953 | clk_disable_unprepare(asrc_priv->ipg_clk); | ||
954 | disable_mem_clk: | ||
955 | clk_disable_unprepare(asrc_priv->mem_clk); | ||
956 | return ret; | ||
942 | } | 957 | } |
943 | 958 | ||
944 | static int fsl_asrc_runtime_suspend(struct device *dev) | 959 | static int fsl_asrc_runtime_suspend(struct device *dev) |
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 45eee131c47d..837979ea5c92 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -839,7 +839,7 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
839 | return ret; | 839 | return ret; |
840 | } | 840 | } |
841 | 841 | ||
842 | ret = imx_pcm_dma_init(pdev); | 842 | ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE); |
843 | if (ret) | 843 | if (ret) |
844 | dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); | 844 | dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); |
845 | 845 | ||
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 5c73bea7b11e..a18fd92c4a85 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -791,7 +791,7 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
791 | return ret; | 791 | return ret; |
792 | 792 | ||
793 | if (sai->sai_on_imx) | 793 | if (sai->sai_on_imx) |
794 | return imx_pcm_dma_init(pdev); | 794 | return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE); |
795 | else | 795 | else |
796 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | 796 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); |
797 | } | 797 | } |
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 066280953c85..b95fbc3f68eb 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h | |||
@@ -13,7 +13,8 @@ | |||
13 | 13 | ||
14 | #define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | 14 | #define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ |
15 | SNDRV_PCM_FMTBIT_S20_3LE |\ | 15 | SNDRV_PCM_FMTBIT_S20_3LE |\ |
16 | SNDRV_PCM_FMTBIT_S24_LE) | 16 | SNDRV_PCM_FMTBIT_S24_LE |\ |
17 | SNDRV_PCM_FMTBIT_S32_LE) | ||
17 | 18 | ||
18 | /* SAI Register Map Register */ | 19 | /* SAI Register Map Register */ |
19 | #define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */ | 20 | #define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */ |
@@ -45,7 +46,7 @@ | |||
45 | #define FSL_SAI_xFR(tx) (tx ? FSL_SAI_TFR : FSL_SAI_RFR) | 46 | #define FSL_SAI_xFR(tx) (tx ? FSL_SAI_TFR : FSL_SAI_RFR) |
46 | #define FSL_SAI_xMR(tx) (tx ? FSL_SAI_TMR : FSL_SAI_RMR) | 47 | #define FSL_SAI_xMR(tx) (tx ? FSL_SAI_TMR : FSL_SAI_RMR) |
47 | 48 | ||
48 | /* SAI Transmit/Recieve Control Register */ | 49 | /* SAI Transmit/Receive Control Register */ |
49 | #define FSL_SAI_CSR_TERE BIT(31) | 50 | #define FSL_SAI_CSR_TERE BIT(31) |
50 | #define FSL_SAI_CSR_FR BIT(25) | 51 | #define FSL_SAI_CSR_FR BIT(25) |
51 | #define FSL_SAI_CSR_SR BIT(24) | 52 | #define FSL_SAI_CSR_SR BIT(24) |
@@ -67,10 +68,10 @@ | |||
67 | #define FSL_SAI_CSR_FRIE BIT(8) | 68 | #define FSL_SAI_CSR_FRIE BIT(8) |
68 | #define FSL_SAI_CSR_FRDE BIT(0) | 69 | #define FSL_SAI_CSR_FRDE BIT(0) |
69 | 70 | ||
70 | /* SAI Transmit and Recieve Configuration 1 Register */ | 71 | /* SAI Transmit and Receive Configuration 1 Register */ |
71 | #define FSL_SAI_CR1_RFW_MASK 0x1f | 72 | #define FSL_SAI_CR1_RFW_MASK 0x1f |
72 | 73 | ||
73 | /* SAI Transmit and Recieve Configuration 2 Register */ | 74 | /* SAI Transmit and Receive Configuration 2 Register */ |
74 | #define FSL_SAI_CR2_SYNC BIT(30) | 75 | #define FSL_SAI_CR2_SYNC BIT(30) |
75 | #define FSL_SAI_CR2_MSEL_MASK (0x3 << 26) | 76 | #define FSL_SAI_CR2_MSEL_MASK (0x3 << 26) |
76 | #define FSL_SAI_CR2_MSEL_BUS 0 | 77 | #define FSL_SAI_CR2_MSEL_BUS 0 |
@@ -82,12 +83,12 @@ | |||
82 | #define FSL_SAI_CR2_BCD_MSTR BIT(24) | 83 | #define FSL_SAI_CR2_BCD_MSTR BIT(24) |
83 | #define FSL_SAI_CR2_DIV_MASK 0xff | 84 | #define FSL_SAI_CR2_DIV_MASK 0xff |
84 | 85 | ||
85 | /* SAI Transmit and Recieve Configuration 3 Register */ | 86 | /* SAI Transmit and Receive Configuration 3 Register */ |
86 | #define FSL_SAI_CR3_TRCE BIT(16) | 87 | #define FSL_SAI_CR3_TRCE BIT(16) |
87 | #define FSL_SAI_CR3_WDFL(x) (x) | 88 | #define FSL_SAI_CR3_WDFL(x) (x) |
88 | #define FSL_SAI_CR3_WDFL_MASK 0x1f | 89 | #define FSL_SAI_CR3_WDFL_MASK 0x1f |
89 | 90 | ||
90 | /* SAI Transmit and Recieve Configuration 4 Register */ | 91 | /* SAI Transmit and Receive Configuration 4 Register */ |
91 | #define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16) | 92 | #define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16) |
92 | #define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16) | 93 | #define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16) |
93 | #define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8) | 94 | #define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8) |
@@ -97,7 +98,7 @@ | |||
97 | #define FSL_SAI_CR4_FSP BIT(1) | 98 | #define FSL_SAI_CR4_FSP BIT(1) |
98 | #define FSL_SAI_CR4_FSD_MSTR BIT(0) | 99 | #define FSL_SAI_CR4_FSD_MSTR BIT(0) |
99 | 100 | ||
100 | /* SAI Transmit and Recieve Configuration 5 Register */ | 101 | /* SAI Transmit and Receive Configuration 5 Register */ |
101 | #define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24) | 102 | #define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24) |
102 | #define FSL_SAI_CR5_WNW_MASK (0x1f << 24) | 103 | #define FSL_SAI_CR5_WNW_MASK (0x1f << 24) |
103 | #define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16) | 104 | #define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16) |
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 8e932219cb3a..ab729f2426fe 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -454,7 +454,8 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream, | |||
454 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 454 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
455 | struct platform_device *pdev = spdif_priv->pdev; | 455 | struct platform_device *pdev = spdif_priv->pdev; |
456 | struct regmap *regmap = spdif_priv->regmap; | 456 | struct regmap *regmap = spdif_priv->regmap; |
457 | u32 scr, mask, i; | 457 | u32 scr, mask; |
458 | int i; | ||
458 | int ret; | 459 | int ret; |
459 | 460 | ||
460 | /* Reset module and interrupts only for first initialization */ | 461 | /* Reset module and interrupts only for first initialization */ |
@@ -482,13 +483,18 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream, | |||
482 | mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | | 483 | mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | |
483 | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | | 484 | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | |
484 | SCR_TXFIFO_FSEL_MASK; | 485 | SCR_TXFIFO_FSEL_MASK; |
485 | for (i = 0; i < SPDIF_TXRATE_MAX; i++) | 486 | for (i = 0; i < SPDIF_TXRATE_MAX; i++) { |
486 | clk_prepare_enable(spdif_priv->txclk[i]); | 487 | ret = clk_prepare_enable(spdif_priv->txclk[i]); |
488 | if (ret) | ||
489 | goto disable_txclk; | ||
490 | } | ||
487 | } else { | 491 | } else { |
488 | scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC; | 492 | scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC; |
489 | mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| | 493 | mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| |
490 | SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; | 494 | SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; |
491 | clk_prepare_enable(spdif_priv->rxclk); | 495 | ret = clk_prepare_enable(spdif_priv->rxclk); |
496 | if (ret) | ||
497 | goto err; | ||
492 | } | 498 | } |
493 | regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); | 499 | regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); |
494 | 500 | ||
@@ -497,6 +503,9 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream, | |||
497 | 503 | ||
498 | return 0; | 504 | return 0; |
499 | 505 | ||
506 | disable_txclk: | ||
507 | for (i--; i >= 0; i--) | ||
508 | clk_disable_unprepare(spdif_priv->txclk[i]); | ||
500 | err: | 509 | err: |
501 | clk_disable_unprepare(spdif_priv->coreclk); | 510 | clk_disable_unprepare(spdif_priv->coreclk); |
502 | 511 | ||
@@ -707,7 +716,7 @@ static int fsl_spdif_subcode_get(struct snd_kcontrol *kcontrol, | |||
707 | return ret; | 716 | return ret; |
708 | } | 717 | } |
709 | 718 | ||
710 | /* Q-subcode infomation. The byte size is SPDIF_UBITS_SIZE/8 */ | 719 | /* Q-subcode information. The byte size is SPDIF_UBITS_SIZE/8 */ |
711 | static int fsl_spdif_qinfo(struct snd_kcontrol *kcontrol, | 720 | static int fsl_spdif_qinfo(struct snd_kcontrol *kcontrol, |
712 | struct snd_ctl_elem_info *uinfo) | 721 | struct snd_ctl_elem_info *uinfo) |
713 | { | 722 | { |
@@ -739,7 +748,7 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol, | |||
739 | return ret; | 748 | return ret; |
740 | } | 749 | } |
741 | 750 | ||
742 | /* Valid bit infomation */ | 751 | /* Valid bit information */ |
743 | static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol, | 752 | static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol, |
744 | struct snd_ctl_elem_info *uinfo) | 753 | struct snd_ctl_elem_info *uinfo) |
745 | { | 754 | { |
@@ -767,7 +776,7 @@ static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol, | |||
767 | return 0; | 776 | return 0; |
768 | } | 777 | } |
769 | 778 | ||
770 | /* DPLL lock infomation */ | 779 | /* DPLL lock information */ |
771 | static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol, | 780 | static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol, |
772 | struct snd_ctl_elem_info *uinfo) | 781 | struct snd_ctl_elem_info *uinfo) |
773 | { | 782 | { |
@@ -1255,7 +1264,7 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1255 | return ret; | 1264 | return ret; |
1256 | } | 1265 | } |
1257 | 1266 | ||
1258 | ret = imx_pcm_dma_init(pdev); | 1267 | ret = imx_pcm_dma_init(pdev, IMX_SPDIF_DMABUF_SIZE); |
1259 | if (ret) | 1268 | if (ret) |
1260 | dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret); | 1269 | dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret); |
1261 | 1270 | ||
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index c0b940e2019f..8ec6fb208ea0 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -156,7 +156,7 @@ struct fsl_ssi_soc_data { | |||
156 | * | 156 | * |
157 | * @dbg_stats: Debugging statistics | 157 | * @dbg_stats: Debugging statistics |
158 | * | 158 | * |
159 | * @soc: SoC specifc data | 159 | * @soc: SoC specific data |
160 | */ | 160 | */ |
161 | struct fsl_ssi_private { | 161 | struct fsl_ssi_private { |
162 | struct regmap *regs; | 162 | struct regmap *regs; |
@@ -900,14 +900,16 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev, | |||
900 | scr &= ~CCSR_SSI_SCR_SYS_CLK_EN; | 900 | scr &= ~CCSR_SSI_SCR_SYS_CLK_EN; |
901 | break; | 901 | break; |
902 | default: | 902 | default: |
903 | return -EINVAL; | 903 | if (!fsl_ssi_is_ac97(ssi_private)) |
904 | return -EINVAL; | ||
904 | } | 905 | } |
905 | 906 | ||
906 | stcr |= strcr; | 907 | stcr |= strcr; |
907 | srcr |= strcr; | 908 | srcr |= strcr; |
908 | 909 | ||
909 | if (ssi_private->cpu_dai_drv.symmetric_rates) { | 910 | if (ssi_private->cpu_dai_drv.symmetric_rates |
910 | /* Need to clear RXDIR when using SYNC mode */ | 911 | || fsl_ssi_is_ac97(ssi_private)) { |
912 | /* Need to clear RXDIR when using SYNC or AC97 mode */ | ||
911 | srcr &= ~CCSR_SSI_SRCR_RXDIR; | 913 | srcr &= ~CCSR_SSI_SRCR_RXDIR; |
912 | scr |= CCSR_SSI_SCR_SYN; | 914 | scr |= CCSR_SSI_SCR_SYN; |
913 | } | 915 | } |
@@ -1101,6 +1103,7 @@ static const struct snd_soc_component_driver fsl_ssi_component = { | |||
1101 | 1103 | ||
1102 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { | 1104 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { |
1103 | .bus_control = true, | 1105 | .bus_control = true, |
1106 | .probe = fsl_ssi_dai_probe, | ||
1104 | .playback = { | 1107 | .playback = { |
1105 | .stream_name = "AC97 Playback", | 1108 | .stream_name = "AC97 Playback", |
1106 | .channels_min = 2, | 1109 | .channels_min = 2, |
@@ -1127,10 +1130,17 @@ static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
1127 | struct regmap *regs = fsl_ac97_data->regs; | 1130 | struct regmap *regs = fsl_ac97_data->regs; |
1128 | unsigned int lreg; | 1131 | unsigned int lreg; |
1129 | unsigned int lval; | 1132 | unsigned int lval; |
1133 | int ret; | ||
1130 | 1134 | ||
1131 | if (reg > 0x7f) | 1135 | if (reg > 0x7f) |
1132 | return; | 1136 | return; |
1133 | 1137 | ||
1138 | ret = clk_prepare_enable(fsl_ac97_data->clk); | ||
1139 | if (ret) { | ||
1140 | pr_err("ac97 write clk_prepare_enable failed: %d\n", | ||
1141 | ret); | ||
1142 | return; | ||
1143 | } | ||
1134 | 1144 | ||
1135 | lreg = reg << 12; | 1145 | lreg = reg << 12; |
1136 | regmap_write(regs, CCSR_SSI_SACADD, lreg); | 1146 | regmap_write(regs, CCSR_SSI_SACADD, lreg); |
@@ -1141,6 +1151,8 @@ static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
1141 | regmap_update_bits(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_RDWR_MASK, | 1151 | regmap_update_bits(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_RDWR_MASK, |
1142 | CCSR_SSI_SACNT_WR); | 1152 | CCSR_SSI_SACNT_WR); |
1143 | udelay(100); | 1153 | udelay(100); |
1154 | |||
1155 | clk_disable_unprepare(fsl_ac97_data->clk); | ||
1144 | } | 1156 | } |
1145 | 1157 | ||
1146 | static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, | 1158 | static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, |
@@ -1151,6 +1163,14 @@ static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, | |||
1151 | unsigned short val = -1; | 1163 | unsigned short val = -1; |
1152 | u32 reg_val; | 1164 | u32 reg_val; |
1153 | unsigned int lreg; | 1165 | unsigned int lreg; |
1166 | int ret; | ||
1167 | |||
1168 | ret = clk_prepare_enable(fsl_ac97_data->clk); | ||
1169 | if (ret) { | ||
1170 | pr_err("ac97 read clk_prepare_enable failed: %d\n", | ||
1171 | ret); | ||
1172 | return -1; | ||
1173 | } | ||
1154 | 1174 | ||
1155 | lreg = (reg & 0x7f) << 12; | 1175 | lreg = (reg & 0x7f) << 12; |
1156 | regmap_write(regs, CCSR_SSI_SACADD, lreg); | 1176 | regmap_write(regs, CCSR_SSI_SACADD, lreg); |
@@ -1162,6 +1182,8 @@ static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, | |||
1162 | regmap_read(regs, CCSR_SSI_SACDAT, ®_val); | 1182 | regmap_read(regs, CCSR_SSI_SACDAT, ®_val); |
1163 | val = (reg_val >> 4) & 0xffff; | 1183 | val = (reg_val >> 4) & 0xffff; |
1164 | 1184 | ||
1185 | clk_disable_unprepare(fsl_ac97_data->clk); | ||
1186 | |||
1165 | return val; | 1187 | return val; |
1166 | } | 1188 | } |
1167 | 1189 | ||
@@ -1210,7 +1232,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev, | |||
1210 | } | 1232 | } |
1211 | } | 1233 | } |
1212 | 1234 | ||
1213 | /* For those SLAVE implementations, we ingore non-baudclk cases | 1235 | /* For those SLAVE implementations, we ignore non-baudclk cases |
1214 | * and, instead, abandon MASTER mode that needs baud clock. | 1236 | * and, instead, abandon MASTER mode that needs baud clock. |
1215 | */ | 1237 | */ |
1216 | ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud"); | 1238 | ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud"); |
@@ -1257,7 +1279,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev, | |||
1257 | if (ret) | 1279 | if (ret) |
1258 | goto error_pcm; | 1280 | goto error_pcm; |
1259 | } else { | 1281 | } else { |
1260 | ret = imx_pcm_dma_init(pdev); | 1282 | ret = imx_pcm_dma_init(pdev, IMX_SSI_DMABUF_SIZE); |
1261 | if (ret) | 1283 | if (ret) |
1262 | goto error_pcm; | 1284 | goto error_pcm; |
1263 | } | 1285 | } |
@@ -1320,7 +1342,11 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1320 | 1342 | ||
1321 | fsl_ac97_data = ssi_private; | 1343 | fsl_ac97_data = ssi_private; |
1322 | 1344 | ||
1323 | snd_soc_set_ac97_ops_of_reset(&fsl_ssi_ac97_ops, pdev); | 1345 | ret = snd_soc_set_ac97_ops_of_reset(&fsl_ssi_ac97_ops, pdev); |
1346 | if (ret) { | ||
1347 | dev_err(&pdev->dev, "could not set AC'97 ops\n"); | ||
1348 | return ret; | ||
1349 | } | ||
1324 | } else { | 1350 | } else { |
1325 | /* Initialize this copy of the CPU DAI driver structure */ | 1351 | /* Initialize this copy of the CPU DAI driver structure */ |
1326 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, | 1352 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, |
@@ -1357,7 +1383,9 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1357 | 1383 | ||
1358 | /* Are the RX and the TX clocks locked? */ | 1384 | /* Are the RX and the TX clocks locked? */ |
1359 | if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { | 1385 | if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { |
1360 | ssi_private->cpu_dai_drv.symmetric_rates = 1; | 1386 | if (!fsl_ssi_is_ac97(ssi_private)) |
1387 | ssi_private->cpu_dai_drv.symmetric_rates = 1; | ||
1388 | |||
1361 | ssi_private->cpu_dai_drv.symmetric_channels = 1; | 1389 | ssi_private->cpu_dai_drv.symmetric_channels = 1; |
1362 | ssi_private->cpu_dai_drv.symmetric_samplebits = 1; | 1390 | ssi_private->cpu_dai_drv.symmetric_samplebits = 1; |
1363 | } | 1391 | } |
@@ -1434,6 +1462,27 @@ done: | |||
1434 | _fsl_ssi_set_dai_fmt(&pdev->dev, ssi_private, | 1462 | _fsl_ssi_set_dai_fmt(&pdev->dev, ssi_private, |
1435 | ssi_private->dai_fmt); | 1463 | ssi_private->dai_fmt); |
1436 | 1464 | ||
1465 | if (fsl_ssi_is_ac97(ssi_private)) { | ||
1466 | u32 ssi_idx; | ||
1467 | |||
1468 | ret = of_property_read_u32(np, "cell-index", &ssi_idx); | ||
1469 | if (ret) { | ||
1470 | dev_err(&pdev->dev, "cannot get SSI index property\n"); | ||
1471 | goto error_sound_card; | ||
1472 | } | ||
1473 | |||
1474 | ssi_private->pdev = | ||
1475 | platform_device_register_data(NULL, | ||
1476 | "ac97-codec", ssi_idx, NULL, 0); | ||
1477 | if (IS_ERR(ssi_private->pdev)) { | ||
1478 | ret = PTR_ERR(ssi_private->pdev); | ||
1479 | dev_err(&pdev->dev, | ||
1480 | "failed to register AC97 codec platform: %d\n", | ||
1481 | ret); | ||
1482 | goto error_sound_card; | ||
1483 | } | ||
1484 | } | ||
1485 | |||
1437 | return 0; | 1486 | return 0; |
1438 | 1487 | ||
1439 | error_sound_card: | 1488 | error_sound_card: |
@@ -1458,6 +1507,9 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
1458 | if (ssi_private->soc->imx) | 1507 | if (ssi_private->soc->imx) |
1459 | fsl_ssi_imx_clean(pdev, ssi_private); | 1508 | fsl_ssi_imx_clean(pdev, ssi_private); |
1460 | 1509 | ||
1510 | if (fsl_ssi_is_ac97(ssi_private)) | ||
1511 | snd_soc_set_ac97_ops(NULL); | ||
1512 | |||
1461 | return 0; | 1513 | return 0; |
1462 | } | 1514 | } |
1463 | 1515 | ||
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index 0db94f492e97..1fc01ed3279d 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
@@ -40,7 +40,7 @@ static const struct snd_pcm_hardware imx_pcm_hardware = { | |||
40 | SNDRV_PCM_INFO_MMAP_VALID | | 40 | SNDRV_PCM_INFO_MMAP_VALID | |
41 | SNDRV_PCM_INFO_PAUSE | | 41 | SNDRV_PCM_INFO_PAUSE | |
42 | SNDRV_PCM_INFO_RESUME, | 42 | SNDRV_PCM_INFO_RESUME, |
43 | .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, | 43 | .buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE, |
44 | .period_bytes_min = 128, | 44 | .period_bytes_min = 128, |
45 | .period_bytes_max = 65535, /* Limited by SDMA engine */ | 45 | .period_bytes_max = 65535, /* Limited by SDMA engine */ |
46 | .periods_min = 2, | 46 | .periods_min = 2, |
@@ -52,13 +52,30 @@ static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = { | |||
52 | .pcm_hardware = &imx_pcm_hardware, | 52 | .pcm_hardware = &imx_pcm_hardware, |
53 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, | 53 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, |
54 | .compat_filter_fn = filter, | 54 | .compat_filter_fn = filter, |
55 | .prealloc_buffer_size = IMX_SSI_DMABUF_SIZE, | 55 | .prealloc_buffer_size = IMX_DEFAULT_DMABUF_SIZE, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | int imx_pcm_dma_init(struct platform_device *pdev) | 58 | int imx_pcm_dma_init(struct platform_device *pdev, size_t size) |
59 | { | 59 | { |
60 | struct snd_dmaengine_pcm_config *config; | ||
61 | struct snd_pcm_hardware *pcm_hardware; | ||
62 | |||
63 | config = devm_kzalloc(&pdev->dev, | ||
64 | sizeof(struct snd_dmaengine_pcm_config), GFP_KERNEL); | ||
65 | *config = imx_dmaengine_pcm_config; | ||
66 | if (size) | ||
67 | config->prealloc_buffer_size = size; | ||
68 | |||
69 | pcm_hardware = devm_kzalloc(&pdev->dev, | ||
70 | sizeof(struct snd_pcm_hardware), GFP_KERNEL); | ||
71 | *pcm_hardware = imx_pcm_hardware; | ||
72 | if (size) | ||
73 | pcm_hardware->buffer_bytes_max = size; | ||
74 | |||
75 | config->pcm_hardware = pcm_hardware; | ||
76 | |||
60 | return devm_snd_dmaengine_pcm_register(&pdev->dev, | 77 | return devm_snd_dmaengine_pcm_register(&pdev->dev, |
61 | &imx_dmaengine_pcm_config, | 78 | config, |
62 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 79 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
63 | } | 80 | } |
64 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); | 81 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); |
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h index c79cb27473be..133c4470acad 100644 --- a/sound/soc/fsl/imx-pcm.h +++ b/sound/soc/fsl/imx-pcm.h | |||
@@ -20,6 +20,11 @@ | |||
20 | */ | 20 | */ |
21 | #define IMX_SSI_DMABUF_SIZE (64 * 1024) | 21 | #define IMX_SSI_DMABUF_SIZE (64 * 1024) |
22 | 22 | ||
23 | #define IMX_DEFAULT_DMABUF_SIZE (64 * 1024) | ||
24 | #define IMX_SAI_DMABUF_SIZE (64 * 1024) | ||
25 | #define IMX_SPDIF_DMABUF_SIZE (64 * 1024) | ||
26 | #define IMX_ESAI_DMABUF_SIZE (256 * 1024) | ||
27 | |||
23 | static inline void | 28 | static inline void |
24 | imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data, | 29 | imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data, |
25 | int dma, enum sdma_peripheral_type peripheral_type) | 30 | int dma, enum sdma_peripheral_type peripheral_type) |
@@ -39,9 +44,9 @@ struct imx_pcm_fiq_params { | |||
39 | }; | 44 | }; |
40 | 45 | ||
41 | #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA) | 46 | #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA) |
42 | int imx_pcm_dma_init(struct platform_device *pdev); | 47 | int imx_pcm_dma_init(struct platform_device *pdev, size_t size); |
43 | #else | 48 | #else |
44 | static inline int imx_pcm_dma_init(struct platform_device *pdev) | 49 | static inline int imx_pcm_dma_init(struct platform_device *pdev, size_t size) |
45 | { | 50 | { |
46 | return -ENODEV; | 51 | return -ENODEV; |
47 | } | 52 | } |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 461ce27b884f..48b2d24dd1f0 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -603,7 +603,7 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
603 | ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx; | 603 | ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx; |
604 | 604 | ||
605 | ssi->fiq_init = imx_pcm_fiq_init(pdev, &ssi->fiq_params); | 605 | ssi->fiq_init = imx_pcm_fiq_init(pdev, &ssi->fiq_params); |
606 | ssi->dma_init = imx_pcm_dma_init(pdev); | 606 | ssi->dma_init = imx_pcm_dma_init(pdev, IMX_SSI_DMABUF_SIZE); |
607 | 607 | ||
608 | if (ssi->fiq_init && ssi->dma_init) { | 608 | if (ssi->fiq_init && ssi->dma_init) { |
609 | ret = ssi->fiq_init; | 609 | ret = ssi->fiq_init; |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index d5554939146e..3ff76d419436 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -76,6 +76,7 @@ static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, | |||
76 | { | 76 | { |
77 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 77 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
78 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 78 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
79 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
79 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | 80 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
80 | struct simple_dai_props *dai_props = | 81 | struct simple_dai_props *dai_props = |
81 | &priv->dai_props[rtd - rtd->card->rtd]; | 82 | &priv->dai_props[rtd - rtd->card->rtd]; |
@@ -91,8 +92,16 @@ static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, | |||
91 | mclk = params_rate(params) * mclk_fs; | 92 | mclk = params_rate(params) * mclk_fs; |
92 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | 93 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, |
93 | SND_SOC_CLOCK_IN); | 94 | SND_SOC_CLOCK_IN); |
95 | if (ret && ret != -ENOTSUPP) | ||
96 | goto err; | ||
97 | |||
98 | ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, | ||
99 | SND_SOC_CLOCK_OUT); | ||
100 | if (ret && ret != -ENOTSUPP) | ||
101 | goto err; | ||
94 | } | 102 | } |
95 | 103 | ||
104 | err: | ||
96 | return ret; | 105 | return ret; |
97 | } | 106 | } |
98 | 107 | ||
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index f3060a4ca040..05fde5e6e257 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -26,14 +26,9 @@ config SND_SST_IPC_ACPI | |||
26 | depends on ACPI | 26 | depends on ACPI |
27 | 27 | ||
28 | config SND_SOC_INTEL_SST | 28 | config SND_SOC_INTEL_SST |
29 | tristate "ASoC support for Intel(R) Smart Sound Technology" | 29 | tristate |
30 | select SND_SOC_INTEL_SST_ACPI if ACPI | 30 | select SND_SOC_INTEL_SST_ACPI if ACPI |
31 | depends on (X86 || COMPILE_TEST) | 31 | depends on (X86 || COMPILE_TEST) |
32 | depends on DW_DMAC_CORE | ||
33 | help | ||
34 | This adds support for Intel(R) Smart Sound Technology (SST). | ||
35 | Say Y if you have such a device | ||
36 | If unsure select "N". | ||
37 | 32 | ||
38 | config SND_SOC_INTEL_SST_ACPI | 33 | config SND_SOC_INTEL_SST_ACPI |
39 | tristate | 34 | tristate |
@@ -46,8 +41,9 @@ config SND_SOC_INTEL_BAYTRAIL | |||
46 | 41 | ||
47 | config SND_SOC_INTEL_HASWELL_MACH | 42 | config SND_SOC_INTEL_HASWELL_MACH |
48 | tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" | 43 | tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" |
49 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C && \ | 44 | depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM |
50 | I2C_DESIGNWARE_PLATFORM | 45 | depends on DW_DMAC_CORE |
46 | select SND_SOC_INTEL_SST | ||
51 | select SND_SOC_INTEL_HASWELL | 47 | select SND_SOC_INTEL_HASWELL |
52 | select SND_SOC_RT5640 | 48 | select SND_SOC_RT5640 |
53 | help | 49 | help |
@@ -58,7 +54,9 @@ config SND_SOC_INTEL_HASWELL_MACH | |||
58 | 54 | ||
59 | config SND_SOC_INTEL_BYT_RT5640_MACH | 55 | config SND_SOC_INTEL_BYT_RT5640_MACH |
60 | tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" | 56 | tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" |
61 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C | 57 | depends on X86_INTEL_LPSS && I2C |
58 | depends on DW_DMAC_CORE | ||
59 | select SND_SOC_INTEL_SST | ||
62 | select SND_SOC_INTEL_BAYTRAIL | 60 | select SND_SOC_INTEL_BAYTRAIL |
63 | select SND_SOC_RT5640 | 61 | select SND_SOC_RT5640 |
64 | help | 62 | help |
@@ -67,7 +65,9 @@ config SND_SOC_INTEL_BYT_RT5640_MACH | |||
67 | 65 | ||
68 | config SND_SOC_INTEL_BYT_MAX98090_MACH | 66 | config SND_SOC_INTEL_BYT_MAX98090_MACH |
69 | tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec" | 67 | tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec" |
70 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C | 68 | depends on X86_INTEL_LPSS && I2C |
69 | depends on DW_DMAC_CORE | ||
70 | select SND_SOC_INTEL_SST | ||
71 | select SND_SOC_INTEL_BAYTRAIL | 71 | select SND_SOC_INTEL_BAYTRAIL |
72 | select SND_SOC_MAX98090 | 72 | select SND_SOC_MAX98090 |
73 | help | 73 | help |
@@ -76,8 +76,10 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH | |||
76 | 76 | ||
77 | config SND_SOC_INTEL_BROADWELL_MACH | 77 | config SND_SOC_INTEL_BROADWELL_MACH |
78 | tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" | 78 | tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" |
79 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC && \ | 79 | depends on X86_INTEL_LPSS && I2C && DW_DMAC && \ |
80 | I2C_DESIGNWARE_PLATFORM | 80 | I2C_DESIGNWARE_PLATFORM |
81 | depends on DW_DMAC_CORE | ||
82 | select SND_SOC_INTEL_SST | ||
81 | select SND_SOC_INTEL_HASWELL | 83 | select SND_SOC_INTEL_HASWELL |
82 | select SND_SOC_RT286 | 84 | select SND_SOC_RT286 |
83 | help | 85 | help |
@@ -132,3 +134,8 @@ config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH | |||
132 | This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell | 134 | This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell |
133 | platforms with MAX98090 audio codec it also can support TI jack chip as aux device. | 135 | platforms with MAX98090 audio codec it also can support TI jack chip as aux device. |
134 | If unsure select "N". | 136 | If unsure select "N". |
137 | |||
138 | config SND_SOC_INTEL_SKYLAKE | ||
139 | tristate | ||
140 | select SND_HDA_EXT_CORE | ||
141 | select SND_SOC_INTEL_SST | ||
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 6de5d5cd3280..2b45435e6245 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -5,6 +5,7 @@ obj-$(CONFIG_SND_SOC_INTEL_SST) += common/ | |||
5 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/ | 5 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/ |
6 | obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/ | 6 | obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/ |
7 | obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += atom/ | 7 | obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += atom/ |
8 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += skylake/ | ||
8 | 9 | ||
9 | # Machine support | 10 | # Machine support |
10 | obj-$(CONFIG_SND_SOC) += boards/ | 11 | obj-$(CONFIG_SND_SOC) += boards/ |
diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 31e9b9ecbb8a..d55388e082e1 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c | |||
@@ -132,7 +132,7 @@ static int sst_send_slot_map(struct sst_data *drv) | |||
132 | sizeof(cmd.header) + cmd.header.length); | 132 | sizeof(cmd.header) + cmd.header.length); |
133 | } | 133 | } |
134 | 134 | ||
135 | int sst_slot_enum_info(struct snd_kcontrol *kcontrol, | 135 | static int sst_slot_enum_info(struct snd_kcontrol *kcontrol, |
136 | struct snd_ctl_elem_info *uinfo) | 136 | struct snd_ctl_elem_info *uinfo) |
137 | { | 137 | { |
138 | struct sst_enum *e = (struct sst_enum *)kcontrol->private_value; | 138 | struct sst_enum *e = (struct sst_enum *)kcontrol->private_value; |
@@ -1298,7 +1298,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) | |||
1298 | dev_dbg(dai->dev, "Stream name=%s\n", | 1298 | dev_dbg(dai->dev, "Stream name=%s\n", |
1299 | dai->playback_widget->name); | 1299 | dai->playback_widget->name); |
1300 | w = dai->playback_widget; | 1300 | w = dai->playback_widget; |
1301 | list_for_each_entry(p, &w->sinks, list_source) { | 1301 | snd_soc_dapm_widget_for_each_sink_path(w, p) { |
1302 | if (p->connected && !p->connected(w, p->sink)) | 1302 | if (p->connected && !p->connected(w, p->sink)) |
1303 | continue; | 1303 | continue; |
1304 | 1304 | ||
@@ -1317,7 +1317,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) | |||
1317 | dev_dbg(dai->dev, "Stream name=%s\n", | 1317 | dev_dbg(dai->dev, "Stream name=%s\n", |
1318 | dai->capture_widget->name); | 1318 | dai->capture_widget->name); |
1319 | w = dai->capture_widget; | 1319 | w = dai->capture_widget; |
1320 | list_for_each_entry(p, &w->sources, list_sink) { | 1320 | snd_soc_dapm_widget_for_each_source_path(w, p) { |
1321 | if (p->connected && !p->connected(w, p->sink)) | 1321 | if (p->connected && !p->connected(w, p->sink)) |
1322 | continue; | 1322 | continue; |
1323 | 1323 | ||
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 641ebe61dc08..683e50116152 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c | |||
@@ -33,7 +33,6 @@ | |||
33 | 33 | ||
34 | struct sst_device *sst; | 34 | struct sst_device *sst; |
35 | static DEFINE_MUTEX(sst_lock); | 35 | static DEFINE_MUTEX(sst_lock); |
36 | extern struct snd_compr_ops sst_platform_compr_ops; | ||
37 | 36 | ||
38 | int sst_register_dsp(struct sst_device *dev) | 37 | int sst_register_dsp(struct sst_device *dev) |
39 | { | 38 | { |
diff --git a/sound/soc/intel/atom/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h index 2409b23eeacf..cb32cc7e5ec1 100644 --- a/sound/soc/intel/atom/sst-mfld-platform.h +++ b/sound/soc/intel/atom/sst-mfld-platform.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "sst-atom-controls.h" | 25 | #include "sst-atom-controls.h" |
26 | 26 | ||
27 | extern struct sst_device *sst; | 27 | extern struct sst_device *sst; |
28 | extern struct snd_compr_ops sst_platform_compr_ops; | ||
28 | 29 | ||
29 | #define SST_MONO 1 | 30 | #define SST_MONO 1 |
30 | #define SST_STEREO 2 | 31 | #define SST_STEREO 2 |
diff --git a/sound/soc/intel/atom/sst/sst_drv_interface.c b/sound/soc/intel/atom/sst/sst_drv_interface.c index 0e0e4d9c021f..ce689c5af5ab 100644 --- a/sound/soc/intel/atom/sst/sst_drv_interface.c +++ b/sound/soc/intel/atom/sst/sst_drv_interface.c | |||
@@ -151,6 +151,7 @@ static int sst_power_control(struct device *dev, bool state) | |||
151 | usage_count = GET_USAGE_COUNT(dev); | 151 | usage_count = GET_USAGE_COUNT(dev); |
152 | dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count); | 152 | dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count); |
153 | if (ret < 0) { | 153 | if (ret < 0) { |
154 | pm_runtime_put_sync(dev); | ||
154 | dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret); | 155 | dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret); |
155 | return ret; | 156 | return ret; |
156 | } | 157 | } |
@@ -204,8 +205,10 @@ static int sst_cdev_open(struct device *dev, | |||
204 | struct intel_sst_drv *ctx = dev_get_drvdata(dev); | 205 | struct intel_sst_drv *ctx = dev_get_drvdata(dev); |
205 | 206 | ||
206 | retval = pm_runtime_get_sync(ctx->dev); | 207 | retval = pm_runtime_get_sync(ctx->dev); |
207 | if (retval < 0) | 208 | if (retval < 0) { |
209 | pm_runtime_put_sync(ctx->dev); | ||
208 | return retval; | 210 | return retval; |
211 | } | ||
209 | 212 | ||
210 | str_id = sst_get_stream(ctx, str_params); | 213 | str_id = sst_get_stream(ctx, str_params); |
211 | if (str_id > 0) { | 214 | if (str_id > 0) { |
@@ -672,8 +675,10 @@ static int sst_send_byte_stream(struct device *dev, | |||
672 | if (NULL == bytes) | 675 | if (NULL == bytes) |
673 | return -EINVAL; | 676 | return -EINVAL; |
674 | ret_val = pm_runtime_get_sync(ctx->dev); | 677 | ret_val = pm_runtime_get_sync(ctx->dev); |
675 | if (ret_val < 0) | 678 | if (ret_val < 0) { |
679 | pm_runtime_put_sync(ctx->dev); | ||
676 | return ret_val; | 680 | return ret_val; |
681 | } | ||
677 | 682 | ||
678 | ret_val = sst_send_byte_stream_mrfld(ctx, bytes); | 683 | ret_val = sst_send_byte_stream_mrfld(ctx, bytes); |
679 | sst_pm_runtime_put(ctx); | 684 | sst_pm_runtime_put(ctx); |
diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c index 5a278618466c..3dc7358828b3 100644 --- a/sound/soc/intel/atom/sst/sst_ipc.c +++ b/sound/soc/intel/atom/sst/sst_ipc.c | |||
@@ -352,10 +352,9 @@ void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx, | |||
352 | * copy from mailbox | 352 | * copy from mailbox |
353 | **/ | 353 | **/ |
354 | if (msg_high.part.large) { | 354 | if (msg_high.part.large) { |
355 | data = kzalloc(msg_low, GFP_KERNEL); | 355 | data = kmemdup((void *)msg->mailbox_data, msg_low, GFP_KERNEL); |
356 | if (!data) | 356 | if (!data) |
357 | return; | 357 | return; |
358 | memcpy(data, (void *) msg->mailbox_data, msg_low); | ||
359 | /* Copy command id so that we can use to put sst to reset */ | 358 | /* Copy command id so that we can use to put sst to reset */ |
360 | dsp_hdr = (struct ipc_dsp_hdr *)data; | 359 | dsp_hdr = (struct ipc_dsp_hdr *)data; |
361 | cmd_id = dsp_hdr->cmd_id; | 360 | cmd_id = dsp_hdr->cmd_id; |
diff --git a/sound/soc/intel/boards/byt-max98090.c b/sound/soc/intel/boards/byt-max98090.c index 7ab8cc9fbfd5..d9f81b8d915d 100644 --- a/sound/soc/intel/boards/byt-max98090.c +++ b/sound/soc/intel/boards/byt-max98090.c | |||
@@ -126,6 +126,7 @@ static struct snd_soc_dai_link byt_max98090_dais[] = { | |||
126 | 126 | ||
127 | static struct snd_soc_card byt_max98090_card = { | 127 | static struct snd_soc_card byt_max98090_card = { |
128 | .name = "byt-max98090", | 128 | .name = "byt-max98090", |
129 | .owner = THIS_MODULE, | ||
129 | .dai_link = byt_max98090_dais, | 130 | .dai_link = byt_max98090_dais, |
130 | .num_links = ARRAY_SIZE(byt_max98090_dais), | 131 | .num_links = ARRAY_SIZE(byt_max98090_dais), |
131 | .dapm_widgets = byt_max98090_widgets, | 132 | .dapm_widgets = byt_max98090_widgets, |
diff --git a/sound/soc/intel/boards/byt-rt5640.c b/sound/soc/intel/boards/byt-rt5640.c index ae89b9b966d9..de9788a3fd06 100644 --- a/sound/soc/intel/boards/byt-rt5640.c +++ b/sound/soc/intel/boards/byt-rt5640.c | |||
@@ -197,6 +197,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { | |||
197 | 197 | ||
198 | static struct snd_soc_card byt_rt5640_card = { | 198 | static struct snd_soc_card byt_rt5640_card = { |
199 | .name = "byt-rt5640", | 199 | .name = "byt-rt5640", |
200 | .owner = THIS_MODULE, | ||
200 | .dai_link = byt_rt5640_dais, | 201 | .dai_link = byt_rt5640_dais, |
201 | .num_links = ARRAY_SIZE(byt_rt5640_dais), | 202 | .num_links = ARRAY_SIZE(byt_rt5640_dais), |
202 | .dapm_widgets = byt_rt5640_widgets, | 203 | .dapm_widgets = byt_rt5640_widgets, |
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 7f55d59024a8..c4453120b11a 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c | |||
@@ -185,6 +185,7 @@ static struct snd_soc_dai_link byt_dailink[] = { | |||
185 | /* SoC card */ | 185 | /* SoC card */ |
186 | static struct snd_soc_card snd_soc_card_byt = { | 186 | static struct snd_soc_card snd_soc_card_byt = { |
187 | .name = "baytrailcraudio", | 187 | .name = "baytrailcraudio", |
188 | .owner = THIS_MODULE, | ||
188 | .dai_link = byt_dailink, | 189 | .dai_link = byt_dailink, |
189 | .num_links = ARRAY_SIZE(byt_dailink), | 190 | .num_links = ARRAY_SIZE(byt_dailink), |
190 | .dapm_widgets = byt_dapm_widgets, | 191 | .dapm_widgets = byt_dapm_widgets, |
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 70f832114a5a..49f4869cec48 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c | |||
@@ -104,21 +104,17 @@ static int cht_aif1_hw_params(struct snd_pcm_substream *substream, | |||
104 | static int cht_ti_jack_event(struct notifier_block *nb, | 104 | static int cht_ti_jack_event(struct notifier_block *nb, |
105 | unsigned long event, void *data) | 105 | unsigned long event, void *data) |
106 | { | 106 | { |
107 | |||
108 | struct snd_soc_jack *jack = (struct snd_soc_jack *)data; | 107 | struct snd_soc_jack *jack = (struct snd_soc_jack *)data; |
109 | struct snd_soc_dai *codec_dai = jack->card->rtd->codec_dai; | 108 | struct snd_soc_dapm_context *dapm = &jack->card->dapm; |
110 | struct snd_soc_codec *codec = codec_dai->codec; | ||
111 | 109 | ||
112 | if (event & SND_JACK_MICROPHONE) { | 110 | if (event & SND_JACK_MICROPHONE) { |
113 | 111 | snd_soc_dapm_force_enable_pin(dapm, "SHDN"); | |
114 | snd_soc_dapm_force_enable_pin(&codec->dapm, "SHDN"); | 112 | snd_soc_dapm_force_enable_pin(dapm, "MICBIAS"); |
115 | snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS"); | 113 | snd_soc_dapm_sync(dapm); |
116 | snd_soc_dapm_sync(&codec->dapm); | ||
117 | } else { | 114 | } else { |
118 | 115 | snd_soc_dapm_disable_pin(dapm, "MICBIAS"); | |
119 | snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS"); | 116 | snd_soc_dapm_disable_pin(dapm, "SHDN"); |
120 | snd_soc_dapm_disable_pin(&codec->dapm, "SHDN"); | 117 | snd_soc_dapm_sync(dapm); |
121 | snd_soc_dapm_sync(&codec->dapm); | ||
122 | } | 118 | } |
123 | 119 | ||
124 | return 0; | 120 | return 0; |
@@ -279,6 +275,7 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
279 | /* SoC card */ | 275 | /* SoC card */ |
280 | static struct snd_soc_card snd_soc_card_cht = { | 276 | static struct snd_soc_card snd_soc_card_cht = { |
281 | .name = "chtmax98090", | 277 | .name = "chtmax98090", |
278 | .owner = THIS_MODULE, | ||
282 | .dai_link = cht_dailink, | 279 | .dai_link = cht_dailink, |
283 | .num_links = ARRAY_SIZE(cht_dailink), | 280 | .num_links = ARRAY_SIZE(cht_dailink), |
284 | .aux_dev = &cht_max98090_headset_dev, | 281 | .aux_dev = &cht_max98090_headset_dev, |
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index bdcaf467842a..7be8461e4d3b 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c | |||
@@ -305,6 +305,7 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
305 | /* SoC card */ | 305 | /* SoC card */ |
306 | static struct snd_soc_card snd_soc_card_chtrt5645 = { | 306 | static struct snd_soc_card snd_soc_card_chtrt5645 = { |
307 | .name = "chtrt5645", | 307 | .name = "chtrt5645", |
308 | .owner = THIS_MODULE, | ||
308 | .dai_link = cht_dailink, | 309 | .dai_link = cht_dailink, |
309 | .num_links = ARRAY_SIZE(cht_dailink), | 310 | .num_links = ARRAY_SIZE(cht_dailink), |
310 | .dapm_widgets = cht_dapm_widgets, | 311 | .dapm_widgets = cht_dapm_widgets, |
@@ -317,6 +318,7 @@ static struct snd_soc_card snd_soc_card_chtrt5645 = { | |||
317 | 318 | ||
318 | static struct snd_soc_card snd_soc_card_chtrt5650 = { | 319 | static struct snd_soc_card snd_soc_card_chtrt5650 = { |
319 | .name = "chtrt5650", | 320 | .name = "chtrt5650", |
321 | .owner = THIS_MODULE, | ||
320 | .dai_link = cht_dailink, | 322 | .dai_link = cht_dailink, |
321 | .num_links = ARRAY_SIZE(cht_dailink), | 323 | .num_links = ARRAY_SIZE(cht_dailink), |
322 | .dapm_widgets = cht_dapm_widgets, | 324 | .dapm_widgets = cht_dapm_widgets, |
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 2c9cc5be439e..23fe04075142 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c | |||
@@ -323,6 +323,7 @@ static int cht_resume_post(struct snd_soc_card *card) | |||
323 | /* SoC card */ | 323 | /* SoC card */ |
324 | static struct snd_soc_card snd_soc_card_cht = { | 324 | static struct snd_soc_card snd_soc_card_cht = { |
325 | .name = "cherrytrailcraudio", | 325 | .name = "cherrytrailcraudio", |
326 | .owner = THIS_MODULE, | ||
326 | .dai_link = cht_dailink, | 327 | .dai_link = cht_dailink, |
327 | .num_links = ARRAY_SIZE(cht_dailink), | 328 | .num_links = ARRAY_SIZE(cht_dailink), |
328 | .dapm_widgets = cht_dapm_widgets, | 329 | .dapm_widgets = cht_dapm_widgets, |
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h index 396d54510350..cbd568eac033 100644 --- a/sound/soc/intel/common/sst-dsp-priv.h +++ b/sound/soc/intel/common/sst-dsp-priv.h | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/firmware.h> | 23 | #include <linux/firmware.h> |
24 | 24 | ||
25 | #include "../skylake/skl-sst-dsp.h" | ||
26 | |||
25 | struct sst_mem_block; | 27 | struct sst_mem_block; |
26 | struct sst_module; | 28 | struct sst_module; |
27 | struct sst_fw; | 29 | struct sst_fw; |
@@ -258,6 +260,8 @@ struct sst_mem_block { | |||
258 | */ | 260 | */ |
259 | struct sst_dsp { | 261 | struct sst_dsp { |
260 | 262 | ||
263 | /* Shared for all platforms */ | ||
264 | |||
261 | /* runtime */ | 265 | /* runtime */ |
262 | struct sst_dsp_device *sst_dev; | 266 | struct sst_dsp_device *sst_dev; |
263 | spinlock_t spinlock; /* IPC locking */ | 267 | spinlock_t spinlock; /* IPC locking */ |
@@ -268,10 +272,6 @@ struct sst_dsp { | |||
268 | int irq; | 272 | int irq; |
269 | u32 id; | 273 | u32 id; |
270 | 274 | ||
271 | /* list of free and used ADSP memory blocks */ | ||
272 | struct list_head used_block_list; | ||
273 | struct list_head free_block_list; | ||
274 | |||
275 | /* operations */ | 275 | /* operations */ |
276 | struct sst_ops *ops; | 276 | struct sst_ops *ops; |
277 | 277 | ||
@@ -284,6 +284,12 @@ struct sst_dsp { | |||
284 | /* mailbox */ | 284 | /* mailbox */ |
285 | struct sst_mailbox mailbox; | 285 | struct sst_mailbox mailbox; |
286 | 286 | ||
287 | /* HSW/Byt data */ | ||
288 | |||
289 | /* list of free and used ADSP memory blocks */ | ||
290 | struct list_head used_block_list; | ||
291 | struct list_head free_block_list; | ||
292 | |||
287 | /* SST FW files loaded and their modules */ | 293 | /* SST FW files loaded and their modules */ |
288 | struct list_head module_list; | 294 | struct list_head module_list; |
289 | struct list_head fw_list; | 295 | struct list_head fw_list; |
@@ -299,6 +305,15 @@ struct sst_dsp { | |||
299 | /* DMA FW loading */ | 305 | /* DMA FW loading */ |
300 | struct sst_dma *dma; | 306 | struct sst_dma *dma; |
301 | bool fw_use_dma; | 307 | bool fw_use_dma; |
308 | |||
309 | /* SKL data */ | ||
310 | |||
311 | /* To allocate CL dma buffers */ | ||
312 | struct skl_dsp_loader_ops dsp_ops; | ||
313 | struct skl_dsp_fw_ops fw_ops; | ||
314 | int sst_state; | ||
315 | struct skl_cl_dev cl_dev; | ||
316 | u32 intr_status; | ||
302 | }; | 317 | }; |
303 | 318 | ||
304 | /* Size optimised DRAM/IRAM memcpy */ | 319 | /* Size optimised DRAM/IRAM memcpy */ |
diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c index 64e94212d2d2..a627236dd1f5 100644 --- a/sound/soc/intel/common/sst-dsp.c +++ b/sound/soc/intel/common/sst-dsp.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/delay.h> | ||
23 | 24 | ||
24 | #include "sst-dsp.h" | 25 | #include "sst-dsp.h" |
25 | #include "sst-dsp-priv.h" | 26 | #include "sst-dsp-priv.h" |
@@ -196,6 +197,22 @@ int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, | |||
196 | } | 197 | } |
197 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64_unlocked); | 198 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64_unlocked); |
198 | 199 | ||
200 | /* This is for registers bits with attribute RWC */ | ||
201 | void sst_dsp_shim_update_bits_forced_unlocked(struct sst_dsp *sst, u32 offset, | ||
202 | u32 mask, u32 value) | ||
203 | { | ||
204 | unsigned int old, new; | ||
205 | u32 ret; | ||
206 | |||
207 | ret = sst_dsp_shim_read_unlocked(sst, offset); | ||
208 | |||
209 | old = ret; | ||
210 | new = (old & (~mask)) | (value & mask); | ||
211 | |||
212 | sst_dsp_shim_write_unlocked(sst, offset, new); | ||
213 | } | ||
214 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced_unlocked); | ||
215 | |||
199 | int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset, | 216 | int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset, |
200 | u32 mask, u32 value) | 217 | u32 mask, u32 value) |
201 | { | 218 | { |
@@ -222,6 +239,60 @@ int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, | |||
222 | } | 239 | } |
223 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); | 240 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); |
224 | 241 | ||
242 | /* This is for registers bits with attribute RWC */ | ||
243 | void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset, | ||
244 | u32 mask, u32 value) | ||
245 | { | ||
246 | unsigned long flags; | ||
247 | |||
248 | spin_lock_irqsave(&sst->spinlock, flags); | ||
249 | sst_dsp_shim_update_bits_forced_unlocked(sst, offset, mask, value); | ||
250 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
251 | } | ||
252 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced); | ||
253 | |||
254 | int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask, | ||
255 | u32 target, u32 timeout, char *operation) | ||
256 | { | ||
257 | int time, ret; | ||
258 | u32 reg; | ||
259 | bool done = false; | ||
260 | |||
261 | /* | ||
262 | * we will poll for couple of ms using mdelay, if not successful | ||
263 | * then go to longer sleep using usleep_range | ||
264 | */ | ||
265 | |||
266 | /* check if set state successful */ | ||
267 | for (time = 0; time < 5; time++) { | ||
268 | if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) { | ||
269 | done = true; | ||
270 | break; | ||
271 | } | ||
272 | mdelay(1); | ||
273 | } | ||
274 | |||
275 | if (done == false) { | ||
276 | /* sleeping in 10ms steps so adjust timeout value */ | ||
277 | timeout /= 10; | ||
278 | |||
279 | for (time = 0; time < timeout; time++) { | ||
280 | if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) | ||
281 | break; | ||
282 | |||
283 | usleep_range(5000, 10000); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | reg = sst_dsp_shim_read_unlocked(ctx, offset); | ||
288 | dev_info(ctx->dev, "FW Poll Status: reg=%#x %s %s\n", reg, operation, | ||
289 | (time < timeout) ? "successful" : "timedout"); | ||
290 | ret = time < timeout ? 0 : -ETIME; | ||
291 | |||
292 | return ret; | ||
293 | } | ||
294 | EXPORT_SYMBOL_GPL(sst_dsp_register_poll); | ||
295 | |||
225 | void sst_dsp_dump(struct sst_dsp *sst) | 296 | void sst_dsp_dump(struct sst_dsp *sst) |
226 | { | 297 | { |
227 | if (sst->ops->dump) | 298 | if (sst->ops->dump) |
diff --git a/sound/soc/intel/common/sst-dsp.h b/sound/soc/intel/common/sst-dsp.h index 96aeb2556ad4..1f45f18715c0 100644 --- a/sound/soc/intel/common/sst-dsp.h +++ b/sound/soc/intel/common/sst-dsp.h | |||
@@ -230,6 +230,8 @@ void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value); | |||
230 | u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset); | 230 | u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset); |
231 | int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, | 231 | int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, |
232 | u64 mask, u64 value); | 232 | u64 mask, u64 value); |
233 | void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset, | ||
234 | u32 mask, u32 value); | ||
233 | 235 | ||
234 | /* SHIM Read / Write Unlocked for callers already holding sst lock */ | 236 | /* SHIM Read / Write Unlocked for callers already holding sst lock */ |
235 | void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value); | 237 | void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value); |
@@ -240,6 +242,8 @@ void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value); | |||
240 | u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset); | 242 | u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset); |
241 | int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, | 243 | int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, |
242 | u64 mask, u64 value); | 244 | u64 mask, u64 value); |
245 | void sst_dsp_shim_update_bits_forced_unlocked(struct sst_dsp *sst, u32 offset, | ||
246 | u32 mask, u32 value); | ||
243 | 247 | ||
244 | /* Internal generic low-level SST IO functions - can be overidden */ | 248 | /* Internal generic low-level SST IO functions - can be overidden */ |
245 | void sst_shim32_write(void __iomem *addr, u32 offset, u32 value); | 249 | void sst_shim32_write(void __iomem *addr, u32 offset, u32 value); |
@@ -278,6 +282,8 @@ void sst_dsp_inbox_read(struct sst_dsp *dsp, void *message, size_t bytes); | |||
278 | void sst_dsp_outbox_write(struct sst_dsp *dsp, void *message, size_t bytes); | 282 | void sst_dsp_outbox_write(struct sst_dsp *dsp, void *message, size_t bytes); |
279 | void sst_dsp_outbox_read(struct sst_dsp *dsp, void *message, size_t bytes); | 283 | void sst_dsp_outbox_read(struct sst_dsp *dsp, void *message, size_t bytes); |
280 | void sst_dsp_mailbox_dump(struct sst_dsp *dsp, size_t bytes); | 284 | void sst_dsp_mailbox_dump(struct sst_dsp *dsp, size_t bytes); |
285 | int sst_dsp_register_poll(struct sst_dsp *dsp, u32 offset, u32 mask, | ||
286 | u32 expected_value, u32 timeout, char *operation); | ||
281 | 287 | ||
282 | /* Debug */ | 288 | /* Debug */ |
283 | void sst_dsp_dump(struct sst_dsp *sst); | 289 | void sst_dsp_dump(struct sst_dsp *sst); |
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile new file mode 100644 index 000000000000..27db22178204 --- /dev/null +++ b/sound/soc/intel/skylake/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o | ||
2 | |||
3 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o | ||
4 | |||
5 | # Skylake IPC Support | ||
6 | snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \ | ||
7 | skl-sst.o | ||
8 | |||
9 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o | ||
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c new file mode 100644 index 000000000000..826d4fd8930a --- /dev/null +++ b/sound/soc/intel/skylake/skl-messages.c | |||
@@ -0,0 +1,884 @@ | |||
1 | /* | ||
2 | * skl-message.c - HDA DSP interface for FW registration, Pipe and Module | ||
3 | * configurations | ||
4 | * | ||
5 | * Copyright (C) 2015 Intel Corp | ||
6 | * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> | ||
7 | * Jeeja KP <jeeja.kp@intel.com> | ||
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as version 2, as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | */ | ||
19 | |||
20 | #include <linux/slab.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include "skl-sst-dsp.h" | ||
25 | #include "skl-sst-ipc.h" | ||
26 | #include "skl.h" | ||
27 | #include "../common/sst-dsp.h" | ||
28 | #include "../common/sst-dsp-priv.h" | ||
29 | #include "skl-topology.h" | ||
30 | #include "skl-tplg-interface.h" | ||
31 | |||
32 | static int skl_alloc_dma_buf(struct device *dev, | ||
33 | struct snd_dma_buffer *dmab, size_t size) | ||
34 | { | ||
35 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); | ||
36 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
37 | |||
38 | if (!bus) | ||
39 | return -ENODEV; | ||
40 | |||
41 | return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, size, dmab); | ||
42 | } | ||
43 | |||
44 | static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) | ||
45 | { | ||
46 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); | ||
47 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
48 | |||
49 | if (!bus) | ||
50 | return -ENODEV; | ||
51 | |||
52 | bus->io_ops->dma_free_pages(bus, dmab); | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | int skl_init_dsp(struct skl *skl) | ||
58 | { | ||
59 | void __iomem *mmio_base; | ||
60 | struct hdac_ext_bus *ebus = &skl->ebus; | ||
61 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
62 | int irq = bus->irq; | ||
63 | struct skl_dsp_loader_ops loader_ops; | ||
64 | int ret; | ||
65 | |||
66 | loader_ops.alloc_dma_buf = skl_alloc_dma_buf; | ||
67 | loader_ops.free_dma_buf = skl_free_dma_buf; | ||
68 | |||
69 | /* enable ppcap interrupt */ | ||
70 | snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); | ||
71 | snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); | ||
72 | |||
73 | /* read the BAR of the ADSP MMIO */ | ||
74 | mmio_base = pci_ioremap_bar(skl->pci, 4); | ||
75 | if (mmio_base == NULL) { | ||
76 | dev_err(bus->dev, "ioremap error\n"); | ||
77 | return -ENXIO; | ||
78 | } | ||
79 | |||
80 | ret = skl_sst_dsp_init(bus->dev, mmio_base, irq, | ||
81 | loader_ops, &skl->skl_sst); | ||
82 | |||
83 | dev_dbg(bus->dev, "dsp registration status=%d\n", ret); | ||
84 | |||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | void skl_free_dsp(struct skl *skl) | ||
89 | { | ||
90 | struct hdac_ext_bus *ebus = &skl->ebus; | ||
91 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
92 | struct skl_sst *ctx = skl->skl_sst; | ||
93 | |||
94 | /* disable ppcap interrupt */ | ||
95 | snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); | ||
96 | |||
97 | skl_sst_dsp_cleanup(bus->dev, ctx); | ||
98 | if (ctx->dsp->addr.lpe) | ||
99 | iounmap(ctx->dsp->addr.lpe); | ||
100 | } | ||
101 | |||
102 | int skl_suspend_dsp(struct skl *skl) | ||
103 | { | ||
104 | struct skl_sst *ctx = skl->skl_sst; | ||
105 | int ret; | ||
106 | |||
107 | /* if ppcap is not supported return 0 */ | ||
108 | if (!skl->ebus.ppcap) | ||
109 | return 0; | ||
110 | |||
111 | ret = skl_dsp_sleep(ctx->dsp); | ||
112 | if (ret < 0) | ||
113 | return ret; | ||
114 | |||
115 | /* disable ppcap interrupt */ | ||
116 | snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); | ||
117 | snd_hdac_ext_bus_ppcap_enable(&skl->ebus, false); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | int skl_resume_dsp(struct skl *skl) | ||
123 | { | ||
124 | struct skl_sst *ctx = skl->skl_sst; | ||
125 | |||
126 | /* if ppcap is not supported return 0 */ | ||
127 | if (!skl->ebus.ppcap) | ||
128 | return 0; | ||
129 | |||
130 | /* enable ppcap interrupt */ | ||
131 | snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); | ||
132 | snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); | ||
133 | |||
134 | return skl_dsp_wake(ctx->dsp); | ||
135 | } | ||
136 | |||
137 | enum skl_bitdepth skl_get_bit_depth(int params) | ||
138 | { | ||
139 | switch (params) { | ||
140 | case 8: | ||
141 | return SKL_DEPTH_8BIT; | ||
142 | |||
143 | case 16: | ||
144 | return SKL_DEPTH_16BIT; | ||
145 | |||
146 | case 24: | ||
147 | return SKL_DEPTH_24BIT; | ||
148 | |||
149 | case 32: | ||
150 | return SKL_DEPTH_32BIT; | ||
151 | |||
152 | default: | ||
153 | return SKL_DEPTH_INVALID; | ||
154 | |||
155 | } | ||
156 | } | ||
157 | |||
158 | static u32 skl_create_channel_map(enum skl_ch_cfg ch_cfg) | ||
159 | { | ||
160 | u32 config; | ||
161 | |||
162 | switch (ch_cfg) { | ||
163 | case SKL_CH_CFG_MONO: | ||
164 | config = (0xFFFFFFF0 | SKL_CHANNEL_LEFT); | ||
165 | break; | ||
166 | |||
167 | case SKL_CH_CFG_STEREO: | ||
168 | config = (0xFFFFFF00 | SKL_CHANNEL_LEFT | ||
169 | | (SKL_CHANNEL_RIGHT << 4)); | ||
170 | break; | ||
171 | |||
172 | case SKL_CH_CFG_2_1: | ||
173 | config = (0xFFFFF000 | SKL_CHANNEL_LEFT | ||
174 | | (SKL_CHANNEL_RIGHT << 4) | ||
175 | | (SKL_CHANNEL_LFE << 8)); | ||
176 | break; | ||
177 | |||
178 | case SKL_CH_CFG_3_0: | ||
179 | config = (0xFFFFF000 | SKL_CHANNEL_LEFT | ||
180 | | (SKL_CHANNEL_CENTER << 4) | ||
181 | | (SKL_CHANNEL_RIGHT << 8)); | ||
182 | break; | ||
183 | |||
184 | case SKL_CH_CFG_3_1: | ||
185 | config = (0xFFFF0000 | SKL_CHANNEL_LEFT | ||
186 | | (SKL_CHANNEL_CENTER << 4) | ||
187 | | (SKL_CHANNEL_RIGHT << 8) | ||
188 | | (SKL_CHANNEL_LFE << 12)); | ||
189 | break; | ||
190 | |||
191 | case SKL_CH_CFG_QUATRO: | ||
192 | config = (0xFFFF0000 | SKL_CHANNEL_LEFT | ||
193 | | (SKL_CHANNEL_RIGHT << 4) | ||
194 | | (SKL_CHANNEL_LEFT_SURROUND << 8) | ||
195 | | (SKL_CHANNEL_RIGHT_SURROUND << 12)); | ||
196 | break; | ||
197 | |||
198 | case SKL_CH_CFG_4_0: | ||
199 | config = (0xFFFF0000 | SKL_CHANNEL_LEFT | ||
200 | | (SKL_CHANNEL_CENTER << 4) | ||
201 | | (SKL_CHANNEL_RIGHT << 8) | ||
202 | | (SKL_CHANNEL_CENTER_SURROUND << 12)); | ||
203 | break; | ||
204 | |||
205 | case SKL_CH_CFG_5_0: | ||
206 | config = (0xFFF00000 | SKL_CHANNEL_LEFT | ||
207 | | (SKL_CHANNEL_CENTER << 4) | ||
208 | | (SKL_CHANNEL_RIGHT << 8) | ||
209 | | (SKL_CHANNEL_LEFT_SURROUND << 12) | ||
210 | | (SKL_CHANNEL_RIGHT_SURROUND << 16)); | ||
211 | break; | ||
212 | |||
213 | case SKL_CH_CFG_5_1: | ||
214 | config = (0xFF000000 | SKL_CHANNEL_CENTER | ||
215 | | (SKL_CHANNEL_LEFT << 4) | ||
216 | | (SKL_CHANNEL_RIGHT << 8) | ||
217 | | (SKL_CHANNEL_LEFT_SURROUND << 12) | ||
218 | | (SKL_CHANNEL_RIGHT_SURROUND << 16) | ||
219 | | (SKL_CHANNEL_LFE << 20)); | ||
220 | break; | ||
221 | |||
222 | case SKL_CH_CFG_DUAL_MONO: | ||
223 | config = (0xFFFFFF00 | SKL_CHANNEL_LEFT | ||
224 | | (SKL_CHANNEL_LEFT << 4)); | ||
225 | break; | ||
226 | |||
227 | case SKL_CH_CFG_I2S_DUAL_STEREO_0: | ||
228 | config = (0xFFFFFF00 | SKL_CHANNEL_LEFT | ||
229 | | (SKL_CHANNEL_RIGHT << 4)); | ||
230 | break; | ||
231 | |||
232 | case SKL_CH_CFG_I2S_DUAL_STEREO_1: | ||
233 | config = (0xFFFF00FF | (SKL_CHANNEL_LEFT << 8) | ||
234 | | (SKL_CHANNEL_RIGHT << 12)); | ||
235 | break; | ||
236 | |||
237 | default: | ||
238 | config = 0xFFFFFFFF; | ||
239 | break; | ||
240 | |||
241 | } | ||
242 | |||
243 | return config; | ||
244 | } | ||
245 | |||
246 | /* | ||
247 | * Each module in DSP expects a base module configuration, which consists of | ||
248 | * PCM format information, which we calculate in driver and resource values | ||
249 | * which are read from widget information passed through topology binary | ||
250 | * This is send when we create a module with INIT_INSTANCE IPC msg | ||
251 | */ | ||
252 | static void skl_set_base_module_format(struct skl_sst *ctx, | ||
253 | struct skl_module_cfg *mconfig, | ||
254 | struct skl_base_cfg *base_cfg) | ||
255 | { | ||
256 | struct skl_module_fmt *format = &mconfig->in_fmt; | ||
257 | |||
258 | base_cfg->audio_fmt.number_of_channels = (u8)format->channels; | ||
259 | |||
260 | base_cfg->audio_fmt.s_freq = format->s_freq; | ||
261 | base_cfg->audio_fmt.bit_depth = format->bit_depth; | ||
262 | base_cfg->audio_fmt.valid_bit_depth = format->valid_bit_depth; | ||
263 | base_cfg->audio_fmt.ch_cfg = format->ch_cfg; | ||
264 | |||
265 | dev_dbg(ctx->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n", | ||
266 | format->bit_depth, format->valid_bit_depth, | ||
267 | format->ch_cfg); | ||
268 | |||
269 | base_cfg->audio_fmt.channel_map = skl_create_channel_map( | ||
270 | base_cfg->audio_fmt.ch_cfg); | ||
271 | |||
272 | base_cfg->audio_fmt.interleaving = SKL_INTERLEAVING_PER_CHANNEL; | ||
273 | |||
274 | base_cfg->cps = mconfig->mcps; | ||
275 | base_cfg->ibs = mconfig->ibs; | ||
276 | base_cfg->obs = mconfig->obs; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * Copies copier capabilities into copier module and updates copier module | ||
281 | * config size. | ||
282 | */ | ||
283 | static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, | ||
284 | struct skl_cpr_cfg *cpr_mconfig) | ||
285 | { | ||
286 | if (mconfig->formats_config.caps_size == 0) | ||
287 | return; | ||
288 | |||
289 | memcpy(cpr_mconfig->gtw_cfg.config_data, | ||
290 | mconfig->formats_config.caps, | ||
291 | mconfig->formats_config.caps_size); | ||
292 | |||
293 | cpr_mconfig->gtw_cfg.config_length = | ||
294 | (mconfig->formats_config.caps_size) / 4; | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * Calculate the gatewat settings required for copier module, type of | ||
299 | * gateway and index of gateway to use | ||
300 | */ | ||
301 | static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | ||
302 | struct skl_module_cfg *mconfig, | ||
303 | struct skl_cpr_cfg *cpr_mconfig) | ||
304 | { | ||
305 | union skl_connector_node_id node_id = {0}; | ||
306 | struct skl_pipe_params *params = mconfig->pipe->p_params; | ||
307 | |||
308 | switch (mconfig->dev_type) { | ||
309 | case SKL_DEVICE_BT: | ||
310 | node_id.node.dma_type = | ||
311 | (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? | ||
312 | SKL_DMA_I2S_LINK_OUTPUT_CLASS : | ||
313 | SKL_DMA_I2S_LINK_INPUT_CLASS; | ||
314 | node_id.node.vindex = params->host_dma_id + | ||
315 | (mconfig->vbus_id << 3); | ||
316 | break; | ||
317 | |||
318 | case SKL_DEVICE_I2S: | ||
319 | node_id.node.dma_type = | ||
320 | (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? | ||
321 | SKL_DMA_I2S_LINK_OUTPUT_CLASS : | ||
322 | SKL_DMA_I2S_LINK_INPUT_CLASS; | ||
323 | node_id.node.vindex = params->host_dma_id + | ||
324 | (mconfig->time_slot << 1) + | ||
325 | (mconfig->vbus_id << 3); | ||
326 | break; | ||
327 | |||
328 | case SKL_DEVICE_DMIC: | ||
329 | node_id.node.dma_type = SKL_DMA_DMIC_LINK_INPUT_CLASS; | ||
330 | node_id.node.vindex = mconfig->vbus_id + | ||
331 | (mconfig->time_slot); | ||
332 | break; | ||
333 | |||
334 | case SKL_DEVICE_HDALINK: | ||
335 | node_id.node.dma_type = | ||
336 | (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? | ||
337 | SKL_DMA_HDA_LINK_OUTPUT_CLASS : | ||
338 | SKL_DMA_HDA_LINK_INPUT_CLASS; | ||
339 | node_id.node.vindex = params->link_dma_id; | ||
340 | break; | ||
341 | |||
342 | default: | ||
343 | node_id.node.dma_type = | ||
344 | (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? | ||
345 | SKL_DMA_HDA_HOST_OUTPUT_CLASS : | ||
346 | SKL_DMA_HDA_HOST_INPUT_CLASS; | ||
347 | node_id.node.vindex = params->host_dma_id; | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | cpr_mconfig->gtw_cfg.node_id = node_id.val; | ||
352 | |||
353 | if (SKL_CONN_SOURCE == mconfig->hw_conn_type) | ||
354 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; | ||
355 | else | ||
356 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; | ||
357 | |||
358 | cpr_mconfig->cpr_feature_mask = 0; | ||
359 | cpr_mconfig->gtw_cfg.config_length = 0; | ||
360 | |||
361 | skl_copy_copier_caps(mconfig, cpr_mconfig); | ||
362 | } | ||
363 | |||
364 | static void skl_setup_out_format(struct skl_sst *ctx, | ||
365 | struct skl_module_cfg *mconfig, | ||
366 | struct skl_audio_data_format *out_fmt) | ||
367 | { | ||
368 | struct skl_module_fmt *format = &mconfig->out_fmt; | ||
369 | |||
370 | out_fmt->number_of_channels = (u8)format->channels; | ||
371 | out_fmt->s_freq = format->s_freq; | ||
372 | out_fmt->bit_depth = format->bit_depth; | ||
373 | out_fmt->valid_bit_depth = format->valid_bit_depth; | ||
374 | out_fmt->ch_cfg = format->ch_cfg; | ||
375 | |||
376 | out_fmt->channel_map = skl_create_channel_map(out_fmt->ch_cfg); | ||
377 | out_fmt->interleaving = SKL_INTERLEAVING_PER_CHANNEL; | ||
378 | |||
379 | dev_dbg(ctx->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", | ||
380 | out_fmt->number_of_channels, format->s_freq, format->bit_depth); | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * DSP needs SRC module for frequency conversion, SRC takes base module | ||
385 | * configuration and the target frequency as extra parameter passed as src | ||
386 | * config | ||
387 | */ | ||
388 | static void skl_set_src_format(struct skl_sst *ctx, | ||
389 | struct skl_module_cfg *mconfig, | ||
390 | struct skl_src_module_cfg *src_mconfig) | ||
391 | { | ||
392 | struct skl_module_fmt *fmt = &mconfig->out_fmt; | ||
393 | |||
394 | skl_set_base_module_format(ctx, mconfig, | ||
395 | (struct skl_base_cfg *)src_mconfig); | ||
396 | |||
397 | src_mconfig->src_cfg = fmt->s_freq; | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | * DSP needs updown module to do channel conversion. updown module take base | ||
402 | * module configuration and channel configuration | ||
403 | * It also take coefficients and now we have defaults applied here | ||
404 | */ | ||
405 | static void skl_set_updown_mixer_format(struct skl_sst *ctx, | ||
406 | struct skl_module_cfg *mconfig, | ||
407 | struct skl_up_down_mixer_cfg *mixer_mconfig) | ||
408 | { | ||
409 | struct skl_module_fmt *fmt = &mconfig->out_fmt; | ||
410 | int i = 0; | ||
411 | |||
412 | skl_set_base_module_format(ctx, mconfig, | ||
413 | (struct skl_base_cfg *)mixer_mconfig); | ||
414 | mixer_mconfig->out_ch_cfg = fmt->ch_cfg; | ||
415 | |||
416 | /* Select F/W default coefficient */ | ||
417 | mixer_mconfig->coeff_sel = 0x0; | ||
418 | |||
419 | /* User coeff, don't care since we are selecting F/W defaults */ | ||
420 | for (i = 0; i < UP_DOWN_MIXER_MAX_COEFF; i++) | ||
421 | mixer_mconfig->coeff[i] = 0xDEADBEEF; | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * 'copier' is DSP internal module which copies data from Host DMA (HDA host | ||
426 | * dma) or link (hda link, SSP, PDM) | ||
427 | * Here we calculate the copier module parameters, like PCM format, output | ||
428 | * format, gateway settings | ||
429 | * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg | ||
430 | */ | ||
431 | static void skl_set_copier_format(struct skl_sst *ctx, | ||
432 | struct skl_module_cfg *mconfig, | ||
433 | struct skl_cpr_cfg *cpr_mconfig) | ||
434 | { | ||
435 | struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt; | ||
436 | struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig; | ||
437 | |||
438 | skl_set_base_module_format(ctx, mconfig, base_cfg); | ||
439 | |||
440 | skl_setup_out_format(ctx, mconfig, out_fmt); | ||
441 | skl_setup_cpr_gateway_cfg(ctx, mconfig, cpr_mconfig); | ||
442 | } | ||
443 | |||
444 | static u16 skl_get_module_param_size(struct skl_sst *ctx, | ||
445 | struct skl_module_cfg *mconfig) | ||
446 | { | ||
447 | u16 param_size; | ||
448 | |||
449 | switch (mconfig->m_type) { | ||
450 | case SKL_MODULE_TYPE_COPIER: | ||
451 | param_size = sizeof(struct skl_cpr_cfg); | ||
452 | param_size += mconfig->formats_config.caps_size; | ||
453 | return param_size; | ||
454 | |||
455 | case SKL_MODULE_TYPE_SRCINT: | ||
456 | return sizeof(struct skl_src_module_cfg); | ||
457 | |||
458 | case SKL_MODULE_TYPE_UPDWMIX: | ||
459 | return sizeof(struct skl_up_down_mixer_cfg); | ||
460 | |||
461 | default: | ||
462 | /* | ||
463 | * return only base cfg when no specific module type is | ||
464 | * specified | ||
465 | */ | ||
466 | return sizeof(struct skl_base_cfg); | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * DSP firmware supports various modules like copier, SRC, updown etc. | ||
474 | * These modules required various parameters to be calculated and sent for | ||
475 | * the module initialization to DSP. By default a generic module needs only | ||
476 | * base module format configuration | ||
477 | */ | ||
478 | |||
479 | static int skl_set_module_format(struct skl_sst *ctx, | ||
480 | struct skl_module_cfg *module_config, | ||
481 | u16 *module_config_size, | ||
482 | void **param_data) | ||
483 | { | ||
484 | u16 param_size; | ||
485 | |||
486 | param_size = skl_get_module_param_size(ctx, module_config); | ||
487 | |||
488 | *param_data = kzalloc(param_size, GFP_KERNEL); | ||
489 | if (NULL == *param_data) | ||
490 | return -ENOMEM; | ||
491 | |||
492 | *module_config_size = param_size; | ||
493 | |||
494 | switch (module_config->m_type) { | ||
495 | case SKL_MODULE_TYPE_COPIER: | ||
496 | skl_set_copier_format(ctx, module_config, *param_data); | ||
497 | break; | ||
498 | |||
499 | case SKL_MODULE_TYPE_SRCINT: | ||
500 | skl_set_src_format(ctx, module_config, *param_data); | ||
501 | break; | ||
502 | |||
503 | case SKL_MODULE_TYPE_UPDWMIX: | ||
504 | skl_set_updown_mixer_format(ctx, module_config, *param_data); | ||
505 | break; | ||
506 | |||
507 | default: | ||
508 | skl_set_base_module_format(ctx, module_config, *param_data); | ||
509 | break; | ||
510 | |||
511 | } | ||
512 | |||
513 | dev_dbg(ctx->dev, "Module type=%d config size: %d bytes\n", | ||
514 | module_config->id.module_id, param_size); | ||
515 | print_hex_dump(KERN_DEBUG, "Module params:", DUMP_PREFIX_OFFSET, 8, 4, | ||
516 | *param_data, param_size, false); | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static int skl_get_queue_index(struct skl_module_pin *mpin, | ||
521 | struct skl_module_inst_id id, int max) | ||
522 | { | ||
523 | int i; | ||
524 | |||
525 | for (i = 0; i < max; i++) { | ||
526 | if (mpin[i].id.module_id == id.module_id && | ||
527 | mpin[i].id.instance_id == id.instance_id) | ||
528 | return i; | ||
529 | } | ||
530 | |||
531 | return -EINVAL; | ||
532 | } | ||
533 | |||
534 | /* | ||
535 | * Allocates queue for each module. | ||
536 | * if dynamic, the pin_index is allocated 0 to max_pin. | ||
537 | * In static, the pin_index is fixed based on module_id and instance id | ||
538 | */ | ||
539 | static int skl_alloc_queue(struct skl_module_pin *mpin, | ||
540 | struct skl_module_inst_id id, int max) | ||
541 | { | ||
542 | int i; | ||
543 | |||
544 | /* | ||
545 | * if pin in dynamic, find first free pin | ||
546 | * otherwise find match module and instance id pin as topology will | ||
547 | * ensure a unique pin is assigned to this so no need to | ||
548 | * allocate/free | ||
549 | */ | ||
550 | for (i = 0; i < max; i++) { | ||
551 | if (mpin[i].is_dynamic) { | ||
552 | if (!mpin[i].in_use) { | ||
553 | mpin[i].in_use = true; | ||
554 | mpin[i].id.module_id = id.module_id; | ||
555 | mpin[i].id.instance_id = id.instance_id; | ||
556 | return i; | ||
557 | } | ||
558 | } else { | ||
559 | if (mpin[i].id.module_id == id.module_id && | ||
560 | mpin[i].id.instance_id == id.instance_id) | ||
561 | return i; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | return -EINVAL; | ||
566 | } | ||
567 | |||
568 | static void skl_free_queue(struct skl_module_pin *mpin, int q_index) | ||
569 | { | ||
570 | if (mpin[q_index].is_dynamic) { | ||
571 | mpin[q_index].in_use = false; | ||
572 | mpin[q_index].id.module_id = 0; | ||
573 | mpin[q_index].id.instance_id = 0; | ||
574 | } | ||
575 | } | ||
576 | |||
577 | /* | ||
578 | * A module needs to be instanataited in DSP. A mdoule is present in a | ||
579 | * collection of module referred as a PIPE. | ||
580 | * We first calculate the module format, based on module type and then | ||
581 | * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper | ||
582 | */ | ||
583 | int skl_init_module(struct skl_sst *ctx, | ||
584 | struct skl_module_cfg *mconfig, char *param) | ||
585 | { | ||
586 | u16 module_config_size = 0; | ||
587 | void *param_data = NULL; | ||
588 | int ret; | ||
589 | struct skl_ipc_init_instance_msg msg; | ||
590 | |||
591 | dev_dbg(ctx->dev, "%s: module_id = %d instance=%d\n", __func__, | ||
592 | mconfig->id.module_id, mconfig->id.instance_id); | ||
593 | |||
594 | if (mconfig->pipe->state != SKL_PIPE_CREATED) { | ||
595 | dev_err(ctx->dev, "Pipe not created state= %d pipe_id= %d\n", | ||
596 | mconfig->pipe->state, mconfig->pipe->ppl_id); | ||
597 | return -EIO; | ||
598 | } | ||
599 | |||
600 | ret = skl_set_module_format(ctx, mconfig, | ||
601 | &module_config_size, ¶m_data); | ||
602 | if (ret < 0) { | ||
603 | dev_err(ctx->dev, "Failed to set module format ret=%d\n", ret); | ||
604 | return ret; | ||
605 | } | ||
606 | |||
607 | msg.module_id = mconfig->id.module_id; | ||
608 | msg.instance_id = mconfig->id.instance_id; | ||
609 | msg.ppl_instance_id = mconfig->pipe->ppl_id; | ||
610 | msg.param_data_size = module_config_size; | ||
611 | msg.core_id = mconfig->core_id; | ||
612 | |||
613 | ret = skl_ipc_init_instance(&ctx->ipc, &msg, param_data); | ||
614 | if (ret < 0) { | ||
615 | dev_err(ctx->dev, "Failed to init instance ret=%d\n", ret); | ||
616 | kfree(param_data); | ||
617 | return ret; | ||
618 | } | ||
619 | mconfig->m_state = SKL_MODULE_INIT_DONE; | ||
620 | |||
621 | return ret; | ||
622 | } | ||
623 | |||
624 | static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg | ||
625 | *src_module, struct skl_module_cfg *dst_module) | ||
626 | { | ||
627 | dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", | ||
628 | __func__, src_module->id.module_id, src_module->id.instance_id); | ||
629 | dev_dbg(ctx->dev, "%s: dst_module=%d dst_instacne=%d\n", __func__, | ||
630 | dst_module->id.module_id, dst_module->id.instance_id); | ||
631 | |||
632 | dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", | ||
633 | src_module->m_state, dst_module->m_state); | ||
634 | } | ||
635 | |||
636 | /* | ||
637 | * On module freeup, we need to unbind the module with modules | ||
638 | * it is already bind. | ||
639 | * Find the pin allocated and unbind then using bind_unbind IPC | ||
640 | */ | ||
641 | int skl_unbind_modules(struct skl_sst *ctx, | ||
642 | struct skl_module_cfg *src_mcfg, | ||
643 | struct skl_module_cfg *dst_mcfg) | ||
644 | { | ||
645 | int ret; | ||
646 | struct skl_ipc_bind_unbind_msg msg; | ||
647 | struct skl_module_inst_id src_id = src_mcfg->id; | ||
648 | struct skl_module_inst_id dst_id = dst_mcfg->id; | ||
649 | int in_max = dst_mcfg->max_in_queue; | ||
650 | int out_max = src_mcfg->max_out_queue; | ||
651 | int src_index, dst_index; | ||
652 | |||
653 | skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); | ||
654 | |||
655 | if (src_mcfg->m_state != SKL_MODULE_BIND_DONE) | ||
656 | return 0; | ||
657 | |||
658 | /* | ||
659 | * if intra module unbind, check if both modules are BIND, | ||
660 | * then send unbind | ||
661 | */ | ||
662 | if ((src_mcfg->pipe->ppl_id != dst_mcfg->pipe->ppl_id) && | ||
663 | dst_mcfg->m_state != SKL_MODULE_BIND_DONE) | ||
664 | return 0; | ||
665 | else if (src_mcfg->m_state < SKL_MODULE_INIT_DONE && | ||
666 | dst_mcfg->m_state < SKL_MODULE_INIT_DONE) | ||
667 | return 0; | ||
668 | |||
669 | /* get src queue index */ | ||
670 | src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); | ||
671 | if (src_index < 0) | ||
672 | return -EINVAL; | ||
673 | |||
674 | msg.src_queue = src_mcfg->m_out_pin[src_index].pin_index; | ||
675 | |||
676 | /* get dst queue index */ | ||
677 | dst_index = skl_get_queue_index(dst_mcfg->m_in_pin, src_id, in_max); | ||
678 | if (dst_index < 0) | ||
679 | return -EINVAL; | ||
680 | |||
681 | msg.dst_queue = dst_mcfg->m_in_pin[dst_index].pin_index; | ||
682 | |||
683 | msg.module_id = src_mcfg->id.module_id; | ||
684 | msg.instance_id = src_mcfg->id.instance_id; | ||
685 | msg.dst_module_id = dst_mcfg->id.module_id; | ||
686 | msg.dst_instance_id = dst_mcfg->id.instance_id; | ||
687 | msg.bind = false; | ||
688 | |||
689 | ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); | ||
690 | if (!ret) { | ||
691 | src_mcfg->m_state = SKL_MODULE_UNINIT; | ||
692 | /* free queue only if unbind is success */ | ||
693 | skl_free_queue(src_mcfg->m_out_pin, src_index); | ||
694 | skl_free_queue(dst_mcfg->m_in_pin, dst_index); | ||
695 | } | ||
696 | |||
697 | return ret; | ||
698 | } | ||
699 | |||
700 | /* | ||
701 | * Once a module is instantiated it need to be 'bind' with other modules in | ||
702 | * the pipeline. For binding we need to find the module pins which are bind | ||
703 | * together | ||
704 | * This function finds the pins and then sends bund_unbind IPC message to | ||
705 | * DSP using IPC helper | ||
706 | */ | ||
707 | int skl_bind_modules(struct skl_sst *ctx, | ||
708 | struct skl_module_cfg *src_mcfg, | ||
709 | struct skl_module_cfg *dst_mcfg) | ||
710 | { | ||
711 | int ret; | ||
712 | struct skl_ipc_bind_unbind_msg msg; | ||
713 | struct skl_module_inst_id src_id = src_mcfg->id; | ||
714 | struct skl_module_inst_id dst_id = dst_mcfg->id; | ||
715 | int in_max = dst_mcfg->max_in_queue; | ||
716 | int out_max = src_mcfg->max_out_queue; | ||
717 | int src_index, dst_index; | ||
718 | |||
719 | skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); | ||
720 | |||
721 | if (src_mcfg->m_state < SKL_MODULE_INIT_DONE && | ||
722 | dst_mcfg->m_state < SKL_MODULE_INIT_DONE) | ||
723 | return 0; | ||
724 | |||
725 | src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_id, out_max); | ||
726 | if (src_index < 0) | ||
727 | return -EINVAL; | ||
728 | |||
729 | msg.src_queue = src_mcfg->m_out_pin[src_index].pin_index; | ||
730 | dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_id, in_max); | ||
731 | if (dst_index < 0) { | ||
732 | skl_free_queue(src_mcfg->m_out_pin, src_index); | ||
733 | return -EINVAL; | ||
734 | } | ||
735 | |||
736 | msg.dst_queue = dst_mcfg->m_in_pin[dst_index].pin_index; | ||
737 | |||
738 | dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", | ||
739 | msg.src_queue, msg.dst_queue); | ||
740 | |||
741 | msg.module_id = src_mcfg->id.module_id; | ||
742 | msg.instance_id = src_mcfg->id.instance_id; | ||
743 | msg.dst_module_id = dst_mcfg->id.module_id; | ||
744 | msg.dst_instance_id = dst_mcfg->id.instance_id; | ||
745 | msg.bind = true; | ||
746 | |||
747 | ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); | ||
748 | |||
749 | if (!ret) { | ||
750 | src_mcfg->m_state = SKL_MODULE_BIND_DONE; | ||
751 | } else { | ||
752 | /* error case , if IPC fails, clear the queue index */ | ||
753 | skl_free_queue(src_mcfg->m_out_pin, src_index); | ||
754 | skl_free_queue(dst_mcfg->m_in_pin, dst_index); | ||
755 | } | ||
756 | |||
757 | return ret; | ||
758 | } | ||
759 | |||
760 | static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, | ||
761 | enum skl_ipc_pipeline_state state) | ||
762 | { | ||
763 | dev_dbg(ctx->dev, "%s: pipe_satate = %d\n", __func__, state); | ||
764 | |||
765 | return skl_ipc_set_pipeline_state(&ctx->ipc, pipe->ppl_id, state); | ||
766 | } | ||
767 | |||
768 | /* | ||
769 | * A pipeline is a collection of modules. Before a module in instantiated a | ||
770 | * pipeline needs to be created for it. | ||
771 | * This function creates pipeline, by sending create pipeline IPC messages | ||
772 | * to FW | ||
773 | */ | ||
774 | int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) | ||
775 | { | ||
776 | int ret; | ||
777 | |||
778 | dev_dbg(ctx->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); | ||
779 | |||
780 | ret = skl_ipc_create_pipeline(&ctx->ipc, pipe->memory_pages, | ||
781 | pipe->pipe_priority, pipe->ppl_id); | ||
782 | if (ret < 0) { | ||
783 | dev_err(ctx->dev, "Failed to create pipeline\n"); | ||
784 | return ret; | ||
785 | } | ||
786 | |||
787 | pipe->state = SKL_PIPE_CREATED; | ||
788 | |||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | /* | ||
793 | * A pipeline needs to be deleted on cleanup. If a pipeline is running, then | ||
794 | * pause the pipeline first and then delete it | ||
795 | * The pipe delete is done by sending delete pipeline IPC. DSP will stop the | ||
796 | * DMA engines and releases resources | ||
797 | */ | ||
798 | int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | ||
799 | { | ||
800 | int ret; | ||
801 | |||
802 | dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); | ||
803 | |||
804 | /* If pipe is not started, do not try to stop the pipe in FW. */ | ||
805 | if (pipe->state > SKL_PIPE_STARTED) { | ||
806 | ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); | ||
807 | if (ret < 0) { | ||
808 | dev_err(ctx->dev, "Failed to stop pipeline\n"); | ||
809 | return ret; | ||
810 | } | ||
811 | |||
812 | pipe->state = SKL_PIPE_PAUSED; | ||
813 | } else { | ||
814 | /* If pipe was not created in FW, do not try to delete it */ | ||
815 | if (pipe->state < SKL_PIPE_CREATED) | ||
816 | return 0; | ||
817 | |||
818 | ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); | ||
819 | if (ret < 0) | ||
820 | dev_err(ctx->dev, "Failed to delete pipeline\n"); | ||
821 | } | ||
822 | |||
823 | return ret; | ||
824 | } | ||
825 | |||
826 | /* | ||
827 | * A pipeline is also a scheduling entity in DSP which can be run, stopped | ||
828 | * For processing data the pipe need to be run by sending IPC set pipe state | ||
829 | * to DSP | ||
830 | */ | ||
831 | int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | ||
832 | { | ||
833 | int ret; | ||
834 | |||
835 | dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); | ||
836 | |||
837 | /* If pipe was not created in FW, do not try to pause or delete */ | ||
838 | if (pipe->state < SKL_PIPE_CREATED) | ||
839 | return 0; | ||
840 | |||
841 | /* Pipe has to be paused before it is started */ | ||
842 | ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); | ||
843 | if (ret < 0) { | ||
844 | dev_err(ctx->dev, "Failed to pause pipe\n"); | ||
845 | return ret; | ||
846 | } | ||
847 | |||
848 | pipe->state = SKL_PIPE_PAUSED; | ||
849 | |||
850 | ret = skl_set_pipe_state(ctx, pipe, PPL_RUNNING); | ||
851 | if (ret < 0) { | ||
852 | dev_err(ctx->dev, "Failed to start pipe\n"); | ||
853 | return ret; | ||
854 | } | ||
855 | |||
856 | pipe->state = SKL_PIPE_STARTED; | ||
857 | |||
858 | return 0; | ||
859 | } | ||
860 | |||
861 | /* | ||
862 | * Stop the pipeline by sending set pipe state IPC | ||
863 | * DSP doesnt implement stop so we always send pause message | ||
864 | */ | ||
865 | int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | ||
866 | { | ||
867 | int ret; | ||
868 | |||
869 | dev_dbg(ctx->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); | ||
870 | |||
871 | /* If pipe was not created in FW, do not try to pause or delete */ | ||
872 | if (pipe->state < SKL_PIPE_PAUSED) | ||
873 | return 0; | ||
874 | |||
875 | ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); | ||
876 | if (ret < 0) { | ||
877 | dev_dbg(ctx->dev, "Failed to stop pipe\n"); | ||
878 | return ret; | ||
879 | } | ||
880 | |||
881 | pipe->state = SKL_PIPE_CREATED; | ||
882 | |||
883 | return 0; | ||
884 | } | ||
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c new file mode 100644 index 000000000000..13036b19d7e5 --- /dev/null +++ b/sound/soc/intel/skylake/skl-nhlt.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * skl-nhlt.c - Intel SKL Platform NHLT parsing | ||
3 | * | ||
4 | * Copyright (C) 2015 Intel Corp | ||
5 | * Author: Sanjiv Kumar <sanjiv.kumar@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | */ | ||
20 | #include "skl.h" | ||
21 | |||
22 | /* Unique identification for getting NHLT blobs */ | ||
23 | static u8 OSC_UUID[16] = {0x6E, 0x88, 0x9F, 0xA6, 0xEB, 0x6C, 0x94, 0x45, | ||
24 | 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53}; | ||
25 | |||
26 | #define DSDT_NHLT_PATH "\\_SB.PCI0.HDAS" | ||
27 | |||
28 | void __iomem *skl_nhlt_init(struct device *dev) | ||
29 | { | ||
30 | acpi_handle handle; | ||
31 | union acpi_object *obj; | ||
32 | struct nhlt_resource_desc *nhlt_ptr = NULL; | ||
33 | |||
34 | if (ACPI_FAILURE(acpi_get_handle(NULL, DSDT_NHLT_PATH, &handle))) { | ||
35 | dev_err(dev, "Requested NHLT device not found\n"); | ||
36 | return NULL; | ||
37 | } | ||
38 | |||
39 | obj = acpi_evaluate_dsm(handle, OSC_UUID, 1, 1, NULL); | ||
40 | if (obj && obj->type == ACPI_TYPE_BUFFER) { | ||
41 | nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; | ||
42 | |||
43 | return ioremap_cache(nhlt_ptr->min_addr, nhlt_ptr->length); | ||
44 | } | ||
45 | |||
46 | dev_err(dev, "device specific method to extract NHLT blob failed\n"); | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | void skl_nhlt_free(void __iomem *addr) | ||
51 | { | ||
52 | iounmap(addr); | ||
53 | addr = NULL; | ||
54 | } | ||
55 | |||
56 | static struct nhlt_specific_cfg *skl_get_specific_cfg( | ||
57 | struct device *dev, struct nhlt_fmt *fmt, | ||
58 | u8 no_ch, u32 rate, u16 bps) | ||
59 | { | ||
60 | struct nhlt_specific_cfg *sp_config; | ||
61 | struct wav_fmt *wfmt; | ||
62 | struct nhlt_fmt_cfg *fmt_config = fmt->fmt_config; | ||
63 | int i; | ||
64 | |||
65 | dev_dbg(dev, "Format count =%d\n", fmt->fmt_count); | ||
66 | |||
67 | for (i = 0; i < fmt->fmt_count; i++) { | ||
68 | wfmt = &fmt_config->fmt_ext.fmt; | ||
69 | dev_dbg(dev, "ch=%d fmt=%d s_rate=%d\n", wfmt->channels, | ||
70 | wfmt->bits_per_sample, wfmt->samples_per_sec); | ||
71 | if (wfmt->channels == no_ch && wfmt->samples_per_sec == rate && | ||
72 | wfmt->bits_per_sample == bps) { | ||
73 | sp_config = &fmt_config->config; | ||
74 | |||
75 | return sp_config; | ||
76 | } | ||
77 | |||
78 | fmt_config = (struct nhlt_fmt_cfg *)(fmt_config->config.caps + | ||
79 | fmt_config->config.size); | ||
80 | } | ||
81 | |||
82 | return NULL; | ||
83 | } | ||
84 | |||
85 | static void dump_config(struct device *dev, u32 instance_id, u8 linktype, | ||
86 | u8 s_fmt, u8 num_channels, u32 s_rate, u8 dirn, u16 bps) | ||
87 | { | ||
88 | dev_dbg(dev, "Input configuration\n"); | ||
89 | dev_dbg(dev, "ch=%d fmt=%d s_rate=%d\n", num_channels, s_fmt, s_rate); | ||
90 | dev_dbg(dev, "vbus_id=%d link_type=%d\n", instance_id, linktype); | ||
91 | dev_dbg(dev, "bits_per_sample=%d\n", bps); | ||
92 | } | ||
93 | |||
94 | static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, | ||
95 | u32 instance_id, u8 link_type, u8 dirn) | ||
96 | { | ||
97 | dev_dbg(dev, "vbus_id=%d link_type=%d dir=%d\n", | ||
98 | epnt->virtual_bus_id, epnt->linktype, epnt->direction); | ||
99 | |||
100 | if ((epnt->virtual_bus_id == instance_id) && | ||
101 | (epnt->linktype == link_type) && | ||
102 | (epnt->direction == dirn)) | ||
103 | return true; | ||
104 | else | ||
105 | return false; | ||
106 | } | ||
107 | |||
108 | struct nhlt_specific_cfg | ||
109 | *skl_get_ep_blob(struct skl *skl, u32 instance, u8 link_type, | ||
110 | u8 s_fmt, u8 num_ch, u32 s_rate, u8 dirn) | ||
111 | { | ||
112 | struct nhlt_fmt *fmt; | ||
113 | struct nhlt_endpoint *epnt; | ||
114 | struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); | ||
115 | struct device *dev = bus->dev; | ||
116 | struct nhlt_specific_cfg *sp_config; | ||
117 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; | ||
118 | u16 bps = num_ch * s_fmt; | ||
119 | u8 j; | ||
120 | |||
121 | dump_config(dev, instance, link_type, s_fmt, num_ch, s_rate, dirn, bps); | ||
122 | |||
123 | epnt = (struct nhlt_endpoint *)nhlt->desc; | ||
124 | |||
125 | dev_dbg(dev, "endpoint count =%d\n", nhlt->endpoint_count); | ||
126 | |||
127 | for (j = 0; j < nhlt->endpoint_count; j++) { | ||
128 | if (skl_check_ep_match(dev, epnt, instance, link_type, dirn)) { | ||
129 | fmt = (struct nhlt_fmt *)(epnt->config.caps + | ||
130 | epnt->config.size); | ||
131 | sp_config = skl_get_specific_cfg(dev, fmt, num_ch, s_rate, bps); | ||
132 | if (sp_config) | ||
133 | return sp_config; | ||
134 | } | ||
135 | |||
136 | epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); | ||
137 | } | ||
138 | |||
139 | return NULL; | ||
140 | } | ||
diff --git a/sound/soc/intel/skylake/skl-nhlt.h b/sound/soc/intel/skylake/skl-nhlt.h new file mode 100644 index 000000000000..3769f9fefe2b --- /dev/null +++ b/sound/soc/intel/skylake/skl-nhlt.h | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | * skl-nhlt.h - Intel HDA Platform NHLT header | ||
3 | * | ||
4 | * Copyright (C) 2015 Intel Corp | ||
5 | * Author: Sanjiv Kumar <sanjiv.kumar@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | */ | ||
20 | #ifndef __SKL_NHLT_H__ | ||
21 | #define __SKL_NHLT_H__ | ||
22 | |||
23 | #include <linux/acpi.h> | ||
24 | |||
25 | struct wav_fmt { | ||
26 | u16 fmt_tag; | ||
27 | u16 channels; | ||
28 | u32 samples_per_sec; | ||
29 | u32 avg_bytes_per_sec; | ||
30 | u16 block_align; | ||
31 | u16 bits_per_sample; | ||
32 | u16 cb_size; | ||
33 | } __packed; | ||
34 | |||
35 | struct wav_fmt_ext { | ||
36 | struct wav_fmt fmt; | ||
37 | union samples { | ||
38 | u16 valid_bits_per_sample; | ||
39 | u16 samples_per_block; | ||
40 | u16 reserved; | ||
41 | } sample; | ||
42 | u32 channel_mask; | ||
43 | u8 sub_fmt[16]; | ||
44 | } __packed; | ||
45 | |||
46 | enum nhlt_link_type { | ||
47 | NHLT_LINK_HDA = 0, | ||
48 | NHLT_LINK_DSP = 1, | ||
49 | NHLT_LINK_DMIC = 2, | ||
50 | NHLT_LINK_SSP = 3, | ||
51 | NHLT_LINK_INVALID | ||
52 | }; | ||
53 | |||
54 | enum nhlt_device_type { | ||
55 | NHLT_DEVICE_BT = 0, | ||
56 | NHLT_DEVICE_DMIC = 1, | ||
57 | NHLT_DEVICE_I2S = 4, | ||
58 | NHLT_DEVICE_INVALID | ||
59 | }; | ||
60 | |||
61 | struct nhlt_specific_cfg { | ||
62 | u32 size; | ||
63 | u8 caps[0]; | ||
64 | } __packed; | ||
65 | |||
66 | struct nhlt_fmt_cfg { | ||
67 | struct wav_fmt_ext fmt_ext; | ||
68 | struct nhlt_specific_cfg config; | ||
69 | } __packed; | ||
70 | |||
71 | struct nhlt_fmt { | ||
72 | u8 fmt_count; | ||
73 | struct nhlt_fmt_cfg fmt_config[0]; | ||
74 | } __packed; | ||
75 | |||
76 | struct nhlt_endpoint { | ||
77 | u32 length; | ||
78 | u8 linktype; | ||
79 | u8 instance_id; | ||
80 | u16 vendor_id; | ||
81 | u16 device_id; | ||
82 | u16 revision_id; | ||
83 | u32 subsystem_id; | ||
84 | u8 device_type; | ||
85 | u8 direction; | ||
86 | u8 virtual_bus_id; | ||
87 | struct nhlt_specific_cfg config; | ||
88 | } __packed; | ||
89 | |||
90 | struct nhlt_acpi_table { | ||
91 | struct acpi_table_header header; | ||
92 | u8 endpoint_count; | ||
93 | struct nhlt_endpoint desc[0]; | ||
94 | } __packed; | ||
95 | |||
96 | struct nhlt_resource_desc { | ||
97 | u32 extra; | ||
98 | u16 flags; | ||
99 | u64 addr_spc_gra; | ||
100 | u64 min_addr; | ||
101 | u64 max_addr; | ||
102 | u64 addr_trans_offset; | ||
103 | u64 length; | ||
104 | } __packed; | ||
105 | |||
106 | #endif | ||
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c new file mode 100644 index 000000000000..7d617bf493bc --- /dev/null +++ b/sound/soc/intel/skylake/skl-pcm.c | |||
@@ -0,0 +1,916 @@ | |||
1 | /* | ||
2 | * skl-pcm.c -ASoC HDA Platform driver file implementing PCM functionality | ||
3 | * | ||
4 | * Copyright (C) 2014-2015 Intel Corp | ||
5 | * Author: Jeeja KP <jeeja.kp@intel.com> | ||
6 | * | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/pci.h> | ||
23 | #include <linux/pm_runtime.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include "skl.h" | ||
27 | |||
28 | #define HDA_MONO 1 | ||
29 | #define HDA_STEREO 2 | ||
30 | |||
31 | static struct snd_pcm_hardware azx_pcm_hw = { | ||
32 | .info = (SNDRV_PCM_INFO_MMAP | | ||
33 | SNDRV_PCM_INFO_INTERLEAVED | | ||
34 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
35 | SNDRV_PCM_INFO_MMAP_VALID | | ||
36 | SNDRV_PCM_INFO_PAUSE | | ||
37 | SNDRV_PCM_INFO_SYNC_START | | ||
38 | SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */ | ||
39 | SNDRV_PCM_INFO_HAS_LINK_ATIME | | ||
40 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), | ||
41 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
42 | .rates = SNDRV_PCM_RATE_48000, | ||
43 | .rate_min = 48000, | ||
44 | .rate_max = 48000, | ||
45 | .channels_min = 2, | ||
46 | .channels_max = 2, | ||
47 | .buffer_bytes_max = AZX_MAX_BUF_SIZE, | ||
48 | .period_bytes_min = 128, | ||
49 | .period_bytes_max = AZX_MAX_BUF_SIZE / 2, | ||
50 | .periods_min = 2, | ||
51 | .periods_max = AZX_MAX_FRAG, | ||
52 | .fifo_size = 0, | ||
53 | }; | ||
54 | |||
55 | static inline | ||
56 | struct hdac_ext_stream *get_hdac_ext_stream(struct snd_pcm_substream *substream) | ||
57 | { | ||
58 | return substream->runtime->private_data; | ||
59 | } | ||
60 | |||
61 | static struct hdac_ext_bus *get_bus_ctx(struct snd_pcm_substream *substream) | ||
62 | { | ||
63 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | ||
64 | struct hdac_stream *hstream = hdac_stream(stream); | ||
65 | struct hdac_bus *bus = hstream->bus; | ||
66 | |||
67 | return hbus_to_ebus(bus); | ||
68 | } | ||
69 | |||
70 | static int skl_substream_alloc_pages(struct hdac_ext_bus *ebus, | ||
71 | struct snd_pcm_substream *substream, | ||
72 | size_t size) | ||
73 | { | ||
74 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | ||
75 | |||
76 | hdac_stream(stream)->bufsize = 0; | ||
77 | hdac_stream(stream)->period_bytes = 0; | ||
78 | hdac_stream(stream)->format_val = 0; | ||
79 | |||
80 | return snd_pcm_lib_malloc_pages(substream, size); | ||
81 | } | ||
82 | |||
83 | static int skl_substream_free_pages(struct hdac_bus *bus, | ||
84 | struct snd_pcm_substream *substream) | ||
85 | { | ||
86 | return snd_pcm_lib_free_pages(substream); | ||
87 | } | ||
88 | |||
89 | static void skl_set_pcm_constrains(struct hdac_ext_bus *ebus, | ||
90 | struct snd_pcm_runtime *runtime) | ||
91 | { | ||
92 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
93 | |||
94 | /* avoid wrap-around with wall-clock */ | ||
95 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, | ||
96 | 20, 178000000); | ||
97 | } | ||
98 | |||
99 | static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_ext_bus *ebus) | ||
100 | { | ||
101 | if (ebus->ppcap) | ||
102 | return HDAC_EXT_STREAM_TYPE_HOST; | ||
103 | else | ||
104 | return HDAC_EXT_STREAM_TYPE_COUPLED; | ||
105 | } | ||
106 | |||
107 | static int skl_pcm_open(struct snd_pcm_substream *substream, | ||
108 | struct snd_soc_dai *dai) | ||
109 | { | ||
110 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
111 | struct hdac_ext_stream *stream; | ||
112 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
113 | struct skl_dma_params *dma_params; | ||
114 | int ret; | ||
115 | |||
116 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | ||
117 | ret = pm_runtime_get_sync(dai->dev); | ||
118 | if (ret) | ||
119 | return ret; | ||
120 | |||
121 | stream = snd_hdac_ext_stream_assign(ebus, substream, | ||
122 | skl_get_host_stream_type(ebus)); | ||
123 | if (stream == NULL) | ||
124 | return -EBUSY; | ||
125 | |||
126 | skl_set_pcm_constrains(ebus, runtime); | ||
127 | |||
128 | /* | ||
129 | * disable WALLCLOCK timestamps for capture streams | ||
130 | * until we figure out how to handle digital inputs | ||
131 | */ | ||
132 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | ||
133 | runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */ | ||
134 | runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME; | ||
135 | } | ||
136 | |||
137 | runtime->private_data = stream; | ||
138 | |||
139 | dma_params = kzalloc(sizeof(*dma_params), GFP_KERNEL); | ||
140 | if (!dma_params) | ||
141 | return -ENOMEM; | ||
142 | |||
143 | dma_params->stream_tag = hdac_stream(stream)->stream_tag; | ||
144 | snd_soc_dai_set_dma_data(dai, substream, dma_params); | ||
145 | |||
146 | dev_dbg(dai->dev, "stream tag set in dma params=%d\n", | ||
147 | dma_params->stream_tag); | ||
148 | snd_pcm_set_sync(substream); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int skl_get_format(struct snd_pcm_substream *substream, | ||
154 | struct snd_soc_dai *dai) | ||
155 | { | ||
156 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
157 | struct skl_dma_params *dma_params; | ||
158 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
159 | int format_val = 0; | ||
160 | |||
161 | if (ebus->ppcap) { | ||
162 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
163 | |||
164 | format_val = snd_hdac_calc_stream_format(runtime->rate, | ||
165 | runtime->channels, | ||
166 | runtime->format, | ||
167 | 32, 0); | ||
168 | } else { | ||
169 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
170 | |||
171 | dma_params = snd_soc_dai_get_dma_data(codec_dai, substream); | ||
172 | if (dma_params) | ||
173 | format_val = dma_params->format; | ||
174 | } | ||
175 | |||
176 | return format_val; | ||
177 | } | ||
178 | |||
179 | static int skl_pcm_prepare(struct snd_pcm_substream *substream, | ||
180 | struct snd_soc_dai *dai) | ||
181 | { | ||
182 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | ||
183 | unsigned int format_val; | ||
184 | int err; | ||
185 | |||
186 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | ||
187 | if (hdac_stream(stream)->prepared) { | ||
188 | dev_dbg(dai->dev, "already stream is prepared - returning\n"); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | format_val = skl_get_format(substream, dai); | ||
193 | dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n", | ||
194 | hdac_stream(stream)->stream_tag, format_val); | ||
195 | snd_hdac_stream_reset(hdac_stream(stream)); | ||
196 | |||
197 | err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); | ||
198 | if (err < 0) | ||
199 | return err; | ||
200 | |||
201 | err = snd_hdac_stream_setup(hdac_stream(stream)); | ||
202 | if (err < 0) | ||
203 | return err; | ||
204 | |||
205 | hdac_stream(stream)->prepared = 1; | ||
206 | |||
207 | return err; | ||
208 | } | ||
209 | |||
210 | static int skl_pcm_hw_params(struct snd_pcm_substream *substream, | ||
211 | struct snd_pcm_hw_params *params, | ||
212 | struct snd_soc_dai *dai) | ||
213 | { | ||
214 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
215 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | ||
216 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
217 | int ret, dma_id; | ||
218 | |||
219 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | ||
220 | ret = skl_substream_alloc_pages(ebus, substream, | ||
221 | params_buffer_bytes(params)); | ||
222 | if (ret < 0) | ||
223 | return ret; | ||
224 | |||
225 | dev_dbg(dai->dev, "format_val, rate=%d, ch=%d, format=%d\n", | ||
226 | runtime->rate, runtime->channels, runtime->format); | ||
227 | |||
228 | dma_id = hdac_stream(stream)->stream_tag - 1; | ||
229 | dev_dbg(dai->dev, "dma_id=%d\n", dma_id); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static void skl_pcm_close(struct snd_pcm_substream *substream, | ||
235 | struct snd_soc_dai *dai) | ||
236 | { | ||
237 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | ||
238 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
239 | struct skl_dma_params *dma_params = NULL; | ||
240 | |||
241 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | ||
242 | |||
243 | snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(ebus)); | ||
244 | |||
245 | dma_params = snd_soc_dai_get_dma_data(dai, substream); | ||
246 | /* | ||
247 | * now we should set this to NULL as we are freeing by the | ||
248 | * dma_params | ||
249 | */ | ||
250 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
251 | |||
252 | pm_runtime_mark_last_busy(dai->dev); | ||
253 | pm_runtime_put_autosuspend(dai->dev); | ||
254 | kfree(dma_params); | ||
255 | } | ||
256 | |||
257 | static int skl_pcm_hw_free(struct snd_pcm_substream *substream, | ||
258 | struct snd_soc_dai *dai) | ||
259 | { | ||
260 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
261 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | ||
262 | |||
263 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | ||
264 | |||
265 | snd_hdac_stream_cleanup(hdac_stream(stream)); | ||
266 | hdac_stream(stream)->prepared = 0; | ||
267 | |||
268 | return skl_substream_free_pages(ebus_to_hbus(ebus), substream); | ||
269 | } | ||
270 | |||
271 | static int skl_link_hw_params(struct snd_pcm_substream *substream, | ||
272 | struct snd_pcm_hw_params *params, | ||
273 | struct snd_soc_dai *dai) | ||
274 | { | ||
275 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
276 | struct hdac_ext_stream *link_dev; | ||
277 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
278 | struct skl_dma_params *dma_params; | ||
279 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
280 | int dma_id; | ||
281 | |||
282 | pr_debug("%s\n", __func__); | ||
283 | link_dev = snd_hdac_ext_stream_assign(ebus, substream, | ||
284 | HDAC_EXT_STREAM_TYPE_LINK); | ||
285 | if (!link_dev) | ||
286 | return -EBUSY; | ||
287 | |||
288 | snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); | ||
289 | |||
290 | /* set the stream tag in the codec dai dma params */ | ||
291 | dma_params = (struct skl_dma_params *) | ||
292 | snd_soc_dai_get_dma_data(codec_dai, substream); | ||
293 | if (dma_params) | ||
294 | dma_params->stream_tag = hdac_stream(link_dev)->stream_tag; | ||
295 | snd_soc_dai_set_dma_data(codec_dai, substream, (void *)dma_params); | ||
296 | dma_id = hdac_stream(link_dev)->stream_tag - 1; | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, | ||
302 | struct snd_soc_dai *dai) | ||
303 | { | ||
304 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
305 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
306 | struct hdac_ext_stream *link_dev = | ||
307 | snd_soc_dai_get_dma_data(dai, substream); | ||
308 | unsigned int format_val = 0; | ||
309 | struct skl_dma_params *dma_params; | ||
310 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
311 | struct snd_pcm_hw_params *params; | ||
312 | struct snd_interval *channels, *rate; | ||
313 | struct hdac_ext_link *link; | ||
314 | |||
315 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | ||
316 | if (link_dev->link_prepared) { | ||
317 | dev_dbg(dai->dev, "already stream is prepared - returning\n"); | ||
318 | return 0; | ||
319 | } | ||
320 | params = devm_kzalloc(dai->dev, sizeof(*params), GFP_KERNEL); | ||
321 | if (params == NULL) | ||
322 | return -ENOMEM; | ||
323 | |||
324 | channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
325 | channels->min = channels->max = substream->runtime->channels; | ||
326 | rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
327 | rate->min = rate->max = substream->runtime->rate; | ||
328 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | ||
329 | SNDRV_PCM_HW_PARAM_FIRST_MASK], | ||
330 | substream->runtime->format); | ||
331 | |||
332 | |||
333 | dma_params = (struct skl_dma_params *) | ||
334 | snd_soc_dai_get_dma_data(codec_dai, substream); | ||
335 | if (dma_params) | ||
336 | format_val = dma_params->format; | ||
337 | dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n", | ||
338 | hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name); | ||
339 | |||
340 | snd_hdac_ext_link_stream_reset(link_dev); | ||
341 | |||
342 | snd_hdac_ext_link_stream_setup(link_dev, format_val); | ||
343 | |||
344 | link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name); | ||
345 | if (!link) | ||
346 | return -EINVAL; | ||
347 | |||
348 | snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag); | ||
349 | link_dev->link_prepared = 1; | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int skl_link_pcm_trigger(struct snd_pcm_substream *substream, | ||
355 | int cmd, struct snd_soc_dai *dai) | ||
356 | { | ||
357 | struct hdac_ext_stream *link_dev = | ||
358 | snd_soc_dai_get_dma_data(dai, substream); | ||
359 | |||
360 | dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd); | ||
361 | switch (cmd) { | ||
362 | case SNDRV_PCM_TRIGGER_START: | ||
363 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
364 | case SNDRV_PCM_TRIGGER_RESUME: | ||
365 | snd_hdac_ext_link_stream_start(link_dev); | ||
366 | break; | ||
367 | |||
368 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
369 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
370 | case SNDRV_PCM_TRIGGER_STOP: | ||
371 | snd_hdac_ext_link_stream_clear(link_dev); | ||
372 | break; | ||
373 | |||
374 | default: | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static int skl_link_hw_free(struct snd_pcm_substream *substream, | ||
381 | struct snd_soc_dai *dai) | ||
382 | { | ||
383 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
384 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
385 | struct hdac_ext_stream *link_dev = | ||
386 | snd_soc_dai_get_dma_data(dai, substream); | ||
387 | struct hdac_ext_link *link; | ||
388 | |||
389 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | ||
390 | |||
391 | link_dev->link_prepared = 0; | ||
392 | |||
393 | link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name); | ||
394 | if (!link) | ||
395 | return -EINVAL; | ||
396 | |||
397 | snd_hdac_ext_link_clear_stream_id(link, hdac_stream(link_dev)->stream_tag); | ||
398 | snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static int skl_hda_be_startup(struct snd_pcm_substream *substream, | ||
403 | struct snd_soc_dai *dai) | ||
404 | { | ||
405 | return pm_runtime_get_sync(dai->dev); | ||
406 | } | ||
407 | |||
408 | static void skl_hda_be_shutdown(struct snd_pcm_substream *substream, | ||
409 | struct snd_soc_dai *dai) | ||
410 | { | ||
411 | pm_runtime_mark_last_busy(dai->dev); | ||
412 | pm_runtime_put_autosuspend(dai->dev); | ||
413 | } | ||
414 | |||
415 | static struct snd_soc_dai_ops skl_pcm_dai_ops = { | ||
416 | .startup = skl_pcm_open, | ||
417 | .shutdown = skl_pcm_close, | ||
418 | .prepare = skl_pcm_prepare, | ||
419 | .hw_params = skl_pcm_hw_params, | ||
420 | .hw_free = skl_pcm_hw_free, | ||
421 | }; | ||
422 | |||
423 | static struct snd_soc_dai_ops skl_dmic_dai_ops = { | ||
424 | .startup = skl_hda_be_startup, | ||
425 | .shutdown = skl_hda_be_shutdown, | ||
426 | }; | ||
427 | |||
428 | static struct snd_soc_dai_ops skl_link_dai_ops = { | ||
429 | .startup = skl_hda_be_startup, | ||
430 | .prepare = skl_link_pcm_prepare, | ||
431 | .hw_params = skl_link_hw_params, | ||
432 | .hw_free = skl_link_hw_free, | ||
433 | .trigger = skl_link_pcm_trigger, | ||
434 | .shutdown = skl_hda_be_shutdown, | ||
435 | }; | ||
436 | |||
437 | static struct snd_soc_dai_driver skl_platform_dai[] = { | ||
438 | { | ||
439 | .name = "System Pin", | ||
440 | .ops = &skl_pcm_dai_ops, | ||
441 | .playback = { | ||
442 | .stream_name = "System Playback", | ||
443 | .channels_min = HDA_MONO, | ||
444 | .channels_max = HDA_STEREO, | ||
445 | .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000, | ||
446 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
447 | }, | ||
448 | .capture = { | ||
449 | .stream_name = "System Capture", | ||
450 | .channels_min = HDA_MONO, | ||
451 | .channels_max = HDA_STEREO, | ||
452 | .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, | ||
453 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
454 | }, | ||
455 | }, | ||
456 | { | ||
457 | .name = "Reference Pin", | ||
458 | .ops = &skl_pcm_dai_ops, | ||
459 | .capture = { | ||
460 | .stream_name = "Reference Capture", | ||
461 | .channels_min = HDA_MONO, | ||
462 | .channels_max = HDA_STEREO, | ||
463 | .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, | ||
464 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
465 | }, | ||
466 | }, | ||
467 | { | ||
468 | .name = "Deepbuffer Pin", | ||
469 | .ops = &skl_pcm_dai_ops, | ||
470 | .playback = { | ||
471 | .stream_name = "Deepbuffer Playback", | ||
472 | .channels_min = HDA_STEREO, | ||
473 | .channels_max = HDA_STEREO, | ||
474 | .rates = SNDRV_PCM_RATE_48000, | ||
475 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
476 | }, | ||
477 | }, | ||
478 | { | ||
479 | .name = "LowLatency Pin", | ||
480 | .ops = &skl_pcm_dai_ops, | ||
481 | .playback = { | ||
482 | .stream_name = "Low Latency Playback", | ||
483 | .channels_min = HDA_STEREO, | ||
484 | .channels_max = HDA_STEREO, | ||
485 | .rates = SNDRV_PCM_RATE_48000, | ||
486 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
487 | }, | ||
488 | }, | ||
489 | /* BE CPU Dais */ | ||
490 | { | ||
491 | .name = "iDisp Pin", | ||
492 | .ops = &skl_link_dai_ops, | ||
493 | .playback = { | ||
494 | .stream_name = "iDisp Tx", | ||
495 | .channels_min = HDA_STEREO, | ||
496 | .channels_max = HDA_STEREO, | ||
497 | .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000, | ||
498 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
499 | }, | ||
500 | }, | ||
501 | { | ||
502 | .name = "DMIC01 Pin", | ||
503 | .ops = &skl_dmic_dai_ops, | ||
504 | .capture = { | ||
505 | .stream_name = "DMIC01 Rx", | ||
506 | .channels_min = HDA_STEREO, | ||
507 | .channels_max = HDA_STEREO, | ||
508 | .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, | ||
509 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
510 | }, | ||
511 | }, | ||
512 | { | ||
513 | .name = "DMIC23 Pin", | ||
514 | .ops = &skl_dmic_dai_ops, | ||
515 | .capture = { | ||
516 | .stream_name = "DMIC23 Rx", | ||
517 | .channels_min = HDA_STEREO, | ||
518 | .channels_max = HDA_STEREO, | ||
519 | .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, | ||
520 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
521 | }, | ||
522 | }, | ||
523 | { | ||
524 | .name = "HD-Codec Pin", | ||
525 | .ops = &skl_link_dai_ops, | ||
526 | .playback = { | ||
527 | .stream_name = "HD-Codec Tx", | ||
528 | .channels_min = HDA_STEREO, | ||
529 | .channels_max = HDA_STEREO, | ||
530 | .rates = SNDRV_PCM_RATE_48000, | ||
531 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
532 | }, | ||
533 | .capture = { | ||
534 | .stream_name = "HD-Codec Rx", | ||
535 | .channels_min = HDA_STEREO, | ||
536 | .channels_max = HDA_STEREO, | ||
537 | .rates = SNDRV_PCM_RATE_48000, | ||
538 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
539 | }, | ||
540 | }, | ||
541 | { | ||
542 | .name = "HD-Codec-SPK Pin", | ||
543 | .ops = &skl_link_dai_ops, | ||
544 | .playback = { | ||
545 | .stream_name = "HD-Codec-SPK Tx", | ||
546 | .channels_min = HDA_STEREO, | ||
547 | .channels_max = HDA_STEREO, | ||
548 | .rates = SNDRV_PCM_RATE_48000, | ||
549 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
550 | }, | ||
551 | }, | ||
552 | { | ||
553 | .name = "HD-Codec-AMIC Pin", | ||
554 | .ops = &skl_link_dai_ops, | ||
555 | .capture = { | ||
556 | .stream_name = "HD-Codec-AMIC Rx", | ||
557 | .channels_min = HDA_STEREO, | ||
558 | .channels_max = HDA_STEREO, | ||
559 | .rates = SNDRV_PCM_RATE_48000, | ||
560 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
561 | }, | ||
562 | }, | ||
563 | }; | ||
564 | |||
565 | static int skl_platform_open(struct snd_pcm_substream *substream) | ||
566 | { | ||
567 | struct snd_pcm_runtime *runtime; | ||
568 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
569 | struct snd_soc_dai_link *dai_link = rtd->dai_link; | ||
570 | |||
571 | dev_dbg(rtd->cpu_dai->dev, "In %s:%s\n", __func__, | ||
572 | dai_link->cpu_dai_name); | ||
573 | |||
574 | runtime = substream->runtime; | ||
575 | snd_soc_set_runtime_hwparams(substream, &azx_pcm_hw); | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | static int skl_pcm_trigger(struct snd_pcm_substream *substream, | ||
581 | int cmd) | ||
582 | { | ||
583 | struct hdac_ext_bus *ebus = get_bus_ctx(substream); | ||
584 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
585 | struct hdac_ext_stream *stream; | ||
586 | struct snd_pcm_substream *s; | ||
587 | bool start; | ||
588 | int sbits = 0; | ||
589 | unsigned long cookie; | ||
590 | struct hdac_stream *hstr; | ||
591 | |||
592 | stream = get_hdac_ext_stream(substream); | ||
593 | hstr = hdac_stream(stream); | ||
594 | |||
595 | dev_dbg(bus->dev, "In %s cmd=%d\n", __func__, cmd); | ||
596 | |||
597 | if (!hstr->prepared) | ||
598 | return -EPIPE; | ||
599 | |||
600 | switch (cmd) { | ||
601 | case SNDRV_PCM_TRIGGER_START: | ||
602 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
603 | case SNDRV_PCM_TRIGGER_RESUME: | ||
604 | start = true; | ||
605 | break; | ||
606 | |||
607 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
608 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
609 | case SNDRV_PCM_TRIGGER_STOP: | ||
610 | start = false; | ||
611 | break; | ||
612 | |||
613 | default: | ||
614 | return -EINVAL; | ||
615 | } | ||
616 | |||
617 | snd_pcm_group_for_each_entry(s, substream) { | ||
618 | if (s->pcm->card != substream->pcm->card) | ||
619 | continue; | ||
620 | stream = get_hdac_ext_stream(s); | ||
621 | sbits |= 1 << hdac_stream(stream)->index; | ||
622 | snd_pcm_trigger_done(s, substream); | ||
623 | } | ||
624 | |||
625 | spin_lock_irqsave(&bus->reg_lock, cookie); | ||
626 | |||
627 | /* first, set SYNC bits of corresponding streams */ | ||
628 | snd_hdac_stream_sync_trigger(hstr, true, sbits, AZX_REG_SSYNC); | ||
629 | |||
630 | snd_pcm_group_for_each_entry(s, substream) { | ||
631 | if (s->pcm->card != substream->pcm->card) | ||
632 | continue; | ||
633 | stream = get_hdac_ext_stream(s); | ||
634 | if (start) | ||
635 | snd_hdac_stream_start(hdac_stream(stream), true); | ||
636 | else | ||
637 | snd_hdac_stream_stop(hdac_stream(stream)); | ||
638 | } | ||
639 | spin_unlock_irqrestore(&bus->reg_lock, cookie); | ||
640 | |||
641 | snd_hdac_stream_sync(hstr, start, sbits); | ||
642 | |||
643 | spin_lock_irqsave(&bus->reg_lock, cookie); | ||
644 | |||
645 | /* reset SYNC bits */ | ||
646 | snd_hdac_stream_sync_trigger(hstr, false, sbits, AZX_REG_SSYNC); | ||
647 | if (start) | ||
648 | snd_hdac_stream_timecounter_init(hstr, sbits); | ||
649 | spin_unlock_irqrestore(&bus->reg_lock, cookie); | ||
650 | |||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | static int skl_dsp_trigger(struct snd_pcm_substream *substream, | ||
655 | int cmd) | ||
656 | { | ||
657 | struct hdac_ext_bus *ebus = get_bus_ctx(substream); | ||
658 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
659 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
660 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
661 | struct hdac_ext_stream *stream; | ||
662 | int start; | ||
663 | unsigned long cookie; | ||
664 | struct hdac_stream *hstr; | ||
665 | |||
666 | dev_dbg(bus->dev, "In %s cmd=%d streamname=%s\n", __func__, cmd, cpu_dai->name); | ||
667 | |||
668 | stream = get_hdac_ext_stream(substream); | ||
669 | hstr = hdac_stream(stream); | ||
670 | |||
671 | if (!hstr->prepared) | ||
672 | return -EPIPE; | ||
673 | |||
674 | switch (cmd) { | ||
675 | case SNDRV_PCM_TRIGGER_START: | ||
676 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
677 | case SNDRV_PCM_TRIGGER_RESUME: | ||
678 | start = 1; | ||
679 | break; | ||
680 | |||
681 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
682 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
683 | case SNDRV_PCM_TRIGGER_STOP: | ||
684 | start = 0; | ||
685 | break; | ||
686 | |||
687 | default: | ||
688 | return -EINVAL; | ||
689 | } | ||
690 | |||
691 | spin_lock_irqsave(&bus->reg_lock, cookie); | ||
692 | |||
693 | if (start) | ||
694 | snd_hdac_stream_start(hdac_stream(stream), true); | ||
695 | else | ||
696 | snd_hdac_stream_stop(hdac_stream(stream)); | ||
697 | |||
698 | if (start) | ||
699 | snd_hdac_stream_timecounter_init(hstr, 0); | ||
700 | |||
701 | spin_unlock_irqrestore(&bus->reg_lock, cookie); | ||
702 | |||
703 | return 0; | ||
704 | } | ||
705 | static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream, | ||
706 | int cmd) | ||
707 | { | ||
708 | struct hdac_ext_bus *ebus = get_bus_ctx(substream); | ||
709 | |||
710 | if (ebus->ppcap) | ||
711 | return skl_dsp_trigger(substream, cmd); | ||
712 | else | ||
713 | return skl_pcm_trigger(substream, cmd); | ||
714 | } | ||
715 | |||
716 | /* calculate runtime delay from LPIB */ | ||
717 | static int skl_get_delay_from_lpib(struct hdac_ext_bus *ebus, | ||
718 | struct hdac_ext_stream *sstream, | ||
719 | unsigned int pos) | ||
720 | { | ||
721 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
722 | struct hdac_stream *hstream = hdac_stream(sstream); | ||
723 | struct snd_pcm_substream *substream = hstream->substream; | ||
724 | int stream = substream->stream; | ||
725 | unsigned int lpib_pos = snd_hdac_stream_get_pos_lpib(hstream); | ||
726 | int delay; | ||
727 | |||
728 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
729 | delay = pos - lpib_pos; | ||
730 | else | ||
731 | delay = lpib_pos - pos; | ||
732 | |||
733 | if (delay < 0) { | ||
734 | if (delay >= hstream->delay_negative_threshold) | ||
735 | delay = 0; | ||
736 | else | ||
737 | delay += hstream->bufsize; | ||
738 | } | ||
739 | |||
740 | if (delay >= hstream->period_bytes) { | ||
741 | dev_info(bus->dev, | ||
742 | "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", | ||
743 | delay, hstream->period_bytes); | ||
744 | delay = 0; | ||
745 | } | ||
746 | |||
747 | return bytes_to_frames(substream->runtime, delay); | ||
748 | } | ||
749 | |||
750 | static unsigned int skl_get_position(struct hdac_ext_stream *hstream, | ||
751 | int codec_delay) | ||
752 | { | ||
753 | struct hdac_stream *hstr = hdac_stream(hstream); | ||
754 | struct snd_pcm_substream *substream = hstr->substream; | ||
755 | struct hdac_ext_bus *ebus = get_bus_ctx(substream); | ||
756 | unsigned int pos; | ||
757 | int delay; | ||
758 | |||
759 | /* use the position buffer as default */ | ||
760 | pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream)); | ||
761 | |||
762 | if (pos >= hdac_stream(hstream)->bufsize) | ||
763 | pos = 0; | ||
764 | |||
765 | if (substream->runtime) { | ||
766 | delay = skl_get_delay_from_lpib(ebus, hstream, pos) | ||
767 | + codec_delay; | ||
768 | substream->runtime->delay += delay; | ||
769 | } | ||
770 | |||
771 | return pos; | ||
772 | } | ||
773 | |||
774 | static snd_pcm_uframes_t skl_platform_pcm_pointer | ||
775 | (struct snd_pcm_substream *substream) | ||
776 | { | ||
777 | struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream); | ||
778 | |||
779 | return bytes_to_frames(substream->runtime, | ||
780 | skl_get_position(hstream, 0)); | ||
781 | } | ||
782 | |||
783 | static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream, | ||
784 | u64 nsec) | ||
785 | { | ||
786 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
787 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
788 | u64 codec_frames, codec_nsecs; | ||
789 | |||
790 | if (!codec_dai->driver->ops->delay) | ||
791 | return nsec; | ||
792 | |||
793 | codec_frames = codec_dai->driver->ops->delay(substream, codec_dai); | ||
794 | codec_nsecs = div_u64(codec_frames * 1000000000LL, | ||
795 | substream->runtime->rate); | ||
796 | |||
797 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
798 | return nsec + codec_nsecs; | ||
799 | |||
800 | return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0; | ||
801 | } | ||
802 | |||
803 | static int skl_get_time_info(struct snd_pcm_substream *substream, | ||
804 | struct timespec *system_ts, struct timespec *audio_ts, | ||
805 | struct snd_pcm_audio_tstamp_config *audio_tstamp_config, | ||
806 | struct snd_pcm_audio_tstamp_report *audio_tstamp_report) | ||
807 | { | ||
808 | struct hdac_ext_stream *sstream = get_hdac_ext_stream(substream); | ||
809 | struct hdac_stream *hstr = hdac_stream(sstream); | ||
810 | u64 nsec; | ||
811 | |||
812 | if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) && | ||
813 | (audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) { | ||
814 | |||
815 | snd_pcm_gettime(substream->runtime, system_ts); | ||
816 | |||
817 | nsec = timecounter_read(&hstr->tc); | ||
818 | nsec = div_u64(nsec, 3); /* can be optimized */ | ||
819 | if (audio_tstamp_config->report_delay) | ||
820 | nsec = skl_adjust_codec_delay(substream, nsec); | ||
821 | |||
822 | *audio_ts = ns_to_timespec(nsec); | ||
823 | |||
824 | audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK; | ||
825 | audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */ | ||
826 | audio_tstamp_report->accuracy = 42; /* 24MHzWallClk == 42ns resolution */ | ||
827 | |||
828 | } else { | ||
829 | audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT; | ||
830 | } | ||
831 | |||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | static struct snd_pcm_ops skl_platform_ops = { | ||
836 | .open = skl_platform_open, | ||
837 | .ioctl = snd_pcm_lib_ioctl, | ||
838 | .trigger = skl_platform_pcm_trigger, | ||
839 | .pointer = skl_platform_pcm_pointer, | ||
840 | .get_time_info = skl_get_time_info, | ||
841 | .mmap = snd_pcm_lib_default_mmap, | ||
842 | .page = snd_pcm_sgbuf_ops_page, | ||
843 | }; | ||
844 | |||
845 | static void skl_pcm_free(struct snd_pcm *pcm) | ||
846 | { | ||
847 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
848 | } | ||
849 | |||
850 | #define MAX_PREALLOC_SIZE (32 * 1024 * 1024) | ||
851 | |||
852 | static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
853 | { | ||
854 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
855 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
856 | struct snd_pcm *pcm = rtd->pcm; | ||
857 | unsigned int size; | ||
858 | int retval = 0; | ||
859 | struct skl *skl = ebus_to_skl(ebus); | ||
860 | |||
861 | if (dai->driver->playback.channels_min || | ||
862 | dai->driver->capture.channels_min) { | ||
863 | /* buffer pre-allocation */ | ||
864 | size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; | ||
865 | if (size > MAX_PREALLOC_SIZE) | ||
866 | size = MAX_PREALLOC_SIZE; | ||
867 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
868 | SNDRV_DMA_TYPE_DEV_SG, | ||
869 | snd_dma_pci_data(skl->pci), | ||
870 | size, MAX_PREALLOC_SIZE); | ||
871 | if (retval) { | ||
872 | dev_err(dai->dev, "dma buffer allocationf fail\n"); | ||
873 | return retval; | ||
874 | } | ||
875 | } | ||
876 | |||
877 | return retval; | ||
878 | } | ||
879 | |||
880 | static struct snd_soc_platform_driver skl_platform_drv = { | ||
881 | .ops = &skl_platform_ops, | ||
882 | .pcm_new = skl_pcm_new, | ||
883 | .pcm_free = skl_pcm_free, | ||
884 | }; | ||
885 | |||
886 | static const struct snd_soc_component_driver skl_component = { | ||
887 | .name = "pcm", | ||
888 | }; | ||
889 | |||
890 | int skl_platform_register(struct device *dev) | ||
891 | { | ||
892 | int ret; | ||
893 | |||
894 | ret = snd_soc_register_platform(dev, &skl_platform_drv); | ||
895 | if (ret) { | ||
896 | dev_err(dev, "soc platform registration failed %d\n", ret); | ||
897 | return ret; | ||
898 | } | ||
899 | ret = snd_soc_register_component(dev, &skl_component, | ||
900 | skl_platform_dai, | ||
901 | ARRAY_SIZE(skl_platform_dai)); | ||
902 | if (ret) { | ||
903 | dev_err(dev, "soc component registration failed %d\n", ret); | ||
904 | snd_soc_unregister_platform(dev); | ||
905 | } | ||
906 | |||
907 | return ret; | ||
908 | |||
909 | } | ||
910 | |||
911 | int skl_platform_unregister(struct device *dev) | ||
912 | { | ||
913 | snd_soc_unregister_component(dev); | ||
914 | snd_soc_unregister_platform(dev); | ||
915 | return 0; | ||
916 | } | ||
diff --git a/sound/soc/intel/skylake/skl-sst-cldma.c b/sound/soc/intel/skylake/skl-sst-cldma.c new file mode 100644 index 000000000000..44748ba98da2 --- /dev/null +++ b/sound/soc/intel/skylake/skl-sst-cldma.c | |||
@@ -0,0 +1,327 @@ | |||
1 | /* | ||
2 | * skl-sst-cldma.c - Code Loader DMA handler | ||
3 | * | ||
4 | * Copyright (C) 2015, Intel Corporation. | ||
5 | * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as version 2, as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/device.h> | ||
19 | #include <linux/mm.h> | ||
20 | #include <linux/kthread.h> | ||
21 | #include "../common/sst-dsp.h" | ||
22 | #include "../common/sst-dsp-priv.h" | ||
23 | |||
24 | static void skl_cldma_int_enable(struct sst_dsp *ctx) | ||
25 | { | ||
26 | sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC, | ||
27 | SKL_ADSPIC_CL_DMA, SKL_ADSPIC_CL_DMA); | ||
28 | } | ||
29 | |||
30 | void skl_cldma_int_disable(struct sst_dsp *ctx) | ||
31 | { | ||
32 | sst_dsp_shim_update_bits_unlocked(ctx, | ||
33 | SKL_ADSP_REG_ADSPIC, SKL_ADSPIC_CL_DMA, 0); | ||
34 | } | ||
35 | |||
36 | /* Code loader helper APIs */ | ||
37 | static void skl_cldma_setup_bdle(struct sst_dsp *ctx, | ||
38 | struct snd_dma_buffer *dmab_data, | ||
39 | u32 **bdlp, int size, int with_ioc) | ||
40 | { | ||
41 | u32 *bdl = *bdlp; | ||
42 | |||
43 | ctx->cl_dev.frags = 0; | ||
44 | while (size > 0) { | ||
45 | phys_addr_t addr = virt_to_phys(dmab_data->area + | ||
46 | (ctx->cl_dev.frags * ctx->cl_dev.bufsize)); | ||
47 | |||
48 | bdl[0] = cpu_to_le32(lower_32_bits(addr)); | ||
49 | bdl[1] = cpu_to_le32(upper_32_bits(addr)); | ||
50 | |||
51 | bdl[2] = cpu_to_le32(ctx->cl_dev.bufsize); | ||
52 | |||
53 | size -= ctx->cl_dev.bufsize; | ||
54 | bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); | ||
55 | |||
56 | bdl += 4; | ||
57 | ctx->cl_dev.frags++; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Setup controller | ||
63 | * Configure the registers to update the dma buffer address and | ||
64 | * enable interrupts. | ||
65 | * Note: Using the channel 1 for transfer | ||
66 | */ | ||
67 | static void skl_cldma_setup_controller(struct sst_dsp *ctx, | ||
68 | struct snd_dma_buffer *dmab_bdl, unsigned int max_size, | ||
69 | u32 count) | ||
70 | { | ||
71 | sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, | ||
72 | CL_SD_BDLPLBA(dmab_bdl->addr)); | ||
73 | sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, | ||
74 | CL_SD_BDLPUBA(dmab_bdl->addr)); | ||
75 | |||
76 | sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, max_size); | ||
77 | sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, count - 1); | ||
78 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, | ||
79 | CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(1)); | ||
80 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, | ||
81 | CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(1)); | ||
82 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, | ||
83 | CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(1)); | ||
84 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, | ||
85 | CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(FW_CL_STREAM_NUMBER)); | ||
86 | } | ||
87 | |||
88 | static void skl_cldma_setup_spb(struct sst_dsp *ctx, | ||
89 | unsigned int size, bool enable) | ||
90 | { | ||
91 | if (enable) | ||
92 | sst_dsp_shim_update_bits_unlocked(ctx, | ||
93 | SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL, | ||
94 | CL_SPBFIFO_SPBFCCTL_SPIBE_MASK, | ||
95 | CL_SPBFIFO_SPBFCCTL_SPIBE(1)); | ||
96 | |||
97 | sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_CL_SPBFIFO_SPIB, size); | ||
98 | } | ||
99 | |||
100 | static void skl_cldma_cleanup_spb(struct sst_dsp *ctx) | ||
101 | { | ||
102 | sst_dsp_shim_update_bits_unlocked(ctx, | ||
103 | SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL, | ||
104 | CL_SPBFIFO_SPBFCCTL_SPIBE_MASK, | ||
105 | CL_SPBFIFO_SPBFCCTL_SPIBE(0)); | ||
106 | |||
107 | sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_CL_SPBFIFO_SPIB, 0); | ||
108 | } | ||
109 | |||
110 | static void skl_cldma_trigger(struct sst_dsp *ctx, bool enable) | ||
111 | { | ||
112 | if (enable) | ||
113 | sst_dsp_shim_update_bits_unlocked(ctx, | ||
114 | SKL_ADSP_REG_CL_SD_CTL, | ||
115 | CL_SD_CTL_RUN_MASK, CL_SD_CTL_RUN(1)); | ||
116 | else | ||
117 | sst_dsp_shim_update_bits_unlocked(ctx, | ||
118 | SKL_ADSP_REG_CL_SD_CTL, | ||
119 | CL_SD_CTL_RUN_MASK, CL_SD_CTL_RUN(0)); | ||
120 | } | ||
121 | |||
122 | static void skl_cldma_cleanup(struct sst_dsp *ctx) | ||
123 | { | ||
124 | skl_cldma_cleanup_spb(ctx); | ||
125 | |||
126 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, | ||
127 | CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(0)); | ||
128 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, | ||
129 | CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(0)); | ||
130 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, | ||
131 | CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(0)); | ||
132 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, | ||
133 | CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(0)); | ||
134 | |||
135 | sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, CL_SD_BDLPLBA(0)); | ||
136 | sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, 0); | ||
137 | |||
138 | sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, 0); | ||
139 | sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, 0); | ||
140 | } | ||
141 | |||
142 | static int skl_cldma_wait_interruptible(struct sst_dsp *ctx) | ||
143 | { | ||
144 | int ret = 0; | ||
145 | |||
146 | if (!wait_event_timeout(ctx->cl_dev.wait_queue, | ||
147 | ctx->cl_dev.wait_condition, | ||
148 | msecs_to_jiffies(SKL_WAIT_TIMEOUT))) { | ||
149 | dev_err(ctx->dev, "%s: Wait timeout\n", __func__); | ||
150 | ret = -EIO; | ||
151 | goto cleanup; | ||
152 | } | ||
153 | |||
154 | dev_dbg(ctx->dev, "%s: Event wake\n", __func__); | ||
155 | if (ctx->cl_dev.wake_status != SKL_CL_DMA_BUF_COMPLETE) { | ||
156 | dev_err(ctx->dev, "%s: DMA Error\n", __func__); | ||
157 | ret = -EIO; | ||
158 | } | ||
159 | |||
160 | cleanup: | ||
161 | ctx->cl_dev.wake_status = SKL_CL_DMA_STATUS_NONE; | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | static void skl_cldma_stop(struct sst_dsp *ctx) | ||
166 | { | ||
167 | ctx->cl_dev.ops.cl_trigger(ctx, false); | ||
168 | } | ||
169 | |||
170 | static void skl_cldma_fill_buffer(struct sst_dsp *ctx, unsigned int size, | ||
171 | const void *curr_pos, bool intr_enable, bool trigger) | ||
172 | { | ||
173 | dev_dbg(ctx->dev, "Size: %x, intr_enable: %d\n", size, intr_enable); | ||
174 | dev_dbg(ctx->dev, "buf_pos_index:%d, trigger:%d\n", | ||
175 | ctx->cl_dev.dma_buffer_offset, trigger); | ||
176 | dev_dbg(ctx->dev, "spib position: %d\n", ctx->cl_dev.curr_spib_pos); | ||
177 | |||
178 | memcpy(ctx->cl_dev.dmab_data.area + ctx->cl_dev.dma_buffer_offset, | ||
179 | curr_pos, size); | ||
180 | |||
181 | if (ctx->cl_dev.curr_spib_pos == ctx->cl_dev.bufsize) | ||
182 | ctx->cl_dev.dma_buffer_offset = 0; | ||
183 | else | ||
184 | ctx->cl_dev.dma_buffer_offset = ctx->cl_dev.curr_spib_pos; | ||
185 | |||
186 | ctx->cl_dev.wait_condition = false; | ||
187 | |||
188 | if (intr_enable) | ||
189 | skl_cldma_int_enable(ctx); | ||
190 | |||
191 | ctx->cl_dev.ops.cl_setup_spb(ctx, ctx->cl_dev.curr_spib_pos, trigger); | ||
192 | if (trigger) | ||
193 | ctx->cl_dev.ops.cl_trigger(ctx, true); | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * The CL dma doesn't have any way to update the transfer status until a BDL | ||
198 | * buffer is fully transferred | ||
199 | * | ||
200 | * So Copying is divided in two parts. | ||
201 | * 1. Interrupt on buffer done where the size to be transferred is more than | ||
202 | * ring buffer size. | ||
203 | * 2. Polling on fw register to identify if data left to transferred doesn't | ||
204 | * fill the ring buffer. Caller takes care of polling the required status | ||
205 | * register to identify the transfer status. | ||
206 | */ | ||
207 | static int | ||
208 | skl_cldma_copy_to_buf(struct sst_dsp *ctx, const void *bin, u32 total_size) | ||
209 | { | ||
210 | int ret = 0; | ||
211 | bool start = true; | ||
212 | unsigned int excess_bytes; | ||
213 | u32 size; | ||
214 | unsigned int bytes_left = total_size; | ||
215 | const void *curr_pos = bin; | ||
216 | |||
217 | if (total_size <= 0) | ||
218 | return -EINVAL; | ||
219 | |||
220 | dev_dbg(ctx->dev, "%s: Total binary size: %u\n", __func__, bytes_left); | ||
221 | |||
222 | while (bytes_left) { | ||
223 | if (bytes_left > ctx->cl_dev.bufsize) { | ||
224 | |||
225 | /* | ||
226 | * dma transfers only till the write pointer as | ||
227 | * updated in spib | ||
228 | */ | ||
229 | if (ctx->cl_dev.curr_spib_pos == 0) | ||
230 | ctx->cl_dev.curr_spib_pos = ctx->cl_dev.bufsize; | ||
231 | |||
232 | size = ctx->cl_dev.bufsize; | ||
233 | skl_cldma_fill_buffer(ctx, size, curr_pos, true, start); | ||
234 | |||
235 | start = false; | ||
236 | ret = skl_cldma_wait_interruptible(ctx); | ||
237 | if (ret < 0) { | ||
238 | skl_cldma_stop(ctx); | ||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | } else { | ||
243 | skl_cldma_int_disable(ctx); | ||
244 | |||
245 | if ((ctx->cl_dev.curr_spib_pos + bytes_left) | ||
246 | <= ctx->cl_dev.bufsize) { | ||
247 | ctx->cl_dev.curr_spib_pos += bytes_left; | ||
248 | } else { | ||
249 | excess_bytes = bytes_left - | ||
250 | (ctx->cl_dev.bufsize - | ||
251 | ctx->cl_dev.curr_spib_pos); | ||
252 | ctx->cl_dev.curr_spib_pos = excess_bytes; | ||
253 | } | ||
254 | |||
255 | size = bytes_left; | ||
256 | skl_cldma_fill_buffer(ctx, size, | ||
257 | curr_pos, false, start); | ||
258 | } | ||
259 | bytes_left -= size; | ||
260 | curr_pos = curr_pos + size; | ||
261 | } | ||
262 | |||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | void skl_cldma_process_intr(struct sst_dsp *ctx) | ||
267 | { | ||
268 | u8 cl_dma_intr_status; | ||
269 | |||
270 | cl_dma_intr_status = | ||
271 | sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_CL_SD_STS); | ||
272 | |||
273 | if (!(cl_dma_intr_status & SKL_CL_DMA_SD_INT_COMPLETE)) | ||
274 | ctx->cl_dev.wake_status = SKL_CL_DMA_ERR; | ||
275 | else | ||
276 | ctx->cl_dev.wake_status = SKL_CL_DMA_BUF_COMPLETE; | ||
277 | |||
278 | ctx->cl_dev.wait_condition = true; | ||
279 | wake_up(&ctx->cl_dev.wait_queue); | ||
280 | } | ||
281 | |||
282 | int skl_cldma_prepare(struct sst_dsp *ctx) | ||
283 | { | ||
284 | int ret; | ||
285 | u32 *bdl; | ||
286 | |||
287 | ctx->cl_dev.bufsize = SKL_MAX_BUFFER_SIZE; | ||
288 | |||
289 | /* Allocate cl ops */ | ||
290 | ctx->cl_dev.ops.cl_setup_bdle = skl_cldma_setup_bdle; | ||
291 | ctx->cl_dev.ops.cl_setup_controller = skl_cldma_setup_controller; | ||
292 | ctx->cl_dev.ops.cl_setup_spb = skl_cldma_setup_spb; | ||
293 | ctx->cl_dev.ops.cl_cleanup_spb = skl_cldma_cleanup_spb; | ||
294 | ctx->cl_dev.ops.cl_trigger = skl_cldma_trigger; | ||
295 | ctx->cl_dev.ops.cl_cleanup_controller = skl_cldma_cleanup; | ||
296 | ctx->cl_dev.ops.cl_copy_to_dmabuf = skl_cldma_copy_to_buf; | ||
297 | ctx->cl_dev.ops.cl_stop_dma = skl_cldma_stop; | ||
298 | |||
299 | /* Allocate buffer*/ | ||
300 | ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev, | ||
301 | &ctx->cl_dev.dmab_data, ctx->cl_dev.bufsize); | ||
302 | if (ret < 0) { | ||
303 | dev_err(ctx->dev, "Alloc buffer for base fw failed: %x", ret); | ||
304 | return ret; | ||
305 | } | ||
306 | /* Setup Code loader BDL */ | ||
307 | ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev, | ||
308 | &ctx->cl_dev.dmab_bdl, PAGE_SIZE); | ||
309 | if (ret < 0) { | ||
310 | dev_err(ctx->dev, "Alloc buffer for blde failed: %x", ret); | ||
311 | ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data); | ||
312 | return ret; | ||
313 | } | ||
314 | bdl = (u32 *)ctx->cl_dev.dmab_bdl.area; | ||
315 | |||
316 | /* Allocate BDLs */ | ||
317 | ctx->cl_dev.ops.cl_setup_bdle(ctx, &ctx->cl_dev.dmab_data, | ||
318 | &bdl, ctx->cl_dev.bufsize, 1); | ||
319 | ctx->cl_dev.ops.cl_setup_controller(ctx, &ctx->cl_dev.dmab_bdl, | ||
320 | ctx->cl_dev.bufsize, ctx->cl_dev.frags); | ||
321 | |||
322 | ctx->cl_dev.curr_spib_pos = 0; | ||
323 | ctx->cl_dev.dma_buffer_offset = 0; | ||
324 | init_waitqueue_head(&ctx->cl_dev.wait_queue); | ||
325 | |||
326 | return ret; | ||
327 | } | ||
diff --git a/sound/soc/intel/skylake/skl-sst-cldma.h b/sound/soc/intel/skylake/skl-sst-cldma.h new file mode 100644 index 000000000000..99e4c86b6358 --- /dev/null +++ b/sound/soc/intel/skylake/skl-sst-cldma.h | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * Intel Code Loader DMA support | ||
3 | * | ||
4 | * Copyright (C) 2015, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as version 2, as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #ifndef SKL_SST_CLDMA_H_ | ||
17 | #define SKL_SST_CLDMA_H_ | ||
18 | |||
19 | #define FW_CL_STREAM_NUMBER 0x1 | ||
20 | |||
21 | #define DMA_ADDRESS_128_BITS_ALIGNMENT 7 | ||
22 | #define BDL_ALIGN(x) (x >> DMA_ADDRESS_128_BITS_ALIGNMENT) | ||
23 | |||
24 | #define SKL_ADSPIC_CL_DMA 0x2 | ||
25 | #define SKL_ADSPIS_CL_DMA 0x2 | ||
26 | #define SKL_CL_DMA_SD_INT_DESC_ERR 0x10 /* Descriptor error interrupt */ | ||
27 | #define SKL_CL_DMA_SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ | ||
28 | #define SKL_CL_DMA_SD_INT_COMPLETE 0x04 /* Buffer completion interrupt */ | ||
29 | |||
30 | /* Intel HD Audio Code Loader DMA Registers */ | ||
31 | |||
32 | #define HDA_ADSP_LOADER_BASE 0x80 | ||
33 | |||
34 | /* Stream Registers */ | ||
35 | #define SKL_ADSP_REG_CL_SD_CTL (HDA_ADSP_LOADER_BASE + 0x00) | ||
36 | #define SKL_ADSP_REG_CL_SD_STS (HDA_ADSP_LOADER_BASE + 0x03) | ||
37 | #define SKL_ADSP_REG_CL_SD_LPIB (HDA_ADSP_LOADER_BASE + 0x04) | ||
38 | #define SKL_ADSP_REG_CL_SD_CBL (HDA_ADSP_LOADER_BASE + 0x08) | ||
39 | #define SKL_ADSP_REG_CL_SD_LVI (HDA_ADSP_LOADER_BASE + 0x0c) | ||
40 | #define SKL_ADSP_REG_CL_SD_FIFOW (HDA_ADSP_LOADER_BASE + 0x0e) | ||
41 | #define SKL_ADSP_REG_CL_SD_FIFOSIZE (HDA_ADSP_LOADER_BASE + 0x10) | ||
42 | #define SKL_ADSP_REG_CL_SD_FORMAT (HDA_ADSP_LOADER_BASE + 0x12) | ||
43 | #define SKL_ADSP_REG_CL_SD_FIFOL (HDA_ADSP_LOADER_BASE + 0x14) | ||
44 | #define SKL_ADSP_REG_CL_SD_BDLPL (HDA_ADSP_LOADER_BASE + 0x18) | ||
45 | #define SKL_ADSP_REG_CL_SD_BDLPU (HDA_ADSP_LOADER_BASE + 0x1c) | ||
46 | |||
47 | /* CL: Software Position Based FIFO Capability Registers */ | ||
48 | #define SKL_ADSP_REG_CL_SPBFIFO (HDA_ADSP_LOADER_BASE + 0x20) | ||
49 | #define SKL_ADSP_REG_CL_SPBFIFO_SPBFCH (SKL_ADSP_REG_CL_SPBFIFO + 0x0) | ||
50 | #define SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL (SKL_ADSP_REG_CL_SPBFIFO + 0x4) | ||
51 | #define SKL_ADSP_REG_CL_SPBFIFO_SPIB (SKL_ADSP_REG_CL_SPBFIFO + 0x8) | ||
52 | #define SKL_ADSP_REG_CL_SPBFIFO_MAXFIFOS (SKL_ADSP_REG_CL_SPBFIFO + 0xc) | ||
53 | |||
54 | /* CL: Stream Descriptor x Control */ | ||
55 | |||
56 | /* Stream Reset */ | ||
57 | #define CL_SD_CTL_SRST_SHIFT 0 | ||
58 | #define CL_SD_CTL_SRST_MASK (1 << CL_SD_CTL_SRST_SHIFT) | ||
59 | #define CL_SD_CTL_SRST(x) \ | ||
60 | ((x << CL_SD_CTL_SRST_SHIFT) & CL_SD_CTL_SRST_MASK) | ||
61 | |||
62 | /* Stream Run */ | ||
63 | #define CL_SD_CTL_RUN_SHIFT 1 | ||
64 | #define CL_SD_CTL_RUN_MASK (1 << CL_SD_CTL_RUN_SHIFT) | ||
65 | #define CL_SD_CTL_RUN(x) \ | ||
66 | ((x << CL_SD_CTL_RUN_SHIFT) & CL_SD_CTL_RUN_MASK) | ||
67 | |||
68 | /* Interrupt On Completion Enable */ | ||
69 | #define CL_SD_CTL_IOCE_SHIFT 2 | ||
70 | #define CL_SD_CTL_IOCE_MASK (1 << CL_SD_CTL_IOCE_SHIFT) | ||
71 | #define CL_SD_CTL_IOCE(x) \ | ||
72 | ((x << CL_SD_CTL_IOCE_SHIFT) & CL_SD_CTL_IOCE_MASK) | ||
73 | |||
74 | /* FIFO Error Interrupt Enable */ | ||
75 | #define CL_SD_CTL_FEIE_SHIFT 3 | ||
76 | #define CL_SD_CTL_FEIE_MASK (1 << CL_SD_CTL_FEIE_SHIFT) | ||
77 | #define CL_SD_CTL_FEIE(x) \ | ||
78 | ((x << CL_SD_CTL_FEIE_SHIFT) & CL_SD_CTL_FEIE_MASK) | ||
79 | |||
80 | /* Descriptor Error Interrupt Enable */ | ||
81 | #define CL_SD_CTL_DEIE_SHIFT 4 | ||
82 | #define CL_SD_CTL_DEIE_MASK (1 << CL_SD_CTL_DEIE_SHIFT) | ||
83 | #define CL_SD_CTL_DEIE(x) \ | ||
84 | ((x << CL_SD_CTL_DEIE_SHIFT) & CL_SD_CTL_DEIE_MASK) | ||
85 | |||
86 | /* FIFO Limit Change */ | ||
87 | #define CL_SD_CTL_FIFOLC_SHIFT 5 | ||
88 | #define CL_SD_CTL_FIFOLC_MASK (1 << CL_SD_CTL_FIFOLC_SHIFT) | ||
89 | #define CL_SD_CTL_FIFOLC(x) \ | ||
90 | ((x << CL_SD_CTL_FIFOLC_SHIFT) & CL_SD_CTL_FIFOLC_MASK) | ||
91 | |||
92 | /* Stripe Control */ | ||
93 | #define CL_SD_CTL_STRIPE_SHIFT 16 | ||
94 | #define CL_SD_CTL_STRIPE_MASK (0x3 << CL_SD_CTL_STRIPE_SHIFT) | ||
95 | #define CL_SD_CTL_STRIPE(x) \ | ||
96 | ((x << CL_SD_CTL_STRIPE_SHIFT) & CL_SD_CTL_STRIPE_MASK) | ||
97 | |||
98 | /* Traffic Priority */ | ||
99 | #define CL_SD_CTL_TP_SHIFT 18 | ||
100 | #define CL_SD_CTL_TP_MASK (1 << CL_SD_CTL_TP_SHIFT) | ||
101 | #define CL_SD_CTL_TP(x) \ | ||
102 | ((x << CL_SD_CTL_TP_SHIFT) & CL_SD_CTL_TP_MASK) | ||
103 | |||
104 | /* Bidirectional Direction Control */ | ||
105 | #define CL_SD_CTL_DIR_SHIFT 19 | ||
106 | #define CL_SD_CTL_DIR_MASK (1 << CL_SD_CTL_DIR_SHIFT) | ||
107 | #define CL_SD_CTL_DIR(x) \ | ||
108 | ((x << CL_SD_CTL_DIR_SHIFT) & CL_SD_CTL_DIR_MASK) | ||
109 | |||
110 | /* Stream Number */ | ||
111 | #define CL_SD_CTL_STRM_SHIFT 20 | ||
112 | #define CL_SD_CTL_STRM_MASK (0xf << CL_SD_CTL_STRM_SHIFT) | ||
113 | #define CL_SD_CTL_STRM(x) \ | ||
114 | ((x << CL_SD_CTL_STRM_SHIFT) & CL_SD_CTL_STRM_MASK) | ||
115 | |||
116 | /* CL: Stream Descriptor x Status */ | ||
117 | |||
118 | /* Buffer Completion Interrupt Status */ | ||
119 | #define CL_SD_STS_BCIS(x) CL_SD_CTL_IOCE(x) | ||
120 | |||
121 | /* FIFO Error */ | ||
122 | #define CL_SD_STS_FIFOE(x) CL_SD_CTL_FEIE(x) | ||
123 | |||
124 | /* Descriptor Error */ | ||
125 | #define CL_SD_STS_DESE(x) CL_SD_CTL_DEIE(x) | ||
126 | |||
127 | /* FIFO Ready */ | ||
128 | #define CL_SD_STS_FIFORDY(x) CL_SD_CTL_FIFOLC(x) | ||
129 | |||
130 | |||
131 | /* CL: Stream Descriptor x Last Valid Index */ | ||
132 | #define CL_SD_LVI_SHIFT 0 | ||
133 | #define CL_SD_LVI_MASK (0xff << CL_SD_LVI_SHIFT) | ||
134 | #define CL_SD_LVI(x) ((x << CL_SD_LVI_SHIFT) & CL_SD_LVI_MASK) | ||
135 | |||
136 | /* CL: Stream Descriptor x FIFO Eviction Watermark */ | ||
137 | #define CL_SD_FIFOW_SHIFT 0 | ||
138 | #define CL_SD_FIFOW_MASK (0x7 << CL_SD_FIFOW_SHIFT) | ||
139 | #define CL_SD_FIFOW(x) \ | ||
140 | ((x << CL_SD_FIFOW_SHIFT) & CL_SD_FIFOW_MASK) | ||
141 | |||
142 | /* CL: Stream Descriptor x Buffer Descriptor List Pointer Lower Base Address */ | ||
143 | |||
144 | /* Protect Bits */ | ||
145 | #define CL_SD_BDLPLBA_PROT_SHIFT 0 | ||
146 | #define CL_SD_BDLPLBA_PROT_MASK (1 << CL_SD_BDLPLBA_PROT_SHIFT) | ||
147 | #define CL_SD_BDLPLBA_PROT(x) \ | ||
148 | ((x << CL_SD_BDLPLBA_PROT_SHIFT) & CL_SD_BDLPLBA_PROT_MASK) | ||
149 | |||
150 | /* Buffer Descriptor List Lower Base Address */ | ||
151 | #define CL_SD_BDLPLBA_SHIFT 7 | ||
152 | #define CL_SD_BDLPLBA_MASK (0x1ffffff << CL_SD_BDLPLBA_SHIFT) | ||
153 | #define CL_SD_BDLPLBA(x) \ | ||
154 | ((BDL_ALIGN(lower_32_bits(x)) << CL_SD_BDLPLBA_SHIFT) & CL_SD_BDLPLBA_MASK) | ||
155 | |||
156 | /* Buffer Descriptor List Upper Base Address */ | ||
157 | #define CL_SD_BDLPUBA_SHIFT 0 | ||
158 | #define CL_SD_BDLPUBA_MASK (0xffffffff << CL_SD_BDLPUBA_SHIFT) | ||
159 | #define CL_SD_BDLPUBA(x) \ | ||
160 | ((upper_32_bits(x) << CL_SD_BDLPUBA_SHIFT) & CL_SD_BDLPUBA_MASK) | ||
161 | |||
162 | /* | ||
163 | * Code Loader - Software Position Based FIFO | ||
164 | * Capability Registers x Software Position Based FIFO Header | ||
165 | */ | ||
166 | |||
167 | /* Next Capability Pointer */ | ||
168 | #define CL_SPBFIFO_SPBFCH_PTR_SHIFT 0 | ||
169 | #define CL_SPBFIFO_SPBFCH_PTR_MASK (0xff << CL_SPBFIFO_SPBFCH_PTR_SHIFT) | ||
170 | #define CL_SPBFIFO_SPBFCH_PTR(x) \ | ||
171 | ((x << CL_SPBFIFO_SPBFCH_PTR_SHIFT) & CL_SPBFIFO_SPBFCH_PTR_MASK) | ||
172 | |||
173 | /* Capability Identifier */ | ||
174 | #define CL_SPBFIFO_SPBFCH_ID_SHIFT 16 | ||
175 | #define CL_SPBFIFO_SPBFCH_ID_MASK (0xfff << CL_SPBFIFO_SPBFCH_ID_SHIFT) | ||
176 | #define CL_SPBFIFO_SPBFCH_ID(x) \ | ||
177 | ((x << CL_SPBFIFO_SPBFCH_ID_SHIFT) & CL_SPBFIFO_SPBFCH_ID_MASK) | ||
178 | |||
179 | /* Capability Version */ | ||
180 | #define CL_SPBFIFO_SPBFCH_VER_SHIFT 28 | ||
181 | #define CL_SPBFIFO_SPBFCH_VER_MASK (0xf << CL_SPBFIFO_SPBFCH_VER_SHIFT) | ||
182 | #define CL_SPBFIFO_SPBFCH_VER(x) \ | ||
183 | ((x << CL_SPBFIFO_SPBFCH_VER_SHIFT) & CL_SPBFIFO_SPBFCH_VER_MASK) | ||
184 | |||
185 | /* Software Position in Buffer Enable */ | ||
186 | #define CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT 0 | ||
187 | #define CL_SPBFIFO_SPBFCCTL_SPIBE_MASK (1 << CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT) | ||
188 | #define CL_SPBFIFO_SPBFCCTL_SPIBE(x) \ | ||
189 | ((x << CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT) & CL_SPBFIFO_SPBFCCTL_SPIBE_MASK) | ||
190 | |||
191 | /* SST IPC SKL defines */ | ||
192 | #define SKL_WAIT_TIMEOUT 500 /* 500 msec */ | ||
193 | #define SKL_MAX_BUFFER_SIZE (32 * PAGE_SIZE) | ||
194 | |||
195 | enum skl_cl_dma_wake_states { | ||
196 | SKL_CL_DMA_STATUS_NONE = 0, | ||
197 | SKL_CL_DMA_BUF_COMPLETE, | ||
198 | SKL_CL_DMA_ERR, /* TODO: Expand the error states */ | ||
199 | }; | ||
200 | |||
201 | struct sst_dsp; | ||
202 | |||
203 | struct skl_cl_dev_ops { | ||
204 | void (*cl_setup_bdle)(struct sst_dsp *ctx, | ||
205 | struct snd_dma_buffer *dmab_data, | ||
206 | u32 **bdlp, int size, int with_ioc); | ||
207 | void (*cl_setup_controller)(struct sst_dsp *ctx, | ||
208 | struct snd_dma_buffer *dmab_bdl, | ||
209 | unsigned int max_size, u32 page_count); | ||
210 | void (*cl_setup_spb)(struct sst_dsp *ctx, | ||
211 | unsigned int size, bool enable); | ||
212 | void (*cl_cleanup_spb)(struct sst_dsp *ctx); | ||
213 | void (*cl_trigger)(struct sst_dsp *ctx, bool enable); | ||
214 | void (*cl_cleanup_controller)(struct sst_dsp *ctx); | ||
215 | int (*cl_copy_to_dmabuf)(struct sst_dsp *ctx, | ||
216 | const void *bin, u32 size); | ||
217 | void (*cl_stop_dma)(struct sst_dsp *ctx); | ||
218 | }; | ||
219 | |||
220 | /** | ||
221 | * skl_cl_dev - holds information for code loader dma transfer | ||
222 | * | ||
223 | * @dmab_data: buffer pointer | ||
224 | * @dmab_bdl: buffer descriptor list | ||
225 | * @bufsize: ring buffer size | ||
226 | * @frags: Last valid buffer descriptor index in the BDL | ||
227 | * @curr_spib_pos: Current position in ring buffer | ||
228 | * @dma_buffer_offset: dma buffer offset | ||
229 | * @ops: operations supported on CL dma | ||
230 | * @wait_queue: wait queue to wake for wake event | ||
231 | * @wake_status: DMA wake status | ||
232 | * @wait_condition: condition to wait on wait queue | ||
233 | * @cl_dma_lock: for synchronized access to cldma | ||
234 | */ | ||
235 | struct skl_cl_dev { | ||
236 | struct snd_dma_buffer dmab_data; | ||
237 | struct snd_dma_buffer dmab_bdl; | ||
238 | |||
239 | unsigned int bufsize; | ||
240 | unsigned int frags; | ||
241 | |||
242 | unsigned int curr_spib_pos; | ||
243 | unsigned int dma_buffer_offset; | ||
244 | struct skl_cl_dev_ops ops; | ||
245 | |||
246 | wait_queue_head_t wait_queue; | ||
247 | int wake_status; | ||
248 | bool wait_condition; | ||
249 | }; | ||
250 | |||
251 | #endif /* SKL_SST_CLDMA_H_ */ | ||
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c new file mode 100644 index 000000000000..94875b008b0b --- /dev/null +++ b/sound/soc/intel/skylake/skl-sst-dsp.c | |||
@@ -0,0 +1,342 @@ | |||
1 | /* | ||
2 | * skl-sst-dsp.c - SKL SST library generic function | ||
3 | * | ||
4 | * Copyright (C) 2014-15, Intel Corporation. | ||
5 | * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> | ||
6 | * Jeeja KP <jeeja.kp@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as version 2, as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | */ | ||
18 | #include <sound/pcm.h> | ||
19 | |||
20 | #include "../common/sst-dsp.h" | ||
21 | #include "../common/sst-ipc.h" | ||
22 | #include "../common/sst-dsp-priv.h" | ||
23 | #include "skl-sst-ipc.h" | ||
24 | |||
25 | /* various timeout values */ | ||
26 | #define SKL_DSP_PU_TO 50 | ||
27 | #define SKL_DSP_PD_TO 50 | ||
28 | #define SKL_DSP_RESET_TO 50 | ||
29 | |||
30 | void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) | ||
31 | { | ||
32 | mutex_lock(&ctx->mutex); | ||
33 | ctx->sst_state = state; | ||
34 | mutex_unlock(&ctx->mutex); | ||
35 | } | ||
36 | |||
37 | static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) | ||
38 | { | ||
39 | int ret; | ||
40 | |||
41 | /* update bits */ | ||
42 | sst_dsp_shim_update_bits_unlocked(ctx, | ||
43 | SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK, | ||
44 | SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)); | ||
45 | |||
46 | /* poll with timeout to check if operation successful */ | ||
47 | ret = sst_dsp_register_poll(ctx, | ||
48 | SKL_ADSP_REG_ADSPCS, | ||
49 | SKL_ADSPCS_CRST_MASK, | ||
50 | SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK), | ||
51 | SKL_DSP_RESET_TO, | ||
52 | "Set reset"); | ||
53 | if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & | ||
54 | SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != | ||
55 | SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) { | ||
56 | dev_err(ctx->dev, "Set reset state failed\n"); | ||
57 | ret = -EIO; | ||
58 | } | ||
59 | |||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) | ||
64 | { | ||
65 | int ret; | ||
66 | |||
67 | dev_dbg(ctx->dev, "In %s\n", __func__); | ||
68 | |||
69 | /* update bits */ | ||
70 | sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, | ||
71 | SKL_ADSPCS_CRST_MASK, 0); | ||
72 | |||
73 | /* poll with timeout to check if operation successful */ | ||
74 | ret = sst_dsp_register_poll(ctx, | ||
75 | SKL_ADSP_REG_ADSPCS, | ||
76 | SKL_ADSPCS_CRST_MASK, | ||
77 | 0, | ||
78 | SKL_DSP_RESET_TO, | ||
79 | "Unset reset"); | ||
80 | |||
81 | if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & | ||
82 | SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 0) { | ||
83 | dev_err(ctx->dev, "Unset reset state failed\n"); | ||
84 | ret = -EIO; | ||
85 | } | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) | ||
91 | { | ||
92 | int val; | ||
93 | bool is_enable; | ||
94 | |||
95 | val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); | ||
96 | |||
97 | is_enable = ((val & SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) && | ||
98 | (val & SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)) && | ||
99 | !(val & SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) && | ||
100 | !(val & SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK))); | ||
101 | |||
102 | dev_dbg(ctx->dev, "DSP core is enabled=%d\n", is_enable); | ||
103 | return is_enable; | ||
104 | } | ||
105 | |||
106 | static int skl_dsp_reset_core(struct sst_dsp *ctx) | ||
107 | { | ||
108 | /* stall core */ | ||
109 | sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS, | ||
110 | sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & | ||
111 | SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)); | ||
112 | |||
113 | /* set reset state */ | ||
114 | return skl_dsp_core_set_reset_state(ctx); | ||
115 | } | ||
116 | |||
117 | static int skl_dsp_start_core(struct sst_dsp *ctx) | ||
118 | { | ||
119 | int ret; | ||
120 | |||
121 | /* unset reset state */ | ||
122 | ret = skl_dsp_core_unset_reset_state(ctx); | ||
123 | if (ret < 0) { | ||
124 | dev_dbg(ctx->dev, "dsp unset reset fails\n"); | ||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | /* run core */ | ||
129 | dev_dbg(ctx->dev, "run core...\n"); | ||
130 | sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS, | ||
131 | sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & | ||
132 | ~SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)); | ||
133 | |||
134 | if (!is_skl_dsp_core_enable(ctx)) { | ||
135 | skl_dsp_reset_core(ctx); | ||
136 | dev_err(ctx->dev, "DSP core enable failed\n"); | ||
137 | ret = -EIO; | ||
138 | } | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | static int skl_dsp_core_power_up(struct sst_dsp *ctx) | ||
144 | { | ||
145 | int ret; | ||
146 | |||
147 | /* update bits */ | ||
148 | sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, | ||
149 | SKL_ADSPCS_SPA_MASK, SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)); | ||
150 | |||
151 | /* poll with timeout to check if operation successful */ | ||
152 | ret = sst_dsp_register_poll(ctx, | ||
153 | SKL_ADSP_REG_ADSPCS, | ||
154 | SKL_ADSPCS_CPA_MASK, | ||
155 | SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK), | ||
156 | SKL_DSP_PU_TO, | ||
157 | "Power up"); | ||
158 | |||
159 | if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & | ||
160 | SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) != | ||
161 | SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) { | ||
162 | dev_err(ctx->dev, "DSP core power up failed\n"); | ||
163 | ret = -EIO; | ||
164 | } | ||
165 | |||
166 | return ret; | ||
167 | } | ||
168 | |||
169 | static int skl_dsp_core_power_down(struct sst_dsp *ctx) | ||
170 | { | ||
171 | /* update bits */ | ||
172 | sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, | ||
173 | SKL_ADSPCS_SPA_MASK, 0); | ||
174 | |||
175 | /* poll with timeout to check if operation successful */ | ||
176 | return sst_dsp_register_poll(ctx, | ||
177 | SKL_ADSP_REG_ADSPCS, | ||
178 | SKL_ADSPCS_SPA_MASK, | ||
179 | 0, | ||
180 | SKL_DSP_PD_TO, | ||
181 | "Power down"); | ||
182 | } | ||
183 | |||
184 | static int skl_dsp_enable_core(struct sst_dsp *ctx) | ||
185 | { | ||
186 | int ret; | ||
187 | |||
188 | /* power up */ | ||
189 | ret = skl_dsp_core_power_up(ctx); | ||
190 | if (ret < 0) { | ||
191 | dev_dbg(ctx->dev, "dsp core power up failed\n"); | ||
192 | return ret; | ||
193 | } | ||
194 | |||
195 | return skl_dsp_start_core(ctx); | ||
196 | } | ||
197 | |||
198 | int skl_dsp_disable_core(struct sst_dsp *ctx) | ||
199 | { | ||
200 | int ret; | ||
201 | |||
202 | ret = skl_dsp_reset_core(ctx); | ||
203 | if (ret < 0) { | ||
204 | dev_err(ctx->dev, "dsp core reset failed\n"); | ||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | /* power down core*/ | ||
209 | ret = skl_dsp_core_power_down(ctx); | ||
210 | if (ret < 0) { | ||
211 | dev_err(ctx->dev, "dsp core power down failed\n"); | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | if (is_skl_dsp_core_enable(ctx)) { | ||
216 | dev_err(ctx->dev, "DSP core disable failed\n"); | ||
217 | ret = -EIO; | ||
218 | } | ||
219 | |||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | int skl_dsp_boot(struct sst_dsp *ctx) | ||
224 | { | ||
225 | int ret; | ||
226 | |||
227 | if (is_skl_dsp_core_enable(ctx)) { | ||
228 | dev_dbg(ctx->dev, "dsp core is already enabled, so reset the dap core\n"); | ||
229 | ret = skl_dsp_reset_core(ctx); | ||
230 | if (ret < 0) { | ||
231 | dev_err(ctx->dev, "dsp reset failed\n"); | ||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | ret = skl_dsp_start_core(ctx); | ||
236 | if (ret < 0) { | ||
237 | dev_err(ctx->dev, "dsp start failed\n"); | ||
238 | return ret; | ||
239 | } | ||
240 | } else { | ||
241 | dev_dbg(ctx->dev, "disable and enable to make sure DSP is invalid state\n"); | ||
242 | ret = skl_dsp_disable_core(ctx); | ||
243 | |||
244 | if (ret < 0) { | ||
245 | dev_err(ctx->dev, "dsp disable core failes\n"); | ||
246 | return ret; | ||
247 | } | ||
248 | ret = skl_dsp_enable_core(ctx); | ||
249 | } | ||
250 | |||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) | ||
255 | { | ||
256 | struct sst_dsp *ctx = dev_id; | ||
257 | u32 val; | ||
258 | irqreturn_t result = IRQ_NONE; | ||
259 | |||
260 | spin_lock(&ctx->spinlock); | ||
261 | |||
262 | val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS); | ||
263 | ctx->intr_status = val; | ||
264 | |||
265 | if (val & SKL_ADSPIS_IPC) { | ||
266 | skl_ipc_int_disable(ctx); | ||
267 | result = IRQ_WAKE_THREAD; | ||
268 | } | ||
269 | |||
270 | if (val & SKL_ADSPIS_CL_DMA) { | ||
271 | skl_cldma_int_disable(ctx); | ||
272 | result = IRQ_WAKE_THREAD; | ||
273 | } | ||
274 | |||
275 | spin_unlock(&ctx->spinlock); | ||
276 | |||
277 | return result; | ||
278 | } | ||
279 | |||
280 | int skl_dsp_wake(struct sst_dsp *ctx) | ||
281 | { | ||
282 | return ctx->fw_ops.set_state_D0(ctx); | ||
283 | } | ||
284 | EXPORT_SYMBOL_GPL(skl_dsp_wake); | ||
285 | |||
286 | int skl_dsp_sleep(struct sst_dsp *ctx) | ||
287 | { | ||
288 | return ctx->fw_ops.set_state_D3(ctx); | ||
289 | } | ||
290 | EXPORT_SYMBOL_GPL(skl_dsp_sleep); | ||
291 | |||
292 | struct sst_dsp *skl_dsp_ctx_init(struct device *dev, | ||
293 | struct sst_dsp_device *sst_dev, int irq) | ||
294 | { | ||
295 | int ret; | ||
296 | struct sst_dsp *sst; | ||
297 | |||
298 | sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); | ||
299 | if (sst == NULL) | ||
300 | return NULL; | ||
301 | |||
302 | spin_lock_init(&sst->spinlock); | ||
303 | mutex_init(&sst->mutex); | ||
304 | sst->dev = dev; | ||
305 | sst->sst_dev = sst_dev; | ||
306 | sst->irq = irq; | ||
307 | sst->ops = sst_dev->ops; | ||
308 | sst->thread_context = sst_dev->thread_context; | ||
309 | |||
310 | /* Initialise SST Audio DSP */ | ||
311 | if (sst->ops->init) { | ||
312 | ret = sst->ops->init(sst, NULL); | ||
313 | if (ret < 0) | ||
314 | return NULL; | ||
315 | } | ||
316 | |||
317 | /* Register the ISR */ | ||
318 | ret = request_threaded_irq(sst->irq, sst->ops->irq_handler, | ||
319 | sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); | ||
320 | if (ret) { | ||
321 | dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n", | ||
322 | sst->irq); | ||
323 | return NULL; | ||
324 | } | ||
325 | |||
326 | return sst; | ||
327 | } | ||
328 | |||
329 | void skl_dsp_free(struct sst_dsp *dsp) | ||
330 | { | ||
331 | skl_ipc_int_disable(dsp); | ||
332 | |||
333 | free_irq(dsp->irq, dsp); | ||
334 | skl_dsp_disable_core(dsp); | ||
335 | } | ||
336 | EXPORT_SYMBOL_GPL(skl_dsp_free); | ||
337 | |||
338 | bool is_skl_dsp_running(struct sst_dsp *ctx) | ||
339 | { | ||
340 | return (ctx->sst_state == SKL_DSP_RUNNING); | ||
341 | } | ||
342 | EXPORT_SYMBOL_GPL(is_skl_dsp_running); | ||
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h new file mode 100644 index 000000000000..6bfcef449bdc --- /dev/null +++ b/sound/soc/intel/skylake/skl-sst-dsp.h | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * Skylake SST DSP Support | ||
3 | * | ||
4 | * Copyright (C) 2014-15, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as version 2, as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #ifndef __SKL_SST_DSP_H__ | ||
17 | #define __SKL_SST_DSP_H__ | ||
18 | |||
19 | #include <linux/interrupt.h> | ||
20 | #include <sound/memalloc.h> | ||
21 | #include "skl-sst-cldma.h" | ||
22 | |||
23 | struct sst_dsp; | ||
24 | struct skl_sst; | ||
25 | struct sst_dsp_device; | ||
26 | |||
27 | /* Intel HD Audio General DSP Registers */ | ||
28 | #define SKL_ADSP_GEN_BASE 0x0 | ||
29 | #define SKL_ADSP_REG_ADSPCS (SKL_ADSP_GEN_BASE + 0x04) | ||
30 | #define SKL_ADSP_REG_ADSPIC (SKL_ADSP_GEN_BASE + 0x08) | ||
31 | #define SKL_ADSP_REG_ADSPIS (SKL_ADSP_GEN_BASE + 0x0C) | ||
32 | #define SKL_ADSP_REG_ADSPIC2 (SKL_ADSP_GEN_BASE + 0x10) | ||
33 | #define SKL_ADSP_REG_ADSPIS2 (SKL_ADSP_GEN_BASE + 0x14) | ||
34 | |||
35 | /* Intel HD Audio Inter-Processor Communication Registers */ | ||
36 | #define SKL_ADSP_IPC_BASE 0x40 | ||
37 | #define SKL_ADSP_REG_HIPCT (SKL_ADSP_IPC_BASE + 0x00) | ||
38 | #define SKL_ADSP_REG_HIPCTE (SKL_ADSP_IPC_BASE + 0x04) | ||
39 | #define SKL_ADSP_REG_HIPCI (SKL_ADSP_IPC_BASE + 0x08) | ||
40 | #define SKL_ADSP_REG_HIPCIE (SKL_ADSP_IPC_BASE + 0x0C) | ||
41 | #define SKL_ADSP_REG_HIPCCTL (SKL_ADSP_IPC_BASE + 0x10) | ||
42 | |||
43 | /* HIPCI */ | ||
44 | #define SKL_ADSP_REG_HIPCI_BUSY BIT(31) | ||
45 | |||
46 | /* HIPCIE */ | ||
47 | #define SKL_ADSP_REG_HIPCIE_DONE BIT(30) | ||
48 | |||
49 | /* HIPCCTL */ | ||
50 | #define SKL_ADSP_REG_HIPCCTL_DONE BIT(1) | ||
51 | #define SKL_ADSP_REG_HIPCCTL_BUSY BIT(0) | ||
52 | |||
53 | /* HIPCT */ | ||
54 | #define SKL_ADSP_REG_HIPCT_BUSY BIT(31) | ||
55 | |||
56 | /* Intel HD Audio SRAM Window 1 */ | ||
57 | #define SKL_ADSP_SRAM1_BASE 0xA000 | ||
58 | |||
59 | #define SKL_ADSP_MMIO_LEN 0x10000 | ||
60 | |||
61 | #define SKL_ADSP_W0_STAT_SZ 0x800 | ||
62 | |||
63 | #define SKL_ADSP_W0_UP_SZ 0x800 | ||
64 | |||
65 | #define SKL_ADSP_W1_SZ 0x1000 | ||
66 | |||
67 | #define SKL_FW_STS_MASK 0xf | ||
68 | |||
69 | #define SKL_FW_INIT 0x1 | ||
70 | #define SKL_FW_RFW_START 0xf | ||
71 | |||
72 | #define SKL_ADSPIC_IPC 1 | ||
73 | #define SKL_ADSPIS_IPC 1 | ||
74 | |||
75 | /* ADSPCS - Audio DSP Control & Status */ | ||
76 | #define SKL_DSP_CORES 1 | ||
77 | #define SKL_DSP_CORE0_MASK 1 | ||
78 | #define SKL_DSP_CORES_MASK ((1 << SKL_DSP_CORES) - 1) | ||
79 | |||
80 | /* Core Reset - asserted high */ | ||
81 | #define SKL_ADSPCS_CRST_SHIFT 0 | ||
82 | #define SKL_ADSPCS_CRST_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_CRST_SHIFT) | ||
83 | #define SKL_ADSPCS_CRST(x) ((x << SKL_ADSPCS_CRST_SHIFT) & SKL_ADSPCS_CRST_MASK) | ||
84 | |||
85 | /* Core run/stall - when set to '1' core is stalled */ | ||
86 | #define SKL_ADSPCS_CSTALL_SHIFT 8 | ||
87 | #define SKL_ADSPCS_CSTALL_MASK (SKL_DSP_CORES_MASK << \ | ||
88 | SKL_ADSPCS_CSTALL_SHIFT) | ||
89 | #define SKL_ADSPCS_CSTALL(x) ((x << SKL_ADSPCS_CSTALL_SHIFT) & \ | ||
90 | SKL_ADSPCS_CSTALL_MASK) | ||
91 | |||
92 | /* Set Power Active - when set to '1' turn cores on */ | ||
93 | #define SKL_ADSPCS_SPA_SHIFT 16 | ||
94 | #define SKL_ADSPCS_SPA_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_SPA_SHIFT) | ||
95 | #define SKL_ADSPCS_SPA(x) ((x << SKL_ADSPCS_SPA_SHIFT) & SKL_ADSPCS_SPA_MASK) | ||
96 | |||
97 | /* Current Power Active - power status of cores, set by hardware */ | ||
98 | #define SKL_ADSPCS_CPA_SHIFT 24 | ||
99 | #define SKL_ADSPCS_CPA_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_CPA_SHIFT) | ||
100 | #define SKL_ADSPCS_CPA(x) ((x << SKL_ADSPCS_CPA_SHIFT) & SKL_ADSPCS_CPA_MASK) | ||
101 | |||
102 | #define SST_DSP_POWER_D0 0x0 /* full On */ | ||
103 | #define SST_DSP_POWER_D3 0x3 /* Off */ | ||
104 | |||
105 | enum skl_dsp_states { | ||
106 | SKL_DSP_RUNNING = 1, | ||
107 | SKL_DSP_RESET, | ||
108 | }; | ||
109 | |||
110 | struct skl_dsp_fw_ops { | ||
111 | int (*load_fw)(struct sst_dsp *ctx); | ||
112 | /* FW module parser/loader */ | ||
113 | int (*parse_fw)(struct sst_dsp *ctx); | ||
114 | int (*set_state_D0)(struct sst_dsp *ctx); | ||
115 | int (*set_state_D3)(struct sst_dsp *ctx); | ||
116 | unsigned int (*get_fw_errcode)(struct sst_dsp *ctx); | ||
117 | }; | ||
118 | |||
119 | struct skl_dsp_loader_ops { | ||
120 | int (*alloc_dma_buf)(struct device *dev, | ||
121 | struct snd_dma_buffer *dmab, size_t size); | ||
122 | int (*free_dma_buf)(struct device *dev, | ||
123 | struct snd_dma_buffer *dmab); | ||
124 | }; | ||
125 | |||
126 | void skl_cldma_process_intr(struct sst_dsp *ctx); | ||
127 | void skl_cldma_int_disable(struct sst_dsp *ctx); | ||
128 | int skl_cldma_prepare(struct sst_dsp *ctx); | ||
129 | |||
130 | void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); | ||
131 | struct sst_dsp *skl_dsp_ctx_init(struct device *dev, | ||
132 | struct sst_dsp_device *sst_dev, int irq); | ||
133 | int skl_dsp_disable_core(struct sst_dsp *ctx); | ||
134 | bool is_skl_dsp_running(struct sst_dsp *ctx); | ||
135 | irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id); | ||
136 | int skl_dsp_wake(struct sst_dsp *ctx); | ||
137 | int skl_dsp_sleep(struct sst_dsp *ctx); | ||
138 | void skl_dsp_free(struct sst_dsp *dsp); | ||
139 | |||
140 | int skl_dsp_boot(struct sst_dsp *ctx); | ||
141 | int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | ||
142 | struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp); | ||
143 | void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); | ||
144 | |||
145 | #endif /*__SKL_SST_DSP_H__*/ | ||
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c new file mode 100644 index 000000000000..937a0a3a63a0 --- /dev/null +++ b/sound/soc/intel/skylake/skl-sst-ipc.c | |||
@@ -0,0 +1,771 @@ | |||
1 | /* | ||
2 | * skl-sst-ipc.c - Intel skl IPC Support | ||
3 | * | ||
4 | * Copyright (C) 2014-15, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as version 2, as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | #include <linux/device.h> | ||
16 | |||
17 | #include "../common/sst-dsp.h" | ||
18 | #include "../common/sst-dsp-priv.h" | ||
19 | #include "skl-sst-dsp.h" | ||
20 | #include "skl-sst-ipc.h" | ||
21 | |||
22 | |||
23 | #define IPC_IXC_STATUS_BITS 24 | ||
24 | |||
25 | /* Global Message - Generic */ | ||
26 | #define IPC_GLB_TYPE_SHIFT 24 | ||
27 | #define IPC_GLB_TYPE_MASK (0xf << IPC_GLB_TYPE_SHIFT) | ||
28 | #define IPC_GLB_TYPE(x) ((x) << IPC_GLB_TYPE_SHIFT) | ||
29 | |||
30 | /* Global Message - Reply */ | ||
31 | #define IPC_GLB_REPLY_STATUS_SHIFT 24 | ||
32 | #define IPC_GLB_REPLY_STATUS_MASK ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1) | ||
33 | #define IPC_GLB_REPLY_STATUS(x) ((x) << IPC_GLB_REPLY_STATUS_SHIFT) | ||
34 | |||
35 | #define IPC_TIMEOUT_MSECS 3000 | ||
36 | |||
37 | #define IPC_EMPTY_LIST_SIZE 8 | ||
38 | |||
39 | #define IPC_MSG_TARGET_SHIFT 30 | ||
40 | #define IPC_MSG_TARGET_MASK 0x1 | ||
41 | #define IPC_MSG_TARGET(x) (((x) & IPC_MSG_TARGET_MASK) \ | ||
42 | << IPC_MSG_TARGET_SHIFT) | ||
43 | |||
44 | #define IPC_MSG_DIR_SHIFT 29 | ||
45 | #define IPC_MSG_DIR_MASK 0x1 | ||
46 | #define IPC_MSG_DIR(x) (((x) & IPC_MSG_DIR_MASK) \ | ||
47 | << IPC_MSG_DIR_SHIFT) | ||
48 | /* Global Notification Message */ | ||
49 | #define IPC_GLB_NOTIFY_TYPE_SHIFT 16 | ||
50 | #define IPC_GLB_NOTIFY_TYPE_MASK 0xFF | ||
51 | #define IPC_GLB_NOTIFY_TYPE(x) (((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \ | ||
52 | & IPC_GLB_NOTIFY_TYPE_MASK) | ||
53 | |||
54 | #define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT 24 | ||
55 | #define IPC_GLB_NOTIFY_MSG_TYPE_MASK 0x1F | ||
56 | #define IPC_GLB_NOTIFY_MSG_TYPE(x) (((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT) \ | ||
57 | & IPC_GLB_NOTIFY_MSG_TYPE_MASK) | ||
58 | |||
59 | #define IPC_GLB_NOTIFY_RSP_SHIFT 29 | ||
60 | #define IPC_GLB_NOTIFY_RSP_MASK 0x1 | ||
61 | #define IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \ | ||
62 | & IPC_GLB_NOTIFY_RSP_MASK) | ||
63 | |||
64 | /* Pipeline operations */ | ||
65 | |||
66 | /* Create pipeline message */ | ||
67 | #define IPC_PPL_MEM_SIZE_SHIFT 0 | ||
68 | #define IPC_PPL_MEM_SIZE_MASK 0x7FF | ||
69 | #define IPC_PPL_MEM_SIZE(x) (((x) & IPC_PPL_MEM_SIZE_MASK) \ | ||
70 | << IPC_PPL_MEM_SIZE_SHIFT) | ||
71 | |||
72 | #define IPC_PPL_TYPE_SHIFT 11 | ||
73 | #define IPC_PPL_TYPE_MASK 0x1F | ||
74 | #define IPC_PPL_TYPE(x) (((x) & IPC_PPL_TYPE_MASK) \ | ||
75 | << IPC_PPL_TYPE_SHIFT) | ||
76 | |||
77 | #define IPC_INSTANCE_ID_SHIFT 16 | ||
78 | #define IPC_INSTANCE_ID_MASK 0xFF | ||
79 | #define IPC_INSTANCE_ID(x) (((x) & IPC_INSTANCE_ID_MASK) \ | ||
80 | << IPC_INSTANCE_ID_SHIFT) | ||
81 | |||
82 | /* Set pipeline state message */ | ||
83 | #define IPC_PPL_STATE_SHIFT 0 | ||
84 | #define IPC_PPL_STATE_MASK 0x1F | ||
85 | #define IPC_PPL_STATE(x) (((x) & IPC_PPL_STATE_MASK) \ | ||
86 | << IPC_PPL_STATE_SHIFT) | ||
87 | |||
88 | /* Module operations primary register */ | ||
89 | #define IPC_MOD_ID_SHIFT 0 | ||
90 | #define IPC_MOD_ID_MASK 0xFFFF | ||
91 | #define IPC_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \ | ||
92 | << IPC_MOD_ID_SHIFT) | ||
93 | |||
94 | #define IPC_MOD_INSTANCE_ID_SHIFT 16 | ||
95 | #define IPC_MOD_INSTANCE_ID_MASK 0xFF | ||
96 | #define IPC_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \ | ||
97 | << IPC_MOD_INSTANCE_ID_SHIFT) | ||
98 | |||
99 | /* Init instance message extension register */ | ||
100 | #define IPC_PARAM_BLOCK_SIZE_SHIFT 0 | ||
101 | #define IPC_PARAM_BLOCK_SIZE_MASK 0xFFFF | ||
102 | #define IPC_PARAM_BLOCK_SIZE(x) (((x) & IPC_PARAM_BLOCK_SIZE_MASK) \ | ||
103 | << IPC_PARAM_BLOCK_SIZE_SHIFT) | ||
104 | |||
105 | #define IPC_PPL_INSTANCE_ID_SHIFT 16 | ||
106 | #define IPC_PPL_INSTANCE_ID_MASK 0xFF | ||
107 | #define IPC_PPL_INSTANCE_ID(x) (((x) & IPC_PPL_INSTANCE_ID_MASK) \ | ||
108 | << IPC_PPL_INSTANCE_ID_SHIFT) | ||
109 | |||
110 | #define IPC_CORE_ID_SHIFT 24 | ||
111 | #define IPC_CORE_ID_MASK 0x1F | ||
112 | #define IPC_CORE_ID(x) (((x) & IPC_CORE_ID_MASK) \ | ||
113 | << IPC_CORE_ID_SHIFT) | ||
114 | |||
115 | /* Bind/Unbind message extension register */ | ||
116 | #define IPC_DST_MOD_ID_SHIFT 0 | ||
117 | #define IPC_DST_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \ | ||
118 | << IPC_DST_MOD_ID_SHIFT) | ||
119 | |||
120 | #define IPC_DST_MOD_INSTANCE_ID_SHIFT 16 | ||
121 | #define IPC_DST_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \ | ||
122 | << IPC_DST_MOD_INSTANCE_ID_SHIFT) | ||
123 | |||
124 | #define IPC_DST_QUEUE_SHIFT 24 | ||
125 | #define IPC_DST_QUEUE_MASK 0x7 | ||
126 | #define IPC_DST_QUEUE(x) (((x) & IPC_DST_QUEUE_MASK) \ | ||
127 | << IPC_DST_QUEUE_SHIFT) | ||
128 | |||
129 | #define IPC_SRC_QUEUE_SHIFT 27 | ||
130 | #define IPC_SRC_QUEUE_MASK 0x7 | ||
131 | #define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \ | ||
132 | << IPC_SRC_QUEUE_SHIFT) | ||
133 | |||
134 | /* Save pipeline messgae extension register */ | ||
135 | #define IPC_DMA_ID_SHIFT 0 | ||
136 | #define IPC_DMA_ID_MASK 0x1F | ||
137 | #define IPC_DMA_ID(x) (((x) & IPC_DMA_ID_MASK) \ | ||
138 | << IPC_DMA_ID_SHIFT) | ||
139 | /* Large Config message extension register */ | ||
140 | #define IPC_DATA_OFFSET_SZ_SHIFT 0 | ||
141 | #define IPC_DATA_OFFSET_SZ_MASK 0xFFFFF | ||
142 | #define IPC_DATA_OFFSET_SZ(x) (((x) & IPC_DATA_OFFSET_SZ_MASK) \ | ||
143 | << IPC_DATA_OFFSET_SZ_SHIFT) | ||
144 | #define IPC_DATA_OFFSET_SZ_CLEAR ~(IPC_DATA_OFFSET_SZ_MASK \ | ||
145 | << IPC_DATA_OFFSET_SZ_SHIFT) | ||
146 | |||
147 | #define IPC_LARGE_PARAM_ID_SHIFT 20 | ||
148 | #define IPC_LARGE_PARAM_ID_MASK 0xFF | ||
149 | #define IPC_LARGE_PARAM_ID(x) (((x) & IPC_LARGE_PARAM_ID_MASK) \ | ||
150 | << IPC_LARGE_PARAM_ID_SHIFT) | ||
151 | |||
152 | #define IPC_FINAL_BLOCK_SHIFT 28 | ||
153 | #define IPC_FINAL_BLOCK_MASK 0x1 | ||
154 | #define IPC_FINAL_BLOCK(x) (((x) & IPC_FINAL_BLOCK_MASK) \ | ||
155 | << IPC_FINAL_BLOCK_SHIFT) | ||
156 | |||
157 | #define IPC_INITIAL_BLOCK_SHIFT 29 | ||
158 | #define IPC_INITIAL_BLOCK_MASK 0x1 | ||
159 | #define IPC_INITIAL_BLOCK(x) (((x) & IPC_INITIAL_BLOCK_MASK) \ | ||
160 | << IPC_INITIAL_BLOCK_SHIFT) | ||
161 | #define IPC_INITIAL_BLOCK_CLEAR ~(IPC_INITIAL_BLOCK_MASK \ | ||
162 | << IPC_INITIAL_BLOCK_SHIFT) | ||
163 | |||
164 | enum skl_ipc_msg_target { | ||
165 | IPC_FW_GEN_MSG = 0, | ||
166 | IPC_MOD_MSG = 1 | ||
167 | }; | ||
168 | |||
169 | enum skl_ipc_msg_direction { | ||
170 | IPC_MSG_REQUEST = 0, | ||
171 | IPC_MSG_REPLY = 1 | ||
172 | }; | ||
173 | |||
174 | /* Global Message Types */ | ||
175 | enum skl_ipc_glb_type { | ||
176 | IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ | ||
177 | IPC_GLB_LOAD_MULTIPLE_MODS = 15, | ||
178 | IPC_GLB_UNLOAD_MULTIPLE_MODS = 16, | ||
179 | IPC_GLB_CREATE_PPL = 17, | ||
180 | IPC_GLB_DELETE_PPL = 18, | ||
181 | IPC_GLB_SET_PPL_STATE = 19, | ||
182 | IPC_GLB_GET_PPL_STATE = 20, | ||
183 | IPC_GLB_GET_PPL_CONTEXT_SIZE = 21, | ||
184 | IPC_GLB_SAVE_PPL = 22, | ||
185 | IPC_GLB_RESTORE_PPL = 23, | ||
186 | IPC_GLB_NOTIFY = 26, | ||
187 | IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */ | ||
188 | }; | ||
189 | |||
190 | enum skl_ipc_glb_reply { | ||
191 | IPC_GLB_REPLY_SUCCESS = 0, | ||
192 | |||
193 | IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1, | ||
194 | IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2, | ||
195 | |||
196 | IPC_GLB_REPLY_BUSY = 3, | ||
197 | IPC_GLB_REPLY_PENDING = 4, | ||
198 | IPC_GLB_REPLY_FAILURE = 5, | ||
199 | IPC_GLB_REPLY_INVALID_REQUEST = 6, | ||
200 | |||
201 | IPC_GLB_REPLY_OUT_OF_MEMORY = 7, | ||
202 | IPC_GLB_REPLY_OUT_OF_MIPS = 8, | ||
203 | |||
204 | IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9, | ||
205 | IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10, | ||
206 | |||
207 | IPC_GLB_REPLY_MOD_MGMT_ERROR = 100, | ||
208 | IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101, | ||
209 | IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102, | ||
210 | |||
211 | IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103, | ||
212 | IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104, | ||
213 | |||
214 | IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120, | ||
215 | IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121, | ||
216 | IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140, | ||
217 | IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141, | ||
218 | |||
219 | IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160, | ||
220 | IPC_GLB_REPLY_PPL_NOT_EXIST = 161, | ||
221 | IPC_GLB_REPLY_PPL_SAVE_FAILED = 162, | ||
222 | IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163, | ||
223 | |||
224 | IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1) | ||
225 | }; | ||
226 | |||
227 | enum skl_ipc_notification_type { | ||
228 | IPC_GLB_NOTIFY_GLITCH = 0, | ||
229 | IPC_GLB_NOTIFY_OVERRUN = 1, | ||
230 | IPC_GLB_NOTIFY_UNDERRUN = 2, | ||
231 | IPC_GLB_NOTIFY_END_STREAM = 3, | ||
232 | IPC_GLB_NOTIFY_PHRASE_DETECTED = 4, | ||
233 | IPC_GLB_NOTIFY_RESOURCE_EVENT = 5, | ||
234 | IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6, | ||
235 | IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7, | ||
236 | IPC_GLB_NOTIFY_FW_READY = 8 | ||
237 | }; | ||
238 | |||
239 | /* Module Message Types */ | ||
240 | enum skl_ipc_module_msg { | ||
241 | IPC_MOD_INIT_INSTANCE = 0, | ||
242 | IPC_MOD_CONFIG_GET = 1, | ||
243 | IPC_MOD_CONFIG_SET = 2, | ||
244 | IPC_MOD_LARGE_CONFIG_GET = 3, | ||
245 | IPC_MOD_LARGE_CONFIG_SET = 4, | ||
246 | IPC_MOD_BIND = 5, | ||
247 | IPC_MOD_UNBIND = 6, | ||
248 | IPC_MOD_SET_DX = 7 | ||
249 | }; | ||
250 | |||
251 | static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, | ||
252 | size_t tx_size) | ||
253 | { | ||
254 | if (tx_size) | ||
255 | memcpy(msg->tx_data, tx_data, tx_size); | ||
256 | } | ||
257 | |||
258 | static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp) | ||
259 | { | ||
260 | u32 hipci; | ||
261 | |||
262 | hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI); | ||
263 | return (hipci & SKL_ADSP_REG_HIPCI_BUSY); | ||
264 | } | ||
265 | |||
266 | /* Lock to be held by caller */ | ||
267 | static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) | ||
268 | { | ||
269 | struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); | ||
270 | |||
271 | if (msg->tx_size) | ||
272 | sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); | ||
273 | sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE, | ||
274 | header->extension); | ||
275 | sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI, | ||
276 | header->primary | SKL_ADSP_REG_HIPCI_BUSY); | ||
277 | } | ||
278 | |||
279 | static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc, | ||
280 | u64 ipc_header) | ||
281 | { | ||
282 | struct ipc_message *msg = NULL; | ||
283 | struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header); | ||
284 | |||
285 | if (list_empty(&ipc->rx_list)) { | ||
286 | dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n", | ||
287 | header->primary); | ||
288 | goto out; | ||
289 | } | ||
290 | |||
291 | msg = list_first_entry(&ipc->rx_list, struct ipc_message, list); | ||
292 | |||
293 | out: | ||
294 | return msg; | ||
295 | |||
296 | } | ||
297 | |||
298 | static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, | ||
299 | struct skl_ipc_header header) | ||
300 | { | ||
301 | struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); | ||
302 | |||
303 | if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { | ||
304 | switch (IPC_GLB_NOTIFY_TYPE(header.primary)) { | ||
305 | |||
306 | case IPC_GLB_NOTIFY_UNDERRUN: | ||
307 | dev_err(ipc->dev, "FW Underrun %x\n", header.primary); | ||
308 | break; | ||
309 | |||
310 | case IPC_GLB_NOTIFY_RESOURCE_EVENT: | ||
311 | dev_err(ipc->dev, "MCPS Budget Violation: %x\n", | ||
312 | header.primary); | ||
313 | break; | ||
314 | |||
315 | case IPC_GLB_NOTIFY_FW_READY: | ||
316 | skl->boot_complete = true; | ||
317 | wake_up(&skl->boot_wait); | ||
318 | break; | ||
319 | |||
320 | default: | ||
321 | dev_err(ipc->dev, "ipc: Unhandled error msg=%x", | ||
322 | header.primary); | ||
323 | break; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, | ||
331 | struct skl_ipc_header header) | ||
332 | { | ||
333 | struct ipc_message *msg; | ||
334 | u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; | ||
335 | u64 *ipc_header = (u64 *)(&header); | ||
336 | |||
337 | msg = skl_ipc_reply_get_msg(ipc, *ipc_header); | ||
338 | if (msg == NULL) { | ||
339 | dev_dbg(ipc->dev, "ipc: rx list is empty\n"); | ||
340 | return; | ||
341 | } | ||
342 | |||
343 | /* first process the header */ | ||
344 | switch (reply) { | ||
345 | case IPC_GLB_REPLY_SUCCESS: | ||
346 | dev_info(ipc->dev, "ipc FW reply %x: success\n", header.primary); | ||
347 | break; | ||
348 | |||
349 | case IPC_GLB_REPLY_OUT_OF_MEMORY: | ||
350 | dev_err(ipc->dev, "ipc fw reply: %x: no memory\n", header.primary); | ||
351 | msg->errno = -ENOMEM; | ||
352 | break; | ||
353 | |||
354 | case IPC_GLB_REPLY_BUSY: | ||
355 | dev_err(ipc->dev, "ipc fw reply: %x: Busy\n", header.primary); | ||
356 | msg->errno = -EBUSY; | ||
357 | break; | ||
358 | |||
359 | default: | ||
360 | dev_err(ipc->dev, "Unknown ipc reply: 0x%x", reply); | ||
361 | msg->errno = -EINVAL; | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | if (reply != IPC_GLB_REPLY_SUCCESS) { | ||
366 | dev_err(ipc->dev, "ipc FW reply: reply=%d", reply); | ||
367 | dev_err(ipc->dev, "FW Error Code: %u\n", | ||
368 | ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); | ||
369 | } | ||
370 | |||
371 | list_del(&msg->list); | ||
372 | sst_ipc_tx_msg_reply_complete(ipc, msg); | ||
373 | } | ||
374 | |||
375 | irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) | ||
376 | { | ||
377 | struct sst_dsp *dsp = context; | ||
378 | struct skl_sst *skl = sst_dsp_get_thread_context(dsp); | ||
379 | struct sst_generic_ipc *ipc = &skl->ipc; | ||
380 | struct skl_ipc_header header = {0}; | ||
381 | u32 hipcie, hipct, hipcte; | ||
382 | int ipc_irq = 0; | ||
383 | |||
384 | if (dsp->intr_status & SKL_ADSPIS_CL_DMA) | ||
385 | skl_cldma_process_intr(dsp); | ||
386 | |||
387 | /* Here we handle IPC interrupts only */ | ||
388 | if (!(dsp->intr_status & SKL_ADSPIS_IPC)) | ||
389 | return IRQ_NONE; | ||
390 | |||
391 | hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE); | ||
392 | hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT); | ||
393 | |||
394 | /* reply message from DSP */ | ||
395 | if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) { | ||
396 | sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL, | ||
397 | SKL_ADSP_REG_HIPCCTL_DONE, 0); | ||
398 | |||
399 | /* clear DONE bit - tell DSP we have completed the operation */ | ||
400 | sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE, | ||
401 | SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE); | ||
402 | |||
403 | ipc_irq = 1; | ||
404 | |||
405 | /* unmask Done interrupt */ | ||
406 | sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL, | ||
407 | SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE); | ||
408 | } | ||
409 | |||
410 | /* New message from DSP */ | ||
411 | if (hipct & SKL_ADSP_REG_HIPCT_BUSY) { | ||
412 | hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE); | ||
413 | header.primary = hipct; | ||
414 | header.extension = hipcte; | ||
415 | dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", | ||
416 | header.primary); | ||
417 | dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x", | ||
418 | header.extension); | ||
419 | |||
420 | if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { | ||
421 | /* Handle Immediate reply from DSP Core */ | ||
422 | skl_ipc_process_reply(ipc, header); | ||
423 | } else { | ||
424 | dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); | ||
425 | skl_ipc_process_notification(ipc, header); | ||
426 | } | ||
427 | /* clear busy interrupt */ | ||
428 | sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT, | ||
429 | SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY); | ||
430 | ipc_irq = 1; | ||
431 | } | ||
432 | |||
433 | if (ipc_irq == 0) | ||
434 | return IRQ_NONE; | ||
435 | |||
436 | skl_ipc_int_enable(dsp); | ||
437 | |||
438 | /* continue to send any remaining messages... */ | ||
439 | queue_kthread_work(&ipc->kworker, &ipc->kwork); | ||
440 | |||
441 | return IRQ_HANDLED; | ||
442 | } | ||
443 | |||
444 | void skl_ipc_int_enable(struct sst_dsp *ctx) | ||
445 | { | ||
446 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC, | ||
447 | SKL_ADSPIC_IPC, SKL_ADSPIC_IPC); | ||
448 | } | ||
449 | |||
450 | void skl_ipc_int_disable(struct sst_dsp *ctx) | ||
451 | { | ||
452 | sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC, | ||
453 | SKL_ADSPIC_IPC, 0); | ||
454 | } | ||
455 | |||
456 | void skl_ipc_op_int_enable(struct sst_dsp *ctx) | ||
457 | { | ||
458 | /* enable IPC DONE interrupt */ | ||
459 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL, | ||
460 | SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE); | ||
461 | |||
462 | /* Enable IPC BUSY interrupt */ | ||
463 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL, | ||
464 | SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY); | ||
465 | } | ||
466 | |||
467 | bool skl_ipc_int_status(struct sst_dsp *ctx) | ||
468 | { | ||
469 | return sst_dsp_shim_read_unlocked(ctx, | ||
470 | SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC; | ||
471 | } | ||
472 | |||
473 | int skl_ipc_init(struct device *dev, struct skl_sst *skl) | ||
474 | { | ||
475 | struct sst_generic_ipc *ipc; | ||
476 | int err; | ||
477 | |||
478 | ipc = &skl->ipc; | ||
479 | ipc->dsp = skl->dsp; | ||
480 | ipc->dev = dev; | ||
481 | |||
482 | ipc->tx_data_max_size = SKL_ADSP_W1_SZ; | ||
483 | ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ; | ||
484 | |||
485 | err = sst_ipc_init(ipc); | ||
486 | if (err) | ||
487 | return err; | ||
488 | |||
489 | ipc->ops.tx_msg = skl_ipc_tx_msg; | ||
490 | ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; | ||
491 | ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy; | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | void skl_ipc_free(struct sst_generic_ipc *ipc) | ||
497 | { | ||
498 | /* Disable IPC DONE interrupt */ | ||
499 | sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, | ||
500 | SKL_ADSP_REG_HIPCCTL_DONE, 0); | ||
501 | |||
502 | /* Disable IPC BUSY interrupt */ | ||
503 | sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, | ||
504 | SKL_ADSP_REG_HIPCCTL_BUSY, 0); | ||
505 | |||
506 | sst_ipc_fini(ipc); | ||
507 | } | ||
508 | |||
509 | int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, | ||
510 | u16 ppl_mem_size, u8 ppl_type, u8 instance_id) | ||
511 | { | ||
512 | struct skl_ipc_header header = {0}; | ||
513 | u64 *ipc_header = (u64 *)(&header); | ||
514 | int ret; | ||
515 | |||
516 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | ||
517 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | ||
518 | header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL); | ||
519 | header.primary |= IPC_INSTANCE_ID(instance_id); | ||
520 | header.primary |= IPC_PPL_TYPE(ppl_type); | ||
521 | header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size); | ||
522 | |||
523 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | ||
524 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | ||
525 | if (ret < 0) { | ||
526 | dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret); | ||
527 | return ret; | ||
528 | } | ||
529 | |||
530 | return ret; | ||
531 | } | ||
532 | EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline); | ||
533 | |||
534 | int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) | ||
535 | { | ||
536 | struct skl_ipc_header header = {0}; | ||
537 | u64 *ipc_header = (u64 *)(&header); | ||
538 | int ret; | ||
539 | |||
540 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | ||
541 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | ||
542 | header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL); | ||
543 | header.primary |= IPC_INSTANCE_ID(instance_id); | ||
544 | |||
545 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | ||
546 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | ||
547 | if (ret < 0) { | ||
548 | dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret); | ||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline); | ||
555 | |||
556 | int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, | ||
557 | u8 instance_id, enum skl_ipc_pipeline_state state) | ||
558 | { | ||
559 | struct skl_ipc_header header = {0}; | ||
560 | u64 *ipc_header = (u64 *)(&header); | ||
561 | int ret; | ||
562 | |||
563 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | ||
564 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | ||
565 | header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE); | ||
566 | header.primary |= IPC_INSTANCE_ID(instance_id); | ||
567 | header.primary |= IPC_PPL_STATE(state); | ||
568 | |||
569 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | ||
570 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | ||
571 | if (ret < 0) { | ||
572 | dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret); | ||
573 | return ret; | ||
574 | } | ||
575 | return ret; | ||
576 | } | ||
577 | EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state); | ||
578 | |||
579 | int | ||
580 | skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) | ||
581 | { | ||
582 | struct skl_ipc_header header = {0}; | ||
583 | u64 *ipc_header = (u64 *)(&header); | ||
584 | int ret; | ||
585 | |||
586 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | ||
587 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | ||
588 | header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL); | ||
589 | header.primary |= IPC_INSTANCE_ID(instance_id); | ||
590 | |||
591 | header.extension = IPC_DMA_ID(dma_id); | ||
592 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | ||
593 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | ||
594 | if (ret < 0) { | ||
595 | dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret); | ||
596 | return ret; | ||
597 | } | ||
598 | |||
599 | return ret; | ||
600 | } | ||
601 | EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline); | ||
602 | |||
603 | int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) | ||
604 | { | ||
605 | struct skl_ipc_header header = {0}; | ||
606 | u64 *ipc_header = (u64 *)(&header); | ||
607 | int ret; | ||
608 | |||
609 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | ||
610 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | ||
611 | header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL); | ||
612 | header.primary |= IPC_INSTANCE_ID(instance_id); | ||
613 | |||
614 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | ||
615 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | ||
616 | if (ret < 0) { | ||
617 | dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret); | ||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | return ret; | ||
622 | } | ||
623 | EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline); | ||
624 | |||
625 | int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, | ||
626 | u16 module_id, struct skl_ipc_dxstate_info *dx) | ||
627 | { | ||
628 | struct skl_ipc_header header = {0}; | ||
629 | u64 *ipc_header = (u64 *)(&header); | ||
630 | int ret; | ||
631 | |||
632 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); | ||
633 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | ||
634 | header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX); | ||
635 | header.primary |= IPC_MOD_INSTANCE_ID(instance_id); | ||
636 | header.primary |= IPC_MOD_ID(module_id); | ||
637 | |||
638 | dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, | ||
639 | header.primary, header.extension); | ||
640 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, | ||
641 | dx, sizeof(dx), NULL, 0); | ||
642 | if (ret < 0) { | ||
643 | dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret); | ||
644 | return ret; | ||
645 | } | ||
646 | |||
647 | return ret; | ||
648 | } | ||
649 | EXPORT_SYMBOL_GPL(skl_ipc_set_dx); | ||
650 | |||
651 | int skl_ipc_init_instance(struct sst_generic_ipc *ipc, | ||
652 | struct skl_ipc_init_instance_msg *msg, void *param_data) | ||
653 | { | ||
654 | struct skl_ipc_header header = {0}; | ||
655 | u64 *ipc_header = (u64 *)(&header); | ||
656 | int ret; | ||
657 | u32 *buffer = (u32 *)param_data; | ||
658 | /* param_block_size must be in dwords */ | ||
659 | u16 param_block_size = msg->param_data_size / sizeof(u32); | ||
660 | |||
661 | print_hex_dump(KERN_DEBUG, NULL, DUMP_PREFIX_NONE, | ||
662 | 16, 4, buffer, param_block_size, false); | ||
663 | |||
664 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); | ||
665 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | ||
666 | header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE); | ||
667 | header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); | ||
668 | header.primary |= IPC_MOD_ID(msg->module_id); | ||
669 | |||
670 | header.extension = IPC_CORE_ID(msg->core_id); | ||
671 | header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id); | ||
672 | header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size); | ||
673 | |||
674 | dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, | ||
675 | header.primary, header.extension); | ||
676 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data, | ||
677 | msg->param_data_size, NULL, 0); | ||
678 | |||
679 | if (ret < 0) { | ||
680 | dev_err(ipc->dev, "ipc: init instance failed\n"); | ||
681 | return ret; | ||
682 | } | ||
683 | |||
684 | return ret; | ||
685 | } | ||
686 | EXPORT_SYMBOL_GPL(skl_ipc_init_instance); | ||
687 | |||
688 | int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, | ||
689 | struct skl_ipc_bind_unbind_msg *msg) | ||
690 | { | ||
691 | struct skl_ipc_header header = {0}; | ||
692 | u64 *ipc_header = (u64 *)(&header); | ||
693 | u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND; | ||
694 | int ret; | ||
695 | |||
696 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); | ||
697 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | ||
698 | header.primary |= IPC_GLB_TYPE(bind_unbind); | ||
699 | header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); | ||
700 | header.primary |= IPC_MOD_ID(msg->module_id); | ||
701 | |||
702 | header.extension = IPC_DST_MOD_ID(msg->dst_module_id); | ||
703 | header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id); | ||
704 | header.extension |= IPC_DST_QUEUE(msg->dst_queue); | ||
705 | header.extension |= IPC_SRC_QUEUE(msg->src_queue); | ||
706 | |||
707 | dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary, | ||
708 | header.extension); | ||
709 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | ||
710 | if (ret < 0) { | ||
711 | dev_err(ipc->dev, "ipc: bind/unbind faileden"); | ||
712 | return ret; | ||
713 | } | ||
714 | |||
715 | return ret; | ||
716 | } | ||
717 | EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind); | ||
718 | |||
719 | int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, | ||
720 | struct skl_ipc_large_config_msg *msg, u32 *param) | ||
721 | { | ||
722 | struct skl_ipc_header header = {0}; | ||
723 | u64 *ipc_header = (u64 *)(&header); | ||
724 | int ret = 0; | ||
725 | size_t sz_remaining, tx_size, data_offset; | ||
726 | |||
727 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); | ||
728 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | ||
729 | header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET); | ||
730 | header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); | ||
731 | header.primary |= IPC_MOD_ID(msg->module_id); | ||
732 | |||
733 | header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); | ||
734 | header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); | ||
735 | header.extension |= IPC_FINAL_BLOCK(0); | ||
736 | header.extension |= IPC_INITIAL_BLOCK(1); | ||
737 | |||
738 | sz_remaining = msg->param_data_size; | ||
739 | data_offset = 0; | ||
740 | while (sz_remaining != 0) { | ||
741 | tx_size = sz_remaining > SKL_ADSP_W1_SZ | ||
742 | ? SKL_ADSP_W1_SZ : sz_remaining; | ||
743 | if (tx_size == sz_remaining) | ||
744 | header.extension |= IPC_FINAL_BLOCK(1); | ||
745 | |||
746 | dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__, | ||
747 | header.primary, header.extension); | ||
748 | dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n", | ||
749 | (unsigned)data_offset, (unsigned)tx_size); | ||
750 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, | ||
751 | ((char *)param) + data_offset, | ||
752 | tx_size, NULL, 0); | ||
753 | if (ret < 0) { | ||
754 | dev_err(ipc->dev, | ||
755 | "ipc: set large config fail, err: %d\n", ret); | ||
756 | return ret; | ||
757 | } | ||
758 | sz_remaining -= tx_size; | ||
759 | data_offset = msg->param_data_size - sz_remaining; | ||
760 | |||
761 | /* clear the fields */ | ||
762 | header.extension &= IPC_INITIAL_BLOCK_CLEAR; | ||
763 | header.extension &= IPC_DATA_OFFSET_SZ_CLEAR; | ||
764 | /* fill the fields */ | ||
765 | header.extension |= IPC_INITIAL_BLOCK(0); | ||
766 | header.extension |= IPC_DATA_OFFSET_SZ(data_offset); | ||
767 | } | ||
768 | |||
769 | return ret; | ||
770 | } | ||
771 | EXPORT_SYMBOL_GPL(skl_ipc_set_large_config); | ||
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h new file mode 100644 index 000000000000..9f5f67202858 --- /dev/null +++ b/sound/soc/intel/skylake/skl-sst-ipc.h | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Intel SKL IPC Support | ||
3 | * | ||
4 | * Copyright (C) 2014-15, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as version 2, as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #ifndef __SKL_IPC_H | ||
17 | #define __SKL_IPC_H | ||
18 | |||
19 | #include <linux/kthread.h> | ||
20 | #include <linux/irqreturn.h> | ||
21 | #include "../common/sst-ipc.h" | ||
22 | |||
23 | struct sst_dsp; | ||
24 | struct skl_sst; | ||
25 | struct sst_generic_ipc; | ||
26 | |||
27 | enum skl_ipc_pipeline_state { | ||
28 | PPL_INVALID_STATE = 0, | ||
29 | PPL_UNINITIALIZED = 1, | ||
30 | PPL_RESET = 2, | ||
31 | PPL_PAUSED = 3, | ||
32 | PPL_RUNNING = 4, | ||
33 | PPL_ERROR_STOP = 5, | ||
34 | PPL_SAVED = 6, | ||
35 | PPL_RESTORED = 7 | ||
36 | }; | ||
37 | |||
38 | struct skl_ipc_dxstate_info { | ||
39 | u32 core_mask; | ||
40 | u32 dx_mask; | ||
41 | }; | ||
42 | |||
43 | struct skl_ipc_header { | ||
44 | u32 primary; | ||
45 | u32 extension; | ||
46 | }; | ||
47 | |||
48 | struct skl_sst { | ||
49 | struct device *dev; | ||
50 | struct sst_dsp *dsp; | ||
51 | |||
52 | /* boot */ | ||
53 | wait_queue_head_t boot_wait; | ||
54 | bool boot_complete; | ||
55 | |||
56 | /* IPC messaging */ | ||
57 | struct sst_generic_ipc ipc; | ||
58 | }; | ||
59 | |||
60 | struct skl_ipc_init_instance_msg { | ||
61 | u32 module_id; | ||
62 | u32 instance_id; | ||
63 | u16 param_data_size; | ||
64 | u8 ppl_instance_id; | ||
65 | u8 core_id; | ||
66 | }; | ||
67 | |||
68 | struct skl_ipc_bind_unbind_msg { | ||
69 | u32 module_id; | ||
70 | u32 instance_id; | ||
71 | u32 dst_module_id; | ||
72 | u32 dst_instance_id; | ||
73 | u8 src_queue; | ||
74 | u8 dst_queue; | ||
75 | bool bind; | ||
76 | }; | ||
77 | |||
78 | struct skl_ipc_large_config_msg { | ||
79 | u32 module_id; | ||
80 | u32 instance_id; | ||
81 | u32 large_param_id; | ||
82 | u32 param_data_size; | ||
83 | }; | ||
84 | |||
85 | #define SKL_IPC_BOOT_MSECS 3000 | ||
86 | |||
87 | #define SKL_IPC_D3_MASK 0 | ||
88 | #define SKL_IPC_D0_MASK 3 | ||
89 | |||
90 | irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context); | ||
91 | |||
92 | int skl_ipc_create_pipeline(struct sst_generic_ipc *sst_ipc, | ||
93 | u16 ppl_mem_size, u8 ppl_type, u8 instance_id); | ||
94 | |||
95 | int skl_ipc_delete_pipeline(struct sst_generic_ipc *sst_ipc, u8 instance_id); | ||
96 | |||
97 | int skl_ipc_set_pipeline_state(struct sst_generic_ipc *sst_ipc, | ||
98 | u8 instance_id, enum skl_ipc_pipeline_state state); | ||
99 | |||
100 | int skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, | ||
101 | u8 instance_id, int dma_id); | ||
102 | |||
103 | int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id); | ||
104 | |||
105 | int skl_ipc_init_instance(struct sst_generic_ipc *sst_ipc, | ||
106 | struct skl_ipc_init_instance_msg *msg, void *param_data); | ||
107 | |||
108 | int skl_ipc_bind_unbind(struct sst_generic_ipc *sst_ipc, | ||
109 | struct skl_ipc_bind_unbind_msg *msg); | ||
110 | |||
111 | int skl_ipc_set_dx(struct sst_generic_ipc *ipc, | ||
112 | u8 instance_id, u16 module_id, struct skl_ipc_dxstate_info *dx); | ||
113 | |||
114 | int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, | ||
115 | struct skl_ipc_large_config_msg *msg, u32 *param); | ||
116 | |||
117 | void skl_ipc_int_enable(struct sst_dsp *dsp); | ||
118 | void skl_ipc_op_int_enable(struct sst_dsp *ctx); | ||
119 | void skl_ipc_int_disable(struct sst_dsp *dsp); | ||
120 | |||
121 | bool skl_ipc_int_status(struct sst_dsp *dsp); | ||
122 | void skl_ipc_free(struct sst_generic_ipc *ipc); | ||
123 | int skl_ipc_init(struct device *dev, struct skl_sst *skl); | ||
124 | |||
125 | #endif /* __SKL_IPC_H */ | ||
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c new file mode 100644 index 000000000000..c18ea51b7484 --- /dev/null +++ b/sound/soc/intel/skylake/skl-sst.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * skl-sst.c - HDA DSP library functions for SKL platform | ||
3 | * | ||
4 | * Copyright (C) 2014-15, Intel Corporation. | ||
5 | * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> | ||
6 | * Jeeja KP <jeeja.kp@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as version 2, as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/device.h> | ||
22 | #include "../common/sst-dsp.h" | ||
23 | #include "../common/sst-dsp-priv.h" | ||
24 | #include "../common/sst-ipc.h" | ||
25 | #include "skl-sst-ipc.h" | ||
26 | |||
27 | #define SKL_BASEFW_TIMEOUT 300 | ||
28 | #define SKL_INIT_TIMEOUT 1000 | ||
29 | |||
30 | /* Intel HD Audio SRAM Window 0*/ | ||
31 | #define SKL_ADSP_SRAM0_BASE 0x8000 | ||
32 | |||
33 | /* Firmware status window */ | ||
34 | #define SKL_ADSP_FW_STATUS SKL_ADSP_SRAM0_BASE | ||
35 | #define SKL_ADSP_ERROR_CODE (SKL_ADSP_FW_STATUS + 0x4) | ||
36 | |||
37 | #define SKL_INSTANCE_ID 0 | ||
38 | #define SKL_BASE_FW_MODULE_ID 0 | ||
39 | |||
40 | static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status) | ||
41 | { | ||
42 | u32 cur_sts; | ||
43 | |||
44 | cur_sts = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS) & SKL_FW_STS_MASK; | ||
45 | |||
46 | return (cur_sts == status); | ||
47 | } | ||
48 | |||
49 | static int skl_transfer_firmware(struct sst_dsp *ctx, | ||
50 | const void *basefw, u32 base_fw_size) | ||
51 | { | ||
52 | int ret = 0; | ||
53 | |||
54 | ret = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, basefw, base_fw_size); | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | |||
58 | ret = sst_dsp_register_poll(ctx, | ||
59 | SKL_ADSP_FW_STATUS, | ||
60 | SKL_FW_STS_MASK, | ||
61 | SKL_FW_RFW_START, | ||
62 | SKL_BASEFW_TIMEOUT, | ||
63 | "Firmware boot"); | ||
64 | |||
65 | ctx->cl_dev.ops.cl_stop_dma(ctx); | ||
66 | |||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | static int skl_load_base_firmware(struct sst_dsp *ctx) | ||
71 | { | ||
72 | int ret = 0, i; | ||
73 | const struct firmware *fw = NULL; | ||
74 | struct skl_sst *skl = ctx->thread_context; | ||
75 | u32 reg; | ||
76 | |||
77 | ret = request_firmware(&fw, "dsp_fw_release.bin", ctx->dev); | ||
78 | if (ret < 0) { | ||
79 | dev_err(ctx->dev, "Request firmware failed %d\n", ret); | ||
80 | skl_dsp_disable_core(ctx); | ||
81 | return -EIO; | ||
82 | } | ||
83 | |||
84 | /* enable Interrupt */ | ||
85 | skl_ipc_int_enable(ctx); | ||
86 | skl_ipc_op_int_enable(ctx); | ||
87 | |||
88 | /* check ROM Status */ | ||
89 | for (i = SKL_INIT_TIMEOUT; i > 0; --i) { | ||
90 | if (skl_check_fw_status(ctx, SKL_FW_INIT)) { | ||
91 | dev_dbg(ctx->dev, | ||
92 | "ROM loaded, we can continue with FW loading\n"); | ||
93 | break; | ||
94 | } | ||
95 | mdelay(1); | ||
96 | } | ||
97 | if (!i) { | ||
98 | reg = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS); | ||
99 | dev_err(ctx->dev, | ||
100 | "Timeout waiting for ROM init done, reg:0x%x\n", reg); | ||
101 | ret = -EIO; | ||
102 | goto skl_load_base_firmware_failed; | ||
103 | } | ||
104 | |||
105 | ret = skl_transfer_firmware(ctx, fw->data, fw->size); | ||
106 | if (ret < 0) { | ||
107 | dev_err(ctx->dev, "Transfer firmware failed%d\n", ret); | ||
108 | goto skl_load_base_firmware_failed; | ||
109 | } else { | ||
110 | ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, | ||
111 | msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); | ||
112 | if (ret == 0) { | ||
113 | dev_err(ctx->dev, "DSP boot failed, FW Ready timed-out\n"); | ||
114 | ret = -EIO; | ||
115 | goto skl_load_base_firmware_failed; | ||
116 | } | ||
117 | |||
118 | dev_dbg(ctx->dev, "Download firmware successful%d\n", ret); | ||
119 | skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); | ||
120 | } | ||
121 | release_firmware(fw); | ||
122 | |||
123 | return 0; | ||
124 | |||
125 | skl_load_base_firmware_failed: | ||
126 | skl_dsp_disable_core(ctx); | ||
127 | release_firmware(fw); | ||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | static int skl_set_dsp_D0(struct sst_dsp *ctx) | ||
132 | { | ||
133 | int ret; | ||
134 | |||
135 | ret = skl_load_base_firmware(ctx); | ||
136 | if (ret < 0) { | ||
137 | dev_err(ctx->dev, "unable to load firmware\n"); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); | ||
142 | |||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | static int skl_set_dsp_D3(struct sst_dsp *ctx) | ||
147 | { | ||
148 | int ret; | ||
149 | struct skl_ipc_dxstate_info dx; | ||
150 | struct skl_sst *skl = ctx->thread_context; | ||
151 | |||
152 | dev_dbg(ctx->dev, "In %s:\n", __func__); | ||
153 | mutex_lock(&ctx->mutex); | ||
154 | if (!is_skl_dsp_running(ctx)) { | ||
155 | mutex_unlock(&ctx->mutex); | ||
156 | return 0; | ||
157 | } | ||
158 | mutex_unlock(&ctx->mutex); | ||
159 | |||
160 | dx.core_mask = SKL_DSP_CORE0_MASK; | ||
161 | dx.dx_mask = SKL_IPC_D3_MASK; | ||
162 | ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, SKL_BASE_FW_MODULE_ID, &dx); | ||
163 | if (ret < 0) { | ||
164 | dev_err(ctx->dev, "Failed to set DSP to D3 state\n"); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | ret = skl_dsp_disable_core(ctx); | ||
169 | if (ret < 0) { | ||
170 | dev_err(ctx->dev, "disable dsp core failed ret: %d\n", ret); | ||
171 | ret = -EIO; | ||
172 | } | ||
173 | skl_dsp_set_state_locked(ctx, SKL_DSP_RESET); | ||
174 | |||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | static unsigned int skl_get_errorcode(struct sst_dsp *ctx) | ||
179 | { | ||
180 | return sst_dsp_shim_read(ctx, SKL_ADSP_ERROR_CODE); | ||
181 | } | ||
182 | |||
183 | static struct skl_dsp_fw_ops skl_fw_ops = { | ||
184 | .set_state_D0 = skl_set_dsp_D0, | ||
185 | .set_state_D3 = skl_set_dsp_D3, | ||
186 | .load_fw = skl_load_base_firmware, | ||
187 | .get_fw_errcode = skl_get_errorcode, | ||
188 | }; | ||
189 | |||
190 | static struct sst_ops skl_ops = { | ||
191 | .irq_handler = skl_dsp_sst_interrupt, | ||
192 | .write = sst_shim32_write, | ||
193 | .read = sst_shim32_read, | ||
194 | .ram_read = sst_memcpy_fromio_32, | ||
195 | .ram_write = sst_memcpy_toio_32, | ||
196 | .free = skl_dsp_free, | ||
197 | }; | ||
198 | |||
199 | static struct sst_dsp_device skl_dev = { | ||
200 | .thread = skl_dsp_irq_thread_handler, | ||
201 | .ops = &skl_ops, | ||
202 | }; | ||
203 | |||
204 | int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | ||
205 | struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp) | ||
206 | { | ||
207 | struct skl_sst *skl; | ||
208 | struct sst_dsp *sst; | ||
209 | int ret; | ||
210 | |||
211 | skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); | ||
212 | if (skl == NULL) | ||
213 | return -ENOMEM; | ||
214 | |||
215 | skl->dev = dev; | ||
216 | skl_dev.thread_context = skl; | ||
217 | |||
218 | skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); | ||
219 | if (!skl->dsp) { | ||
220 | dev_err(skl->dev, "%s: no device\n", __func__); | ||
221 | return -ENODEV; | ||
222 | } | ||
223 | |||
224 | sst = skl->dsp; | ||
225 | |||
226 | sst->addr.lpe = mmio_base; | ||
227 | sst->addr.shim = mmio_base; | ||
228 | sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), | ||
229 | SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); | ||
230 | |||
231 | sst->dsp_ops = dsp_ops; | ||
232 | sst->fw_ops = skl_fw_ops; | ||
233 | |||
234 | ret = skl_ipc_init(dev, skl); | ||
235 | if (ret) | ||
236 | return ret; | ||
237 | |||
238 | skl->boot_complete = false; | ||
239 | init_waitqueue_head(&skl->boot_wait); | ||
240 | |||
241 | ret = skl_dsp_boot(sst); | ||
242 | if (ret < 0) { | ||
243 | dev_err(skl->dev, "Boot dsp core failed ret: %d", ret); | ||
244 | goto free_ipc; | ||
245 | } | ||
246 | |||
247 | ret = skl_cldma_prepare(sst); | ||
248 | if (ret < 0) { | ||
249 | dev_err(dev, "CL dma prepare failed : %d", ret); | ||
250 | goto free_ipc; | ||
251 | } | ||
252 | |||
253 | |||
254 | ret = sst->fw_ops.load_fw(sst); | ||
255 | if (ret < 0) { | ||
256 | dev_err(dev, "Load base fw failed : %d", ret); | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | if (dsp) | ||
261 | *dsp = skl; | ||
262 | |||
263 | return 0; | ||
264 | |||
265 | free_ipc: | ||
266 | skl_ipc_free(&skl->ipc); | ||
267 | return ret; | ||
268 | } | ||
269 | EXPORT_SYMBOL_GPL(skl_sst_dsp_init); | ||
270 | |||
271 | void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) | ||
272 | { | ||
273 | skl_ipc_free(&ctx->ipc); | ||
274 | ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); | ||
275 | ctx->dsp->ops->free(ctx->dsp); | ||
276 | } | ||
277 | EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup); | ||
278 | |||
279 | MODULE_LICENSE("GPL v2"); | ||
280 | MODULE_DESCRIPTION("Intel Skylake IPC driver"); | ||
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h new file mode 100644 index 000000000000..8c7767baa94f --- /dev/null +++ b/sound/soc/intel/skylake/skl-topology.h | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | * skl_topology.h - Intel HDA Platform topology header file | ||
3 | * | ||
4 | * Copyright (C) 2014-15 Intel Corp | ||
5 | * Author: Jeeja KP <jeeja.kp@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #ifndef __SKL_TOPOLOGY_H__ | ||
22 | #define __SKL_TOPOLOGY_H__ | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | |||
26 | #include <sound/hdaudio_ext.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include "skl.h" | ||
29 | #include "skl-tplg-interface.h" | ||
30 | |||
31 | #define BITS_PER_BYTE 8 | ||
32 | #define MAX_TS_GROUPS 8 | ||
33 | #define MAX_DMIC_TS_GROUPS 4 | ||
34 | #define MAX_FIXED_DMIC_PARAMS_SIZE 727 | ||
35 | |||
36 | /* Maximum number of coefficients up down mixer module */ | ||
37 | #define UP_DOWN_MIXER_MAX_COEFF 6 | ||
38 | |||
39 | enum skl_channel_index { | ||
40 | SKL_CHANNEL_LEFT = 0, | ||
41 | SKL_CHANNEL_RIGHT = 1, | ||
42 | SKL_CHANNEL_CENTER = 2, | ||
43 | SKL_CHANNEL_LEFT_SURROUND = 3, | ||
44 | SKL_CHANNEL_CENTER_SURROUND = 3, | ||
45 | SKL_CHANNEL_RIGHT_SURROUND = 4, | ||
46 | SKL_CHANNEL_LFE = 7, | ||
47 | SKL_CHANNEL_INVALID = 0xF, | ||
48 | }; | ||
49 | |||
50 | enum skl_bitdepth { | ||
51 | SKL_DEPTH_8BIT = 8, | ||
52 | SKL_DEPTH_16BIT = 16, | ||
53 | SKL_DEPTH_24BIT = 24, | ||
54 | SKL_DEPTH_32BIT = 32, | ||
55 | SKL_DEPTH_INVALID | ||
56 | }; | ||
57 | |||
58 | enum skl_interleaving { | ||
59 | /* [s1_ch1...s1_chN,...,sM_ch1...sM_chN] */ | ||
60 | SKL_INTERLEAVING_PER_CHANNEL = 0, | ||
61 | /* [s1_ch1...sM_ch1,...,s1_chN...sM_chN] */ | ||
62 | SKL_INTERLEAVING_PER_SAMPLE = 1, | ||
63 | }; | ||
64 | |||
65 | enum skl_s_freq { | ||
66 | SKL_FS_8000 = 8000, | ||
67 | SKL_FS_11025 = 11025, | ||
68 | SKL_FS_12000 = 12000, | ||
69 | SKL_FS_16000 = 16000, | ||
70 | SKL_FS_22050 = 22050, | ||
71 | SKL_FS_24000 = 24000, | ||
72 | SKL_FS_32000 = 32000, | ||
73 | SKL_FS_44100 = 44100, | ||
74 | SKL_FS_48000 = 48000, | ||
75 | SKL_FS_64000 = 64000, | ||
76 | SKL_FS_88200 = 88200, | ||
77 | SKL_FS_96000 = 96000, | ||
78 | SKL_FS_128000 = 128000, | ||
79 | SKL_FS_176400 = 176400, | ||
80 | SKL_FS_192000 = 192000, | ||
81 | SKL_FS_INVALID | ||
82 | }; | ||
83 | |||
84 | enum skl_widget_type { | ||
85 | SKL_WIDGET_VMIXER = 1, | ||
86 | SKL_WIDGET_MIXER = 2, | ||
87 | SKL_WIDGET_PGA = 3, | ||
88 | SKL_WIDGET_MUX = 4 | ||
89 | }; | ||
90 | |||
91 | struct skl_audio_data_format { | ||
92 | enum skl_s_freq s_freq; | ||
93 | enum skl_bitdepth bit_depth; | ||
94 | u32 channel_map; | ||
95 | enum skl_ch_cfg ch_cfg; | ||
96 | enum skl_interleaving interleaving; | ||
97 | u8 number_of_channels; | ||
98 | u8 valid_bit_depth; | ||
99 | u8 sample_type; | ||
100 | u8 reserved[1]; | ||
101 | } __packed; | ||
102 | |||
103 | struct skl_base_cfg { | ||
104 | u32 cps; | ||
105 | u32 ibs; | ||
106 | u32 obs; | ||
107 | u32 is_pages; | ||
108 | struct skl_audio_data_format audio_fmt; | ||
109 | }; | ||
110 | |||
111 | struct skl_cpr_gtw_cfg { | ||
112 | u32 node_id; | ||
113 | u32 dma_buffer_size; | ||
114 | u32 config_length; | ||
115 | /* not mandatory; required only for DMIC/I2S */ | ||
116 | u32 config_data[1]; | ||
117 | } __packed; | ||
118 | |||
119 | struct skl_cpr_cfg { | ||
120 | struct skl_base_cfg base_cfg; | ||
121 | struct skl_audio_data_format out_fmt; | ||
122 | u32 cpr_feature_mask; | ||
123 | struct skl_cpr_gtw_cfg gtw_cfg; | ||
124 | } __packed; | ||
125 | |||
126 | |||
127 | struct skl_src_module_cfg { | ||
128 | struct skl_base_cfg base_cfg; | ||
129 | enum skl_s_freq src_cfg; | ||
130 | } __packed; | ||
131 | |||
132 | struct skl_up_down_mixer_cfg { | ||
133 | struct skl_base_cfg base_cfg; | ||
134 | enum skl_ch_cfg out_ch_cfg; | ||
135 | /* This should be set to 1 if user coefficients are required */ | ||
136 | u32 coeff_sel; | ||
137 | /* Pass the user coeff in this array */ | ||
138 | s32 coeff[UP_DOWN_MIXER_MAX_COEFF]; | ||
139 | } __packed; | ||
140 | |||
141 | enum skl_dma_type { | ||
142 | SKL_DMA_HDA_HOST_OUTPUT_CLASS = 0, | ||
143 | SKL_DMA_HDA_HOST_INPUT_CLASS = 1, | ||
144 | SKL_DMA_HDA_HOST_INOUT_CLASS = 2, | ||
145 | SKL_DMA_HDA_LINK_OUTPUT_CLASS = 8, | ||
146 | SKL_DMA_HDA_LINK_INPUT_CLASS = 9, | ||
147 | SKL_DMA_HDA_LINK_INOUT_CLASS = 0xA, | ||
148 | SKL_DMA_DMIC_LINK_INPUT_CLASS = 0xB, | ||
149 | SKL_DMA_I2S_LINK_OUTPUT_CLASS = 0xC, | ||
150 | SKL_DMA_I2S_LINK_INPUT_CLASS = 0xD, | ||
151 | }; | ||
152 | |||
153 | union skl_ssp_dma_node { | ||
154 | u8 val; | ||
155 | struct { | ||
156 | u8 dual_mono:1; | ||
157 | u8 time_slot:3; | ||
158 | u8 i2s_instance:4; | ||
159 | } dma_node; | ||
160 | }; | ||
161 | |||
162 | union skl_connector_node_id { | ||
163 | u32 val; | ||
164 | struct { | ||
165 | u32 vindex:8; | ||
166 | u32 dma_type:4; | ||
167 | u32 rsvd:20; | ||
168 | } node; | ||
169 | }; | ||
170 | |||
171 | struct skl_module_fmt { | ||
172 | u32 channels; | ||
173 | u32 s_freq; | ||
174 | u32 bit_depth; | ||
175 | u32 valid_bit_depth; | ||
176 | u32 ch_cfg; | ||
177 | }; | ||
178 | |||
179 | struct skl_module_inst_id { | ||
180 | u32 module_id; | ||
181 | u32 instance_id; | ||
182 | }; | ||
183 | |||
184 | struct skl_module_pin { | ||
185 | struct skl_module_inst_id id; | ||
186 | u8 pin_index; | ||
187 | bool is_dynamic; | ||
188 | bool in_use; | ||
189 | }; | ||
190 | |||
191 | struct skl_specific_cfg { | ||
192 | u32 caps_size; | ||
193 | u32 *caps; | ||
194 | }; | ||
195 | |||
196 | enum skl_pipe_state { | ||
197 | SKL_PIPE_INVALID = 0, | ||
198 | SKL_PIPE_CREATED = 1, | ||
199 | SKL_PIPE_PAUSED = 2, | ||
200 | SKL_PIPE_STARTED = 3 | ||
201 | }; | ||
202 | |||
203 | struct skl_pipe_module { | ||
204 | struct snd_soc_dapm_widget *w; | ||
205 | struct list_head node; | ||
206 | }; | ||
207 | |||
208 | struct skl_pipe_params { | ||
209 | u8 host_dma_id; | ||
210 | u8 link_dma_id; | ||
211 | u32 ch; | ||
212 | u32 s_freq; | ||
213 | u32 s_fmt; | ||
214 | u8 linktype; | ||
215 | int stream; | ||
216 | }; | ||
217 | |||
218 | struct skl_pipe { | ||
219 | u8 ppl_id; | ||
220 | u8 pipe_priority; | ||
221 | u16 conn_type; | ||
222 | u32 memory_pages; | ||
223 | struct skl_pipe_params *p_params; | ||
224 | enum skl_pipe_state state; | ||
225 | struct list_head w_list; | ||
226 | }; | ||
227 | |||
228 | enum skl_module_state { | ||
229 | SKL_MODULE_UNINIT = 0, | ||
230 | SKL_MODULE_INIT_DONE = 1, | ||
231 | SKL_MODULE_LOADED = 2, | ||
232 | SKL_MODULE_UNLOADED = 3, | ||
233 | SKL_MODULE_BIND_DONE = 4 | ||
234 | }; | ||
235 | |||
236 | struct skl_module_cfg { | ||
237 | struct skl_module_inst_id id; | ||
238 | struct skl_module_fmt in_fmt; | ||
239 | struct skl_module_fmt out_fmt; | ||
240 | u8 max_in_queue; | ||
241 | u8 max_out_queue; | ||
242 | u8 in_queue_mask; | ||
243 | u8 out_queue_mask; | ||
244 | u8 in_queue; | ||
245 | u8 out_queue; | ||
246 | u32 mcps; | ||
247 | u32 ibs; | ||
248 | u32 obs; | ||
249 | u8 is_loadable; | ||
250 | u8 core_id; | ||
251 | u8 dev_type; | ||
252 | u8 dma_id; | ||
253 | u8 time_slot; | ||
254 | u32 params_fixup; | ||
255 | u32 converter; | ||
256 | u32 vbus_id; | ||
257 | struct skl_module_pin *m_in_pin; | ||
258 | struct skl_module_pin *m_out_pin; | ||
259 | enum skl_module_type m_type; | ||
260 | enum skl_hw_conn_type hw_conn_type; | ||
261 | enum skl_module_state m_state; | ||
262 | struct skl_pipe *pipe; | ||
263 | struct skl_specific_cfg formats_config; | ||
264 | }; | ||
265 | |||
266 | int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe); | ||
267 | |||
268 | int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | ||
269 | |||
270 | int skl_pause_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | ||
271 | |||
272 | int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | ||
273 | |||
274 | int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | ||
275 | |||
276 | int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config, | ||
277 | char *param); | ||
278 | |||
279 | int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg | ||
280 | *src_module, struct skl_module_cfg *dst_module); | ||
281 | |||
282 | int skl_unbind_modules(struct skl_sst *ctx, struct skl_module_cfg | ||
283 | *src_module, struct skl_module_cfg *dst_module); | ||
284 | |||
285 | enum skl_bitdepth skl_get_bit_depth(int params); | ||
286 | #endif | ||
diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h new file mode 100644 index 000000000000..a50689825bca --- /dev/null +++ b/sound/soc/intel/skylake/skl-tplg-interface.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * skl-tplg-interface.h - Intel DSP FW private data interface | ||
3 | * | ||
4 | * Copyright (C) 2015 Intel Corp | ||
5 | * Author: Jeeja KP <jeeja.kp@intel.com> | ||
6 | * Nilofer, Samreen <samreen.nilofer@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as version 2, as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #ifndef __HDA_TPLG_INTERFACE_H__ | ||
20 | #define __HDA_TPLG_INTERFACE_H__ | ||
21 | |||
22 | /** | ||
23 | * enum skl_ch_cfg - channel configuration | ||
24 | * | ||
25 | * @SKL_CH_CFG_MONO: One channel only | ||
26 | * @SKL_CH_CFG_STEREO: L & R | ||
27 | * @SKL_CH_CFG_2_1: L, R & LFE | ||
28 | * @SKL_CH_CFG_3_0: L, C & R | ||
29 | * @SKL_CH_CFG_3_1: L, C, R & LFE | ||
30 | * @SKL_CH_CFG_QUATRO: L, R, Ls & Rs | ||
31 | * @SKL_CH_CFG_4_0: L, C, R & Cs | ||
32 | * @SKL_CH_CFG_5_0: L, C, R, Ls & Rs | ||
33 | * @SKL_CH_CFG_5_1: L, C, R, Ls, Rs & LFE | ||
34 | * @SKL_CH_CFG_DUAL_MONO: One channel replicated in two | ||
35 | * @SKL_CH_CFG_I2S_DUAL_STEREO_0: Stereo(L,R) in 4 slots, 1st stream:[ L, R, -, - ] | ||
36 | * @SKL_CH_CFG_I2S_DUAL_STEREO_1: Stereo(L,R) in 4 slots, 2nd stream:[ -, -, L, R ] | ||
37 | * @SKL_CH_CFG_INVALID: Invalid | ||
38 | */ | ||
39 | enum skl_ch_cfg { | ||
40 | SKL_CH_CFG_MONO = 0, | ||
41 | SKL_CH_CFG_STEREO = 1, | ||
42 | SKL_CH_CFG_2_1 = 2, | ||
43 | SKL_CH_CFG_3_0 = 3, | ||
44 | SKL_CH_CFG_3_1 = 4, | ||
45 | SKL_CH_CFG_QUATRO = 5, | ||
46 | SKL_CH_CFG_4_0 = 6, | ||
47 | SKL_CH_CFG_5_0 = 7, | ||
48 | SKL_CH_CFG_5_1 = 8, | ||
49 | SKL_CH_CFG_DUAL_MONO = 9, | ||
50 | SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10, | ||
51 | SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11, | ||
52 | SKL_CH_CFG_INVALID | ||
53 | }; | ||
54 | |||
55 | enum skl_module_type { | ||
56 | SKL_MODULE_TYPE_MIXER = 0, | ||
57 | SKL_MODULE_TYPE_COPIER, | ||
58 | SKL_MODULE_TYPE_UPDWMIX, | ||
59 | SKL_MODULE_TYPE_SRCINT | ||
60 | }; | ||
61 | |||
62 | enum skl_core_affinity { | ||
63 | SKL_AFFINITY_CORE_0 = 0, | ||
64 | SKL_AFFINITY_CORE_1, | ||
65 | SKL_AFFINITY_CORE_MAX | ||
66 | }; | ||
67 | |||
68 | enum skl_pipe_conn_type { | ||
69 | SKL_PIPE_CONN_TYPE_NONE = 0, | ||
70 | SKL_PIPE_CONN_TYPE_FE, | ||
71 | SKL_PIPE_CONN_TYPE_BE | ||
72 | }; | ||
73 | |||
74 | enum skl_hw_conn_type { | ||
75 | SKL_CONN_NONE = 0, | ||
76 | SKL_CONN_SOURCE = 1, | ||
77 | SKL_CONN_SINK = 2 | ||
78 | }; | ||
79 | |||
80 | enum skl_dev_type { | ||
81 | SKL_DEVICE_BT = 0x0, | ||
82 | SKL_DEVICE_DMIC = 0x1, | ||
83 | SKL_DEVICE_I2S = 0x2, | ||
84 | SKL_DEVICE_SLIMBUS = 0x3, | ||
85 | SKL_DEVICE_HDALINK = 0x4, | ||
86 | SKL_DEVICE_NONE | ||
87 | }; | ||
88 | #endif | ||
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c new file mode 100644 index 000000000000..348d094e81d6 --- /dev/null +++ b/sound/soc/intel/skylake/skl.c | |||
@@ -0,0 +1,536 @@ | |||
1 | /* | ||
2 | * skl.c - Implementation of ASoC Intel SKL HD Audio driver | ||
3 | * | ||
4 | * Copyright (C) 2014-2015 Intel Corp | ||
5 | * Author: Jeeja KP <jeeja.kp@intel.com> | ||
6 | * | ||
7 | * Derived mostly from Intel HDA driver with following copyrights: | ||
8 | * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> | ||
9 | * PeiSen Hou <pshou@realtek.com.tw> | ||
10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; version 2 of the License. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, but | ||
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
19 | * General Public License for more details. | ||
20 | * | ||
21 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/pci.h> | ||
26 | #include <linux/pm_runtime.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include "skl.h" | ||
30 | |||
31 | /* | ||
32 | * initialize the PCI registers | ||
33 | */ | ||
34 | static void skl_update_pci_byte(struct pci_dev *pci, unsigned int reg, | ||
35 | unsigned char mask, unsigned char val) | ||
36 | { | ||
37 | unsigned char data; | ||
38 | |||
39 | pci_read_config_byte(pci, reg, &data); | ||
40 | data &= ~mask; | ||
41 | data |= (val & mask); | ||
42 | pci_write_config_byte(pci, reg, data); | ||
43 | } | ||
44 | |||
45 | static void skl_init_pci(struct skl *skl) | ||
46 | { | ||
47 | struct hdac_ext_bus *ebus = &skl->ebus; | ||
48 | |||
49 | /* | ||
50 | * Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | ||
51 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | ||
52 | * Ensuring these bits are 0 clears playback static on some HD Audio | ||
53 | * codecs. | ||
54 | * The PCI register TCSEL is defined in the Intel manuals. | ||
55 | */ | ||
56 | dev_dbg(ebus_to_hbus(ebus)->dev, "Clearing TCSEL\n"); | ||
57 | skl_update_pci_byte(skl->pci, AZX_PCIREG_TCSEL, 0x07, 0); | ||
58 | } | ||
59 | |||
60 | /* called from IRQ */ | ||
61 | static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr) | ||
62 | { | ||
63 | snd_pcm_period_elapsed(hstr->substream); | ||
64 | } | ||
65 | |||
66 | static irqreturn_t skl_interrupt(int irq, void *dev_id) | ||
67 | { | ||
68 | struct hdac_ext_bus *ebus = dev_id; | ||
69 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
70 | u32 status; | ||
71 | |||
72 | if (!pm_runtime_active(bus->dev)) | ||
73 | return IRQ_NONE; | ||
74 | |||
75 | spin_lock(&bus->reg_lock); | ||
76 | |||
77 | status = snd_hdac_chip_readl(bus, INTSTS); | ||
78 | if (status == 0 || status == 0xffffffff) { | ||
79 | spin_unlock(&bus->reg_lock); | ||
80 | return IRQ_NONE; | ||
81 | } | ||
82 | |||
83 | /* clear rirb int */ | ||
84 | status = snd_hdac_chip_readb(bus, RIRBSTS); | ||
85 | if (status & RIRB_INT_MASK) { | ||
86 | if (status & RIRB_INT_RESPONSE) | ||
87 | snd_hdac_bus_update_rirb(bus); | ||
88 | snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); | ||
89 | } | ||
90 | |||
91 | spin_unlock(&bus->reg_lock); | ||
92 | |||
93 | return snd_hdac_chip_readl(bus, INTSTS) ? IRQ_WAKE_THREAD : IRQ_HANDLED; | ||
94 | } | ||
95 | |||
96 | static irqreturn_t skl_threaded_handler(int irq, void *dev_id) | ||
97 | { | ||
98 | struct hdac_ext_bus *ebus = dev_id; | ||
99 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
100 | u32 status; | ||
101 | |||
102 | status = snd_hdac_chip_readl(bus, INTSTS); | ||
103 | |||
104 | snd_hdac_bus_handle_stream_irq(bus, status, skl_stream_update); | ||
105 | |||
106 | return IRQ_HANDLED; | ||
107 | } | ||
108 | |||
109 | static int skl_acquire_irq(struct hdac_ext_bus *ebus, int do_disconnect) | ||
110 | { | ||
111 | struct skl *skl = ebus_to_skl(ebus); | ||
112 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
113 | int ret; | ||
114 | |||
115 | ret = request_threaded_irq(skl->pci->irq, skl_interrupt, | ||
116 | skl_threaded_handler, | ||
117 | IRQF_SHARED, | ||
118 | KBUILD_MODNAME, ebus); | ||
119 | if (ret) { | ||
120 | dev_err(bus->dev, | ||
121 | "unable to grab IRQ %d, disabling device\n", | ||
122 | skl->pci->irq); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | bus->irq = skl->pci->irq; | ||
127 | pci_intx(skl->pci, 1); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | #ifdef CONFIG_PM_SLEEP | ||
133 | /* | ||
134 | * power management | ||
135 | */ | ||
136 | static int skl_suspend(struct device *dev) | ||
137 | { | ||
138 | struct pci_dev *pci = to_pci_dev(dev); | ||
139 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | ||
140 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
141 | |||
142 | snd_hdac_bus_stop_chip(bus); | ||
143 | snd_hdac_bus_enter_link_reset(bus); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int skl_resume(struct device *dev) | ||
149 | { | ||
150 | struct pci_dev *pci = to_pci_dev(dev); | ||
151 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | ||
152 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
153 | struct skl *hda = ebus_to_skl(ebus); | ||
154 | |||
155 | skl_init_pci(hda); | ||
156 | |||
157 | snd_hdac_bus_init_chip(bus, 1); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | #endif /* CONFIG_PM_SLEEP */ | ||
162 | |||
163 | #ifdef CONFIG_PM | ||
164 | static int skl_runtime_suspend(struct device *dev) | ||
165 | { | ||
166 | struct pci_dev *pci = to_pci_dev(dev); | ||
167 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | ||
168 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
169 | |||
170 | dev_dbg(bus->dev, "in %s\n", __func__); | ||
171 | |||
172 | /* enable controller wake up event */ | ||
173 | snd_hdac_chip_updatew(bus, WAKEEN, 0, STATESTS_INT_MASK); | ||
174 | |||
175 | snd_hdac_bus_stop_chip(bus); | ||
176 | snd_hdac_bus_enter_link_reset(bus); | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static int skl_runtime_resume(struct device *dev) | ||
182 | { | ||
183 | struct pci_dev *pci = to_pci_dev(dev); | ||
184 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | ||
185 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
186 | struct skl *hda = ebus_to_skl(ebus); | ||
187 | int status; | ||
188 | |||
189 | dev_dbg(bus->dev, "in %s\n", __func__); | ||
190 | |||
191 | /* Read STATESTS before controller reset */ | ||
192 | status = snd_hdac_chip_readw(bus, STATESTS); | ||
193 | |||
194 | skl_init_pci(hda); | ||
195 | snd_hdac_bus_init_chip(bus, true); | ||
196 | /* disable controller Wake Up event */ | ||
197 | snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, 0); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | #endif /* CONFIG_PM */ | ||
202 | |||
203 | static const struct dev_pm_ops skl_pm = { | ||
204 | SET_SYSTEM_SLEEP_PM_OPS(skl_suspend, skl_resume) | ||
205 | SET_RUNTIME_PM_OPS(skl_runtime_suspend, skl_runtime_resume, NULL) | ||
206 | }; | ||
207 | |||
208 | /* | ||
209 | * destructor | ||
210 | */ | ||
211 | static int skl_free(struct hdac_ext_bus *ebus) | ||
212 | { | ||
213 | struct skl *skl = ebus_to_skl(ebus); | ||
214 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
215 | |||
216 | skl->init_failed = 1; /* to be sure */ | ||
217 | |||
218 | snd_hdac_ext_stop_streams(ebus); | ||
219 | |||
220 | if (bus->irq >= 0) | ||
221 | free_irq(bus->irq, (void *)bus); | ||
222 | if (bus->remap_addr) | ||
223 | iounmap(bus->remap_addr); | ||
224 | |||
225 | snd_hdac_bus_free_stream_pages(bus); | ||
226 | snd_hdac_stream_free_all(ebus); | ||
227 | snd_hdac_link_free_all(ebus); | ||
228 | pci_release_regions(skl->pci); | ||
229 | pci_disable_device(skl->pci); | ||
230 | |||
231 | snd_hdac_ext_bus_exit(ebus); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int skl_dmic_device_register(struct skl *skl) | ||
237 | { | ||
238 | struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); | ||
239 | struct platform_device *pdev; | ||
240 | int ret; | ||
241 | |||
242 | /* SKL has one dmic port, so allocate dmic device for this */ | ||
243 | pdev = platform_device_alloc("dmic-codec", -1); | ||
244 | if (!pdev) { | ||
245 | dev_err(bus->dev, "failed to allocate dmic device\n"); | ||
246 | return -ENOMEM; | ||
247 | } | ||
248 | |||
249 | ret = platform_device_add(pdev); | ||
250 | if (ret) { | ||
251 | dev_err(bus->dev, "failed to add dmic device: %d\n", ret); | ||
252 | platform_device_put(pdev); | ||
253 | return ret; | ||
254 | } | ||
255 | skl->dmic_dev = pdev; | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static void skl_dmic_device_unregister(struct skl *skl) | ||
261 | { | ||
262 | if (skl->dmic_dev) | ||
263 | platform_device_unregister(skl->dmic_dev); | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * Probe the given codec address | ||
268 | */ | ||
269 | static int probe_codec(struct hdac_ext_bus *ebus, int addr) | ||
270 | { | ||
271 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
272 | unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | | ||
273 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; | ||
274 | unsigned int res; | ||
275 | |||
276 | mutex_lock(&bus->cmd_mutex); | ||
277 | snd_hdac_bus_send_cmd(bus, cmd); | ||
278 | snd_hdac_bus_get_response(bus, addr, &res); | ||
279 | mutex_unlock(&bus->cmd_mutex); | ||
280 | if (res == -1) | ||
281 | return -EIO; | ||
282 | dev_dbg(bus->dev, "codec #%d probed OK\n", addr); | ||
283 | |||
284 | return snd_hdac_ext_bus_device_init(ebus, addr); | ||
285 | } | ||
286 | |||
287 | /* Codec initialization */ | ||
288 | static int skl_codec_create(struct hdac_ext_bus *ebus) | ||
289 | { | ||
290 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
291 | int c, max_slots; | ||
292 | |||
293 | max_slots = HDA_MAX_CODECS; | ||
294 | |||
295 | /* First try to probe all given codec slots */ | ||
296 | for (c = 0; c < max_slots; c++) { | ||
297 | if ((bus->codec_mask & (1 << c))) { | ||
298 | if (probe_codec(ebus, c) < 0) { | ||
299 | /* | ||
300 | * Some BIOSen give you wrong codec addresses | ||
301 | * that don't exist | ||
302 | */ | ||
303 | dev_warn(bus->dev, | ||
304 | "Codec #%d probe error; disabling it...\n", c); | ||
305 | bus->codec_mask &= ~(1 << c); | ||
306 | /* | ||
307 | * More badly, accessing to a non-existing | ||
308 | * codec often screws up the controller bus, | ||
309 | * and disturbs the further communications. | ||
310 | * Thus if an error occurs during probing, | ||
311 | * better to reset the controller bus to get | ||
312 | * back to the sanity state. | ||
313 | */ | ||
314 | snd_hdac_bus_stop_chip(bus); | ||
315 | snd_hdac_bus_init_chip(bus, true); | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static const struct hdac_bus_ops bus_core_ops = { | ||
324 | .command = snd_hdac_bus_send_cmd, | ||
325 | .get_response = snd_hdac_bus_get_response, | ||
326 | }; | ||
327 | |||
328 | /* | ||
329 | * constructor | ||
330 | */ | ||
331 | static int skl_create(struct pci_dev *pci, | ||
332 | const struct hdac_io_ops *io_ops, | ||
333 | struct skl **rskl) | ||
334 | { | ||
335 | struct skl *skl; | ||
336 | struct hdac_ext_bus *ebus; | ||
337 | |||
338 | int err; | ||
339 | |||
340 | *rskl = NULL; | ||
341 | |||
342 | err = pci_enable_device(pci); | ||
343 | if (err < 0) | ||
344 | return err; | ||
345 | |||
346 | skl = devm_kzalloc(&pci->dev, sizeof(*skl), GFP_KERNEL); | ||
347 | if (!skl) { | ||
348 | pci_disable_device(pci); | ||
349 | return -ENOMEM; | ||
350 | } | ||
351 | ebus = &skl->ebus; | ||
352 | snd_hdac_ext_bus_init(ebus, &pci->dev, &bus_core_ops, io_ops); | ||
353 | ebus->bus.use_posbuf = 1; | ||
354 | skl->pci = pci; | ||
355 | |||
356 | ebus->bus.bdl_pos_adj = 0; | ||
357 | |||
358 | *rskl = skl; | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int skl_first_init(struct hdac_ext_bus *ebus) | ||
364 | { | ||
365 | struct skl *skl = ebus_to_skl(ebus); | ||
366 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
367 | struct pci_dev *pci = skl->pci; | ||
368 | int err; | ||
369 | unsigned short gcap; | ||
370 | int cp_streams, pb_streams, start_idx; | ||
371 | |||
372 | err = pci_request_regions(pci, "Skylake HD audio"); | ||
373 | if (err < 0) | ||
374 | return err; | ||
375 | |||
376 | bus->addr = pci_resource_start(pci, 0); | ||
377 | bus->remap_addr = pci_ioremap_bar(pci, 0); | ||
378 | if (bus->remap_addr == NULL) { | ||
379 | dev_err(bus->dev, "ioremap error\n"); | ||
380 | return -ENXIO; | ||
381 | } | ||
382 | |||
383 | snd_hdac_ext_bus_parse_capabilities(ebus); | ||
384 | |||
385 | if (skl_acquire_irq(ebus, 0) < 0) | ||
386 | return -EBUSY; | ||
387 | |||
388 | pci_set_master(pci); | ||
389 | synchronize_irq(bus->irq); | ||
390 | |||
391 | gcap = snd_hdac_chip_readw(bus, GCAP); | ||
392 | dev_dbg(bus->dev, "chipset global capabilities = 0x%x\n", gcap); | ||
393 | |||
394 | /* allow 64bit DMA address if supported by H/W */ | ||
395 | if (!dma_set_mask(bus->dev, DMA_BIT_MASK(64))) { | ||
396 | dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(64)); | ||
397 | } else { | ||
398 | dma_set_mask(bus->dev, DMA_BIT_MASK(32)); | ||
399 | dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(32)); | ||
400 | } | ||
401 | |||
402 | /* read number of streams from GCAP register */ | ||
403 | cp_streams = (gcap >> 8) & 0x0f; | ||
404 | pb_streams = (gcap >> 12) & 0x0f; | ||
405 | |||
406 | if (!pb_streams && !cp_streams) | ||
407 | return -EIO; | ||
408 | |||
409 | ebus->num_streams = cp_streams + pb_streams; | ||
410 | |||
411 | /* initialize streams */ | ||
412 | snd_hdac_ext_stream_init_all | ||
413 | (ebus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE); | ||
414 | start_idx = cp_streams; | ||
415 | snd_hdac_ext_stream_init_all | ||
416 | (ebus, start_idx, pb_streams, SNDRV_PCM_STREAM_PLAYBACK); | ||
417 | |||
418 | err = snd_hdac_bus_alloc_stream_pages(bus); | ||
419 | if (err < 0) | ||
420 | return err; | ||
421 | |||
422 | /* initialize chip */ | ||
423 | skl_init_pci(skl); | ||
424 | |||
425 | snd_hdac_bus_init_chip(bus, true); | ||
426 | |||
427 | /* codec detection */ | ||
428 | if (!bus->codec_mask) { | ||
429 | dev_err(bus->dev, "no codecs found!\n"); | ||
430 | return -ENODEV; | ||
431 | } | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int skl_probe(struct pci_dev *pci, | ||
437 | const struct pci_device_id *pci_id) | ||
438 | { | ||
439 | struct skl *skl; | ||
440 | struct hdac_ext_bus *ebus = NULL; | ||
441 | struct hdac_bus *bus = NULL; | ||
442 | int err; | ||
443 | |||
444 | /* we use ext core ops, so provide NULL for ops here */ | ||
445 | err = skl_create(pci, NULL, &skl); | ||
446 | if (err < 0) | ||
447 | return err; | ||
448 | |||
449 | ebus = &skl->ebus; | ||
450 | bus = ebus_to_hbus(ebus); | ||
451 | |||
452 | err = skl_first_init(ebus); | ||
453 | if (err < 0) | ||
454 | goto out_free; | ||
455 | |||
456 | pci_set_drvdata(skl->pci, ebus); | ||
457 | |||
458 | /* check if dsp is there */ | ||
459 | if (ebus->ppcap) { | ||
460 | /* TODO register with dsp IPC */ | ||
461 | dev_dbg(bus->dev, "Register dsp\n"); | ||
462 | } | ||
463 | |||
464 | if (ebus->mlcap) | ||
465 | snd_hdac_ext_bus_get_ml_capabilities(ebus); | ||
466 | |||
467 | /* create device for soc dmic */ | ||
468 | err = skl_dmic_device_register(skl); | ||
469 | if (err < 0) | ||
470 | goto out_free; | ||
471 | |||
472 | /* register platform dai and controls */ | ||
473 | err = skl_platform_register(bus->dev); | ||
474 | if (err < 0) | ||
475 | goto out_dmic_free; | ||
476 | |||
477 | /* create codec instances */ | ||
478 | err = skl_codec_create(ebus); | ||
479 | if (err < 0) | ||
480 | goto out_unregister; | ||
481 | |||
482 | /*configure PM */ | ||
483 | pm_runtime_set_autosuspend_delay(bus->dev, SKL_SUSPEND_DELAY); | ||
484 | pm_runtime_use_autosuspend(bus->dev); | ||
485 | pm_runtime_put_noidle(bus->dev); | ||
486 | pm_runtime_allow(bus->dev); | ||
487 | |||
488 | return 0; | ||
489 | |||
490 | out_unregister: | ||
491 | skl_platform_unregister(bus->dev); | ||
492 | out_dmic_free: | ||
493 | skl_dmic_device_unregister(skl); | ||
494 | out_free: | ||
495 | skl->init_failed = 1; | ||
496 | skl_free(ebus); | ||
497 | |||
498 | return err; | ||
499 | } | ||
500 | |||
501 | static void skl_remove(struct pci_dev *pci) | ||
502 | { | ||
503 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | ||
504 | struct skl *skl = ebus_to_skl(ebus); | ||
505 | |||
506 | if (pci_dev_run_wake(pci)) | ||
507 | pm_runtime_get_noresume(&pci->dev); | ||
508 | pci_dev_put(pci); | ||
509 | skl_platform_unregister(&pci->dev); | ||
510 | skl_dmic_device_unregister(skl); | ||
511 | skl_free(ebus); | ||
512 | dev_set_drvdata(&pci->dev, NULL); | ||
513 | } | ||
514 | |||
515 | /* PCI IDs */ | ||
516 | static const struct pci_device_id skl_ids[] = { | ||
517 | /* Sunrise Point-LP */ | ||
518 | { PCI_DEVICE(0x8086, 0x9d70), 0}, | ||
519 | { 0, } | ||
520 | }; | ||
521 | MODULE_DEVICE_TABLE(pci, skl_ids); | ||
522 | |||
523 | /* pci_driver definition */ | ||
524 | static struct pci_driver skl_driver = { | ||
525 | .name = KBUILD_MODNAME, | ||
526 | .id_table = skl_ids, | ||
527 | .probe = skl_probe, | ||
528 | .remove = skl_remove, | ||
529 | .driver = { | ||
530 | .pm = &skl_pm, | ||
531 | }, | ||
532 | }; | ||
533 | module_pci_driver(skl_driver); | ||
534 | |||
535 | MODULE_LICENSE("GPL v2"); | ||
536 | MODULE_DESCRIPTION("Intel Skylake ASoC HDA driver"); | ||
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h new file mode 100644 index 000000000000..f7fdbb02947f --- /dev/null +++ b/sound/soc/intel/skylake/skl.h | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * skl.h - HD Audio skylake defintions. | ||
3 | * | ||
4 | * Copyright (C) 2015 Intel Corp | ||
5 | * Author: Jeeja KP <jeeja.kp@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #ifndef __SOUND_SOC_SKL_H | ||
22 | #define __SOUND_SOC_SKL_H | ||
23 | |||
24 | #include <sound/hda_register.h> | ||
25 | #include <sound/hdaudio_ext.h> | ||
26 | #include "skl-nhlt.h" | ||
27 | |||
28 | #define SKL_SUSPEND_DELAY 2000 | ||
29 | |||
30 | /* Vendor Specific Registers */ | ||
31 | #define AZX_REG_VS_EM1 0x1000 | ||
32 | #define AZX_REG_VS_INRC 0x1004 | ||
33 | #define AZX_REG_VS_OUTRC 0x1008 | ||
34 | #define AZX_REG_VS_FIFOTRK 0x100C | ||
35 | #define AZX_REG_VS_FIFOTRK2 0x1010 | ||
36 | #define AZX_REG_VS_EM2 0x1030 | ||
37 | #define AZX_REG_VS_EM3L 0x1038 | ||
38 | #define AZX_REG_VS_EM3U 0x103C | ||
39 | #define AZX_REG_VS_EM4L 0x1040 | ||
40 | #define AZX_REG_VS_EM4U 0x1044 | ||
41 | #define AZX_REG_VS_LTRC 0x1048 | ||
42 | #define AZX_REG_VS_D0I3C 0x104A | ||
43 | #define AZX_REG_VS_PCE 0x104B | ||
44 | #define AZX_REG_VS_L2MAGC 0x1050 | ||
45 | #define AZX_REG_VS_L2LAHPT 0x1054 | ||
46 | #define AZX_REG_VS_SDXDPIB_XBASE 0x1084 | ||
47 | #define AZX_REG_VS_SDXDPIB_XINTERVAL 0x20 | ||
48 | #define AZX_REG_VS_SDXEFIFOS_XBASE 0x1094 | ||
49 | #define AZX_REG_VS_SDXEFIFOS_XINTERVAL 0x20 | ||
50 | |||
51 | struct skl { | ||
52 | struct hdac_ext_bus ebus; | ||
53 | struct pci_dev *pci; | ||
54 | |||
55 | unsigned int init_failed:1; /* delayed init failed */ | ||
56 | struct platform_device *dmic_dev; | ||
57 | |||
58 | void __iomem *nhlt; /* nhlt ptr */ | ||
59 | struct skl_sst *skl_sst; /* sst skl ctx */ | ||
60 | }; | ||
61 | |||
62 | #define skl_to_ebus(s) (&(s)->ebus) | ||
63 | #define ebus_to_skl(sbus) \ | ||
64 | container_of(sbus, struct skl, sbus) | ||
65 | |||
66 | /* to pass dai dma data */ | ||
67 | struct skl_dma_params { | ||
68 | u32 format; | ||
69 | u8 stream_tag; | ||
70 | }; | ||
71 | |||
72 | int skl_platform_unregister(struct device *dev); | ||
73 | int skl_platform_register(struct device *dev); | ||
74 | |||
75 | void __iomem *skl_nhlt_init(struct device *dev); | ||
76 | void skl_nhlt_free(void __iomem *addr); | ||
77 | struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, | ||
78 | u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn); | ||
79 | |||
80 | int skl_init_dsp(struct skl *skl); | ||
81 | void skl_free_dsp(struct skl *skl); | ||
82 | int skl_suspend_dsp(struct skl *skl); | ||
83 | int skl_resume_dsp(struct skl *skl); | ||
84 | #endif /* __SOUND_SOC_SKL_H */ | ||
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index 4cf2245950d7..dbfdfe99c69d 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c | |||
@@ -148,10 +148,14 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) | |||
148 | dram = mv_mbus_dram_info(); | 148 | dram = mv_mbus_dram_info(); |
149 | addr = substream->dma_buffer.addr; | 149 | addr = substream->dma_buffer.addr; |
150 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 150 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
151 | if (priv->substream_play) | ||
152 | return -EBUSY; | ||
151 | priv->substream_play = substream; | 153 | priv->substream_play = substream; |
152 | kirkwood_dma_conf_mbus_windows(priv->io, | 154 | kirkwood_dma_conf_mbus_windows(priv->io, |
153 | KIRKWOOD_PLAYBACK_WIN, addr, dram); | 155 | KIRKWOOD_PLAYBACK_WIN, addr, dram); |
154 | } else { | 156 | } else { |
157 | if (priv->substream_rec) | ||
158 | return -EBUSY; | ||
155 | priv->substream_rec = substream; | 159 | priv->substream_rec = substream; |
156 | kirkwood_dma_conf_mbus_windows(priv->io, | 160 | kirkwood_dma_conf_mbus_windows(priv->io, |
157 | KIRKWOOD_RECORD_WIN, addr, dram); | 161 | KIRKWOOD_RECORD_WIN, addr, dram); |
diff --git a/sound/soc/mediatek/mt8173-max98090.c b/sound/soc/mediatek/mt8173-max98090.c index 2d2536af141f..684e8a78bed0 100644 --- a/sound/soc/mediatek/mt8173-max98090.c +++ b/sound/soc/mediatek/mt8173-max98090.c | |||
@@ -136,6 +136,7 @@ static struct snd_soc_dai_link mt8173_max98090_dais[] = { | |||
136 | 136 | ||
137 | static struct snd_soc_card mt8173_max98090_card = { | 137 | static struct snd_soc_card mt8173_max98090_card = { |
138 | .name = "mt8173-max98090", | 138 | .name = "mt8173-max98090", |
139 | .owner = THIS_MODULE, | ||
139 | .dai_link = mt8173_max98090_dais, | 140 | .dai_link = mt8173_max98090_dais, |
140 | .num_links = ARRAY_SIZE(mt8173_max98090_dais), | 141 | .num_links = ARRAY_SIZE(mt8173_max98090_dais), |
141 | .controls = mt8173_max98090_controls, | 142 | .controls = mt8173_max98090_controls, |
@@ -202,7 +203,6 @@ MODULE_DEVICE_TABLE(of, mt8173_max98090_dt_match); | |||
202 | static struct platform_driver mt8173_max98090_driver = { | 203 | static struct platform_driver mt8173_max98090_driver = { |
203 | .driver = { | 204 | .driver = { |
204 | .name = "mt8173-max98090", | 205 | .name = "mt8173-max98090", |
205 | .owner = THIS_MODULE, | ||
206 | .of_match_table = mt8173_max98090_dt_match, | 206 | .of_match_table = mt8173_max98090_dt_match, |
207 | #ifdef CONFIG_PM | 207 | #ifdef CONFIG_PM |
208 | .pm = &snd_soc_pm_ops, | 208 | .pm = &snd_soc_pm_ops, |
diff --git a/sound/soc/mediatek/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173-rt5650-rt5676.c index 6f52eca05e26..86cf9752f18a 100644 --- a/sound/soc/mediatek/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173-rt5650-rt5676.c | |||
@@ -191,6 +191,7 @@ static struct snd_soc_codec_conf mt8173_rt5650_rt5676_codec_conf[] = { | |||
191 | 191 | ||
192 | static struct snd_soc_card mt8173_rt5650_rt5676_card = { | 192 | static struct snd_soc_card mt8173_rt5650_rt5676_card = { |
193 | .name = "mtk-rt5650-rt5676", | 193 | .name = "mtk-rt5650-rt5676", |
194 | .owner = THIS_MODULE, | ||
194 | .dai_link = mt8173_rt5650_rt5676_dais, | 195 | .dai_link = mt8173_rt5650_rt5676_dais, |
195 | .num_links = ARRAY_SIZE(mt8173_rt5650_rt5676_dais), | 196 | .num_links = ARRAY_SIZE(mt8173_rt5650_rt5676_dais), |
196 | .codec_conf = mt8173_rt5650_rt5676_codec_conf, | 197 | .codec_conf = mt8173_rt5650_rt5676_codec_conf, |
@@ -269,7 +270,6 @@ MODULE_DEVICE_TABLE(of, mt8173_rt5650_rt5676_dt_match); | |||
269 | static struct platform_driver mt8173_rt5650_rt5676_driver = { | 270 | static struct platform_driver mt8173_rt5650_rt5676_driver = { |
270 | .driver = { | 271 | .driver = { |
271 | .name = "mtk-rt5650-rt5676", | 272 | .name = "mtk-rt5650-rt5676", |
272 | .owner = THIS_MODULE, | ||
273 | .of_match_table = mt8173_rt5650_rt5676_dt_match, | 273 | .of_match_table = mt8173_rt5650_rt5676_dt_match, |
274 | #ifdef CONFIG_PM | 274 | #ifdef CONFIG_PM |
275 | .pm = &snd_soc_pm_ops, | 275 | .pm = &snd_soc_pm_ops, |
diff --git a/sound/soc/mediatek/mtk-afe-common.h b/sound/soc/mediatek/mtk-afe-common.h index a88b17511fdf..cc4393cb1130 100644 --- a/sound/soc/mediatek/mtk-afe-common.h +++ b/sound/soc/mediatek/mtk-afe-common.h | |||
@@ -98,12 +98,4 @@ struct mtk_afe_memif { | |||
98 | const struct mtk_afe_irq_data *irqdata; | 98 | const struct mtk_afe_irq_data *irqdata; |
99 | }; | 99 | }; |
100 | 100 | ||
101 | struct mtk_afe { | ||
102 | /* address for ioremap audio hardware register */ | ||
103 | void __iomem *base_addr; | ||
104 | struct device *dev; | ||
105 | struct regmap *regmap; | ||
106 | struct mtk_afe_memif memif[MTK_AFE_MEMIF_NUM]; | ||
107 | struct clk *clocks[MTK_CLK_NUM]; | ||
108 | }; | ||
109 | #endif | 101 | #endif |
diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c index 9863da73dfe0..d190fe017559 100644 --- a/sound/soc/mediatek/mtk-afe-pcm.c +++ b/sound/soc/mediatek/mtk-afe-pcm.c | |||
@@ -45,18 +45,21 @@ | |||
45 | /* Memory interface */ | 45 | /* Memory interface */ |
46 | #define AFE_DL1_BASE 0x0040 | 46 | #define AFE_DL1_BASE 0x0040 |
47 | #define AFE_DL1_CUR 0x0044 | 47 | #define AFE_DL1_CUR 0x0044 |
48 | #define AFE_DL1_END 0x0048 | ||
48 | #define AFE_DL2_BASE 0x0050 | 49 | #define AFE_DL2_BASE 0x0050 |
49 | #define AFE_DL2_CUR 0x0054 | 50 | #define AFE_DL2_CUR 0x0054 |
50 | #define AFE_AWB_BASE 0x0070 | 51 | #define AFE_AWB_BASE 0x0070 |
51 | #define AFE_AWB_CUR 0x007c | 52 | #define AFE_AWB_CUR 0x007c |
52 | #define AFE_VUL_BASE 0x0080 | 53 | #define AFE_VUL_BASE 0x0080 |
53 | #define AFE_VUL_CUR 0x008c | 54 | #define AFE_VUL_CUR 0x008c |
55 | #define AFE_VUL_END 0x0088 | ||
54 | #define AFE_DAI_BASE 0x0090 | 56 | #define AFE_DAI_BASE 0x0090 |
55 | #define AFE_DAI_CUR 0x009c | 57 | #define AFE_DAI_CUR 0x009c |
56 | #define AFE_MOD_PCM_BASE 0x0330 | 58 | #define AFE_MOD_PCM_BASE 0x0330 |
57 | #define AFE_MOD_PCM_CUR 0x033c | 59 | #define AFE_MOD_PCM_CUR 0x033c |
58 | #define AFE_HDMI_OUT_BASE 0x0374 | 60 | #define AFE_HDMI_OUT_BASE 0x0374 |
59 | #define AFE_HDMI_OUT_CUR 0x0378 | 61 | #define AFE_HDMI_OUT_CUR 0x0378 |
62 | #define AFE_HDMI_OUT_END 0x037c | ||
60 | 63 | ||
61 | #define AFE_ADDA2_TOP_CON0 0x0600 | 64 | #define AFE_ADDA2_TOP_CON0 0x0600 |
62 | 65 | ||
@@ -127,6 +130,34 @@ enum afe_tdm_ch_start { | |||
127 | AFE_TDM_CH_ZERO, | 130 | AFE_TDM_CH_ZERO, |
128 | }; | 131 | }; |
129 | 132 | ||
133 | static const unsigned int mtk_afe_backup_list[] = { | ||
134 | AUDIO_TOP_CON0, | ||
135 | AFE_CONN1, | ||
136 | AFE_CONN2, | ||
137 | AFE_CONN7, | ||
138 | AFE_CONN8, | ||
139 | AFE_DAC_CON1, | ||
140 | AFE_DL1_BASE, | ||
141 | AFE_DL1_END, | ||
142 | AFE_VUL_BASE, | ||
143 | AFE_VUL_END, | ||
144 | AFE_HDMI_OUT_BASE, | ||
145 | AFE_HDMI_OUT_END, | ||
146 | AFE_HDMI_CONN0, | ||
147 | AFE_DAC_CON0, | ||
148 | }; | ||
149 | |||
150 | struct mtk_afe { | ||
151 | /* address for ioremap audio hardware register */ | ||
152 | void __iomem *base_addr; | ||
153 | struct device *dev; | ||
154 | struct regmap *regmap; | ||
155 | struct mtk_afe_memif memif[MTK_AFE_MEMIF_NUM]; | ||
156 | struct clk *clocks[MTK_CLK_NUM]; | ||
157 | unsigned int backup_regs[ARRAY_SIZE(mtk_afe_backup_list)]; | ||
158 | bool suspended; | ||
159 | }; | ||
160 | |||
130 | static const struct snd_pcm_hardware mtk_afe_hardware = { | 161 | static const struct snd_pcm_hardware mtk_afe_hardware = { |
131 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 162 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
132 | SNDRV_PCM_INFO_MMAP_VALID), | 163 | SNDRV_PCM_INFO_MMAP_VALID), |
@@ -722,11 +753,53 @@ static const struct snd_soc_dai_ops mtk_afe_hdmi_ops = { | |||
722 | 753 | ||
723 | }; | 754 | }; |
724 | 755 | ||
756 | static int mtk_afe_runtime_suspend(struct device *dev); | ||
757 | static int mtk_afe_runtime_resume(struct device *dev); | ||
758 | |||
759 | static int mtk_afe_dai_suspend(struct snd_soc_dai *dai) | ||
760 | { | ||
761 | struct mtk_afe *afe = snd_soc_dai_get_drvdata(dai); | ||
762 | int i; | ||
763 | |||
764 | dev_dbg(afe->dev, "%s\n", __func__); | ||
765 | if (pm_runtime_status_suspended(afe->dev) || afe->suspended) | ||
766 | return 0; | ||
767 | |||
768 | for (i = 0; i < ARRAY_SIZE(mtk_afe_backup_list); i++) | ||
769 | regmap_read(afe->regmap, mtk_afe_backup_list[i], | ||
770 | &afe->backup_regs[i]); | ||
771 | |||
772 | afe->suspended = true; | ||
773 | mtk_afe_runtime_suspend(afe->dev); | ||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static int mtk_afe_dai_resume(struct snd_soc_dai *dai) | ||
778 | { | ||
779 | struct mtk_afe *afe = snd_soc_dai_get_drvdata(dai); | ||
780 | int i = 0; | ||
781 | |||
782 | dev_dbg(afe->dev, "%s\n", __func__); | ||
783 | if (pm_runtime_status_suspended(afe->dev) || !afe->suspended) | ||
784 | return 0; | ||
785 | |||
786 | mtk_afe_runtime_resume(afe->dev); | ||
787 | |||
788 | for (i = 0; i < ARRAY_SIZE(mtk_afe_backup_list); i++) | ||
789 | regmap_write(afe->regmap, mtk_afe_backup_list[i], | ||
790 | afe->backup_regs[i]); | ||
791 | |||
792 | afe->suspended = false; | ||
793 | return 0; | ||
794 | } | ||
795 | |||
725 | static struct snd_soc_dai_driver mtk_afe_pcm_dais[] = { | 796 | static struct snd_soc_dai_driver mtk_afe_pcm_dais[] = { |
726 | /* FE DAIs: memory intefaces to CPU */ | 797 | /* FE DAIs: memory intefaces to CPU */ |
727 | { | 798 | { |
728 | .name = "DL1", /* downlink 1 */ | 799 | .name = "DL1", /* downlink 1 */ |
729 | .id = MTK_AFE_MEMIF_DL1, | 800 | .id = MTK_AFE_MEMIF_DL1, |
801 | .suspend = mtk_afe_dai_suspend, | ||
802 | .resume = mtk_afe_dai_resume, | ||
730 | .playback = { | 803 | .playback = { |
731 | .stream_name = "DL1", | 804 | .stream_name = "DL1", |
732 | .channels_min = 1, | 805 | .channels_min = 1, |
@@ -738,6 +811,8 @@ static struct snd_soc_dai_driver mtk_afe_pcm_dais[] = { | |||
738 | }, { | 811 | }, { |
739 | .name = "VUL", /* voice uplink */ | 812 | .name = "VUL", /* voice uplink */ |
740 | .id = MTK_AFE_MEMIF_VUL, | 813 | .id = MTK_AFE_MEMIF_VUL, |
814 | .suspend = mtk_afe_dai_suspend, | ||
815 | .resume = mtk_afe_dai_resume, | ||
741 | .capture = { | 816 | .capture = { |
742 | .stream_name = "VUL", | 817 | .stream_name = "VUL", |
743 | .channels_min = 1, | 818 | .channels_min = 1, |
@@ -774,6 +849,8 @@ static struct snd_soc_dai_driver mtk_afe_hdmi_dais[] = { | |||
774 | { | 849 | { |
775 | .name = "HDMI", | 850 | .name = "HDMI", |
776 | .id = MTK_AFE_MEMIF_HDMI, | 851 | .id = MTK_AFE_MEMIF_HDMI, |
852 | .suspend = mtk_afe_dai_suspend, | ||
853 | .resume = mtk_afe_dai_resume, | ||
777 | .playback = { | 854 | .playback = { |
778 | .stream_name = "HDMI", | 855 | .stream_name = "HDMI", |
779 | .channels_min = 2, | 856 | .channels_min = 2, |
@@ -820,10 +897,6 @@ static const struct snd_kcontrol_new mtk_afe_o10_mix[] = { | |||
820 | }; | 897 | }; |
821 | 898 | ||
822 | static const struct snd_soc_dapm_widget mtk_afe_pcm_widgets[] = { | 899 | static const struct snd_soc_dapm_widget mtk_afe_pcm_widgets[] = { |
823 | /* Backend DAIs */ | ||
824 | SND_SOC_DAPM_AIF_IN("I2S Capture", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
825 | SND_SOC_DAPM_AIF_OUT("I2S Playback", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
826 | |||
827 | /* inter-connections */ | 900 | /* inter-connections */ |
828 | SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0), | 901 | SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0), |
829 | SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0), | 902 | SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0), |
@@ -855,11 +928,6 @@ static const struct snd_soc_dapm_route mtk_afe_pcm_routes[] = { | |||
855 | { "O10", "I18 Switch", "I18" }, | 928 | { "O10", "I18 Switch", "I18" }, |
856 | }; | 929 | }; |
857 | 930 | ||
858 | static const struct snd_soc_dapm_widget mtk_afe_hdmi_widgets[] = { | ||
859 | /* Backend DAIs */ | ||
860 | SND_SOC_DAPM_AIF_OUT("HDMIO Playback", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
861 | }; | ||
862 | |||
863 | static const struct snd_soc_dapm_route mtk_afe_hdmi_routes[] = { | 931 | static const struct snd_soc_dapm_route mtk_afe_hdmi_routes[] = { |
864 | {"HDMIO Playback", NULL, "HDMI"}, | 932 | {"HDMIO Playback", NULL, "HDMI"}, |
865 | }; | 933 | }; |
@@ -874,8 +942,6 @@ static const struct snd_soc_component_driver mtk_afe_pcm_dai_component = { | |||
874 | 942 | ||
875 | static const struct snd_soc_component_driver mtk_afe_hdmi_dai_component = { | 943 | static const struct snd_soc_component_driver mtk_afe_hdmi_dai_component = { |
876 | .name = "mtk-afe-hdmi-dai", | 944 | .name = "mtk-afe-hdmi-dai", |
877 | .dapm_widgets = mtk_afe_hdmi_widgets, | ||
878 | .num_dapm_widgets = ARRAY_SIZE(mtk_afe_hdmi_widgets), | ||
879 | .dapm_routes = mtk_afe_hdmi_routes, | 945 | .dapm_routes = mtk_afe_hdmi_routes, |
880 | .num_dapm_routes = ARRAY_SIZE(mtk_afe_hdmi_routes), | 946 | .num_dapm_routes = ARRAY_SIZE(mtk_afe_hdmi_routes), |
881 | }; | 947 | }; |
@@ -1220,7 +1286,6 @@ static const struct dev_pm_ops mtk_afe_pm_ops = { | |||
1220 | static struct platform_driver mtk_afe_pcm_driver = { | 1286 | static struct platform_driver mtk_afe_pcm_driver = { |
1221 | .driver = { | 1287 | .driver = { |
1222 | .name = "mtk-afe-pcm", | 1288 | .name = "mtk-afe-pcm", |
1223 | .owner = THIS_MODULE, | ||
1224 | .of_match_table = mtk_afe_pcm_dt_match, | 1289 | .of_match_table = mtk_afe_pcm_dt_match, |
1225 | .pm = &mtk_afe_pm_ops, | 1290 | .pm = &mtk_afe_pm_ops, |
1226 | }, | 1291 | }, |
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c index 5ae5ca15b6d6..e09326158bc2 100644 --- a/sound/soc/nuc900/nuc900-pcm.c +++ b/sound/soc/nuc900/nuc900-pcm.c | |||
@@ -308,13 +308,7 @@ static struct snd_soc_platform_driver nuc900_soc_platform = { | |||
308 | 308 | ||
309 | static int nuc900_soc_platform_probe(struct platform_device *pdev) | 309 | static int nuc900_soc_platform_probe(struct platform_device *pdev) |
310 | { | 310 | { |
311 | return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform); | 311 | return devm_snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform); |
312 | } | ||
313 | |||
314 | static int nuc900_soc_platform_remove(struct platform_device *pdev) | ||
315 | { | ||
316 | snd_soc_unregister_platform(&pdev->dev); | ||
317 | return 0; | ||
318 | } | 312 | } |
319 | 313 | ||
320 | static struct platform_driver nuc900_pcm_driver = { | 314 | static struct platform_driver nuc900_pcm_driver = { |
@@ -323,7 +317,6 @@ static struct platform_driver nuc900_pcm_driver = { | |||
323 | }, | 317 | }, |
324 | 318 | ||
325 | .probe = nuc900_soc_platform_probe, | 319 | .probe = nuc900_soc_platform_probe, |
326 | .remove = nuc900_soc_platform_remove, | ||
327 | }; | 320 | }; |
328 | 321 | ||
329 | module_platform_driver(nuc900_pcm_driver); | 322 | module_platform_driver(nuc900_pcm_driver); |
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 68a125205375..c7563e230c7d 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c | |||
@@ -965,25 +965,15 @@ int omap_mcbsp_init(struct platform_device *pdev) | |||
965 | mcbsp->free = true; | 965 | mcbsp->free = true; |
966 | 966 | ||
967 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | 967 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
968 | if (!res) { | 968 | if (!res) |
969 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 969 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
970 | if (!res) { | 970 | |
971 | dev_err(mcbsp->dev, "invalid memory resource\n"); | 971 | mcbsp->io_base = devm_ioremap_resource(&pdev->dev, res); |
972 | return -ENOMEM; | 972 | if (IS_ERR(mcbsp->io_base)) |
973 | } | 973 | return PTR_ERR(mcbsp->io_base); |
974 | } | ||
975 | if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), | ||
976 | dev_name(&pdev->dev))) { | ||
977 | dev_err(mcbsp->dev, "memory region already claimed\n"); | ||
978 | return -ENODEV; | ||
979 | } | ||
980 | 974 | ||
981 | mcbsp->phys_base = res->start; | 975 | mcbsp->phys_base = res->start; |
982 | mcbsp->reg_cache_size = resource_size(res); | 976 | mcbsp->reg_cache_size = resource_size(res); |
983 | mcbsp->io_base = devm_ioremap(&pdev->dev, res->start, | ||
984 | resource_size(res)); | ||
985 | if (!mcbsp->io_base) | ||
986 | return -ENOMEM; | ||
987 | 977 | ||
988 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); | 978 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); |
989 | if (!res) | 979 | if (!res) |
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c index aeef25c0cb3d..584b2372339e 100644 --- a/sound/soc/omap/omap-hdmi-audio.c +++ b/sound/soc/omap/omap-hdmi-audio.c | |||
@@ -81,7 +81,15 @@ static int hdmi_dai_startup(struct snd_pcm_substream *substream, | |||
81 | ret = snd_pcm_hw_constraint_step(substream->runtime, 0, | 81 | ret = snd_pcm_hw_constraint_step(substream->runtime, 0, |
82 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); | 82 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); |
83 | if (ret < 0) { | 83 | if (ret < 0) { |
84 | dev_err(dai->dev, "could not apply constraint\n"); | 84 | dev_err(dai->dev, "Could not apply period constraint: %d\n", |
85 | ret); | ||
86 | return ret; | ||
87 | } | ||
88 | ret = snd_pcm_hw_constraint_step(substream->runtime, 0, | ||
89 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128); | ||
90 | if (ret < 0) { | ||
91 | dev_err(dai->dev, "Could not apply buffer constraint: %d\n", | ||
92 | ret); | ||
85 | return ret; | 93 | return ret; |
86 | } | 94 | } |
87 | 95 | ||
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 076bec606d78..732e749a1f8e 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c | |||
@@ -154,8 +154,7 @@ static const struct snd_soc_dapm_route omap3pandora_map[] = { | |||
154 | 154 | ||
155 | static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) | 155 | static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) |
156 | { | 156 | { |
157 | struct snd_soc_codec *codec = rtd->codec; | 157 | struct snd_soc_dapm_context *dapm = &rtd->card->dapm; |
158 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
159 | 158 | ||
160 | /* All TWL4030 output pins are floating */ | 159 | /* All TWL4030 output pins are floating */ |
161 | snd_soc_dapm_nc_pin(dapm, "EARPIECE"); | 160 | snd_soc_dapm_nc_pin(dapm, "EARPIECE"); |
@@ -174,8 +173,7 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) | |||
174 | 173 | ||
175 | static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) | 174 | static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) |
176 | { | 175 | { |
177 | struct snd_soc_codec *codec = rtd->codec; | 176 | struct snd_soc_dapm_context *dapm = &rtd->card->dapm; |
178 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
179 | 177 | ||
180 | /* Not comnnected */ | 178 | /* Not comnnected */ |
181 | snd_soc_dapm_nc_pin(dapm, "HSMIC"); | 179 | snd_soc_dapm_nc_pin(dapm, "HSMIC"); |
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 1eb45dcfb8e8..51e790d006f5 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c | |||
@@ -232,13 +232,7 @@ static int mmp_pcm_probe(struct platform_device *pdev) | |||
232 | mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].period_bytes_max = | 232 | mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].period_bytes_max = |
233 | pdata->period_max_capture; | 233 | pdata->period_max_capture; |
234 | } | 234 | } |
235 | return snd_soc_register_platform(&pdev->dev, &mmp_soc_platform); | 235 | return devm_snd_soc_register_platform(&pdev->dev, &mmp_soc_platform); |
236 | } | ||
237 | |||
238 | static int mmp_pcm_remove(struct platform_device *pdev) | ||
239 | { | ||
240 | snd_soc_unregister_platform(&pdev->dev); | ||
241 | return 0; | ||
242 | } | 236 | } |
243 | 237 | ||
244 | static struct platform_driver mmp_pcm_driver = { | 238 | static struct platform_driver mmp_pcm_driver = { |
@@ -247,7 +241,6 @@ static struct platform_driver mmp_pcm_driver = { | |||
247 | }, | 241 | }, |
248 | 242 | ||
249 | .probe = mmp_pcm_probe, | 243 | .probe = mmp_pcm_probe, |
250 | .remove = mmp_pcm_remove, | ||
251 | }; | 244 | }; |
252 | 245 | ||
253 | module_platform_driver(mmp_pcm_driver); | 246 | module_platform_driver(mmp_pcm_driver); |
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index fbe2e93d6edc..3da485ec1de7 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -813,14 +813,8 @@ static const struct of_device_id pxa_ssp_of_ids[] = { | |||
813 | 813 | ||
814 | static int asoc_ssp_probe(struct platform_device *pdev) | 814 | static int asoc_ssp_probe(struct platform_device *pdev) |
815 | { | 815 | { |
816 | return snd_soc_register_component(&pdev->dev, &pxa_ssp_component, | 816 | return devm_snd_soc_register_component(&pdev->dev, &pxa_ssp_component, |
817 | &pxa_ssp_dai, 1); | 817 | &pxa_ssp_dai, 1); |
818 | } | ||
819 | |||
820 | static int asoc_ssp_remove(struct platform_device *pdev) | ||
821 | { | ||
822 | snd_soc_unregister_component(&pdev->dev); | ||
823 | return 0; | ||
824 | } | 818 | } |
825 | 819 | ||
826 | static struct platform_driver asoc_ssp_driver = { | 820 | static struct platform_driver asoc_ssp_driver = { |
@@ -830,7 +824,6 @@ static struct platform_driver asoc_ssp_driver = { | |||
830 | }, | 824 | }, |
831 | 825 | ||
832 | .probe = asoc_ssp_probe, | 826 | .probe = asoc_ssp_probe, |
833 | .remove = asoc_ssp_remove, | ||
834 | }; | 827 | }; |
835 | 828 | ||
836 | module_platform_driver(asoc_ssp_driver); | 829 | module_platform_driver(asoc_ssp_driver); |
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index e68290c15328..6b4e40036910 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c | |||
@@ -367,19 +367,12 @@ static const struct snd_soc_component_driver pxa_i2s_component = { | |||
367 | 367 | ||
368 | static int pxa2xx_i2s_drv_probe(struct platform_device *pdev) | 368 | static int pxa2xx_i2s_drv_probe(struct platform_device *pdev) |
369 | { | 369 | { |
370 | return snd_soc_register_component(&pdev->dev, &pxa_i2s_component, | 370 | return devm_snd_soc_register_component(&pdev->dev, &pxa_i2s_component, |
371 | &pxa_i2s_dai, 1); | 371 | &pxa_i2s_dai, 1); |
372 | } | ||
373 | |||
374 | static int pxa2xx_i2s_drv_remove(struct platform_device *pdev) | ||
375 | { | ||
376 | snd_soc_unregister_component(&pdev->dev); | ||
377 | return 0; | ||
378 | } | 372 | } |
379 | 373 | ||
380 | static struct platform_driver pxa2xx_i2s_driver = { | 374 | static struct platform_driver pxa2xx_i2s_driver = { |
381 | .probe = pxa2xx_i2s_drv_probe, | 375 | .probe = pxa2xx_i2s_drv_probe, |
382 | .remove = pxa2xx_i2s_drv_remove, | ||
383 | 376 | ||
384 | .driver = { | 377 | .driver = { |
385 | .name = "pxa2xx-i2s", | 378 | .name = "pxa2xx-i2s", |
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index a51c9da66614..831ee37d2e3e 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c | |||
@@ -124,13 +124,7 @@ static struct snd_soc_platform_driver pxa2xx_soc_platform = { | |||
124 | 124 | ||
125 | static int pxa2xx_soc_platform_probe(struct platform_device *pdev) | 125 | static int pxa2xx_soc_platform_probe(struct platform_device *pdev) |
126 | { | 126 | { |
127 | return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform); | 127 | return devm_snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform); |
128 | } | ||
129 | |||
130 | static int pxa2xx_soc_platform_remove(struct platform_device *pdev) | ||
131 | { | ||
132 | snd_soc_unregister_platform(&pdev->dev); | ||
133 | return 0; | ||
134 | } | 128 | } |
135 | 129 | ||
136 | #ifdef CONFIG_OF | 130 | #ifdef CONFIG_OF |
@@ -147,7 +141,6 @@ static struct platform_driver pxa_pcm_driver = { | |||
147 | }, | 141 | }, |
148 | 142 | ||
149 | .probe = pxa2xx_soc_platform_probe, | 143 | .probe = pxa2xx_soc_platform_probe, |
150 | .remove = pxa2xx_soc_platform_remove, | ||
151 | }; | 144 | }; |
152 | 145 | ||
153 | module_platform_driver(pxa_pcm_driver); | 146 | module_platform_driver(pxa_pcm_driver); |
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 807fedfa1c76..3cc252e55468 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | config SND_SOC_QCOM | 1 | config SND_SOC_QCOM |
2 | tristate "ASoC support for QCOM platforms" | 2 | tristate "ASoC support for QCOM platforms" |
3 | depends on ARCH_QCOM || COMPILE_TEST | ||
3 | help | 4 | help |
4 | Say Y or M if you want to add support to use audio devices | 5 | Say Y or M if you want to add support to use audio devices |
5 | in Qualcomm Technologies SOC-based platforms. | 6 | in Qualcomm Technologies SOC-based platforms. |
@@ -14,19 +15,17 @@ config SND_SOC_LPASS_PLATFORM | |||
14 | 15 | ||
15 | config SND_SOC_LPASS_IPQ806X | 16 | config SND_SOC_LPASS_IPQ806X |
16 | tristate | 17 | tristate |
17 | depends on SND_SOC_QCOM | ||
18 | select SND_SOC_LPASS_CPU | 18 | select SND_SOC_LPASS_CPU |
19 | select SND_SOC_LPASS_PLATFORM | 19 | select SND_SOC_LPASS_PLATFORM |
20 | 20 | ||
21 | config SND_SOC_LPASS_APQ8016 | 21 | config SND_SOC_LPASS_APQ8016 |
22 | tristate | 22 | tristate |
23 | depends on SND_SOC_QCOM | ||
24 | select SND_SOC_LPASS_CPU | 23 | select SND_SOC_LPASS_CPU |
25 | select SND_SOC_LPASS_PLATFORM | 24 | select SND_SOC_LPASS_PLATFORM |
26 | 25 | ||
27 | config SND_SOC_STORM | 26 | config SND_SOC_STORM |
28 | tristate "ASoC I2S support for Storm boards" | 27 | tristate "ASoC I2S support for Storm boards" |
29 | depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) | 28 | depends on SND_SOC_QCOM |
30 | select SND_SOC_LPASS_IPQ806X | 29 | select SND_SOC_LPASS_IPQ806X |
31 | select SND_SOC_MAX98357A | 30 | select SND_SOC_MAX98357A |
32 | help | 31 | help |
@@ -35,7 +34,7 @@ config SND_SOC_STORM | |||
35 | 34 | ||
36 | config SND_SOC_APQ8016_SBC | 35 | config SND_SOC_APQ8016_SBC |
37 | tristate "SoC Audio support for APQ8016 SBC platforms" | 36 | tristate "SoC Audio support for APQ8016 SBC platforms" |
38 | depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) | 37 | depends on SND_SOC_QCOM |
39 | select SND_SOC_LPASS_APQ8016 | 38 | select SND_SOC_LPASS_APQ8016 |
40 | help | 39 | help |
41 | Support for Qualcomm Technologies LPASS audio block in | 40 | Support for Qualcomm Technologies LPASS audio block in |
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 23f3d59e6d09..97bc2023f08a 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c | |||
@@ -235,7 +235,7 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, | |||
235 | return ret; | 235 | return ret; |
236 | } | 236 | } |
237 | 237 | ||
238 | struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = { | 238 | const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = { |
239 | .set_sysclk = lpass_cpu_daiops_set_sysclk, | 239 | .set_sysclk = lpass_cpu_daiops_set_sysclk, |
240 | .startup = lpass_cpu_daiops_startup, | 240 | .startup = lpass_cpu_daiops_startup, |
241 | .shutdown = lpass_cpu_daiops_shutdown, | 241 | .shutdown = lpass_cpu_daiops_shutdown, |
diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c index 7356d3a766d6..7a4167952711 100644 --- a/sound/soc/qcom/lpass-ipq806x.c +++ b/sound/soc/qcom/lpass-ipq806x.c | |||
@@ -73,7 +73,7 @@ static int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) | |||
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | 75 | ||
76 | struct lpass_variant ipq806x_data = { | 76 | static struct lpass_variant ipq806x_data = { |
77 | .i2sctrl_reg_base = 0x0010, | 77 | .i2sctrl_reg_base = 0x0010, |
78 | .i2sctrl_reg_stride = 0x04, | 78 | .i2sctrl_reg_stride = 0x04, |
79 | .i2s_ports = 5, | 79 | .i2s_ports = 5, |
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index d6e86c119e74..0b63e2e5bcc9 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h | |||
@@ -93,6 +93,6 @@ int asoc_qcom_lpass_platform_register(struct platform_device *); | |||
93 | int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev); | 93 | int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev); |
94 | int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev); | 94 | int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev); |
95 | int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai); | 95 | int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai); |
96 | extern struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops; | 96 | extern const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops; |
97 | 97 | ||
98 | #endif /* __LPASS_H__ */ | 98 | #endif /* __LPASS_H__ */ |
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index e18182699d83..58bae8e2cf5f 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig | |||
@@ -14,3 +14,22 @@ config SND_SOC_ROCKCHIP_I2S | |||
14 | Say Y or M if you want to add support for I2S driver for | 14 | Say Y or M if you want to add support for I2S driver for |
15 | Rockchip I2S device. The device supports upto maximum of | 15 | Rockchip I2S device. The device supports upto maximum of |
16 | 8 channels each for play and record. | 16 | 8 channels each for play and record. |
17 | |||
18 | config SND_SOC_ROCKCHIP_MAX98090 | ||
19 | tristate "ASoC support for Rockchip boards using a MAX98090 codec" | ||
20 | depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB | ||
21 | select SND_SOC_ROCKCHIP_I2S | ||
22 | select SND_SOC_MAX98090 | ||
23 | select SND_SOC_TS3A227E | ||
24 | help | ||
25 | Say Y or M here if you want to add support for SoC audio on Rockchip | ||
26 | boards using the MAX98090 codec, such as Veyron. | ||
27 | |||
28 | config SND_SOC_ROCKCHIP_RT5645 | ||
29 | tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec" | ||
30 | depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB | ||
31 | select SND_SOC_ROCKCHIP_I2S | ||
32 | select SND_SOC_RT5645 | ||
33 | help | ||
34 | Say Y or M here if you want to add support for SoC audio on Rockchip | ||
35 | boards using the RT5645/RT5650 codec, such as Veyron. | ||
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile index b9219092b47f..1bc1dc3c729a 100644 --- a/sound/soc/rockchip/Makefile +++ b/sound/soc/rockchip/Makefile | |||
@@ -2,3 +2,9 @@ | |||
2 | snd-soc-i2s-objs := rockchip_i2s.o | 2 | snd-soc-i2s-objs := rockchip_i2s.o |
3 | 3 | ||
4 | obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-i2s.o | 4 | obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-i2s.o |
5 | |||
6 | snd-soc-rockchip-max98090-objs := rockchip_max98090.o | ||
7 | snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o | ||
8 | |||
9 | obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o | ||
10 | obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o | ||
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index acb5be53bfb4..b93610212e3d 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -483,16 +483,14 @@ static int rockchip_i2s_probe(struct platform_device *pdev) | |||
483 | goto err_suspend; | 483 | goto err_suspend; |
484 | } | 484 | } |
485 | 485 | ||
486 | ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | 486 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); |
487 | if (ret) { | 487 | if (ret) { |
488 | dev_err(&pdev->dev, "Could not register PCM\n"); | 488 | dev_err(&pdev->dev, "Could not register PCM\n"); |
489 | goto err_pcm_register; | 489 | return ret; |
490 | } | 490 | } |
491 | 491 | ||
492 | return 0; | 492 | return 0; |
493 | 493 | ||
494 | err_pcm_register: | ||
495 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
496 | err_suspend: | 494 | err_suspend: |
497 | if (!pm_runtime_status_suspended(&pdev->dev)) | 495 | if (!pm_runtime_status_suspended(&pdev->dev)) |
498 | i2s_runtime_suspend(&pdev->dev); | 496 | i2s_runtime_suspend(&pdev->dev); |
@@ -512,8 +510,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev) | |||
512 | 510 | ||
513 | clk_disable_unprepare(i2s->mclk); | 511 | clk_disable_unprepare(i2s->mclk); |
514 | clk_disable_unprepare(i2s->hclk); | 512 | clk_disable_unprepare(i2s->hclk); |
515 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
516 | snd_soc_unregister_component(&pdev->dev); | ||
517 | 513 | ||
518 | return 0; | 514 | return 0; |
519 | } | 515 | } |
diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c new file mode 100644 index 000000000000..26567b10393a --- /dev/null +++ b/sound/soc/rockchip/rockchip_max98090.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* | ||
2 | * Rockchip machine ASoC driver for boards using a MAX90809 CODEC. | ||
3 | * | ||
4 | * Copyright (c) 2014, ROCKCHIP CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/of_gpio.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/jack.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/pcm_params.h> | ||
29 | #include <sound/soc.h> | ||
30 | |||
31 | #include "rockchip_i2s.h" | ||
32 | #include "../codecs/ts3a227e.h" | ||
33 | |||
34 | #define DRV_NAME "rockchip-snd-max98090" | ||
35 | |||
36 | static struct snd_soc_jack headset_jack; | ||
37 | static struct snd_soc_jack_pin headset_jack_pins[] = { | ||
38 | { | ||
39 | .pin = "Headset Jack", | ||
40 | .mask = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | | ||
41 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
42 | SND_JACK_BTN_2 | SND_JACK_BTN_3, | ||
43 | }, | ||
44 | }; | ||
45 | |||
46 | static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { | ||
47 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
48 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
49 | SND_SOC_DAPM_MIC("Int Mic", NULL), | ||
50 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
51 | }; | ||
52 | |||
53 | static const struct snd_soc_dapm_route rk_audio_map[] = { | ||
54 | {"IN34", NULL, "Headset Mic"}, | ||
55 | {"IN34", NULL, "MICBIAS"}, | ||
56 | {"MICBIAS", NULL, "Headset Mic"}, | ||
57 | {"DMICL", NULL, "Int Mic"}, | ||
58 | {"Headphone", NULL, "HPL"}, | ||
59 | {"Headphone", NULL, "HPR"}, | ||
60 | {"Speaker", NULL, "SPKL"}, | ||
61 | {"Speaker", NULL, "SPKR"}, | ||
62 | }; | ||
63 | |||
64 | static const struct snd_kcontrol_new rk_mc_controls[] = { | ||
65 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
66 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
67 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
68 | SOC_DAPM_PIN_SWITCH("Speaker"), | ||
69 | }; | ||
70 | |||
71 | static int rk_aif1_hw_params(struct snd_pcm_substream *substream, | ||
72 | struct snd_pcm_hw_params *params) | ||
73 | { | ||
74 | int ret = 0; | ||
75 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
76 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
77 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
78 | int mclk; | ||
79 | |||
80 | switch (params_rate(params)) { | ||
81 | case 8000: | ||
82 | case 16000: | ||
83 | case 48000: | ||
84 | case 96000: | ||
85 | mclk = 12288000; | ||
86 | break; | ||
87 | case 44100: | ||
88 | mclk = 11289600; | ||
89 | break; | ||
90 | default: | ||
91 | return -EINVAL; | ||
92 | } | ||
93 | |||
94 | ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, | ||
95 | SND_SOC_CLOCK_OUT); | ||
96 | if (ret < 0) { | ||
97 | dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | ||
102 | SND_SOC_CLOCK_IN); | ||
103 | if (ret < 0) { | ||
104 | dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | static int rk_init(struct snd_soc_pcm_runtime *runtime) | ||
112 | { | ||
113 | /* Enable Headset and 4 Buttons Jack detection */ | ||
114 | return snd_soc_card_jack_new(runtime->card, "Headset Jack", | ||
115 | SND_JACK_HEADSET | | ||
116 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
117 | SND_JACK_BTN_2 | SND_JACK_BTN_3, | ||
118 | &headset_jack, | ||
119 | headset_jack_pins, | ||
120 | ARRAY_SIZE(headset_jack_pins)); | ||
121 | } | ||
122 | |||
123 | static int rk_98090_headset_init(struct snd_soc_component *component) | ||
124 | { | ||
125 | return ts3a227e_enable_jack_detect(component, &headset_jack); | ||
126 | } | ||
127 | |||
128 | static struct snd_soc_ops rk_aif1_ops = { | ||
129 | .hw_params = rk_aif1_hw_params, | ||
130 | }; | ||
131 | |||
132 | static struct snd_soc_aux_dev rk_98090_headset_dev = { | ||
133 | .name = "Headset Chip", | ||
134 | .init = rk_98090_headset_init, | ||
135 | }; | ||
136 | |||
137 | static struct snd_soc_dai_link rk_dailink = { | ||
138 | .name = "max98090", | ||
139 | .stream_name = "Audio", | ||
140 | .codec_dai_name = "HiFi", | ||
141 | .init = rk_init, | ||
142 | .ops = &rk_aif1_ops, | ||
143 | /* set max98090 as slave */ | ||
144 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
145 | SND_SOC_DAIFMT_CBS_CFS, | ||
146 | }; | ||
147 | |||
148 | static struct snd_soc_card snd_soc_card_rk = { | ||
149 | .name = "ROCKCHIP-I2S", | ||
150 | .owner = THIS_MODULE, | ||
151 | .dai_link = &rk_dailink, | ||
152 | .num_links = 1, | ||
153 | .aux_dev = &rk_98090_headset_dev, | ||
154 | .num_aux_devs = 1, | ||
155 | .dapm_widgets = rk_dapm_widgets, | ||
156 | .num_dapm_widgets = ARRAY_SIZE(rk_dapm_widgets), | ||
157 | .dapm_routes = rk_audio_map, | ||
158 | .num_dapm_routes = ARRAY_SIZE(rk_audio_map), | ||
159 | .controls = rk_mc_controls, | ||
160 | .num_controls = ARRAY_SIZE(rk_mc_controls), | ||
161 | }; | ||
162 | |||
163 | static int snd_rk_mc_probe(struct platform_device *pdev) | ||
164 | { | ||
165 | int ret = 0; | ||
166 | struct snd_soc_card *card = &snd_soc_card_rk; | ||
167 | struct device_node *np = pdev->dev.of_node; | ||
168 | |||
169 | /* register the soc card */ | ||
170 | card->dev = &pdev->dev; | ||
171 | |||
172 | rk_dailink.codec_of_node = of_parse_phandle(np, | ||
173 | "rockchip,audio-codec", 0); | ||
174 | if (!rk_dailink.codec_of_node) { | ||
175 | dev_err(&pdev->dev, | ||
176 | "Property 'rockchip,audio-codec' missing or invalid\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | rk_dailink.cpu_of_node = of_parse_phandle(np, | ||
181 | "rockchip,i2s-controller", 0); | ||
182 | if (!rk_dailink.cpu_of_node) { | ||
183 | dev_err(&pdev->dev, | ||
184 | "Property 'rockchip,i2s-controller' missing or invalid\n"); | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | rk_dailink.platform_of_node = rk_dailink.cpu_of_node; | ||
189 | |||
190 | rk_98090_headset_dev.codec_of_node = of_parse_phandle(np, | ||
191 | "rockchip,headset-codec", 0); | ||
192 | if (!rk_98090_headset_dev.codec_of_node) { | ||
193 | dev_err(&pdev->dev, | ||
194 | "Property 'rockchip,headset-codec' missing/invalid\n"); | ||
195 | return -EINVAL; | ||
196 | } | ||
197 | |||
198 | ret = snd_soc_of_parse_card_name(card, "rockchip,model"); | ||
199 | if (ret) { | ||
200 | dev_err(&pdev->dev, | ||
201 | "Soc parse card name failed %d\n", ret); | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | ret = devm_snd_soc_register_card(&pdev->dev, card); | ||
206 | if (ret) { | ||
207 | dev_err(&pdev->dev, | ||
208 | "Soc register card failed %d\n", ret); | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static const struct of_device_id rockchip_max98090_of_match[] = { | ||
216 | { .compatible = "rockchip,rockchip-audio-max98090", }, | ||
217 | {}, | ||
218 | }; | ||
219 | |||
220 | MODULE_DEVICE_TABLE(of, rockchip_max98090_of_match); | ||
221 | |||
222 | static struct platform_driver snd_rk_mc_driver = { | ||
223 | .probe = snd_rk_mc_probe, | ||
224 | .driver = { | ||
225 | .name = DRV_NAME, | ||
226 | .pm = &snd_soc_pm_ops, | ||
227 | .of_match_table = rockchip_max98090_of_match, | ||
228 | }, | ||
229 | }; | ||
230 | |||
231 | module_platform_driver(snd_rk_mc_driver); | ||
232 | |||
233 | MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>"); | ||
234 | MODULE_DESCRIPTION("Rockchip max98090 machine ASoC driver"); | ||
235 | MODULE_LICENSE("GPL v2"); | ||
236 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c new file mode 100644 index 000000000000..68c62e4c2316 --- /dev/null +++ b/sound/soc/rockchip/rockchip_rt5645.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * Rockchip machine ASoC driver for boards using a RT5645/RT5650 CODEC. | ||
3 | * | ||
4 | * Copyright (c) 2015, ROCKCHIP CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/of_gpio.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/jack.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/pcm_params.h> | ||
30 | #include <sound/soc.h> | ||
31 | #include "rockchip_i2s.h" | ||
32 | |||
33 | #define DRV_NAME "rockchip-snd-rt5645" | ||
34 | |||
35 | static struct snd_soc_jack headset_jack; | ||
36 | |||
37 | /* Jack detect via rt5645 driver. */ | ||
38 | extern int rt5645_set_jack_detect(struct snd_soc_codec *codec, | ||
39 | struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack, | ||
40 | struct snd_soc_jack *btn_jack); | ||
41 | |||
42 | static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { | ||
43 | SND_SOC_DAPM_HP("Headphones", NULL), | ||
44 | SND_SOC_DAPM_SPK("Speakers", NULL), | ||
45 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
46 | SND_SOC_DAPM_MIC("Int Mic", NULL), | ||
47 | }; | ||
48 | |||
49 | static const struct snd_soc_dapm_route rk_audio_map[] = { | ||
50 | /* Input Lines */ | ||
51 | {"DMIC L2", NULL, "Int Mic"}, | ||
52 | {"DMIC R2", NULL, "Int Mic"}, | ||
53 | {"RECMIXL", NULL, "Headset Mic"}, | ||
54 | {"RECMIXR", NULL, "Headset Mic"}, | ||
55 | |||
56 | /* Output Lines */ | ||
57 | {"Headphones", NULL, "HPOR"}, | ||
58 | {"Headphones", NULL, "HPOL"}, | ||
59 | {"Speakers", NULL, "SPOL"}, | ||
60 | {"Speakers", NULL, "SPOR"}, | ||
61 | }; | ||
62 | |||
63 | static const struct snd_kcontrol_new rk_mc_controls[] = { | ||
64 | SOC_DAPM_PIN_SWITCH("Headphones"), | ||
65 | SOC_DAPM_PIN_SWITCH("Speakers"), | ||
66 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
67 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
68 | }; | ||
69 | |||
70 | static int rk_aif1_hw_params(struct snd_pcm_substream *substream, | ||
71 | struct snd_pcm_hw_params *params) | ||
72 | { | ||
73 | int ret = 0; | ||
74 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
75 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
76 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
77 | int mclk; | ||
78 | |||
79 | switch (params_rate(params)) { | ||
80 | case 8000: | ||
81 | case 16000: | ||
82 | case 48000: | ||
83 | case 96000: | ||
84 | mclk = 12288000; | ||
85 | break; | ||
86 | case 44100: | ||
87 | mclk = 11289600; | ||
88 | break; | ||
89 | default: | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, | ||
94 | SND_SOC_CLOCK_OUT); | ||
95 | if (ret < 0) { | ||
96 | dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret); | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | ||
101 | SND_SOC_CLOCK_IN); | ||
102 | if (ret < 0) { | ||
103 | dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret); | ||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | static int rk_init(struct snd_soc_pcm_runtime *runtime) | ||
111 | { | ||
112 | struct snd_soc_card *card = runtime->card; | ||
113 | int ret; | ||
114 | |||
115 | /* Enable Headset and 4 Buttons Jack detection */ | ||
116 | ret = snd_soc_card_jack_new(card, "Headset Jack", | ||
117 | SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | | ||
118 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
119 | SND_JACK_BTN_2 | SND_JACK_BTN_3, | ||
120 | &headset_jack, NULL, 0); | ||
121 | if (ret) { | ||
122 | dev_err(card->dev, "New Headset Jack failed! (%d)\n", ret); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | return rt5645_set_jack_detect(runtime->codec, | ||
127 | &headset_jack, | ||
128 | &headset_jack, | ||
129 | &headset_jack); | ||
130 | } | ||
131 | |||
132 | static struct snd_soc_ops rk_aif1_ops = { | ||
133 | .hw_params = rk_aif1_hw_params, | ||
134 | }; | ||
135 | |||
136 | static struct snd_soc_dai_link rk_dailink = { | ||
137 | .name = "rt5645", | ||
138 | .stream_name = "rt5645 PCM", | ||
139 | .codec_dai_name = "rt5645-aif1", | ||
140 | .init = rk_init, | ||
141 | .ops = &rk_aif1_ops, | ||
142 | /* set rt5645 as slave */ | ||
143 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
144 | SND_SOC_DAIFMT_CBS_CFS, | ||
145 | }; | ||
146 | |||
147 | static struct snd_soc_card snd_soc_card_rk = { | ||
148 | .name = "I2S-RT5650", | ||
149 | .owner = THIS_MODULE, | ||
150 | .dai_link = &rk_dailink, | ||
151 | .num_links = 1, | ||
152 | .dapm_widgets = rk_dapm_widgets, | ||
153 | .num_dapm_widgets = ARRAY_SIZE(rk_dapm_widgets), | ||
154 | .dapm_routes = rk_audio_map, | ||
155 | .num_dapm_routes = ARRAY_SIZE(rk_audio_map), | ||
156 | .controls = rk_mc_controls, | ||
157 | .num_controls = ARRAY_SIZE(rk_mc_controls), | ||
158 | }; | ||
159 | |||
160 | static int snd_rk_mc_probe(struct platform_device *pdev) | ||
161 | { | ||
162 | int ret = 0; | ||
163 | struct snd_soc_card *card = &snd_soc_card_rk; | ||
164 | struct device_node *np = pdev->dev.of_node; | ||
165 | |||
166 | /* register the soc card */ | ||
167 | card->dev = &pdev->dev; | ||
168 | |||
169 | rk_dailink.codec_of_node = of_parse_phandle(np, | ||
170 | "rockchip,audio-codec", 0); | ||
171 | if (!rk_dailink.codec_of_node) { | ||
172 | dev_err(&pdev->dev, | ||
173 | "Property 'rockchip,audio-codec' missing or invalid\n"); | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | rk_dailink.cpu_of_node = of_parse_phandle(np, | ||
178 | "rockchip,i2s-controller", 0); | ||
179 | if (!rk_dailink.cpu_of_node) { | ||
180 | dev_err(&pdev->dev, | ||
181 | "Property 'rockchip,i2s-controller' missing or invalid\n"); | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | rk_dailink.platform_of_node = rk_dailink.cpu_of_node; | ||
186 | |||
187 | ret = snd_soc_of_parse_card_name(card, "rockchip,model"); | ||
188 | if (ret) { | ||
189 | dev_err(&pdev->dev, | ||
190 | "Soc parse card name failed %d\n", ret); | ||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | ret = devm_snd_soc_register_card(&pdev->dev, card); | ||
195 | if (ret) { | ||
196 | dev_err(&pdev->dev, | ||
197 | "Soc register card failed %d\n", ret); | ||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | static const struct of_device_id rockchip_rt5645_of_match[] = { | ||
205 | { .compatible = "rockchip,rockchip-audio-rt5645", }, | ||
206 | {}, | ||
207 | }; | ||
208 | |||
209 | MODULE_DEVICE_TABLE(of, rockchip_rt5645_of_match); | ||
210 | |||
211 | static struct platform_driver snd_rk_mc_driver = { | ||
212 | .probe = snd_rk_mc_probe, | ||
213 | .driver = { | ||
214 | .name = DRV_NAME, | ||
215 | .pm = &snd_soc_pm_ops, | ||
216 | .of_match_table = rockchip_rt5645_of_match, | ||
217 | }, | ||
218 | }; | ||
219 | |||
220 | module_platform_driver(snd_rk_mc_driver); | ||
221 | |||
222 | MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>"); | ||
223 | MODULE_DESCRIPTION("Rockchip rt5645 machine ASoC driver"); | ||
224 | MODULE_LICENSE("GPL v2"); | ||
225 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/samsung/arndale_rt5631.c b/sound/soc/samsung/arndale_rt5631.c index 8bf2e2c4bafb..ee1fda92f2f4 100644 --- a/sound/soc/samsung/arndale_rt5631.c +++ b/sound/soc/samsung/arndale_rt5631.c | |||
@@ -71,6 +71,7 @@ static struct snd_soc_dai_link arndale_rt5631_dai[] = { | |||
71 | 71 | ||
72 | static struct snd_soc_card arndale_rt5631 = { | 72 | static struct snd_soc_card arndale_rt5631 = { |
73 | .name = "Arndale RT5631", | 73 | .name = "Arndale RT5631", |
74 | .owner = THIS_MODULE, | ||
74 | .dai_link = arndale_rt5631_dai, | 75 | .dai_link = arndale_rt5631_dai, |
75 | .num_links = ARRAY_SIZE(arndale_rt5631_dai), | 76 | .num_links = ARRAY_SIZE(arndale_rt5631_dai), |
76 | }; | 77 | }; |
@@ -116,15 +117,6 @@ static int arndale_audio_probe(struct platform_device *pdev) | |||
116 | return ret; | 117 | return ret; |
117 | } | 118 | } |
118 | 119 | ||
119 | static int arndale_audio_remove(struct platform_device *pdev) | ||
120 | { | ||
121 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
122 | |||
123 | snd_soc_unregister_card(card); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static const struct of_device_id samsung_arndale_rt5631_of_match[] __maybe_unused = { | 120 | static const struct of_device_id samsung_arndale_rt5631_of_match[] __maybe_unused = { |
129 | { .compatible = "samsung,arndale-rt5631", }, | 121 | { .compatible = "samsung,arndale-rt5631", }, |
130 | { .compatible = "samsung,arndale-alc5631", }, | 122 | { .compatible = "samsung,arndale-alc5631", }, |
@@ -139,7 +131,6 @@ static struct platform_driver arndale_audio_driver = { | |||
139 | .of_match_table = of_match_ptr(samsung_arndale_rt5631_of_match), | 131 | .of_match_table = of_match_ptr(samsung_arndale_rt5631_of_match), |
140 | }, | 132 | }, |
141 | .probe = arndale_audio_probe, | 133 | .probe = arndale_audio_probe, |
142 | .remove = arndale_audio_remove, | ||
143 | }; | 134 | }; |
144 | 135 | ||
145 | module_platform_driver(arndale_audio_driver); | 136 | module_platform_driver(arndale_audio_driver); |
diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 7651dc924161..07ce2cfa4845 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c | |||
@@ -56,6 +56,7 @@ static int snow_late_probe(struct snd_soc_card *card) | |||
56 | 56 | ||
57 | static struct snd_soc_card snow_snd = { | 57 | static struct snd_soc_card snow_snd = { |
58 | .name = "Snow-I2S", | 58 | .name = "Snow-I2S", |
59 | .owner = THIS_MODULE, | ||
59 | .dai_link = snow_dai, | 60 | .dai_link = snow_dai, |
60 | .num_links = ARRAY_SIZE(snow_dai), | 61 | .num_links = ARRAY_SIZE(snow_dai), |
61 | 62 | ||
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index fd11404a3bc7..8fad4441c87d 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c | |||
@@ -327,13 +327,7 @@ static struct snd_soc_platform_driver sh7760_soc_platform = { | |||
327 | 327 | ||
328 | static int sh7760_soc_platform_probe(struct platform_device *pdev) | 328 | static int sh7760_soc_platform_probe(struct platform_device *pdev) |
329 | { | 329 | { |
330 | return snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform); | 330 | return devm_snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform); |
331 | } | ||
332 | |||
333 | static int sh7760_soc_platform_remove(struct platform_device *pdev) | ||
334 | { | ||
335 | snd_soc_unregister_platform(&pdev->dev); | ||
336 | return 0; | ||
337 | } | 331 | } |
338 | 332 | ||
339 | static struct platform_driver sh7760_pcm_driver = { | 333 | static struct platform_driver sh7760_pcm_driver = { |
@@ -342,7 +336,6 @@ static struct platform_driver sh7760_pcm_driver = { | |||
342 | }, | 336 | }, |
343 | 337 | ||
344 | .probe = sh7760_soc_platform_probe, | 338 | .probe = sh7760_soc_platform_probe, |
345 | .remove = sh7760_soc_platform_remove, | ||
346 | }; | 339 | }; |
347 | 340 | ||
348 | module_platform_driver(sh7760_pcm_driver); | 341 | module_platform_driver(sh7760_pcm_driver); |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 142c066eaee2..0215c78cbddf 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -1911,7 +1911,6 @@ MODULE_DEVICE_TABLE(of, fsi_of_match); | |||
1911 | 1911 | ||
1912 | static const struct platform_device_id fsi_id_table[] = { | 1912 | static const struct platform_device_id fsi_id_table[] = { |
1913 | { "sh_fsi", (kernel_ulong_t)&fsi1_core }, | 1913 | { "sh_fsi", (kernel_ulong_t)&fsi1_core }, |
1914 | { "sh_fsi2", (kernel_ulong_t)&fsi2_core }, | ||
1915 | {}, | 1914 | {}, |
1916 | }; | 1915 | }; |
1917 | MODULE_DEVICE_TABLE(platform, fsi_id_table); | 1916 | MODULE_DEVICE_TABLE(platform, fsi_id_table); |
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index f1b445173fba..8b258501aa35 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | snd-soc-rcar-objs := core.o gen.o dma.o src.o adg.o ssi.o dvc.o | 1 | snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o ctu.o mix.o dvc.o |
2 | obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o | 2 | obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o |
3 | 3 | ||
4 | snd-soc-rsrc-card-objs := rsrc-card.o | 4 | snd-soc-rsrc-card-objs := rsrc-card.o |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f1e5920654f6..f3feed5ce9b6 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -203,9 +203,9 @@ int rsnd_io_is_working(struct rsnd_dai_stream *io) | |||
203 | } | 203 | } |
204 | 204 | ||
205 | /* | 205 | /* |
206 | * settting function | 206 | * ADINR function |
207 | */ | 207 | */ |
208 | u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | 208 | u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io) |
209 | { | 209 | { |
210 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 210 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
211 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 211 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
@@ -227,6 +227,64 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | |||
227 | return adinr; | 227 | return adinr; |
228 | } | 228 | } |
229 | 229 | ||
230 | u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | ||
231 | { | ||
232 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
233 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
234 | struct device *dev = rsnd_priv_to_dev(priv); | ||
235 | u32 chan = runtime->channels; | ||
236 | |||
237 | switch (chan) { | ||
238 | case 1: | ||
239 | case 2: | ||
240 | case 4: | ||
241 | case 6: | ||
242 | case 8: | ||
243 | break; | ||
244 | default: | ||
245 | dev_warn(dev, "not supported channel\n"); | ||
246 | chan = 0; | ||
247 | break; | ||
248 | } | ||
249 | |||
250 | return chan; | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * DALIGN function | ||
255 | */ | ||
256 | u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | ||
257 | { | ||
258 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | ||
259 | struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); | ||
260 | struct rsnd_mod *target = src ? src : ssi; | ||
261 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
262 | u32 val = 0x76543210; | ||
263 | u32 mask = ~0; | ||
264 | |||
265 | mask <<= runtime->channels * 4; | ||
266 | val = val & mask; | ||
267 | |||
268 | switch (runtime->sample_bits) { | ||
269 | case 16: | ||
270 | val |= 0x67452301 & ~mask; | ||
271 | break; | ||
272 | case 32: | ||
273 | val |= 0x76543210 & ~mask; | ||
274 | break; | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * exchange channeles on SRC if possible, | ||
279 | * otherwise, R/L volume settings on DVC | ||
280 | * changes inverted channels | ||
281 | */ | ||
282 | if (mod == target) | ||
283 | return val; | ||
284 | else | ||
285 | return 0x76543210; | ||
286 | } | ||
287 | |||
230 | /* | 288 | /* |
231 | * rsnd_dai functions | 289 | * rsnd_dai functions |
232 | */ | 290 | */ |
@@ -242,9 +300,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | |||
242 | if (val == __rsnd_mod_call_##func) { \ | 300 | if (val == __rsnd_mod_call_##func) { \ |
243 | called = 1; \ | 301 | called = 1; \ |
244 | ret = (mod)->ops->func(mod, io, param); \ | 302 | ret = (mod)->ops->func(mod, io, param); \ |
245 | mod->status = (mod->status & ~mask) + \ | ||
246 | (add << __rsnd_mod_shift_##func); \ | ||
247 | } \ | 303 | } \ |
304 | mod->status = (mod->status & ~mask) + \ | ||
305 | (add << __rsnd_mod_shift_##func); \ | ||
248 | dev_dbg(dev, "%s[%d] 0x%08x %s\n", \ | 306 | dev_dbg(dev, "%s[%d] 0x%08x %s\n", \ |
249 | rsnd_mod_name(mod), rsnd_mod_id(mod), mod->status, \ | 307 | rsnd_mod_name(mod), rsnd_mod_id(mod), mod->status, \ |
250 | called ? #func : ""); \ | 308 | called ? #func : ""); \ |
@@ -274,21 +332,21 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | |||
274 | static int rsnd_dai_connect(struct rsnd_mod *mod, | 332 | static int rsnd_dai_connect(struct rsnd_mod *mod, |
275 | struct rsnd_dai_stream *io) | 333 | struct rsnd_dai_stream *io) |
276 | { | 334 | { |
335 | struct rsnd_priv *priv; | ||
336 | struct device *dev; | ||
337 | |||
277 | if (!mod) | 338 | if (!mod) |
278 | return -EIO; | 339 | return -EIO; |
279 | 340 | ||
280 | if (io->mod[mod->type]) { | 341 | priv = rsnd_mod_to_priv(mod); |
281 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 342 | dev = rsnd_priv_to_dev(priv); |
282 | struct device *dev = rsnd_priv_to_dev(priv); | ||
283 | |||
284 | dev_err(dev, "%s[%d] is not empty\n", | ||
285 | rsnd_mod_name(mod), | ||
286 | rsnd_mod_id(mod)); | ||
287 | return -EIO; | ||
288 | } | ||
289 | 343 | ||
290 | io->mod[mod->type] = mod; | 344 | io->mod[mod->type] = mod; |
291 | 345 | ||
346 | dev_dbg(dev, "%s[%d] is connected to io (%s)\n", | ||
347 | rsnd_mod_name(mod), rsnd_mod_id(mod), | ||
348 | rsnd_io_is_play(io) ? "Playback" : "Capture"); | ||
349 | |||
292 | return 0; | 350 | return 0; |
293 | } | 351 | } |
294 | 352 | ||
@@ -517,7 +575,7 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { | |||
517 | .set_fmt = rsnd_soc_dai_set_fmt, | 575 | .set_fmt = rsnd_soc_dai_set_fmt, |
518 | }; | 576 | }; |
519 | 577 | ||
520 | #define rsnd_path_parse(priv, io, type) \ | 578 | #define rsnd_path_add(priv, io, type) \ |
521 | ({ \ | 579 | ({ \ |
522 | struct rsnd_mod *mod; \ | 580 | struct rsnd_mod *mod; \ |
523 | int ret = 0; \ | 581 | int ret = 0; \ |
@@ -533,7 +591,7 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { | |||
533 | ret; \ | 591 | ret; \ |
534 | }) | 592 | }) |
535 | 593 | ||
536 | #define rsnd_path_break(priv, io, type) \ | 594 | #define rsnd_path_remove(priv, io, type) \ |
537 | { \ | 595 | { \ |
538 | struct rsnd_mod *mod; \ | 596 | struct rsnd_mod *mod; \ |
539 | int id = -1; \ | 597 | int id = -1; \ |
@@ -547,6 +605,79 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { | |||
547 | } \ | 605 | } \ |
548 | } | 606 | } |
549 | 607 | ||
608 | void rsnd_path_parse(struct rsnd_priv *priv, | ||
609 | struct rsnd_dai_stream *io) | ||
610 | { | ||
611 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); | ||
612 | struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); | ||
613 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | ||
614 | struct rsnd_mod *cmd; | ||
615 | struct device *dev = rsnd_priv_to_dev(priv); | ||
616 | u32 data; | ||
617 | |||
618 | /* Gen1 is not supported */ | ||
619 | if (rsnd_is_gen1(priv)) | ||
620 | return; | ||
621 | |||
622 | if (!mix && !dvc) | ||
623 | return; | ||
624 | |||
625 | if (mix) { | ||
626 | struct rsnd_dai *rdai; | ||
627 | int i; | ||
628 | u32 path[] = { | ||
629 | [0] = 0, | ||
630 | [1] = 1 << 0, | ||
631 | [2] = 0, | ||
632 | [3] = 0, | ||
633 | [4] = 0, | ||
634 | [5] = 1 << 8 | ||
635 | }; | ||
636 | |||
637 | /* | ||
638 | * it is assuming that integrater is well understanding about | ||
639 | * data path. Here doesn't check impossible connection, | ||
640 | * like src2 + src5 | ||
641 | */ | ||
642 | data = 0; | ||
643 | for_each_rsnd_dai(rdai, priv, i) { | ||
644 | io = &rdai->playback; | ||
645 | if (mix == rsnd_io_to_mod_mix(io)) | ||
646 | data |= path[rsnd_mod_id(src)]; | ||
647 | |||
648 | io = &rdai->capture; | ||
649 | if (mix == rsnd_io_to_mod_mix(io)) | ||
650 | data |= path[rsnd_mod_id(src)]; | ||
651 | } | ||
652 | |||
653 | /* | ||
654 | * We can't use ctu = rsnd_io_ctu() here. | ||
655 | * Since, ID of dvc/mix are 0 or 1 (= same as CMD number) | ||
656 | * but ctu IDs are 0 - 7 (= CTU00 - CTU13) | ||
657 | */ | ||
658 | cmd = mix; | ||
659 | } else { | ||
660 | u32 path[] = { | ||
661 | [0] = 0x30000, | ||
662 | [1] = 0x30001, | ||
663 | [2] = 0x40000, | ||
664 | [3] = 0x10000, | ||
665 | [4] = 0x20000, | ||
666 | [5] = 0x40100 | ||
667 | }; | ||
668 | |||
669 | data = path[rsnd_mod_id(src)]; | ||
670 | |||
671 | cmd = dvc; | ||
672 | } | ||
673 | |||
674 | dev_dbg(dev, "ctu/mix path = 0x%08x", data); | ||
675 | |||
676 | rsnd_mod_write(cmd, CMD_ROUTE_SLCT, data); | ||
677 | |||
678 | rsnd_mod_write(cmd, CMD_CTRL, 0x10); | ||
679 | } | ||
680 | |||
550 | static int rsnd_path_init(struct rsnd_priv *priv, | 681 | static int rsnd_path_init(struct rsnd_priv *priv, |
551 | struct rsnd_dai *rdai, | 682 | struct rsnd_dai *rdai, |
552 | struct rsnd_dai_stream *io) | 683 | struct rsnd_dai_stream *io) |
@@ -564,18 +695,28 @@ static int rsnd_path_init(struct rsnd_priv *priv, | |||
564 | * using fixed path. | 695 | * using fixed path. |
565 | */ | 696 | */ |
566 | 697 | ||
698 | /* SSI */ | ||
699 | ret = rsnd_path_add(priv, io, ssi); | ||
700 | if (ret < 0) | ||
701 | return ret; | ||
702 | |||
567 | /* SRC */ | 703 | /* SRC */ |
568 | ret = rsnd_path_parse(priv, io, src); | 704 | ret = rsnd_path_add(priv, io, src); |
569 | if (ret < 0) | 705 | if (ret < 0) |
570 | return ret; | 706 | return ret; |
571 | 707 | ||
572 | /* SSI */ | 708 | /* CTU */ |
573 | ret = rsnd_path_parse(priv, io, ssi); | 709 | ret = rsnd_path_add(priv, io, ctu); |
710 | if (ret < 0) | ||
711 | return ret; | ||
712 | |||
713 | /* MIX */ | ||
714 | ret = rsnd_path_add(priv, io, mix); | ||
574 | if (ret < 0) | 715 | if (ret < 0) |
575 | return ret; | 716 | return ret; |
576 | 717 | ||
577 | /* DVC */ | 718 | /* DVC */ |
578 | ret = rsnd_path_parse(priv, io, dvc); | 719 | ret = rsnd_path_add(priv, io, dvc); |
579 | if (ret < 0) | 720 | if (ret < 0) |
580 | return ret; | 721 | return ret; |
581 | 722 | ||
@@ -589,13 +730,15 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
589 | struct device_node *dai_node, *dai_np; | 730 | struct device_node *dai_node, *dai_np; |
590 | struct device_node *ssi_node, *ssi_np; | 731 | struct device_node *ssi_node, *ssi_np; |
591 | struct device_node *src_node, *src_np; | 732 | struct device_node *src_node, *src_np; |
733 | struct device_node *ctu_node, *ctu_np; | ||
734 | struct device_node *mix_node, *mix_np; | ||
592 | struct device_node *dvc_node, *dvc_np; | 735 | struct device_node *dvc_node, *dvc_np; |
593 | struct device_node *playback, *capture; | 736 | struct device_node *playback, *capture; |
594 | struct rsnd_dai_platform_info *dai_info; | 737 | struct rsnd_dai_platform_info *dai_info; |
595 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | 738 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); |
596 | struct device *dev = &pdev->dev; | 739 | struct device *dev = &pdev->dev; |
597 | int nr, i; | 740 | int nr, i; |
598 | int dai_i, ssi_i, src_i, dvc_i; | 741 | int dai_i, ssi_i, src_i, ctu_i, mix_i, dvc_i; |
599 | 742 | ||
600 | if (!of_data) | 743 | if (!of_data) |
601 | return; | 744 | return; |
@@ -621,6 +764,8 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
621 | 764 | ||
622 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); | 765 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); |
623 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); | 766 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); |
767 | ctu_node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu"); | ||
768 | mix_node = of_get_child_by_name(dev->of_node, "rcar_sound,mix"); | ||
624 | dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); | 769 | dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); |
625 | 770 | ||
626 | #define mod_parse(name) \ | 771 | #define mod_parse(name) \ |
@@ -657,6 +802,8 @@ if (name##_node) { \ | |||
657 | 802 | ||
658 | mod_parse(ssi); | 803 | mod_parse(ssi); |
659 | mod_parse(src); | 804 | mod_parse(src); |
805 | mod_parse(ctu); | ||
806 | mod_parse(mix); | ||
660 | mod_parse(dvc); | 807 | mod_parse(dvc); |
661 | 808 | ||
662 | of_node_put(playback); | 809 | of_node_put(playback); |
@@ -1033,8 +1180,8 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv, | |||
1033 | /* | 1180 | /* |
1034 | * remove SRC/DVC from DAI, | 1181 | * remove SRC/DVC from DAI, |
1035 | */ | 1182 | */ |
1036 | rsnd_path_break(priv, io, src); | 1183 | rsnd_path_remove(priv, io, src); |
1037 | rsnd_path_break(priv, io, dvc); | 1184 | rsnd_path_remove(priv, io, dvc); |
1038 | 1185 | ||
1039 | /* | 1186 | /* |
1040 | * fallback | 1187 | * fallback |
@@ -1069,6 +1216,8 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1069 | rsnd_dma_probe, | 1216 | rsnd_dma_probe, |
1070 | rsnd_ssi_probe, | 1217 | rsnd_ssi_probe, |
1071 | rsnd_src_probe, | 1218 | rsnd_src_probe, |
1219 | rsnd_ctu_probe, | ||
1220 | rsnd_mix_probe, | ||
1072 | rsnd_dvc_probe, | 1221 | rsnd_dvc_probe, |
1073 | rsnd_adg_probe, | 1222 | rsnd_adg_probe, |
1074 | rsnd_dai_probe, | 1223 | rsnd_dai_probe, |
@@ -1164,6 +1313,8 @@ static int rsnd_remove(struct platform_device *pdev) | |||
1164 | struct rsnd_priv *priv) = { | 1313 | struct rsnd_priv *priv) = { |
1165 | rsnd_ssi_remove, | 1314 | rsnd_ssi_remove, |
1166 | rsnd_src_remove, | 1315 | rsnd_src_remove, |
1316 | rsnd_ctu_remove, | ||
1317 | rsnd_mix_remove, | ||
1167 | rsnd_dvc_remove, | 1318 | rsnd_dvc_remove, |
1168 | }; | 1319 | }; |
1169 | int ret = 0, i; | 1320 | int ret = 0, i; |
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c new file mode 100644 index 000000000000..05498bba5874 --- /dev/null +++ b/sound/soc/sh/rcar/ctu.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * ctu.c | ||
3 | * | ||
4 | * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include "rsnd.h" | ||
11 | |||
12 | #define CTU_NAME_SIZE 16 | ||
13 | #define CTU_NAME "ctu" | ||
14 | |||
15 | struct rsnd_ctu { | ||
16 | struct rsnd_ctu_platform_info *info; /* rcar_snd.h */ | ||
17 | struct rsnd_mod mod; | ||
18 | }; | ||
19 | |||
20 | #define rsnd_ctu_nr(priv) ((priv)->ctu_nr) | ||
21 | #define for_each_rsnd_ctu(pos, priv, i) \ | ||
22 | for ((i) = 0; \ | ||
23 | ((i) < rsnd_ctu_nr(priv)) && \ | ||
24 | ((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \ | ||
25 | i++) | ||
26 | |||
27 | #define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1) | ||
28 | #define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0) | ||
29 | static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable) | ||
30 | { | ||
31 | rsnd_mod_write(mod, CTU_CTUIR, enable); | ||
32 | } | ||
33 | |||
34 | static int rsnd_ctu_init(struct rsnd_mod *mod, | ||
35 | struct rsnd_dai_stream *io, | ||
36 | struct rsnd_priv *priv) | ||
37 | { | ||
38 | rsnd_mod_hw_start(mod); | ||
39 | |||
40 | rsnd_ctu_initialize_lock(mod); | ||
41 | |||
42 | rsnd_mod_write(mod, CTU_ADINR, rsnd_get_adinr_chan(mod, io)); | ||
43 | |||
44 | rsnd_ctu_initialize_unlock(mod); | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int rsnd_ctu_quit(struct rsnd_mod *mod, | ||
50 | struct rsnd_dai_stream *io, | ||
51 | struct rsnd_priv *priv) | ||
52 | { | ||
53 | rsnd_mod_hw_stop(mod); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static struct rsnd_mod_ops rsnd_ctu_ops = { | ||
59 | .name = CTU_NAME, | ||
60 | .init = rsnd_ctu_init, | ||
61 | .quit = rsnd_ctu_quit, | ||
62 | }; | ||
63 | |||
64 | struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id) | ||
65 | { | ||
66 | if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv))) | ||
67 | id = 0; | ||
68 | |||
69 | return &((struct rsnd_ctu *)(priv->ctu) + id)->mod; | ||
70 | } | ||
71 | |||
72 | static void rsnd_of_parse_ctu(struct platform_device *pdev, | ||
73 | const struct rsnd_of_data *of_data, | ||
74 | struct rsnd_priv *priv) | ||
75 | { | ||
76 | struct device_node *node; | ||
77 | struct rsnd_ctu_platform_info *ctu_info; | ||
78 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
79 | struct device *dev = &pdev->dev; | ||
80 | int nr; | ||
81 | |||
82 | if (!of_data) | ||
83 | return; | ||
84 | |||
85 | node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu"); | ||
86 | if (!node) | ||
87 | return; | ||
88 | |||
89 | nr = of_get_child_count(node); | ||
90 | if (!nr) | ||
91 | goto rsnd_of_parse_ctu_end; | ||
92 | |||
93 | ctu_info = devm_kzalloc(dev, | ||
94 | sizeof(struct rsnd_ctu_platform_info) * nr, | ||
95 | GFP_KERNEL); | ||
96 | if (!ctu_info) { | ||
97 | dev_err(dev, "ctu info allocation error\n"); | ||
98 | goto rsnd_of_parse_ctu_end; | ||
99 | } | ||
100 | |||
101 | info->ctu_info = ctu_info; | ||
102 | info->ctu_info_nr = nr; | ||
103 | |||
104 | rsnd_of_parse_ctu_end: | ||
105 | of_node_put(node); | ||
106 | |||
107 | } | ||
108 | |||
109 | int rsnd_ctu_probe(struct platform_device *pdev, | ||
110 | const struct rsnd_of_data *of_data, | ||
111 | struct rsnd_priv *priv) | ||
112 | { | ||
113 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
114 | struct device *dev = rsnd_priv_to_dev(priv); | ||
115 | struct rsnd_ctu *ctu; | ||
116 | struct clk *clk; | ||
117 | char name[CTU_NAME_SIZE]; | ||
118 | int i, nr, ret; | ||
119 | |||
120 | /* This driver doesn't support Gen1 at this point */ | ||
121 | if (rsnd_is_gen1(priv)) { | ||
122 | dev_warn(dev, "CTU is not supported on Gen1\n"); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | |||
126 | rsnd_of_parse_ctu(pdev, of_data, priv); | ||
127 | |||
128 | nr = info->ctu_info_nr; | ||
129 | if (!nr) | ||
130 | return 0; | ||
131 | |||
132 | ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL); | ||
133 | if (!ctu) | ||
134 | return -ENOMEM; | ||
135 | |||
136 | priv->ctu_nr = nr; | ||
137 | priv->ctu = ctu; | ||
138 | |||
139 | for_each_rsnd_ctu(ctu, priv, i) { | ||
140 | /* | ||
141 | * CTU00, CTU01, CTU02, CTU03 => CTU0 | ||
142 | * CTU10, CTU11, CTU12, CTU13 => CTU1 | ||
143 | */ | ||
144 | snprintf(name, CTU_NAME_SIZE, "%s.%d", | ||
145 | CTU_NAME, i / 4); | ||
146 | |||
147 | clk = devm_clk_get(dev, name); | ||
148 | if (IS_ERR(clk)) | ||
149 | return PTR_ERR(clk); | ||
150 | |||
151 | ctu->info = &info->ctu_info[i]; | ||
152 | |||
153 | ret = rsnd_mod_init(priv, &ctu->mod, &rsnd_ctu_ops, | ||
154 | clk, RSND_MOD_CTU, i); | ||
155 | if (ret) | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | void rsnd_ctu_remove(struct platform_device *pdev, | ||
163 | struct rsnd_priv *priv) | ||
164 | { | ||
165 | struct rsnd_ctu *ctu; | ||
166 | int i; | ||
167 | |||
168 | for_each_rsnd_ctu(ctu, priv, i) { | ||
169 | rsnd_mod_quit(&ctu->mod); | ||
170 | } | ||
171 | } | ||
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index d306e298c63d..bfbb8a5e93bd 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c | |||
@@ -27,6 +27,15 @@ struct rsnd_dma_ctrl { | |||
27 | int dmapp_num; | 27 | int dmapp_num; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | struct rsnd_dma_ops { | ||
31 | char *name; | ||
32 | void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); | ||
33 | void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); | ||
34 | int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id, | ||
35 | struct rsnd_mod *mod_from, struct rsnd_mod *mod_to); | ||
36 | void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); | ||
37 | }; | ||
38 | |||
30 | #define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma) | 39 | #define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma) |
31 | 40 | ||
32 | /* | 41 | /* |
@@ -168,7 +177,7 @@ static int rsnd_dmaen_init(struct rsnd_dai_stream *io, | |||
168 | dma_cap_set(DMA_SLAVE, mask); | 177 | dma_cap_set(DMA_SLAVE, mask); |
169 | 178 | ||
170 | dmaen->chan = dma_request_channel(mask, shdma_chan_filter, | 179 | dmaen->chan = dma_request_channel(mask, shdma_chan_filter, |
171 | (void *)id); | 180 | (void *)(uintptr_t)id); |
172 | } | 181 | } |
173 | if (IS_ERR_OR_NULL(dmaen->chan)) { | 182 | if (IS_ERR_OR_NULL(dmaen->chan)) { |
174 | dmaen->chan = NULL; | 183 | dmaen->chan = NULL; |
@@ -182,7 +191,8 @@ static int rsnd_dmaen_init(struct rsnd_dai_stream *io, | |||
182 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | 191 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
183 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | 192 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
184 | 193 | ||
185 | dev_dbg(dev, "dma : %pad -> %pad\n", | 194 | dev_dbg(dev, "%s %pad -> %pad\n", |
195 | dma->ops->name, | ||
186 | &cfg.src_addr, &cfg.dst_addr); | 196 | &cfg.src_addr, &cfg.dst_addr); |
187 | 197 | ||
188 | ret = dmaengine_slave_config(dmaen->chan, &cfg); | 198 | ret = dmaengine_slave_config(dmaen->chan, &cfg); |
@@ -215,6 +225,7 @@ static void rsnd_dmaen_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma) | |||
215 | } | 225 | } |
216 | 226 | ||
217 | static struct rsnd_dma_ops rsnd_dmaen_ops = { | 227 | static struct rsnd_dma_ops rsnd_dmaen_ops = { |
228 | .name = "audmac", | ||
218 | .start = rsnd_dmaen_start, | 229 | .start = rsnd_dmaen_start, |
219 | .stop = rsnd_dmaen_stop, | 230 | .stop = rsnd_dmaen_stop, |
220 | .init = rsnd_dmaen_init, | 231 | .init = rsnd_dmaen_init, |
@@ -360,6 +371,7 @@ static int rsnd_dmapp_init(struct rsnd_dai_stream *io, | |||
360 | } | 371 | } |
361 | 372 | ||
362 | static struct rsnd_dma_ops rsnd_dmapp_ops = { | 373 | static struct rsnd_dma_ops rsnd_dmapp_ops = { |
374 | .name = "audmac-pp", | ||
363 | .start = rsnd_dmapp_start, | 375 | .start = rsnd_dmapp_start, |
364 | .stop = rsnd_dmapp_stop, | 376 | .stop = rsnd_dmapp_stop, |
365 | .init = rsnd_dmapp_init, | 377 | .init = rsnd_dmapp_init, |
@@ -414,7 +426,9 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, | |||
414 | phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); | 426 | phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); |
415 | int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); | 427 | int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); |
416 | int use_src = !!rsnd_io_to_mod_src(io); | 428 | int use_src = !!rsnd_io_to_mod_src(io); |
417 | int use_dvc = !!rsnd_io_to_mod_dvc(io); | 429 | int use_cmd = !!rsnd_io_to_mod_dvc(io) || |
430 | !!rsnd_io_to_mod_mix(io) || | ||
431 | !!rsnd_io_to_mod_ctu(io); | ||
418 | int id = rsnd_mod_id(mod); | 432 | int id = rsnd_mod_id(mod); |
419 | struct dma_addr { | 433 | struct dma_addr { |
420 | dma_addr_t out_addr; | 434 | dma_addr_t out_addr; |
@@ -452,7 +466,7 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, | |||
452 | }; | 466 | }; |
453 | 467 | ||
454 | /* it shouldn't happen */ | 468 | /* it shouldn't happen */ |
455 | if (use_dvc && !use_src) | 469 | if (use_cmd && !use_src) |
456 | dev_err(dev, "DVC is selected without SRC\n"); | 470 | dev_err(dev, "DVC is selected without SRC\n"); |
457 | 471 | ||
458 | /* use SSIU or SSI ? */ | 472 | /* use SSIU or SSI ? */ |
@@ -460,8 +474,8 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, | |||
460 | is_ssi++; | 474 | is_ssi++; |
461 | 475 | ||
462 | return (is_from) ? | 476 | return (is_from) ? |
463 | dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr : | 477 | dma_addrs[is_ssi][is_play][use_src + use_cmd].out_addr : |
464 | dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; | 478 | dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr; |
465 | } | 479 | } |
466 | 480 | ||
467 | static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io, | 481 | static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io, |
@@ -482,7 +496,7 @@ static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io, | |||
482 | return rsnd_gen2_dma_addr(io, mod, is_play, is_from); | 496 | return rsnd_gen2_dma_addr(io, mod, is_play, is_from); |
483 | } | 497 | } |
484 | 498 | ||
485 | #define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ | 499 | #define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */ |
486 | static void rsnd_dma_of_path(struct rsnd_dma *dma, | 500 | static void rsnd_dma_of_path(struct rsnd_dma *dma, |
487 | struct rsnd_dai_stream *io, | 501 | struct rsnd_dai_stream *io, |
488 | int is_play, | 502 | int is_play, |
@@ -492,55 +506,81 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma, | |||
492 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); | 506 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); |
493 | struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); | 507 | struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); |
494 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 508 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
509 | struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io); | ||
510 | struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); | ||
495 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); | 511 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); |
496 | struct rsnd_mod *mod[MOD_MAX]; | 512 | struct rsnd_mod *mod[MOD_MAX]; |
497 | int i, index; | 513 | struct rsnd_mod *mod_start, *mod_end; |
514 | struct rsnd_priv *priv = rsnd_mod_to_priv(this); | ||
515 | struct device *dev = rsnd_priv_to_dev(priv); | ||
516 | int nr, i; | ||
498 | 517 | ||
518 | if (!ssi) | ||
519 | return; | ||
499 | 520 | ||
500 | for (i = 0; i < MOD_MAX; i++) | 521 | nr = 0; |
522 | for (i = 0; i < MOD_MAX; i++) { | ||
501 | mod[i] = NULL; | 523 | mod[i] = NULL; |
524 | nr += !!rsnd_io_to_mod(io, i); | ||
525 | } | ||
502 | 526 | ||
503 | /* | 527 | /* |
504 | * in play case... | 528 | * [S] -*-> [E] |
529 | * [S] -*-> SRC -o-> [E] | ||
530 | * [S] -*-> SRC -> DVC -o-> [E] | ||
531 | * [S] -*-> SRC -> CTU -> MIX -> DVC -o-> [E] | ||
505 | * | 532 | * |
506 | * src -> dst | 533 | * playback [S] = mem |
534 | * [E] = SSI | ||
507 | * | 535 | * |
508 | * mem -> SSI | 536 | * capture [S] = SSI |
509 | * mem -> SRC -> SSI | 537 | * [E] = mem |
510 | * mem -> SRC -> DVC -> SSI | 538 | * |
539 | * -*-> Audio DMAC | ||
540 | * -o-> Audio DMAC peri peri | ||
511 | */ | 541 | */ |
512 | mod[0] = NULL; /* for "mem" */ | 542 | mod_start = (is_play) ? NULL : ssi; |
513 | index = 1; | 543 | mod_end = (is_play) ? ssi : NULL; |
514 | for (i = 1; i < MOD_MAX; i++) { | ||
515 | if (!src) { | ||
516 | mod[i] = ssi; | ||
517 | } else if (!dvc) { | ||
518 | mod[i] = src; | ||
519 | src = NULL; | ||
520 | } else { | ||
521 | if ((!is_play) && (this == src)) | ||
522 | this = dvc; | ||
523 | 544 | ||
524 | mod[i] = (is_play) ? src : dvc; | 545 | mod[0] = mod_start; |
525 | i++; | 546 | for (i = 1; i < nr; i++) { |
526 | mod[i] = (is_play) ? dvc : src; | 547 | if (src) { |
548 | mod[i] = src; | ||
527 | src = NULL; | 549 | src = NULL; |
550 | } else if (ctu) { | ||
551 | mod[i] = ctu; | ||
552 | ctu = NULL; | ||
553 | } else if (mix) { | ||
554 | mod[i] = mix; | ||
555 | mix = NULL; | ||
556 | } else if (dvc) { | ||
557 | mod[i] = dvc; | ||
528 | dvc = NULL; | 558 | dvc = NULL; |
529 | } | 559 | } |
530 | |||
531 | if (mod[i] == this) | ||
532 | index = i; | ||
533 | |||
534 | if (mod[i] == ssi) | ||
535 | break; | ||
536 | } | 560 | } |
561 | mod[i] = mod_end; | ||
537 | 562 | ||
538 | if (is_play) { | 563 | /* |
539 | *mod_from = mod[index - 1]; | 564 | * | SSI | SRC | |
540 | *mod_to = mod[index]; | 565 | * -------------+-----+-----+ |
566 | * is_play | o | * | | ||
567 | * !is_play | * | o | | ||
568 | */ | ||
569 | if ((this == ssi) == (is_play)) { | ||
570 | *mod_from = mod[nr - 1]; | ||
571 | *mod_to = mod[nr]; | ||
541 | } else { | 572 | } else { |
542 | *mod_from = mod[index]; | 573 | *mod_from = mod[0]; |
543 | *mod_to = mod[index - 1]; | 574 | *mod_to = mod[1]; |
575 | } | ||
576 | |||
577 | dev_dbg(dev, "module connection (this is %s[%d])\n", | ||
578 | rsnd_mod_name(this), rsnd_mod_id(this)); | ||
579 | for (i = 0; i <= nr; i++) { | ||
580 | dev_dbg(dev, " %s[%d]%s\n", | ||
581 | rsnd_mod_name(mod[i]), rsnd_mod_id(mod[i]), | ||
582 | (mod[i] == *mod_from) ? " from" : | ||
583 | (mod[i] == *mod_to) ? " to" : ""); | ||
544 | } | 584 | } |
545 | } | 585 | } |
546 | 586 | ||
@@ -568,10 +608,11 @@ void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma) | |||
568 | 608 | ||
569 | int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id) | 609 | int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id) |
570 | { | 610 | { |
571 | struct rsnd_mod *mod_from; | 611 | struct rsnd_mod *mod_from = NULL; |
572 | struct rsnd_mod *mod_to; | 612 | struct rsnd_mod *mod_to = NULL; |
573 | struct rsnd_priv *priv = rsnd_io_to_priv(io); | 613 | struct rsnd_priv *priv = rsnd_io_to_priv(io); |
574 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); | 614 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); |
615 | struct device *dev = rsnd_priv_to_dev(priv); | ||
575 | int is_play = rsnd_io_is_play(io); | 616 | int is_play = rsnd_io_is_play(io); |
576 | 617 | ||
577 | /* | 618 | /* |
@@ -598,6 +639,11 @@ int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id) | |||
598 | if (rsnd_is_gen1(priv)) | 639 | if (rsnd_is_gen1(priv)) |
599 | dma->ops = &rsnd_dmaen_ops; | 640 | dma->ops = &rsnd_dmaen_ops; |
600 | 641 | ||
642 | dev_dbg(dev, "%s %s[%d] -> %s[%d]\n", | ||
643 | dma->ops->name, | ||
644 | rsnd_mod_name(mod_from), rsnd_mod_id(mod_from), | ||
645 | rsnd_mod_name(mod_to), rsnd_mod_id(mod_to)); | ||
646 | |||
601 | return dma->ops->init(io, dma, id, mod_from, mod_to); | 647 | return dma->ops->init(io, dma, id, mod_from, mod_to); |
602 | } | 648 | } |
603 | 649 | ||
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 36fc020cbc18..57796387d482 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c | |||
@@ -24,6 +24,7 @@ struct rsnd_dvc { | |||
24 | struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */ | 24 | struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */ |
25 | }; | 25 | }; |
26 | 26 | ||
27 | #define rsnd_dvc_nr(priv) ((priv)->dvc_nr) | ||
27 | #define rsnd_dvc_of_node(priv) \ | 28 | #define rsnd_dvc_of_node(priv) \ |
28 | of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc") | 29 | of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc") |
29 | 30 | ||
@@ -63,6 +64,19 @@ static const char * const dvc_ramp_rate[] = { | |||
63 | "0.125 dB/8192 steps", /* 10111 */ | 64 | "0.125 dB/8192 steps", /* 10111 */ |
64 | }; | 65 | }; |
65 | 66 | ||
67 | static void rsnd_dvc_soft_reset(struct rsnd_mod *mod) | ||
68 | { | ||
69 | rsnd_mod_write(mod, DVC_SWRSR, 0); | ||
70 | rsnd_mod_write(mod, DVC_SWRSR, 1); | ||
71 | } | ||
72 | |||
73 | #define rsnd_dvc_initialize_lock(mod) __rsnd_dvc_initialize_lock(mod, 1) | ||
74 | #define rsnd_dvc_initialize_unlock(mod) __rsnd_dvc_initialize_lock(mod, 0) | ||
75 | static void __rsnd_dvc_initialize_lock(struct rsnd_mod *mod, u32 enable) | ||
76 | { | ||
77 | rsnd_mod_write(mod, DVC_DVUIR, enable); | ||
78 | } | ||
79 | |||
66 | static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io, | 80 | static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io, |
67 | struct rsnd_mod *mod) | 81 | struct rsnd_mod *mod) |
68 | { | 82 | { |
@@ -135,49 +149,24 @@ static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod, | |||
135 | return 0; | 149 | return 0; |
136 | } | 150 | } |
137 | 151 | ||
138 | static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | 152 | static int rsnd_dvc_init(struct rsnd_mod *mod, |
139 | struct rsnd_dai_stream *io, | 153 | struct rsnd_dai_stream *io, |
140 | struct rsnd_priv *priv) | 154 | struct rsnd_priv *priv) |
141 | { | 155 | { |
142 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); | 156 | rsnd_mod_hw_start(mod); |
143 | struct device *dev = rsnd_priv_to_dev(priv); | ||
144 | int dvc_id = rsnd_mod_id(dvc_mod); | ||
145 | int src_id = rsnd_mod_id(src_mod); | ||
146 | u32 route[] = { | ||
147 | [0] = 0x30000, | ||
148 | [1] = 0x30001, | ||
149 | [2] = 0x40000, | ||
150 | [3] = 0x10000, | ||
151 | [4] = 0x20000, | ||
152 | [5] = 0x40100 | ||
153 | }; | ||
154 | |||
155 | if (src_id >= ARRAY_SIZE(route)) { | ||
156 | dev_err(dev, "DVC%d isn't connected to SRC%d\n", dvc_id, src_id); | ||
157 | return -EINVAL; | ||
158 | } | ||
159 | |||
160 | rsnd_mod_hw_start(dvc_mod); | ||
161 | 157 | ||
162 | /* | 158 | rsnd_dvc_soft_reset(mod); |
163 | * fixme | ||
164 | * it doesn't support CTU/MIX | ||
165 | */ | ||
166 | rsnd_mod_write(dvc_mod, CMD_ROUTE_SLCT, route[src_id]); | ||
167 | 159 | ||
168 | rsnd_mod_write(dvc_mod, DVC_SWRSR, 0); | 160 | rsnd_dvc_initialize_lock(mod); |
169 | rsnd_mod_write(dvc_mod, DVC_SWRSR, 1); | ||
170 | 161 | ||
171 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 1); | 162 | rsnd_path_parse(priv, io); |
172 | 163 | ||
173 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod, io)); | 164 | rsnd_mod_write(mod, DVC_ADINR, rsnd_get_adinr_bit(mod, io)); |
174 | 165 | ||
175 | /* ch0/ch1 Volume */ | 166 | /* ch0/ch1 Volume */ |
176 | rsnd_dvc_volume_update(io, dvc_mod); | 167 | rsnd_dvc_volume_update(io, mod); |
177 | 168 | ||
178 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); | 169 | rsnd_adg_set_cmd_timsel_gen2(mod, io); |
179 | |||
180 | rsnd_adg_set_cmd_timsel_gen2(dvc_mod, io); | ||
181 | 170 | ||
182 | return 0; | 171 | return 0; |
183 | } | 172 | } |
@@ -195,6 +184,8 @@ static int rsnd_dvc_start(struct rsnd_mod *mod, | |||
195 | struct rsnd_dai_stream *io, | 184 | struct rsnd_dai_stream *io, |
196 | struct rsnd_priv *priv) | 185 | struct rsnd_priv *priv) |
197 | { | 186 | { |
187 | rsnd_dvc_initialize_unlock(mod); | ||
188 | |||
198 | rsnd_mod_write(mod, CMD_CTRL, 0x10); | 189 | rsnd_mod_write(mod, CMD_CTRL, 0x10); |
199 | 190 | ||
200 | return 0; | 191 | return 0; |
@@ -341,23 +332,21 @@ int rsnd_dvc_probe(struct platform_device *pdev, | |||
341 | char name[RSND_DVC_NAME_SIZE]; | 332 | char name[RSND_DVC_NAME_SIZE]; |
342 | int i, nr, ret; | 333 | int i, nr, ret; |
343 | 334 | ||
344 | rsnd_of_parse_dvc(pdev, of_data, priv); | ||
345 | |||
346 | nr = info->dvc_info_nr; | ||
347 | if (!nr) | ||
348 | return 0; | ||
349 | |||
350 | /* This driver doesn't support Gen1 at this point */ | 335 | /* This driver doesn't support Gen1 at this point */ |
351 | if (rsnd_is_gen1(priv)) { | 336 | if (rsnd_is_gen1(priv)) { |
352 | dev_warn(dev, "CMD is not supported on Gen1\n"); | 337 | dev_warn(dev, "CMD is not supported on Gen1\n"); |
353 | return -EINVAL; | 338 | return -EINVAL; |
354 | } | 339 | } |
355 | 340 | ||
341 | rsnd_of_parse_dvc(pdev, of_data, priv); | ||
342 | |||
343 | nr = info->dvc_info_nr; | ||
344 | if (!nr) | ||
345 | return 0; | ||
346 | |||
356 | dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL); | 347 | dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL); |
357 | if (!dvc) { | 348 | if (!dvc) |
358 | dev_err(dev, "CMD allocate failed\n"); | ||
359 | return -ENOMEM; | 349 | return -ENOMEM; |
360 | } | ||
361 | 350 | ||
362 | priv->dvc_nr = nr; | 351 | priv->dvc_nr = nr; |
363 | priv->dvc = dvc; | 352 | priv->dvc = dvc; |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 8c7dc51b1c4f..f04d17bc6e3d 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -103,6 +103,22 @@ void rsnd_write(struct rsnd_priv *priv, | |||
103 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); | 103 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); |
104 | } | 104 | } |
105 | 105 | ||
106 | void rsnd_force_write(struct rsnd_priv *priv, | ||
107 | struct rsnd_mod *mod, | ||
108 | enum rsnd_reg reg, u32 data) | ||
109 | { | ||
110 | struct device *dev = rsnd_priv_to_dev(priv); | ||
111 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
112 | |||
113 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | ||
114 | return; | ||
115 | |||
116 | dev_dbg(dev, "w %s[%d] - %4d : %08x\n", | ||
117 | rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data); | ||
118 | |||
119 | regmap_fields_force_write(gen->regs[reg], rsnd_mod_id(mod), data); | ||
120 | } | ||
121 | |||
106 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | 122 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, |
107 | enum rsnd_reg reg, u32 mask, u32 data) | 123 | enum rsnd_reg reg, u32 mask, u32 data) |
108 | { | 124 | { |
@@ -200,12 +216,13 @@ static int rsnd_gen2_probe(struct platform_device *pdev, | |||
200 | /* FIXME: it needs SSI_MODE2/3 in the future */ | 216 | /* FIXME: it needs SSI_MODE2/3 in the future */ |
201 | RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), | 217 | RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), |
202 | RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80), | 218 | RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80), |
203 | RSND_GEN_M_REG(BUSIF_DALIGN, 0x8, 0x80), | 219 | RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8, 0x80), |
204 | RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), | 220 | RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), |
205 | RSND_GEN_M_REG(INT_ENABLE, 0x18, 0x80), | 221 | RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80), |
206 | }; | 222 | }; |
207 | struct rsnd_regmap_field_conf conf_scu[] = { | 223 | struct rsnd_regmap_field_conf conf_scu[] = { |
208 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), | 224 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), |
225 | RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20), | ||
209 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), | 226 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), |
210 | RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), | 227 | RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), |
211 | RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), | 228 | RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), |
@@ -223,6 +240,18 @@ static int rsnd_gen2_probe(struct platform_device *pdev, | |||
223 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), | 240 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), |
224 | RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), | 241 | RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), |
225 | RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), | 242 | RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), |
243 | RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100), | ||
244 | RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100), | ||
245 | RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40), | ||
246 | RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40), | ||
247 | RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40), | ||
248 | RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40), | ||
249 | RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40), | ||
250 | RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40), | ||
251 | RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40), | ||
252 | RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40), | ||
253 | RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40), | ||
254 | RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40), | ||
226 | RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), | 255 | RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), |
227 | RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), | 256 | RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), |
228 | RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), | 257 | RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), |
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c new file mode 100644 index 000000000000..0d5c102db6f5 --- /dev/null +++ b/sound/soc/sh/rcar/mix.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* | ||
2 | * mix.c | ||
3 | * | ||
4 | * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include "rsnd.h" | ||
11 | |||
12 | #define MIX_NAME_SIZE 16 | ||
13 | #define MIX_NAME "mix" | ||
14 | |||
15 | struct rsnd_mix { | ||
16 | struct rsnd_mix_platform_info *info; /* rcar_snd.h */ | ||
17 | struct rsnd_mod mod; | ||
18 | }; | ||
19 | |||
20 | #define rsnd_mix_nr(priv) ((priv)->mix_nr) | ||
21 | #define for_each_rsnd_mix(pos, priv, i) \ | ||
22 | for ((i) = 0; \ | ||
23 | ((i) < rsnd_mix_nr(priv)) && \ | ||
24 | ((pos) = (struct rsnd_mix *)(priv)->mix + i); \ | ||
25 | i++) | ||
26 | |||
27 | |||
28 | static void rsnd_mix_soft_reset(struct rsnd_mod *mod) | ||
29 | { | ||
30 | rsnd_mod_write(mod, MIX_SWRSR, 0); | ||
31 | rsnd_mod_write(mod, MIX_SWRSR, 1); | ||
32 | } | ||
33 | |||
34 | #define rsnd_mix_initialize_lock(mod) __rsnd_mix_initialize_lock(mod, 1) | ||
35 | #define rsnd_mix_initialize_unlock(mod) __rsnd_mix_initialize_lock(mod, 0) | ||
36 | static void __rsnd_mix_initialize_lock(struct rsnd_mod *mod, u32 enable) | ||
37 | { | ||
38 | rsnd_mod_write(mod, MIX_MIXIR, enable); | ||
39 | } | ||
40 | |||
41 | static void rsnd_mix_volume_update(struct rsnd_dai_stream *io, | ||
42 | struct rsnd_mod *mod) | ||
43 | { | ||
44 | |||
45 | /* Disable MIX dB setting */ | ||
46 | rsnd_mod_write(mod, MIX_MDBER, 0); | ||
47 | |||
48 | rsnd_mod_write(mod, MIX_MDBAR, 0); | ||
49 | rsnd_mod_write(mod, MIX_MDBBR, 0); | ||
50 | rsnd_mod_write(mod, MIX_MDBCR, 0); | ||
51 | rsnd_mod_write(mod, MIX_MDBDR, 0); | ||
52 | |||
53 | /* Enable MIX dB setting */ | ||
54 | rsnd_mod_write(mod, MIX_MDBER, 1); | ||
55 | } | ||
56 | |||
57 | static int rsnd_mix_init(struct rsnd_mod *mod, | ||
58 | struct rsnd_dai_stream *io, | ||
59 | struct rsnd_priv *priv) | ||
60 | { | ||
61 | rsnd_mod_hw_start(mod); | ||
62 | |||
63 | rsnd_mix_soft_reset(mod); | ||
64 | |||
65 | rsnd_mix_initialize_lock(mod); | ||
66 | |||
67 | rsnd_mod_write(mod, MIX_ADINR, rsnd_get_adinr_chan(mod, io)); | ||
68 | |||
69 | rsnd_path_parse(priv, io); | ||
70 | |||
71 | /* volume step */ | ||
72 | rsnd_mod_write(mod, MIX_MIXMR, 0); | ||
73 | rsnd_mod_write(mod, MIX_MVPDR, 0); | ||
74 | |||
75 | rsnd_mix_volume_update(io, mod); | ||
76 | |||
77 | rsnd_mix_initialize_unlock(mod); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int rsnd_mix_quit(struct rsnd_mod *mod, | ||
83 | struct rsnd_dai_stream *io, | ||
84 | struct rsnd_priv *priv) | ||
85 | { | ||
86 | rsnd_mod_hw_stop(mod); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static struct rsnd_mod_ops rsnd_mix_ops = { | ||
92 | .name = MIX_NAME, | ||
93 | .init = rsnd_mix_init, | ||
94 | .quit = rsnd_mix_quit, | ||
95 | }; | ||
96 | |||
97 | struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id) | ||
98 | { | ||
99 | if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv))) | ||
100 | id = 0; | ||
101 | |||
102 | return &((struct rsnd_mix *)(priv->mix) + id)->mod; | ||
103 | } | ||
104 | |||
105 | static void rsnd_of_parse_mix(struct platform_device *pdev, | ||
106 | const struct rsnd_of_data *of_data, | ||
107 | struct rsnd_priv *priv) | ||
108 | { | ||
109 | struct device_node *node; | ||
110 | struct rsnd_mix_platform_info *mix_info; | ||
111 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
112 | struct device *dev = &pdev->dev; | ||
113 | int nr; | ||
114 | |||
115 | if (!of_data) | ||
116 | return; | ||
117 | |||
118 | node = of_get_child_by_name(dev->of_node, "rcar_sound,mix"); | ||
119 | if (!node) | ||
120 | return; | ||
121 | |||
122 | nr = of_get_child_count(node); | ||
123 | if (!nr) | ||
124 | goto rsnd_of_parse_mix_end; | ||
125 | |||
126 | mix_info = devm_kzalloc(dev, | ||
127 | sizeof(struct rsnd_mix_platform_info) * nr, | ||
128 | GFP_KERNEL); | ||
129 | if (!mix_info) { | ||
130 | dev_err(dev, "mix info allocation error\n"); | ||
131 | goto rsnd_of_parse_mix_end; | ||
132 | } | ||
133 | |||
134 | info->mix_info = mix_info; | ||
135 | info->mix_info_nr = nr; | ||
136 | |||
137 | rsnd_of_parse_mix_end: | ||
138 | of_node_put(node); | ||
139 | |||
140 | } | ||
141 | |||
142 | int rsnd_mix_probe(struct platform_device *pdev, | ||
143 | const struct rsnd_of_data *of_data, | ||
144 | struct rsnd_priv *priv) | ||
145 | { | ||
146 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
147 | struct device *dev = rsnd_priv_to_dev(priv); | ||
148 | struct rsnd_mix *mix; | ||
149 | struct clk *clk; | ||
150 | char name[MIX_NAME_SIZE]; | ||
151 | int i, nr, ret; | ||
152 | |||
153 | /* This driver doesn't support Gen1 at this point */ | ||
154 | if (rsnd_is_gen1(priv)) { | ||
155 | dev_warn(dev, "MIX is not supported on Gen1\n"); | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | |||
159 | rsnd_of_parse_mix(pdev, of_data, priv); | ||
160 | |||
161 | nr = info->mix_info_nr; | ||
162 | if (!nr) | ||
163 | return 0; | ||
164 | |||
165 | mix = devm_kzalloc(dev, sizeof(*mix) * nr, GFP_KERNEL); | ||
166 | if (!mix) | ||
167 | return -ENOMEM; | ||
168 | |||
169 | priv->mix_nr = nr; | ||
170 | priv->mix = mix; | ||
171 | |||
172 | for_each_rsnd_mix(mix, priv, i) { | ||
173 | snprintf(name, MIX_NAME_SIZE, "%s.%d", | ||
174 | MIX_NAME, i); | ||
175 | |||
176 | clk = devm_clk_get(dev, name); | ||
177 | if (IS_ERR(clk)) | ||
178 | return PTR_ERR(clk); | ||
179 | |||
180 | mix->info = &info->mix_info[i]; | ||
181 | |||
182 | ret = rsnd_mod_init(priv, &mix->mod, &rsnd_mix_ops, | ||
183 | clk, RSND_MOD_MIX, i); | ||
184 | if (ret) | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | void rsnd_mix_remove(struct platform_device *pdev, | ||
192 | struct rsnd_priv *priv) | ||
193 | { | ||
194 | struct rsnd_mix *mix; | ||
195 | int i; | ||
196 | |||
197 | for_each_rsnd_mix(mix, priv, i) { | ||
198 | rsnd_mod_quit(&mix->mod); | ||
199 | } | ||
200 | } | ||
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 09fcc54a8ee0..7a0e52b4640a 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -47,6 +47,18 @@ enum rsnd_reg { | |||
47 | RSND_REG_SCU_SYS_STATUS0, | 47 | RSND_REG_SCU_SYS_STATUS0, |
48 | RSND_REG_SCU_SYS_INT_EN0, | 48 | RSND_REG_SCU_SYS_INT_EN0, |
49 | RSND_REG_CMD_ROUTE_SLCT, | 49 | RSND_REG_CMD_ROUTE_SLCT, |
50 | RSND_REG_CTU_CTUIR, | ||
51 | RSND_REG_CTU_ADINR, | ||
52 | RSND_REG_MIX_SWRSR, | ||
53 | RSND_REG_MIX_MIXIR, | ||
54 | RSND_REG_MIX_ADINR, | ||
55 | RSND_REG_MIX_MIXMR, | ||
56 | RSND_REG_MIX_MVPDR, | ||
57 | RSND_REG_MIX_MDBAR, | ||
58 | RSND_REG_MIX_MDBBR, | ||
59 | RSND_REG_MIX_MDBCR, | ||
60 | RSND_REG_MIX_MDBDR, | ||
61 | RSND_REG_MIX_MDBER, | ||
50 | RSND_REG_DVC_SWRSR, | 62 | RSND_REG_DVC_SWRSR, |
51 | RSND_REG_DVC_DVUIR, | 63 | RSND_REG_DVC_DVUIR, |
52 | RSND_REG_DVC_ADINR, | 64 | RSND_REG_DVC_ADINR, |
@@ -99,6 +111,7 @@ enum rsnd_reg { | |||
99 | RSND_REG_SHARE26, | 111 | RSND_REG_SHARE26, |
100 | RSND_REG_SHARE27, | 112 | RSND_REG_SHARE27, |
101 | RSND_REG_SHARE28, | 113 | RSND_REG_SHARE28, |
114 | RSND_REG_SHARE29, | ||
102 | 115 | ||
103 | RSND_REG_MAX, | 116 | RSND_REG_MAX, |
104 | }; | 117 | }; |
@@ -119,7 +132,7 @@ enum rsnd_reg { | |||
119 | #define RSND_REG_SSI_CTRL RSND_REG_SHARE02 | 132 | #define RSND_REG_SSI_CTRL RSND_REG_SHARE02 |
120 | #define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03 | 133 | #define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03 |
121 | #define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04 | 134 | #define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04 |
122 | #define RSND_REG_INT_ENABLE RSND_REG_SHARE05 | 135 | #define RSND_REG_SSI_INT_ENABLE RSND_REG_SHARE05 |
123 | #define RSND_REG_SRC_BSDSR RSND_REG_SHARE06 | 136 | #define RSND_REG_SRC_BSDSR RSND_REG_SHARE06 |
124 | #define RSND_REG_SRC_BSISR RSND_REG_SHARE07 | 137 | #define RSND_REG_SRC_BSISR RSND_REG_SHARE07 |
125 | #define RSND_REG_DIV_EN RSND_REG_SHARE08 | 138 | #define RSND_REG_DIV_EN RSND_REG_SHARE08 |
@@ -136,13 +149,14 @@ enum rsnd_reg { | |||
136 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 | 149 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 |
137 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 | 150 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 |
138 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 | 151 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 |
139 | #define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22 | 152 | #define RSND_REG_SSI_BUSIF_DALIGN RSND_REG_SHARE22 |
140 | #define RSND_REG_DVC_VRCTR RSND_REG_SHARE23 | 153 | #define RSND_REG_DVC_VRCTR RSND_REG_SHARE23 |
141 | #define RSND_REG_DVC_VRPDR RSND_REG_SHARE24 | 154 | #define RSND_REG_DVC_VRPDR RSND_REG_SHARE24 |
142 | #define RSND_REG_DVC_VRDBR RSND_REG_SHARE25 | 155 | #define RSND_REG_DVC_VRDBR RSND_REG_SHARE25 |
143 | #define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26 | 156 | #define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26 |
144 | #define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27 | 157 | #define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27 |
145 | #define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28 | 158 | #define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28 |
159 | #define RSND_REG_SRC_BUSIF_DALIGN RSND_REG_SHARE29 | ||
146 | 160 | ||
147 | struct rsnd_of_data; | 161 | struct rsnd_of_data; |
148 | struct rsnd_priv; | 162 | struct rsnd_priv; |
@@ -157,27 +171,28 @@ struct rsnd_dai_stream; | |||
157 | rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r) | 171 | rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r) |
158 | #define rsnd_mod_write(m, r, d) \ | 172 | #define rsnd_mod_write(m, r, d) \ |
159 | rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d) | 173 | rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d) |
174 | #define rsnd_mod_force_write(m, r, d) \ | ||
175 | rsnd_force_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d) | ||
160 | #define rsnd_mod_bset(m, r, s, d) \ | 176 | #define rsnd_mod_bset(m, r, s, d) \ |
161 | rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d) | 177 | rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d) |
162 | 178 | ||
163 | u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); | 179 | u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); |
164 | void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod, | 180 | void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod, |
165 | enum rsnd_reg reg, u32 data); | 181 | enum rsnd_reg reg, u32 data); |
182 | void rsnd_force_write(struct rsnd_priv *priv, struct rsnd_mod *mod, | ||
183 | enum rsnd_reg reg, u32 data); | ||
166 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, | 184 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, |
167 | u32 mask, u32 data); | 185 | u32 mask, u32 data); |
168 | u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io); | 186 | u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io); |
187 | u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io); | ||
188 | u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io); | ||
189 | void rsnd_path_parse(struct rsnd_priv *priv, | ||
190 | struct rsnd_dai_stream *io); | ||
169 | 191 | ||
170 | /* | 192 | /* |
171 | * R-Car DMA | 193 | * R-Car DMA |
172 | */ | 194 | */ |
173 | struct rsnd_dma; | 195 | struct rsnd_dma; |
174 | struct rsnd_dma_ops { | ||
175 | void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); | ||
176 | void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); | ||
177 | int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id, | ||
178 | struct rsnd_mod *mod_from, struct rsnd_mod *mod_to); | ||
179 | void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); | ||
180 | }; | ||
181 | 196 | ||
182 | struct rsnd_dmaen { | 197 | struct rsnd_dmaen { |
183 | struct dma_chan *chan; | 198 | struct dma_chan *chan; |
@@ -217,6 +232,8 @@ struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, | |||
217 | */ | 232 | */ |
218 | enum rsnd_mod_type { | 233 | enum rsnd_mod_type { |
219 | RSND_MOD_DVC = 0, | 234 | RSND_MOD_DVC = 0, |
235 | RSND_MOD_MIX, | ||
236 | RSND_MOD_CTU, | ||
220 | RSND_MOD_SRC, | 237 | RSND_MOD_SRC, |
221 | RSND_MOD_SSI, | 238 | RSND_MOD_SSI, |
222 | RSND_MOD_MAX, | 239 | RSND_MOD_MAX, |
@@ -312,7 +329,7 @@ struct rsnd_mod { | |||
312 | 329 | ||
313 | #define rsnd_mod_to_priv(mod) ((mod)->priv) | 330 | #define rsnd_mod_to_priv(mod) ((mod)->priv) |
314 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) | 331 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) |
315 | #define rsnd_mod_id(mod) ((mod)->id) | 332 | #define rsnd_mod_id(mod) ((mod) ? (mod)->id : -1) |
316 | #define rsnd_mod_hw_start(mod) clk_enable((mod)->clk) | 333 | #define rsnd_mod_hw_start(mod) clk_enable((mod)->clk) |
317 | #define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk) | 334 | #define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk) |
318 | 335 | ||
@@ -345,9 +362,12 @@ struct rsnd_dai_stream { | |||
345 | int byte_per_period; | 362 | int byte_per_period; |
346 | int next_period_byte; | 363 | int next_period_byte; |
347 | }; | 364 | }; |
348 | #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) | 365 | #define rsnd_io_to_mod(io, i) ((i) < RSND_MOD_MAX ? (io)->mod[(i)] : NULL) |
349 | #define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) | 366 | #define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI) |
350 | #define rsnd_io_to_mod_dvc(io) ((io)->mod[RSND_MOD_DVC]) | 367 | #define rsnd_io_to_mod_src(io) rsnd_io_to_mod((io), RSND_MOD_SRC) |
368 | #define rsnd_io_to_mod_ctu(io) rsnd_io_to_mod((io), RSND_MOD_CTU) | ||
369 | #define rsnd_io_to_mod_mix(io) rsnd_io_to_mod((io), RSND_MOD_MIX) | ||
370 | #define rsnd_io_to_mod_dvc(io) rsnd_io_to_mod((io), RSND_MOD_DVC) | ||
351 | #define rsnd_io_to_rdai(io) ((io)->rdai) | 371 | #define rsnd_io_to_rdai(io) ((io)->rdai) |
352 | #define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io))) | 372 | #define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io))) |
353 | #define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io) | 373 | #define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io) |
@@ -437,12 +457,6 @@ struct rsnd_priv { | |||
437 | void *gen; | 457 | void *gen; |
438 | 458 | ||
439 | /* | 459 | /* |
440 | * below value will be filled on rsnd_src_probe() | ||
441 | */ | ||
442 | void *src; | ||
443 | int src_nr; | ||
444 | |||
445 | /* | ||
446 | * below value will be filled on rsnd_adg_probe() | 460 | * below value will be filled on rsnd_adg_probe() |
447 | */ | 461 | */ |
448 | void *adg; | 462 | void *adg; |
@@ -459,6 +473,24 @@ struct rsnd_priv { | |||
459 | int ssi_nr; | 473 | int ssi_nr; |
460 | 474 | ||
461 | /* | 475 | /* |
476 | * below value will be filled on rsnd_src_probe() | ||
477 | */ | ||
478 | void *src; | ||
479 | int src_nr; | ||
480 | |||
481 | /* | ||
482 | * below value will be filled on rsnd_ctu_probe() | ||
483 | */ | ||
484 | void *ctu; | ||
485 | int ctu_nr; | ||
486 | |||
487 | /* | ||
488 | * below value will be filled on rsnd_mix_probe() | ||
489 | */ | ||
490 | void *mix; | ||
491 | int mix_nr; | ||
492 | |||
493 | /* | ||
462 | * below value will be filled on rsnd_dvc_probe() | 494 | * below value will be filled on rsnd_dvc_probe() |
463 | */ | 495 | */ |
464 | void *dvc; | 496 | void *dvc; |
@@ -531,6 +563,19 @@ int rsnd_kctrl_new_e(struct rsnd_mod *mod, | |||
531 | u32 max); | 563 | u32 max); |
532 | 564 | ||
533 | /* | 565 | /* |
566 | * R-Car SSI | ||
567 | */ | ||
568 | int rsnd_ssi_probe(struct platform_device *pdev, | ||
569 | const struct rsnd_of_data *of_data, | ||
570 | struct rsnd_priv *priv); | ||
571 | void rsnd_ssi_remove(struct platform_device *pdev, | ||
572 | struct rsnd_priv *priv); | ||
573 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | ||
574 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); | ||
575 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); | ||
576 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod); | ||
577 | |||
578 | /* | ||
534 | * R-Car SRC | 579 | * R-Car SRC |
535 | */ | 580 | */ |
536 | int rsnd_src_probe(struct platform_device *pdev, | 581 | int rsnd_src_probe(struct platform_device *pdev, |
@@ -550,20 +595,27 @@ int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | |||
550 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod); | 595 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod); |
551 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod); | 596 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod); |
552 | 597 | ||
553 | #define rsnd_src_nr(priv) ((priv)->src_nr) | 598 | /* |
599 | * R-Car CTU | ||
600 | */ | ||
601 | int rsnd_ctu_probe(struct platform_device *pdev, | ||
602 | const struct rsnd_of_data *of_data, | ||
603 | struct rsnd_priv *priv); | ||
604 | |||
605 | void rsnd_ctu_remove(struct platform_device *pdev, | ||
606 | struct rsnd_priv *priv); | ||
607 | struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id); | ||
554 | 608 | ||
555 | /* | 609 | /* |
556 | * R-Car SSI | 610 | * R-Car MIX |
557 | */ | 611 | */ |
558 | int rsnd_ssi_probe(struct platform_device *pdev, | 612 | int rsnd_mix_probe(struct platform_device *pdev, |
559 | const struct rsnd_of_data *of_data, | 613 | const struct rsnd_of_data *of_data, |
560 | struct rsnd_priv *priv); | 614 | struct rsnd_priv *priv); |
561 | void rsnd_ssi_remove(struct platform_device *pdev, | 615 | |
616 | void rsnd_mix_remove(struct platform_device *pdev, | ||
562 | struct rsnd_priv *priv); | 617 | struct rsnd_priv *priv); |
563 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | 618 | struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id); |
564 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); | ||
565 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); | ||
566 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod); | ||
567 | 619 | ||
568 | /* | 620 | /* |
569 | * R-Car DVC | 621 | * R-Car DVC |
@@ -575,7 +627,4 @@ void rsnd_dvc_remove(struct platform_device *pdev, | |||
575 | struct rsnd_priv *priv); | 627 | struct rsnd_priv *priv); |
576 | struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id); | 628 | struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id); |
577 | 629 | ||
578 | #define rsnd_dvc_nr(priv) ((priv)->dvc_nr) | ||
579 | |||
580 | |||
581 | #endif | 630 | #endif |
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 84e935711e29..d61db9c385ea 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c | |||
@@ -41,6 +41,7 @@ static const struct rsrc_card_of_data routes_of_ssi0_ak4642 = { | |||
41 | static const struct of_device_id rsrc_card_of_match[] = { | 41 | static const struct of_device_id rsrc_card_of_match[] = { |
42 | { .compatible = "renesas,rsrc-card,lager", .data = &routes_of_ssi0_ak4642 }, | 42 | { .compatible = "renesas,rsrc-card,lager", .data = &routes_of_ssi0_ak4642 }, |
43 | { .compatible = "renesas,rsrc-card,koelsch", .data = &routes_of_ssi0_ak4642 }, | 43 | { .compatible = "renesas,rsrc-card,koelsch", .data = &routes_of_ssi0_ak4642 }, |
44 | { .compatible = "renesas,rsrc-card", }, | ||
44 | {}, | 45 | {}, |
45 | }; | 46 | }; |
46 | MODULE_DEVICE_TABLE(of, rsrc_card_of_match); | 47 | MODULE_DEVICE_TABLE(of, rsrc_card_of_match); |
@@ -242,8 +243,15 @@ static int rsrc_card_parse_links(struct device_node *np, | |||
242 | snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name); | 243 | snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name); |
243 | 244 | ||
244 | /* additional name prefix */ | 245 | /* additional name prefix */ |
245 | priv->codec_conf.of_node = dai_link->codec_of_node; | 246 | if (of_data) { |
246 | priv->codec_conf.name_prefix = of_data->prefix; | 247 | priv->codec_conf.of_node = dai_link->codec_of_node; |
248 | priv->codec_conf.name_prefix = of_data->prefix; | ||
249 | } else { | ||
250 | snd_soc_of_parse_audio_prefix(&priv->snd_card, | ||
251 | &priv->codec_conf, | ||
252 | dai_link->codec_of_node, | ||
253 | "audio-prefix"); | ||
254 | } | ||
247 | 255 | ||
248 | /* set dai_name */ | 256 | /* set dai_name */ |
249 | snprintf(dai_props->dai_name, DAI_NAME_NUM, "be.%s", | 257 | snprintf(dai_props->dai_name, DAI_NAME_NUM, "be.%s", |
@@ -361,8 +369,14 @@ static int rsrc_card_parse_of(struct device_node *node, | |||
361 | priv->snd_card.num_links = num; | 369 | priv->snd_card.num_links = num; |
362 | priv->snd_card.codec_conf = &priv->codec_conf; | 370 | priv->snd_card.codec_conf = &priv->codec_conf; |
363 | priv->snd_card.num_configs = 1; | 371 | priv->snd_card.num_configs = 1; |
364 | priv->snd_card.of_dapm_routes = of_data->routes; | 372 | |
365 | priv->snd_card.num_of_dapm_routes = of_data->num_routes; | 373 | if (of_data) { |
374 | priv->snd_card.of_dapm_routes = of_data->routes; | ||
375 | priv->snd_card.num_of_dapm_routes = of_data->num_routes; | ||
376 | } else { | ||
377 | snd_soc_of_parse_audio_routing(&priv->snd_card, | ||
378 | "audio-routing"); | ||
379 | } | ||
366 | 380 | ||
367 | /* Parse the card name from DT */ | 381 | /* Parse the card name from DT */ |
368 | snd_soc_of_parse_card_name(&priv->snd_card, "card-name"); | 382 | snd_soc_of_parse_card_name(&priv->snd_card, "card-name"); |
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index c61c17180142..89a18e102feb 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -30,6 +30,7 @@ struct rsnd_src { | |||
30 | 30 | ||
31 | #define RSND_SRC_NAME_SIZE 16 | 31 | #define RSND_SRC_NAME_SIZE 16 |
32 | 32 | ||
33 | #define rsnd_src_nr(priv) ((priv)->src_nr) | ||
33 | #define rsnd_enable_sync_convert(src) ((src)->sen.val) | 34 | #define rsnd_enable_sync_convert(src) ((src)->sen.val) |
34 | #define rsnd_src_of_node(priv) \ | 35 | #define rsnd_src_of_node(priv) \ |
35 | of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src") | 36 | of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src") |
@@ -117,6 +118,20 @@ struct rsnd_src { | |||
117 | /* | 118 | /* |
118 | * Gen1/Gen2 common functions | 119 | * Gen1/Gen2 common functions |
119 | */ | 120 | */ |
121 | static void rsnd_src_soft_reset(struct rsnd_mod *mod) | ||
122 | { | ||
123 | rsnd_mod_write(mod, SRC_SWRSR, 0); | ||
124 | rsnd_mod_write(mod, SRC_SWRSR, 1); | ||
125 | } | ||
126 | |||
127 | |||
128 | #define rsnd_src_initialize_lock(mod) __rsnd_src_initialize_lock(mod, 1) | ||
129 | #define rsnd_src_initialize_unlock(mod) __rsnd_src_initialize_lock(mod, 0) | ||
130 | static void __rsnd_src_initialize_lock(struct rsnd_mod *mod, u32 enable) | ||
131 | { | ||
132 | rsnd_mod_write(mod, SRC_SRCIR, enable); | ||
133 | } | ||
134 | |||
120 | static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io, | 135 | static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io, |
121 | struct rsnd_mod *mod) | 136 | struct rsnd_mod *mod) |
122 | { | 137 | { |
@@ -133,7 +148,6 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | |||
133 | int use_busif) | 148 | int use_busif) |
134 | { | 149 | { |
135 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | 150 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
136 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
137 | int ssi_id = rsnd_mod_id(ssi_mod); | 151 | int ssi_id = rsnd_mod_id(ssi_mod); |
138 | 152 | ||
139 | /* | 153 | /* |
@@ -170,27 +184,14 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | |||
170 | * DMA settings for SSIU | 184 | * DMA settings for SSIU |
171 | */ | 185 | */ |
172 | if (use_busif) { | 186 | if (use_busif) { |
173 | u32 val = 0x76543210; | 187 | u32 val = rsnd_get_dalign(ssi_mod, io); |
174 | u32 mask = ~0; | ||
175 | 188 | ||
176 | rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, | 189 | rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, |
177 | rsnd_get_adinr(ssi_mod, io)); | 190 | rsnd_get_adinr_bit(ssi_mod, io)); |
178 | rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); | 191 | rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); |
179 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); | 192 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); |
180 | 193 | ||
181 | mask <<= runtime->channels * 4; | 194 | rsnd_mod_write(ssi_mod, SSI_BUSIF_DALIGN, val); |
182 | val = val & mask; | ||
183 | |||
184 | switch (runtime->sample_bits) { | ||
185 | case 16: | ||
186 | val |= 0x67452301 & ~mask; | ||
187 | break; | ||
188 | case 32: | ||
189 | val |= 0x76543210 & ~mask; | ||
190 | break; | ||
191 | } | ||
192 | rsnd_mod_write(ssi_mod, BUSIF_DALIGN, val); | ||
193 | |||
194 | } | 195 | } |
195 | 196 | ||
196 | return 0; | 197 | return 0; |
@@ -215,10 +216,9 @@ int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod) | |||
215 | return 0; | 216 | return 0; |
216 | 217 | ||
217 | /* enable SSI interrupt if Gen2 */ | 218 | /* enable SSI interrupt if Gen2 */ |
218 | if (rsnd_ssi_is_dma_mode(ssi_mod)) | 219 | rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, |
219 | rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0e000000); | 220 | rsnd_ssi_is_dma_mode(ssi_mod) ? |
220 | else | 221 | 0x0e000000 : 0x0f000000); |
221 | rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); | ||
222 | 222 | ||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
@@ -231,7 +231,7 @@ int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod) | |||
231 | return 0; | 231 | return 0; |
232 | 232 | ||
233 | /* disable SSI interrupt if Gen2 */ | 233 | /* disable SSI interrupt if Gen2 */ |
234 | rsnd_mod_write(ssi_mod, INT_ENABLE, 0x00000000); | 234 | rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, 0x00000000); |
235 | 235 | ||
236 | return 0; | 236 | return 0; |
237 | } | 237 | } |
@@ -294,12 +294,8 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, | |||
294 | if (convert_rate) | 294 | if (convert_rate) |
295 | fsrate = 0x0400000 / convert_rate * runtime->rate; | 295 | fsrate = 0x0400000 / convert_rate * runtime->rate; |
296 | 296 | ||
297 | /* set/clear soft reset */ | ||
298 | rsnd_mod_write(mod, SRC_SWRSR, 0); | ||
299 | rsnd_mod_write(mod, SRC_SWRSR, 1); | ||
300 | |||
301 | /* Set channel number and output bit length */ | 297 | /* Set channel number and output bit length */ |
302 | rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod, io)); | 298 | rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr_bit(mod, io)); |
303 | 299 | ||
304 | /* Enable the initial value of IFS */ | 300 | /* Enable the initial value of IFS */ |
305 | if (fsrate) { | 301 | if (fsrate) { |
@@ -358,17 +354,15 @@ static int rsnd_src_init(struct rsnd_mod *mod, | |||
358 | 354 | ||
359 | rsnd_mod_hw_start(mod); | 355 | rsnd_mod_hw_start(mod); |
360 | 356 | ||
357 | rsnd_src_soft_reset(mod); | ||
358 | |||
359 | rsnd_src_initialize_lock(mod); | ||
360 | |||
361 | src->err = 0; | 361 | src->err = 0; |
362 | 362 | ||
363 | /* reset sync convert_rate */ | 363 | /* reset sync convert_rate */ |
364 | src->sync.val = 0; | 364 | src->sync.val = 0; |
365 | 365 | ||
366 | /* | ||
367 | * Initialize the operation of the SRC internal circuits | ||
368 | * see rsnd_src_start() | ||
369 | */ | ||
370 | rsnd_mod_write(mod, SRC_SRCIR, 1); | ||
371 | |||
372 | return 0; | 366 | return 0; |
373 | } | 367 | } |
374 | 368 | ||
@@ -395,11 +389,7 @@ static int rsnd_src_quit(struct rsnd_mod *mod, | |||
395 | 389 | ||
396 | static int rsnd_src_start(struct rsnd_mod *mod) | 390 | static int rsnd_src_start(struct rsnd_mod *mod) |
397 | { | 391 | { |
398 | /* | 392 | rsnd_src_initialize_unlock(mod); |
399 | * Cancel the initialization and operate the SRC function | ||
400 | * see rsnd_src_init() | ||
401 | */ | ||
402 | rsnd_mod_write(mod, SRC_SRCIR, 0); | ||
403 | 393 | ||
404 | return 0; | 394 | return 0; |
405 | } | 395 | } |
@@ -617,6 +607,14 @@ static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable) | |||
617 | int_val = 0; | 607 | int_val = 0; |
618 | } | 608 | } |
619 | 609 | ||
610 | /* | ||
611 | * WORKAROUND | ||
612 | * | ||
613 | * ignore over flow error when rsnd_enable_sync_convert() | ||
614 | */ | ||
615 | if (rsnd_enable_sync_convert(src)) | ||
616 | sys_int_val = sys_int_val & 0xffff; | ||
617 | |||
620 | rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); | 618 | rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); |
621 | rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); | 619 | rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); |
622 | rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); | 620 | rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); |
@@ -632,11 +630,22 @@ static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod) | |||
632 | 630 | ||
633 | static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) | 631 | static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) |
634 | { | 632 | { |
635 | u32 val = OUF_SRC(rsnd_mod_id(mod)); | 633 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
634 | u32 val0, val1; | ||
636 | bool ret = false; | 635 | bool ret = false; |
637 | 636 | ||
638 | if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val) || | 637 | val0 = val1 = OUF_SRC(rsnd_mod_id(mod)); |
639 | (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val)) { | 638 | |
639 | /* | ||
640 | * WORKAROUND | ||
641 | * | ||
642 | * ignore over flow error when rsnd_enable_sync_convert() | ||
643 | */ | ||
644 | if (rsnd_enable_sync_convert(src)) | ||
645 | val0 = val0 & 0xffff; | ||
646 | |||
647 | if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) || | ||
648 | (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) { | ||
640 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 649 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
641 | 650 | ||
642 | src->err++; | 651 | src->err++; |
@@ -652,7 +661,20 @@ static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) | |||
652 | static int _rsnd_src_start_gen2(struct rsnd_mod *mod, | 661 | static int _rsnd_src_start_gen2(struct rsnd_mod *mod, |
653 | struct rsnd_dai_stream *io) | 662 | struct rsnd_dai_stream *io) |
654 | { | 663 | { |
655 | u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; | 664 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
665 | u32 val; | ||
666 | |||
667 | val = rsnd_get_dalign(mod, io); | ||
668 | |||
669 | rsnd_mod_write(mod, SRC_BUSIF_DALIGN, val); | ||
670 | |||
671 | /* | ||
672 | * WORKAROUND | ||
673 | * | ||
674 | * Enable SRC output if you want to use sync convert together with DVC | ||
675 | */ | ||
676 | val = (rsnd_io_to_mod_dvc(io) && !rsnd_enable_sync_convert(src)) ? | ||
677 | 0x01 : 0x11; | ||
656 | 678 | ||
657 | rsnd_mod_write(mod, SRC_CTRL, val); | 679 | rsnd_mod_write(mod, SRC_CTRL, val); |
658 | 680 | ||
@@ -922,13 +944,6 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod, | |||
922 | return 0; | 944 | return 0; |
923 | 945 | ||
924 | /* | 946 | /* |
925 | * We can't use SRC sync convert | ||
926 | * if it has DVC | ||
927 | */ | ||
928 | if (rsnd_io_to_mod_dvc(io)) | ||
929 | return 0; | ||
930 | |||
931 | /* | ||
932 | * enable sync convert | 947 | * enable sync convert |
933 | */ | 948 | */ |
934 | ret = rsnd_kctrl_new_s(mod, io, rtd, | 949 | ret = rsnd_kctrl_new_s(mod, io, rtd, |
@@ -1047,10 +1062,8 @@ int rsnd_src_probe(struct platform_device *pdev, | |||
1047 | return 0; | 1062 | return 0; |
1048 | 1063 | ||
1049 | src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); | 1064 | src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); |
1050 | if (!src) { | 1065 | if (!src) |
1051 | dev_err(dev, "SRC allocate failed\n"); | ||
1052 | return -ENOMEM; | 1066 | return -ENOMEM; |
1053 | } | ||
1054 | 1067 | ||
1055 | priv->src_nr = nr; | 1068 | priv->src_nr = nr; |
1056 | priv->src = src; | 1069 | priv->src = src; |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2fbe59f7f9b5..d45b9a7e324e 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -770,10 +770,8 @@ int rsnd_ssi_probe(struct platform_device *pdev, | |||
770 | */ | 770 | */ |
771 | nr = info->ssi_info_nr; | 771 | nr = info->ssi_info_nr; |
772 | ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); | 772 | ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); |
773 | if (!ssi) { | 773 | if (!ssi) |
774 | dev_err(dev, "SSI allocate failed\n"); | ||
775 | return -ENOMEM; | 774 | return -ENOMEM; |
776 | } | ||
777 | 775 | ||
778 | priv->ssi = ssi; | 776 | priv->ssi = ssi; |
779 | priv->ssi_nr = nr; | 777 | priv->ssi_nr = nr; |
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index ab13146e4f82..89ed1b107ac5 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c | |||
@@ -385,14 +385,9 @@ static const struct snd_soc_component_driver sh4_ssi_component = { | |||
385 | 385 | ||
386 | static int sh4_soc_dai_probe(struct platform_device *pdev) | 386 | static int sh4_soc_dai_probe(struct platform_device *pdev) |
387 | { | 387 | { |
388 | return snd_soc_register_component(&pdev->dev, &sh4_ssi_component, | 388 | return devm_snd_soc_register_component(&pdev->dev, &sh4_ssi_component, |
389 | sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); | 389 | sh4_ssi_dai, |
390 | } | 390 | ARRAY_SIZE(sh4_ssi_dai)); |
391 | |||
392 | static int sh4_soc_dai_remove(struct platform_device *pdev) | ||
393 | { | ||
394 | snd_soc_unregister_component(&pdev->dev); | ||
395 | return 0; | ||
396 | } | 391 | } |
397 | 392 | ||
398 | static struct platform_driver sh4_ssi_driver = { | 393 | static struct platform_driver sh4_ssi_driver = { |
@@ -401,7 +396,6 @@ static struct platform_driver sh4_ssi_driver = { | |||
401 | }, | 396 | }, |
402 | 397 | ||
403 | .probe = sh4_soc_dai_probe, | 398 | .probe = sh4_soc_dai_probe, |
404 | .remove = sh4_soc_dai_remove, | ||
405 | }; | 399 | }; |
406 | 400 | ||
407 | module_platform_driver(sh4_ssi_driver); | 401 | module_platform_driver(sh4_ssi_driver); |
diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index 08d7259bbaab..d40efc9fe0a9 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c | |||
@@ -85,10 +85,19 @@ EXPORT_SYMBOL(snd_soc_alloc_ac97_codec); | |||
85 | /** | 85 | /** |
86 | * snd_soc_new_ac97_codec - initailise AC97 device | 86 | * snd_soc_new_ac97_codec - initailise AC97 device |
87 | * @codec: audio codec | 87 | * @codec: audio codec |
88 | * @id: The expected device ID | ||
89 | * @id_mask: Mask that is applied to the device ID before comparing with @id | ||
88 | * | 90 | * |
89 | * Initialises AC97 codec resources for use by ad-hoc devices only. | 91 | * Initialises AC97 codec resources for use by ad-hoc devices only. |
92 | * | ||
93 | * If @id is not 0 this function will reset the device, then read the ID from | ||
94 | * the device and check if it matches the expected ID. If it doesn't match an | ||
95 | * error will be returned and device will not be registered. | ||
96 | * | ||
97 | * Returns: A PTR_ERR() on failure or a valid snd_ac97 struct on success. | ||
90 | */ | 98 | */ |
91 | struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec) | 99 | struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec, |
100 | unsigned int id, unsigned int id_mask) | ||
92 | { | 101 | { |
93 | struct snd_ac97 *ac97; | 102 | struct snd_ac97 *ac97; |
94 | int ret; | 103 | int ret; |
@@ -97,13 +106,24 @@ struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec) | |||
97 | if (IS_ERR(ac97)) | 106 | if (IS_ERR(ac97)) |
98 | return ac97; | 107 | return ac97; |
99 | 108 | ||
100 | ret = device_add(&ac97->dev); | 109 | if (id) { |
101 | if (ret) { | 110 | ret = snd_ac97_reset(ac97, false, id, id_mask); |
102 | put_device(&ac97->dev); | 111 | if (ret < 0) { |
103 | return ERR_PTR(ret); | 112 | dev_err(codec->dev, "Failed to reset AC97 device: %d\n", |
113 | ret); | ||
114 | goto err_put_device; | ||
115 | } | ||
104 | } | 116 | } |
105 | 117 | ||
118 | ret = device_add(&ac97->dev); | ||
119 | if (ret) | ||
120 | goto err_put_device; | ||
121 | |||
106 | return ac97; | 122 | return ac97; |
123 | |||
124 | err_put_device: | ||
125 | put_device(&ac97->dev); | ||
126 | return ERR_PTR(ret); | ||
107 | } | 127 | } |
108 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | 128 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); |
109 | 129 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0e1e69c7abd5..6173d15236c3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -654,10 +654,12 @@ int snd_soc_suspend(struct device *dev) | |||
654 | 654 | ||
655 | /* suspend all CODECs */ | 655 | /* suspend all CODECs */ |
656 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { | 656 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
657 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
658 | |||
657 | /* If there are paths active then the CODEC will be held with | 659 | /* If there are paths active then the CODEC will be held with |
658 | * bias _ON and should not be suspended. */ | 660 | * bias _ON and should not be suspended. */ |
659 | if (!codec->suspended) { | 661 | if (!codec->suspended) { |
660 | switch (codec->dapm.bias_level) { | 662 | switch (snd_soc_dapm_get_bias_level(dapm)) { |
661 | case SND_SOC_BIAS_STANDBY: | 663 | case SND_SOC_BIAS_STANDBY: |
662 | /* | 664 | /* |
663 | * If the CODEC is capable of idle | 665 | * If the CODEC is capable of idle |
@@ -665,7 +667,7 @@ int snd_soc_suspend(struct device *dev) | |||
665 | * means it's doing something, | 667 | * means it's doing something, |
666 | * otherwise fall through. | 668 | * otherwise fall through. |
667 | */ | 669 | */ |
668 | if (codec->dapm.idle_bias_off) { | 670 | if (dapm->idle_bias_off) { |
669 | dev_dbg(codec->dev, | 671 | dev_dbg(codec->dev, |
670 | "ASoC: idle_bias_off CODEC on over suspend\n"); | 672 | "ASoC: idle_bias_off CODEC on over suspend\n"); |
671 | break; | 673 | break; |
@@ -978,7 +980,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
978 | 980 | ||
979 | static void soc_remove_component(struct snd_soc_component *component) | 981 | static void soc_remove_component(struct snd_soc_component *component) |
980 | { | 982 | { |
981 | if (!component->probed) | 983 | if (!component->card) |
982 | return; | 984 | return; |
983 | 985 | ||
984 | /* This is a HACK and will be removed soon */ | 986 | /* This is a HACK and will be removed soon */ |
@@ -991,7 +993,7 @@ static void soc_remove_component(struct snd_soc_component *component) | |||
991 | snd_soc_dapm_free(snd_soc_component_get_dapm(component)); | 993 | snd_soc_dapm_free(snd_soc_component_get_dapm(component)); |
992 | 994 | ||
993 | soc_cleanup_component_debugfs(component); | 995 | soc_cleanup_component_debugfs(component); |
994 | component->probed = 0; | 996 | component->card = NULL; |
995 | module_put(component->dev->driver->owner); | 997 | module_put(component->dev->driver->owner); |
996 | } | 998 | } |
997 | 999 | ||
@@ -1102,16 +1104,26 @@ static int soc_probe_component(struct snd_soc_card *card, | |||
1102 | struct snd_soc_dai *dai; | 1104 | struct snd_soc_dai *dai; |
1103 | int ret; | 1105 | int ret; |
1104 | 1106 | ||
1105 | if (component->probed) | 1107 | if (!strcmp(component->name, "snd-soc-dummy")) |
1106 | return 0; | 1108 | return 0; |
1107 | 1109 | ||
1108 | component->card = card; | 1110 | if (component->card) { |
1109 | dapm->card = card; | 1111 | if (component->card != card) { |
1110 | soc_set_name_prefix(card, component); | 1112 | dev_err(component->dev, |
1113 | "Trying to bind component to card \"%s\" but is already bound to card \"%s\"\n", | ||
1114 | card->name, component->card->name); | ||
1115 | return -ENODEV; | ||
1116 | } | ||
1117 | return 0; | ||
1118 | } | ||
1111 | 1119 | ||
1112 | if (!try_module_get(component->dev->driver->owner)) | 1120 | if (!try_module_get(component->dev->driver->owner)) |
1113 | return -ENODEV; | 1121 | return -ENODEV; |
1114 | 1122 | ||
1123 | component->card = card; | ||
1124 | dapm->card = card; | ||
1125 | soc_set_name_prefix(card, component); | ||
1126 | |||
1115 | soc_init_component_debugfs(component); | 1127 | soc_init_component_debugfs(component); |
1116 | 1128 | ||
1117 | if (component->dapm_widgets) { | 1129 | if (component->dapm_widgets) { |
@@ -1155,7 +1167,6 @@ static int soc_probe_component(struct snd_soc_card *card, | |||
1155 | snd_soc_dapm_add_routes(dapm, component->dapm_routes, | 1167 | snd_soc_dapm_add_routes(dapm, component->dapm_routes, |
1156 | component->num_dapm_routes); | 1168 | component->num_dapm_routes); |
1157 | 1169 | ||
1158 | component->probed = 1; | ||
1159 | list_add(&dapm->list, &card->dapm_list); | 1170 | list_add(&dapm->list, &card->dapm_list); |
1160 | 1171 | ||
1161 | /* This is a HACK and will be removed soon */ | 1172 | /* This is a HACK and will be removed soon */ |
@@ -1166,6 +1177,7 @@ static int soc_probe_component(struct snd_soc_card *card, | |||
1166 | 1177 | ||
1167 | err_probe: | 1178 | err_probe: |
1168 | soc_cleanup_component_debugfs(component); | 1179 | soc_cleanup_component_debugfs(component); |
1180 | component->card = NULL; | ||
1169 | module_put(component->dev->driver->owner); | 1181 | module_put(component->dev->driver->owner); |
1170 | 1182 | ||
1171 | return ret; | 1183 | return ret; |
@@ -1449,7 +1461,7 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) | |||
1449 | rtd->dev_registered = 0; | 1461 | rtd->dev_registered = 0; |
1450 | } | 1462 | } |
1451 | 1463 | ||
1452 | if (component && component->probed) | 1464 | if (component) |
1453 | soc_remove_component(component); | 1465 | soc_remove_component(component); |
1454 | } | 1466 | } |
1455 | 1467 | ||
@@ -2128,7 +2140,7 @@ EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll); | |||
2128 | /** | 2140 | /** |
2129 | * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. | 2141 | * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. |
2130 | * @dai: DAI | 2142 | * @dai: DAI |
2131 | * @ratio Ratio of BCLK to Sample rate. | 2143 | * @ratio: Ratio of BCLK to Sample rate. |
2132 | * | 2144 | * |
2133 | * Configures the DAI for a preset BCLK to sample rate ratio. | 2145 | * Configures the DAI for a preset BCLK to sample rate ratio. |
2134 | */ | 2146 | */ |
@@ -2652,10 +2664,7 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, | |||
2652 | component->probe = component->driver->probe; | 2664 | component->probe = component->driver->probe; |
2653 | component->remove = component->driver->remove; | 2665 | component->remove = component->driver->remove; |
2654 | 2666 | ||
2655 | if (!component->dapm_ptr) | 2667 | dapm = &component->dapm; |
2656 | component->dapm_ptr = &component->dapm; | ||
2657 | |||
2658 | dapm = component->dapm_ptr; | ||
2659 | dapm->dev = dev; | 2668 | dapm->dev = dev; |
2660 | dapm->component = component; | 2669 | dapm->component = component; |
2661 | dapm->bias_level = SND_SOC_BIAS_OFF; | 2670 | dapm->bias_level = SND_SOC_BIAS_OFF; |
@@ -2799,6 +2808,7 @@ EXPORT_SYMBOL_GPL(snd_soc_register_component); | |||
2799 | /** | 2808 | /** |
2800 | * snd_soc_unregister_component - Unregister a component from the ASoC core | 2809 | * snd_soc_unregister_component - Unregister a component from the ASoC core |
2801 | * | 2810 | * |
2811 | * @dev: The device to unregister | ||
2802 | */ | 2812 | */ |
2803 | void snd_soc_unregister_component(struct device *dev) | 2813 | void snd_soc_unregister_component(struct device *dev) |
2804 | { | 2814 | { |
@@ -2839,7 +2849,7 @@ static void snd_soc_platform_drv_remove(struct snd_soc_component *component) | |||
2839 | * snd_soc_add_platform - Add a platform to the ASoC core | 2849 | * snd_soc_add_platform - Add a platform to the ASoC core |
2840 | * @dev: The parent device for the platform | 2850 | * @dev: The parent device for the platform |
2841 | * @platform: The platform to add | 2851 | * @platform: The platform to add |
2842 | * @platform_driver: The driver for the platform | 2852 | * @platform_drv: The driver for the platform |
2843 | */ | 2853 | */ |
2844 | int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, | 2854 | int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, |
2845 | const struct snd_soc_platform_driver *platform_drv) | 2855 | const struct snd_soc_platform_driver *platform_drv) |
@@ -2878,7 +2888,8 @@ EXPORT_SYMBOL_GPL(snd_soc_add_platform); | |||
2878 | /** | 2888 | /** |
2879 | * snd_soc_register_platform - Register a platform with the ASoC core | 2889 | * snd_soc_register_platform - Register a platform with the ASoC core |
2880 | * | 2890 | * |
2881 | * @platform: platform to register | 2891 | * @dev: The device for the platform |
2892 | * @platform_drv: The driver for the platform | ||
2882 | */ | 2893 | */ |
2883 | int snd_soc_register_platform(struct device *dev, | 2894 | int snd_soc_register_platform(struct device *dev, |
2884 | const struct snd_soc_platform_driver *platform_drv) | 2895 | const struct snd_soc_platform_driver *platform_drv) |
@@ -2939,7 +2950,7 @@ EXPORT_SYMBOL_GPL(snd_soc_lookup_platform); | |||
2939 | /** | 2950 | /** |
2940 | * snd_soc_unregister_platform - Unregister a platform from the ASoC core | 2951 | * snd_soc_unregister_platform - Unregister a platform from the ASoC core |
2941 | * | 2952 | * |
2942 | * @platform: platform to unregister | 2953 | * @dev: platform to unregister |
2943 | */ | 2954 | */ |
2944 | void snd_soc_unregister_platform(struct device *dev) | 2955 | void snd_soc_unregister_platform(struct device *dev) |
2945 | { | 2956 | { |
@@ -3030,13 +3041,17 @@ static int snd_soc_codec_set_bias_level(struct snd_soc_dapm_context *dapm, | |||
3030 | /** | 3041 | /** |
3031 | * snd_soc_register_codec - Register a codec with the ASoC core | 3042 | * snd_soc_register_codec - Register a codec with the ASoC core |
3032 | * | 3043 | * |
3033 | * @codec: codec to register | 3044 | * @dev: The parent device for this codec |
3045 | * @codec_drv: Codec driver | ||
3046 | * @dai_drv: The associated DAI driver | ||
3047 | * @num_dai: Number of DAIs | ||
3034 | */ | 3048 | */ |
3035 | int snd_soc_register_codec(struct device *dev, | 3049 | int snd_soc_register_codec(struct device *dev, |
3036 | const struct snd_soc_codec_driver *codec_drv, | 3050 | const struct snd_soc_codec_driver *codec_drv, |
3037 | struct snd_soc_dai_driver *dai_drv, | 3051 | struct snd_soc_dai_driver *dai_drv, |
3038 | int num_dai) | 3052 | int num_dai) |
3039 | { | 3053 | { |
3054 | struct snd_soc_dapm_context *dapm; | ||
3040 | struct snd_soc_codec *codec; | 3055 | struct snd_soc_codec *codec; |
3041 | struct snd_soc_dai *dai; | 3056 | struct snd_soc_dai *dai; |
3042 | int ret, i; | 3057 | int ret, i; |
@@ -3047,7 +3062,6 @@ int snd_soc_register_codec(struct device *dev, | |||
3047 | if (codec == NULL) | 3062 | if (codec == NULL) |
3048 | return -ENOMEM; | 3063 | return -ENOMEM; |
3049 | 3064 | ||
3050 | codec->component.dapm_ptr = &codec->dapm; | ||
3051 | codec->component.codec = codec; | 3065 | codec->component.codec = codec; |
3052 | 3066 | ||
3053 | ret = snd_soc_component_initialize(&codec->component, | 3067 | ret = snd_soc_component_initialize(&codec->component, |
@@ -3077,12 +3091,14 @@ int snd_soc_register_codec(struct device *dev, | |||
3077 | if (codec_drv->read) | 3091 | if (codec_drv->read) |
3078 | codec->component.read = snd_soc_codec_drv_read; | 3092 | codec->component.read = snd_soc_codec_drv_read; |
3079 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; | 3093 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; |
3080 | codec->dapm.idle_bias_off = codec_drv->idle_bias_off; | 3094 | |
3081 | codec->dapm.suspend_bias_off = codec_drv->suspend_bias_off; | 3095 | dapm = snd_soc_codec_get_dapm(codec); |
3096 | dapm->idle_bias_off = codec_drv->idle_bias_off; | ||
3097 | dapm->suspend_bias_off = codec_drv->suspend_bias_off; | ||
3082 | if (codec_drv->seq_notifier) | 3098 | if (codec_drv->seq_notifier) |
3083 | codec->dapm.seq_notifier = codec_drv->seq_notifier; | 3099 | dapm->seq_notifier = codec_drv->seq_notifier; |
3084 | if (codec_drv->set_bias_level) | 3100 | if (codec_drv->set_bias_level) |
3085 | codec->dapm.set_bias_level = snd_soc_codec_set_bias_level; | 3101 | dapm->set_bias_level = snd_soc_codec_set_bias_level; |
3086 | codec->dev = dev; | 3102 | codec->dev = dev; |
3087 | codec->driver = codec_drv; | 3103 | codec->driver = codec_drv; |
3088 | codec->component.val_bytes = codec_drv->reg_word_size; | 3104 | codec->component.val_bytes = codec_drv->reg_word_size; |
@@ -3129,7 +3145,7 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec); | |||
3129 | /** | 3145 | /** |
3130 | * snd_soc_unregister_codec - Unregister a codec from the ASoC core | 3146 | * snd_soc_unregister_codec - Unregister a codec from the ASoC core |
3131 | * | 3147 | * |
3132 | * @codec: codec to unregister | 3148 | * @dev: codec to unregister |
3133 | */ | 3149 | */ |
3134 | void snd_soc_unregister_codec(struct device *dev) | 3150 | void snd_soc_unregister_codec(struct device *dev) |
3135 | { | 3151 | { |
@@ -3304,6 +3320,26 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np, | |||
3304 | } | 3320 | } |
3305 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); | 3321 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); |
3306 | 3322 | ||
3323 | void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, | ||
3324 | struct snd_soc_codec_conf *codec_conf, | ||
3325 | struct device_node *of_node, | ||
3326 | const char *propname) | ||
3327 | { | ||
3328 | struct device_node *np = card->dev->of_node; | ||
3329 | const char *str; | ||
3330 | int ret; | ||
3331 | |||
3332 | ret = of_property_read_string(np, propname, &str); | ||
3333 | if (ret < 0) { | ||
3334 | /* no prefix is not error */ | ||
3335 | return; | ||
3336 | } | ||
3337 | |||
3338 | codec_conf->of_node = of_node; | ||
3339 | codec_conf->name_prefix = str; | ||
3340 | } | ||
3341 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix); | ||
3342 | |||
3307 | int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | 3343 | int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, |
3308 | const char *propname) | 3344 | const char *propname) |
3309 | { | 3345 | { |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index e0de8072c514..f4bf21a5539b 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -47,6 +47,13 @@ | |||
47 | 47 | ||
48 | #define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++; | 48 | #define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++; |
49 | 49 | ||
50 | #define SND_SOC_DAPM_DIR_REVERSE(x) ((x == SND_SOC_DAPM_DIR_IN) ? \ | ||
51 | SND_SOC_DAPM_DIR_OUT : SND_SOC_DAPM_DIR_IN) | ||
52 | |||
53 | #define snd_soc_dapm_for_each_direction(dir) \ | ||
54 | for ((dir) = SND_SOC_DAPM_DIR_IN; (dir) <= SND_SOC_DAPM_DIR_OUT; \ | ||
55 | (dir)++) | ||
56 | |||
50 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | 57 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, |
51 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, | 58 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, |
52 | const char *control, | 59 | const char *control, |
@@ -167,45 +174,59 @@ static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) | |||
167 | } | 174 | } |
168 | 175 | ||
169 | /* | 176 | /* |
170 | * dapm_widget_invalidate_input_paths() - Invalidate the cached number of input | 177 | * Common implementation for dapm_widget_invalidate_input_paths() and |
171 | * paths | 178 | * dapm_widget_invalidate_output_paths(). The function is inlined since the |
172 | * @w: The widget for which to invalidate the cached number of input paths | 179 | * combined size of the two specialized functions is only marginally larger then |
173 | * | 180 | * the size of the generic function and at the same time the fast path of the |
174 | * The function resets the cached number of inputs for the specified widget and | 181 | * specialized functions is significantly smaller than the generic function. |
175 | * all widgets that can be reached via outgoing paths from the widget. | ||
176 | * | ||
177 | * This function must be called if the number of input paths for a widget might | ||
178 | * have changed. E.g. if the source state of a widget changes or a path is added | ||
179 | * or activated with the widget as the sink. | ||
180 | */ | 182 | */ |
181 | static void dapm_widget_invalidate_input_paths(struct snd_soc_dapm_widget *w) | 183 | static __always_inline void dapm_widget_invalidate_paths( |
184 | struct snd_soc_dapm_widget *w, enum snd_soc_dapm_direction dir) | ||
182 | { | 185 | { |
183 | struct snd_soc_dapm_widget *sink; | 186 | enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir); |
187 | struct snd_soc_dapm_widget *node; | ||
184 | struct snd_soc_dapm_path *p; | 188 | struct snd_soc_dapm_path *p; |
185 | LIST_HEAD(list); | 189 | LIST_HEAD(list); |
186 | 190 | ||
187 | dapm_assert_locked(w->dapm); | 191 | dapm_assert_locked(w->dapm); |
188 | 192 | ||
189 | if (w->inputs == -1) | 193 | if (w->endpoints[dir] == -1) |
190 | return; | 194 | return; |
191 | 195 | ||
192 | w->inputs = -1; | ||
193 | list_add_tail(&w->work_list, &list); | 196 | list_add_tail(&w->work_list, &list); |
197 | w->endpoints[dir] = -1; | ||
194 | 198 | ||
195 | list_for_each_entry(w, &list, work_list) { | 199 | list_for_each_entry(w, &list, work_list) { |
196 | list_for_each_entry(p, &w->sinks, list_source) { | 200 | snd_soc_dapm_widget_for_each_path(w, dir, p) { |
197 | if (p->is_supply || p->weak || !p->connect) | 201 | if (p->is_supply || p->weak || !p->connect) |
198 | continue; | 202 | continue; |
199 | sink = p->sink; | 203 | node = p->node[rdir]; |
200 | if (sink->inputs != -1) { | 204 | if (node->endpoints[dir] != -1) { |
201 | sink->inputs = -1; | 205 | node->endpoints[dir] = -1; |
202 | list_add_tail(&sink->work_list, &list); | 206 | list_add_tail(&node->work_list, &list); |
203 | } | 207 | } |
204 | } | 208 | } |
205 | } | 209 | } |
206 | } | 210 | } |
207 | 211 | ||
208 | /* | 212 | /* |
213 | * dapm_widget_invalidate_input_paths() - Invalidate the cached number of | ||
214 | * input paths | ||
215 | * @w: The widget for which to invalidate the cached number of input paths | ||
216 | * | ||
217 | * Resets the cached number of inputs for the specified widget and all widgets | ||
218 | * that can be reached via outcoming paths from the widget. | ||
219 | * | ||
220 | * This function must be called if the number of output paths for a widget might | ||
221 | * have changed. E.g. if the source state of a widget changes or a path is added | ||
222 | * or activated with the widget as the sink. | ||
223 | */ | ||
224 | static void dapm_widget_invalidate_input_paths(struct snd_soc_dapm_widget *w) | ||
225 | { | ||
226 | dapm_widget_invalidate_paths(w, SND_SOC_DAPM_DIR_IN); | ||
227 | } | ||
228 | |||
229 | /* | ||
209 | * dapm_widget_invalidate_output_paths() - Invalidate the cached number of | 230 | * dapm_widget_invalidate_output_paths() - Invalidate the cached number of |
210 | * output paths | 231 | * output paths |
211 | * @w: The widget for which to invalidate the cached number of output paths | 232 | * @w: The widget for which to invalidate the cached number of output paths |
@@ -219,29 +240,7 @@ static void dapm_widget_invalidate_input_paths(struct snd_soc_dapm_widget *w) | |||
219 | */ | 240 | */ |
220 | static void dapm_widget_invalidate_output_paths(struct snd_soc_dapm_widget *w) | 241 | static void dapm_widget_invalidate_output_paths(struct snd_soc_dapm_widget *w) |
221 | { | 242 | { |
222 | struct snd_soc_dapm_widget *source; | 243 | dapm_widget_invalidate_paths(w, SND_SOC_DAPM_DIR_OUT); |
223 | struct snd_soc_dapm_path *p; | ||
224 | LIST_HEAD(list); | ||
225 | |||
226 | dapm_assert_locked(w->dapm); | ||
227 | |||
228 | if (w->outputs == -1) | ||
229 | return; | ||
230 | |||
231 | w->outputs = -1; | ||
232 | list_add_tail(&w->work_list, &list); | ||
233 | |||
234 | list_for_each_entry(w, &list, work_list) { | ||
235 | list_for_each_entry(p, &w->sources, list_sink) { | ||
236 | if (p->is_supply || p->weak || !p->connect) | ||
237 | continue; | ||
238 | source = p->source; | ||
239 | if (source->outputs != -1) { | ||
240 | source->outputs = -1; | ||
241 | list_add_tail(&source->work_list, &list); | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | } | 244 | } |
246 | 245 | ||
247 | /* | 246 | /* |
@@ -270,9 +269,9 @@ static void dapm_path_invalidate(struct snd_soc_dapm_path *p) | |||
270 | * endpoints is either connected or disconnected that sum won't change, | 269 | * endpoints is either connected or disconnected that sum won't change, |
271 | * so there is no need to re-check the path. | 270 | * so there is no need to re-check the path. |
272 | */ | 271 | */ |
273 | if (p->source->inputs != 0) | 272 | if (p->source->endpoints[SND_SOC_DAPM_DIR_IN] != 0) |
274 | dapm_widget_invalidate_input_paths(p->sink); | 273 | dapm_widget_invalidate_input_paths(p->sink); |
275 | if (p->sink->outputs != 0) | 274 | if (p->sink->endpoints[SND_SOC_DAPM_DIR_OUT] != 0) |
276 | dapm_widget_invalidate_output_paths(p->source); | 275 | dapm_widget_invalidate_output_paths(p->source); |
277 | } | 276 | } |
278 | 277 | ||
@@ -283,11 +282,11 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card) | |||
283 | mutex_lock(&card->dapm_mutex); | 282 | mutex_lock(&card->dapm_mutex); |
284 | 283 | ||
285 | list_for_each_entry(w, &card->widgets, list) { | 284 | list_for_each_entry(w, &card->widgets, list) { |
286 | if (w->is_sink || w->is_source) { | 285 | if (w->is_ep) { |
287 | dapm_mark_dirty(w, "Rechecking endpoints"); | 286 | dapm_mark_dirty(w, "Rechecking endpoints"); |
288 | if (w->is_sink) | 287 | if (w->is_ep & SND_SOC_DAPM_EP_SINK) |
289 | dapm_widget_invalidate_output_paths(w); | 288 | dapm_widget_invalidate_output_paths(w); |
290 | if (w->is_source) | 289 | if (w->is_ep & SND_SOC_DAPM_EP_SOURCE) |
291 | dapm_widget_invalidate_input_paths(w); | 290 | dapm_widget_invalidate_input_paths(w); |
292 | } | 291 | } |
293 | } | 292 | } |
@@ -894,7 +893,7 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w) | |||
894 | /* add kcontrol */ | 893 | /* add kcontrol */ |
895 | for (i = 0; i < w->num_kcontrols; i++) { | 894 | for (i = 0; i < w->num_kcontrols; i++) { |
896 | /* match name */ | 895 | /* match name */ |
897 | list_for_each_entry(path, &w->sources, list_sink) { | 896 | snd_soc_dapm_widget_for_each_source_path(w, path) { |
898 | /* mixer/mux paths name must match control name */ | 897 | /* mixer/mux paths name must match control name */ |
899 | if (path->name != (char *)w->kcontrol_news[i].name) | 898 | if (path->name != (char *)w->kcontrol_news[i].name) |
900 | continue; | 899 | continue; |
@@ -923,18 +922,18 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w) | |||
923 | static int dapm_new_mux(struct snd_soc_dapm_widget *w) | 922 | static int dapm_new_mux(struct snd_soc_dapm_widget *w) |
924 | { | 923 | { |
925 | struct snd_soc_dapm_context *dapm = w->dapm; | 924 | struct snd_soc_dapm_context *dapm = w->dapm; |
925 | enum snd_soc_dapm_direction dir; | ||
926 | struct snd_soc_dapm_path *path; | 926 | struct snd_soc_dapm_path *path; |
927 | struct list_head *paths; | ||
928 | const char *type; | 927 | const char *type; |
929 | int ret; | 928 | int ret; |
930 | 929 | ||
931 | switch (w->id) { | 930 | switch (w->id) { |
932 | case snd_soc_dapm_mux: | 931 | case snd_soc_dapm_mux: |
933 | paths = &w->sources; | 932 | dir = SND_SOC_DAPM_DIR_OUT; |
934 | type = "mux"; | 933 | type = "mux"; |
935 | break; | 934 | break; |
936 | case snd_soc_dapm_demux: | 935 | case snd_soc_dapm_demux: |
937 | paths = &w->sinks; | 936 | dir = SND_SOC_DAPM_DIR_IN; |
938 | type = "demux"; | 937 | type = "demux"; |
939 | break; | 938 | break; |
940 | default: | 939 | default: |
@@ -948,7 +947,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) | |||
948 | return -EINVAL; | 947 | return -EINVAL; |
949 | } | 948 | } |
950 | 949 | ||
951 | if (list_empty(paths)) { | 950 | if (list_empty(&w->edges[dir])) { |
952 | dev_err(dapm->dev, "ASoC: %s %s has no paths\n", type, w->name); | 951 | dev_err(dapm->dev, "ASoC: %s %s has no paths\n", type, w->name); |
953 | return -EINVAL; | 952 | return -EINVAL; |
954 | } | 953 | } |
@@ -957,16 +956,9 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) | |||
957 | if (ret < 0) | 956 | if (ret < 0) |
958 | return ret; | 957 | return ret; |
959 | 958 | ||
960 | if (w->id == snd_soc_dapm_mux) { | 959 | snd_soc_dapm_widget_for_each_path(w, dir, path) { |
961 | list_for_each_entry(path, &w->sources, list_sink) { | 960 | if (path->name) |
962 | if (path->name) | 961 | dapm_kcontrol_add_path(w->kcontrols[0], path); |
963 | dapm_kcontrol_add_path(w->kcontrols[0], path); | ||
964 | } | ||
965 | } else { | ||
966 | list_for_each_entry(path, &w->sinks, list_source) { | ||
967 | if (path->name) | ||
968 | dapm_kcontrol_add_path(w->kcontrols[0], path); | ||
969 | } | ||
970 | } | 962 | } |
971 | 963 | ||
972 | return 0; | 964 | return 0; |
@@ -1032,66 +1024,59 @@ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) | |||
1032 | } | 1024 | } |
1033 | } | 1025 | } |
1034 | 1026 | ||
1035 | /* add widget to list if it's not already in the list */ | 1027 | static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list, |
1036 | static int dapm_list_add_widget(struct snd_soc_dapm_widget_list **list, | 1028 | struct list_head *widgets) |
1037 | struct snd_soc_dapm_widget *w) | ||
1038 | { | 1029 | { |
1039 | struct snd_soc_dapm_widget_list *wlist; | 1030 | struct snd_soc_dapm_widget *w; |
1040 | int wlistsize, wlistentries, i; | 1031 | struct list_head *it; |
1041 | 1032 | unsigned int size = 0; | |
1042 | if (*list == NULL) | 1033 | unsigned int i = 0; |
1043 | return -EINVAL; | ||
1044 | |||
1045 | wlist = *list; | ||
1046 | 1034 | ||
1047 | /* is this widget already in the list */ | 1035 | list_for_each(it, widgets) |
1048 | for (i = 0; i < wlist->num_widgets; i++) { | 1036 | size++; |
1049 | if (wlist->widgets[i] == w) | ||
1050 | return 0; | ||
1051 | } | ||
1052 | 1037 | ||
1053 | /* allocate some new space */ | 1038 | *list = kzalloc(sizeof(**list) + size * sizeof(*w), GFP_KERNEL); |
1054 | wlistentries = wlist->num_widgets + 1; | 1039 | if (*list == NULL) |
1055 | wlistsize = sizeof(struct snd_soc_dapm_widget_list) + | ||
1056 | wlistentries * sizeof(struct snd_soc_dapm_widget *); | ||
1057 | *list = krealloc(wlist, wlistsize, GFP_KERNEL); | ||
1058 | if (*list == NULL) { | ||
1059 | dev_err(w->dapm->dev, "ASoC: can't allocate widget list for %s\n", | ||
1060 | w->name); | ||
1061 | return -ENOMEM; | 1040 | return -ENOMEM; |
1062 | } | ||
1063 | wlist = *list; | ||
1064 | 1041 | ||
1065 | /* insert the widget */ | 1042 | list_for_each_entry(w, widgets, work_list) |
1066 | dev_dbg(w->dapm->dev, "ASoC: added %s in widget list pos %d\n", | 1043 | (*list)->widgets[i++] = w; |
1067 | w->name, wlist->num_widgets); | ||
1068 | 1044 | ||
1069 | wlist->widgets[wlist->num_widgets] = w; | 1045 | (*list)->num_widgets = i; |
1070 | wlist->num_widgets++; | 1046 | |
1071 | return 1; | 1047 | return 0; |
1072 | } | 1048 | } |
1073 | 1049 | ||
1074 | /* | 1050 | /* |
1075 | * Recursively check for a completed path to an active or physically connected | 1051 | * Common implementation for is_connected_output_ep() and |
1076 | * output widget. Returns number of complete paths. | 1052 | * is_connected_input_ep(). The function is inlined since the combined size of |
1053 | * the two specialized functions is only marginally larger then the size of the | ||
1054 | * generic function and at the same time the fast path of the specialized | ||
1055 | * functions is significantly smaller than the generic function. | ||
1077 | */ | 1056 | */ |
1078 | static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, | 1057 | static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget, |
1079 | struct snd_soc_dapm_widget_list **list) | 1058 | struct list_head *list, enum snd_soc_dapm_direction dir, |
1059 | int (*fn)(struct snd_soc_dapm_widget *, struct list_head *)) | ||
1080 | { | 1060 | { |
1061 | enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir); | ||
1081 | struct snd_soc_dapm_path *path; | 1062 | struct snd_soc_dapm_path *path; |
1082 | int con = 0; | 1063 | int con = 0; |
1083 | 1064 | ||
1084 | if (widget->outputs >= 0) | 1065 | if (widget->endpoints[dir] >= 0) |
1085 | return widget->outputs; | 1066 | return widget->endpoints[dir]; |
1086 | 1067 | ||
1087 | DAPM_UPDATE_STAT(widget, path_checks); | 1068 | DAPM_UPDATE_STAT(widget, path_checks); |
1088 | 1069 | ||
1089 | if (widget->is_sink && widget->connected) { | 1070 | /* do we need to add this widget to the list ? */ |
1090 | widget->outputs = snd_soc_dapm_suspend_check(widget); | 1071 | if (list) |
1091 | return widget->outputs; | 1072 | list_add_tail(&widget->work_list, list); |
1073 | |||
1074 | if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) { | ||
1075 | widget->endpoints[dir] = snd_soc_dapm_suspend_check(widget); | ||
1076 | return widget->endpoints[dir]; | ||
1092 | } | 1077 | } |
1093 | 1078 | ||
1094 | list_for_each_entry(path, &widget->sinks, list_source) { | 1079 | snd_soc_dapm_widget_for_each_path(widget, rdir, path) { |
1095 | DAPM_UPDATE_STAT(widget, neighbour_checks); | 1080 | DAPM_UPDATE_STAT(widget, neighbour_checks); |
1096 | 1081 | ||
1097 | if (path->weak || path->is_supply) | 1082 | if (path->weak || path->is_supply) |
@@ -1100,91 +1085,40 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, | |||
1100 | if (path->walking) | 1085 | if (path->walking) |
1101 | return 1; | 1086 | return 1; |
1102 | 1087 | ||
1103 | trace_snd_soc_dapm_output_path(widget, path); | 1088 | trace_snd_soc_dapm_path(widget, dir, path); |
1104 | 1089 | ||
1105 | if (path->connect) { | 1090 | if (path->connect) { |
1106 | path->walking = 1; | 1091 | path->walking = 1; |
1107 | 1092 | con += fn(path->node[dir], list); | |
1108 | /* do we need to add this widget to the list ? */ | ||
1109 | if (list) { | ||
1110 | int err; | ||
1111 | err = dapm_list_add_widget(list, path->sink); | ||
1112 | if (err < 0) { | ||
1113 | dev_err(widget->dapm->dev, | ||
1114 | "ASoC: could not add widget %s\n", | ||
1115 | widget->name); | ||
1116 | path->walking = 0; | ||
1117 | return con; | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1121 | con += is_connected_output_ep(path->sink, list); | ||
1122 | |||
1123 | path->walking = 0; | 1093 | path->walking = 0; |
1124 | } | 1094 | } |
1125 | } | 1095 | } |
1126 | 1096 | ||
1127 | widget->outputs = con; | 1097 | widget->endpoints[dir] = con; |
1128 | 1098 | ||
1129 | return con; | 1099 | return con; |
1130 | } | 1100 | } |
1131 | 1101 | ||
1132 | /* | 1102 | /* |
1133 | * Recursively check for a completed path to an active or physically connected | 1103 | * Recursively check for a completed path to an active or physically connected |
1104 | * output widget. Returns number of complete paths. | ||
1105 | */ | ||
1106 | static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, | ||
1107 | struct list_head *list) | ||
1108 | { | ||
1109 | return is_connected_ep(widget, list, SND_SOC_DAPM_DIR_OUT, | ||
1110 | is_connected_output_ep); | ||
1111 | } | ||
1112 | |||
1113 | /* | ||
1114 | * Recursively check for a completed path to an active or physically connected | ||
1134 | * input widget. Returns number of complete paths. | 1115 | * input widget. Returns number of complete paths. |
1135 | */ | 1116 | */ |
1136 | static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, | 1117 | static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, |
1137 | struct snd_soc_dapm_widget_list **list) | 1118 | struct list_head *list) |
1138 | { | 1119 | { |
1139 | struct snd_soc_dapm_path *path; | 1120 | return is_connected_ep(widget, list, SND_SOC_DAPM_DIR_IN, |
1140 | int con = 0; | 1121 | is_connected_input_ep); |
1141 | |||
1142 | if (widget->inputs >= 0) | ||
1143 | return widget->inputs; | ||
1144 | |||
1145 | DAPM_UPDATE_STAT(widget, path_checks); | ||
1146 | |||
1147 | if (widget->is_source && widget->connected) { | ||
1148 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
1149 | return widget->inputs; | ||
1150 | } | ||
1151 | |||
1152 | list_for_each_entry(path, &widget->sources, list_sink) { | ||
1153 | DAPM_UPDATE_STAT(widget, neighbour_checks); | ||
1154 | |||
1155 | if (path->weak || path->is_supply) | ||
1156 | continue; | ||
1157 | |||
1158 | if (path->walking) | ||
1159 | return 1; | ||
1160 | |||
1161 | trace_snd_soc_dapm_input_path(widget, path); | ||
1162 | |||
1163 | if (path->connect) { | ||
1164 | path->walking = 1; | ||
1165 | |||
1166 | /* do we need to add this widget to the list ? */ | ||
1167 | if (list) { | ||
1168 | int err; | ||
1169 | err = dapm_list_add_widget(list, path->source); | ||
1170 | if (err < 0) { | ||
1171 | dev_err(widget->dapm->dev, | ||
1172 | "ASoC: could not add widget %s\n", | ||
1173 | widget->name); | ||
1174 | path->walking = 0; | ||
1175 | return con; | ||
1176 | } | ||
1177 | } | ||
1178 | |||
1179 | con += is_connected_input_ep(path->source, list); | ||
1180 | |||
1181 | path->walking = 0; | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1185 | widget->inputs = con; | ||
1186 | |||
1187 | return con; | ||
1188 | } | 1122 | } |
1189 | 1123 | ||
1190 | /** | 1124 | /** |
@@ -1204,7 +1138,9 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, | |||
1204 | { | 1138 | { |
1205 | struct snd_soc_card *card = dai->component->card; | 1139 | struct snd_soc_card *card = dai->component->card; |
1206 | struct snd_soc_dapm_widget *w; | 1140 | struct snd_soc_dapm_widget *w; |
1141 | LIST_HEAD(widgets); | ||
1207 | int paths; | 1142 | int paths; |
1143 | int ret; | ||
1208 | 1144 | ||
1209 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 1145 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
1210 | 1146 | ||
@@ -1213,14 +1149,21 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, | |||
1213 | * to reset the cached number of inputs and outputs. | 1149 | * to reset the cached number of inputs and outputs. |
1214 | */ | 1150 | */ |
1215 | list_for_each_entry(w, &card->widgets, list) { | 1151 | list_for_each_entry(w, &card->widgets, list) { |
1216 | w->inputs = -1; | 1152 | w->endpoints[SND_SOC_DAPM_DIR_IN] = -1; |
1217 | w->outputs = -1; | 1153 | w->endpoints[SND_SOC_DAPM_DIR_OUT] = -1; |
1218 | } | 1154 | } |
1219 | 1155 | ||
1220 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 1156 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
1221 | paths = is_connected_output_ep(dai->playback_widget, list); | 1157 | paths = is_connected_output_ep(dai->playback_widget, &widgets); |
1222 | else | 1158 | else |
1223 | paths = is_connected_input_ep(dai->capture_widget, list); | 1159 | paths = is_connected_input_ep(dai->capture_widget, &widgets); |
1160 | |||
1161 | /* Drop starting point */ | ||
1162 | list_del(widgets.next); | ||
1163 | |||
1164 | ret = dapm_widget_list_create(list, &widgets); | ||
1165 | if (ret) | ||
1166 | paths = ret; | ||
1224 | 1167 | ||
1225 | trace_snd_soc_dapm_connected(paths, stream); | 1168 | trace_snd_soc_dapm_connected(paths, stream); |
1226 | mutex_unlock(&card->dapm_mutex); | 1169 | mutex_unlock(&card->dapm_mutex); |
@@ -1321,7 +1264,7 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | |||
1321 | DAPM_UPDATE_STAT(w, power_checks); | 1264 | DAPM_UPDATE_STAT(w, power_checks); |
1322 | 1265 | ||
1323 | /* Check if one of our outputs is connected */ | 1266 | /* Check if one of our outputs is connected */ |
1324 | list_for_each_entry(path, &w->sinks, list_source) { | 1267 | snd_soc_dapm_widget_for_each_sink_path(w, path) { |
1325 | DAPM_UPDATE_STAT(w, neighbour_checks); | 1268 | DAPM_UPDATE_STAT(w, neighbour_checks); |
1326 | 1269 | ||
1327 | if (path->weak) | 1270 | if (path->weak) |
@@ -1745,12 +1688,12 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, | |||
1745 | /* If we changed our power state perhaps our neigbours changed | 1688 | /* If we changed our power state perhaps our neigbours changed |
1746 | * also. | 1689 | * also. |
1747 | */ | 1690 | */ |
1748 | list_for_each_entry(path, &w->sources, list_sink) | 1691 | snd_soc_dapm_widget_for_each_source_path(w, path) |
1749 | dapm_widget_set_peer_power(path->source, power, path->connect); | 1692 | dapm_widget_set_peer_power(path->source, power, path->connect); |
1750 | 1693 | ||
1751 | /* Supplies can't affect their outputs, only their inputs */ | 1694 | /* Supplies can't affect their outputs, only their inputs */ |
1752 | if (!w->is_supply) { | 1695 | if (!w->is_supply) { |
1753 | list_for_each_entry(path, &w->sinks, list_source) | 1696 | snd_soc_dapm_widget_for_each_sink_path(w, path) |
1754 | dapm_widget_set_peer_power(path->sink, power, | 1697 | dapm_widget_set_peer_power(path->sink, power, |
1755 | path->connect); | 1698 | path->connect); |
1756 | } | 1699 | } |
@@ -1951,6 +1894,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1951 | { | 1894 | { |
1952 | struct snd_soc_dapm_widget *w = file->private_data; | 1895 | struct snd_soc_dapm_widget *w = file->private_data; |
1953 | struct snd_soc_card *card = w->dapm->card; | 1896 | struct snd_soc_card *card = w->dapm->card; |
1897 | enum snd_soc_dapm_direction dir, rdir; | ||
1954 | char *buf; | 1898 | char *buf; |
1955 | int in, out; | 1899 | int in, out; |
1956 | ssize_t ret; | 1900 | ssize_t ret; |
@@ -1987,25 +1931,21 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1987 | w->sname, | 1931 | w->sname, |
1988 | w->active ? "active" : "inactive"); | 1932 | w->active ? "active" : "inactive"); |
1989 | 1933 | ||
1990 | list_for_each_entry(p, &w->sources, list_sink) { | 1934 | snd_soc_dapm_for_each_direction(dir) { |
1991 | if (p->connected && !p->connected(w, p->source)) | 1935 | rdir = SND_SOC_DAPM_DIR_REVERSE(dir); |
1992 | continue; | 1936 | snd_soc_dapm_widget_for_each_path(w, dir, p) { |
1937 | if (p->connected && !p->connected(w, p->node[rdir])) | ||
1938 | continue; | ||
1993 | 1939 | ||
1994 | if (p->connect) | 1940 | if (!p->connect) |
1995 | ret += snprintf(buf + ret, PAGE_SIZE - ret, | 1941 | continue; |
1996 | " in \"%s\" \"%s\"\n", | ||
1997 | p->name ? p->name : "static", | ||
1998 | p->source->name); | ||
1999 | } | ||
2000 | list_for_each_entry(p, &w->sinks, list_source) { | ||
2001 | if (p->connected && !p->connected(w, p->sink)) | ||
2002 | continue; | ||
2003 | 1942 | ||
2004 | if (p->connect) | ||
2005 | ret += snprintf(buf + ret, PAGE_SIZE - ret, | 1943 | ret += snprintf(buf + ret, PAGE_SIZE - ret, |
2006 | " out \"%s\" \"%s\"\n", | 1944 | " %s \"%s\" \"%s\"\n", |
1945 | (rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out", | ||
2007 | p->name ? p->name : "static", | 1946 | p->name ? p->name : "static", |
2008 | p->sink->name); | 1947 | p->node[rdir]->name); |
1948 | } | ||
2009 | } | 1949 | } |
2010 | 1950 | ||
2011 | mutex_unlock(&card->dapm_mutex); | 1951 | mutex_unlock(&card->dapm_mutex); |
@@ -2223,14 +2163,16 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, | |||
2223 | } | 2163 | } |
2224 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); | 2164 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); |
2225 | 2165 | ||
2226 | static ssize_t dapm_widget_show_codec(struct snd_soc_codec *codec, char *buf) | 2166 | static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt, |
2167 | char *buf) | ||
2227 | { | 2168 | { |
2169 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); | ||
2228 | struct snd_soc_dapm_widget *w; | 2170 | struct snd_soc_dapm_widget *w; |
2229 | int count = 0; | 2171 | int count = 0; |
2230 | char *state = "not set"; | 2172 | char *state = "not set"; |
2231 | 2173 | ||
2232 | list_for_each_entry(w, &codec->component.card->widgets, list) { | 2174 | list_for_each_entry(w, &cmpnt->card->widgets, list) { |
2233 | if (w->dapm != &codec->dapm) | 2175 | if (w->dapm != dapm) |
2234 | continue; | 2176 | continue; |
2235 | 2177 | ||
2236 | /* only display widgets that burnm power */ | 2178 | /* only display widgets that burnm power */ |
@@ -2258,7 +2200,7 @@ static ssize_t dapm_widget_show_codec(struct snd_soc_codec *codec, char *buf) | |||
2258 | } | 2200 | } |
2259 | } | 2201 | } |
2260 | 2202 | ||
2261 | switch (codec->dapm.bias_level) { | 2203 | switch (snd_soc_dapm_get_bias_level(dapm)) { |
2262 | case SND_SOC_BIAS_ON: | 2204 | case SND_SOC_BIAS_ON: |
2263 | state = "On"; | 2205 | state = "On"; |
2264 | break; | 2206 | break; |
@@ -2287,8 +2229,9 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
2287 | mutex_lock(&rtd->card->dapm_mutex); | 2229 | mutex_lock(&rtd->card->dapm_mutex); |
2288 | 2230 | ||
2289 | for (i = 0; i < rtd->num_codecs; i++) { | 2231 | for (i = 0; i < rtd->num_codecs; i++) { |
2290 | struct snd_soc_codec *codec = rtd->codec_dais[i]->codec; | 2232 | struct snd_soc_component *cmpnt = rtd->codec_dais[i]->component; |
2291 | count += dapm_widget_show_codec(codec, buf + count); | 2233 | |
2234 | count += dapm_widget_show_component(cmpnt, buf + count); | ||
2292 | } | 2235 | } |
2293 | 2236 | ||
2294 | mutex_unlock(&rtd->card->dapm_mutex); | 2237 | mutex_unlock(&rtd->card->dapm_mutex); |
@@ -2305,37 +2248,43 @@ struct attribute *soc_dapm_dev_attrs[] = { | |||
2305 | 2248 | ||
2306 | static void dapm_free_path(struct snd_soc_dapm_path *path) | 2249 | static void dapm_free_path(struct snd_soc_dapm_path *path) |
2307 | { | 2250 | { |
2308 | list_del(&path->list_sink); | 2251 | list_del(&path->list_node[SND_SOC_DAPM_DIR_IN]); |
2309 | list_del(&path->list_source); | 2252 | list_del(&path->list_node[SND_SOC_DAPM_DIR_OUT]); |
2310 | list_del(&path->list_kcontrol); | 2253 | list_del(&path->list_kcontrol); |
2311 | list_del(&path->list); | 2254 | list_del(&path->list); |
2312 | kfree(path); | 2255 | kfree(path); |
2313 | } | 2256 | } |
2314 | 2257 | ||
2258 | void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w) | ||
2259 | { | ||
2260 | struct snd_soc_dapm_path *p, *next_p; | ||
2261 | enum snd_soc_dapm_direction dir; | ||
2262 | |||
2263 | list_del(&w->list); | ||
2264 | /* | ||
2265 | * remove source and sink paths associated to this widget. | ||
2266 | * While removing the path, remove reference to it from both | ||
2267 | * source and sink widgets so that path is removed only once. | ||
2268 | */ | ||
2269 | snd_soc_dapm_for_each_direction(dir) { | ||
2270 | snd_soc_dapm_widget_for_each_path_safe(w, dir, p, next_p) | ||
2271 | dapm_free_path(p); | ||
2272 | } | ||
2273 | |||
2274 | kfree(w->kcontrols); | ||
2275 | kfree_const(w->name); | ||
2276 | kfree(w); | ||
2277 | } | ||
2278 | |||
2315 | /* free all dapm widgets and resources */ | 2279 | /* free all dapm widgets and resources */ |
2316 | static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) | 2280 | static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) |
2317 | { | 2281 | { |
2318 | struct snd_soc_dapm_widget *w, *next_w; | 2282 | struct snd_soc_dapm_widget *w, *next_w; |
2319 | struct snd_soc_dapm_path *p, *next_p; | ||
2320 | 2283 | ||
2321 | list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { | 2284 | list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { |
2322 | if (w->dapm != dapm) | 2285 | if (w->dapm != dapm) |
2323 | continue; | 2286 | continue; |
2324 | list_del(&w->list); | 2287 | snd_soc_dapm_free_widget(w); |
2325 | /* | ||
2326 | * remove source and sink paths associated to this widget. | ||
2327 | * While removing the path, remove reference to it from both | ||
2328 | * source and sink widgets so that path is removed only once. | ||
2329 | */ | ||
2330 | list_for_each_entry_safe(p, next_p, &w->sources, list_sink) | ||
2331 | dapm_free_path(p); | ||
2332 | |||
2333 | list_for_each_entry_safe(p, next_p, &w->sinks, list_source) | ||
2334 | dapm_free_path(p); | ||
2335 | |||
2336 | kfree(w->kcontrols); | ||
2337 | kfree(w->name); | ||
2338 | kfree(w); | ||
2339 | } | 2288 | } |
2340 | } | 2289 | } |
2341 | 2290 | ||
@@ -2441,20 +2390,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); | |||
2441 | */ | 2390 | */ |
2442 | static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w) | 2391 | static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w) |
2443 | { | 2392 | { |
2393 | enum snd_soc_dapm_direction dir; | ||
2444 | struct snd_soc_dapm_path *p; | 2394 | struct snd_soc_dapm_path *p; |
2395 | unsigned int ep; | ||
2445 | 2396 | ||
2446 | switch (w->id) { | 2397 | switch (w->id) { |
2447 | case snd_soc_dapm_input: | 2398 | case snd_soc_dapm_input: |
2448 | /* On a fully routed card a input is never a source */ | 2399 | /* On a fully routed card a input is never a source */ |
2449 | if (w->dapm->card->fully_routed) | 2400 | if (w->dapm->card->fully_routed) |
2450 | break; | 2401 | return; |
2451 | w->is_source = 1; | 2402 | ep = SND_SOC_DAPM_EP_SOURCE; |
2452 | list_for_each_entry(p, &w->sources, list_sink) { | 2403 | snd_soc_dapm_widget_for_each_source_path(w, p) { |
2453 | if (p->source->id == snd_soc_dapm_micbias || | 2404 | if (p->source->id == snd_soc_dapm_micbias || |
2454 | p->source->id == snd_soc_dapm_mic || | 2405 | p->source->id == snd_soc_dapm_mic || |
2455 | p->source->id == snd_soc_dapm_line || | 2406 | p->source->id == snd_soc_dapm_line || |
2456 | p->source->id == snd_soc_dapm_output) { | 2407 | p->source->id == snd_soc_dapm_output) { |
2457 | w->is_source = 0; | 2408 | ep = 0; |
2458 | break; | 2409 | break; |
2459 | } | 2410 | } |
2460 | } | 2411 | } |
@@ -2462,25 +2413,30 @@ static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w) | |||
2462 | case snd_soc_dapm_output: | 2413 | case snd_soc_dapm_output: |
2463 | /* On a fully routed card a output is never a sink */ | 2414 | /* On a fully routed card a output is never a sink */ |
2464 | if (w->dapm->card->fully_routed) | 2415 | if (w->dapm->card->fully_routed) |
2465 | break; | 2416 | return; |
2466 | w->is_sink = 1; | 2417 | ep = SND_SOC_DAPM_EP_SINK; |
2467 | list_for_each_entry(p, &w->sinks, list_source) { | 2418 | snd_soc_dapm_widget_for_each_sink_path(w, p) { |
2468 | if (p->sink->id == snd_soc_dapm_spk || | 2419 | if (p->sink->id == snd_soc_dapm_spk || |
2469 | p->sink->id == snd_soc_dapm_hp || | 2420 | p->sink->id == snd_soc_dapm_hp || |
2470 | p->sink->id == snd_soc_dapm_line || | 2421 | p->sink->id == snd_soc_dapm_line || |
2471 | p->sink->id == snd_soc_dapm_input) { | 2422 | p->sink->id == snd_soc_dapm_input) { |
2472 | w->is_sink = 0; | 2423 | ep = 0; |
2473 | break; | 2424 | break; |
2474 | } | 2425 | } |
2475 | } | 2426 | } |
2476 | break; | 2427 | break; |
2477 | case snd_soc_dapm_line: | 2428 | case snd_soc_dapm_line: |
2478 | w->is_sink = !list_empty(&w->sources); | 2429 | ep = 0; |
2479 | w->is_source = !list_empty(&w->sinks); | 2430 | snd_soc_dapm_for_each_direction(dir) { |
2431 | if (!list_empty(&w->edges[dir])) | ||
2432 | ep |= SND_SOC_DAPM_DIR_TO_EP(dir); | ||
2433 | } | ||
2480 | break; | 2434 | break; |
2481 | default: | 2435 | default: |
2482 | break; | 2436 | return; |
2483 | } | 2437 | } |
2438 | |||
2439 | w->is_ep = ep; | ||
2484 | } | 2440 | } |
2485 | 2441 | ||
2486 | static int snd_soc_dapm_check_dynamic_path(struct snd_soc_dapm_context *dapm, | 2442 | static int snd_soc_dapm_check_dynamic_path(struct snd_soc_dapm_context *dapm, |
@@ -2533,6 +2489,8 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2533 | int (*connected)(struct snd_soc_dapm_widget *source, | 2489 | int (*connected)(struct snd_soc_dapm_widget *source, |
2534 | struct snd_soc_dapm_widget *sink)) | 2490 | struct snd_soc_dapm_widget *sink)) |
2535 | { | 2491 | { |
2492 | struct snd_soc_dapm_widget *widgets[2]; | ||
2493 | enum snd_soc_dapm_direction dir; | ||
2536 | struct snd_soc_dapm_path *path; | 2494 | struct snd_soc_dapm_path *path; |
2537 | int ret; | 2495 | int ret; |
2538 | 2496 | ||
@@ -2565,13 +2523,14 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2565 | if (!path) | 2523 | if (!path) |
2566 | return -ENOMEM; | 2524 | return -ENOMEM; |
2567 | 2525 | ||
2568 | path->source = wsource; | 2526 | path->node[SND_SOC_DAPM_DIR_IN] = wsource; |
2569 | path->sink = wsink; | 2527 | path->node[SND_SOC_DAPM_DIR_OUT] = wsink; |
2528 | widgets[SND_SOC_DAPM_DIR_IN] = wsource; | ||
2529 | widgets[SND_SOC_DAPM_DIR_OUT] = wsink; | ||
2530 | |||
2570 | path->connected = connected; | 2531 | path->connected = connected; |
2571 | INIT_LIST_HEAD(&path->list); | 2532 | INIT_LIST_HEAD(&path->list); |
2572 | INIT_LIST_HEAD(&path->list_kcontrol); | 2533 | INIT_LIST_HEAD(&path->list_kcontrol); |
2573 | INIT_LIST_HEAD(&path->list_source); | ||
2574 | INIT_LIST_HEAD(&path->list_sink); | ||
2575 | 2534 | ||
2576 | if (wsource->is_supply || wsink->is_supply) | 2535 | if (wsource->is_supply || wsink->is_supply) |
2577 | path->is_supply = 1; | 2536 | path->is_supply = 1; |
@@ -2609,14 +2568,13 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2609 | } | 2568 | } |
2610 | 2569 | ||
2611 | list_add(&path->list, &dapm->card->paths); | 2570 | list_add(&path->list, &dapm->card->paths); |
2612 | list_add(&path->list_sink, &wsink->sources); | 2571 | snd_soc_dapm_for_each_direction(dir) |
2613 | list_add(&path->list_source, &wsource->sinks); | 2572 | list_add(&path->list_node[dir], &widgets[dir]->edges[dir]); |
2614 | |||
2615 | dapm_update_widget_flags(wsource); | ||
2616 | dapm_update_widget_flags(wsink); | ||
2617 | 2573 | ||
2618 | dapm_mark_dirty(wsource, "Route added"); | 2574 | snd_soc_dapm_for_each_direction(dir) { |
2619 | dapm_mark_dirty(wsink, "Route added"); | 2575 | dapm_update_widget_flags(widgets[dir]); |
2576 | dapm_mark_dirty(widgets[dir], "Route added"); | ||
2577 | } | ||
2620 | 2578 | ||
2621 | if (dapm->card->instantiated && path->connect) | 2579 | if (dapm->card->instantiated && path->connect) |
2622 | dapm_path_invalidate(path); | 2580 | dapm_path_invalidate(path); |
@@ -2864,7 +2822,7 @@ static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm, | |||
2864 | dev_warn(dapm->dev, "ASoC: Ignoring control for weak route %s->%s\n", | 2822 | dev_warn(dapm->dev, "ASoC: Ignoring control for weak route %s->%s\n", |
2865 | route->source, route->sink); | 2823 | route->source, route->sink); |
2866 | 2824 | ||
2867 | list_for_each_entry(path, &source->sinks, list_source) { | 2825 | snd_soc_dapm_widget_for_each_sink_path(source, path) { |
2868 | if (path->sink == sink) { | 2826 | if (path->sink == sink) { |
2869 | path->weak = 1; | 2827 | path->weak = 1; |
2870 | count++; | 2828 | count++; |
@@ -2918,7 +2876,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes); | |||
2918 | 2876 | ||
2919 | /** | 2877 | /** |
2920 | * snd_soc_dapm_new_widgets - add new dapm widgets | 2878 | * snd_soc_dapm_new_widgets - add new dapm widgets |
2921 | * @dapm: DAPM context | 2879 | * @card: card to be checked for new dapm widgets |
2922 | * | 2880 | * |
2923 | * Checks the codec for any new dapm widgets and creates them if found. | 2881 | * Checks the codec for any new dapm widgets and creates them if found. |
2924 | * | 2882 | * |
@@ -3298,6 +3256,7 @@ struct snd_soc_dapm_widget * | |||
3298 | snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | 3256 | snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, |
3299 | const struct snd_soc_dapm_widget *widget) | 3257 | const struct snd_soc_dapm_widget *widget) |
3300 | { | 3258 | { |
3259 | enum snd_soc_dapm_direction dir; | ||
3301 | struct snd_soc_dapm_widget *w; | 3260 | struct snd_soc_dapm_widget *w; |
3302 | const char *prefix; | 3261 | const char *prefix; |
3303 | int ret; | 3262 | int ret; |
@@ -3344,7 +3303,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | |||
3344 | if (prefix) | 3303 | if (prefix) |
3345 | w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name); | 3304 | w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name); |
3346 | else | 3305 | else |
3347 | w->name = kasprintf(GFP_KERNEL, "%s", widget->name); | 3306 | w->name = kstrdup_const(widget->name, GFP_KERNEL); |
3348 | if (w->name == NULL) { | 3307 | if (w->name == NULL) { |
3349 | kfree(w); | 3308 | kfree(w); |
3350 | return NULL; | 3309 | return NULL; |
@@ -3352,27 +3311,27 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | |||
3352 | 3311 | ||
3353 | switch (w->id) { | 3312 | switch (w->id) { |
3354 | case snd_soc_dapm_mic: | 3313 | case snd_soc_dapm_mic: |
3355 | w->is_source = 1; | 3314 | w->is_ep = SND_SOC_DAPM_EP_SOURCE; |
3356 | w->power_check = dapm_generic_check_power; | 3315 | w->power_check = dapm_generic_check_power; |
3357 | break; | 3316 | break; |
3358 | case snd_soc_dapm_input: | 3317 | case snd_soc_dapm_input: |
3359 | if (!dapm->card->fully_routed) | 3318 | if (!dapm->card->fully_routed) |
3360 | w->is_source = 1; | 3319 | w->is_ep = SND_SOC_DAPM_EP_SOURCE; |
3361 | w->power_check = dapm_generic_check_power; | 3320 | w->power_check = dapm_generic_check_power; |
3362 | break; | 3321 | break; |
3363 | case snd_soc_dapm_spk: | 3322 | case snd_soc_dapm_spk: |
3364 | case snd_soc_dapm_hp: | 3323 | case snd_soc_dapm_hp: |
3365 | w->is_sink = 1; | 3324 | w->is_ep = SND_SOC_DAPM_EP_SINK; |
3366 | w->power_check = dapm_generic_check_power; | 3325 | w->power_check = dapm_generic_check_power; |
3367 | break; | 3326 | break; |
3368 | case snd_soc_dapm_output: | 3327 | case snd_soc_dapm_output: |
3369 | if (!dapm->card->fully_routed) | 3328 | if (!dapm->card->fully_routed) |
3370 | w->is_sink = 1; | 3329 | w->is_ep = SND_SOC_DAPM_EP_SINK; |
3371 | w->power_check = dapm_generic_check_power; | 3330 | w->power_check = dapm_generic_check_power; |
3372 | break; | 3331 | break; |
3373 | case snd_soc_dapm_vmid: | 3332 | case snd_soc_dapm_vmid: |
3374 | case snd_soc_dapm_siggen: | 3333 | case snd_soc_dapm_siggen: |
3375 | w->is_source = 1; | 3334 | w->is_ep = SND_SOC_DAPM_EP_SOURCE; |
3376 | w->power_check = dapm_always_on_check_power; | 3335 | w->power_check = dapm_always_on_check_power; |
3377 | break; | 3336 | break; |
3378 | case snd_soc_dapm_mux: | 3337 | case snd_soc_dapm_mux: |
@@ -3406,14 +3365,14 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | |||
3406 | } | 3365 | } |
3407 | 3366 | ||
3408 | w->dapm = dapm; | 3367 | w->dapm = dapm; |
3409 | INIT_LIST_HEAD(&w->sources); | ||
3410 | INIT_LIST_HEAD(&w->sinks); | ||
3411 | INIT_LIST_HEAD(&w->list); | 3368 | INIT_LIST_HEAD(&w->list); |
3412 | INIT_LIST_HEAD(&w->dirty); | 3369 | INIT_LIST_HEAD(&w->dirty); |
3413 | list_add_tail(&w->list, &dapm->card->widgets); | 3370 | list_add_tail(&w->list, &dapm->card->widgets); |
3414 | 3371 | ||
3415 | w->inputs = -1; | 3372 | snd_soc_dapm_for_each_direction(dir) { |
3416 | w->outputs = -1; | 3373 | INIT_LIST_HEAD(&w->edges[dir]); |
3374 | w->endpoints[dir] = -1; | ||
3375 | } | ||
3417 | 3376 | ||
3418 | /* machine layer set ups unconnected pins and insertions */ | 3377 | /* machine layer set ups unconnected pins and insertions */ |
3419 | w->connected = 1; | 3378 | w->connected = 1; |
@@ -3467,19 +3426,17 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, | |||
3467 | int ret; | 3426 | int ret; |
3468 | 3427 | ||
3469 | if (WARN_ON(!config) || | 3428 | if (WARN_ON(!config) || |
3470 | WARN_ON(list_empty(&w->sources) || list_empty(&w->sinks))) | 3429 | WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || |
3430 | list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) | ||
3471 | return -EINVAL; | 3431 | return -EINVAL; |
3472 | 3432 | ||
3473 | /* We only support a single source and sink, pick the first */ | 3433 | /* We only support a single source and sink, pick the first */ |
3474 | source_p = list_first_entry(&w->sources, struct snd_soc_dapm_path, | 3434 | source_p = list_first_entry(&w->edges[SND_SOC_DAPM_DIR_OUT], |
3475 | list_sink); | 3435 | struct snd_soc_dapm_path, |
3476 | sink_p = list_first_entry(&w->sinks, struct snd_soc_dapm_path, | 3436 | list_node[SND_SOC_DAPM_DIR_OUT]); |
3477 | list_source); | 3437 | sink_p = list_first_entry(&w->edges[SND_SOC_DAPM_DIR_IN], |
3478 | 3438 | struct snd_soc_dapm_path, | |
3479 | if (WARN_ON(!source_p || !sink_p) || | 3439 | list_node[SND_SOC_DAPM_DIR_IN]); |
3480 | WARN_ON(!sink_p->source || !source_p->sink) || | ||
3481 | WARN_ON(!source_p->source || !sink_p->sink)) | ||
3482 | return -EINVAL; | ||
3483 | 3440 | ||
3484 | source = source_p->source->priv; | 3441 | source = source_p->source->priv; |
3485 | sink = sink_p->sink->priv; | 3442 | sink = sink_p->sink->priv; |
@@ -3821,11 +3778,6 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, | |||
3821 | for (i = 0; i < rtd->num_codecs; i++) { | 3778 | for (i = 0; i < rtd->num_codecs; i++) { |
3822 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | 3779 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; |
3823 | 3780 | ||
3824 | /* there is no point in connecting BE DAI links with dummies */ | ||
3825 | if (snd_soc_dai_is_dummy(codec_dai) || | ||
3826 | snd_soc_dai_is_dummy(cpu_dai)) | ||
3827 | continue; | ||
3828 | |||
3829 | /* connect BE DAI playback if widgets are valid */ | 3781 | /* connect BE DAI playback if widgets are valid */ |
3830 | if (codec_dai->playback_widget && cpu_dai->playback_widget) { | 3782 | if (codec_dai->playback_widget && cpu_dai->playback_widget) { |
3831 | source = cpu_dai->playback_widget; | 3783 | source = cpu_dai->playback_widget; |
@@ -3856,6 +3808,7 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, | |||
3856 | int event) | 3808 | int event) |
3857 | { | 3809 | { |
3858 | struct snd_soc_dapm_widget *w; | 3810 | struct snd_soc_dapm_widget *w; |
3811 | unsigned int ep; | ||
3859 | 3812 | ||
3860 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 3813 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
3861 | w = dai->playback_widget; | 3814 | w = dai->playback_widget; |
@@ -3865,12 +3818,22 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, | |||
3865 | if (w) { | 3818 | if (w) { |
3866 | dapm_mark_dirty(w, "stream event"); | 3819 | dapm_mark_dirty(w, "stream event"); |
3867 | 3820 | ||
3821 | if (w->id == snd_soc_dapm_dai_in) { | ||
3822 | ep = SND_SOC_DAPM_EP_SOURCE; | ||
3823 | dapm_widget_invalidate_input_paths(w); | ||
3824 | } else { | ||
3825 | ep = SND_SOC_DAPM_EP_SINK; | ||
3826 | dapm_widget_invalidate_output_paths(w); | ||
3827 | } | ||
3828 | |||
3868 | switch (event) { | 3829 | switch (event) { |
3869 | case SND_SOC_DAPM_STREAM_START: | 3830 | case SND_SOC_DAPM_STREAM_START: |
3870 | w->active = 1; | 3831 | w->active = 1; |
3832 | w->is_ep = ep; | ||
3871 | break; | 3833 | break; |
3872 | case SND_SOC_DAPM_STREAM_STOP: | 3834 | case SND_SOC_DAPM_STREAM_STOP: |
3873 | w->active = 0; | 3835 | w->active = 0; |
3836 | w->is_ep = 0; | ||
3874 | break; | 3837 | break; |
3875 | case SND_SOC_DAPM_STREAM_SUSPEND: | 3838 | case SND_SOC_DAPM_STREAM_SUSPEND: |
3876 | case SND_SOC_DAPM_STREAM_RESUME: | 3839 | case SND_SOC_DAPM_STREAM_RESUME: |
@@ -3878,14 +3841,6 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, | |||
3878 | case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: | 3841 | case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: |
3879 | break; | 3842 | break; |
3880 | } | 3843 | } |
3881 | |||
3882 | if (w->id == snd_soc_dapm_dai_in) { | ||
3883 | w->is_source = w->active; | ||
3884 | dapm_widget_invalidate_input_paths(w); | ||
3885 | } else { | ||
3886 | w->is_sink = w->active; | ||
3887 | dapm_widget_invalidate_output_paths(w); | ||
3888 | } | ||
3889 | } | 3844 | } |
3890 | } | 3845 | } |
3891 | 3846 | ||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 256b9c91aa94..70e4b9d8bdcd 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -1231,24 +1231,17 @@ static int widget_in_list(struct snd_soc_dapm_widget_list *list, | |||
1231 | } | 1231 | } |
1232 | 1232 | ||
1233 | int dpcm_path_get(struct snd_soc_pcm_runtime *fe, | 1233 | int dpcm_path_get(struct snd_soc_pcm_runtime *fe, |
1234 | int stream, struct snd_soc_dapm_widget_list **list_) | 1234 | int stream, struct snd_soc_dapm_widget_list **list) |
1235 | { | 1235 | { |
1236 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; | 1236 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; |
1237 | struct snd_soc_dapm_widget_list *list; | ||
1238 | int paths; | 1237 | int paths; |
1239 | 1238 | ||
1240 | list = kzalloc(sizeof(struct snd_soc_dapm_widget_list) + | ||
1241 | sizeof(struct snd_soc_dapm_widget *), GFP_KERNEL); | ||
1242 | if (list == NULL) | ||
1243 | return -ENOMEM; | ||
1244 | |||
1245 | /* get number of valid DAI paths and their widgets */ | 1239 | /* get number of valid DAI paths and their widgets */ |
1246 | paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list); | 1240 | paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list); |
1247 | 1241 | ||
1248 | dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths, | 1242 | dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths, |
1249 | stream ? "capture" : "playback"); | 1243 | stream ? "capture" : "playback"); |
1250 | 1244 | ||
1251 | *list_ = list; | ||
1252 | return paths; | 1245 | return paths; |
1253 | } | 1246 | } |
1254 | 1247 | ||
@@ -1306,7 +1299,12 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, | |||
1306 | 1299 | ||
1307 | switch (list->widgets[i]->id) { | 1300 | switch (list->widgets[i]->id) { |
1308 | case snd_soc_dapm_dai_in: | 1301 | case snd_soc_dapm_dai_in: |
1302 | if (stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
1303 | continue; | ||
1304 | break; | ||
1309 | case snd_soc_dapm_dai_out: | 1305 | case snd_soc_dapm_dai_out: |
1306 | if (stream != SNDRV_PCM_STREAM_CAPTURE) | ||
1307 | continue; | ||
1310 | break; | 1308 | break; |
1311 | default: | 1309 | default: |
1312 | continue; | 1310 | continue; |
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 31068b8f3db0..69d01cd925ce 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c | |||
@@ -45,12 +45,12 @@ | |||
45 | #define SOC_TPLG_PASS_VENDOR 1 | 45 | #define SOC_TPLG_PASS_VENDOR 1 |
46 | #define SOC_TPLG_PASS_MIXER 2 | 46 | #define SOC_TPLG_PASS_MIXER 2 |
47 | #define SOC_TPLG_PASS_WIDGET 3 | 47 | #define SOC_TPLG_PASS_WIDGET 3 |
48 | #define SOC_TPLG_PASS_GRAPH 4 | 48 | #define SOC_TPLG_PASS_PCM_DAI 4 |
49 | #define SOC_TPLG_PASS_PINS 5 | 49 | #define SOC_TPLG_PASS_GRAPH 5 |
50 | #define SOC_TPLG_PASS_PCM_DAI 6 | 50 | #define SOC_TPLG_PASS_PINS 6 |
51 | 51 | ||
52 | #define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST | 52 | #define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST |
53 | #define SOC_TPLG_PASS_END SOC_TPLG_PASS_PCM_DAI | 53 | #define SOC_TPLG_PASS_END SOC_TPLG_PASS_PINS |
54 | 54 | ||
55 | struct soc_tplg { | 55 | struct soc_tplg { |
56 | const struct firmware *fw; | 56 | const struct firmware *fw; |
@@ -66,10 +66,14 @@ struct soc_tplg { | |||
66 | u32 index; /* current block index */ | 66 | u32 index; /* current block index */ |
67 | u32 req_index; /* required index, only loaded/free matching blocks */ | 67 | u32 req_index; /* required index, only loaded/free matching blocks */ |
68 | 68 | ||
69 | /* kcontrol operations */ | 69 | /* vendor specific kcontrol operations */ |
70 | const struct snd_soc_tplg_kcontrol_ops *io_ops; | 70 | const struct snd_soc_tplg_kcontrol_ops *io_ops; |
71 | int io_ops_count; | 71 | int io_ops_count; |
72 | 72 | ||
73 | /* vendor specific bytes ext handlers, for TLV bytes controls */ | ||
74 | const struct snd_soc_tplg_bytes_ext_ops *bytes_ext_ops; | ||
75 | int bytes_ext_ops_count; | ||
76 | |||
73 | /* optional fw loading callbacks to component drivers */ | 77 | /* optional fw loading callbacks to component drivers */ |
74 | struct snd_soc_tplg_ops *ops; | 78 | struct snd_soc_tplg_ops *ops; |
75 | }; | 79 | }; |
@@ -508,38 +512,74 @@ static void remove_pcm_dai(struct snd_soc_component *comp, | |||
508 | /* bind a kcontrol to it's IO handlers */ | 512 | /* bind a kcontrol to it's IO handlers */ |
509 | static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr, | 513 | static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr, |
510 | struct snd_kcontrol_new *k, | 514 | struct snd_kcontrol_new *k, |
511 | const struct snd_soc_tplg_kcontrol_ops *ops, int num_ops, | 515 | const struct soc_tplg *tplg) |
512 | const struct snd_soc_tplg_kcontrol_ops *bops, int num_bops) | ||
513 | { | 516 | { |
514 | int i; | 517 | const struct snd_soc_tplg_kcontrol_ops *ops; |
518 | const struct snd_soc_tplg_bytes_ext_ops *ext_ops; | ||
519 | int num_ops, i; | ||
520 | |||
521 | if (hdr->ops.info == SND_SOC_TPLG_CTL_BYTES | ||
522 | && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER | ||
523 | && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | ||
524 | && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { | ||
525 | struct soc_bytes_ext *sbe; | ||
526 | struct snd_soc_tplg_bytes_control *be; | ||
527 | |||
528 | sbe = (struct soc_bytes_ext *)k->private_value; | ||
529 | be = container_of(hdr, struct snd_soc_tplg_bytes_control, hdr); | ||
530 | |||
531 | /* TLV bytes controls need standard kcontrol info handler, | ||
532 | * TLV callback and extended put/get handlers. | ||
533 | */ | ||
534 | k->info = snd_soc_bytes_info; | ||
535 | k->tlv.c = snd_soc_bytes_tlv_callback; | ||
536 | |||
537 | ext_ops = tplg->bytes_ext_ops; | ||
538 | num_ops = tplg->bytes_ext_ops_count; | ||
539 | for (i = 0; i < num_ops; i++) { | ||
540 | if (!sbe->put && ext_ops[i].id == be->ext_ops.put) | ||
541 | sbe->put = ext_ops[i].put; | ||
542 | if (!sbe->get && ext_ops[i].id == be->ext_ops.get) | ||
543 | sbe->get = ext_ops[i].get; | ||
544 | } | ||
515 | 545 | ||
516 | /* try and map standard kcontrols handler first */ | 546 | if (sbe->put && sbe->get) |
547 | return 0; | ||
548 | else | ||
549 | return -EINVAL; | ||
550 | } | ||
551 | |||
552 | /* try and map vendor specific kcontrol handlers first */ | ||
553 | ops = tplg->io_ops; | ||
554 | num_ops = tplg->io_ops_count; | ||
517 | for (i = 0; i < num_ops; i++) { | 555 | for (i = 0; i < num_ops; i++) { |
518 | 556 | ||
519 | if (ops[i].id == hdr->ops.put) | 557 | if (k->put == NULL && ops[i].id == hdr->ops.put) |
520 | k->put = ops[i].put; | 558 | k->put = ops[i].put; |
521 | if (ops[i].id == hdr->ops.get) | 559 | if (k->get == NULL && ops[i].id == hdr->ops.get) |
522 | k->get = ops[i].get; | 560 | k->get = ops[i].get; |
523 | if (ops[i].id == hdr->ops.info) | 561 | if (k->info == NULL && ops[i].id == hdr->ops.info) |
524 | k->info = ops[i].info; | 562 | k->info = ops[i].info; |
525 | } | 563 | } |
526 | 564 | ||
527 | /* standard handlers found ? */ | 565 | /* vendor specific handlers found ? */ |
528 | if (k->put && k->get && k->info) | 566 | if (k->put && k->get && k->info) |
529 | return 0; | 567 | return 0; |
530 | 568 | ||
531 | /* none found so try bespoke handlers */ | 569 | /* none found so try standard kcontrol handlers */ |
532 | for (i = 0; i < num_bops; i++) { | 570 | ops = io_ops; |
571 | num_ops = ARRAY_SIZE(io_ops); | ||
572 | for (i = 0; i < num_ops; i++) { | ||
533 | 573 | ||
534 | if (k->put == NULL && bops[i].id == hdr->ops.put) | 574 | if (k->put == NULL && ops[i].id == hdr->ops.put) |
535 | k->put = bops[i].put; | 575 | k->put = ops[i].put; |
536 | if (k->get == NULL && bops[i].id == hdr->ops.get) | 576 | if (k->get == NULL && ops[i].id == hdr->ops.get) |
537 | k->get = bops[i].get; | 577 | k->get = ops[i].get; |
538 | if (k->info == NULL && bops[i].id == hdr->ops.info) | 578 | if (k->info == NULL && ops[i].id == hdr->ops.info) |
539 | k->info = bops[i].info; | 579 | k->info = ops[i].info; |
540 | } | 580 | } |
541 | 581 | ||
542 | /* bespoke handlers found ? */ | 582 | /* standard handlers found ? */ |
543 | if (k->put && k->get && k->info) | 583 | if (k->put && k->get && k->info) |
544 | return 0; | 584 | return 0; |
545 | 585 | ||
@@ -609,9 +649,7 @@ static int soc_tplg_create_tlv(struct soc_tplg *tplg, | |||
609 | if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)) | 649 | if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)) |
610 | return 0; | 650 | return 0; |
611 | 651 | ||
612 | if (tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { | 652 | if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) { |
613 | kc->tlv.c = snd_soc_bytes_tlv_callback; | ||
614 | } else { | ||
615 | tplg_tlv = &tc->tlv; | 653 | tplg_tlv = &tc->tlv; |
616 | switch (tplg_tlv->type) { | 654 | switch (tplg_tlv->type) { |
617 | case SNDRV_CTL_TLVT_DB_SCALE: | 655 | case SNDRV_CTL_TLVT_DB_SCALE: |
@@ -682,8 +720,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, | |||
682 | INIT_LIST_HEAD(&sbe->dobj.list); | 720 | INIT_LIST_HEAD(&sbe->dobj.list); |
683 | 721 | ||
684 | /* map io handlers */ | 722 | /* map io handlers */ |
685 | err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, io_ops, | 723 | err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg); |
686 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
687 | if (err) { | 724 | if (err) { |
688 | soc_control_err(tplg, &be->hdr, be->hdr.name); | 725 | soc_control_err(tplg, &be->hdr, be->hdr.name); |
689 | kfree(sbe); | 726 | kfree(sbe); |
@@ -777,8 +814,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, | |||
777 | INIT_LIST_HEAD(&sm->dobj.list); | 814 | INIT_LIST_HEAD(&sm->dobj.list); |
778 | 815 | ||
779 | /* map io handlers */ | 816 | /* map io handlers */ |
780 | err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, io_ops, | 817 | err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg); |
781 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
782 | if (err) { | 818 | if (err) { |
783 | soc_control_err(tplg, &mc->hdr, mc->hdr.name); | 819 | soc_control_err(tplg, &mc->hdr, mc->hdr.name); |
784 | kfree(sm); | 820 | kfree(sm); |
@@ -855,12 +891,12 @@ static int soc_tplg_denum_create_values(struct soc_enum *se, | |||
855 | if (ec->items > sizeof(*ec->values)) | 891 | if (ec->items > sizeof(*ec->values)) |
856 | return -EINVAL; | 892 | return -EINVAL; |
857 | 893 | ||
858 | se->dobj.control.dvalues = | 894 | se->dobj.control.dvalues = kmemdup(ec->values, |
859 | kmalloc(ec->items * sizeof(u32), GFP_KERNEL); | 895 | ec->items * sizeof(u32), |
896 | GFP_KERNEL); | ||
860 | if (!se->dobj.control.dvalues) | 897 | if (!se->dobj.control.dvalues) |
861 | return -ENOMEM; | 898 | return -ENOMEM; |
862 | 899 | ||
863 | memcpy(se->dobj.control.dvalues, ec->values, ec->items * sizeof(u32)); | ||
864 | return 0; | 900 | return 0; |
865 | } | 901 | } |
866 | 902 | ||
@@ -950,8 +986,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, | |||
950 | } | 986 | } |
951 | 987 | ||
952 | /* map io handlers */ | 988 | /* map io handlers */ |
953 | err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, io_ops, | 989 | err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg); |
954 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
955 | if (err) { | 990 | if (err) { |
956 | soc_control_err(tplg, &ec->hdr, ec->hdr.name); | 991 | soc_control_err(tplg, &ec->hdr, ec->hdr.name); |
957 | kfree(se); | 992 | kfree(se); |
@@ -1093,7 +1128,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( | |||
1093 | struct snd_soc_tplg_mixer_control *mc; | 1128 | struct snd_soc_tplg_mixer_control *mc; |
1094 | int i, err; | 1129 | int i, err; |
1095 | 1130 | ||
1096 | kc = kzalloc(sizeof(*kc) * num_kcontrols, GFP_KERNEL); | 1131 | kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL); |
1097 | if (kc == NULL) | 1132 | if (kc == NULL) |
1098 | return NULL; | 1133 | return NULL; |
1099 | 1134 | ||
@@ -1137,8 +1172,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( | |||
1137 | INIT_LIST_HEAD(&sm->dobj.list); | 1172 | INIT_LIST_HEAD(&sm->dobj.list); |
1138 | 1173 | ||
1139 | /* map io handlers */ | 1174 | /* map io handlers */ |
1140 | err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc[i], io_ops, | 1175 | err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc[i], tplg); |
1141 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
1142 | if (err) { | 1176 | if (err) { |
1143 | soc_control_err(tplg, &mc->hdr, mc->hdr.name); | 1177 | soc_control_err(tplg, &mc->hdr, mc->hdr.name); |
1144 | kfree(sm); | 1178 | kfree(sm); |
@@ -1235,8 +1269,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( | |||
1235 | } | 1269 | } |
1236 | 1270 | ||
1237 | /* map io handlers */ | 1271 | /* map io handlers */ |
1238 | err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, io_ops, | 1272 | err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg); |
1239 | ARRAY_SIZE(io_ops), tplg->io_ops, tplg->io_ops_count); | ||
1240 | if (err) { | 1273 | if (err) { |
1241 | soc_control_err(tplg, &ec->hdr, ec->hdr.name); | 1274 | soc_control_err(tplg, &ec->hdr, ec->hdr.name); |
1242 | goto err_se; | 1275 | goto err_se; |
@@ -1274,7 +1307,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( | |||
1274 | struct snd_kcontrol_new *kc; | 1307 | struct snd_kcontrol_new *kc; |
1275 | int i, err; | 1308 | int i, err; |
1276 | 1309 | ||
1277 | kc = kzalloc(sizeof(*kc) * count, GFP_KERNEL); | 1310 | kc = kcalloc(count, sizeof(*kc), GFP_KERNEL); |
1278 | if (!kc) | 1311 | if (!kc) |
1279 | return NULL; | 1312 | return NULL; |
1280 | 1313 | ||
@@ -1297,7 +1330,6 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( | |||
1297 | "ASoC: adding bytes kcontrol %s with access 0x%x\n", | 1330 | "ASoC: adding bytes kcontrol %s with access 0x%x\n", |
1298 | be->hdr.name, be->hdr.access); | 1331 | be->hdr.name, be->hdr.access); |
1299 | 1332 | ||
1300 | memset(kc, 0, sizeof(*kc)); | ||
1301 | kc[i].name = be->hdr.name; | 1333 | kc[i].name = be->hdr.name; |
1302 | kc[i].private_value = (long)sbe; | 1334 | kc[i].private_value = (long)sbe; |
1303 | kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 1335 | kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
@@ -1307,9 +1339,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( | |||
1307 | INIT_LIST_HEAD(&sbe->dobj.list); | 1339 | INIT_LIST_HEAD(&sbe->dobj.list); |
1308 | 1340 | ||
1309 | /* map standard io handlers and check for external handlers */ | 1341 | /* map standard io handlers and check for external handlers */ |
1310 | err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], io_ops, | 1342 | err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], tplg); |
1311 | ARRAY_SIZE(io_ops), tplg->io_ops, | ||
1312 | tplg->io_ops_count); | ||
1313 | if (err) { | 1343 | if (err) { |
1314 | soc_control_err(tplg, &be->hdr, be->hdr.name); | 1344 | soc_control_err(tplg, &be->hdr, be->hdr.name); |
1315 | kfree(sbe); | 1345 | kfree(sbe); |
@@ -1737,6 +1767,8 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp, | |||
1737 | tplg.req_index = id; | 1767 | tplg.req_index = id; |
1738 | tplg.io_ops = ops->io_ops; | 1768 | tplg.io_ops = ops->io_ops; |
1739 | tplg.io_ops_count = ops->io_ops_count; | 1769 | tplg.io_ops_count = ops->io_ops_count; |
1770 | tplg.bytes_ext_ops = ops->bytes_ext_ops; | ||
1771 | tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count; | ||
1740 | 1772 | ||
1741 | return soc_tplg_load(&tplg); | 1773 | return soc_tplg_load(&tplg); |
1742 | } | 1774 | } |
@@ -1758,7 +1790,6 @@ void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, | |||
1758 | u32 index) | 1790 | u32 index) |
1759 | { | 1791 | { |
1760 | struct snd_soc_dapm_widget *w, *next_w; | 1792 | struct snd_soc_dapm_widget *w, *next_w; |
1761 | struct snd_soc_dapm_path *p, *next_p; | ||
1762 | 1793 | ||
1763 | list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { | 1794 | list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { |
1764 | 1795 | ||
@@ -1770,31 +1801,9 @@ void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, | |||
1770 | if (w->dobj.index != index && | 1801 | if (w->dobj.index != index && |
1771 | w->dobj.index != SND_SOC_TPLG_INDEX_ALL) | 1802 | w->dobj.index != SND_SOC_TPLG_INDEX_ALL) |
1772 | continue; | 1803 | continue; |
1773 | |||
1774 | list_del(&w->list); | ||
1775 | |||
1776 | /* | ||
1777 | * remove source and sink paths associated to this widget. | ||
1778 | * While removing the path, remove reference to it from both | ||
1779 | * source and sink widgets so that path is removed only once. | ||
1780 | */ | ||
1781 | list_for_each_entry_safe(p, next_p, &w->sources, list_sink) { | ||
1782 | list_del(&p->list_sink); | ||
1783 | list_del(&p->list_source); | ||
1784 | list_del(&p->list); | ||
1785 | kfree(p); | ||
1786 | } | ||
1787 | list_for_each_entry_safe(p, next_p, &w->sinks, list_source) { | ||
1788 | list_del(&p->list_sink); | ||
1789 | list_del(&p->list_source); | ||
1790 | list_del(&p->list); | ||
1791 | kfree(p); | ||
1792 | } | ||
1793 | /* check and free and dynamic widget kcontrols */ | 1804 | /* check and free and dynamic widget kcontrols */ |
1794 | snd_soc_tplg_widget_remove(w); | 1805 | snd_soc_tplg_widget_remove(w); |
1795 | kfree(w->kcontrols); | 1806 | snd_soc_dapm_free_widget(w); |
1796 | kfree(w->name); | ||
1797 | kfree(w); | ||
1798 | } | 1807 | } |
1799 | } | 1808 | } |
1800 | EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all); | 1809 | EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all); |
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c index a4028601da01..977a078eb92f 100644 --- a/sound/soc/spear/spdif_in.c +++ b/sound/soc/spear/spdif_in.c | |||
@@ -203,35 +203,25 @@ static int spdif_in_probe(struct platform_device *pdev) | |||
203 | struct spdif_in_dev *host; | 203 | struct spdif_in_dev *host; |
204 | struct spear_spdif_platform_data *pdata; | 204 | struct spear_spdif_platform_data *pdata; |
205 | struct resource *res, *res_fifo; | 205 | struct resource *res, *res_fifo; |
206 | void __iomem *io_base; | ||
206 | int ret; | 207 | int ret; |
207 | 208 | ||
208 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 209 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
209 | if (!res) | 210 | io_base = devm_ioremap_resource(&pdev->dev, res); |
210 | return -EINVAL; | 211 | if (IS_ERR(io_base)) |
212 | return PTR_ERR(io_base); | ||
211 | 213 | ||
212 | res_fifo = platform_get_resource(pdev, IORESOURCE_IO, 0); | 214 | res_fifo = platform_get_resource(pdev, IORESOURCE_IO, 0); |
213 | if (!res_fifo) | 215 | if (!res_fifo) |
214 | return -EINVAL; | 216 | return -EINVAL; |
215 | 217 | ||
216 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
217 | resource_size(res), pdev->name)) { | ||
218 | dev_warn(&pdev->dev, "Failed to get memory resourse\n"); | ||
219 | return -ENOENT; | ||
220 | } | ||
221 | |||
222 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); | 218 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); |
223 | if (!host) { | 219 | if (!host) { |
224 | dev_warn(&pdev->dev, "kzalloc fail\n"); | 220 | dev_warn(&pdev->dev, "kzalloc fail\n"); |
225 | return -ENOMEM; | 221 | return -ENOMEM; |
226 | } | 222 | } |
227 | 223 | ||
228 | host->io_base = devm_ioremap(&pdev->dev, res->start, | 224 | host->io_base = io_base; |
229 | resource_size(res)); | ||
230 | if (!host->io_base) { | ||
231 | dev_warn(&pdev->dev, "ioremap failed\n"); | ||
232 | return -ENOMEM; | ||
233 | } | ||
234 | |||
235 | host->irq = platform_get_irq(pdev, 0); | 225 | host->irq = platform_get_irq(pdev, 0); |
236 | if (host->irq < 0) | 226 | if (host->irq < 0) |
237 | return -EINVAL; | 227 | return -EINVAL; |
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c index a7dc3c56f44d..e8476da157cd 100644 --- a/sound/soc/spear/spear_pcm.c +++ b/sound/soc/spear/spear_pcm.c | |||
@@ -44,7 +44,7 @@ int devm_spear_pcm_platform_register(struct device *dev, | |||
44 | *config = spear_dmaengine_pcm_config; | 44 | *config = spear_dmaengine_pcm_config; |
45 | config->compat_filter_fn = filter; | 45 | config->compat_filter_fn = filter; |
46 | 46 | ||
47 | return snd_dmaengine_pcm_register(dev, config, | 47 | return devm_snd_dmaengine_pcm_register(dev, config, |
48 | SND_DMAENGINE_PCM_FLAG_NO_DT | | 48 | SND_DMAENGINE_PCM_FLAG_NO_DT | |
49 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 49 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
50 | } | 50 | } |
diff --git a/sound/soc/sti/Kconfig b/sound/soc/sti/Kconfig new file mode 100644 index 000000000000..64a690077023 --- /dev/null +++ b/sound/soc/sti/Kconfig | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # STM SoC audio configuration | ||
3 | # | ||
4 | menuconfig SND_SOC_STI | ||
5 | tristate "SoC Audio support for STI System-On-Chip" | ||
6 | depends on SND_SOC | ||
7 | depends on ARCH_STI || COMPILE_TEST | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
9 | help | ||
10 | Say Y if you want to enable ASoC-support for | ||
11 | any of the STI platforms (e.g. STIH416). | ||
diff --git a/sound/soc/sti/Makefile b/sound/soc/sti/Makefile new file mode 100644 index 000000000000..4b188d2d76b8 --- /dev/null +++ b/sound/soc/sti/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # STI platform support | ||
2 | snd-soc-sti-objs := sti_uniperif.o uniperif_player.o uniperif_reader.o | ||
3 | |||
4 | obj-$(CONFIG_SND_SOC_STI) += snd-soc-sti.o | ||
diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c new file mode 100644 index 000000000000..39bcefe5eea0 --- /dev/null +++ b/sound/soc/sti/sti_uniperif.c | |||
@@ -0,0 +1,254 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2015 | ||
3 | * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com> | ||
4 | * for STMicroelectronics. | ||
5 | * License terms: GNU General Public License (GPL), version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/pinctrl/consumer.h> | ||
10 | |||
11 | #include "uniperif.h" | ||
12 | |||
13 | /* | ||
14 | * sti_uniperiph_dai_create_ctrl | ||
15 | * This function is used to create Ctrl associated to DAI but also pcm device. | ||
16 | * Request is done by front end to associate ctrl with pcm device id | ||
17 | */ | ||
18 | static int sti_uniperiph_dai_create_ctrl(struct snd_soc_dai *dai) | ||
19 | { | ||
20 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
21 | struct uniperif *uni = priv->dai_data.uni; | ||
22 | struct snd_kcontrol_new *ctrl; | ||
23 | int i; | ||
24 | |||
25 | if (!uni->num_ctrls) | ||
26 | return 0; | ||
27 | |||
28 | for (i = 0; i < uni->num_ctrls; i++) { | ||
29 | /* | ||
30 | * Several Control can have same name. Controls are indexed on | ||
31 | * Uniperipheral instance ID | ||
32 | */ | ||
33 | ctrl = &uni->snd_ctrls[i]; | ||
34 | ctrl->index = uni->info->id; | ||
35 | ctrl->device = uni->info->id; | ||
36 | } | ||
37 | |||
38 | return snd_soc_add_dai_controls(dai, uni->snd_ctrls, uni->num_ctrls); | ||
39 | } | ||
40 | |||
41 | /* | ||
42 | * DAI | ||
43 | */ | ||
44 | int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream, | ||
45 | struct snd_pcm_hw_params *params, | ||
46 | struct snd_soc_dai *dai) | ||
47 | { | ||
48 | struct snd_dmaengine_dai_dma_data *dma_data; | ||
49 | int transfer_size; | ||
50 | |||
51 | transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES; | ||
52 | |||
53 | dma_data = snd_soc_dai_get_dma_data(dai, substream); | ||
54 | dma_data->maxburst = transfer_size; | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | int sti_uniperiph_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
60 | { | ||
61 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
62 | |||
63 | priv->dai_data.uni->daifmt = fmt; | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int sti_uniperiph_dai_suspend(struct snd_soc_dai *dai) | ||
69 | { | ||
70 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
71 | struct uniperif *uni = priv->dai_data.uni; | ||
72 | int ret; | ||
73 | |||
74 | /* The uniperipheral should be in stopped state */ | ||
75 | if (uni->state != UNIPERIF_STATE_STOPPED) { | ||
76 | dev_err(uni->dev, "%s: invalid uni state( %d)", | ||
77 | __func__, (int)uni->state); | ||
78 | return -EBUSY; | ||
79 | } | ||
80 | |||
81 | /* Pinctrl: switch pinstate to sleep */ | ||
82 | ret = pinctrl_pm_select_sleep_state(uni->dev); | ||
83 | if (ret) | ||
84 | dev_err(uni->dev, "%s: failed to select pinctrl state", | ||
85 | __func__); | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | static int sti_uniperiph_dai_resume(struct snd_soc_dai *dai) | ||
91 | { | ||
92 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
93 | struct uniperif *uni = priv->dai_data.uni; | ||
94 | int ret; | ||
95 | |||
96 | if (of_device_is_compatible(dai->dev->of_node, "st,sti-uni-player")) { | ||
97 | ret = uni_player_resume(uni); | ||
98 | if (ret) | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | /* pinctrl: switch pinstate to default */ | ||
103 | ret = pinctrl_pm_select_default_state(uni->dev); | ||
104 | if (ret) | ||
105 | dev_err(uni->dev, "%s: failed to select pinctrl state", | ||
106 | __func__); | ||
107 | |||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | static int sti_uniperiph_dai_probe(struct snd_soc_dai *dai) | ||
112 | { | ||
113 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
114 | struct sti_uniperiph_dai *dai_data = &priv->dai_data; | ||
115 | |||
116 | /* DMA settings*/ | ||
117 | if (of_device_is_compatible(dai->dev->of_node, "st,sti-uni-player")) | ||
118 | snd_soc_dai_init_dma_data(dai, &dai_data->dma_data, NULL); | ||
119 | else | ||
120 | snd_soc_dai_init_dma_data(dai, NULL, &dai_data->dma_data); | ||
121 | |||
122 | dai_data->dma_data.addr = dai_data->uni->fifo_phys_address; | ||
123 | dai_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
124 | |||
125 | return sti_uniperiph_dai_create_ctrl(dai); | ||
126 | } | ||
127 | |||
128 | static const struct snd_soc_dai_driver sti_uniperiph_dai_template = { | ||
129 | .probe = sti_uniperiph_dai_probe, | ||
130 | .suspend = sti_uniperiph_dai_suspend, | ||
131 | .resume = sti_uniperiph_dai_resume | ||
132 | }; | ||
133 | |||
134 | static const struct snd_soc_component_driver sti_uniperiph_dai_component = { | ||
135 | .name = "sti_cpu_dai", | ||
136 | }; | ||
137 | |||
138 | static int sti_uniperiph_cpu_dai_of(struct device_node *node, | ||
139 | struct sti_uniperiph_data *priv) | ||
140 | { | ||
141 | const char *str; | ||
142 | int ret; | ||
143 | struct device *dev = &priv->pdev->dev; | ||
144 | struct sti_uniperiph_dai *dai_data = &priv->dai_data; | ||
145 | struct snd_soc_dai_driver *dai = priv->dai; | ||
146 | struct snd_soc_pcm_stream *stream; | ||
147 | struct uniperif *uni; | ||
148 | |||
149 | uni = devm_kzalloc(dev, sizeof(*uni), GFP_KERNEL); | ||
150 | if (!uni) | ||
151 | return -ENOMEM; | ||
152 | |||
153 | *dai = sti_uniperiph_dai_template; | ||
154 | ret = of_property_read_string(node, "dai-name", &str); | ||
155 | if (ret < 0) { | ||
156 | dev_err(dev, "%s: dai name missing.\n", __func__); | ||
157 | return -EINVAL; | ||
158 | } | ||
159 | dai->name = str; | ||
160 | |||
161 | /* Get resources */ | ||
162 | uni->mem_region = platform_get_resource(priv->pdev, IORESOURCE_MEM, 0); | ||
163 | |||
164 | if (!uni->mem_region) { | ||
165 | dev_err(dev, "Failed to get memory resource"); | ||
166 | return -ENODEV; | ||
167 | } | ||
168 | |||
169 | uni->base = devm_ioremap_resource(dev, uni->mem_region); | ||
170 | |||
171 | if (IS_ERR(uni->base)) | ||
172 | return PTR_ERR(uni->base); | ||
173 | |||
174 | uni->fifo_phys_address = uni->mem_region->start + | ||
175 | UNIPERIF_FIFO_DATA_OFFSET(uni); | ||
176 | |||
177 | uni->irq = platform_get_irq(priv->pdev, 0); | ||
178 | if (uni->irq < 0) { | ||
179 | dev_err(dev, "Failed to get IRQ resource"); | ||
180 | return -ENXIO; | ||
181 | } | ||
182 | |||
183 | dai_data->uni = uni; | ||
184 | |||
185 | if (of_device_is_compatible(node, "st,sti-uni-player")) { | ||
186 | uni_player_init(priv->pdev, uni); | ||
187 | stream = &dai->playback; | ||
188 | } else { | ||
189 | uni_reader_init(priv->pdev, uni); | ||
190 | stream = &dai->capture; | ||
191 | } | ||
192 | dai->ops = uni->dai_ops; | ||
193 | |||
194 | stream->stream_name = dai->name; | ||
195 | stream->channels_min = uni->hw->channels_min; | ||
196 | stream->channels_max = uni->hw->channels_max; | ||
197 | stream->rates = uni->hw->rates; | ||
198 | stream->formats = uni->hw->formats; | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static const struct snd_dmaengine_pcm_config dmaengine_pcm_config = { | ||
204 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, | ||
205 | }; | ||
206 | |||
207 | static int sti_uniperiph_probe(struct platform_device *pdev) | ||
208 | { | ||
209 | struct sti_uniperiph_data *priv; | ||
210 | struct device_node *node = pdev->dev.of_node; | ||
211 | int ret; | ||
212 | |||
213 | /* Allocate the private data and the CPU_DAI array */ | ||
214 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
215 | if (!priv) | ||
216 | return -ENOMEM; | ||
217 | priv->dai = devm_kzalloc(&pdev->dev, sizeof(*priv->dai), GFP_KERNEL); | ||
218 | if (!priv->dai) | ||
219 | return -ENOMEM; | ||
220 | |||
221 | priv->pdev = pdev; | ||
222 | |||
223 | ret = sti_uniperiph_cpu_dai_of(node, priv); | ||
224 | |||
225 | dev_set_drvdata(&pdev->dev, priv); | ||
226 | |||
227 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
228 | &sti_uniperiph_dai_component, | ||
229 | priv->dai, 1); | ||
230 | if (ret < 0) | ||
231 | return ret; | ||
232 | |||
233 | return devm_snd_dmaengine_pcm_register(&pdev->dev, | ||
234 | &dmaengine_pcm_config, 0); | ||
235 | } | ||
236 | |||
237 | static const struct of_device_id snd_soc_sti_match[] = { | ||
238 | { .compatible = "st,sti-uni-player", }, | ||
239 | { .compatible = "st,sti-uni-reader", }, | ||
240 | {}, | ||
241 | }; | ||
242 | |||
243 | static struct platform_driver sti_uniperiph_driver = { | ||
244 | .driver = { | ||
245 | .name = "sti-uniperiph-dai", | ||
246 | .of_match_table = snd_soc_sti_match, | ||
247 | }, | ||
248 | .probe = sti_uniperiph_probe, | ||
249 | }; | ||
250 | module_platform_driver(sti_uniperiph_driver); | ||
251 | |||
252 | MODULE_DESCRIPTION("uniperipheral DAI driver"); | ||
253 | MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); | ||
254 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h new file mode 100644 index 000000000000..f0fd5a9944e9 --- /dev/null +++ b/sound/soc/sti/uniperif.h | |||
@@ -0,0 +1,1229 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2015 | ||
3 | * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com> | ||
4 | * for STMicroelectronics. | ||
5 | * License terms: GNU General Public License (GPL), version 2 | ||
6 | */ | ||
7 | |||
8 | #ifndef __SND_ST_AUD_UNIPERIF_H | ||
9 | #define __SND_ST_AUD_UNIPERIF_H | ||
10 | |||
11 | #include <linux/regmap.h> | ||
12 | |||
13 | #include <sound/dmaengine_pcm.h> | ||
14 | |||
15 | /* | ||
16 | * Register access macros | ||
17 | */ | ||
18 | |||
19 | #define GET_UNIPERIF_REG(ip, offset, shift, mask) \ | ||
20 | ((readl_relaxed(ip->base + offset) >> shift) & mask) | ||
21 | #define SET_UNIPERIF_REG(ip, offset, shift, mask, value) \ | ||
22 | writel_relaxed(((readl_relaxed(ip->base + offset) & \ | ||
23 | ~(mask << shift)) | (((value) & mask) << shift)), ip->base + offset) | ||
24 | #define SET_UNIPERIF_BIT_REG(ip, offset, shift, mask, value) \ | ||
25 | writel_relaxed((((value) & mask) << shift), ip->base + offset) | ||
26 | |||
27 | /* | ||
28 | * AUD_UNIPERIF_SOFT_RST reg | ||
29 | */ | ||
30 | |||
31 | #define UNIPERIF_SOFT_RST_OFFSET(ip) 0x0000 | ||
32 | #define GET_UNIPERIF_SOFT_RST(ip) \ | ||
33 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? \ | ||
34 | readl_relaxed(ip->base + UNIPERIF_SOFT_RST_OFFSET(ip)) : 0) | ||
35 | #define SET_UNIPERIF_SOFT_RST(ip, value) \ | ||
36 | writel_relaxed(value, ip->base + UNIPERIF_SOFT_RST_OFFSET(ip)) | ||
37 | |||
38 | /* SOFT_RST */ | ||
39 | #define UNIPERIF_SOFT_RST_SOFT_RST_SHIFT(ip) 0x0 | ||
40 | #define UNIPERIF_SOFT_RST_SOFT_RST_MASK(ip) 0x1 | ||
41 | #define SET_UNIPERIF_SOFT_RST_SOFT_RST(ip) \ | ||
42 | SET_UNIPERIF_BIT_REG(ip, \ | ||
43 | UNIPERIF_SOFT_RST_OFFSET(ip), \ | ||
44 | UNIPERIF_SOFT_RST_SOFT_RST_SHIFT(ip), \ | ||
45 | UNIPERIF_SOFT_RST_SOFT_RST_MASK(ip), 1) | ||
46 | #define GET_UNIPERIF_SOFT_RST_SOFT_RST(ip) \ | ||
47 | GET_UNIPERIF_REG(ip, \ | ||
48 | UNIPERIF_SOFT_RST_OFFSET(ip), \ | ||
49 | UNIPERIF_SOFT_RST_SOFT_RST_SHIFT(ip), \ | ||
50 | UNIPERIF_SOFT_RST_SOFT_RST_MASK(ip)) | ||
51 | |||
52 | /* | ||
53 | * AUD_UNIPERIF_FIFO_DATA reg | ||
54 | */ | ||
55 | |||
56 | #define UNIPERIF_FIFO_DATA_OFFSET(ip) 0x0004 | ||
57 | #define SET_UNIPERIF_DATA(ip, value) \ | ||
58 | writel_relaxed(value, ip->base + UNIPERIF_FIFO_DATA_OFFSET(ip)) | ||
59 | |||
60 | /* | ||
61 | * AUD_UNIPERIF_CHANNEL_STA_REGN reg | ||
62 | */ | ||
63 | |||
64 | #define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) | ||
65 | #define GET_UNIPERIF_CHANNEL_STA_REGN(ip) \ | ||
66 | readl_relaxed(ip->base + UNIPERIF_CHANNEL_STA_REGN(ip, n)) | ||
67 | #define SET_UNIPERIF_CHANNEL_STA_REGN(ip, n, value) \ | ||
68 | writel_relaxed(value, ip->base + \ | ||
69 | UNIPERIF_CHANNEL_STA_REGN(ip, n)) | ||
70 | |||
71 | #define UNIPERIF_CHANNEL_STA_REG0_OFFSET(ip) 0x0060 | ||
72 | #define GET_UNIPERIF_CHANNEL_STA_REG0(ip) \ | ||
73 | readl_relaxed(ip->base + UNIPERIF_CHANNEL_STA_REG0_OFFSET(ip)) | ||
74 | #define SET_UNIPERIF_CHANNEL_STA_REG0(ip, value) \ | ||
75 | writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG0_OFFSET(ip)) | ||
76 | |||
77 | #define UNIPERIF_CHANNEL_STA_REG1_OFFSET(ip) 0x0064 | ||
78 | #define GET_UNIPERIF_CHANNEL_STA_REG1(ip) \ | ||
79 | readl_relaxed(ip->base + UNIPERIF_CHANNEL_STA_REG1_OFFSET(ip)) | ||
80 | #define SET_UNIPERIF_CHANNEL_STA_REG1(ip, value) \ | ||
81 | writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG1_OFFSET(ip)) | ||
82 | |||
83 | #define UNIPERIF_CHANNEL_STA_REG2_OFFSET(ip) 0x0068 | ||
84 | #define GET_UNIPERIF_CHANNEL_STA_REG2(ip) \ | ||
85 | readl_relaxed(ip->base + UNIPERIF_CHANNEL_STA_REG2_OFFSET(ip)) | ||
86 | #define SET_UNIPERIF_CHANNEL_STA_REG2(ip, value) \ | ||
87 | writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG2_OFFSET(ip)) | ||
88 | |||
89 | #define UNIPERIF_CHANNEL_STA_REG3_OFFSET(ip) 0x006C | ||
90 | #define GET_UNIPERIF_CHANNEL_STA_REG3(ip) \ | ||
91 | readl_relaxed(ip->base + UNIPERIF_CHANNEL_STA_REG3_OFFSET(ip)) | ||
92 | #define SET_UNIPERIF_CHANNEL_STA_REG3(ip, value) \ | ||
93 | writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG3_OFFSET(ip)) | ||
94 | |||
95 | #define UNIPERIF_CHANNEL_STA_REG4_OFFSET(ip) 0x0070 | ||
96 | #define GET_UNIPERIF_CHANNEL_STA_REG4(ip) \ | ||
97 | readl_relaxed(ip->base + UNIPERIF_CHANNEL_STA_REG4_OFFSET(ip)) | ||
98 | #define SET_UNIPERIF_CHANNEL_STA_REG4(ip, value) \ | ||
99 | writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG4_OFFSET(ip)) | ||
100 | |||
101 | #define UNIPERIF_CHANNEL_STA_REG5_OFFSET(ip) 0x0074 | ||
102 | #define GET_UNIPERIF_CHANNEL_STA_REG5(ip) \ | ||
103 | readl_relaxed(ip->base + UNIPERIF_CHANNEL_STA_REG5_OFFSET(ip)) | ||
104 | #define SET_UNIPERIF_CHANNEL_STA_REG5(ip, value) \ | ||
105 | writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG5_OFFSET(ip)) | ||
106 | |||
107 | /* | ||
108 | * AUD_UNIPERIF_ITS reg | ||
109 | */ | ||
110 | |||
111 | #define UNIPERIF_ITS_OFFSET(ip) 0x000C | ||
112 | #define GET_UNIPERIF_ITS(ip) \ | ||
113 | readl_relaxed(ip->base + UNIPERIF_ITS_OFFSET(ip)) | ||
114 | |||
115 | /* MEM_BLK_READ */ | ||
116 | #define UNIPERIF_ITS_MEM_BLK_READ_SHIFT(ip) 5 | ||
117 | #define UNIPERIF_ITS_MEM_BLK_READ_MASK(ip) \ | ||
118 | (BIT(UNIPERIF_ITS_MEM_BLK_READ_SHIFT(ip))) | ||
119 | |||
120 | /* FIFO_ERROR */ | ||
121 | #define UNIPERIF_ITS_FIFO_ERROR_SHIFT(ip) \ | ||
122 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 0 : 8) | ||
123 | #define UNIPERIF_ITS_FIFO_ERROR_MASK(ip) \ | ||
124 | (BIT(UNIPERIF_ITS_FIFO_ERROR_SHIFT(ip))) | ||
125 | |||
126 | /* DMA_ERROR */ | ||
127 | #define UNIPERIF_ITS_DMA_ERROR_SHIFT(ip) 9 | ||
128 | #define UNIPERIF_ITS_DMA_ERROR_MASK(ip) \ | ||
129 | (BIT(UNIPERIF_ITS_DMA_ERROR_SHIFT(ip))) | ||
130 | |||
131 | /* UNDERFLOW_REC_DONE */ | ||
132 | #define UNIPERIF_ITS_UNDERFLOW_REC_DONE_SHIFT(ip) \ | ||
133 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 12) | ||
134 | #define UNIPERIF_ITS_UNDERFLOW_REC_DONE_MASK(ip) \ | ||
135 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? \ | ||
136 | 0 : (BIT(UNIPERIF_ITS_UNDERFLOW_REC_DONE_SHIFT(ip)))) | ||
137 | |||
138 | /* UNDERFLOW_REC_FAILED */ | ||
139 | #define UNIPERIF_ITS_UNDERFLOW_REC_FAILED_SHIFT(ip) \ | ||
140 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 13) | ||
141 | #define UNIPERIF_ITS_UNDERFLOW_REC_FAILED_MASK(ip) \ | ||
142 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? \ | ||
143 | 0 : (BIT(UNIPERIF_ITS_UNDERFLOW_REC_FAILED_SHIFT(ip)))) | ||
144 | |||
145 | /* | ||
146 | * AUD_UNIPERIF_ITS_BCLR reg | ||
147 | */ | ||
148 | |||
149 | /* FIFO_ERROR */ | ||
150 | #define UNIPERIF_ITS_BCLR_FIFO_ERROR_SHIFT(ip) \ | ||
151 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 0 : 8) | ||
152 | #define UNIPERIF_ITS_BCLR_FIFO_ERROR_MASK(ip) \ | ||
153 | (BIT(UNIPERIF_ITS_BCLR_FIFO_ERROR_SHIFT(ip))) | ||
154 | #define SET_UNIPERIF_ITS_BCLR_FIFO_ERROR(ip) \ | ||
155 | SET_UNIPERIF_ITS_BCLR(ip, \ | ||
156 | UNIPERIF_ITS_BCLR_FIFO_ERROR_MASK(ip)) | ||
157 | |||
158 | #define UNIPERIF_ITS_BCLR_OFFSET(ip) 0x0010 | ||
159 | #define SET_UNIPERIF_ITS_BCLR(ip, value) \ | ||
160 | writel_relaxed(value, ip->base + UNIPERIF_ITS_BCLR_OFFSET(ip)) | ||
161 | |||
162 | /* | ||
163 | * AUD_UNIPERIF_ITM reg | ||
164 | */ | ||
165 | |||
166 | #define UNIPERIF_ITM_OFFSET(ip) 0x0018 | ||
167 | #define GET_UNIPERIF_ITM(ip) \ | ||
168 | readl_relaxed(ip->base + UNIPERIF_ITM_OFFSET(ip)) | ||
169 | |||
170 | /* FIFO_ERROR */ | ||
171 | #define UNIPERIF_ITM_FIFO_ERROR_SHIFT(ip) \ | ||
172 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 0 : 8) | ||
173 | #define UNIPERIF_ITM_FIFO_ERROR_MASK(ip) \ | ||
174 | (BIT(UNIPERIF_ITM_FIFO_ERROR_SHIFT(ip))) | ||
175 | |||
176 | /* UNDERFLOW_REC_DONE */ | ||
177 | #define UNIPERIF_ITM_UNDERFLOW_REC_DONE_SHIFT(ip) \ | ||
178 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 12) | ||
179 | #define UNIPERIF_ITM_UNDERFLOW_REC_DONE_MASK(ip) \ | ||
180 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? \ | ||
181 | 0 : (BIT(UNIPERIF_ITM_UNDERFLOW_REC_DONE_SHIFT(ip)))) | ||
182 | |||
183 | /* UNDERFLOW_REC_FAILED */ | ||
184 | #define UNIPERIF_ITM_UNDERFLOW_REC_FAILED_SHIFT(ip) \ | ||
185 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 13) | ||
186 | #define UNIPERIF_ITM_UNDERFLOW_REC_FAILED_MASK(ip) \ | ||
187 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? \ | ||
188 | 0 : (BIT(UNIPERIF_ITM_UNDERFLOW_REC_FAILED_SHIFT(ip)))) | ||
189 | |||
190 | /* | ||
191 | * AUD_UNIPERIF_ITM_BCLR reg | ||
192 | */ | ||
193 | |||
194 | #define UNIPERIF_ITM_BCLR_OFFSET(ip) 0x001c | ||
195 | #define SET_UNIPERIF_ITM_BCLR(ip, value) \ | ||
196 | writel_relaxed(value, ip->base + UNIPERIF_ITM_BCLR_OFFSET(ip)) | ||
197 | |||
198 | /* FIFO_ERROR */ | ||
199 | #define UNIPERIF_ITM_BCLR_FIFO_ERROR_SHIFT(ip) \ | ||
200 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 0 : 8) | ||
201 | #define UNIPERIF_ITM_BCLR_FIFO_ERROR_MASK(ip) \ | ||
202 | (BIT(UNIPERIF_ITM_BCLR_FIFO_ERROR_SHIFT(ip))) | ||
203 | #define SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(ip) \ | ||
204 | SET_UNIPERIF_ITM_BCLR(ip, \ | ||
205 | UNIPERIF_ITM_BCLR_FIFO_ERROR_MASK(ip)) | ||
206 | |||
207 | /* DMA_ERROR */ | ||
208 | #define UNIPERIF_ITM_BCLR_DMA_ERROR_SHIFT(ip) 9 | ||
209 | #define UNIPERIF_ITM_BCLR_DMA_ERROR_MASK(ip) \ | ||
210 | (BIT(UNIPERIF_ITM_BCLR_DMA_ERROR_SHIFT(ip))) | ||
211 | #define SET_UNIPERIF_ITM_BCLR_DMA_ERROR(ip) \ | ||
212 | SET_UNIPERIF_ITM_BCLR(ip, \ | ||
213 | UNIPERIF_ITM_BCLR_DMA_ERROR_MASK(ip)) | ||
214 | |||
215 | /* | ||
216 | * AUD_UNIPERIF_ITM_BSET reg | ||
217 | */ | ||
218 | |||
219 | #define UNIPERIF_ITM_BSET_OFFSET(ip) 0x0020 | ||
220 | #define SET_UNIPERIF_ITM_BSET(ip, value) \ | ||
221 | writel_relaxed(value, ip->base + UNIPERIF_ITM_BSET_OFFSET(ip)) | ||
222 | |||
223 | /* FIFO_ERROR */ | ||
224 | #define UNIPERIF_ITM_BSET_FIFO_ERROR_SHIFT(ip) \ | ||
225 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 0 : 8) | ||
226 | #define UNIPERIF_ITM_BSET_FIFO_ERROR_MASK(ip) \ | ||
227 | (BIT(UNIPERIF_ITM_BSET_FIFO_ERROR_SHIFT(ip))) | ||
228 | #define SET_UNIPERIF_ITM_BSET_FIFO_ERROR(ip) \ | ||
229 | SET_UNIPERIF_ITM_BSET(ip, \ | ||
230 | UNIPERIF_ITM_BSET_FIFO_ERROR_MASK(ip)) | ||
231 | |||
232 | /* MEM_BLK_READ */ | ||
233 | #define UNIPERIF_ITM_BSET_MEM_BLK_READ_SHIFT(ip) 5 | ||
234 | #define UNIPERIF_ITM_BSET_MEM_BLK_READ_MASK(ip) \ | ||
235 | (BIT(UNIPERIF_ITM_BSET_MEM_BLK_READ_SHIFT(ip))) | ||
236 | #define SET_UNIPERIF_ITM_BSET_MEM_BLK_READ(ip) \ | ||
237 | SET_UNIPERIF_ITM_BSET(ip, \ | ||
238 | UNIPERIF_ITM_BSET_MEM_BLK_READ_MASK(ip)) | ||
239 | |||
240 | /* DMA_ERROR */ | ||
241 | #define UNIPERIF_ITM_BSET_DMA_ERROR_SHIFT(ip) 9 | ||
242 | #define UNIPERIF_ITM_BSET_DMA_ERROR_MASK(ip) \ | ||
243 | (BIT(UNIPERIF_ITM_BSET_DMA_ERROR_SHIFT(ip))) | ||
244 | #define SET_UNIPERIF_ITM_BSET_DMA_ERROR(ip) \ | ||
245 | SET_UNIPERIF_ITM_BSET(ip, \ | ||
246 | UNIPERIF_ITM_BSET_DMA_ERROR_MASK(ip)) | ||
247 | |||
248 | /* UNDERFLOW_REC_DONE */ | ||
249 | #define UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE_SHIFT(ip) \ | ||
250 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 12) | ||
251 | #define UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE_MASK(ip) \ | ||
252 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? \ | ||
253 | 0 : (BIT(UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE_SHIFT(ip)))) | ||
254 | #define SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE(ip) \ | ||
255 | SET_UNIPERIF_ITM_BSET(ip, \ | ||
256 | UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE_MASK(ip)) | ||
257 | |||
258 | /* UNDERFLOW_REC_FAILED */ | ||
259 | #define UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED_SHIFT(ip) \ | ||
260 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 13) | ||
261 | #define UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED_MASK(ip) \ | ||
262 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? \ | ||
263 | 0 : (BIT(UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED_SHIFT(ip)))) | ||
264 | #define SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED(ip) \ | ||
265 | SET_UNIPERIF_ITM_BSET(ip, \ | ||
266 | UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED_MASK(ip)) | ||
267 | |||
268 | /* | ||
269 | * UNIPERIF_CONFIG reg | ||
270 | */ | ||
271 | |||
272 | #define UNIPERIF_CONFIG_OFFSET(ip) 0x0040 | ||
273 | #define GET_UNIPERIF_CONFIG(ip) \ | ||
274 | readl_relaxed(ip->base + UNIPERIF_CONFIG_OFFSET(ip)) | ||
275 | #define SET_UNIPERIF_CONFIG(ip, value) \ | ||
276 | writel_relaxed(value, ip->base + UNIPERIF_CONFIG_OFFSET(ip)) | ||
277 | |||
278 | /* PARITY_CNTR */ | ||
279 | #define UNIPERIF_CONFIG_PARITY_CNTR_SHIFT(ip) 0 | ||
280 | #define UNIPERIF_CONFIG_PARITY_CNTR_MASK(ip) 0x1 | ||
281 | #define GET_UNIPERIF_CONFIG_PARITY_CNTR(ip) \ | ||
282 | GET_UNIPERIF_REG(ip, \ | ||
283 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
284 | UNIPERIF_CONFIG_PARITY_CNTR_SHIFT(ip), \ | ||
285 | UNIPERIF_CONFIG_PARITY_CNTR_MASK(ip)) | ||
286 | #define SET_UNIPERIF_CONFIG_PARITY_CNTR_BY_HW(ip) \ | ||
287 | SET_UNIPERIF_REG(ip, \ | ||
288 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
289 | UNIPERIF_CONFIG_PARITY_CNTR_SHIFT(ip), \ | ||
290 | UNIPERIF_CONFIG_PARITY_CNTR_MASK(ip), 0) | ||
291 | #define SET_UNIPERIF_CONFIG_PARITY_CNTR_BY_SW(ip) \ | ||
292 | SET_UNIPERIF_REG(ip, \ | ||
293 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
294 | UNIPERIF_CONFIG_PARITY_CNTR_SHIFT(ip), \ | ||
295 | UNIPERIF_CONFIG_PARITY_CNTR_MASK(ip), 1) | ||
296 | |||
297 | /* CHANNEL_STA_CNTR */ | ||
298 | #define UNIPERIF_CONFIG_CHANNEL_STA_CNTR_SHIFT(ip) 1 | ||
299 | #define UNIPERIF_CONFIG_CHANNEL_STA_CNTR_MASK(ip) 0x1 | ||
300 | #define GET_UNIPERIF_CONFIG_CHANNEL_STA_CNTR(ip) \ | ||
301 | GET_UNIPERIF_REG(ip, \ | ||
302 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
303 | UNIPERIF_CONFIG_CHANNEL_STA_CNTR_SHIFT(ip), \ | ||
304 | UNIPERIF_CONFIG_CHANNEL_STA_CNTR_MASK(ip)) | ||
305 | #define SET_UNIPERIF_CONFIG_CHANNEL_STA_CNTR_BY_SW(ip) \ | ||
306 | SET_UNIPERIF_REG(ip, \ | ||
307 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
308 | UNIPERIF_CONFIG_CHANNEL_STA_CNTR_SHIFT(ip), \ | ||
309 | UNIPERIF_CONFIG_CHANNEL_STA_CNTR_MASK(ip), 0) | ||
310 | #define SET_UNIPERIF_CONFIG_CHANNEL_STA_CNTR_BY_HW(ip) \ | ||
311 | SET_UNIPERIF_REG(ip, \ | ||
312 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
313 | UNIPERIF_CONFIG_CHANNEL_STA_CNTR_SHIFT(ip), \ | ||
314 | UNIPERIF_CONFIG_CHANNEL_STA_CNTR_MASK(ip), 1) | ||
315 | |||
316 | /* USER_DAT_CNTR */ | ||
317 | #define UNIPERIF_CONFIG_USER_DAT_CNTR_SHIFT(ip) 2 | ||
318 | #define UNIPERIF_CONFIG_USER_DAT_CNTR_MASK(ip) 0x1 | ||
319 | #define GET_UNIPERIF_CONFIG_USER_DAT_CNTR(ip) \ | ||
320 | GET_UNIPERIF_REG(ip, \ | ||
321 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
322 | UNIPERIF_CONFIG_USER_DAT_CNTR_SHIFT(ip), \ | ||
323 | UNIPERIF_CONFIG_USER_DAT_CNTR_MASK(ip)) | ||
324 | #define SET_UNIPERIF_CONFIG_USER_DAT_CNTR_BY_HW(ip) \ | ||
325 | SET_UNIPERIF_REG(ip, \ | ||
326 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
327 | UNIPERIF_CONFIG_USER_DAT_CNTR_SHIFT(ip), \ | ||
328 | UNIPERIF_CONFIG_USER_DAT_CNTR_MASK(ip), 1) | ||
329 | #define SET_UNIPERIF_CONFIG_USER_DAT_CNTR_BY_SW(ip) \ | ||
330 | SET_UNIPERIF_REG(ip, \ | ||
331 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
332 | UNIPERIF_CONFIG_USER_DAT_CNTR_SHIFT(ip), \ | ||
333 | UNIPERIF_CONFIG_USER_DAT_CNTR_MASK(ip), 0) | ||
334 | |||
335 | /* VALIDITY_DAT_CNTR */ | ||
336 | #define UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_SHIFT(ip) 3 | ||
337 | #define UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_MASK(ip) 0x1 | ||
338 | #define GET_UNIPERIF_CONFIG_VALIDITY_DAT_CNTR(ip) \ | ||
339 | GET_UNIPERIF_REG(ip, \ | ||
340 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
341 | UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_SHIFT(ip), \ | ||
342 | UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_MASK(ip)) | ||
343 | #define SET_UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_BY_SW(ip) \ | ||
344 | SET_UNIPERIF_REG(ip, \ | ||
345 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
346 | UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_SHIFT(ip), \ | ||
347 | UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_MASK(ip), 0) | ||
348 | #define SET_UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_BY_HW(ip) \ | ||
349 | SET_UNIPERIF_REG(ip, \ | ||
350 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
351 | UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_SHIFT(ip), \ | ||
352 | UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_MASK(ip), 1) | ||
353 | |||
354 | /* ONE_BIT_AUD_SUPPORT */ | ||
355 | #define UNIPERIF_CONFIG_ONE_BIT_AUD_SHIFT(ip) 4 | ||
356 | #define UNIPERIF_CONFIG_ONE_BIT_AUD_MASK(ip) 0x1 | ||
357 | #define GET_UNIPERIF_CONFIG_ONE_BIT_AUD(ip) \ | ||
358 | GET_UNIPERIF_REG(ip, \ | ||
359 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
360 | UNIPERIF_CONFIG_ONE_BIT_AUD_SHIFT(ip), \ | ||
361 | UNIPERIF_CONFIG_ONE_BIT_AUD_MASK(ip)) | ||
362 | #define SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(ip) \ | ||
363 | SET_UNIPERIF_REG(ip, \ | ||
364 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
365 | UNIPERIF_CONFIG_ONE_BIT_AUD_SHIFT(ip), \ | ||
366 | UNIPERIF_CONFIG_ONE_BIT_AUD_MASK(ip), 0) | ||
367 | #define SET_UNIPERIF_CONFIG_ONE_BIT_AUD_ENABLE(ip) \ | ||
368 | SET_UNIPERIF_REG(ip, \ | ||
369 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
370 | UNIPERIF_CONFIG_ONE_BIT_AUD_SHIFT(ip), \ | ||
371 | UNIPERIF_CONFIG_ONE_BIT_AUD_MASK(ip), 1) | ||
372 | |||
373 | /* MEMORY_FMT */ | ||
374 | #define UNIPERIF_CONFIG_MEM_FMT_SHIFT(ip) 5 | ||
375 | #define UNIPERIF_CONFIG_MEM_FMT_MASK(ip) 0x1 | ||
376 | #define VALUE_UNIPERIF_CONFIG_MEM_FMT_16_0(ip) 0 | ||
377 | #define VALUE_UNIPERIF_CONFIG_MEM_FMT_16_16(ip) 1 | ||
378 | #define GET_UNIPERIF_CONFIG_MEM_FMT(ip) \ | ||
379 | GET_UNIPERIF_REG(ip, \ | ||
380 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
381 | UNIPERIF_CONFIG_MEM_FMT_SHIFT(ip), \ | ||
382 | UNIPERIF_CONFIG_MEM_FMT_MASK(ip)) | ||
383 | #define SET_UNIPERIF_CONFIG_MEM_FMT(ip, value) \ | ||
384 | SET_UNIPERIF_REG(ip, \ | ||
385 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
386 | UNIPERIF_CONFIG_MEM_FMT_SHIFT(ip), \ | ||
387 | UNIPERIF_CONFIG_MEM_FMT_MASK(ip), value) | ||
388 | #define SET_UNIPERIF_CONFIG_MEM_FMT_16_0(ip) \ | ||
389 | SET_UNIPERIF_CONFIG_MEM_FMT(ip, \ | ||
390 | VALUE_UNIPERIF_CONFIG_MEM_FMT_16_0(ip)) | ||
391 | #define SET_UNIPERIF_CONFIG_MEM_FMT_16_16(ip) \ | ||
392 | SET_UNIPERIF_CONFIG_MEM_FMT(ip, \ | ||
393 | VALUE_UNIPERIF_CONFIG_MEM_FMT_16_16(ip)) | ||
394 | |||
395 | /* REPEAT_CHL_STS */ | ||
396 | #define UNIPERIF_CONFIG_REPEAT_CHL_STS_SHIFT(ip) 6 | ||
397 | #define UNIPERIF_CONFIG_REPEAT_CHL_STS_MASK(ip) 0x1 | ||
398 | #define GET_UNIPERIF_CONFIG_REPEAT_CHL_STS(ip) \ | ||
399 | GET_UNIPERIF_REG(ip, \ | ||
400 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
401 | UNIPERIF_CONFIG_REPEAT_CHL_STS_SHIFT(ip), \ | ||
402 | UNIPERIF_CONFIG_REPEAT_CHL_STS_MASK(ip)) | ||
403 | #define SET_UNIPERIF_CONFIG_REPEAT_CHL_STS_ENABLE(ip) \ | ||
404 | SET_UNIPERIF_REG(ip, \ | ||
405 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
406 | UNIPERIF_CONFIG_REPEAT_CHL_STS_SHIFT(ip), \ | ||
407 | UNIPERIF_CONFIG_REPEAT_CHL_STS_MASK(ip), 0) | ||
408 | #define SET_UNIPERIF_CONFIG_REPEAT_CHL_STS_DISABLE(ip) \ | ||
409 | SET_UNIPERIF_REG(ip, \ | ||
410 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
411 | UNIPERIF_CONFIG_REPEAT_CHL_STS_SHIFT(ip), \ | ||
412 | UNIPERIF_CONFIG_REPEAT_CHL_STS_MASK(ip), 1) | ||
413 | |||
414 | /* BACK_STALL_REQ */ | ||
415 | #define UNIPERIF_CONFIG_BACK_STALL_REQ_SHIFT(ip) \ | ||
416 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 7 : -1) | ||
417 | #define UNIPERIF_CONFIG_BACK_STALL_REQ_MASK(ip) 0x1 | ||
418 | #define GET_UNIPERIF_CONFIG_BACK_STALL_REQ(ip) \ | ||
419 | GET_UNIPERIF_REG(ip, \ | ||
420 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
421 | UNIPERIF_CONFIG_BACK_STALL_REQ_SHIFT(ip), \ | ||
422 | UNIPERIF_CONFIG_BACK_STALL_REQ_MASK(ip)) | ||
423 | #define SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(ip) \ | ||
424 | SET_UNIPERIF_REG(ip, \ | ||
425 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
426 | UNIPERIF_CONFIG_BACK_STALL_REQ_SHIFT(ip), \ | ||
427 | UNIPERIF_CONFIG_BACK_STALL_REQ_MASK(ip), 0) | ||
428 | #define SET_UNIPERIF_CONFIG_BACK_STALL_REQ_ENABLE(ip) \ | ||
429 | SET_UNIPERIF_REG(ip, \ | ||
430 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
431 | UNIPERIF_CONFIG_BACK_STALL_REQ_SHIFT(ip), \ | ||
432 | UNIPERIF_CONFIG_BACK_STALL_REQ_MASK(ip), 1) | ||
433 | |||
434 | /* FDMA_TRIGGER_LIMIT */ | ||
435 | #define UNIPERIF_CONFIG_DMA_TRIG_LIMIT_SHIFT(ip) 8 | ||
436 | #define UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(ip) 0x7F | ||
437 | #define GET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(ip) \ | ||
438 | GET_UNIPERIF_REG(ip, \ | ||
439 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
440 | UNIPERIF_CONFIG_DMA_TRIG_LIMIT_SHIFT(ip), \ | ||
441 | UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(ip)) | ||
442 | #define SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(ip, value) \ | ||
443 | SET_UNIPERIF_REG(ip, \ | ||
444 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
445 | UNIPERIF_CONFIG_DMA_TRIG_LIMIT_SHIFT(ip), \ | ||
446 | UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(ip), value) | ||
447 | |||
448 | /* CHL_STS_UPDATE */ | ||
449 | #define UNIPERIF_CONFIG_CHL_STS_UPDATE_SHIFT(ip) \ | ||
450 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 16 : -1) | ||
451 | #define UNIPERIF_CONFIG_CHL_STS_UPDATE_MASK(ip) 0x1 | ||
452 | #define GET_UNIPERIF_CONFIG_CHL_STS_UPDATE(ip) \ | ||
453 | GET_UNIPERIF_REG(ip, \ | ||
454 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
455 | UNIPERIF_CONFIG_CHL_STS_UPDATE_SHIFT(ip), \ | ||
456 | UNIPERIF_CONFIG_CHL_STS_UPDATE_MASK(ip)) | ||
457 | #define SET_UNIPERIF_CONFIG_CHL_STS_UPDATE(ip) \ | ||
458 | SET_UNIPERIF_REG(ip, \ | ||
459 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
460 | UNIPERIF_CONFIG_CHL_STS_UPDATE_SHIFT(ip), \ | ||
461 | UNIPERIF_CONFIG_CHL_STS_UPDATE_MASK(ip), 1) | ||
462 | |||
463 | /* IDLE_MOD */ | ||
464 | #define UNIPERIF_CONFIG_IDLE_MOD_SHIFT(ip) 18 | ||
465 | #define UNIPERIF_CONFIG_IDLE_MOD_MASK(ip) 0x1 | ||
466 | #define GET_UNIPERIF_CONFIG_IDLE_MOD(ip) \ | ||
467 | GET_UNIPERIF_REG(ip, \ | ||
468 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
469 | UNIPERIF_CONFIG_IDLE_MOD_SHIFT(ip), \ | ||
470 | UNIPERIF_CONFIG_IDLE_MOD_MASK(ip)) | ||
471 | #define SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(ip) \ | ||
472 | SET_UNIPERIF_REG(ip, \ | ||
473 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
474 | UNIPERIF_CONFIG_IDLE_MOD_SHIFT(ip), \ | ||
475 | UNIPERIF_CONFIG_IDLE_MOD_MASK(ip), 0) | ||
476 | #define SET_UNIPERIF_CONFIG_IDLE_MOD_ENABLE(ip) \ | ||
477 | SET_UNIPERIF_REG(ip, \ | ||
478 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
479 | UNIPERIF_CONFIG_IDLE_MOD_SHIFT(ip), \ | ||
480 | UNIPERIF_CONFIG_IDLE_MOD_MASK(ip), 1) | ||
481 | |||
482 | /* SUBFRAME_SELECTION */ | ||
483 | #define UNIPERIF_CONFIG_SUBFRAME_SEL_SHIFT(ip) 19 | ||
484 | #define UNIPERIF_CONFIG_SUBFRAME_SEL_MASK(ip) 0x1 | ||
485 | #define GET_UNIPERIF_CONFIG_SUBFRAME_SEL(ip) \ | ||
486 | GET_UNIPERIF_REG(ip, \ | ||
487 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
488 | UNIPERIF_CONFIG_SUBFRAME_SEL_SHIFT(ip), \ | ||
489 | UNIPERIF_CONFIG_SUBFRAME_SEL_MASK(ip)) | ||
490 | #define SET_UNIPERIF_CONFIG_SUBFRAME_SEL_SUBF1_SUBF0(ip) \ | ||
491 | SET_UNIPERIF_REG(ip, \ | ||
492 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
493 | UNIPERIF_CONFIG_SUBFRAME_SEL_SHIFT(ip), \ | ||
494 | UNIPERIF_CONFIG_SUBFRAME_SEL_MASK(ip), 1) | ||
495 | #define SET_UNIPERIF_CONFIG_SUBFRAME_SEL_SUBF0_SUBF1(ip) \ | ||
496 | SET_UNIPERIF_REG(ip, \ | ||
497 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
498 | UNIPERIF_CONFIG_SUBFRAME_SEL_SHIFT(ip), \ | ||
499 | UNIPERIF_CONFIG_SUBFRAME_SEL_MASK(ip), 0) | ||
500 | |||
501 | /* FULL_SW_CONTROL */ | ||
502 | #define UNIPERIF_CONFIG_SPDIF_SW_CTRL_SHIFT(ip) 20 | ||
503 | #define UNIPERIF_CONFIG_SPDIF_SW_CTRL_MASK(ip) 0x1 | ||
504 | #define GET_UNIPERIF_CONFIG_SPDIF_SW_CTRL(ip) \ | ||
505 | GET_UNIPERIF_REG(ip, \ | ||
506 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
507 | UNIPERIF_CONFIG_SPDIF_SW_CTRL_SHIFT(ip), \ | ||
508 | UNIPERIF_CONFIG_SPDIF_SW_CTRL_MASK(ip)) | ||
509 | #define SET_UNIPERIF_CONFIG_SPDIF_SW_CTRL_ENABLE(ip) \ | ||
510 | SET_UNIPERIF_REG(ip, \ | ||
511 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
512 | UNIPERIF_CONFIG_SPDIF_SW_CTRL_SHIFT(ip), \ | ||
513 | UNIPERIF_CONFIG_SPDIF_SW_CTRL_MASK(ip), 1) | ||
514 | #define SET_UNIPERIF_CONFIG_SPDIF_SW_CTRL_DISABLE(ip) \ | ||
515 | SET_UNIPERIF_REG(ip, \ | ||
516 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
517 | UNIPERIF_CONFIG_SPDIF_SW_CTRL_SHIFT(ip), \ | ||
518 | UNIPERIF_CONFIG_SPDIF_SW_CTRL_MASK(ip), 0) | ||
519 | |||
520 | /* MASTER_CLKEDGE */ | ||
521 | #define UNIPERIF_CONFIG_MSTR_CLKEDGE_SHIFT(ip) \ | ||
522 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 24 : -1) | ||
523 | #define UNIPERIF_CONFIG_MSTR_CLKEDGE_MASK(ip) 0x1 | ||
524 | #define GET_UNIPERIF_CONFIG_MSTR_CLKEDGE(ip) \ | ||
525 | GET_UNIPERIF_REG(ip, \ | ||
526 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
527 | UNIPERIF_CONFIG_MSTR_CLKEDGE_SHIFT(ip), \ | ||
528 | UNIPERIF_CONFIG_MSTR_CLKEDGE_MASK(ip)) | ||
529 | #define SET_UNIPERIF_CONFIG_MSTR_CLKEDGE_FALLING(ip) \ | ||
530 | SET_UNIPERIF_REG(ip, \ | ||
531 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
532 | UNIPERIF_CONFIG_MSTR_CLKEDGE_SHIFT(ip), \ | ||
533 | UNIPERIF_CONFIG_MSTR_CLKEDGE_MASK(ip), 1) | ||
534 | #define SET_UNIPERIF_CONFIG_MSTR_CLKEDGE_RISING(ip) \ | ||
535 | SET_UNIPERIF_REG(ip, \ | ||
536 | UNIPERIF_CONFIG_OFFSET(ip), \ | ||
537 | UNIPERIF_CONFIG_MSTR_CLKEDGE_SHIFT(ip), \ | ||
538 | UNIPERIF_CONFIG_MSTR_CLKEDGE_MASK(ip), 0) | ||
539 | |||
540 | /* | ||
541 | * UNIPERIF_CTRL reg | ||
542 | */ | ||
543 | |||
544 | #define UNIPERIF_CTRL_OFFSET(ip) 0x0044 | ||
545 | #define GET_UNIPERIF_CTRL(ip) \ | ||
546 | readl_relaxed(ip->base + UNIPERIF_CTRL_OFFSET(ip)) | ||
547 | #define SET_UNIPERIF_CTRL(ip, value) \ | ||
548 | writel_relaxed(value, ip->base + UNIPERIF_CTRL_OFFSET(ip)) | ||
549 | |||
550 | /* OPERATION */ | ||
551 | #define UNIPERIF_CTRL_OPERATION_SHIFT(ip) 0 | ||
552 | #define UNIPERIF_CTRL_OPERATION_MASK(ip) 0x7 | ||
553 | #define GET_UNIPERIF_CTRL_OPERATION(ip) \ | ||
554 | GET_UNIPERIF_REG(ip, \ | ||
555 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
556 | UNIPERIF_CTRL_OPERATION_SHIFT(ip), \ | ||
557 | UNIPERIF_CTRL_OPERATION_MASK(ip)) | ||
558 | #define VALUE_UNIPERIF_CTRL_OPERATION_OFF(ip) 0 | ||
559 | #define SET_UNIPERIF_CTRL_OPERATION_OFF(ip) \ | ||
560 | SET_UNIPERIF_REG(ip, \ | ||
561 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
562 | UNIPERIF_CTRL_OPERATION_SHIFT(ip), \ | ||
563 | UNIPERIF_CTRL_OPERATION_MASK(ip), \ | ||
564 | VALUE_UNIPERIF_CTRL_OPERATION_OFF(ip)) | ||
565 | #define VALUE_UNIPERIF_CTRL_OPERATION_MUTE_PCM_NULL(ip) \ | ||
566 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 1 : -1) | ||
567 | #define SET_UNIPERIF_CTRL_OPERATION_MUTE_PCM_NULL(ip) \ | ||
568 | SET_UNIPERIF_REG(ip, \ | ||
569 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
570 | UNIPERIF_CTRL_OPERATION_SHIFT(ip), \ | ||
571 | UNIPERIF_CTRL_OPERATION_MASK(ip), \ | ||
572 | VALUE_UNIPERIF_CTRL_OPERATION_MUTE_PCM_NULL(ip)) | ||
573 | #define VALUE_UNIPERIF_CTRL_OPERATION_MUTE_PAUSE_BURST(ip) \ | ||
574 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 2 : -1) | ||
575 | #define SET_UNIPERIF_CTRL_OPERATION_MUTE_PAUSE_BURST(ip) \ | ||
576 | SET_UNIPERIF_REG(ip, \ | ||
577 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
578 | UNIPERIF_CTRL_OPERATION_SHIFT(ip), \ | ||
579 | UNIPERIF_CTRL_OPERATION_MASK(ip), \ | ||
580 | VALUE_UNIPERIF_CTRL_OPERATION_MUTE_PAUSE_BURST(ip)) | ||
581 | #define VALUE_UNIPERIF_CTRL_OPERATION_PCM_DATA(ip) 3 | ||
582 | #define SET_UNIPERIF_CTRL_OPERATION_PCM_DATA(ip) \ | ||
583 | SET_UNIPERIF_REG(ip, \ | ||
584 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
585 | UNIPERIF_CTRL_OPERATION_SHIFT(ip), \ | ||
586 | UNIPERIF_CTRL_OPERATION_MASK(ip), \ | ||
587 | VALUE_UNIPERIF_CTRL_OPERATION_PCM_DATA(ip)) | ||
588 | /* This is the same as above! */ | ||
589 | #define VALUE_UNIPERIF_CTRL_OPERATION_AUDIO_DATA(ip) 3 | ||
590 | #define SET_UNIPERIF_CTRL_OPERATION_AUDIO_DATA(ip) \ | ||
591 | SET_UNIPERIF_REG(ip, \ | ||
592 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
593 | UNIPERIF_CTRL_OPERATION_SHIFT(ip), \ | ||
594 | UNIPERIF_CTRL_OPERATION_MASK(ip), \ | ||
595 | VALUE_UNIPERIF_CTRL_OPERATION_AUDIO_DATA(ip)) | ||
596 | #define VALUE_UNIPERIF_CTRL_OPERATION_ENC_DATA(ip) 4 | ||
597 | #define SET_UNIPERIF_CTRL_OPERATION_ENC_DATA(ip) \ | ||
598 | SET_UNIPERIF_REG(ip, \ | ||
599 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
600 | UNIPERIF_CTRL_OPERATION_SHIFT(ip), \ | ||
601 | UNIPERIF_CTRL_OPERATION_MASK(ip), \ | ||
602 | VALUE_UNIPERIF_CTRL_OPERATION_ENC_DATA(ip)) | ||
603 | #define VALUE_UNIPERIF_CTRL_OPERATION_CD_DATA(ip) \ | ||
604 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 5 : -1) | ||
605 | #define SET_UNIPERIF_CTRL_OPERATION_CD_DATA(ip) \ | ||
606 | SET_UNIPERIF_REG(ip, \ | ||
607 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
608 | UNIPERIF_CTRL_OPERATION_SHIFT(ip), \ | ||
609 | UNIPERIF_CTRL_OPERATION_MASK(ip), \ | ||
610 | VALUE_UNIPERIF_CTRL_OPERATION_CD_DATA(ip)) | ||
611 | #define VALUE_UNIPERIF_CTRL_OPERATION_STANDBY(ip) \ | ||
612 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 7) | ||
613 | #define SET_UNIPERIF_CTRL_OPERATION_STANDBY(ip) \ | ||
614 | SET_UNIPERIF_REG(ip, \ | ||
615 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
616 | UNIPERIF_CTRL_OPERATION_SHIFT(ip), \ | ||
617 | UNIPERIF_CTRL_OPERATION_MASK(ip), \ | ||
618 | VALUE_UNIPERIF_CTRL_OPERATION_STANDBY(ip)) | ||
619 | |||
620 | /* EXIT_STBY_ON_EOBLOCK */ | ||
621 | #define UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_SHIFT(ip) \ | ||
622 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 3) | ||
623 | #define UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_MASK(ip) 0x1 | ||
624 | #define GET_UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK(ip) \ | ||
625 | GET_UNIPERIF_REG(ip, \ | ||
626 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
627 | UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_SHIFT(ip), \ | ||
628 | UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_MASK(ip)) | ||
629 | #define SET_UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_OFF(ip) \ | ||
630 | SET_UNIPERIF_REG(ip, \ | ||
631 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
632 | UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_SHIFT(ip), \ | ||
633 | UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_MASK(ip), 0) | ||
634 | #define SET_UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_ON(ip) \ | ||
635 | SET_UNIPERIF_REG(ip, \ | ||
636 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
637 | UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_SHIFT(ip), \ | ||
638 | UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_MASK(ip), 1) | ||
639 | |||
640 | /* ROUNDING */ | ||
641 | #define UNIPERIF_CTRL_ROUNDING_SHIFT(ip) 4 | ||
642 | #define UNIPERIF_CTRL_ROUNDING_MASK(ip) 0x1 | ||
643 | #define GET_UNIPERIF_CTRL_ROUNDING(ip) \ | ||
644 | GET_UNIPERIF_REG(ip, \ | ||
645 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
646 | UNIPERIF_CTRL_ROUNDING_SHIFT(ip), \ | ||
647 | UNIPERIF_CTRL_ROUNDING_MASK(ip)) | ||
648 | #define SET_UNIPERIF_CTRL_ROUNDING_OFF(ip) \ | ||
649 | SET_UNIPERIF_REG(ip, \ | ||
650 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
651 | UNIPERIF_CTRL_ROUNDING_SHIFT(ip), \ | ||
652 | UNIPERIF_CTRL_ROUNDING_MASK(ip), 0) | ||
653 | #define SET_UNIPERIF_CTRL_ROUNDING_ON(ip) \ | ||
654 | SET_UNIPERIF_REG(ip, \ | ||
655 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
656 | UNIPERIF_CTRL_ROUNDING_SHIFT(ip), \ | ||
657 | UNIPERIF_CTRL_ROUNDING_MASK(ip), 1) | ||
658 | |||
659 | /* DIVIDER */ | ||
660 | #define UNIPERIF_CTRL_DIVIDER_SHIFT(ip) 5 | ||
661 | #define UNIPERIF_CTRL_DIVIDER_MASK(ip) 0xff | ||
662 | #define GET_UNIPERIF_CTRL_DIVIDER(ip) \ | ||
663 | GET_UNIPERIF_REG(ip, \ | ||
664 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
665 | UNIPERIF_CTRL_DIVIDER_SHIFT(ip), \ | ||
666 | UNIPERIF_CTRL_DIVIDER_MASK(ip)) | ||
667 | #define SET_UNIPERIF_CTRL_DIVIDER(ip, value) \ | ||
668 | SET_UNIPERIF_REG(ip, \ | ||
669 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
670 | UNIPERIF_CTRL_DIVIDER_SHIFT(ip), \ | ||
671 | UNIPERIF_CTRL_DIVIDER_MASK(ip), value) | ||
672 | |||
673 | /* BYTE_SWAP */ | ||
674 | #define UNIPERIF_CTRL_BYTE_SWP_SHIFT(ip) \ | ||
675 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 13 : -1) | ||
676 | #define UNIPERIF_CTRL_BYTE_SWP_MASK(ip) 0x1 | ||
677 | #define GET_UNIPERIF_CTRL_BYTE_SWP(ip) \ | ||
678 | GET_UNIPERIF_REG(ip, \ | ||
679 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
680 | UNIPERIF_CTRL_BYTE_SWP_SHIFT(ip), \ | ||
681 | UNIPERIF_CTRL_BYTE_SWP_MASK(ip)) | ||
682 | #define SET_UNIPERIF_CTRL_BYTE_SWP_OFF(ip) \ | ||
683 | SET_UNIPERIF_REG(ip, \ | ||
684 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
685 | UNIPERIF_CTRL_BYTE_SWP_SHIFT(ip), \ | ||
686 | UNIPERIF_CTRL_BYTE_SWP_MASK(ip), 0) | ||
687 | #define SET_UNIPERIF_CTRL_BYTE_SWP_ON(ip) \ | ||
688 | SET_UNIPERIF_REG(ip, \ | ||
689 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
690 | UNIPERIF_CTRL_BYTE_SWP_SHIFT(ip), \ | ||
691 | UNIPERIF_CTRL_BYTE_SWP_MASK(ip), 1) | ||
692 | |||
693 | /* ZERO_STUFFING_HW_SW */ | ||
694 | #define UNIPERIF_CTRL_ZERO_STUFF_SHIFT(ip) \ | ||
695 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 14 : -1) | ||
696 | #define UNIPERIF_CTRL_ZERO_STUFF_MASK(ip) 0x1 | ||
697 | #define GET_UNIPERIF_CTRL_ZERO_STUFF(ip) \ | ||
698 | GET_UNIPERIF_REG(ip, \ | ||
699 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
700 | UNIPERIF_CTRL_ZERO_STUFF_SHIFT(ip), \ | ||
701 | UNIPERIF_CTRL_ZERO_STUFF_MASK(ip)) | ||
702 | #define SET_UNIPERIF_CTRL_ZERO_STUFF_HW(ip) \ | ||
703 | SET_UNIPERIF_REG(ip, \ | ||
704 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
705 | UNIPERIF_CTRL_ZERO_STUFF_SHIFT(ip), \ | ||
706 | UNIPERIF_CTRL_ZERO_STUFF_MASK(ip), 1) | ||
707 | #define SET_UNIPERIF_CTRL_ZERO_STUFF_SW(ip) \ | ||
708 | SET_UNIPERIF_REG(ip, \ | ||
709 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
710 | UNIPERIF_CTRL_ZERO_STUFF_SHIFT(ip), \ | ||
711 | UNIPERIF_CTRL_ZERO_STUFF_MASK(ip), 0) | ||
712 | |||
713 | /* SPDIF_LAT */ | ||
714 | #define UNIPERIF_CTRL_SPDIF_LAT_SHIFT(ip) \ | ||
715 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 16 : -1) | ||
716 | #define UNIPERIF_CTRL_SPDIF_LAT_MASK(ip) 0x1 | ||
717 | #define GET_UNIPERIF_CTRL_SPDIF_LAT(ip) \ | ||
718 | GET_UNIPERIF_REG(ip, \ | ||
719 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
720 | UNIPERIF_CTRL_SPDIF_LAT_SHIFT(ip), \ | ||
721 | UNIPERIF_CTRL_SPDIF_LAT_MASK(ip)) | ||
722 | #define SET_UNIPERIF_CTRL_SPDIF_LAT_ON(ip) \ | ||
723 | SET_UNIPERIF_REG(ip, \ | ||
724 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
725 | UNIPERIF_CTRL_SPDIF_LAT_SHIFT(ip), \ | ||
726 | UNIPERIF_CTRL_SPDIF_LAT_MASK(ip), 1) | ||
727 | #define SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(ip) \ | ||
728 | SET_UNIPERIF_REG(ip, \ | ||
729 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
730 | UNIPERIF_CTRL_SPDIF_LAT_SHIFT(ip), \ | ||
731 | UNIPERIF_CTRL_SPDIF_LAT_MASK(ip), 0) | ||
732 | |||
733 | /* EN_SPDIF_FORMATTING */ | ||
734 | #define UNIPERIF_CTRL_SPDIF_FMT_SHIFT(ip) 17 | ||
735 | #define UNIPERIF_CTRL_SPDIF_FMT_MASK(ip) 0x1 | ||
736 | #define GET_UNIPERIF_CTRL_SPDIF_FMT(ip) \ | ||
737 | GET_UNIPERIF_REG(ip, \ | ||
738 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
739 | UNIPERIF_CTRL_SPDIF_FMT_SHIFT(ip), \ | ||
740 | UNIPERIF_CTRL_SPDIF_FMT_MASK(ip)) | ||
741 | #define SET_UNIPERIF_CTRL_SPDIF_FMT_ON(ip) \ | ||
742 | SET_UNIPERIF_REG(ip, \ | ||
743 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
744 | UNIPERIF_CTRL_SPDIF_FMT_SHIFT(ip), \ | ||
745 | UNIPERIF_CTRL_SPDIF_FMT_MASK(ip), 1) | ||
746 | #define SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(ip) \ | ||
747 | SET_UNIPERIF_REG(ip, \ | ||
748 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
749 | UNIPERIF_CTRL_SPDIF_FMT_SHIFT(ip), \ | ||
750 | UNIPERIF_CTRL_SPDIF_FMT_MASK(ip), 0) | ||
751 | |||
752 | /* READER_OUT_SELECT */ | ||
753 | #define UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip) \ | ||
754 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 18 : -1) | ||
755 | #define UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip) 0x1 | ||
756 | #define GET_UNIPERIF_CTRL_READER_OUT_SEL(ip) \ | ||
757 | GET_UNIPERIF_REG(ip, \ | ||
758 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
759 | UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip), \ | ||
760 | UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip)) | ||
761 | #define SET_UNIPERIF_CTRL_READER_OUT_SEL_IN_MEM(ip) \ | ||
762 | SET_UNIPERIF_REG(ip, \ | ||
763 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
764 | UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip), \ | ||
765 | UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 0) | ||
766 | #define SET_UNIPERIF_CTRL_READER_OUT_SEL_ON_I2S_LINE(ip) \ | ||
767 | SET_UNIPERIF_REG(ip, \ | ||
768 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
769 | UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip), \ | ||
770 | CORAUD_UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 1) | ||
771 | |||
772 | /* UNDERFLOW_REC_WINDOW */ | ||
773 | #define UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_SHIFT(ip) 20 | ||
774 | #define UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_MASK(ip) 0xff | ||
775 | #define GET_UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW(ip) \ | ||
776 | GET_UNIPERIF_REG(ip, \ | ||
777 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
778 | UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_SHIFT(ip), \ | ||
779 | UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_MASK(ip)) | ||
780 | #define SET_UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW(ip, value) \ | ||
781 | SET_UNIPERIF_REG(ip, \ | ||
782 | UNIPERIF_CTRL_OFFSET(ip), \ | ||
783 | UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_SHIFT(ip), \ | ||
784 | UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_MASK(ip), value) | ||
785 | |||
786 | /* | ||
787 | * UNIPERIF_I2S_FMT a.k.a UNIPERIF_FORMAT reg | ||
788 | */ | ||
789 | |||
790 | #define UNIPERIF_I2S_FMT_OFFSET(ip) 0x0048 | ||
791 | #define GET_UNIPERIF_I2S_FMT(ip) \ | ||
792 | readl_relaxed(ip->base + UNIPERIF_I2S_FMT_OFFSET(ip)) | ||
793 | #define SET_UNIPERIF_I2S_FMT(ip, value) \ | ||
794 | writel_relaxed(value, ip->base + UNIPERIF_I2S_FMT_OFFSET(ip)) | ||
795 | |||
796 | /* NBIT */ | ||
797 | #define UNIPERIF_I2S_FMT_NBIT_SHIFT(ip) 0 | ||
798 | #define UNIPERIF_I2S_FMT_NBIT_MASK(ip) 0x1 | ||
799 | #define GET_UNIPERIF_I2S_FMT_NBIT(ip) \ | ||
800 | GET_UNIPERIF_REG(ip, \ | ||
801 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
802 | UNIPERIF_I2S_FMT_NBIT_SHIFT(ip), \ | ||
803 | UNIPERIF_I2S_FMT_NBIT_MASK(ip)) | ||
804 | #define SET_UNIPERIF_I2S_FMT_NBIT_32(ip) \ | ||
805 | SET_UNIPERIF_REG(ip, \ | ||
806 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
807 | UNIPERIF_I2S_FMT_NBIT_SHIFT(ip), \ | ||
808 | UNIPERIF_I2S_FMT_NBIT_MASK(ip), 0) | ||
809 | #define SET_UNIPERIF_I2S_FMT_NBIT_16(ip) \ | ||
810 | SET_UNIPERIF_REG(ip, \ | ||
811 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
812 | UNIPERIF_I2S_FMT_NBIT_SHIFT(ip), \ | ||
813 | UNIPERIF_I2S_FMT_NBIT_MASK(ip), 1) | ||
814 | |||
815 | /* DATA_SIZE */ | ||
816 | #define UNIPERIF_I2S_FMT_DATA_SIZE_SHIFT(ip) 1 | ||
817 | #define UNIPERIF_I2S_FMT_DATA_SIZE_MASK(ip) 0x7 | ||
818 | #define GET_UNIPERIF_I2S_FMT_DATA_SIZE(ip) \ | ||
819 | GET_UNIPERIF_REG(ip, \ | ||
820 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
821 | UNIPERIF_I2S_FMT_DATA_SIZE_SHIFT(ip), \ | ||
822 | UNIPERIF_I2S_FMT_DATA_SIZE_MASK(ip)) | ||
823 | #define SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(ip) \ | ||
824 | SET_UNIPERIF_REG(ip, \ | ||
825 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
826 | UNIPERIF_I2S_FMT_DATA_SIZE_SHIFT(ip), \ | ||
827 | UNIPERIF_I2S_FMT_DATA_SIZE_MASK(ip), 0) | ||
828 | #define SET_UNIPERIF_I2S_FMT_DATA_SIZE_18(ip) \ | ||
829 | SET_UNIPERIF_REG(ip, \ | ||
830 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
831 | UNIPERIF_I2S_FMT_DATA_SIZE_SHIFT(ip), \ | ||
832 | UNIPERIF_I2S_FMT_DATA_SIZE_MASK(ip), 1) | ||
833 | #define SET_UNIPERIF_I2S_FMT_DATA_SIZE_20(ip) \ | ||
834 | SET_UNIPERIF_REG(ip, \ | ||
835 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
836 | UNIPERIF_I2S_FMT_DATA_SIZE_SHIFT(ip), \ | ||
837 | UNIPERIF_I2S_FMT_DATA_SIZE_MASK(ip), 2) | ||
838 | #define SET_UNIPERIF_I2S_FMT_DATA_SIZE_24(ip) \ | ||
839 | SET_UNIPERIF_REG(ip, \ | ||
840 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
841 | UNIPERIF_I2S_FMT_DATA_SIZE_SHIFT(ip), \ | ||
842 | UNIPERIF_I2S_FMT_DATA_SIZE_MASK(ip), 3) | ||
843 | #define SET_UNIPERIF_I2S_FMTL_DATA_SIZE_28(ip) \ | ||
844 | SET_UNIPERIF_REG(ip, \ | ||
845 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
846 | UNIPERIF_I2S_FMT_DATA_SIZE_SHIFT(ip), \ | ||
847 | UNIPERIF_I2S_FMT_DATA_SIZE_MASK(ip), 4) | ||
848 | #define SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(ip) \ | ||
849 | SET_UNIPERIF_REG(ip, \ | ||
850 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
851 | UNIPERIF_I2S_FMT_DATA_SIZE_SHIFT(ip), \ | ||
852 | UNIPERIF_I2S_FMT_DATA_SIZE_MASK(ip), 5) | ||
853 | |||
854 | /* LR_POL */ | ||
855 | #define UNIPERIF_I2S_FMT_LR_POL_SHIFT(ip) 4 | ||
856 | #define UNIPERIF_I2S_FMT_LR_POL_MASK(ip) 0x1 | ||
857 | #define VALUE_UNIPERIF_I2S_FMT_LR_POL_LOW(ip) 0x0 | ||
858 | #define VALUE_UNIPERIF_I2S_FMT_LR_POL_HIG(ip) 0x1 | ||
859 | #define GET_UNIPERIF_I2S_FMT_LR_POL(ip) \ | ||
860 | GET_UNIPERIF_REG(ip, \ | ||
861 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
862 | UNIPERIF_I2S_FMT_LR_POL_SHIFT(ip), \ | ||
863 | UNIPERIF_I2S_FMT_LR_POL_MASK(ip)) | ||
864 | #define SET_UNIPERIF_I2S_FMT_LR_POL(ip, value) \ | ||
865 | SET_UNIPERIF_REG(ip, \ | ||
866 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
867 | UNIPERIF_I2S_FMT_LR_POL_SHIFT(ip), \ | ||
868 | UNIPERIF_I2S_FMT_LR_POL_MASK(ip), value) | ||
869 | #define SET_UNIPERIF_I2S_FMT_LR_POL_LOW(ip) \ | ||
870 | SET_UNIPERIF_I2S_FMT_LR_POL(ip, \ | ||
871 | VALUE_UNIPERIF_I2S_FMT_LR_POL_LOW(ip)) | ||
872 | #define SET_UNIPERIF_I2S_FMT_LR_POL_HIG(ip) \ | ||
873 | SET_UNIPERIF_I2S_FMT_LR_POL(ip, \ | ||
874 | VALUE_UNIPERIF_I2S_FMT_LR_POL_HIG(ip)) | ||
875 | |||
876 | /* SCLK_EDGE */ | ||
877 | #define UNIPERIF_I2S_FMT_SCLK_EDGE_SHIFT(ip) 5 | ||
878 | #define UNIPERIF_I2S_FMT_SCLK_EDGE_MASK(ip) 0x1 | ||
879 | #define GET_UNIPERIF_I2S_FMT_SCLK_EDGE(ip) \ | ||
880 | GET_UNIPERIF_REG(ip, \ | ||
881 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
882 | UNIPERIF_I2S_FMT_SCLK_EDGE_SHIFT(ip), \ | ||
883 | UNIPERIF_I2S_FMT_SCLK_EDGE_MASK(ip)) | ||
884 | #define SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(ip) \ | ||
885 | SET_UNIPERIF_REG(ip, \ | ||
886 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
887 | UNIPERIF_I2S_FMT_SCLK_EDGE_SHIFT(ip), \ | ||
888 | UNIPERIF_I2S_FMT_SCLK_EDGE_MASK(ip), 0) | ||
889 | #define SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(ip) \ | ||
890 | SET_UNIPERIF_REG(ip, \ | ||
891 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
892 | UNIPERIF_I2S_FMT_SCLK_EDGE_SHIFT(ip), \ | ||
893 | UNIPERIF_I2S_FMT_SCLK_EDGE_MASK(ip), 1) | ||
894 | |||
895 | /* PADDING */ | ||
896 | #define UNIPERIF_I2S_FMT_PADDING_SHIFT(ip) 6 | ||
897 | #define UNIPERIF_I2S_FMT_PADDING_MASK(ip) 0x1 | ||
898 | #define UNIPERIF_I2S_FMT_PADDING_MASK(ip) 0x1 | ||
899 | #define VALUE_UNIPERIF_I2S_FMT_PADDING_I2S_MODE(ip) 0x0 | ||
900 | #define VALUE_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(ip) 0x1 | ||
901 | #define GET_UNIPERIF_I2S_FMT_PADDING(ip) \ | ||
902 | GET_UNIPERIF_REG(ip, \ | ||
903 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
904 | UNIPERIF_I2S_FMT_PADDING_SHIFT(ip), \ | ||
905 | UNIPERIF_I2S_FMT_PADDING_MASK(ip)) | ||
906 | #define SET_UNIPERIF_I2S_FMT_PADDING(ip, value) \ | ||
907 | SET_UNIPERIF_REG(ip, \ | ||
908 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
909 | UNIPERIF_I2S_FMT_PADDING_SHIFT(ip), \ | ||
910 | UNIPERIF_I2S_FMT_PADDING_MASK(ip), value) | ||
911 | #define SET_UNIPERIF_I2S_FMT_PADDING_I2S_MODE(ip) \ | ||
912 | SET_UNIPERIF_I2S_FMT_PADDING(ip, \ | ||
913 | VALUE_UNIPERIF_I2S_FMT_PADDING_I2S_MODE(ip)) | ||
914 | #define SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(ip) \ | ||
915 | SET_UNIPERIF_I2S_FMT_PADDING(ip, \ | ||
916 | VALUE_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(ip)) | ||
917 | |||
918 | /* ALIGN */ | ||
919 | #define UNIPERIF_I2S_FMT_ALIGN_SHIFT(ip) 7 | ||
920 | #define UNIPERIF_I2S_FMT_ALIGN_MASK(ip) 0x1 | ||
921 | #define GET_UNIPERIF_I2S_FMT_ALIGN(ip) \ | ||
922 | GET_UNIPERIF_REG(ip, \ | ||
923 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
924 | UNIPERIF_I2S_FMT_ALIGN_SHIFT(ip), \ | ||
925 | UNIPERIF_I2S_FMT_ALIGN_MASK(ip)) | ||
926 | #define SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(ip) \ | ||
927 | SET_UNIPERIF_REG(ip, \ | ||
928 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
929 | UNIPERIF_I2S_FMT_ALIGN_SHIFT(ip), \ | ||
930 | UNIPERIF_I2S_FMT_ALIGN_MASK(ip), 0) | ||
931 | #define SET_UNIPERIF_I2S_FMT_ALIGN_RIGHT(ip) \ | ||
932 | SET_UNIPERIF_REG(ip, \ | ||
933 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
934 | UNIPERIF_I2S_FMT_ALIGN_SHIFT(ip), \ | ||
935 | UNIPERIF_I2S_FMT_ALIGN_MASK(ip), 1) | ||
936 | |||
937 | /* ORDER */ | ||
938 | #define UNIPERIF_I2S_FMT_ORDER_SHIFT(ip) 8 | ||
939 | #define UNIPERIF_I2S_FMT_ORDER_MASK(ip) 0x1 | ||
940 | #define GET_UNIPERIF_I2S_FMT_ORDER(ip) \ | ||
941 | GET_UNIPERIF_REG(ip, \ | ||
942 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
943 | UNIPERIF_I2S_FMT_ORDER_SHIFT(ip), \ | ||
944 | UNIPERIF_I2S_FMT_ORDER_MASK(ip)) | ||
945 | #define SET_UNIPERIF_I2S_FMT_ORDER_LSB(ip) \ | ||
946 | SET_UNIPERIF_REG(ip, \ | ||
947 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
948 | UNIPERIF_I2S_FMT_ORDER_SHIFT(ip), \ | ||
949 | UNIPERIF_I2S_FMT_ORDER_MASK(ip), 0) | ||
950 | #define SET_UNIPERIF_I2S_FMT_ORDER_MSB(ip) \ | ||
951 | SET_UNIPERIF_REG(ip, \ | ||
952 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
953 | UNIPERIF_I2S_FMT_ORDER_SHIFT(ip), \ | ||
954 | UNIPERIF_I2S_FMT_ORDER_MASK(ip), 1) | ||
955 | |||
956 | /* NUM_CH */ | ||
957 | #define UNIPERIF_I2S_FMT_NUM_CH_SHIFT(ip) 9 | ||
958 | #define UNIPERIF_I2S_FMT_NUM_CH_MASK(ip) 0x7 | ||
959 | #define GET_UNIPERIF_I2S_FMT_NUM_CH(ip) \ | ||
960 | GET_UNIPERIF_REG(ip, \ | ||
961 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
962 | UNIPERIF_I2S_FMT_NUM_CH_SHIFT(ip), \ | ||
963 | UNIPERIF_I2S_FMT_NUM_CH_MASK(ip)) | ||
964 | #define SET_UNIPERIF_I2S_FMT_NUM_CH(ip, value) \ | ||
965 | SET_UNIPERIF_REG(ip, \ | ||
966 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
967 | UNIPERIF_I2S_FMT_NUM_CH_SHIFT(ip), \ | ||
968 | UNIPERIF_I2S_FMT_NUM_CH_MASK(ip), value) | ||
969 | |||
970 | /* NO_OF_SAMPLES_TO_READ */ | ||
971 | #define UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ_SHIFT(ip) 12 | ||
972 | #define UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ_MASK(ip) 0xfffff | ||
973 | #define GET_UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ(ip) \ | ||
974 | GET_UNIPERIF_REG(ip, \ | ||
975 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
976 | UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ_SHIFT(ip), \ | ||
977 | UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ_MASK(ip)) | ||
978 | #define SET_UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ(ip, value) \ | ||
979 | SET_UNIPERIF_REG(ip, \ | ||
980 | UNIPERIF_I2S_FMT_OFFSET(ip), \ | ||
981 | UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ_SHIFT(ip), \ | ||
982 | UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ_MASK(ip), value) | ||
983 | |||
984 | /* | ||
985 | * UNIPERIF_BIT_CONTROL reg | ||
986 | */ | ||
987 | |||
988 | #define UNIPERIF_BIT_CONTROL_OFFSET(ip) \ | ||
989 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 0x004c) | ||
990 | #define GET_UNIPERIF_BIT_CONTROL(ip) \ | ||
991 | readl_relaxed(ip->base + UNIPERIF_BIT_CONTROL_OFFSET(ip)) | ||
992 | #define SET_UNIPERIF_BIT_CONTROL(ip, value) \ | ||
993 | writel_relaxed(value, ip->base + UNIPERIF_BIT_CONTROL_OFFSET(ip)) | ||
994 | |||
995 | /* CLR_UNDERFLOW_DURATION */ | ||
996 | #define UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION_SHIFT(ip) 0 | ||
997 | #define UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION_MASK(ip) 0x1 | ||
998 | #define GET_UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION(ip) \ | ||
999 | GET_UNIPERIF_REG(ip, \ | ||
1000 | UNIPERIF_BIT_CONTROL_OFFSET(ip), \ | ||
1001 | UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION_SHIFT(ip), \ | ||
1002 | UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION_MASK(ip)) | ||
1003 | #define SET_UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION(ip) \ | ||
1004 | SET_UNIPERIF_REG(ip, \ | ||
1005 | UNIPERIF_BIT_CONTROL_OFFSET(ip), \ | ||
1006 | UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION_SHIFT(ip), \ | ||
1007 | UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION_MASK(ip), 1) | ||
1008 | |||
1009 | /* CHL_STS_UPDATE */ | ||
1010 | #define UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE_SHIFT(ip) 1 | ||
1011 | #define UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE_MASK(ip) 0x1 | ||
1012 | #define GET_UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE(ip) \ | ||
1013 | GET_UNIPERIF_REG(ip, \ | ||
1014 | UNIPERIF_BIT_CONTROL_OFFSET(ip), \ | ||
1015 | UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE_SHIFT(ip), \ | ||
1016 | UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE_MASK(ip)) | ||
1017 | #define SET_UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE(ip) \ | ||
1018 | SET_UNIPERIF_BIT_REG(ip, \ | ||
1019 | UNIPERIF_BIT_CONTROL_OFFSET(ip), \ | ||
1020 | UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE_SHIFT(ip), \ | ||
1021 | UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE_MASK(ip), 1) | ||
1022 | |||
1023 | /* | ||
1024 | * UNIPERIF_STATUS_1 reg | ||
1025 | */ | ||
1026 | |||
1027 | #define UNIPERIF_STATUS_1_OFFSET(ip) 0x0050 | ||
1028 | #define GET_UNIPERIF_STATUS_1(ip) \ | ||
1029 | readl_relaxed(ip->base + UNIPERIF_STATUS_1_OFFSET(ip)) | ||
1030 | #define SET_UNIPERIF_STATUS_1(ip, value) \ | ||
1031 | writel_relaxed(value, ip->base + UNIPERIF_STATUS_1_OFFSET(ip)) | ||
1032 | |||
1033 | /* UNDERFLOW_DURATION */ | ||
1034 | #define UNIPERIF_STATUS_1_UNDERFLOW_DURATION_SHIFT(ip) \ | ||
1035 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 0) | ||
1036 | #define UNIPERIF_STATUS_1_UNDERFLOW_DURATION_MASK(ip) 0xff | ||
1037 | #define GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(ip) \ | ||
1038 | GET_UNIPERIF_REG(ip, \ | ||
1039 | UNIPERIF_STATUS_1_OFFSET(ip), \ | ||
1040 | UNIPERIF_STATUS_1_UNDERFLOW_DURATION_SHIFT(ip), \ | ||
1041 | UNIPERIF_STATUS_1_UNDERFLOW_DURATION_MASK(ip)) | ||
1042 | #define SET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(ip, value) \ | ||
1043 | SET_UNIPERIF_REG(ip, \ | ||
1044 | UNIPERIF_STATUS_1_OFFSET(ip), \ | ||
1045 | UNIPERIF_STATUS_1_UNDERFLOW_DURATION_SHIFT(ip), \ | ||
1046 | UNIPERIF_STATUS_1_UNDERFLOW_DURATION_MASK(ip), value) | ||
1047 | |||
1048 | /* | ||
1049 | * AUD_UNIPERIF_CHANNEL_STA_REGN reg | ||
1050 | */ | ||
1051 | |||
1052 | #define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) | ||
1053 | #define GET_UNIPERIF_CHANNEL_STA_REGN(ip) \ | ||
1054 | readl_relaxed(ip->base + UNIPERIF_CHANNEL_STA_REGN(ip, n)) | ||
1055 | #define SET_UNIPERIF_CHANNEL_STA_REGN(ip, n, value) \ | ||
1056 | writel_relaxed(value, ip->base + \ | ||
1057 | UNIPERIF_CHANNEL_STA_REGN(ip, n)) | ||
1058 | |||
1059 | /* | ||
1060 | * AUD_UNIPERIF_USER_VALIDITY reg | ||
1061 | */ | ||
1062 | |||
1063 | #define UNIPERIF_USER_VALIDITY_OFFSET(ip) 0x0090 | ||
1064 | #define GET_UNIPERIF_USER_VALIDITY(ip) \ | ||
1065 | readl_relaxed(ip->base + UNIPERIF_USER_VALIDITY_OFFSET(ip)) | ||
1066 | #define SET_UNIPERIF_USER_VALIDITY(ip, value) \ | ||
1067 | writel_relaxed(value, ip->base + UNIPERIF_USER_VALIDITY_OFFSET(ip)) | ||
1068 | |||
1069 | /* VALIDITY_LEFT_AND_RIGHT */ | ||
1070 | #define UNIPERIF_USER_VALIDITY_VALIDITY_LR_SHIFT(ip) 0 | ||
1071 | #define UNIPERIF_USER_VALIDITY_VALIDITY_LR_MASK(ip) 0x3 | ||
1072 | #define GET_UNIPERIF_USER_VALIDITY_VALIDITY_LR(ip) \ | ||
1073 | GET_UNIPERIF_REG(ip, \ | ||
1074 | UNIPERIF_USER_VALIDITY_OFFSET(ip), \ | ||
1075 | UNIPERIF_USER_VALIDITY_VALIDITY_LR_SHIFT(ip), \ | ||
1076 | UNIPERIF_USER_VALIDITY_VALIDITY_LR_MASK(ip)) | ||
1077 | #define SET_UNIPERIF_USER_VALIDITY_VALIDITY_LR(ip, value) \ | ||
1078 | SET_UNIPERIF_REG(ip, \ | ||
1079 | UNIPERIF_USER_VALIDITY_OFFSET(ip), \ | ||
1080 | UNIPERIF_USER_VALIDITY_VALIDITY_LR_SHIFT(ip), \ | ||
1081 | UNIPERIF_USER_VALIDITY_VALIDITY_LR_MASK(ip), \ | ||
1082 | value ? 0x3 : 0) | ||
1083 | |||
1084 | /* | ||
1085 | * UNIPERIF_DBG_STANDBY_LEFT_SP reg | ||
1086 | */ | ||
1087 | #define UNIPERIF_DBG_STANDBY_LEFT_SP_OFFSET(ip) 0x0150 | ||
1088 | #define UNIPERIF_DBG_STANDBY_LEFT_SP_SHIFT(ip) \ | ||
1089 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? -1 : 0) | ||
1090 | #define UNIPERIF_DBG_STANDBY_LEFT_SP_MASK(ip) \ | ||
1091 | ((ip)->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 ? 0 : 0xFFFFFF) | ||
1092 | #define GET_UNIPERIF_DBG_STANDBY_LEFT_SP(ip) \ | ||
1093 | GET_UNIPERIF_REG(ip, \ | ||
1094 | UNIPERIF_DBG_STANDBY_LEFT_SP_OFFSET(ip), \ | ||
1095 | UNIPERIF_DBG_STANDBY_LEFT_SP_SHIFT(ip), \ | ||
1096 | UNIPERIF_DBG_STANDBY_LEFT_SP_MASK(ip)) | ||
1097 | #define SET_UNIPERIF_DBG_STANDBY_LEFT_SP(ip, value) \ | ||
1098 | SET_UNIPERIF_REG(ip, \ | ||
1099 | UNIPERIF_DBG_STANDBY_LEFT_SP_OFFSET(ip), \ | ||
1100 | UNIPERIF_DBG_STANDBY_LEFT_SP_SHIFT(ip), \ | ||
1101 | UNIPERIF_DBG_STANDBY_LEFT_SP_MASK(ip), value) | ||
1102 | |||
1103 | /* | ||
1104 | * uniperipheral IP capabilities | ||
1105 | */ | ||
1106 | |||
1107 | #define UNIPERIF_FIFO_SIZE 70 /* FIFO is 70 cells deep */ | ||
1108 | #define UNIPERIF_FIFO_FRAMES 4 /* FDMA trigger limit in frames */ | ||
1109 | |||
1110 | /* | ||
1111 | * Uniperipheral IP revisions | ||
1112 | */ | ||
1113 | enum uniperif_version { | ||
1114 | SND_ST_UNIPERIF_VERSION_UNKNOWN, | ||
1115 | /* SASG1 (Orly), Newman */ | ||
1116 | SND_ST_UNIPERIF_VERSION_C6AUD0_UNI_1_0, | ||
1117 | /* SASC1, SASG2 (Orly2) */ | ||
1118 | SND_ST_UNIPERIF_VERSION_UNI_PLR_1_0, | ||
1119 | /* SASC1, SASG2 (Orly2), TELSS, Cannes */ | ||
1120 | SND_ST_UNIPERIF_VERSION_UNI_RDR_1_0, | ||
1121 | /* TELSS (SASC1) */ | ||
1122 | SND_ST_UNIPERIF_VERSION_TDM_PLR_1_0, | ||
1123 | /* Cannes/Monaco */ | ||
1124 | SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 | ||
1125 | }; | ||
1126 | |||
1127 | enum uniperif_type { | ||
1128 | SND_ST_UNIPERIF_PLAYER_TYPE_NONE, | ||
1129 | SND_ST_UNIPERIF_PLAYER_TYPE_HDMI, | ||
1130 | SND_ST_UNIPERIF_PLAYER_TYPE_PCM, | ||
1131 | SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF | ||
1132 | }; | ||
1133 | |||
1134 | enum uniperif_state { | ||
1135 | UNIPERIF_STATE_STOPPED, | ||
1136 | UNIPERIF_STATE_STARTED, | ||
1137 | UNIPERIF_STATE_STANDBY, | ||
1138 | UNIPERIF_STATE_UNDERFLOW, | ||
1139 | UNIPERIF_STATE_OVERFLOW = UNIPERIF_STATE_UNDERFLOW, | ||
1140 | UNIPERIF_STATE_XRUN | ||
1141 | }; | ||
1142 | |||
1143 | enum uniperif_iec958_encoding_mode { | ||
1144 | UNIPERIF_IEC958_ENCODING_MODE_PCM, | ||
1145 | UNIPERIF_IEC958_ENCODING_MODE_ENCODED | ||
1146 | }; | ||
1147 | |||
1148 | struct uniperif_info { | ||
1149 | int id; /* instance value of the uniperipheral IP */ | ||
1150 | enum uniperif_type player_type; | ||
1151 | int underflow_enabled; /* Underflow recovery mode */ | ||
1152 | }; | ||
1153 | |||
1154 | struct uniperif_iec958_settings { | ||
1155 | enum uniperif_iec958_encoding_mode encoding_mode; | ||
1156 | struct snd_aes_iec958 iec958; | ||
1157 | }; | ||
1158 | |||
1159 | struct uniperif { | ||
1160 | /* System information */ | ||
1161 | struct uniperif_info *info; | ||
1162 | struct device *dev; | ||
1163 | int ver; /* IP version, used by register access macros */ | ||
1164 | struct regmap_field *clk_sel; | ||
1165 | |||
1166 | /* capabilities */ | ||
1167 | const struct snd_pcm_hardware *hw; | ||
1168 | |||
1169 | /* Resources */ | ||
1170 | struct resource *mem_region; | ||
1171 | void __iomem *base; | ||
1172 | unsigned long fifo_phys_address; | ||
1173 | int irq; | ||
1174 | |||
1175 | /* Clocks */ | ||
1176 | struct clk *clk; | ||
1177 | int mclk; | ||
1178 | int clk_adj; | ||
1179 | |||
1180 | /* Runtime data */ | ||
1181 | enum uniperif_state state; | ||
1182 | |||
1183 | struct snd_pcm_substream *substream; | ||
1184 | |||
1185 | /* Specific to IEC958 player */ | ||
1186 | struct uniperif_iec958_settings stream_settings; | ||
1187 | struct mutex ctrl_lock; /* For resource updated by stream and controls*/ | ||
1188 | |||
1189 | /*alsa ctrl*/ | ||
1190 | struct snd_kcontrol_new *snd_ctrls; | ||
1191 | int num_ctrls; | ||
1192 | |||
1193 | /* dai properties */ | ||
1194 | unsigned int daifmt; | ||
1195 | |||
1196 | /* DAI callbacks */ | ||
1197 | const struct snd_soc_dai_ops *dai_ops; | ||
1198 | }; | ||
1199 | |||
1200 | struct sti_uniperiph_dai { | ||
1201 | int stream; | ||
1202 | struct uniperif *uni; | ||
1203 | struct snd_dmaengine_dai_dma_data dma_data; | ||
1204 | }; | ||
1205 | |||
1206 | struct sti_uniperiph_data { | ||
1207 | struct platform_device *pdev; | ||
1208 | struct snd_soc_dai_driver *dai; | ||
1209 | struct sti_uniperiph_dai dai_data; | ||
1210 | }; | ||
1211 | |||
1212 | /* uniperiph player*/ | ||
1213 | int uni_player_init(struct platform_device *pdev, | ||
1214 | struct uniperif *uni_player); | ||
1215 | int uni_player_resume(struct uniperif *player); | ||
1216 | |||
1217 | /* uniperiph reader */ | ||
1218 | int uni_reader_init(struct platform_device *pdev, | ||
1219 | struct uniperif *uni_reader); | ||
1220 | |||
1221 | /* common */ | ||
1222 | int sti_uniperiph_dai_set_fmt(struct snd_soc_dai *dai, | ||
1223 | unsigned int fmt); | ||
1224 | |||
1225 | int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream, | ||
1226 | struct snd_pcm_hw_params *params, | ||
1227 | struct snd_soc_dai *dai); | ||
1228 | |||
1229 | #endif | ||
diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c new file mode 100644 index 000000000000..f6eefe1b8f8f --- /dev/null +++ b/sound/soc/sti/uniperif_player.c | |||
@@ -0,0 +1,1110 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2015 | ||
3 | * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com> | ||
4 | * for STMicroelectronics. | ||
5 | * License terms: GNU General Public License (GPL), version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/clk.h> | ||
9 | #include <linux/delay.h> | ||
10 | #include <linux/io.h> | ||
11 | #include <linux/mfd/syscon.h> | ||
12 | |||
13 | #include <sound/asoundef.h> | ||
14 | #include <sound/soc.h> | ||
15 | |||
16 | #include "uniperif.h" | ||
17 | |||
18 | /* | ||
19 | * Some hardware-related definitions | ||
20 | */ | ||
21 | |||
22 | /* sys config registers definitions */ | ||
23 | #define SYS_CFG_AUDIO_GLUE 0xA4 | ||
24 | #define SYS_CFG_AUDI0_GLUE_PCM_CLKX 8 | ||
25 | |||
26 | /* | ||
27 | * Driver specific types. | ||
28 | */ | ||
29 | #define UNIPERIF_PLAYER_TYPE_IS_HDMI(p) \ | ||
30 | ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_HDMI) | ||
31 | #define UNIPERIF_PLAYER_TYPE_IS_PCM(p) \ | ||
32 | ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_PCM) | ||
33 | #define UNIPERIF_PLAYER_TYPE_IS_SPDIF(p) \ | ||
34 | ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF) | ||
35 | #define UNIPERIF_PLAYER_TYPE_IS_IEC958(p) \ | ||
36 | (UNIPERIF_PLAYER_TYPE_IS_HDMI(p) || \ | ||
37 | UNIPERIF_PLAYER_TYPE_IS_SPDIF(p)) | ||
38 | |||
39 | #define UNIPERIF_PLAYER_CLK_ADJ_MIN -999999 | ||
40 | #define UNIPERIF_PLAYER_CLK_ADJ_MAX 1000000 | ||
41 | |||
42 | /* | ||
43 | * Note: snd_pcm_hardware is linked to DMA controller but is declared here to | ||
44 | * integrate DAI_CPU capability in term of rate and supported channels | ||
45 | */ | ||
46 | static const struct snd_pcm_hardware uni_player_pcm_hw = { | ||
47 | .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
48 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP | | ||
49 | SNDRV_PCM_INFO_MMAP_VALID, | ||
50 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE, | ||
51 | |||
52 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
53 | .rate_min = 8000, | ||
54 | .rate_max = 192000, | ||
55 | |||
56 | .channels_min = 2, | ||
57 | .channels_max = 8, | ||
58 | |||
59 | .periods_min = 2, | ||
60 | .periods_max = 48, | ||
61 | |||
62 | .period_bytes_min = 128, | ||
63 | .period_bytes_max = 64 * PAGE_SIZE, | ||
64 | .buffer_bytes_max = 256 * PAGE_SIZE | ||
65 | }; | ||
66 | |||
67 | static inline int reset_player(struct uniperif *player) | ||
68 | { | ||
69 | int count = 10; | ||
70 | |||
71 | if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) { | ||
72 | while (GET_UNIPERIF_SOFT_RST_SOFT_RST(player) && count) { | ||
73 | udelay(5); | ||
74 | count--; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | if (!count) { | ||
79 | dev_err(player->dev, "Failed to reset uniperif"); | ||
80 | return -EIO; | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * uni_player_irq_handler | ||
88 | * In case of error audio stream is stopped; stop action is protected via PCM | ||
89 | * stream lock to avoid race condition with trigger callback. | ||
90 | */ | ||
91 | static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) | ||
92 | { | ||
93 | irqreturn_t ret = IRQ_NONE; | ||
94 | struct uniperif *player = dev_id; | ||
95 | unsigned int status; | ||
96 | unsigned int tmp; | ||
97 | |||
98 | if (player->state == UNIPERIF_STATE_STOPPED) { | ||
99 | /* Unexpected IRQ: do nothing */ | ||
100 | return IRQ_NONE; | ||
101 | } | ||
102 | |||
103 | /* Get interrupt status & clear them immediately */ | ||
104 | status = GET_UNIPERIF_ITS(player); | ||
105 | SET_UNIPERIF_ITS_BCLR(player, status); | ||
106 | |||
107 | /* Check for fifo error (underrun) */ | ||
108 | if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(player))) { | ||
109 | dev_err(player->dev, "FIFO underflow error detected"); | ||
110 | |||
111 | /* Interrupt is just for information when underflow recovery */ | ||
112 | if (player->info->underflow_enabled) { | ||
113 | /* Update state to underflow */ | ||
114 | player->state = UNIPERIF_STATE_UNDERFLOW; | ||
115 | |||
116 | } else { | ||
117 | /* Disable interrupt so doesn't continually fire */ | ||
118 | SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player); | ||
119 | |||
120 | /* Stop the player */ | ||
121 | snd_pcm_stream_lock(player->substream); | ||
122 | snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); | ||
123 | snd_pcm_stream_unlock(player->substream); | ||
124 | } | ||
125 | |||
126 | ret = IRQ_HANDLED; | ||
127 | } | ||
128 | |||
129 | /* Check for dma error (overrun) */ | ||
130 | if (unlikely(status & UNIPERIF_ITS_DMA_ERROR_MASK(player))) { | ||
131 | dev_err(player->dev, "DMA error detected"); | ||
132 | |||
133 | /* Disable interrupt so doesn't continually fire */ | ||
134 | SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player); | ||
135 | |||
136 | /* Stop the player */ | ||
137 | snd_pcm_stream_lock(player->substream); | ||
138 | snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); | ||
139 | snd_pcm_stream_unlock(player->substream); | ||
140 | |||
141 | ret = IRQ_HANDLED; | ||
142 | } | ||
143 | |||
144 | /* Check for underflow recovery done */ | ||
145 | if (unlikely(status & UNIPERIF_ITM_UNDERFLOW_REC_DONE_MASK(player))) { | ||
146 | if (!player->info->underflow_enabled) { | ||
147 | dev_err(player->dev, "unexpected Underflow recovering"); | ||
148 | return -EPERM; | ||
149 | } | ||
150 | /* Read the underflow recovery duration */ | ||
151 | tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player); | ||
152 | |||
153 | /* Clear the underflow recovery duration */ | ||
154 | SET_UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION(player); | ||
155 | |||
156 | /* Update state to started */ | ||
157 | player->state = UNIPERIF_STATE_STARTED; | ||
158 | |||
159 | ret = IRQ_HANDLED; | ||
160 | } | ||
161 | |||
162 | /* Check if underflow recovery failed */ | ||
163 | if (unlikely(status & | ||
164 | UNIPERIF_ITM_UNDERFLOW_REC_FAILED_MASK(player))) { | ||
165 | dev_err(player->dev, "Underflow recovery failed"); | ||
166 | |||
167 | /* Stop the player */ | ||
168 | snd_pcm_stream_lock(player->substream); | ||
169 | snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); | ||
170 | snd_pcm_stream_unlock(player->substream); | ||
171 | |||
172 | ret = IRQ_HANDLED; | ||
173 | } | ||
174 | |||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | static int uni_player_clk_set_rate(struct uniperif *player, unsigned long rate) | ||
179 | { | ||
180 | int rate_adjusted, rate_achieved, delta, ret; | ||
181 | int adjustment = player->clk_adj; | ||
182 | |||
183 | /* | ||
184 | * a | ||
185 | * F = f + --------- * f = f + d | ||
186 | * 1000000 | ||
187 | * | ||
188 | * a | ||
189 | * d = --------- * f | ||
190 | * 1000000 | ||
191 | * | ||
192 | * where: | ||
193 | * f - nominal rate | ||
194 | * a - adjustment in ppm (parts per milion) | ||
195 | * F - rate to be set in synthesizer | ||
196 | * d - delta (difference) between f and F | ||
197 | */ | ||
198 | if (adjustment < 0) { | ||
199 | /* div64_64 operates on unsigned values... */ | ||
200 | delta = -1; | ||
201 | adjustment = -adjustment; | ||
202 | } else { | ||
203 | delta = 1; | ||
204 | } | ||
205 | /* 500000 ppm is 0.5, which is used to round up values */ | ||
206 | delta *= (int)div64_u64((uint64_t)rate * | ||
207 | (uint64_t)adjustment + 500000, 1000000); | ||
208 | rate_adjusted = rate + delta; | ||
209 | |||
210 | /* Adjusted rate should never be == 0 */ | ||
211 | if (!rate_adjusted) | ||
212 | return -EINVAL; | ||
213 | |||
214 | ret = clk_set_rate(player->clk, rate_adjusted); | ||
215 | if (ret < 0) | ||
216 | return ret; | ||
217 | |||
218 | rate_achieved = clk_get_rate(player->clk); | ||
219 | if (!rate_achieved) | ||
220 | /* If value is 0 means that clock or parent not valid */ | ||
221 | return -EINVAL; | ||
222 | |||
223 | /* | ||
224 | * Using ALSA's adjustment control, we can modify the rate to be up | ||
225 | * to twice as much as requested, but no more | ||
226 | */ | ||
227 | delta = rate_achieved - rate; | ||
228 | if (delta < 0) { | ||
229 | /* div64_64 operates on unsigned values... */ | ||
230 | delta = -delta; | ||
231 | adjustment = -1; | ||
232 | } else { | ||
233 | adjustment = 1; | ||
234 | } | ||
235 | /* Frequency/2 is added to round up result */ | ||
236 | adjustment *= (int)div64_u64((uint64_t)delta * 1000000 + rate / 2, | ||
237 | rate); | ||
238 | player->clk_adj = adjustment; | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static void uni_player_set_channel_status(struct uniperif *player, | ||
243 | struct snd_pcm_runtime *runtime) | ||
244 | { | ||
245 | int n; | ||
246 | unsigned int status; | ||
247 | |||
248 | /* | ||
249 | * Some AVRs and TVs require the channel status to contain a correct | ||
250 | * sampling frequency. If no sample rate is already specified, then | ||
251 | * set one. | ||
252 | */ | ||
253 | mutex_lock(&player->ctrl_lock); | ||
254 | if (runtime && (player->stream_settings.iec958.status[3] | ||
255 | == IEC958_AES3_CON_FS_NOTID)) { | ||
256 | switch (runtime->rate) { | ||
257 | case 22050: | ||
258 | player->stream_settings.iec958.status[3] = | ||
259 | IEC958_AES3_CON_FS_22050; | ||
260 | break; | ||
261 | case 44100: | ||
262 | player->stream_settings.iec958.status[3] = | ||
263 | IEC958_AES3_CON_FS_44100; | ||
264 | break; | ||
265 | case 88200: | ||
266 | player->stream_settings.iec958.status[3] = | ||
267 | IEC958_AES3_CON_FS_88200; | ||
268 | break; | ||
269 | case 176400: | ||
270 | player->stream_settings.iec958.status[3] = | ||
271 | IEC958_AES3_CON_FS_176400; | ||
272 | break; | ||
273 | case 24000: | ||
274 | player->stream_settings.iec958.status[3] = | ||
275 | IEC958_AES3_CON_FS_24000; | ||
276 | break; | ||
277 | case 48000: | ||
278 | player->stream_settings.iec958.status[3] = | ||
279 | IEC958_AES3_CON_FS_48000; | ||
280 | break; | ||
281 | case 96000: | ||
282 | player->stream_settings.iec958.status[3] = | ||
283 | IEC958_AES3_CON_FS_96000; | ||
284 | break; | ||
285 | case 192000: | ||
286 | player->stream_settings.iec958.status[3] = | ||
287 | IEC958_AES3_CON_FS_192000; | ||
288 | break; | ||
289 | case 32000: | ||
290 | player->stream_settings.iec958.status[3] = | ||
291 | IEC958_AES3_CON_FS_32000; | ||
292 | break; | ||
293 | default: | ||
294 | /* Mark as sampling frequency not indicated */ | ||
295 | player->stream_settings.iec958.status[3] = | ||
296 | IEC958_AES3_CON_FS_NOTID; | ||
297 | break; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | /* Audio mode: | ||
302 | * Use audio mode status to select PCM or encoded mode | ||
303 | */ | ||
304 | if (player->stream_settings.iec958.status[0] & IEC958_AES0_NONAUDIO) | ||
305 | player->stream_settings.encoding_mode = | ||
306 | UNIPERIF_IEC958_ENCODING_MODE_ENCODED; | ||
307 | else | ||
308 | player->stream_settings.encoding_mode = | ||
309 | UNIPERIF_IEC958_ENCODING_MODE_PCM; | ||
310 | |||
311 | if (player->stream_settings.encoding_mode == | ||
312 | UNIPERIF_IEC958_ENCODING_MODE_PCM) | ||
313 | /* Clear user validity bits */ | ||
314 | SET_UNIPERIF_USER_VALIDITY_VALIDITY_LR(player, 0); | ||
315 | else | ||
316 | /* Set user validity bits */ | ||
317 | SET_UNIPERIF_USER_VALIDITY_VALIDITY_LR(player, 1); | ||
318 | |||
319 | /* Program the new channel status */ | ||
320 | for (n = 0; n < 6; ++n) { | ||
321 | status = | ||
322 | player->stream_settings.iec958.status[0 + (n * 4)] & 0xf; | ||
323 | status |= | ||
324 | player->stream_settings.iec958.status[1 + (n * 4)] << 8; | ||
325 | status |= | ||
326 | player->stream_settings.iec958.status[2 + (n * 4)] << 16; | ||
327 | status |= | ||
328 | player->stream_settings.iec958.status[3 + (n * 4)] << 24; | ||
329 | SET_UNIPERIF_CHANNEL_STA_REGN(player, n, status); | ||
330 | } | ||
331 | mutex_unlock(&player->ctrl_lock); | ||
332 | |||
333 | /* Update the channel status */ | ||
334 | if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) | ||
335 | SET_UNIPERIF_CONFIG_CHL_STS_UPDATE(player); | ||
336 | else | ||
337 | SET_UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE(player); | ||
338 | } | ||
339 | |||
340 | static int uni_player_prepare_iec958(struct uniperif *player, | ||
341 | struct snd_pcm_runtime *runtime) | ||
342 | { | ||
343 | int clk_div; | ||
344 | |||
345 | clk_div = player->mclk / runtime->rate; | ||
346 | |||
347 | /* Oversampling must be multiple of 128 as iec958 frame is 32-bits */ | ||
348 | if ((clk_div % 128) || (clk_div <= 0)) { | ||
349 | dev_err(player->dev, "%s: invalid clk_div %d", | ||
350 | __func__, clk_div); | ||
351 | return -EINVAL; | ||
352 | } | ||
353 | |||
354 | switch (runtime->format) { | ||
355 | case SNDRV_PCM_FORMAT_S16_LE: | ||
356 | /* 16/16 memory format */ | ||
357 | SET_UNIPERIF_CONFIG_MEM_FMT_16_16(player); | ||
358 | /* 16-bits per sub-frame */ | ||
359 | SET_UNIPERIF_I2S_FMT_NBIT_32(player); | ||
360 | /* Set 16-bit sample precision */ | ||
361 | SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(player); | ||
362 | break; | ||
363 | case SNDRV_PCM_FORMAT_S32_LE: | ||
364 | /* 16/0 memory format */ | ||
365 | SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player); | ||
366 | /* 32-bits per sub-frame */ | ||
367 | SET_UNIPERIF_I2S_FMT_NBIT_32(player); | ||
368 | /* Set 24-bit sample precision */ | ||
369 | SET_UNIPERIF_I2S_FMT_DATA_SIZE_24(player); | ||
370 | break; | ||
371 | default: | ||
372 | dev_err(player->dev, "format not supported"); | ||
373 | return -EINVAL; | ||
374 | } | ||
375 | |||
376 | /* Set parity to be calculated by the hardware */ | ||
377 | SET_UNIPERIF_CONFIG_PARITY_CNTR_BY_HW(player); | ||
378 | |||
379 | /* Set channel status bits to be inserted by the hardware */ | ||
380 | SET_UNIPERIF_CONFIG_CHANNEL_STA_CNTR_BY_HW(player); | ||
381 | |||
382 | /* Set user data bits to be inserted by the hardware */ | ||
383 | SET_UNIPERIF_CONFIG_USER_DAT_CNTR_BY_HW(player); | ||
384 | |||
385 | /* Set validity bits to be inserted by the hardware */ | ||
386 | SET_UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_BY_HW(player); | ||
387 | |||
388 | /* Set full software control to disabled */ | ||
389 | SET_UNIPERIF_CONFIG_SPDIF_SW_CTRL_DISABLE(player); | ||
390 | |||
391 | SET_UNIPERIF_CTRL_ZERO_STUFF_HW(player); | ||
392 | |||
393 | /* Update the channel status */ | ||
394 | uni_player_set_channel_status(player, runtime); | ||
395 | |||
396 | /* Clear the user validity user bits */ | ||
397 | SET_UNIPERIF_USER_VALIDITY_VALIDITY_LR(player, 0); | ||
398 | |||
399 | /* Disable one-bit audio mode */ | ||
400 | SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player); | ||
401 | |||
402 | /* Enable consecutive frames repetition of Z preamble (not for HBRA) */ | ||
403 | SET_UNIPERIF_CONFIG_REPEAT_CHL_STS_ENABLE(player); | ||
404 | |||
405 | /* Change to SUF0_SUBF1 and left/right channels swap! */ | ||
406 | SET_UNIPERIF_CONFIG_SUBFRAME_SEL_SUBF1_SUBF0(player); | ||
407 | |||
408 | /* Set data output as MSB first */ | ||
409 | SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); | ||
410 | |||
411 | if (player->stream_settings.encoding_mode == | ||
412 | UNIPERIF_IEC958_ENCODING_MODE_ENCODED) | ||
413 | SET_UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_ON(player); | ||
414 | else | ||
415 | SET_UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_OFF(player); | ||
416 | |||
417 | SET_UNIPERIF_I2S_FMT_NUM_CH(player, runtime->channels / 2); | ||
418 | |||
419 | /* Set rounding to off */ | ||
420 | SET_UNIPERIF_CTRL_ROUNDING_OFF(player); | ||
421 | |||
422 | /* Set clock divisor */ | ||
423 | SET_UNIPERIF_CTRL_DIVIDER(player, clk_div / 128); | ||
424 | |||
425 | /* Set the spdif latency to not wait before starting player */ | ||
426 | SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player); | ||
427 | |||
428 | /* | ||
429 | * Ensure iec958 formatting is off. It will be enabled in function | ||
430 | * uni_player_start() at the same time as the operation | ||
431 | * mode is set to work around a silicon issue. | ||
432 | */ | ||
433 | if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) | ||
434 | SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player); | ||
435 | else | ||
436 | SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int uni_player_prepare_pcm(struct uniperif *player, | ||
442 | struct snd_pcm_runtime *runtime) | ||
443 | { | ||
444 | int output_frame_size, slot_width, clk_div; | ||
445 | |||
446 | /* Force slot width to 32 in I2S mode (HW constraint) */ | ||
447 | if ((player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == | ||
448 | SND_SOC_DAIFMT_I2S) { | ||
449 | slot_width = 32; | ||
450 | } else { | ||
451 | switch (runtime->format) { | ||
452 | case SNDRV_PCM_FORMAT_S16_LE: | ||
453 | slot_width = 16; | ||
454 | break; | ||
455 | default: | ||
456 | slot_width = 32; | ||
457 | break; | ||
458 | } | ||
459 | } | ||
460 | output_frame_size = slot_width * runtime->channels; | ||
461 | |||
462 | clk_div = player->mclk / runtime->rate; | ||
463 | /* | ||
464 | * For 32 bits subframe clk_div must be a multiple of 128, | ||
465 | * for 16 bits must be a multiple of 64 | ||
466 | */ | ||
467 | if ((slot_width == 32) && (clk_div % 128)) { | ||
468 | dev_err(player->dev, "%s: invalid clk_div", __func__); | ||
469 | return -EINVAL; | ||
470 | } | ||
471 | |||
472 | if ((slot_width == 16) && (clk_div % 64)) { | ||
473 | dev_err(player->dev, "%s: invalid clk_div", __func__); | ||
474 | return -EINVAL; | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * Number of bits per subframe (which is one channel sample) | ||
479 | * on output - Transfer 16 or 32 bits from FIFO | ||
480 | */ | ||
481 | switch (slot_width) { | ||
482 | case 32: | ||
483 | SET_UNIPERIF_I2S_FMT_NBIT_32(player); | ||
484 | SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(player); | ||
485 | break; | ||
486 | case 16: | ||
487 | SET_UNIPERIF_I2S_FMT_NBIT_16(player); | ||
488 | SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(player); | ||
489 | break; | ||
490 | default: | ||
491 | dev_err(player->dev, "subframe format not supported"); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | /* Configure data memory format */ | ||
496 | switch (runtime->format) { | ||
497 | case SNDRV_PCM_FORMAT_S16_LE: | ||
498 | /* One data word contains two samples */ | ||
499 | SET_UNIPERIF_CONFIG_MEM_FMT_16_16(player); | ||
500 | break; | ||
501 | |||
502 | case SNDRV_PCM_FORMAT_S32_LE: | ||
503 | /* | ||
504 | * Actually "16 bits/0 bits" means "32/28/24/20/18/16 bits | ||
505 | * on the left than zeros (if less than 32 bytes)"... ;-) | ||
506 | */ | ||
507 | SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player); | ||
508 | break; | ||
509 | |||
510 | default: | ||
511 | dev_err(player->dev, "format not supported"); | ||
512 | return -EINVAL; | ||
513 | } | ||
514 | |||
515 | /* Set rounding to off */ | ||
516 | SET_UNIPERIF_CTRL_ROUNDING_OFF(player); | ||
517 | |||
518 | /* Set clock divisor */ | ||
519 | SET_UNIPERIF_CTRL_DIVIDER(player, clk_div / (2 * output_frame_size)); | ||
520 | |||
521 | /* Number of channelsmust be even*/ | ||
522 | if ((runtime->channels % 2) || (runtime->channels < 2) || | ||
523 | (runtime->channels > 10)) { | ||
524 | dev_err(player->dev, "%s: invalid nb of channels", __func__); | ||
525 | return -EINVAL; | ||
526 | } | ||
527 | |||
528 | SET_UNIPERIF_I2S_FMT_NUM_CH(player, runtime->channels / 2); | ||
529 | |||
530 | /* Set 1-bit audio format to disabled */ | ||
531 | SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player); | ||
532 | |||
533 | SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); | ||
534 | SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(player); | ||
535 | |||
536 | /* No iec958 formatting as outputting to DAC */ | ||
537 | SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player); | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * ALSA uniperipheral iec958 controls | ||
544 | */ | ||
545 | static int uni_player_ctl_iec958_info(struct snd_kcontrol *kcontrol, | ||
546 | struct snd_ctl_elem_info *uinfo) | ||
547 | { | ||
548 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
549 | uinfo->count = 1; | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | static int uni_player_ctl_iec958_get(struct snd_kcontrol *kcontrol, | ||
555 | struct snd_ctl_elem_value *ucontrol) | ||
556 | { | ||
557 | struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); | ||
558 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
559 | struct uniperif *player = priv->dai_data.uni; | ||
560 | struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; | ||
561 | |||
562 | mutex_lock(&player->ctrl_lock); | ||
563 | ucontrol->value.iec958.status[0] = iec958->status[0]; | ||
564 | ucontrol->value.iec958.status[1] = iec958->status[1]; | ||
565 | ucontrol->value.iec958.status[2] = iec958->status[2]; | ||
566 | ucontrol->value.iec958.status[3] = iec958->status[3]; | ||
567 | mutex_unlock(&player->ctrl_lock); | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol, | ||
572 | struct snd_ctl_elem_value *ucontrol) | ||
573 | { | ||
574 | struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); | ||
575 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
576 | struct uniperif *player = priv->dai_data.uni; | ||
577 | struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; | ||
578 | |||
579 | mutex_lock(&player->ctrl_lock); | ||
580 | iec958->status[0] = ucontrol->value.iec958.status[0]; | ||
581 | iec958->status[1] = ucontrol->value.iec958.status[1]; | ||
582 | iec958->status[2] = ucontrol->value.iec958.status[2]; | ||
583 | iec958->status[3] = ucontrol->value.iec958.status[3]; | ||
584 | mutex_unlock(&player->ctrl_lock); | ||
585 | |||
586 | uni_player_set_channel_status(player, NULL); | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static struct snd_kcontrol_new uni_player_iec958_ctl = { | ||
592 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
593 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), | ||
594 | .info = uni_player_ctl_iec958_info, | ||
595 | .get = uni_player_ctl_iec958_get, | ||
596 | .put = uni_player_ctl_iec958_put, | ||
597 | }; | ||
598 | |||
599 | /* | ||
600 | * uniperif rate adjustement control | ||
601 | */ | ||
602 | static int snd_sti_clk_adjustment_info(struct snd_kcontrol *kcontrol, | ||
603 | struct snd_ctl_elem_info *uinfo) | ||
604 | { | ||
605 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
606 | uinfo->count = 1; | ||
607 | uinfo->value.integer.min = UNIPERIF_PLAYER_CLK_ADJ_MIN; | ||
608 | uinfo->value.integer.max = UNIPERIF_PLAYER_CLK_ADJ_MAX; | ||
609 | uinfo->value.integer.step = 1; | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static int snd_sti_clk_adjustment_get(struct snd_kcontrol *kcontrol, | ||
615 | struct snd_ctl_elem_value *ucontrol) | ||
616 | { | ||
617 | struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); | ||
618 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
619 | struct uniperif *player = priv->dai_data.uni; | ||
620 | |||
621 | mutex_lock(&player->ctrl_lock); | ||
622 | ucontrol->value.integer.value[0] = player->clk_adj; | ||
623 | mutex_unlock(&player->ctrl_lock); | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static int snd_sti_clk_adjustment_put(struct snd_kcontrol *kcontrol, | ||
629 | struct snd_ctl_elem_value *ucontrol) | ||
630 | { | ||
631 | struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); | ||
632 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
633 | struct uniperif *player = priv->dai_data.uni; | ||
634 | int ret = 0; | ||
635 | |||
636 | if ((ucontrol->value.integer.value[0] < UNIPERIF_PLAYER_CLK_ADJ_MIN) || | ||
637 | (ucontrol->value.integer.value[0] > UNIPERIF_PLAYER_CLK_ADJ_MAX)) | ||
638 | return -EINVAL; | ||
639 | |||
640 | mutex_lock(&player->ctrl_lock); | ||
641 | player->clk_adj = ucontrol->value.integer.value[0]; | ||
642 | |||
643 | if (player->mclk) | ||
644 | ret = uni_player_clk_set_rate(player, player->mclk); | ||
645 | mutex_unlock(&player->ctrl_lock); | ||
646 | |||
647 | return ret; | ||
648 | } | ||
649 | |||
650 | static struct snd_kcontrol_new uni_player_clk_adj_ctl = { | ||
651 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
652 | .name = "PCM Playback Oversampling Freq. Adjustment", | ||
653 | .info = snd_sti_clk_adjustment_info, | ||
654 | .get = snd_sti_clk_adjustment_get, | ||
655 | .put = snd_sti_clk_adjustment_put, | ||
656 | }; | ||
657 | |||
658 | static struct snd_kcontrol_new *snd_sti_pcm_ctl[] = { | ||
659 | &uni_player_clk_adj_ctl, | ||
660 | }; | ||
661 | |||
662 | static struct snd_kcontrol_new *snd_sti_iec_ctl[] = { | ||
663 | &uni_player_iec958_ctl, | ||
664 | &uni_player_clk_adj_ctl, | ||
665 | }; | ||
666 | |||
667 | static int uni_player_startup(struct snd_pcm_substream *substream, | ||
668 | struct snd_soc_dai *dai) | ||
669 | { | ||
670 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
671 | struct uniperif *player = priv->dai_data.uni; | ||
672 | |||
673 | player->clk_adj = 0; | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
679 | unsigned int freq, int dir) | ||
680 | { | ||
681 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
682 | struct uniperif *player = priv->dai_data.uni; | ||
683 | int ret; | ||
684 | |||
685 | if (dir == SND_SOC_CLOCK_IN) | ||
686 | return 0; | ||
687 | |||
688 | if (clk_id != 0) | ||
689 | return -EINVAL; | ||
690 | |||
691 | mutex_lock(&player->ctrl_lock); | ||
692 | ret = uni_player_clk_set_rate(player, freq); | ||
693 | if (!ret) | ||
694 | player->mclk = freq; | ||
695 | mutex_unlock(&player->ctrl_lock); | ||
696 | |||
697 | return ret; | ||
698 | } | ||
699 | |||
700 | static int uni_player_prepare(struct snd_pcm_substream *substream, | ||
701 | struct snd_soc_dai *dai) | ||
702 | { | ||
703 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
704 | struct uniperif *player = priv->dai_data.uni; | ||
705 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
706 | int transfer_size, trigger_limit; | ||
707 | int ret; | ||
708 | |||
709 | /* The player should be stopped */ | ||
710 | if (player->state != UNIPERIF_STATE_STOPPED) { | ||
711 | dev_err(player->dev, "%s: invalid player state %d", __func__, | ||
712 | player->state); | ||
713 | return -EINVAL; | ||
714 | } | ||
715 | |||
716 | /* Calculate transfer size (in fifo cells and bytes) for frame count */ | ||
717 | transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; | ||
718 | |||
719 | /* Calculate number of empty cells available before asserting DREQ */ | ||
720 | if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) { | ||
721 | trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size; | ||
722 | } else { | ||
723 | /* | ||
724 | * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 | ||
725 | * FDMA_TRIGGER_LIMIT also controls when the state switches | ||
726 | * from OFF or STANDBY to AUDIO DATA. | ||
727 | */ | ||
728 | trigger_limit = transfer_size; | ||
729 | } | ||
730 | |||
731 | /* Trigger limit must be an even number */ | ||
732 | if ((!trigger_limit % 2) || (trigger_limit != 1 && transfer_size % 2) || | ||
733 | (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(player))) { | ||
734 | dev_err(player->dev, "invalid trigger limit %d", trigger_limit); | ||
735 | return -EINVAL; | ||
736 | } | ||
737 | |||
738 | SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(player, trigger_limit); | ||
739 | |||
740 | /* Uniperipheral setup depends on player type */ | ||
741 | switch (player->info->player_type) { | ||
742 | case SND_ST_UNIPERIF_PLAYER_TYPE_HDMI: | ||
743 | ret = uni_player_prepare_iec958(player, runtime); | ||
744 | break; | ||
745 | case SND_ST_UNIPERIF_PLAYER_TYPE_PCM: | ||
746 | ret = uni_player_prepare_pcm(player, runtime); | ||
747 | break; | ||
748 | case SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF: | ||
749 | ret = uni_player_prepare_iec958(player, runtime); | ||
750 | break; | ||
751 | default: | ||
752 | dev_err(player->dev, "invalid player type"); | ||
753 | return -EINVAL; | ||
754 | } | ||
755 | |||
756 | if (ret) | ||
757 | return ret; | ||
758 | |||
759 | switch (player->daifmt & SND_SOC_DAIFMT_INV_MASK) { | ||
760 | case SND_SOC_DAIFMT_NB_NF: | ||
761 | SET_UNIPERIF_I2S_FMT_LR_POL_LOW(player); | ||
762 | SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(player); | ||
763 | break; | ||
764 | case SND_SOC_DAIFMT_NB_IF: | ||
765 | SET_UNIPERIF_I2S_FMT_LR_POL_HIG(player); | ||
766 | SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(player); | ||
767 | break; | ||
768 | case SND_SOC_DAIFMT_IB_NF: | ||
769 | SET_UNIPERIF_I2S_FMT_LR_POL_LOW(player); | ||
770 | SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(player); | ||
771 | break; | ||
772 | case SND_SOC_DAIFMT_IB_IF: | ||
773 | SET_UNIPERIF_I2S_FMT_LR_POL_HIG(player); | ||
774 | SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(player); | ||
775 | break; | ||
776 | } | ||
777 | |||
778 | switch (player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
779 | case SND_SOC_DAIFMT_I2S: | ||
780 | SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(player); | ||
781 | SET_UNIPERIF_I2S_FMT_PADDING_I2S_MODE(player); | ||
782 | break; | ||
783 | case SND_SOC_DAIFMT_LEFT_J: | ||
784 | SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(player); | ||
785 | SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(player); | ||
786 | break; | ||
787 | case SND_SOC_DAIFMT_RIGHT_J: | ||
788 | SET_UNIPERIF_I2S_FMT_ALIGN_RIGHT(player); | ||
789 | SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(player); | ||
790 | break; | ||
791 | default: | ||
792 | dev_err(player->dev, "format not supported"); | ||
793 | return -EINVAL; | ||
794 | } | ||
795 | |||
796 | SET_UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ(player, 0); | ||
797 | |||
798 | /* Reset uniperipheral player */ | ||
799 | SET_UNIPERIF_SOFT_RST_SOFT_RST(player); | ||
800 | |||
801 | return reset_player(player); | ||
802 | } | ||
803 | |||
804 | static int uni_player_start(struct uniperif *player) | ||
805 | { | ||
806 | int ret; | ||
807 | |||
808 | /* The player should be stopped */ | ||
809 | if (player->state != UNIPERIF_STATE_STOPPED) { | ||
810 | dev_err(player->dev, "%s: invalid player state", __func__); | ||
811 | return -EINVAL; | ||
812 | } | ||
813 | |||
814 | ret = clk_prepare_enable(player->clk); | ||
815 | if (ret) { | ||
816 | dev_err(player->dev, "%s: Failed to enable clock", __func__); | ||
817 | return ret; | ||
818 | } | ||
819 | |||
820 | /* Clear any pending interrupts */ | ||
821 | SET_UNIPERIF_ITS_BCLR(player, GET_UNIPERIF_ITS(player)); | ||
822 | |||
823 | /* Set the interrupt mask */ | ||
824 | SET_UNIPERIF_ITM_BSET_DMA_ERROR(player); | ||
825 | SET_UNIPERIF_ITM_BSET_FIFO_ERROR(player); | ||
826 | |||
827 | /* Enable underflow recovery interrupts */ | ||
828 | if (player->info->underflow_enabled) { | ||
829 | SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE(player); | ||
830 | SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED(player); | ||
831 | } | ||
832 | |||
833 | /* Reset uniperipheral player */ | ||
834 | SET_UNIPERIF_SOFT_RST_SOFT_RST(player); | ||
835 | |||
836 | ret = reset_player(player); | ||
837 | if (ret < 0) | ||
838 | return ret; | ||
839 | |||
840 | /* | ||
841 | * Does not use IEC61937 features of the uniperipheral hardware. | ||
842 | * Instead it performs IEC61937 in software and inserts it directly | ||
843 | * into the audio data stream. As such, when encoded mode is selected, | ||
844 | * linear pcm mode is still used, but with the differences of the | ||
845 | * channel status bits set for encoded mode and the validity bits set. | ||
846 | */ | ||
847 | SET_UNIPERIF_CTRL_OPERATION_PCM_DATA(player); | ||
848 | |||
849 | /* | ||
850 | * If iec958 formatting is required for hdmi or spdif, then it must be | ||
851 | * enabled after the operation mode is set. If set prior to this, it | ||
852 | * will not take affect and hang the player. | ||
853 | */ | ||
854 | if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) | ||
855 | if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) | ||
856 | SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player); | ||
857 | |||
858 | /* Force channel status update (no update if clk disable) */ | ||
859 | if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) | ||
860 | SET_UNIPERIF_CONFIG_CHL_STS_UPDATE(player); | ||
861 | else | ||
862 | SET_UNIPERIF_BIT_CONTROL_CHL_STS_UPDATE(player); | ||
863 | |||
864 | /* Update state to started */ | ||
865 | player->state = UNIPERIF_STATE_STARTED; | ||
866 | |||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | static int uni_player_stop(struct uniperif *player) | ||
871 | { | ||
872 | int ret; | ||
873 | |||
874 | /* The player should not be in stopped state */ | ||
875 | if (player->state == UNIPERIF_STATE_STOPPED) { | ||
876 | dev_err(player->dev, "%s: invalid player state", __func__); | ||
877 | return -EINVAL; | ||
878 | } | ||
879 | |||
880 | /* Turn the player off */ | ||
881 | SET_UNIPERIF_CTRL_OPERATION_OFF(player); | ||
882 | |||
883 | /* Soft reset the player */ | ||
884 | SET_UNIPERIF_SOFT_RST_SOFT_RST(player); | ||
885 | |||
886 | ret = reset_player(player); | ||
887 | if (ret < 0) | ||
888 | return ret; | ||
889 | |||
890 | /* Disable interrupts */ | ||
891 | SET_UNIPERIF_ITM_BCLR(player, GET_UNIPERIF_ITM(player)); | ||
892 | |||
893 | /* Disable clock */ | ||
894 | clk_disable_unprepare(player->clk); | ||
895 | |||
896 | /* Update state to stopped and return */ | ||
897 | player->state = UNIPERIF_STATE_STOPPED; | ||
898 | |||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | int uni_player_resume(struct uniperif *player) | ||
903 | { | ||
904 | int ret; | ||
905 | |||
906 | /* Select the frequency synthesizer clock */ | ||
907 | if (player->clk_sel) { | ||
908 | ret = regmap_field_write(player->clk_sel, 1); | ||
909 | if (ret) { | ||
910 | dev_err(player->dev, | ||
911 | "%s: Failed to select freq synth clock", | ||
912 | __func__); | ||
913 | return ret; | ||
914 | } | ||
915 | } | ||
916 | |||
917 | SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player); | ||
918 | SET_UNIPERIF_CTRL_ROUNDING_OFF(player); | ||
919 | SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player); | ||
920 | SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(player); | ||
921 | |||
922 | return 0; | ||
923 | } | ||
924 | EXPORT_SYMBOL_GPL(uni_player_resume); | ||
925 | |||
926 | static int uni_player_trigger(struct snd_pcm_substream *substream, | ||
927 | int cmd, struct snd_soc_dai *dai) | ||
928 | { | ||
929 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
930 | struct uniperif *player = priv->dai_data.uni; | ||
931 | |||
932 | switch (cmd) { | ||
933 | case SNDRV_PCM_TRIGGER_START: | ||
934 | return uni_player_start(player); | ||
935 | case SNDRV_PCM_TRIGGER_STOP: | ||
936 | return uni_player_stop(player); | ||
937 | case SNDRV_PCM_TRIGGER_RESUME: | ||
938 | return uni_player_resume(player); | ||
939 | default: | ||
940 | return -EINVAL; | ||
941 | } | ||
942 | } | ||
943 | |||
944 | static void uni_player_shutdown(struct snd_pcm_substream *substream, | ||
945 | struct snd_soc_dai *dai) | ||
946 | { | ||
947 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
948 | struct uniperif *player = priv->dai_data.uni; | ||
949 | |||
950 | if (player->state != UNIPERIF_STATE_STOPPED) | ||
951 | /* Stop the player */ | ||
952 | uni_player_stop(player); | ||
953 | } | ||
954 | |||
955 | static int uni_player_parse_dt_clk_glue(struct platform_device *pdev, | ||
956 | struct uniperif *player) | ||
957 | { | ||
958 | int bit_offset; | ||
959 | struct device_node *node = pdev->dev.of_node; | ||
960 | struct regmap *regmap; | ||
961 | |||
962 | bit_offset = SYS_CFG_AUDI0_GLUE_PCM_CLKX + player->info->id; | ||
963 | |||
964 | regmap = syscon_regmap_lookup_by_phandle(node, "st,syscfg"); | ||
965 | |||
966 | if (regmap) { | ||
967 | struct reg_field regfield = | ||
968 | REG_FIELD(SYS_CFG_AUDIO_GLUE, bit_offset, bit_offset); | ||
969 | |||
970 | player->clk_sel = regmap_field_alloc(regmap, regfield); | ||
971 | } else { | ||
972 | dev_err(&pdev->dev, "sti-audio-clk-glue syscf not found\n"); | ||
973 | return -EINVAL; | ||
974 | } | ||
975 | |||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | static int uni_player_parse_dt(struct platform_device *pdev, | ||
980 | struct uniperif *player) | ||
981 | { | ||
982 | struct uniperif_info *info; | ||
983 | struct device *dev = &pdev->dev; | ||
984 | struct device_node *pnode = pdev->dev.of_node; | ||
985 | const char *mode; | ||
986 | |||
987 | /* Allocate memory for the info structure */ | ||
988 | info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); | ||
989 | if (!info) | ||
990 | return -ENOMEM; | ||
991 | |||
992 | of_property_read_u32(pnode, "version", &player->ver); | ||
993 | if (player->ver == SND_ST_UNIPERIF_VERSION_UNKNOWN) { | ||
994 | dev_err(dev, "Unknown uniperipheral version "); | ||
995 | return -EINVAL; | ||
996 | } | ||
997 | /* Underflow recovery is only supported on later ip revisions */ | ||
998 | if (player->ver >= SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) | ||
999 | info->underflow_enabled = 1; | ||
1000 | |||
1001 | of_property_read_u32(pnode, "uniperiph-id", &info->id); | ||
1002 | |||
1003 | /* Read the device mode property */ | ||
1004 | of_property_read_string(pnode, "mode", &mode); | ||
1005 | |||
1006 | if (strcasecmp(mode, "hdmi") == 0) | ||
1007 | info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_HDMI; | ||
1008 | else if (strcasecmp(mode, "pcm") == 0) | ||
1009 | info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_PCM; | ||
1010 | else if (strcasecmp(mode, "spdif") == 0) | ||
1011 | info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF; | ||
1012 | else | ||
1013 | info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_NONE; | ||
1014 | |||
1015 | /* Save the info structure */ | ||
1016 | player->info = info; | ||
1017 | |||
1018 | /* Get the PCM_CLK_SEL bit from audio-glue-ctrl SoC register */ | ||
1019 | if (uni_player_parse_dt_clk_glue(pdev, player)) | ||
1020 | return -EINVAL; | ||
1021 | |||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1025 | static const struct snd_soc_dai_ops uni_player_dai_ops = { | ||
1026 | .startup = uni_player_startup, | ||
1027 | .shutdown = uni_player_shutdown, | ||
1028 | .prepare = uni_player_prepare, | ||
1029 | .trigger = uni_player_trigger, | ||
1030 | .hw_params = sti_uniperiph_dai_hw_params, | ||
1031 | .set_fmt = sti_uniperiph_dai_set_fmt, | ||
1032 | .set_sysclk = uni_player_set_sysclk | ||
1033 | }; | ||
1034 | |||
1035 | int uni_player_init(struct platform_device *pdev, | ||
1036 | struct uniperif *player) | ||
1037 | { | ||
1038 | int ret = 0; | ||
1039 | |||
1040 | player->dev = &pdev->dev; | ||
1041 | player->state = UNIPERIF_STATE_STOPPED; | ||
1042 | player->hw = &uni_player_pcm_hw; | ||
1043 | player->dai_ops = &uni_player_dai_ops; | ||
1044 | |||
1045 | ret = uni_player_parse_dt(pdev, player); | ||
1046 | |||
1047 | if (ret < 0) { | ||
1048 | dev_err(player->dev, "Failed to parse DeviceTree"); | ||
1049 | return ret; | ||
1050 | } | ||
1051 | |||
1052 | /* Get uniperif resource */ | ||
1053 | player->clk = of_clk_get(pdev->dev.of_node, 0); | ||
1054 | if (IS_ERR(player->clk)) | ||
1055 | ret = PTR_ERR(player->clk); | ||
1056 | |||
1057 | /* Select the frequency synthesizer clock */ | ||
1058 | if (player->clk_sel) { | ||
1059 | ret = regmap_field_write(player->clk_sel, 1); | ||
1060 | if (ret) { | ||
1061 | dev_err(player->dev, | ||
1062 | "%s: Failed to select freq synth clock", | ||
1063 | __func__); | ||
1064 | return ret; | ||
1065 | } | ||
1066 | } | ||
1067 | |||
1068 | ret = devm_request_irq(&pdev->dev, player->irq, | ||
1069 | uni_player_irq_handler, IRQF_SHARED, | ||
1070 | dev_name(&pdev->dev), player); | ||
1071 | if (ret < 0) | ||
1072 | return ret; | ||
1073 | |||
1074 | mutex_init(&player->ctrl_lock); | ||
1075 | |||
1076 | /* Ensure that disabled by default */ | ||
1077 | SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player); | ||
1078 | SET_UNIPERIF_CTRL_ROUNDING_OFF(player); | ||
1079 | SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player); | ||
1080 | SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(player); | ||
1081 | |||
1082 | if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) { | ||
1083 | /* Set default iec958 status bits */ | ||
1084 | |||
1085 | /* Consumer, PCM, copyright, 2ch, mode 0 */ | ||
1086 | player->stream_settings.iec958.status[0] = 0x00; | ||
1087 | /* Broadcast reception category */ | ||
1088 | player->stream_settings.iec958.status[1] = | ||
1089 | IEC958_AES1_CON_GENERAL; | ||
1090 | /* Do not take into account source or channel number */ | ||
1091 | player->stream_settings.iec958.status[2] = | ||
1092 | IEC958_AES2_CON_SOURCE_UNSPEC; | ||
1093 | /* Sampling frequency not indicated */ | ||
1094 | player->stream_settings.iec958.status[3] = | ||
1095 | IEC958_AES3_CON_FS_NOTID; | ||
1096 | /* Max sample word 24-bit, sample word length not indicated */ | ||
1097 | player->stream_settings.iec958.status[4] = | ||
1098 | IEC958_AES4_CON_MAX_WORDLEN_24 | | ||
1099 | IEC958_AES4_CON_WORDLEN_24_20; | ||
1100 | |||
1101 | player->num_ctrls = ARRAY_SIZE(snd_sti_iec_ctl); | ||
1102 | player->snd_ctrls = snd_sti_iec_ctl[0]; | ||
1103 | } else { | ||
1104 | player->num_ctrls = ARRAY_SIZE(snd_sti_pcm_ctl); | ||
1105 | player->snd_ctrls = snd_sti_pcm_ctl[0]; | ||
1106 | } | ||
1107 | |||
1108 | return 0; | ||
1109 | } | ||
1110 | EXPORT_SYMBOL_GPL(uni_player_init); | ||
diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c new file mode 100644 index 000000000000..c502626f339b --- /dev/null +++ b/sound/soc/sti/uniperif_reader.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2015 | ||
3 | * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com> | ||
4 | * for STMicroelectronics. | ||
5 | * License terms: GNU General Public License (GPL), version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/clk.h> | ||
9 | #include <linux/delay.h> | ||
10 | #include <linux/io.h> | ||
11 | |||
12 | #include <sound/soc.h> | ||
13 | |||
14 | #include "uniperif.h" | ||
15 | |||
16 | /* | ||
17 | * Note: snd_pcm_hardware is linked to DMA controller but is declared here to | ||
18 | * integrate unireader capability in term of rate and supported channels | ||
19 | */ | ||
20 | static const struct snd_pcm_hardware uni_reader_pcm_hw = { | ||
21 | .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
22 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP | | ||
23 | SNDRV_PCM_INFO_MMAP_VALID, | ||
24 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE, | ||
25 | |||
26 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
27 | .rate_min = 8000, | ||
28 | .rate_max = 96000, | ||
29 | |||
30 | .channels_min = 2, | ||
31 | .channels_max = 8, | ||
32 | |||
33 | .periods_min = 2, | ||
34 | .periods_max = 48, | ||
35 | |||
36 | .period_bytes_min = 128, | ||
37 | .period_bytes_max = 64 * PAGE_SIZE, | ||
38 | .buffer_bytes_max = 256 * PAGE_SIZE | ||
39 | }; | ||
40 | |||
41 | /* | ||
42 | * uni_reader_irq_handler | ||
43 | * In case of error audio stream is stopped; stop action is protected via PCM | ||
44 | * stream lock to avoid race condition with trigger callback. | ||
45 | */ | ||
46 | static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id) | ||
47 | { | ||
48 | irqreturn_t ret = IRQ_NONE; | ||
49 | struct uniperif *reader = dev_id; | ||
50 | unsigned int status; | ||
51 | |||
52 | if (reader->state == UNIPERIF_STATE_STOPPED) { | ||
53 | /* Unexpected IRQ: do nothing */ | ||
54 | dev_warn(reader->dev, "unexpected IRQ "); | ||
55 | return IRQ_HANDLED; | ||
56 | } | ||
57 | |||
58 | /* Get interrupt status & clear them immediately */ | ||
59 | status = GET_UNIPERIF_ITS(reader); | ||
60 | SET_UNIPERIF_ITS_BCLR(reader, status); | ||
61 | |||
62 | /* Check for fifo overflow error */ | ||
63 | if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) { | ||
64 | dev_err(reader->dev, "FIFO error detected"); | ||
65 | |||
66 | snd_pcm_stream_lock(reader->substream); | ||
67 | snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN); | ||
68 | snd_pcm_stream_unlock(reader->substream); | ||
69 | |||
70 | return IRQ_HANDLED; | ||
71 | } | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | static int uni_reader_prepare(struct snd_pcm_substream *substream, | ||
77 | struct snd_soc_dai *dai) | ||
78 | { | ||
79 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
80 | struct uniperif *reader = priv->dai_data.uni; | ||
81 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
82 | int transfer_size, trigger_limit; | ||
83 | int slot_width; | ||
84 | int count = 10; | ||
85 | |||
86 | /* The reader should be stopped */ | ||
87 | if (reader->state != UNIPERIF_STATE_STOPPED) { | ||
88 | dev_err(reader->dev, "%s: invalid reader state %d", __func__, | ||
89 | reader->state); | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | /* Calculate transfer size (in fifo cells and bytes) for frame count */ | ||
94 | transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; | ||
95 | |||
96 | /* Calculate number of empty cells available before asserting DREQ */ | ||
97 | if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) | ||
98 | trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size; | ||
99 | else | ||
100 | /* | ||
101 | * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 | ||
102 | * FDMA_TRIGGER_LIMIT also controls when the state switches | ||
103 | * from OFF or STANDBY to AUDIO DATA. | ||
104 | */ | ||
105 | trigger_limit = transfer_size; | ||
106 | |||
107 | /* Trigger limit must be an even number */ | ||
108 | if ((!trigger_limit % 2) || | ||
109 | (trigger_limit != 1 && transfer_size % 2) || | ||
110 | (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) { | ||
111 | dev_err(reader->dev, "invalid trigger limit %d", trigger_limit); | ||
112 | return -EINVAL; | ||
113 | } | ||
114 | |||
115 | SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit); | ||
116 | |||
117 | switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) { | ||
118 | case SND_SOC_DAIFMT_IB_IF: | ||
119 | case SND_SOC_DAIFMT_NB_IF: | ||
120 | SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); | ||
121 | break; | ||
122 | default: | ||
123 | SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); | ||
124 | } | ||
125 | |||
126 | /* Force slot width to 32 in I2S mode */ | ||
127 | if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) | ||
128 | == SND_SOC_DAIFMT_I2S) { | ||
129 | slot_width = 32; | ||
130 | } else { | ||
131 | switch (runtime->format) { | ||
132 | case SNDRV_PCM_FORMAT_S16_LE: | ||
133 | slot_width = 16; | ||
134 | break; | ||
135 | default: | ||
136 | slot_width = 32; | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | /* Number of bits per subframe (i.e one channel sample) on input. */ | ||
142 | switch (slot_width) { | ||
143 | case 32: | ||
144 | SET_UNIPERIF_I2S_FMT_NBIT_32(reader); | ||
145 | SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader); | ||
146 | break; | ||
147 | case 16: | ||
148 | SET_UNIPERIF_I2S_FMT_NBIT_16(reader); | ||
149 | SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(reader); | ||
150 | break; | ||
151 | default: | ||
152 | dev_err(reader->dev, "subframe format not supported"); | ||
153 | return -EINVAL; | ||
154 | } | ||
155 | |||
156 | /* Configure data memory format */ | ||
157 | switch (runtime->format) { | ||
158 | case SNDRV_PCM_FORMAT_S16_LE: | ||
159 | /* One data word contains two samples */ | ||
160 | SET_UNIPERIF_CONFIG_MEM_FMT_16_16(reader); | ||
161 | break; | ||
162 | |||
163 | case SNDRV_PCM_FORMAT_S32_LE: | ||
164 | /* | ||
165 | * Actually "16 bits/0 bits" means "32/28/24/20/18/16 bits | ||
166 | * on the MSB then zeros (if less than 32 bytes)"... | ||
167 | */ | ||
168 | SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader); | ||
169 | break; | ||
170 | |||
171 | default: | ||
172 | dev_err(reader->dev, "format not supported"); | ||
173 | return -EINVAL; | ||
174 | } | ||
175 | |||
176 | switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
177 | case SND_SOC_DAIFMT_I2S: | ||
178 | SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); | ||
179 | SET_UNIPERIF_I2S_FMT_PADDING_I2S_MODE(reader); | ||
180 | break; | ||
181 | case SND_SOC_DAIFMT_LEFT_J: | ||
182 | SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); | ||
183 | SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(reader); | ||
184 | break; | ||
185 | case SND_SOC_DAIFMT_RIGHT_J: | ||
186 | SET_UNIPERIF_I2S_FMT_ALIGN_RIGHT(reader); | ||
187 | SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(reader); | ||
188 | break; | ||
189 | default: | ||
190 | dev_err(reader->dev, "format not supported"); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); | ||
195 | |||
196 | /* Data clocking (changing) on the rising edge */ | ||
197 | SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); | ||
198 | |||
199 | /* Number of channels must be even */ | ||
200 | |||
201 | if ((runtime->channels % 2) || (runtime->channels < 2) || | ||
202 | (runtime->channels > 10)) { | ||
203 | dev_err(reader->dev, "%s: invalid nb of channels", __func__); | ||
204 | return -EINVAL; | ||
205 | } | ||
206 | |||
207 | SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2); | ||
208 | |||
209 | /* Clear any pending interrupts */ | ||
210 | SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader)); | ||
211 | |||
212 | SET_UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ(reader, 0); | ||
213 | |||
214 | /* Set the interrupt mask */ | ||
215 | SET_UNIPERIF_ITM_BSET_DMA_ERROR(reader); | ||
216 | SET_UNIPERIF_ITM_BSET_FIFO_ERROR(reader); | ||
217 | SET_UNIPERIF_ITM_BSET_MEM_BLK_READ(reader); | ||
218 | |||
219 | /* Enable underflow recovery interrupts */ | ||
220 | if (reader->info->underflow_enabled) { | ||
221 | SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE(reader); | ||
222 | SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED(reader); | ||
223 | } | ||
224 | |||
225 | /* Reset uniperipheral reader */ | ||
226 | SET_UNIPERIF_SOFT_RST_SOFT_RST(reader); | ||
227 | |||
228 | while (GET_UNIPERIF_SOFT_RST_SOFT_RST(reader)) { | ||
229 | udelay(5); | ||
230 | count--; | ||
231 | } | ||
232 | if (!count) { | ||
233 | dev_err(reader->dev, "Failed to reset uniperif"); | ||
234 | return -EIO; | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static int uni_reader_start(struct uniperif *reader) | ||
241 | { | ||
242 | /* The reader should be stopped */ | ||
243 | if (reader->state != UNIPERIF_STATE_STOPPED) { | ||
244 | dev_err(reader->dev, "%s: invalid reader state", __func__); | ||
245 | return -EINVAL; | ||
246 | } | ||
247 | |||
248 | /* Enable reader interrupts (and clear possible stalled ones) */ | ||
249 | SET_UNIPERIF_ITS_BCLR_FIFO_ERROR(reader); | ||
250 | SET_UNIPERIF_ITM_BSET_FIFO_ERROR(reader); | ||
251 | |||
252 | /* Launch the reader */ | ||
253 | SET_UNIPERIF_CTRL_OPERATION_PCM_DATA(reader); | ||
254 | |||
255 | /* Update state to started */ | ||
256 | reader->state = UNIPERIF_STATE_STARTED; | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int uni_reader_stop(struct uniperif *reader) | ||
261 | { | ||
262 | /* The reader should not be in stopped state */ | ||
263 | if (reader->state == UNIPERIF_STATE_STOPPED) { | ||
264 | dev_err(reader->dev, "%s: invalid reader state", __func__); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | /* Turn the reader off */ | ||
269 | SET_UNIPERIF_CTRL_OPERATION_OFF(reader); | ||
270 | |||
271 | /* Disable interrupts */ | ||
272 | SET_UNIPERIF_ITM_BCLR(reader, GET_UNIPERIF_ITM(reader)); | ||
273 | |||
274 | /* Update state to stopped and return */ | ||
275 | reader->state = UNIPERIF_STATE_STOPPED; | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int uni_reader_trigger(struct snd_pcm_substream *substream, | ||
281 | int cmd, struct snd_soc_dai *dai) | ||
282 | { | ||
283 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
284 | struct uniperif *reader = priv->dai_data.uni; | ||
285 | |||
286 | switch (cmd) { | ||
287 | case SNDRV_PCM_TRIGGER_START: | ||
288 | return uni_reader_start(reader); | ||
289 | case SNDRV_PCM_TRIGGER_STOP: | ||
290 | return uni_reader_stop(reader); | ||
291 | default: | ||
292 | return -EINVAL; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static void uni_reader_shutdown(struct snd_pcm_substream *substream, | ||
297 | struct snd_soc_dai *dai) | ||
298 | { | ||
299 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | ||
300 | struct uniperif *reader = priv->dai_data.uni; | ||
301 | |||
302 | if (reader->state != UNIPERIF_STATE_STOPPED) { | ||
303 | /* Stop the reader */ | ||
304 | uni_reader_stop(reader); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | static int uni_reader_parse_dt(struct platform_device *pdev, | ||
309 | struct uniperif *reader) | ||
310 | { | ||
311 | struct uniperif_info *info; | ||
312 | struct device_node *node = pdev->dev.of_node; | ||
313 | |||
314 | /* Allocate memory for the info structure */ | ||
315 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | ||
316 | if (!info) | ||
317 | return -ENOMEM; | ||
318 | |||
319 | of_property_read_u32(node, "version", &reader->ver); | ||
320 | |||
321 | /* Save the info structure */ | ||
322 | reader->info = info; | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static const struct snd_soc_dai_ops uni_reader_dai_ops = { | ||
328 | .shutdown = uni_reader_shutdown, | ||
329 | .prepare = uni_reader_prepare, | ||
330 | .trigger = uni_reader_trigger, | ||
331 | .hw_params = sti_uniperiph_dai_hw_params, | ||
332 | .set_fmt = sti_uniperiph_dai_set_fmt, | ||
333 | }; | ||
334 | |||
335 | int uni_reader_init(struct platform_device *pdev, | ||
336 | struct uniperif *reader) | ||
337 | { | ||
338 | int ret = 0; | ||
339 | |||
340 | reader->dev = &pdev->dev; | ||
341 | reader->state = UNIPERIF_STATE_STOPPED; | ||
342 | reader->hw = &uni_reader_pcm_hw; | ||
343 | reader->dai_ops = &uni_reader_dai_ops; | ||
344 | |||
345 | dev_err(reader->dev, "%s: enter\n", __func__); | ||
346 | ret = uni_reader_parse_dt(pdev, reader); | ||
347 | if (ret < 0) { | ||
348 | dev_err(reader->dev, "Failed to parse DeviceTree"); | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | ret = devm_request_irq(&pdev->dev, reader->irq, | ||
353 | uni_reader_irq_handler, IRQF_SHARED, | ||
354 | dev_name(&pdev->dev), reader); | ||
355 | if (ret < 0) { | ||
356 | dev_err(&pdev->dev, "Failed to request IRQ"); | ||
357 | return -EBUSY; | ||
358 | } | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | EXPORT_SYMBOL_GPL(uni_reader_init); | ||
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index f52600b4f3fd..89add13c31cf 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c | |||
@@ -133,7 +133,7 @@ static const struct regmap_config tegra20_das_regmap_config = { | |||
133 | 133 | ||
134 | static int tegra20_das_probe(struct platform_device *pdev) | 134 | static int tegra20_das_probe(struct platform_device *pdev) |
135 | { | 135 | { |
136 | struct resource *res, *region; | 136 | struct resource *res; |
137 | void __iomem *regs; | 137 | void __iomem *regs; |
138 | int ret = 0; | 138 | int ret = 0; |
139 | 139 | ||
@@ -149,24 +149,9 @@ static int tegra20_das_probe(struct platform_device *pdev) | |||
149 | das->dev = &pdev->dev; | 149 | das->dev = &pdev->dev; |
150 | 150 | ||
151 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 151 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
152 | if (!res) { | 152 | regs = devm_ioremap_resource(&pdev->dev, res); |
153 | dev_err(&pdev->dev, "No memory resource\n"); | 153 | if (IS_ERR(regs)) { |
154 | ret = -ENODEV; | 154 | ret = PTR_ERR(regs); |
155 | goto err; | ||
156 | } | ||
157 | |||
158 | region = devm_request_mem_region(&pdev->dev, res->start, | ||
159 | resource_size(res), pdev->name); | ||
160 | if (!region) { | ||
161 | dev_err(&pdev->dev, "Memory region already claimed\n"); | ||
162 | ret = -EBUSY; | ||
163 | goto err; | ||
164 | } | ||
165 | |||
166 | regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | ||
167 | if (!regs) { | ||
168 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
169 | ret = -ENOMEM; | ||
170 | goto err; | 155 | goto err; |
171 | } | 156 | } |
172 | 157 | ||
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 05f1c6ee99e3..14106fa82bca 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c | |||
@@ -339,7 +339,7 @@ static const struct regmap_config tegra20_i2s_regmap_config = { | |||
339 | static int tegra20_i2s_platform_probe(struct platform_device *pdev) | 339 | static int tegra20_i2s_platform_probe(struct platform_device *pdev) |
340 | { | 340 | { |
341 | struct tegra20_i2s *i2s; | 341 | struct tegra20_i2s *i2s; |
342 | struct resource *mem, *memregion; | 342 | struct resource *mem; |
343 | void __iomem *regs; | 343 | void __iomem *regs; |
344 | int ret; | 344 | int ret; |
345 | 345 | ||
@@ -362,24 +362,9 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) | |||
362 | } | 362 | } |
363 | 363 | ||
364 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 364 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
365 | if (!mem) { | 365 | regs = devm_ioremap_resource(&pdev->dev, mem); |
366 | dev_err(&pdev->dev, "No memory resource\n"); | 366 | if (IS_ERR(regs)) { |
367 | ret = -ENODEV; | 367 | ret = PTR_ERR(regs); |
368 | goto err_clk_put; | ||
369 | } | ||
370 | |||
371 | memregion = devm_request_mem_region(&pdev->dev, mem->start, | ||
372 | resource_size(mem), DRV_NAME); | ||
373 | if (!memregion) { | ||
374 | dev_err(&pdev->dev, "Memory region already claimed\n"); | ||
375 | ret = -EBUSY; | ||
376 | goto err_clk_put; | ||
377 | } | ||
378 | |||
379 | regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | ||
380 | if (!regs) { | ||
381 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
382 | ret = -ENOMEM; | ||
383 | goto err_clk_put; | 368 | goto err_clk_put; |
384 | } | 369 | } |
385 | 370 | ||
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 9141477a528d..a0c3640572b9 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c | |||
@@ -265,7 +265,7 @@ static const struct regmap_config tegra20_spdif_regmap_config = { | |||
265 | static int tegra20_spdif_platform_probe(struct platform_device *pdev) | 265 | static int tegra20_spdif_platform_probe(struct platform_device *pdev) |
266 | { | 266 | { |
267 | struct tegra20_spdif *spdif; | 267 | struct tegra20_spdif *spdif; |
268 | struct resource *mem, *memregion, *dmareq; | 268 | struct resource *mem, *dmareq; |
269 | void __iomem *regs; | 269 | void __iomem *regs; |
270 | int ret; | 270 | int ret; |
271 | 271 | ||
@@ -273,45 +273,26 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev) | |||
273 | GFP_KERNEL); | 273 | GFP_KERNEL); |
274 | if (!spdif) { | 274 | if (!spdif) { |
275 | dev_err(&pdev->dev, "Can't allocate tegra20_spdif\n"); | 275 | dev_err(&pdev->dev, "Can't allocate tegra20_spdif\n"); |
276 | ret = -ENOMEM; | 276 | return -ENOMEM; |
277 | goto err; | ||
278 | } | 277 | } |
279 | dev_set_drvdata(&pdev->dev, spdif); | 278 | dev_set_drvdata(&pdev->dev, spdif); |
280 | 279 | ||
281 | spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out"); | 280 | spdif->clk_spdif_out = devm_clk_get(&pdev->dev, "spdif_out"); |
282 | if (IS_ERR(spdif->clk_spdif_out)) { | 281 | if (IS_ERR(spdif->clk_spdif_out)) { |
283 | pr_err("Can't retrieve spdif clock\n"); | 282 | pr_err("Can't retrieve spdif clock\n"); |
284 | ret = PTR_ERR(spdif->clk_spdif_out); | 283 | ret = PTR_ERR(spdif->clk_spdif_out); |
285 | goto err; | 284 | return ret; |
286 | } | 285 | } |
287 | 286 | ||
288 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 287 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
289 | if (!mem) { | 288 | regs = devm_ioremap_resource(&pdev->dev, mem); |
290 | dev_err(&pdev->dev, "No memory resource\n"); | 289 | if (IS_ERR(regs)) |
291 | ret = -ENODEV; | 290 | return PTR_ERR(regs); |
292 | goto err_clk_put; | ||
293 | } | ||
294 | 291 | ||
295 | dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 292 | dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
296 | if (!dmareq) { | 293 | if (!dmareq) { |
297 | dev_err(&pdev->dev, "No DMA resource\n"); | 294 | dev_err(&pdev->dev, "No DMA resource\n"); |
298 | ret = -ENODEV; | 295 | return -ENODEV; |
299 | goto err_clk_put; | ||
300 | } | ||
301 | |||
302 | memregion = devm_request_mem_region(&pdev->dev, mem->start, | ||
303 | resource_size(mem), DRV_NAME); | ||
304 | if (!memregion) { | ||
305 | dev_err(&pdev->dev, "Memory region already claimed\n"); | ||
306 | ret = -EBUSY; | ||
307 | goto err_clk_put; | ||
308 | } | ||
309 | |||
310 | regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | ||
311 | if (!regs) { | ||
312 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
313 | ret = -ENOMEM; | ||
314 | goto err_clk_put; | ||
315 | } | 296 | } |
316 | 297 | ||
317 | spdif->regmap = devm_regmap_init_mmio(&pdev->dev, regs, | 298 | spdif->regmap = devm_regmap_init_mmio(&pdev->dev, regs, |
@@ -319,7 +300,7 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev) | |||
319 | if (IS_ERR(spdif->regmap)) { | 300 | if (IS_ERR(spdif->regmap)) { |
320 | dev_err(&pdev->dev, "regmap init failed\n"); | 301 | dev_err(&pdev->dev, "regmap init failed\n"); |
321 | ret = PTR_ERR(spdif->regmap); | 302 | ret = PTR_ERR(spdif->regmap); |
322 | goto err_clk_put; | 303 | return ret; |
323 | } | 304 | } |
324 | 305 | ||
325 | spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; | 306 | spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; |
@@ -335,7 +316,7 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev) | |||
335 | } | 316 | } |
336 | 317 | ||
337 | ret = snd_soc_register_component(&pdev->dev, &tegra20_spdif_component, | 318 | ret = snd_soc_register_component(&pdev->dev, &tegra20_spdif_component, |
338 | &tegra20_spdif_dai, 1); | 319 | &tegra20_spdif_dai, 1); |
339 | if (ret) { | 320 | if (ret) { |
340 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | 321 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); |
341 | ret = -ENOMEM; | 322 | ret = -ENOMEM; |
@@ -357,16 +338,12 @@ err_suspend: | |||
357 | tegra20_spdif_runtime_suspend(&pdev->dev); | 338 | tegra20_spdif_runtime_suspend(&pdev->dev); |
358 | err_pm_disable: | 339 | err_pm_disable: |
359 | pm_runtime_disable(&pdev->dev); | 340 | pm_runtime_disable(&pdev->dev); |
360 | err_clk_put: | 341 | |
361 | clk_put(spdif->clk_spdif_out); | ||
362 | err: | ||
363 | return ret; | 342 | return ret; |
364 | } | 343 | } |
365 | 344 | ||
366 | static int tegra20_spdif_platform_remove(struct platform_device *pdev) | 345 | static int tegra20_spdif_platform_remove(struct platform_device *pdev) |
367 | { | 346 | { |
368 | struct tegra20_spdif *spdif = dev_get_drvdata(&pdev->dev); | ||
369 | |||
370 | pm_runtime_disable(&pdev->dev); | 347 | pm_runtime_disable(&pdev->dev); |
371 | if (!pm_runtime_status_suspended(&pdev->dev)) | 348 | if (!pm_runtime_status_suspended(&pdev->dev)) |
372 | tegra20_spdif_runtime_suspend(&pdev->dev); | 349 | tegra20_spdif_runtime_suspend(&pdev->dev); |
@@ -374,8 +351,6 @@ static int tegra20_spdif_platform_remove(struct platform_device *pdev) | |||
374 | tegra_pcm_platform_unregister(&pdev->dev); | 351 | tegra_pcm_platform_unregister(&pdev->dev); |
375 | snd_soc_unregister_component(&pdev->dev); | 352 | snd_soc_unregister_component(&pdev->dev); |
376 | 353 | ||
377 | clk_put(spdif->clk_spdif_out); | ||
378 | |||
379 | return 0; | 354 | return 0; |
380 | } | 355 | } |
381 | 356 | ||
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index bc94e5d8e79a..fef3b9a21a66 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c | |||
@@ -521,7 +521,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev) | |||
521 | const struct tegra30_ahub_soc_data *soc_data; | 521 | const struct tegra30_ahub_soc_data *soc_data; |
522 | struct reset_control *rst; | 522 | struct reset_control *rst; |
523 | int i; | 523 | int i; |
524 | struct resource *res0, *res1, *region; | 524 | struct resource *res0, *res1; |
525 | void __iomem *regs_apbif, *regs_ahub; | 525 | void __iomem *regs_apbif, *regs_ahub; |
526 | int ret = 0; | 526 | int ret = 0; |
527 | 527 | ||
@@ -549,103 +549,67 @@ static int tegra30_ahub_probe(struct platform_device *pdev) | |||
549 | dev_err(&pdev->dev, "Can't get reset %s\n", | 549 | dev_err(&pdev->dev, "Can't get reset %s\n", |
550 | configlink_mods[i].rst_name); | 550 | configlink_mods[i].rst_name); |
551 | ret = PTR_ERR(rst); | 551 | ret = PTR_ERR(rst); |
552 | goto err; | 552 | return ret; |
553 | } | 553 | } |
554 | 554 | ||
555 | ret = reset_control_deassert(rst); | 555 | ret = reset_control_deassert(rst); |
556 | reset_control_put(rst); | 556 | reset_control_put(rst); |
557 | if (ret) | 557 | if (ret) |
558 | goto err; | 558 | return ret; |
559 | } | 559 | } |
560 | 560 | ||
561 | ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), | 561 | ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), |
562 | GFP_KERNEL); | 562 | GFP_KERNEL); |
563 | if (!ahub) { | 563 | if (!ahub) { |
564 | dev_err(&pdev->dev, "Can't allocate tegra30_ahub\n"); | 564 | dev_err(&pdev->dev, "Can't allocate tegra30_ahub\n"); |
565 | ret = -ENOMEM; | 565 | return -ENOMEM; |
566 | goto err; | ||
567 | } | 566 | } |
568 | dev_set_drvdata(&pdev->dev, ahub); | 567 | dev_set_drvdata(&pdev->dev, ahub); |
569 | 568 | ||
570 | ahub->soc_data = soc_data; | 569 | ahub->soc_data = soc_data; |
571 | ahub->dev = &pdev->dev; | 570 | ahub->dev = &pdev->dev; |
572 | 571 | ||
573 | ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio"); | 572 | ahub->clk_d_audio = devm_clk_get(&pdev->dev, "d_audio"); |
574 | if (IS_ERR(ahub->clk_d_audio)) { | 573 | if (IS_ERR(ahub->clk_d_audio)) { |
575 | dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n"); | 574 | dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n"); |
576 | ret = PTR_ERR(ahub->clk_d_audio); | 575 | ret = PTR_ERR(ahub->clk_d_audio); |
577 | goto err; | 576 | return ret; |
578 | } | 577 | } |
579 | 578 | ||
580 | ahub->clk_apbif = clk_get(&pdev->dev, "apbif"); | 579 | ahub->clk_apbif = devm_clk_get(&pdev->dev, "apbif"); |
581 | if (IS_ERR(ahub->clk_apbif)) { | 580 | if (IS_ERR(ahub->clk_apbif)) { |
582 | dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n"); | 581 | dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n"); |
583 | ret = PTR_ERR(ahub->clk_apbif); | 582 | ret = PTR_ERR(ahub->clk_apbif); |
584 | goto err_clk_put_d_audio; | 583 | return ret; |
585 | } | 584 | } |
586 | 585 | ||
587 | res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 586 | res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
588 | if (!res0) { | 587 | regs_apbif = devm_ioremap_resource(&pdev->dev, res0); |
589 | dev_err(&pdev->dev, "No apbif memory resource\n"); | 588 | if (IS_ERR(regs_apbif)) |
590 | ret = -ENODEV; | 589 | return PTR_ERR(regs_apbif); |
591 | goto err_clk_put_apbif; | ||
592 | } | ||
593 | 590 | ||
594 | region = devm_request_mem_region(&pdev->dev, res0->start, | ||
595 | resource_size(res0), DRV_NAME); | ||
596 | if (!region) { | ||
597 | dev_err(&pdev->dev, "request region apbif failed\n"); | ||
598 | ret = -EBUSY; | ||
599 | goto err_clk_put_apbif; | ||
600 | } | ||
601 | ahub->apbif_addr = res0->start; | 591 | ahub->apbif_addr = res0->start; |
602 | 592 | ||
603 | regs_apbif = devm_ioremap(&pdev->dev, res0->start, | ||
604 | resource_size(res0)); | ||
605 | if (!regs_apbif) { | ||
606 | dev_err(&pdev->dev, "ioremap apbif failed\n"); | ||
607 | ret = -ENOMEM; | ||
608 | goto err_clk_put_apbif; | ||
609 | } | ||
610 | |||
611 | ahub->regmap_apbif = devm_regmap_init_mmio(&pdev->dev, regs_apbif, | 593 | ahub->regmap_apbif = devm_regmap_init_mmio(&pdev->dev, regs_apbif, |
612 | &tegra30_ahub_apbif_regmap_config); | 594 | &tegra30_ahub_apbif_regmap_config); |
613 | if (IS_ERR(ahub->regmap_apbif)) { | 595 | if (IS_ERR(ahub->regmap_apbif)) { |
614 | dev_err(&pdev->dev, "apbif regmap init failed\n"); | 596 | dev_err(&pdev->dev, "apbif regmap init failed\n"); |
615 | ret = PTR_ERR(ahub->regmap_apbif); | 597 | ret = PTR_ERR(ahub->regmap_apbif); |
616 | goto err_clk_put_apbif; | 598 | return ret; |
617 | } | 599 | } |
618 | regcache_cache_only(ahub->regmap_apbif, true); | 600 | regcache_cache_only(ahub->regmap_apbif, true); |
619 | 601 | ||
620 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 602 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
621 | if (!res1) { | 603 | regs_ahub = devm_ioremap_resource(&pdev->dev, res1); |
622 | dev_err(&pdev->dev, "No ahub memory resource\n"); | 604 | if (IS_ERR(regs_ahub)) |
623 | ret = -ENODEV; | 605 | return PTR_ERR(regs_ahub); |
624 | goto err_clk_put_apbif; | ||
625 | } | ||
626 | |||
627 | region = devm_request_mem_region(&pdev->dev, res1->start, | ||
628 | resource_size(res1), DRV_NAME); | ||
629 | if (!region) { | ||
630 | dev_err(&pdev->dev, "request region ahub failed\n"); | ||
631 | ret = -EBUSY; | ||
632 | goto err_clk_put_apbif; | ||
633 | } | ||
634 | |||
635 | regs_ahub = devm_ioremap(&pdev->dev, res1->start, | ||
636 | resource_size(res1)); | ||
637 | if (!regs_ahub) { | ||
638 | dev_err(&pdev->dev, "ioremap ahub failed\n"); | ||
639 | ret = -ENOMEM; | ||
640 | goto err_clk_put_apbif; | ||
641 | } | ||
642 | 606 | ||
643 | ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub, | 607 | ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub, |
644 | &tegra30_ahub_ahub_regmap_config); | 608 | &tegra30_ahub_ahub_regmap_config); |
645 | if (IS_ERR(ahub->regmap_ahub)) { | 609 | if (IS_ERR(ahub->regmap_ahub)) { |
646 | dev_err(&pdev->dev, "ahub regmap init failed\n"); | 610 | dev_err(&pdev->dev, "ahub regmap init failed\n"); |
647 | ret = PTR_ERR(ahub->regmap_ahub); | 611 | ret = PTR_ERR(ahub->regmap_ahub); |
648 | goto err_clk_put_apbif; | 612 | return ret; |
649 | } | 613 | } |
650 | regcache_cache_only(ahub->regmap_ahub, true); | 614 | regcache_cache_only(ahub->regmap_ahub, true); |
651 | 615 | ||
@@ -662,12 +626,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev) | |||
662 | 626 | ||
663 | err_pm_disable: | 627 | err_pm_disable: |
664 | pm_runtime_disable(&pdev->dev); | 628 | pm_runtime_disable(&pdev->dev); |
665 | err_clk_put_apbif: | 629 | |
666 | clk_put(ahub->clk_apbif); | ||
667 | err_clk_put_d_audio: | ||
668 | clk_put(ahub->clk_d_audio); | ||
669 | ahub = NULL; | ||
670 | err: | ||
671 | return ret; | 630 | return ret; |
672 | } | 631 | } |
673 | 632 | ||
@@ -680,11 +639,6 @@ static int tegra30_ahub_remove(struct platform_device *pdev) | |||
680 | if (!pm_runtime_status_suspended(&pdev->dev)) | 639 | if (!pm_runtime_status_suspended(&pdev->dev)) |
681 | tegra30_ahub_runtime_suspend(&pdev->dev); | 640 | tegra30_ahub_runtime_suspend(&pdev->dev); |
682 | 641 | ||
683 | clk_put(ahub->clk_apbif); | ||
684 | clk_put(ahub->clk_d_audio); | ||
685 | |||
686 | ahub = NULL; | ||
687 | |||
688 | return 0; | 642 | return 0; |
689 | } | 643 | } |
690 | 644 | ||
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index fe36375ba89c..8e55583aa104 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c | |||
@@ -379,7 +379,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) | |||
379 | struct tegra30_i2s *i2s; | 379 | struct tegra30_i2s *i2s; |
380 | const struct of_device_id *match; | 380 | const struct of_device_id *match; |
381 | u32 cif_ids[2]; | 381 | u32 cif_ids[2]; |
382 | struct resource *mem, *memregion; | 382 | struct resource *mem; |
383 | void __iomem *regs; | 383 | void __iomem *regs; |
384 | int ret; | 384 | int ret; |
385 | 385 | ||
@@ -419,24 +419,9 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) | |||
419 | } | 419 | } |
420 | 420 | ||
421 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 421 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
422 | if (!mem) { | 422 | regs = devm_ioremap_resource(&pdev->dev, mem); |
423 | dev_err(&pdev->dev, "No memory resource\n"); | 423 | if (IS_ERR(regs)) { |
424 | ret = -ENODEV; | 424 | ret = PTR_ERR(regs); |
425 | goto err_clk_put; | ||
426 | } | ||
427 | |||
428 | memregion = devm_request_mem_region(&pdev->dev, mem->start, | ||
429 | resource_size(mem), DRV_NAME); | ||
430 | if (!memregion) { | ||
431 | dev_err(&pdev->dev, "Memory region already claimed\n"); | ||
432 | ret = -EBUSY; | ||
433 | goto err_clk_put; | ||
434 | } | ||
435 | |||
436 | regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | ||
437 | if (!regs) { | ||
438 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
439 | ret = -ENOMEM; | ||
440 | goto err_clk_put; | 425 | goto err_clk_put; |
441 | } | 426 | } |
442 | 427 | ||
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index 88eacfd83da6..a8f705bb60dc 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c | |||
@@ -411,13 +411,8 @@ static struct snd_soc_platform_driver txx9aclc_soc_platform = { | |||
411 | 411 | ||
412 | static int txx9aclc_soc_platform_probe(struct platform_device *pdev) | 412 | static int txx9aclc_soc_platform_probe(struct platform_device *pdev) |
413 | { | 413 | { |
414 | return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform); | 414 | return devm_snd_soc_register_platform(&pdev->dev, |
415 | } | 415 | &txx9aclc_soc_platform); |
416 | |||
417 | static int txx9aclc_soc_platform_remove(struct platform_device *pdev) | ||
418 | { | ||
419 | snd_soc_unregister_platform(&pdev->dev); | ||
420 | return 0; | ||
421 | } | 416 | } |
422 | 417 | ||
423 | static struct platform_driver txx9aclc_pcm_driver = { | 418 | static struct platform_driver txx9aclc_pcm_driver = { |
@@ -426,7 +421,6 @@ static struct platform_driver txx9aclc_pcm_driver = { | |||
426 | }, | 421 | }, |
427 | 422 | ||
428 | .probe = txx9aclc_soc_platform_probe, | 423 | .probe = txx9aclc_soc_platform_probe, |
429 | .remove = txx9aclc_soc_platform_remove, | ||
430 | }; | 424 | }; |
431 | 425 | ||
432 | module_platform_driver(txx9aclc_pcm_driver); | 426 | module_platform_driver(txx9aclc_pcm_driver); |
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 978f2d7316b0..f5df08ded770 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c | |||
@@ -773,20 +773,22 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) | |||
773 | } | 773 | } |
774 | prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50); | 774 | prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50); |
775 | 775 | ||
776 | drvdata->pclk = clk_get(&pdev->dev, "apb_pclk"); | 776 | drvdata->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); |
777 | if (IS_ERR(drvdata->pclk)) { | 777 | if (IS_ERR(drvdata->pclk)) { |
778 | ret = (int)PTR_ERR(drvdata->pclk); | 778 | ret = (int)PTR_ERR(drvdata->pclk); |
779 | dev_err(&pdev->dev, "%s: ERROR: clk_get of pclk failed (%d)!\n", | 779 | dev_err(&pdev->dev, |
780 | "%s: ERROR: devm_clk_get of pclk failed (%d)!\n", | ||
780 | __func__, ret); | 781 | __func__, ret); |
781 | goto err_pclk; | 782 | return ret; |
782 | } | 783 | } |
783 | 784 | ||
784 | drvdata->clk = clk_get(&pdev->dev, NULL); | 785 | drvdata->clk = devm_clk_get(&pdev->dev, NULL); |
785 | if (IS_ERR(drvdata->clk)) { | 786 | if (IS_ERR(drvdata->clk)) { |
786 | ret = (int)PTR_ERR(drvdata->clk); | 787 | ret = (int)PTR_ERR(drvdata->clk); |
787 | dev_err(&pdev->dev, "%s: ERROR: clk_get failed (%d)!\n", | 788 | dev_err(&pdev->dev, |
789 | "%s: ERROR: devm_clk_get failed (%d)!\n", | ||
788 | __func__, ret); | 790 | __func__, ret); |
789 | goto err_clk; | 791 | return ret; |
790 | } | 792 | } |
791 | 793 | ||
792 | ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp, | 794 | ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp, |
@@ -795,7 +797,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) | |||
795 | dev_err(&pdev->dev, | 797 | dev_err(&pdev->dev, |
796 | "%s: ERROR: Failed to init MSP-struct (%d)!", | 798 | "%s: ERROR: Failed to init MSP-struct (%d)!", |
797 | __func__, ret); | 799 | __func__, ret); |
798 | goto err_init_msp; | 800 | return ret; |
799 | } | 801 | } |
800 | dev_set_drvdata(&pdev->dev, drvdata); | 802 | dev_set_drvdata(&pdev->dev, drvdata); |
801 | 803 | ||
@@ -804,7 +806,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) | |||
804 | if (ret < 0) { | 806 | if (ret < 0) { |
805 | dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n", | 807 | dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n", |
806 | __func__, drvdata->msp->id); | 808 | __func__, drvdata->msp->id); |
807 | goto err_init_msp; | 809 | return ret; |
808 | } | 810 | } |
809 | 811 | ||
810 | ret = ux500_pcm_register_platform(pdev); | 812 | ret = ux500_pcm_register_platform(pdev); |
@@ -819,13 +821,6 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) | |||
819 | 821 | ||
820 | err_reg_plat: | 822 | err_reg_plat: |
821 | snd_soc_unregister_component(&pdev->dev); | 823 | snd_soc_unregister_component(&pdev->dev); |
822 | err_init_msp: | ||
823 | clk_put(drvdata->clk); | ||
824 | err_clk: | ||
825 | clk_put(drvdata->pclk); | ||
826 | err_pclk: | ||
827 | devm_regulator_put(drvdata->reg_vape); | ||
828 | |||
829 | return ret; | 824 | return ret; |
830 | } | 825 | } |
831 | 826 | ||
@@ -837,12 +832,8 @@ static int ux500_msp_drv_remove(struct platform_device *pdev) | |||
837 | 832 | ||
838 | snd_soc_unregister_component(&pdev->dev); | 833 | snd_soc_unregister_component(&pdev->dev); |
839 | 834 | ||
840 | devm_regulator_put(drvdata->reg_vape); | ||
841 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s"); | 835 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s"); |
842 | 836 | ||
843 | clk_put(drvdata->clk); | ||
844 | clk_put(drvdata->pclk); | ||
845 | |||
846 | ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp); | 837 | ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp); |
847 | 838 | ||
848 | return 0; | 839 | return 0; |
diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index 1cfb19e12949..8382ffa3bcaf 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c | |||
@@ -75,7 +75,7 @@ struct xtfpga_i2s { | |||
75 | * stream in the pcm_close callback it synchronizes with the interrupt | 75 | * stream in the pcm_close callback it synchronizes with the interrupt |
76 | * handler by means of synchronize_rcu call. | 76 | * handler by means of synchronize_rcu call. |
77 | */ | 77 | */ |
78 | struct snd_pcm_substream *tx_substream; | 78 | struct snd_pcm_substream __rcu *tx_substream; |
79 | unsigned (*tx_fn)(struct xtfpga_i2s *i2s, | 79 | unsigned (*tx_fn)(struct xtfpga_i2s *i2s, |
80 | struct snd_pcm_runtime *runtime, | 80 | struct snd_pcm_runtime *runtime, |
81 | unsigned tx_ptr); | 81 | unsigned tx_ptr); |
@@ -474,11 +474,6 @@ static int xtfpga_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
474 | card->dev, size, size); | 474 | card->dev, size, size); |
475 | } | 475 | } |
476 | 476 | ||
477 | static void xtfpga_pcm_free(struct snd_pcm *pcm) | ||
478 | { | ||
479 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
480 | } | ||
481 | |||
482 | static const struct snd_pcm_ops xtfpga_pcm_ops = { | 477 | static const struct snd_pcm_ops xtfpga_pcm_ops = { |
483 | .open = xtfpga_pcm_open, | 478 | .open = xtfpga_pcm_open, |
484 | .close = xtfpga_pcm_close, | 479 | .close = xtfpga_pcm_close, |
@@ -490,7 +485,6 @@ static const struct snd_pcm_ops xtfpga_pcm_ops = { | |||
490 | 485 | ||
491 | static const struct snd_soc_platform_driver xtfpga_soc_platform = { | 486 | static const struct snd_soc_platform_driver xtfpga_soc_platform = { |
492 | .pcm_new = xtfpga_pcm_new, | 487 | .pcm_new = xtfpga_pcm_new, |
493 | .pcm_free = xtfpga_pcm_free, | ||
494 | .ops = &xtfpga_pcm_ops, | 488 | .ops = &xtfpga_pcm_ops, |
495 | }; | 489 | }; |
496 | 490 | ||
diff --git a/sound/soc/zte/zx296702-i2s.c b/sound/soc/zte/zx296702-i2s.c index 1930c42e1f55..1cad93dc1fcf 100644 --- a/sound/soc/zte/zx296702-i2s.c +++ b/sound/soc/zte/zx296702-i2s.c | |||
@@ -380,7 +380,7 @@ static int zx_i2s_probe(struct platform_device *pdev) | |||
380 | struct zx_i2s_info *zx_i2s; | 380 | struct zx_i2s_info *zx_i2s; |
381 | int ret; | 381 | int ret; |
382 | 382 | ||
383 | zx_i2s = kzalloc(sizeof(*zx_i2s), GFP_KERNEL); | 383 | zx_i2s = devm_kzalloc(&pdev->dev, sizeof(*zx_i2s), GFP_KERNEL); |
384 | if (!zx_i2s) | 384 | if (!zx_i2s) |
385 | return -ENOMEM; | 385 | return -ENOMEM; |
386 | 386 | ||
@@ -401,8 +401,8 @@ static int zx_i2s_probe(struct platform_device *pdev) | |||
401 | writel_relaxed(0, zx_i2s->reg_base + ZX_I2S_FIFO_CTRL); | 401 | writel_relaxed(0, zx_i2s->reg_base + ZX_I2S_FIFO_CTRL); |
402 | platform_set_drvdata(pdev, zx_i2s); | 402 | platform_set_drvdata(pdev, zx_i2s); |
403 | 403 | ||
404 | ret = snd_soc_register_component(&pdev->dev, &zx_i2s_component, | 404 | ret = devm_snd_soc_register_component(&pdev->dev, &zx_i2s_component, |
405 | &zx_i2s_dai, 1); | 405 | &zx_i2s_dai, 1); |
406 | if (ret) { | 406 | if (ret) { |
407 | dev_err(&pdev->dev, "Register DAI failed: %d\n", ret); | 407 | dev_err(&pdev->dev, "Register DAI failed: %d\n", ret); |
408 | return ret; | 408 | return ret; |