diff options
author | Takashi Iwai <tiwai@suse.de> | 2017-02-20 15:43:40 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2017-02-20 15:43:40 -0500 |
commit | 4e25d30c8ddeae6ad0b68440aacadaacb14f8538 (patch) | |
tree | 08fe4ac15aec508b370262ad653c83a91be247b5 /sound | |
parent | d2bb390a2081a36ffe906724d2848d846f2aeb29 (diff) | |
parent | 141dee78c40ac2c43aa4ff306688d625e1c731de (diff) |
Merge tag 'asoc-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.11
Another release that's mainly focused on drivers rather than core
changes, highlights include:
- A huge batch of updates to the Intel drivers, mainly around
DisplayPort and HDMI with some additional board support too.
- Channel mapping support for HDMI.
- Support for AllWinner A31 and A33, Everest Semiconductor ES8328,
Nuvoton NAU8540.
Diffstat (limited to 'sound')
128 files changed, 5225 insertions, 1464 deletions
diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 3be051ab5533..c96d7a7a36af 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c | |||
@@ -128,14 +128,17 @@ void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *ebus, | |||
128 | { | 128 | { |
129 | struct hdac_stream *hstream = &stream->hstream; | 129 | struct hdac_stream *hstream = &stream->hstream; |
130 | struct hdac_bus *bus = &ebus->bus; | 130 | struct hdac_bus *bus = &ebus->bus; |
131 | u32 val; | ||
132 | int mask = AZX_PPCTL_PROCEN(hstream->index); | ||
131 | 133 | ||
132 | spin_lock_irq(&bus->reg_lock); | 134 | spin_lock_irq(&bus->reg_lock); |
133 | if (decouple) | 135 | val = readw(bus->ppcap + AZX_REG_PP_PPCTL) & mask; |
134 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, 0, | 136 | |
135 | AZX_PPCTL_PROCEN(hstream->index)); | 137 | if (decouple && !val) |
136 | else | 138 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, mask); |
137 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, | 139 | else if (!decouple && val) |
138 | AZX_PPCTL_PROCEN(hstream->index), 0); | 140 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, 0); |
141 | |||
139 | stream->decoupled = decouple; | 142 | stream->decoupled = decouple; |
140 | spin_unlock_irq(&bus->reg_lock); | 143 | spin_unlock_irq(&bus->reg_lock); |
141 | } | 144 | } |
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index 504c7cd7f58a..818b052377f3 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c | |||
@@ -670,13 +670,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream, | |||
670 | { | 670 | { |
671 | int status; | 671 | int status; |
672 | uint64_t size; | 672 | uint64_t size; |
673 | struct snd_dma_buffer *dma_buffer; | ||
674 | struct page *pg; | 673 | struct page *pg; |
675 | struct snd_pcm_runtime *runtime; | 674 | struct snd_pcm_runtime *runtime; |
676 | struct audio_substream_data *rtd; | 675 | struct audio_substream_data *rtd; |
677 | 676 | ||
678 | dma_buffer = &substream->dma_buffer; | ||
679 | |||
680 | runtime = substream->runtime; | 677 | runtime = substream->runtime; |
681 | rtd = runtime->private_data; | 678 | rtd = runtime->private_data; |
682 | 679 | ||
diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index ac6a814c8ecf..a72c7d642026 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c | |||
@@ -51,11 +51,7 @@ | |||
51 | #include <sound/soc.h> | 51 | #include <sound/soc.h> |
52 | #include <sound/pcm_params.h> | 52 | #include <sound/pcm_params.h> |
53 | 53 | ||
54 | #include "atmel_ssc_dai.h" | ||
55 | |||
56 | struct tse850_priv { | 54 | struct tse850_priv { |
57 | int ssc_id; | ||
58 | |||
59 | struct gpio_desc *add; | 55 | struct gpio_desc *add; |
60 | struct gpio_desc *loop1; | 56 | struct gpio_desc *loop1; |
61 | struct gpio_desc *loop2; | 57 | struct gpio_desc *loop2; |
@@ -329,23 +325,20 @@ static int tse850_dt_init(struct platform_device *pdev) | |||
329 | { | 325 | { |
330 | struct device_node *np = pdev->dev.of_node; | 326 | struct device_node *np = pdev->dev.of_node; |
331 | struct device_node *codec_np, *cpu_np; | 327 | struct device_node *codec_np, *cpu_np; |
332 | struct snd_soc_card *card = &tse850_card; | ||
333 | struct snd_soc_dai_link *dailink = &tse850_dailink; | 328 | struct snd_soc_dai_link *dailink = &tse850_dailink; |
334 | struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card); | ||
335 | 329 | ||
336 | if (!np) { | 330 | if (!np) { |
337 | dev_err(&pdev->dev, "only device tree supported\n"); | 331 | dev_err(&pdev->dev, "only device tree supported\n"); |
338 | return -EINVAL; | 332 | return -EINVAL; |
339 | } | 333 | } |
340 | 334 | ||
341 | cpu_np = of_parse_phandle(np, "axentia,ssc-controller", 0); | 335 | cpu_np = of_parse_phandle(np, "axentia,cpu-dai", 0); |
342 | if (!cpu_np) { | 336 | if (!cpu_np) { |
343 | dev_err(&pdev->dev, "failed to get dai and pcm info\n"); | 337 | dev_err(&pdev->dev, "failed to get cpu dai\n"); |
344 | return -EINVAL; | 338 | return -EINVAL; |
345 | } | 339 | } |
346 | dailink->cpu_of_node = cpu_np; | 340 | dailink->cpu_of_node = cpu_np; |
347 | dailink->platform_of_node = cpu_np; | 341 | dailink->platform_of_node = cpu_np; |
348 | tse850->ssc_id = of_alias_get_id(cpu_np, "ssc"); | ||
349 | of_node_put(cpu_np); | 342 | of_node_put(cpu_np); |
350 | 343 | ||
351 | codec_np = of_parse_phandle(np, "axentia,audio-codec", 0); | 344 | codec_np = of_parse_phandle(np, "axentia,audio-codec", 0); |
@@ -415,23 +408,14 @@ static int tse850_probe(struct platform_device *pdev) | |||
415 | return ret; | 408 | return ret; |
416 | } | 409 | } |
417 | 410 | ||
418 | ret = atmel_ssc_set_audio(tse850->ssc_id); | ||
419 | if (ret != 0) { | ||
420 | dev_err(dev, | ||
421 | "failed to set SSC %d for audio\n", tse850->ssc_id); | ||
422 | goto err_disable_ana; | ||
423 | } | ||
424 | |||
425 | ret = snd_soc_register_card(card); | 411 | ret = snd_soc_register_card(card); |
426 | if (ret) { | 412 | if (ret) { |
427 | dev_err(dev, "snd_soc_register_card failed\n"); | 413 | dev_err(dev, "snd_soc_register_card failed\n"); |
428 | goto err_put_audio; | 414 | goto err_disable_ana; |
429 | } | 415 | } |
430 | 416 | ||
431 | return 0; | 417 | return 0; |
432 | 418 | ||
433 | err_put_audio: | ||
434 | atmel_ssc_put_audio(tse850->ssc_id); | ||
435 | err_disable_ana: | 419 | err_disable_ana: |
436 | regulator_disable(tse850->ana); | 420 | regulator_disable(tse850->ana); |
437 | return ret; | 421 | return ret; |
@@ -443,7 +427,6 @@ static int tse850_remove(struct platform_device *pdev) | |||
443 | struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card); | 427 | struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card); |
444 | 428 | ||
445 | snd_soc_unregister_card(card); | 429 | snd_soc_unregister_card(card); |
446 | atmel_ssc_put_audio(tse850->ssc_id); | ||
447 | regulator_disable(tse850->ana); | 430 | regulator_disable(tse850->ana); |
448 | 431 | ||
449 | return 0; | 432 | return 0; |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9e1718a8cb1c..e49e9da7f1f6 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -45,7 +45,7 @@ config SND_SOC_ALL_CODECS | |||
45 | select SND_SOC_ALC5623 if I2C | 45 | select SND_SOC_ALC5623 if I2C |
46 | select SND_SOC_ALC5632 if I2C | 46 | select SND_SOC_ALC5632 if I2C |
47 | select SND_SOC_BT_SCO | 47 | select SND_SOC_BT_SCO |
48 | select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC | 48 | select SND_SOC_CQ0093VC |
49 | select SND_SOC_CS35L32 if I2C | 49 | select SND_SOC_CS35L32 if I2C |
50 | select SND_SOC_CS35L33 if I2C | 50 | select SND_SOC_CS35L33 if I2C |
51 | select SND_SOC_CS35L34 if I2C | 51 | select SND_SOC_CS35L34 if I2C |
@@ -95,6 +95,7 @@ config SND_SOC_ALL_CODECS | |||
95 | select SND_SOC_MAX9877 if I2C | 95 | select SND_SOC_MAX9877 if I2C |
96 | select SND_SOC_MC13783 if MFD_MC13XXX | 96 | select SND_SOC_MC13783 if MFD_MC13XXX |
97 | select SND_SOC_ML26124 if I2C | 97 | select SND_SOC_ML26124 if I2C |
98 | select SND_SOC_NAU8540 if I2C | ||
98 | select SND_SOC_NAU8810 if I2C | 99 | select SND_SOC_NAU8810 if I2C |
99 | select SND_SOC_NAU8825 if I2C | 100 | select SND_SOC_NAU8825 if I2C |
100 | select SND_SOC_HDMI_CODEC | 101 | select SND_SOC_HDMI_CODEC |
@@ -117,8 +118,8 @@ config SND_SOC_ALL_CODECS | |||
117 | select SND_SOC_RT5651 if I2C | 118 | select SND_SOC_RT5651 if I2C |
118 | select SND_SOC_RT5659 if I2C | 119 | select SND_SOC_RT5659 if I2C |
119 | select SND_SOC_RT5660 if I2C | 120 | select SND_SOC_RT5660 if I2C |
120 | select SND_SOC_RT5665 if I2C | ||
121 | select SND_SOC_RT5663 if I2C | 121 | select SND_SOC_RT5663 if I2C |
122 | select SND_SOC_RT5665 if I2C | ||
122 | select SND_SOC_RT5670 if I2C | 123 | select SND_SOC_RT5670 if I2C |
123 | select SND_SOC_RT5677 if I2C && SPI_MASTER | 124 | select SND_SOC_RT5677 if I2C && SPI_MASTER |
124 | select SND_SOC_SGTL5000 if I2C | 125 | select SND_SOC_SGTL5000 if I2C |
@@ -525,14 +526,16 @@ config SND_SOC_HDMI_CODEC | |||
525 | select HDMI | 526 | select HDMI |
526 | 527 | ||
527 | config SND_SOC_ES8328 | 528 | config SND_SOC_ES8328 |
528 | tristate "Everest Semi ES8328 CODEC" | 529 | tristate |
529 | 530 | ||
530 | config SND_SOC_ES8328_I2C | 531 | config SND_SOC_ES8328_I2C |
531 | tristate | 532 | tristate "Everest Semi ES8328 CODEC (I2C)" |
533 | depends on I2C | ||
532 | select SND_SOC_ES8328 | 534 | select SND_SOC_ES8328 |
533 | 535 | ||
534 | config SND_SOC_ES8328_SPI | 536 | config SND_SOC_ES8328_SPI |
535 | tristate | 537 | tristate "Everest Semi ES8328 CODEC (SPI)" |
538 | depends on SPI_MASTER | ||
536 | select SND_SOC_ES8328 | 539 | select SND_SOC_ES8328 |
537 | 540 | ||
538 | config SND_SOC_GTM601 | 541 | config SND_SOC_GTM601 |
@@ -668,8 +671,8 @@ config SND_SOC_RL6231 | |||
668 | default y if SND_SOC_RT5651=y | 671 | default y if SND_SOC_RT5651=y |
669 | default y if SND_SOC_RT5659=y | 672 | default y if SND_SOC_RT5659=y |
670 | default y if SND_SOC_RT5660=y | 673 | default y if SND_SOC_RT5660=y |
671 | default y if SND_SOC_RT5665=y | ||
672 | default y if SND_SOC_RT5663=y | 674 | default y if SND_SOC_RT5663=y |
675 | default y if SND_SOC_RT5665=y | ||
673 | default y if SND_SOC_RT5670=y | 676 | default y if SND_SOC_RT5670=y |
674 | default y if SND_SOC_RT5677=y | 677 | default y if SND_SOC_RT5677=y |
675 | default m if SND_SOC_RT5514=m | 678 | default m if SND_SOC_RT5514=m |
@@ -679,8 +682,8 @@ config SND_SOC_RL6231 | |||
679 | default m if SND_SOC_RT5651=m | 682 | default m if SND_SOC_RT5651=m |
680 | default m if SND_SOC_RT5659=m | 683 | default m if SND_SOC_RT5659=m |
681 | default m if SND_SOC_RT5660=m | 684 | default m if SND_SOC_RT5660=m |
682 | default m if SND_SOC_RT5665=m | ||
683 | default m if SND_SOC_RT5663=m | 685 | default m if SND_SOC_RT5663=m |
686 | default m if SND_SOC_RT5665=m | ||
684 | default m if SND_SOC_RT5670=m | 687 | default m if SND_SOC_RT5670=m |
685 | default m if SND_SOC_RT5677=m | 688 | default m if SND_SOC_RT5677=m |
686 | 689 | ||
@@ -728,10 +731,10 @@ config SND_SOC_RT5659 | |||
728 | config SND_SOC_RT5660 | 731 | config SND_SOC_RT5660 |
729 | tristate | 732 | tristate |
730 | 733 | ||
731 | config SND_SOC_RT5665 | 734 | config SND_SOC_RT5663 |
732 | tristate | 735 | tristate |
733 | 736 | ||
734 | config SND_SOC_RT5663 | 737 | config SND_SOC_RT5665 |
735 | tristate | 738 | tristate |
736 | 739 | ||
737 | config SND_SOC_RT5670 | 740 | config SND_SOC_RT5670 |
@@ -1105,6 +1108,10 @@ config SND_SOC_MC13783 | |||
1105 | config SND_SOC_ML26124 | 1108 | config SND_SOC_ML26124 |
1106 | tristate | 1109 | tristate |
1107 | 1110 | ||
1111 | config SND_SOC_NAU8540 | ||
1112 | tristate "Nuvoton Technology Corporation NAU85L40 CODEC" | ||
1113 | depends on I2C | ||
1114 | |||
1108 | config SND_SOC_NAU8810 | 1115 | config SND_SOC_NAU8810 |
1109 | tristate "Nuvoton Technology Corporation NAU88C10 CODEC" | 1116 | tristate "Nuvoton Technology Corporation NAU88C10 CODEC" |
1110 | depends on I2C | 1117 | depends on I2C |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 7e1dad79610b..1796cb987e71 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -90,6 +90,7 @@ snd-soc-mc13783-objs := mc13783.o | |||
90 | snd-soc-ml26124-objs := ml26124.o | 90 | snd-soc-ml26124-objs := ml26124.o |
91 | snd-soc-msm8916-analog-objs := msm8916-wcd-analog.o | 91 | snd-soc-msm8916-analog-objs := msm8916-wcd-analog.o |
92 | snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o | 92 | snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o |
93 | snd-soc-nau8540-objs := nau8540.o | ||
93 | snd-soc-nau8810-objs := nau8810.o | 94 | snd-soc-nau8810-objs := nau8810.o |
94 | snd-soc-nau8825-objs := nau8825.o | 95 | snd-soc-nau8825-objs := nau8825.o |
95 | snd-soc-hdmi-codec-objs := hdmi-codec.o | 96 | snd-soc-hdmi-codec-objs := hdmi-codec.o |
@@ -118,8 +119,8 @@ snd-soc-rt5645-objs := rt5645.o | |||
118 | snd-soc-rt5651-objs := rt5651.o | 119 | snd-soc-rt5651-objs := rt5651.o |
119 | snd-soc-rt5659-objs := rt5659.o | 120 | snd-soc-rt5659-objs := rt5659.o |
120 | snd-soc-rt5660-objs := rt5660.o | 121 | snd-soc-rt5660-objs := rt5660.o |
121 | snd-soc-rt5665-objs := rt5665.o | ||
122 | snd-soc-rt5663-objs := rt5663.o | 122 | snd-soc-rt5663-objs := rt5663.o |
123 | snd-soc-rt5665-objs := rt5665.o | ||
123 | snd-soc-rt5670-objs := rt5670.o | 124 | snd-soc-rt5670-objs := rt5670.o |
124 | snd-soc-rt5677-objs := rt5677.o | 125 | snd-soc-rt5677-objs := rt5677.o |
125 | snd-soc-rt5677-spi-objs := rt5677-spi.o | 126 | snd-soc-rt5677-spi-objs := rt5677-spi.o |
@@ -318,6 +319,7 @@ obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o | |||
318 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o | 319 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o |
319 | obj-$(CONFIG_SND_SOC_MSM8916_WCD_ANALOG) +=snd-soc-msm8916-analog.o | 320 | obj-$(CONFIG_SND_SOC_MSM8916_WCD_ANALOG) +=snd-soc-msm8916-analog.o |
320 | obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o | 321 | obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o |
322 | obj-$(CONFIG_SND_SOC_NAU8540) += snd-soc-nau8540.o | ||
321 | obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o | 323 | obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o |
322 | obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o | 324 | obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o |
323 | obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o | 325 | obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o |
@@ -346,8 +348,8 @@ obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o | |||
346 | obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o | 348 | obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o |
347 | obj-$(CONFIG_SND_SOC_RT5659) += snd-soc-rt5659.o | 349 | obj-$(CONFIG_SND_SOC_RT5659) += snd-soc-rt5659.o |
348 | obj-$(CONFIG_SND_SOC_RT5660) += snd-soc-rt5660.o | 350 | obj-$(CONFIG_SND_SOC_RT5660) += snd-soc-rt5660.o |
349 | obj-$(CONFIG_SND_SOC_RT5665) += snd-soc-rt5665.o | ||
350 | obj-$(CONFIG_SND_SOC_RT5663) += snd-soc-rt5663.o | 351 | obj-$(CONFIG_SND_SOC_RT5663) += snd-soc-rt5663.o |
352 | obj-$(CONFIG_SND_SOC_RT5665) += snd-soc-rt5665.o | ||
351 | obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o | 353 | obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o |
352 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o | 354 | obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o |
353 | obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o | 355 | obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o |
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index b36511d965c8..2c1bd2763864 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c | |||
@@ -65,7 +65,6 @@ static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, | |||
65 | { | 65 | { |
66 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | 66 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
67 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 67 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
68 | int ret; | ||
69 | 68 | ||
70 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 69 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
71 | adau->pll_regs[5] = 1; | 70 | adau->pll_regs[5] = 1; |
@@ -78,7 +77,7 @@ static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, | |||
78 | } | 77 | } |
79 | 78 | ||
80 | /* The PLL register is 6 bytes long and can only be written at once. */ | 79 | /* The PLL register is 6 bytes long and can only be written at once. */ |
81 | ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL, | 80 | regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL, |
82 | adau->pll_regs, ARRAY_SIZE(adau->pll_regs)); | 81 | adau->pll_regs, ARRAY_SIZE(adau->pll_regs)); |
83 | 82 | ||
84 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 83 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 2609f95b7d19..23ab9646c351 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -189,7 +189,7 @@ static int ak4642_lout_event(struct snd_soc_dapm_widget *w, | |||
189 | case SND_SOC_DAPM_POST_PMU: | 189 | case SND_SOC_DAPM_POST_PMU: |
190 | case SND_SOC_DAPM_POST_PMD: | 190 | case SND_SOC_DAPM_POST_PMD: |
191 | /* Power save mode OFF */ | 191 | /* Power save mode OFF */ |
192 | mdelay(300); | 192 | msleep(300); |
193 | snd_soc_update_bits(codec, SG_SL2, LOPS, 0); | 193 | snd_soc_update_bits(codec, SG_SL2, LOPS, 0); |
194 | break; | 194 | break; |
195 | } | 195 | } |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 56707860657c..1822e3b3de80 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -192,6 +192,7 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |||
192 | #define ARIZONA_DSP_ROUTES(name) \ | 192 | #define ARIZONA_DSP_ROUTES(name) \ |
193 | { name, NULL, name " Preloader"}, \ | 193 | { name, NULL, name " Preloader"}, \ |
194 | { name " Preloader", NULL, "SYSCLK" }, \ | 194 | { name " Preloader", NULL, "SYSCLK" }, \ |
195 | { name " Preload", NULL, name " Preloader"}, \ | ||
195 | { name, NULL, name " Aux 1" }, \ | 196 | { name, NULL, name " Aux 1" }, \ |
196 | { name, NULL, name " Aux 2" }, \ | 197 | { name, NULL, name " Aux 2" }, \ |
197 | { name, NULL, name " Aux 3" }, \ | 198 | { name, NULL, name " Aux 3" }, \ |
diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 73559ae864b6..47e6fddef92b 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c | |||
@@ -173,6 +173,9 @@ SOC_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]), | |||
173 | SOC_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]), | 173 | SOC_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]), |
174 | SOC_ENUM("ASRC RATE 1", arizona_asrc_rate1), | 174 | SOC_ENUM("ASRC RATE 1", arizona_asrc_rate1), |
175 | 175 | ||
176 | WM_ADSP2_PRELOAD_SWITCH("DSP2", 2), | ||
177 | WM_ADSP2_PRELOAD_SWITCH("DSP3", 3), | ||
178 | |||
176 | ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE), | 179 | ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE), |
177 | ARIZONA_MIXER_CONTROLS("DSP2R", ARIZONA_DSP2RMIX_INPUT_1_SOURCE), | 180 | ARIZONA_MIXER_CONTROLS("DSP2R", ARIZONA_DSP2RMIX_INPUT_1_SOURCE), |
178 | ARIZONA_MIXER_CONTROLS("DSP3L", ARIZONA_DSP3LMIX_INPUT_1_SOURCE), | 181 | ARIZONA_MIXER_CONTROLS("DSP3L", ARIZONA_DSP3LMIX_INPUT_1_SOURCE), |
@@ -1121,7 +1124,10 @@ static int cs47l24_codec_probe(struct snd_soc_codec *codec) | |||
1121 | 1124 | ||
1122 | priv->core.arizona->dapm = dapm; | 1125 | priv->core.arizona->dapm = dapm; |
1123 | 1126 | ||
1124 | arizona_init_spk(codec); | 1127 | ret = arizona_init_spk(codec); |
1128 | if (ret < 0) | ||
1129 | return ret; | ||
1130 | |||
1125 | arizona_init_gpio(codec); | 1131 | arizona_init_gpio(codec); |
1126 | arizona_init_mono(codec); | 1132 | arizona_init_mono(codec); |
1127 | arizona_init_notifiers(codec); | 1133 | arizona_init_notifiers(codec); |
diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index c69e97654fc6..d256ebf9e309 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c | |||
@@ -1634,7 +1634,8 @@ static const struct snd_soc_dapm_widget da7218_dapm_widgets[] = { | |||
1634 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | 1634 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
1635 | 1635 | ||
1636 | /* DAI */ | 1636 | /* DAI */ |
1637 | SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, SND_SOC_NOPM, 0, 0), | 1637 | SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, DA7218_DAI_TDM_CTRL, |
1638 | DA7218_DAI_OE_SHIFT, DA7218_NO_INVERT), | ||
1638 | SND_SOC_DAPM_AIF_IN("DAIIN", "Playback", 0, SND_SOC_NOPM, 0, 0), | 1639 | SND_SOC_DAPM_AIF_IN("DAIIN", "Playback", 0, SND_SOC_NOPM, 0, 0), |
1639 | 1640 | ||
1640 | /* Output Mixers */ | 1641 | /* Output Mixers */ |
diff --git a/sound/soc/codecs/es8328-i2c.c b/sound/soc/codecs/es8328-i2c.c index 2d05b5d3a6ce..318ab28c5351 100644 --- a/sound/soc/codecs/es8328-i2c.c +++ b/sound/soc/codecs/es8328-i2c.c | |||
@@ -20,12 +20,14 @@ | |||
20 | 20 | ||
21 | static const struct i2c_device_id es8328_id[] = { | 21 | static const struct i2c_device_id es8328_id[] = { |
22 | { "es8328", 0 }, | 22 | { "es8328", 0 }, |
23 | { "es8388", 0 }, | ||
23 | { } | 24 | { } |
24 | }; | 25 | }; |
25 | MODULE_DEVICE_TABLE(i2c, es8328_id); | 26 | MODULE_DEVICE_TABLE(i2c, es8328_id); |
26 | 27 | ||
27 | static const struct of_device_id es8328_of_match[] = { | 28 | static const struct of_device_id es8328_of_match[] = { |
28 | { .compatible = "everest,es8328", }, | 29 | { .compatible = "everest,es8328", }, |
30 | { .compatible = "everest,es8388", }, | ||
29 | { } | 31 | { } |
30 | }; | 32 | }; |
31 | MODULE_DEVICE_TABLE(of, es8328_of_match); | 33 | MODULE_DEVICE_TABLE(of, es8328_of_match); |
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 37722194b107..3f84fbd071e2 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c | |||
@@ -589,9 +589,21 @@ static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
589 | u8 dac_mode = 0; | 589 | u8 dac_mode = 0; |
590 | u8 adc_mode = 0; | 590 | u8 adc_mode = 0; |
591 | 591 | ||
592 | /* set master/slave audio interface */ | 592 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
593 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBM_CFM) | 593 | case SND_SOC_DAIFMT_CBM_CFM: |
594 | /* Master serial port mode, with BCLK generated automatically */ | ||
595 | snd_soc_update_bits(codec, ES8328_MASTERMODE, | ||
596 | ES8328_MASTERMODE_MSC, | ||
597 | ES8328_MASTERMODE_MSC); | ||
598 | break; | ||
599 | case SND_SOC_DAIFMT_CBS_CFS: | ||
600 | /* Slave serial port mode */ | ||
601 | snd_soc_update_bits(codec, ES8328_MASTERMODE, | ||
602 | ES8328_MASTERMODE_MSC, 0); | ||
603 | break; | ||
604 | default: | ||
594 | return -EINVAL; | 605 | return -EINVAL; |
606 | } | ||
595 | 607 | ||
596 | /* interface format */ | 608 | /* interface format */ |
597 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 609 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
@@ -620,10 +632,6 @@ static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
620 | snd_soc_update_bits(codec, ES8328_ADCCONTROL4, | 632 | snd_soc_update_bits(codec, ES8328_ADCCONTROL4, |
621 | ES8328_ADCCONTROL4_ADCFORMAT_MASK, adc_mode); | 633 | ES8328_ADCCONTROL4_ADCFORMAT_MASK, adc_mode); |
622 | 634 | ||
623 | /* Master serial port mode, with BCLK generated automatically */ | ||
624 | snd_soc_update_bits(codec, ES8328_MASTERMODE, | ||
625 | ES8328_MASTERMODE_MSC, ES8328_MASTERMODE_MSC); | ||
626 | |||
627 | return 0; | 635 | return 0; |
628 | } | 636 | } |
629 | 637 | ||
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 0c6228a0bf95..78fca8acd3ec 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c | |||
@@ -42,10 +42,15 @@ | |||
42 | #define HDA_MAX_CONNECTIONS 32 | 42 | #define HDA_MAX_CONNECTIONS 32 |
43 | 43 | ||
44 | #define HDA_MAX_CVTS 3 | 44 | #define HDA_MAX_CVTS 3 |
45 | #define HDA_MAX_PORTS 3 | ||
45 | 46 | ||
46 | #define ELD_MAX_SIZE 256 | 47 | #define ELD_MAX_SIZE 256 |
47 | #define ELD_FIXED_BYTES 20 | 48 | #define ELD_FIXED_BYTES 20 |
48 | 49 | ||
50 | #define ELD_VER_CEA_861D 2 | ||
51 | #define ELD_VER_PARTIAL 31 | ||
52 | #define ELD_MAX_MNL 16 | ||
53 | |||
49 | struct hdac_hdmi_cvt_params { | 54 | struct hdac_hdmi_cvt_params { |
50 | unsigned int channels_min; | 55 | unsigned int channels_min; |
51 | unsigned int channels_max; | 56 | unsigned int channels_max; |
@@ -77,43 +82,180 @@ struct hdac_hdmi_eld { | |||
77 | struct hdac_hdmi_pin { | 82 | struct hdac_hdmi_pin { |
78 | struct list_head head; | 83 | struct list_head head; |
79 | hda_nid_t nid; | 84 | hda_nid_t nid; |
85 | bool mst_capable; | ||
86 | struct hdac_hdmi_port *ports; | ||
87 | int num_ports; | ||
88 | struct hdac_ext_device *edev; | ||
89 | }; | ||
90 | |||
91 | struct hdac_hdmi_port { | ||
92 | struct list_head head; | ||
93 | int id; | ||
94 | struct hdac_hdmi_pin *pin; | ||
80 | int num_mux_nids; | 95 | int num_mux_nids; |
81 | hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; | 96 | hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; |
82 | struct hdac_hdmi_eld eld; | 97 | struct hdac_hdmi_eld eld; |
83 | struct hdac_ext_device *edev; | 98 | const char *jack_pin; |
84 | int repoll_count; | 99 | struct snd_soc_dapm_context *dapm; |
85 | struct delayed_work work; | 100 | const char *output_pin; |
86 | struct mutex lock; | ||
87 | bool chmap_set; | ||
88 | unsigned char chmap[8]; /* ALSA API channel-map */ | ||
89 | int channels; /* current number of channels */ | ||
90 | }; | 101 | }; |
91 | 102 | ||
92 | struct hdac_hdmi_pcm { | 103 | struct hdac_hdmi_pcm { |
93 | struct list_head head; | 104 | struct list_head head; |
94 | int pcm_id; | 105 | int pcm_id; |
95 | struct hdac_hdmi_pin *pin; | 106 | struct list_head port_list; |
96 | struct hdac_hdmi_cvt *cvt; | 107 | struct hdac_hdmi_cvt *cvt; |
97 | struct snd_jack *jack; | 108 | struct snd_soc_jack *jack; |
109 | int stream_tag; | ||
110 | int channels; | ||
111 | int format; | ||
112 | bool chmap_set; | ||
113 | unsigned char chmap[8]; /* ALSA API channel-map */ | ||
114 | struct mutex lock; | ||
115 | int jack_event; | ||
98 | }; | 116 | }; |
99 | 117 | ||
100 | struct hdac_hdmi_dai_pin_map { | 118 | struct hdac_hdmi_dai_port_map { |
101 | int dai_id; | 119 | int dai_id; |
102 | struct hdac_hdmi_pin *pin; | 120 | struct hdac_hdmi_port *port; |
103 | struct hdac_hdmi_cvt *cvt; | 121 | struct hdac_hdmi_cvt *cvt; |
104 | }; | 122 | }; |
105 | 123 | ||
106 | struct hdac_hdmi_priv { | 124 | struct hdac_hdmi_priv { |
107 | struct hdac_hdmi_dai_pin_map dai_map[HDA_MAX_CVTS]; | 125 | struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS]; |
108 | struct list_head pin_list; | 126 | struct list_head pin_list; |
109 | struct list_head cvt_list; | 127 | struct list_head cvt_list; |
110 | struct list_head pcm_list; | 128 | struct list_head pcm_list; |
111 | int num_pin; | 129 | int num_pin; |
112 | int num_cvt; | 130 | int num_cvt; |
131 | int num_ports; | ||
113 | struct mutex pin_mutex; | 132 | struct mutex pin_mutex; |
114 | struct hdac_chmap chmap; | 133 | struct hdac_chmap chmap; |
115 | }; | 134 | }; |
116 | 135 | ||
136 | static struct hdac_hdmi_pcm * | ||
137 | hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi, | ||
138 | struct hdac_hdmi_cvt *cvt) | ||
139 | { | ||
140 | struct hdac_hdmi_pcm *pcm = NULL; | ||
141 | |||
142 | list_for_each_entry(pcm, &hdmi->pcm_list, head) { | ||
143 | if (pcm->cvt == cvt) | ||
144 | break; | ||
145 | } | ||
146 | |||
147 | return pcm; | ||
148 | } | ||
149 | |||
150 | static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, | ||
151 | struct hdac_hdmi_port *port, bool is_connect) | ||
152 | { | ||
153 | struct hdac_ext_device *edev = port->pin->edev; | ||
154 | |||
155 | if (is_connect) | ||
156 | snd_soc_dapm_enable_pin(port->dapm, port->jack_pin); | ||
157 | else | ||
158 | snd_soc_dapm_disable_pin(port->dapm, port->jack_pin); | ||
159 | |||
160 | if (is_connect) { | ||
161 | /* | ||
162 | * Report Jack connect event when a device is connected | ||
163 | * for the first time where same PCM is attached to multiple | ||
164 | * ports. | ||
165 | */ | ||
166 | if (pcm->jack_event == 0) { | ||
167 | dev_dbg(&edev->hdac.dev, | ||
168 | "jack report for pcm=%d\n", | ||
169 | pcm->pcm_id); | ||
170 | snd_soc_jack_report(pcm->jack, SND_JACK_AVOUT, | ||
171 | SND_JACK_AVOUT); | ||
172 | } | ||
173 | pcm->jack_event++; | ||
174 | } else { | ||
175 | /* | ||
176 | * Report Jack disconnect event when a device is disconnected | ||
177 | * is the only last connected device when same PCM is attached | ||
178 | * to multiple ports. | ||
179 | */ | ||
180 | if (pcm->jack_event == 1) | ||
181 | snd_soc_jack_report(pcm->jack, 0, SND_JACK_AVOUT); | ||
182 | if (pcm->jack_event > 0) | ||
183 | pcm->jack_event--; | ||
184 | } | ||
185 | |||
186 | snd_soc_dapm_sync(port->dapm); | ||
187 | } | ||
188 | |||
189 | /* MST supported verbs */ | ||
190 | /* | ||
191 | * Get the no devices that can be connected to a port on the Pin widget. | ||
192 | */ | ||
193 | static int hdac_hdmi_get_port_len(struct hdac_ext_device *hdac, hda_nid_t nid) | ||
194 | { | ||
195 | unsigned int caps; | ||
196 | unsigned int type, param; | ||
197 | |||
198 | caps = get_wcaps(&hdac->hdac, nid); | ||
199 | type = get_wcaps_type(caps); | ||
200 | |||
201 | if (!(caps & AC_WCAP_DIGITAL) || (type != AC_WID_PIN)) | ||
202 | return 0; | ||
203 | |||
204 | param = snd_hdac_read_parm_uncached(&hdac->hdac, nid, | ||
205 | AC_PAR_DEVLIST_LEN); | ||
206 | if (param == -1) | ||
207 | return param; | ||
208 | |||
209 | return param & AC_DEV_LIST_LEN_MASK; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * Get the port entry select on the pin. Return the port entry | ||
214 | * id selected on the pin. Return 0 means the first port entry | ||
215 | * is selected or MST is not supported. | ||
216 | */ | ||
217 | static int hdac_hdmi_port_select_get(struct hdac_ext_device *hdac, | ||
218 | struct hdac_hdmi_port *port) | ||
219 | { | ||
220 | return snd_hdac_codec_read(&hdac->hdac, port->pin->nid, | ||
221 | 0, AC_VERB_GET_DEVICE_SEL, 0); | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Sets the selected port entry for the configuring Pin widget verb. | ||
226 | * returns error if port set is not equal to port get otherwise success | ||
227 | */ | ||
228 | static int hdac_hdmi_port_select_set(struct hdac_ext_device *hdac, | ||
229 | struct hdac_hdmi_port *port) | ||
230 | { | ||
231 | int num_ports; | ||
232 | |||
233 | if (!port->pin->mst_capable) | ||
234 | return 0; | ||
235 | |||
236 | /* AC_PAR_DEVLIST_LEN is 0 based. */ | ||
237 | num_ports = hdac_hdmi_get_port_len(hdac, port->pin->nid); | ||
238 | |||
239 | if (num_ports < 0) | ||
240 | return -EIO; | ||
241 | /* | ||
242 | * Device List Length is a 0 based integer value indicating the | ||
243 | * number of sink device that a MST Pin Widget can support. | ||
244 | */ | ||
245 | if (num_ports + 1 < port->id) | ||
246 | return 0; | ||
247 | |||
248 | snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0, | ||
249 | AC_VERB_SET_DEVICE_SEL, port->id); | ||
250 | |||
251 | if (port->id != hdac_hdmi_port_select_get(hdac, port)) | ||
252 | return -EIO; | ||
253 | |||
254 | dev_dbg(&hdac->hdac.dev, "Selected the port=%d\n", port->id); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
117 | static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi, | 259 | static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi, |
118 | int pcm_idx) | 260 | int pcm_idx) |
119 | { | 261 | { |
@@ -173,99 +315,6 @@ format_constraint: | |||
173 | 315 | ||
174 | } | 316 | } |
175 | 317 | ||
176 | /* HDMI ELD routines */ | ||
177 | static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec, | ||
178 | hda_nid_t nid, int byte_index) | ||
179 | { | ||
180 | unsigned int val; | ||
181 | |||
182 | val = snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD, | ||
183 | byte_index); | ||
184 | |||
185 | dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n", | ||
186 | byte_index, val); | ||
187 | |||
188 | return val; | ||
189 | } | ||
190 | |||
191 | static int hdac_hdmi_get_eld_size(struct hdac_device *codec, hda_nid_t nid) | ||
192 | { | ||
193 | return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, | ||
194 | AC_DIPSIZE_ELD_BUF); | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * This function queries the ELD size and ELD data and fills in the buffer | ||
199 | * passed by user | ||
200 | */ | ||
201 | static int hdac_hdmi_get_eld(struct hdac_device *codec, hda_nid_t nid, | ||
202 | unsigned char *buf, int *eld_size) | ||
203 | { | ||
204 | int i, size, ret = 0; | ||
205 | |||
206 | /* | ||
207 | * ELD size is initialized to zero in caller function. If no errors and | ||
208 | * ELD is valid, actual eld_size is assigned. | ||
209 | */ | ||
210 | |||
211 | size = hdac_hdmi_get_eld_size(codec, nid); | ||
212 | if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) { | ||
213 | dev_err(&codec->dev, "HDMI: invalid ELD buf size %d\n", size); | ||
214 | return -ERANGE; | ||
215 | } | ||
216 | |||
217 | /* set ELD buffer */ | ||
218 | for (i = 0; i < size; i++) { | ||
219 | unsigned int val = hdac_hdmi_get_eld_data(codec, nid, i); | ||
220 | /* | ||
221 | * Graphics driver might be writing to ELD buffer right now. | ||
222 | * Just abort. The caller will repoll after a while. | ||
223 | */ | ||
224 | if (!(val & AC_ELDD_ELD_VALID)) { | ||
225 | dev_err(&codec->dev, | ||
226 | "HDMI: invalid ELD data byte %d\n", i); | ||
227 | ret = -EINVAL; | ||
228 | goto error; | ||
229 | } | ||
230 | val &= AC_ELDD_ELD_DATA; | ||
231 | /* | ||
232 | * The first byte cannot be zero. This can happen on some DVI | ||
233 | * connections. Some Intel chips may also need some 250ms delay | ||
234 | * to return non-zero ELD data, even when the graphics driver | ||
235 | * correctly writes ELD content before setting ELD_valid bit. | ||
236 | */ | ||
237 | if (!val && !i) { | ||
238 | dev_err(&codec->dev, "HDMI: 0 ELD data\n"); | ||
239 | ret = -EINVAL; | ||
240 | goto error; | ||
241 | } | ||
242 | buf[i] = val; | ||
243 | } | ||
244 | |||
245 | *eld_size = size; | ||
246 | error: | ||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac, | ||
251 | hda_nid_t cvt_nid, hda_nid_t pin_nid, | ||
252 | u32 stream_tag, int format) | ||
253 | { | ||
254 | unsigned int val; | ||
255 | |||
256 | dev_dbg(&hdac->hdac.dev, "cvt nid %d pnid %d stream %d format 0x%x\n", | ||
257 | cvt_nid, pin_nid, stream_tag, format); | ||
258 | |||
259 | val = (stream_tag << 4); | ||
260 | |||
261 | snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0, | ||
262 | AC_VERB_SET_CHANNEL_STREAMID, val); | ||
263 | snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0, | ||
264 | AC_VERB_SET_STREAM_FORMAT, format); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static void | 318 | static void |
270 | hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid, | 319 | hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid, |
271 | int packet_index, int byte_index) | 320 | int packet_index, int byte_index) |
@@ -291,13 +340,14 @@ struct dp_audio_infoframe { | |||
291 | }; | 340 | }; |
292 | 341 | ||
293 | static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, | 342 | static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, |
294 | hda_nid_t cvt_nid, hda_nid_t pin_nid) | 343 | struct hdac_hdmi_pcm *pcm, struct hdac_hdmi_port *port) |
295 | { | 344 | { |
296 | uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; | 345 | uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; |
297 | struct hdmi_audio_infoframe frame; | 346 | struct hdmi_audio_infoframe frame; |
347 | struct hdac_hdmi_pin *pin = port->pin; | ||
298 | struct dp_audio_infoframe dp_ai; | 348 | struct dp_audio_infoframe dp_ai; |
299 | struct hdac_hdmi_priv *hdmi = hdac->private_data; | 349 | struct hdac_hdmi_priv *hdmi = hdac->private_data; |
300 | struct hdac_hdmi_pin *pin; | 350 | struct hdac_hdmi_cvt *cvt = pcm->cvt; |
301 | u8 *dip; | 351 | u8 *dip; |
302 | int ret; | 352 | int ret; |
303 | int i; | 353 | int i; |
@@ -305,21 +355,16 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, | |||
305 | u8 conn_type; | 355 | u8 conn_type; |
306 | int channels, ca; | 356 | int channels, ca; |
307 | 357 | ||
308 | list_for_each_entry(pin, &hdmi->pin_list, head) { | 358 | ca = snd_hdac_channel_allocation(&hdac->hdac, port->eld.info.spk_alloc, |
309 | if (pin->nid == pin_nid) | 359 | pcm->channels, pcm->chmap_set, true, pcm->chmap); |
310 | break; | ||
311 | } | ||
312 | |||
313 | ca = snd_hdac_channel_allocation(&hdac->hdac, pin->eld.info.spk_alloc, | ||
314 | pin->channels, pin->chmap_set, true, pin->chmap); | ||
315 | 360 | ||
316 | channels = snd_hdac_get_active_channels(ca); | 361 | channels = snd_hdac_get_active_channels(ca); |
317 | hdmi->chmap.ops.set_channel_count(&hdac->hdac, cvt_nid, channels); | 362 | hdmi->chmap.ops.set_channel_count(&hdac->hdac, cvt->nid, channels); |
318 | 363 | ||
319 | snd_hdac_setup_channel_mapping(&hdmi->chmap, pin->nid, false, ca, | 364 | snd_hdac_setup_channel_mapping(&hdmi->chmap, pin->nid, false, ca, |
320 | pin->channels, pin->chmap, pin->chmap_set); | 365 | pcm->channels, pcm->chmap, pcm->chmap_set); |
321 | 366 | ||
322 | eld_buf = pin->eld.eld_buffer; | 367 | eld_buf = port->eld.eld_buffer; |
323 | conn_type = drm_eld_get_conn_type(eld_buf); | 368 | conn_type = drm_eld_get_conn_type(eld_buf); |
324 | 369 | ||
325 | switch (conn_type) { | 370 | switch (conn_type) { |
@@ -353,75 +398,50 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, | |||
353 | } | 398 | } |
354 | 399 | ||
355 | /* stop infoframe transmission */ | 400 | /* stop infoframe transmission */ |
356 | hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); | 401 | hdac_hdmi_set_dip_index(hdac, pin->nid, 0x0, 0x0); |
357 | snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, | 402 | snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, |
358 | AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_DISABLE); | 403 | AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_DISABLE); |
359 | 404 | ||
360 | 405 | ||
361 | /* Fill infoframe. Index auto-incremented */ | 406 | /* Fill infoframe. Index auto-incremented */ |
362 | hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); | 407 | hdac_hdmi_set_dip_index(hdac, pin->nid, 0x0, 0x0); |
363 | if (conn_type == DRM_ELD_CONN_TYPE_HDMI) { | 408 | if (conn_type == DRM_ELD_CONN_TYPE_HDMI) { |
364 | for (i = 0; i < sizeof(buffer); i++) | 409 | for (i = 0; i < sizeof(buffer); i++) |
365 | snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, | 410 | snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, |
366 | AC_VERB_SET_HDMI_DIP_DATA, buffer[i]); | 411 | AC_VERB_SET_HDMI_DIP_DATA, buffer[i]); |
367 | } else { | 412 | } else { |
368 | for (i = 0; i < sizeof(dp_ai); i++) | 413 | for (i = 0; i < sizeof(dp_ai); i++) |
369 | snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, | 414 | snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, |
370 | AC_VERB_SET_HDMI_DIP_DATA, dip[i]); | 415 | AC_VERB_SET_HDMI_DIP_DATA, dip[i]); |
371 | } | 416 | } |
372 | 417 | ||
373 | /* Start infoframe */ | 418 | /* Start infoframe */ |
374 | hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); | 419 | hdac_hdmi_set_dip_index(hdac, pin->nid, 0x0, 0x0); |
375 | snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, | 420 | snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, |
376 | AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_BEST); | 421 | AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_BEST); |
377 | 422 | ||
378 | return 0; | 423 | return 0; |
379 | } | 424 | } |
380 | 425 | ||
381 | static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev, | 426 | static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai, |
382 | struct hdac_hdmi_dai_pin_map *dai_map, unsigned int pwr_state) | 427 | unsigned int tx_mask, unsigned int rx_mask, |
428 | int slots, int slot_width) | ||
383 | { | 429 | { |
384 | /* Power up pin widget */ | 430 | struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai); |
385 | if (!snd_hdac_check_power_state(&edev->hdac, dai_map->pin->nid, | 431 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
386 | pwr_state)) | 432 | struct hdac_hdmi_dai_port_map *dai_map; |
387 | snd_hdac_codec_write(&edev->hdac, dai_map->pin->nid, 0, | 433 | struct hdac_hdmi_pcm *pcm; |
388 | AC_VERB_SET_POWER_STATE, pwr_state); | ||
389 | |||
390 | /* Power up converter */ | ||
391 | if (!snd_hdac_check_power_state(&edev->hdac, dai_map->cvt->nid, | ||
392 | pwr_state)) | ||
393 | snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0, | ||
394 | AC_VERB_SET_POWER_STATE, pwr_state); | ||
395 | } | ||
396 | 434 | ||
397 | static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream, | 435 | dev_dbg(&edev->hdac.dev, "%s: strm_tag: %d\n", __func__, tx_mask); |
398 | struct snd_soc_dai *dai) | ||
399 | { | ||
400 | struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); | ||
401 | struct hdac_hdmi_priv *hdmi = hdac->private_data; | ||
402 | struct hdac_hdmi_dai_pin_map *dai_map; | ||
403 | struct hdac_hdmi_pin *pin; | ||
404 | struct hdac_ext_dma_params *dd; | ||
405 | int ret; | ||
406 | 436 | ||
407 | dai_map = &hdmi->dai_map[dai->id]; | 437 | dai_map = &hdmi->dai_map[dai->id]; |
408 | pin = dai_map->pin; | ||
409 | |||
410 | dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream); | ||
411 | dev_dbg(&hdac->hdac.dev, "stream tag from cpu dai %d format in cvt 0x%x\n", | ||
412 | dd->stream_tag, dd->format); | ||
413 | 438 | ||
414 | mutex_lock(&pin->lock); | 439 | pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt); |
415 | pin->channels = substream->runtime->channels; | ||
416 | 440 | ||
417 | ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt->nid, | 441 | if (pcm) |
418 | dai_map->pin->nid); | 442 | pcm->stream_tag = (tx_mask << 4); |
419 | mutex_unlock(&pin->lock); | ||
420 | if (ret < 0) | ||
421 | return ret; | ||
422 | 443 | ||
423 | return hdac_hdmi_setup_stream(hdac, dai_map->cvt->nid, | 444 | return 0; |
424 | dai_map->pin->nid, dd->stream_tag, dd->format); | ||
425 | } | 445 | } |
426 | 446 | ||
427 | static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream, | 447 | static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream, |
@@ -429,101 +449,41 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream, | |||
429 | { | 449 | { |
430 | struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); | 450 | struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); |
431 | struct hdac_hdmi_priv *hdmi = hdac->private_data; | 451 | struct hdac_hdmi_priv *hdmi = hdac->private_data; |
432 | struct hdac_hdmi_dai_pin_map *dai_map; | 452 | struct hdac_hdmi_dai_port_map *dai_map; |
433 | struct hdac_hdmi_pin *pin; | 453 | struct hdac_hdmi_port *port; |
434 | struct hdac_ext_dma_params *dd; | 454 | struct hdac_hdmi_pcm *pcm; |
455 | int format; | ||
435 | 456 | ||
436 | dai_map = &hdmi->dai_map[dai->id]; | 457 | dai_map = &hdmi->dai_map[dai->id]; |
437 | pin = dai_map->pin; | 458 | port = dai_map->port; |
438 | 459 | ||
439 | if (!pin) | 460 | if (!port) |
440 | return -ENODEV; | 461 | return -ENODEV; |
441 | 462 | ||
442 | if ((!pin->eld.monitor_present) || (!pin->eld.eld_valid)) { | 463 | if ((!port->eld.monitor_present) || (!port->eld.eld_valid)) { |
443 | dev_err(&hdac->hdac.dev, "device is not configured for this pin: %d\n", | 464 | dev_err(&hdac->hdac.dev, |
444 | pin->nid); | 465 | "device is not configured for this pin:port%d:%d\n", |
466 | port->pin->nid, port->id); | ||
445 | return -ENODEV; | 467 | return -ENODEV; |
446 | } | 468 | } |
447 | 469 | ||
448 | dd = snd_soc_dai_get_dma_data(dai, substream); | 470 | format = snd_hdac_calc_stream_format(params_rate(hparams), |
449 | if (!dd) { | ||
450 | dd = kzalloc(sizeof(*dd), GFP_KERNEL); | ||
451 | if (!dd) | ||
452 | return -ENOMEM; | ||
453 | } | ||
454 | |||
455 | dd->format = snd_hdac_calc_stream_format(params_rate(hparams), | ||
456 | params_channels(hparams), params_format(hparams), | 471 | params_channels(hparams), params_format(hparams), |
457 | 24, 0); | 472 | 24, 0); |
458 | 473 | ||
459 | snd_soc_dai_set_dma_data(dai, substream, (void *)dd); | 474 | pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt); |
460 | 475 | if (!pcm) | |
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream, | ||
465 | struct snd_soc_dai *dai) | ||
466 | { | ||
467 | struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai); | ||
468 | struct hdac_ext_dma_params *dd; | ||
469 | struct hdac_hdmi_priv *hdmi = edev->private_data; | ||
470 | struct hdac_hdmi_dai_pin_map *dai_map; | ||
471 | |||
472 | dai_map = &hdmi->dai_map[dai->id]; | ||
473 | |||
474 | dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream); | ||
475 | |||
476 | if (dd) { | ||
477 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
478 | kfree(dd); | ||
479 | } | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static void hdac_hdmi_enable_cvt(struct hdac_ext_device *edev, | ||
485 | struct hdac_hdmi_dai_pin_map *dai_map) | ||
486 | { | ||
487 | /* Enable transmission */ | ||
488 | snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0, | ||
489 | AC_VERB_SET_DIGI_CONVERT_1, 1); | ||
490 | |||
491 | /* Category Code (CC) to zero */ | ||
492 | snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0, | ||
493 | AC_VERB_SET_DIGI_CONVERT_2, 0); | ||
494 | } | ||
495 | |||
496 | static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac, | ||
497 | struct hdac_hdmi_dai_pin_map *dai_map) | ||
498 | { | ||
499 | int mux_idx; | ||
500 | struct hdac_hdmi_pin *pin = dai_map->pin; | ||
501 | |||
502 | for (mux_idx = 0; mux_idx < pin->num_mux_nids; mux_idx++) { | ||
503 | if (pin->mux_nids[mux_idx] == dai_map->cvt->nid) { | ||
504 | snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, | ||
505 | AC_VERB_SET_CONNECT_SEL, mux_idx); | ||
506 | break; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | if (mux_idx == pin->num_mux_nids) | ||
511 | return -EIO; | 476 | return -EIO; |
512 | 477 | ||
513 | /* Enable out path for this pin widget */ | 478 | pcm->format = format; |
514 | snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, | 479 | pcm->channels = params_channels(hparams); |
515 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
516 | |||
517 | hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0); | ||
518 | |||
519 | snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, | ||
520 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
521 | 480 | ||
522 | return 0; | 481 | return 0; |
523 | } | 482 | } |
524 | 483 | ||
525 | static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac, | 484 | static int hdac_hdmi_query_port_connlist(struct hdac_ext_device *hdac, |
526 | struct hdac_hdmi_pin *pin) | 485 | struct hdac_hdmi_pin *pin, |
486 | struct hdac_hdmi_port *port) | ||
527 | { | 487 | { |
528 | if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) { | 488 | if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) { |
529 | dev_warn(&hdac->hdac.dev, | 489 | dev_warn(&hdac->hdac.dev, |
@@ -532,51 +492,60 @@ static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac, | |||
532 | return -EINVAL; | 492 | return -EINVAL; |
533 | } | 493 | } |
534 | 494 | ||
535 | pin->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid, | 495 | if (hdac_hdmi_port_select_set(hdac, port) < 0) |
536 | pin->mux_nids, HDA_MAX_CONNECTIONS); | 496 | return -EIO; |
537 | if (pin->num_mux_nids == 0) | ||
538 | dev_warn(&hdac->hdac.dev, "No connections found for pin: %d\n", | ||
539 | pin->nid); | ||
540 | 497 | ||
541 | dev_dbg(&hdac->hdac.dev, "num_mux_nids %d for pin: %d\n", | 498 | port->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid, |
542 | pin->num_mux_nids, pin->nid); | 499 | port->mux_nids, HDA_MAX_CONNECTIONS); |
500 | if (port->num_mux_nids == 0) | ||
501 | dev_warn(&hdac->hdac.dev, | ||
502 | "No connections found for pin:port %d:%d\n", | ||
503 | pin->nid, port->id); | ||
504 | |||
505 | dev_dbg(&hdac->hdac.dev, "num_mux_nids %d for pin:port %d:%d\n", | ||
506 | port->num_mux_nids, pin->nid, port->id); | ||
543 | 507 | ||
544 | return pin->num_mux_nids; | 508 | return port->num_mux_nids; |
545 | } | 509 | } |
546 | 510 | ||
547 | /* | 511 | /* |
548 | * Query pcm list and return pin widget to which stream is routed. | 512 | * Query pcm list and return port to which stream is routed. |
549 | * | 513 | * |
550 | * Also query connection list of the pin, to validate the cvt to pin map. | 514 | * Also query connection list of the pin, to validate the cvt to port map. |
551 | * | 515 | * |
552 | * Same stream rendering to multiple pins simultaneously can be done | 516 | * Same stream rendering to multiple ports simultaneously can be done |
553 | * possibly, but not supported for now in driver. So return the first pin | 517 | * possibly, but not supported for now in driver. So return the first port |
554 | * connected. | 518 | * connected. |
555 | */ | 519 | */ |
556 | static struct hdac_hdmi_pin *hdac_hdmi_get_pin_from_cvt( | 520 | static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt( |
557 | struct hdac_ext_device *edev, | 521 | struct hdac_ext_device *edev, |
558 | struct hdac_hdmi_priv *hdmi, | 522 | struct hdac_hdmi_priv *hdmi, |
559 | struct hdac_hdmi_cvt *cvt) | 523 | struct hdac_hdmi_cvt *cvt) |
560 | { | 524 | { |
561 | struct hdac_hdmi_pcm *pcm; | 525 | struct hdac_hdmi_pcm *pcm; |
562 | struct hdac_hdmi_pin *pin = NULL; | 526 | struct hdac_hdmi_port *port = NULL; |
563 | int ret, i; | 527 | int ret, i; |
564 | 528 | ||
565 | list_for_each_entry(pcm, &hdmi->pcm_list, head) { | 529 | list_for_each_entry(pcm, &hdmi->pcm_list, head) { |
566 | if (pcm->cvt == cvt) { | 530 | if (pcm->cvt == cvt) { |
567 | pin = pcm->pin; | 531 | if (list_empty(&pcm->port_list)) |
568 | break; | 532 | continue; |
569 | } | 533 | |
570 | } | 534 | list_for_each_entry(port, &pcm->port_list, head) { |
571 | 535 | mutex_lock(&pcm->lock); | |
572 | if (pin) { | 536 | ret = hdac_hdmi_query_port_connlist(edev, |
573 | ret = hdac_hdmi_query_pin_connlist(edev, pin); | 537 | port->pin, port); |
574 | if (ret < 0) | 538 | mutex_unlock(&pcm->lock); |
575 | return NULL; | 539 | if (ret < 0) |
576 | 540 | continue; | |
577 | for (i = 0; i < pin->num_mux_nids; i++) { | 541 | |
578 | if (pin->mux_nids[i] == cvt->nid) | 542 | for (i = 0; i < port->num_mux_nids; i++) { |
579 | return pin; | 543 | if (port->mux_nids[i] == cvt->nid && |
544 | port->eld.monitor_present && | ||
545 | port->eld.eld_valid) | ||
546 | return port; | ||
547 | } | ||
548 | } | ||
580 | } | 549 | } |
581 | } | 550 | } |
582 | 551 | ||
@@ -593,67 +562,42 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, | |||
593 | { | 562 | { |
594 | struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); | 563 | struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); |
595 | struct hdac_hdmi_priv *hdmi = hdac->private_data; | 564 | struct hdac_hdmi_priv *hdmi = hdac->private_data; |
596 | struct hdac_hdmi_dai_pin_map *dai_map; | 565 | struct hdac_hdmi_dai_port_map *dai_map; |
597 | struct hdac_hdmi_cvt *cvt; | 566 | struct hdac_hdmi_cvt *cvt; |
598 | struct hdac_hdmi_pin *pin; | 567 | struct hdac_hdmi_port *port; |
599 | int ret; | 568 | int ret; |
600 | 569 | ||
601 | dai_map = &hdmi->dai_map[dai->id]; | 570 | dai_map = &hdmi->dai_map[dai->id]; |
602 | 571 | ||
603 | cvt = dai_map->cvt; | 572 | cvt = dai_map->cvt; |
604 | pin = hdac_hdmi_get_pin_from_cvt(hdac, hdmi, cvt); | 573 | port = hdac_hdmi_get_port_from_cvt(hdac, hdmi, cvt); |
605 | 574 | ||
606 | /* | 575 | /* |
607 | * To make PA and other userland happy. | 576 | * To make PA and other userland happy. |
608 | * userland scans devices so returning error does not help. | 577 | * userland scans devices so returning error does not help. |
609 | */ | 578 | */ |
610 | if (!pin) | 579 | if (!port) |
611 | return 0; | 580 | return 0; |
612 | 581 | if ((!port->eld.monitor_present) || | |
613 | if ((!pin->eld.monitor_present) || | 582 | (!port->eld.eld_valid)) { |
614 | (!pin->eld.eld_valid)) { | ||
615 | 583 | ||
616 | dev_warn(&hdac->hdac.dev, | 584 | dev_warn(&hdac->hdac.dev, |
617 | "Failed: monitor present? %d ELD valid?: %d for pin: %d\n", | 585 | "Failed: present?:%d ELD valid?:%d pin:port: %d:%d\n", |
618 | pin->eld.monitor_present, pin->eld.eld_valid, pin->nid); | 586 | port->eld.monitor_present, port->eld.eld_valid, |
587 | port->pin->nid, port->id); | ||
619 | 588 | ||
620 | return 0; | 589 | return 0; |
621 | } | 590 | } |
622 | 591 | ||
623 | dai_map->pin = pin; | 592 | dai_map->port = port; |
624 | |||
625 | hdac_hdmi_enable_cvt(hdac, dai_map); | ||
626 | ret = hdac_hdmi_enable_pin(hdac, dai_map); | ||
627 | if (ret < 0) | ||
628 | return ret; | ||
629 | 593 | ||
630 | ret = hdac_hdmi_eld_limit_formats(substream->runtime, | 594 | ret = hdac_hdmi_eld_limit_formats(substream->runtime, |
631 | pin->eld.eld_buffer); | 595 | port->eld.eld_buffer); |
632 | if (ret < 0) | 596 | if (ret < 0) |
633 | return ret; | 597 | return ret; |
634 | 598 | ||
635 | return snd_pcm_hw_constraint_eld(substream->runtime, | 599 | return snd_pcm_hw_constraint_eld(substream->runtime, |
636 | pin->eld.eld_buffer); | 600 | port->eld.eld_buffer); |
637 | } | ||
638 | |||
639 | static int hdac_hdmi_trigger(struct snd_pcm_substream *substream, int cmd, | ||
640 | struct snd_soc_dai *dai) | ||
641 | { | ||
642 | struct hdac_hdmi_dai_pin_map *dai_map; | ||
643 | struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); | ||
644 | struct hdac_hdmi_priv *hdmi = hdac->private_data; | ||
645 | int ret; | ||
646 | |||
647 | dai_map = &hdmi->dai_map[dai->id]; | ||
648 | if (cmd == SNDRV_PCM_TRIGGER_RESUME) { | ||
649 | ret = hdac_hdmi_enable_pin(hdac, dai_map); | ||
650 | if (ret < 0) | ||
651 | return ret; | ||
652 | |||
653 | return hdac_hdmi_playback_prepare(substream, dai); | ||
654 | } | ||
655 | |||
656 | return 0; | ||
657 | } | 601 | } |
658 | 602 | ||
659 | static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream, | 603 | static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream, |
@@ -661,29 +605,23 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream, | |||
661 | { | 605 | { |
662 | struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); | 606 | struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); |
663 | struct hdac_hdmi_priv *hdmi = hdac->private_data; | 607 | struct hdac_hdmi_priv *hdmi = hdac->private_data; |
664 | struct hdac_hdmi_dai_pin_map *dai_map; | 608 | struct hdac_hdmi_dai_port_map *dai_map; |
609 | struct hdac_hdmi_pcm *pcm; | ||
665 | 610 | ||
666 | dai_map = &hdmi->dai_map[dai->id]; | 611 | dai_map = &hdmi->dai_map[dai->id]; |
667 | 612 | ||
668 | if (dai_map->pin) { | 613 | pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt); |
669 | snd_hdac_codec_write(&hdac->hdac, dai_map->cvt->nid, 0, | ||
670 | AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
671 | snd_hdac_codec_write(&hdac->hdac, dai_map->cvt->nid, 0, | ||
672 | AC_VERB_SET_STREAM_FORMAT, 0); | ||
673 | |||
674 | hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3); | ||
675 | |||
676 | snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0, | ||
677 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | ||
678 | |||
679 | mutex_lock(&dai_map->pin->lock); | ||
680 | dai_map->pin->chmap_set = false; | ||
681 | memset(dai_map->pin->chmap, 0, sizeof(dai_map->pin->chmap)); | ||
682 | dai_map->pin->channels = 0; | ||
683 | mutex_unlock(&dai_map->pin->lock); | ||
684 | 614 | ||
685 | dai_map->pin = NULL; | 615 | if (pcm) { |
616 | mutex_lock(&pcm->lock); | ||
617 | pcm->chmap_set = false; | ||
618 | memset(pcm->chmap, 0, sizeof(pcm->chmap)); | ||
619 | pcm->channels = 0; | ||
620 | mutex_unlock(&pcm->lock); | ||
686 | } | 621 | } |
622 | |||
623 | if (dai_map->port) | ||
624 | dai_map->port = NULL; | ||
687 | } | 625 | } |
688 | 626 | ||
689 | static int | 627 | static int |
@@ -716,10 +654,11 @@ hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt) | |||
716 | } | 654 | } |
717 | 655 | ||
718 | static int hdac_hdmi_fill_widget_info(struct device *dev, | 656 | static int hdac_hdmi_fill_widget_info(struct device *dev, |
719 | struct snd_soc_dapm_widget *w, | 657 | struct snd_soc_dapm_widget *w, enum snd_soc_dapm_type id, |
720 | enum snd_soc_dapm_type id, void *priv, | 658 | void *priv, const char *wname, const char *stream, |
721 | const char *wname, const char *stream, | 659 | struct snd_kcontrol_new *wc, int numkc, |
722 | struct snd_kcontrol_new *wc, int numkc) | 660 | int (*event)(struct snd_soc_dapm_widget *, |
661 | struct snd_kcontrol *, int), unsigned short event_flags) | ||
723 | { | 662 | { |
724 | w->id = id; | 663 | w->id = id; |
725 | w->name = devm_kstrdup(dev, wname, GFP_KERNEL); | 664 | w->name = devm_kstrdup(dev, wname, GFP_KERNEL); |
@@ -732,6 +671,8 @@ static int hdac_hdmi_fill_widget_info(struct device *dev, | |||
732 | w->kcontrol_news = wc; | 671 | w->kcontrol_news = wc; |
733 | w->num_kcontrols = numkc; | 672 | w->num_kcontrols = numkc; |
734 | w->priv = priv; | 673 | w->priv = priv; |
674 | w->event = event; | ||
675 | w->event_flags = event_flags; | ||
735 | 676 | ||
736 | return 0; | 677 | return 0; |
737 | } | 678 | } |
@@ -748,30 +689,175 @@ static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route, | |||
748 | } | 689 | } |
749 | 690 | ||
750 | static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev, | 691 | static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev, |
751 | struct hdac_hdmi_pin *pin) | 692 | struct hdac_hdmi_port *port) |
752 | { | 693 | { |
753 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 694 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
754 | struct hdac_hdmi_pcm *pcm = NULL; | 695 | struct hdac_hdmi_pcm *pcm = NULL; |
696 | struct hdac_hdmi_port *p; | ||
755 | 697 | ||
756 | list_for_each_entry(pcm, &hdmi->pcm_list, head) { | 698 | list_for_each_entry(pcm, &hdmi->pcm_list, head) { |
757 | if (pcm->pin == pin) | 699 | if (list_empty(&pcm->port_list)) |
758 | return pcm; | 700 | continue; |
701 | |||
702 | list_for_each_entry(p, &pcm->port_list, head) { | ||
703 | if (p->id == port->id && port->pin == p->pin) | ||
704 | return pcm; | ||
705 | } | ||
759 | } | 706 | } |
760 | 707 | ||
761 | return NULL; | 708 | return NULL; |
762 | } | 709 | } |
763 | 710 | ||
711 | static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev, | ||
712 | hda_nid_t nid, unsigned int pwr_state) | ||
713 | { | ||
714 | if (get_wcaps(&edev->hdac, nid) & AC_WCAP_POWER) { | ||
715 | if (!snd_hdac_check_power_state(&edev->hdac, nid, pwr_state)) | ||
716 | snd_hdac_codec_write(&edev->hdac, nid, 0, | ||
717 | AC_VERB_SET_POWER_STATE, pwr_state); | ||
718 | } | ||
719 | } | ||
720 | |||
721 | static void hdac_hdmi_set_amp(struct hdac_ext_device *edev, | ||
722 | hda_nid_t nid, int val) | ||
723 | { | ||
724 | if (get_wcaps(&edev->hdac, nid) & AC_WCAP_OUT_AMP) | ||
725 | snd_hdac_codec_write(&edev->hdac, nid, 0, | ||
726 | AC_VERB_SET_AMP_GAIN_MUTE, val); | ||
727 | } | ||
728 | |||
729 | |||
730 | static int hdac_hdmi_pin_output_widget_event(struct snd_soc_dapm_widget *w, | ||
731 | struct snd_kcontrol *kc, int event) | ||
732 | { | ||
733 | struct hdac_hdmi_port *port = w->priv; | ||
734 | struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev); | ||
735 | struct hdac_hdmi_pcm *pcm; | ||
736 | |||
737 | dev_dbg(&edev->hdac.dev, "%s: widget: %s event: %x\n", | ||
738 | __func__, w->name, event); | ||
739 | |||
740 | pcm = hdac_hdmi_get_pcm(edev, port); | ||
741 | if (!pcm) | ||
742 | return -EIO; | ||
743 | |||
744 | /* set the device if pin is mst_capable */ | ||
745 | if (hdac_hdmi_port_select_set(edev, port) < 0) | ||
746 | return -EIO; | ||
747 | |||
748 | switch (event) { | ||
749 | case SND_SOC_DAPM_PRE_PMU: | ||
750 | hdac_hdmi_set_power_state(edev, port->pin->nid, AC_PWRST_D0); | ||
751 | |||
752 | /* Enable out path for this pin widget */ | ||
753 | snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0, | ||
754 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
755 | |||
756 | hdac_hdmi_set_amp(edev, port->pin->nid, AMP_OUT_UNMUTE); | ||
757 | |||
758 | return hdac_hdmi_setup_audio_infoframe(edev, pcm, port); | ||
759 | |||
760 | case SND_SOC_DAPM_POST_PMD: | ||
761 | hdac_hdmi_set_amp(edev, port->pin->nid, AMP_OUT_MUTE); | ||
762 | |||
763 | /* Disable out path for this pin widget */ | ||
764 | snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0, | ||
765 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
766 | |||
767 | hdac_hdmi_set_power_state(edev, port->pin->nid, AC_PWRST_D3); | ||
768 | break; | ||
769 | |||
770 | } | ||
771 | |||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | static int hdac_hdmi_cvt_output_widget_event(struct snd_soc_dapm_widget *w, | ||
776 | struct snd_kcontrol *kc, int event) | ||
777 | { | ||
778 | struct hdac_hdmi_cvt *cvt = w->priv; | ||
779 | struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev); | ||
780 | struct hdac_hdmi_priv *hdmi = edev->private_data; | ||
781 | struct hdac_hdmi_pcm *pcm; | ||
782 | |||
783 | dev_dbg(&edev->hdac.dev, "%s: widget: %s event: %x\n", | ||
784 | __func__, w->name, event); | ||
785 | |||
786 | pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, cvt); | ||
787 | if (!pcm) | ||
788 | return -EIO; | ||
789 | |||
790 | switch (event) { | ||
791 | case SND_SOC_DAPM_PRE_PMU: | ||
792 | hdac_hdmi_set_power_state(edev, cvt->nid, AC_PWRST_D0); | ||
793 | |||
794 | /* Enable transmission */ | ||
795 | snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, | ||
796 | AC_VERB_SET_DIGI_CONVERT_1, 1); | ||
797 | |||
798 | /* Category Code (CC) to zero */ | ||
799 | snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, | ||
800 | AC_VERB_SET_DIGI_CONVERT_2, 0); | ||
801 | |||
802 | snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, | ||
803 | AC_VERB_SET_CHANNEL_STREAMID, pcm->stream_tag); | ||
804 | snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, | ||
805 | AC_VERB_SET_STREAM_FORMAT, pcm->format); | ||
806 | break; | ||
807 | |||
808 | case SND_SOC_DAPM_POST_PMD: | ||
809 | snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, | ||
810 | AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
811 | snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, | ||
812 | AC_VERB_SET_STREAM_FORMAT, 0); | ||
813 | |||
814 | hdac_hdmi_set_power_state(edev, cvt->nid, AC_PWRST_D3); | ||
815 | break; | ||
816 | |||
817 | } | ||
818 | |||
819 | return 0; | ||
820 | } | ||
821 | |||
822 | static int hdac_hdmi_pin_mux_widget_event(struct snd_soc_dapm_widget *w, | ||
823 | struct snd_kcontrol *kc, int event) | ||
824 | { | ||
825 | struct hdac_hdmi_port *port = w->priv; | ||
826 | struct hdac_ext_device *edev = to_hda_ext_device(w->dapm->dev); | ||
827 | int mux_idx; | ||
828 | |||
829 | dev_dbg(&edev->hdac.dev, "%s: widget: %s event: %x\n", | ||
830 | __func__, w->name, event); | ||
831 | |||
832 | if (!kc) | ||
833 | kc = w->kcontrols[0]; | ||
834 | |||
835 | mux_idx = dapm_kcontrol_get_value(kc); | ||
836 | |||
837 | /* set the device if pin is mst_capable */ | ||
838 | if (hdac_hdmi_port_select_set(edev, port) < 0) | ||
839 | return -EIO; | ||
840 | |||
841 | if (mux_idx > 0) { | ||
842 | snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0, | ||
843 | AC_VERB_SET_CONNECT_SEL, (mux_idx - 1)); | ||
844 | } | ||
845 | |||
846 | return 0; | ||
847 | } | ||
848 | |||
764 | /* | 849 | /* |
765 | * Based on user selection, map the PINs with the PCMs. | 850 | * Based on user selection, map the PINs with the PCMs. |
766 | */ | 851 | */ |
767 | static int hdac_hdmi_set_pin_mux(struct snd_kcontrol *kcontrol, | 852 | static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, |
768 | struct snd_ctl_elem_value *ucontrol) | 853 | struct snd_ctl_elem_value *ucontrol) |
769 | { | 854 | { |
770 | int ret; | 855 | int ret; |
856 | struct hdac_hdmi_port *p, *p_next; | ||
771 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 857 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
772 | struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); | 858 | struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); |
773 | struct snd_soc_dapm_context *dapm = w->dapm; | 859 | struct snd_soc_dapm_context *dapm = w->dapm; |
774 | struct hdac_hdmi_pin *pin = w->priv; | 860 | struct hdac_hdmi_port *port = w->priv; |
775 | struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev); | 861 | struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev); |
776 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 862 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
777 | struct hdac_hdmi_pcm *pcm = NULL; | 863 | struct hdac_hdmi_pcm *pcm = NULL; |
@@ -781,26 +867,35 @@ static int hdac_hdmi_set_pin_mux(struct snd_kcontrol *kcontrol, | |||
781 | if (ret < 0) | 867 | if (ret < 0) |
782 | return ret; | 868 | return ret; |
783 | 869 | ||
870 | if (port == NULL) | ||
871 | return -EINVAL; | ||
872 | |||
784 | mutex_lock(&hdmi->pin_mutex); | 873 | mutex_lock(&hdmi->pin_mutex); |
785 | list_for_each_entry(pcm, &hdmi->pcm_list, head) { | 874 | list_for_each_entry(pcm, &hdmi->pcm_list, head) { |
786 | if (pcm->pin == pin) | 875 | if (list_empty(&pcm->port_list)) |
787 | pcm->pin = NULL; | 876 | continue; |
788 | 877 | ||
789 | /* | 878 | list_for_each_entry_safe(p, p_next, &pcm->port_list, head) { |
790 | * Jack status is not reported during device probe as the | 879 | if (p == port && p->id == port->id && |
791 | * PCMs are not registered by then. So report it here. | 880 | p->pin == port->pin) { |
792 | */ | 881 | hdac_hdmi_jack_report(pcm, port, false); |
793 | if (!strcmp(cvt_name, pcm->cvt->name) && !pcm->pin) { | 882 | list_del(&p->head); |
794 | pcm->pin = pin; | 883 | } |
795 | if (pin->eld.monitor_present && pin->eld.eld_valid) { | 884 | } |
796 | dev_dbg(&edev->hdac.dev, | 885 | } |
797 | "jack report for pcm=%d\n", | ||
798 | pcm->pcm_id); | ||
799 | 886 | ||
800 | snd_jack_report(pcm->jack, SND_JACK_AVOUT); | 887 | /* |
888 | * Jack status is not reported during device probe as the | ||
889 | * PCMs are not registered by then. So report it here. | ||
890 | */ | ||
891 | list_for_each_entry(pcm, &hdmi->pcm_list, head) { | ||
892 | if (!strcmp(cvt_name, pcm->cvt->name)) { | ||
893 | list_add_tail(&port->head, &pcm->port_list); | ||
894 | if (port->eld.monitor_present && port->eld.eld_valid) { | ||
895 | hdac_hdmi_jack_report(pcm, port, true); | ||
896 | mutex_unlock(&hdmi->pin_mutex); | ||
897 | return ret; | ||
801 | } | 898 | } |
802 | mutex_unlock(&hdmi->pin_mutex); | ||
803 | return ret; | ||
804 | } | 899 | } |
805 | } | 900 | } |
806 | mutex_unlock(&hdmi->pin_mutex); | 901 | mutex_unlock(&hdmi->pin_mutex); |
@@ -817,12 +912,13 @@ static int hdac_hdmi_set_pin_mux(struct snd_kcontrol *kcontrol, | |||
817 | * care of selecting the right one and leaving all other inputs selected to | 912 | * care of selecting the right one and leaving all other inputs selected to |
818 | * "NONE" | 913 | * "NONE" |
819 | */ | 914 | */ |
820 | static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev, | 915 | static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev, |
821 | struct hdac_hdmi_pin *pin, | 916 | struct hdac_hdmi_port *port, |
822 | struct snd_soc_dapm_widget *widget, | 917 | struct snd_soc_dapm_widget *widget, |
823 | const char *widget_name) | 918 | const char *widget_name) |
824 | { | 919 | { |
825 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 920 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
921 | struct hdac_hdmi_pin *pin = port->pin; | ||
826 | struct snd_kcontrol_new *kc; | 922 | struct snd_kcontrol_new *kc; |
827 | struct hdac_hdmi_cvt *cvt; | 923 | struct hdac_hdmi_cvt *cvt; |
828 | struct soc_enum *se; | 924 | struct soc_enum *se; |
@@ -841,7 +937,7 @@ static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev, | |||
841 | if (!se) | 937 | if (!se) |
842 | return -ENOMEM; | 938 | return -ENOMEM; |
843 | 939 | ||
844 | sprintf(kc_name, "Pin %d Input", pin->nid); | 940 | sprintf(kc_name, "Pin %d port %d Input", pin->nid, port->id); |
845 | kc->name = devm_kstrdup(&edev->hdac.dev, kc_name, GFP_KERNEL); | 941 | kc->name = devm_kstrdup(&edev->hdac.dev, kc_name, GFP_KERNEL); |
846 | if (!kc->name) | 942 | if (!kc->name) |
847 | return -ENOMEM; | 943 | return -ENOMEM; |
@@ -850,7 +946,7 @@ static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev, | |||
850 | kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 946 | kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
851 | kc->access = 0; | 947 | kc->access = 0; |
852 | kc->info = snd_soc_info_enum_double; | 948 | kc->info = snd_soc_info_enum_double; |
853 | kc->put = hdac_hdmi_set_pin_mux; | 949 | kc->put = hdac_hdmi_set_pin_port_mux; |
854 | kc->get = snd_soc_dapm_get_enum_double; | 950 | kc->get = snd_soc_dapm_get_enum_double; |
855 | 951 | ||
856 | se->reg = SND_SOC_NOPM; | 952 | se->reg = SND_SOC_NOPM; |
@@ -878,7 +974,9 @@ static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev, | |||
878 | return -ENOMEM; | 974 | return -ENOMEM; |
879 | 975 | ||
880 | return hdac_hdmi_fill_widget_info(&edev->hdac.dev, widget, | 976 | return hdac_hdmi_fill_widget_info(&edev->hdac.dev, widget, |
881 | snd_soc_dapm_mux, pin, widget_name, NULL, kc, 1); | 977 | snd_soc_dapm_mux, port, widget_name, NULL, kc, 1, |
978 | hdac_hdmi_pin_mux_widget_event, | ||
979 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_REG); | ||
882 | } | 980 | } |
883 | 981 | ||
884 | /* Add cvt <- input <- mux route map */ | 982 | /* Add cvt <- input <- mux route map */ |
@@ -889,10 +987,10 @@ static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev, | |||
889 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 987 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
890 | const struct snd_kcontrol_new *kc; | 988 | const struct snd_kcontrol_new *kc; |
891 | struct soc_enum *se; | 989 | struct soc_enum *se; |
892 | int mux_index = hdmi->num_cvt + hdmi->num_pin; | 990 | int mux_index = hdmi->num_cvt + hdmi->num_ports; |
893 | int i, j; | 991 | int i, j; |
894 | 992 | ||
895 | for (i = 0; i < hdmi->num_pin; i++) { | 993 | for (i = 0; i < hdmi->num_ports; i++) { |
896 | kc = widgets[mux_index].kcontrol_news; | 994 | kc = widgets[mux_index].kcontrol_news; |
897 | se = (struct soc_enum *)kc->private_value; | 995 | se = (struct soc_enum *)kc->private_value; |
898 | for (j = 0; j < hdmi->num_cvt; j++) { | 996 | for (j = 0; j < hdmi->num_cvt; j++) { |
@@ -911,17 +1009,18 @@ static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev, | |||
911 | /* | 1009 | /* |
912 | * Widgets are added in the below sequence | 1010 | * Widgets are added in the below sequence |
913 | * Converter widgets for num converters enumerated | 1011 | * Converter widgets for num converters enumerated |
914 | * Pin widgets for num pins enumerated | 1012 | * Pin-port widgets for num ports for Pins enumerated |
915 | * Pin mux widgets to represent connenction list of pin widget | 1013 | * Pin-port mux widgets to represent connenction list of pin widget |
916 | * | 1014 | * |
917 | * Total widgets elements = num_cvt + num_pin + num_pin; | 1015 | * For each port, one Mux and One output widget is added |
1016 | * Total widgets elements = num_cvt + (num_ports * 2); | ||
918 | * | 1017 | * |
919 | * Routes are added as below: | 1018 | * Routes are added as below: |
920 | * pin mux -> pin (based on num_pins) | 1019 | * pin-port mux -> pin (based on num_ports) |
921 | * cvt -> "Input sel control" -> pin_mux | 1020 | * cvt -> "Input sel control" -> pin-port_mux |
922 | * | 1021 | * |
923 | * Total route elements: | 1022 | * Total route elements: |
924 | * num_pins + (pin_muxes * num_cvt) | 1023 | * num_ports + (pin_muxes * num_cvt) |
925 | */ | 1024 | */ |
926 | static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) | 1025 | static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) |
927 | { | 1026 | { |
@@ -933,14 +1032,14 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) | |||
933 | char widget_name[NAME_SIZE]; | 1032 | char widget_name[NAME_SIZE]; |
934 | struct hdac_hdmi_cvt *cvt; | 1033 | struct hdac_hdmi_cvt *cvt; |
935 | struct hdac_hdmi_pin *pin; | 1034 | struct hdac_hdmi_pin *pin; |
936 | int ret, i = 0, num_routes = 0; | 1035 | int ret, i = 0, num_routes = 0, j; |
937 | 1036 | ||
938 | if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list)) | 1037 | if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list)) |
939 | return -EINVAL; | 1038 | return -EINVAL; |
940 | 1039 | ||
941 | widgets = devm_kzalloc(dapm->dev, | 1040 | widgets = devm_kzalloc(dapm->dev, (sizeof(*widgets) * |
942 | (sizeof(*widgets) * ((2 * hdmi->num_pin) + hdmi->num_cvt)), | 1041 | ((2 * hdmi->num_ports) + hdmi->num_cvt)), |
943 | GFP_KERNEL); | 1042 | GFP_KERNEL); |
944 | 1043 | ||
945 | if (!widgets) | 1044 | if (!widgets) |
946 | return -ENOMEM; | 1045 | return -ENOMEM; |
@@ -949,37 +1048,50 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) | |||
949 | list_for_each_entry(cvt, &hdmi->cvt_list, head) { | 1048 | list_for_each_entry(cvt, &hdmi->cvt_list, head) { |
950 | sprintf(widget_name, "Converter %d", cvt->nid); | 1049 | sprintf(widget_name, "Converter %d", cvt->nid); |
951 | ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i], | 1050 | ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i], |
952 | snd_soc_dapm_aif_in, &cvt->nid, | 1051 | snd_soc_dapm_aif_in, cvt, |
953 | widget_name, dai_drv[i].playback.stream_name, NULL, 0); | 1052 | widget_name, dai_drv[i].playback.stream_name, NULL, 0, |
1053 | hdac_hdmi_cvt_output_widget_event, | ||
1054 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); | ||
954 | if (ret < 0) | 1055 | if (ret < 0) |
955 | return ret; | 1056 | return ret; |
956 | i++; | 1057 | i++; |
957 | } | 1058 | } |
958 | 1059 | ||
959 | list_for_each_entry(pin, &hdmi->pin_list, head) { | 1060 | list_for_each_entry(pin, &hdmi->pin_list, head) { |
960 | sprintf(widget_name, "hif%d Output", pin->nid); | 1061 | for (j = 0; j < pin->num_ports; j++) { |
961 | ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i], | 1062 | sprintf(widget_name, "hif%d-%d Output", |
962 | snd_soc_dapm_output, &pin->nid, | 1063 | pin->nid, pin->ports[j].id); |
963 | widget_name, NULL, NULL, 0); | 1064 | ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i], |
964 | if (ret < 0) | 1065 | snd_soc_dapm_output, &pin->ports[j], |
965 | return ret; | 1066 | widget_name, NULL, NULL, 0, |
966 | i++; | 1067 | hdac_hdmi_pin_output_widget_event, |
1068 | SND_SOC_DAPM_PRE_PMU | | ||
1069 | SND_SOC_DAPM_POST_PMD); | ||
1070 | if (ret < 0) | ||
1071 | return ret; | ||
1072 | pin->ports[j].output_pin = widgets[i].name; | ||
1073 | i++; | ||
1074 | } | ||
967 | } | 1075 | } |
968 | 1076 | ||
969 | /* DAPM widgets to represent the connection list to pin widget */ | 1077 | /* DAPM widgets to represent the connection list to pin widget */ |
970 | list_for_each_entry(pin, &hdmi->pin_list, head) { | 1078 | list_for_each_entry(pin, &hdmi->pin_list, head) { |
971 | sprintf(widget_name, "Pin %d Mux", pin->nid); | 1079 | for (j = 0; j < pin->num_ports; j++) { |
972 | ret = hdac_hdmi_create_pin_muxs(edev, pin, &widgets[i], | 1080 | sprintf(widget_name, "Pin%d-Port%d Mux", |
973 | widget_name); | 1081 | pin->nid, pin->ports[j].id); |
974 | if (ret < 0) | 1082 | ret = hdac_hdmi_create_pin_port_muxs(edev, |
975 | return ret; | 1083 | &pin->ports[j], &widgets[i], |
976 | i++; | 1084 | widget_name); |
1085 | if (ret < 0) | ||
1086 | return ret; | ||
1087 | i++; | ||
977 | 1088 | ||
978 | /* For cvt to pin_mux mapping */ | 1089 | /* For cvt to pin_mux mapping */ |
979 | num_routes += hdmi->num_cvt; | 1090 | num_routes += hdmi->num_cvt; |
980 | 1091 | ||
981 | /* For pin_mux to pin mapping */ | 1092 | /* For pin_mux to pin mapping */ |
982 | num_routes++; | 1093 | num_routes++; |
1094 | } | ||
983 | } | 1095 | } |
984 | 1096 | ||
985 | route = devm_kzalloc(dapm->dev, (sizeof(*route) * num_routes), | 1097 | route = devm_kzalloc(dapm->dev, (sizeof(*route) * num_routes), |
@@ -990,20 +1102,22 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) | |||
990 | i = 0; | 1102 | i = 0; |
991 | /* Add pin <- NULL <- mux route map */ | 1103 | /* Add pin <- NULL <- mux route map */ |
992 | list_for_each_entry(pin, &hdmi->pin_list, head) { | 1104 | list_for_each_entry(pin, &hdmi->pin_list, head) { |
993 | int sink_index = i + hdmi->num_cvt; | 1105 | for (j = 0; j < pin->num_ports; j++) { |
994 | int src_index = sink_index + hdmi->num_pin; | 1106 | int sink_index = i + hdmi->num_cvt; |
1107 | int src_index = sink_index + pin->num_ports * | ||
1108 | hdmi->num_pin; | ||
995 | 1109 | ||
996 | hdac_hdmi_fill_route(&route[i], | 1110 | hdac_hdmi_fill_route(&route[i], |
997 | widgets[sink_index].name, NULL, | 1111 | widgets[sink_index].name, NULL, |
998 | widgets[src_index].name, NULL); | 1112 | widgets[src_index].name, NULL); |
999 | i++; | 1113 | i++; |
1000 | 1114 | } | |
1001 | } | 1115 | } |
1002 | 1116 | ||
1003 | hdac_hdmi_add_pinmux_cvt_route(edev, widgets, route, i); | 1117 | hdac_hdmi_add_pinmux_cvt_route(edev, widgets, route, i); |
1004 | 1118 | ||
1005 | snd_soc_dapm_new_controls(dapm, widgets, | 1119 | snd_soc_dapm_new_controls(dapm, widgets, |
1006 | ((2 * hdmi->num_pin) + hdmi->num_cvt)); | 1120 | ((2 * hdmi->num_ports) + hdmi->num_cvt)); |
1007 | 1121 | ||
1008 | snd_soc_dapm_add_routes(dapm, route, num_routes); | 1122 | snd_soc_dapm_add_routes(dapm, route, num_routes); |
1009 | snd_soc_dapm_new_widgets(dapm->card); | 1123 | snd_soc_dapm_new_widgets(dapm->card); |
@@ -1015,7 +1129,7 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) | |||
1015 | static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev) | 1129 | static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev) |
1016 | { | 1130 | { |
1017 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1131 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1018 | struct hdac_hdmi_dai_pin_map *dai_map; | 1132 | struct hdac_hdmi_dai_port_map *dai_map; |
1019 | struct hdac_hdmi_cvt *cvt; | 1133 | struct hdac_hdmi_cvt *cvt; |
1020 | int dai_id = 0; | 1134 | int dai_id = 0; |
1021 | 1135 | ||
@@ -1059,132 +1173,149 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid) | |||
1059 | return hdac_hdmi_query_cvt_params(&edev->hdac, cvt); | 1173 | return hdac_hdmi_query_cvt_params(&edev->hdac, cvt); |
1060 | } | 1174 | } |
1061 | 1175 | ||
1062 | static void hdac_hdmi_parse_eld(struct hdac_ext_device *edev, | 1176 | static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev, |
1063 | struct hdac_hdmi_pin *pin) | 1177 | struct hdac_hdmi_port *port) |
1064 | { | 1178 | { |
1065 | pin->eld.info.spk_alloc = pin->eld.eld_buffer[DRM_ELD_SPEAKER]; | 1179 | unsigned int ver, mnl; |
1180 | |||
1181 | ver = (port->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK) | ||
1182 | >> DRM_ELD_VER_SHIFT; | ||
1183 | |||
1184 | if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) { | ||
1185 | dev_err(&edev->hdac.dev, "HDMI: Unknown ELD version %d\n", ver); | ||
1186 | return -EINVAL; | ||
1187 | } | ||
1188 | |||
1189 | mnl = (port->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] & | ||
1190 | DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT; | ||
1191 | |||
1192 | if (mnl > ELD_MAX_MNL) { | ||
1193 | dev_err(&edev->hdac.dev, "HDMI: MNL Invalid %d\n", mnl); | ||
1194 | return -EINVAL; | ||
1195 | } | ||
1196 | |||
1197 | port->eld.info.spk_alloc = port->eld.eld_buffer[DRM_ELD_SPEAKER]; | ||
1198 | |||
1199 | return 0; | ||
1066 | } | 1200 | } |
1067 | 1201 | ||
1068 | static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll) | 1202 | static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, |
1203 | struct hdac_hdmi_port *port) | ||
1069 | { | 1204 | { |
1070 | struct hdac_ext_device *edev = pin->edev; | 1205 | struct hdac_ext_device *edev = pin->edev; |
1071 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1206 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1072 | struct hdac_hdmi_pcm *pcm; | 1207 | struct hdac_hdmi_pcm *pcm; |
1073 | int val; | 1208 | int size = 0; |
1209 | int port_id = -1; | ||
1074 | 1210 | ||
1075 | pin->repoll_count = repoll; | 1211 | if (!hdmi) |
1212 | return; | ||
1076 | 1213 | ||
1077 | pm_runtime_get_sync(&edev->hdac.dev); | 1214 | /* |
1078 | val = snd_hdac_codec_read(&edev->hdac, pin->nid, 0, | 1215 | * In case of non MST pin, get_eld info API expectes port |
1079 | AC_VERB_GET_PIN_SENSE, 0); | 1216 | * to be -1. |
1217 | */ | ||
1218 | mutex_lock(&hdmi->pin_mutex); | ||
1219 | port->eld.monitor_present = false; | ||
1080 | 1220 | ||
1081 | dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n", | 1221 | if (pin->mst_capable) |
1082 | val, pin->nid); | 1222 | port_id = port->id; |
1083 | 1223 | ||
1224 | size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, port_id, | ||
1225 | &port->eld.monitor_present, | ||
1226 | port->eld.eld_buffer, | ||
1227 | ELD_MAX_SIZE); | ||
1084 | 1228 | ||
1085 | mutex_lock(&hdmi->pin_mutex); | 1229 | if (size > 0) { |
1086 | pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE); | 1230 | size = min(size, ELD_MAX_SIZE); |
1087 | pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV); | 1231 | if (hdac_hdmi_parse_eld(edev, port) < 0) |
1232 | size = -EINVAL; | ||
1233 | } | ||
1088 | 1234 | ||
1089 | pcm = hdac_hdmi_get_pcm(edev, pin); | 1235 | if (size > 0) { |
1236 | port->eld.eld_valid = true; | ||
1237 | port->eld.eld_size = size; | ||
1238 | } else { | ||
1239 | port->eld.eld_valid = false; | ||
1240 | port->eld.eld_size = 0; | ||
1241 | } | ||
1090 | 1242 | ||
1091 | if (!pin->eld.monitor_present || !pin->eld.eld_valid) { | 1243 | pcm = hdac_hdmi_get_pcm(edev, port); |
1092 | 1244 | ||
1093 | dev_dbg(&edev->hdac.dev, "%s: disconnect for pin %d\n", | 1245 | if (!port->eld.monitor_present || !port->eld.eld_valid) { |
1094 | __func__, pin->nid); | 1246 | |
1247 | dev_err(&edev->hdac.dev, "%s: disconnect for pin:port %d:%d\n", | ||
1248 | __func__, pin->nid, port->id); | ||
1095 | 1249 | ||
1096 | /* | 1250 | /* |
1097 | * PCMs are not registered during device probe, so don't | 1251 | * PCMs are not registered during device probe, so don't |
1098 | * report jack here. It will be done in usermode mux | 1252 | * report jack here. It will be done in usermode mux |
1099 | * control select. | 1253 | * control select. |
1100 | */ | 1254 | */ |
1101 | if (pcm) { | 1255 | if (pcm) |
1102 | dev_dbg(&edev->hdac.dev, | 1256 | hdac_hdmi_jack_report(pcm, port, false); |
1103 | "jack report for pcm=%d\n", pcm->pcm_id); | ||
1104 | |||
1105 | snd_jack_report(pcm->jack, 0); | ||
1106 | } | ||
1107 | 1257 | ||
1108 | mutex_unlock(&hdmi->pin_mutex); | 1258 | mutex_unlock(&hdmi->pin_mutex); |
1109 | goto put_hdac_device; | 1259 | return; |
1110 | } | 1260 | } |
1111 | 1261 | ||
1112 | if (pin->eld.monitor_present && pin->eld.eld_valid) { | 1262 | if (port->eld.monitor_present && port->eld.eld_valid) { |
1113 | /* TODO: use i915 component for reading ELD later */ | 1263 | if (pcm) |
1114 | if (hdac_hdmi_get_eld(&edev->hdac, pin->nid, | 1264 | hdac_hdmi_jack_report(pcm, port, true); |
1115 | pin->eld.eld_buffer, | ||
1116 | &pin->eld.eld_size) == 0) { | ||
1117 | 1265 | ||
1118 | if (pcm) { | 1266 | print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1, |
1119 | dev_dbg(&edev->hdac.dev, | 1267 | port->eld.eld_buffer, port->eld.eld_size, false); |
1120 | "jack report for pcm=%d\n", | ||
1121 | pcm->pcm_id); | ||
1122 | |||
1123 | snd_jack_report(pcm->jack, SND_JACK_AVOUT); | ||
1124 | } | ||
1125 | hdac_hdmi_parse_eld(edev, pin); | ||
1126 | 1268 | ||
1127 | print_hex_dump_debug("ELD: ", | ||
1128 | DUMP_PREFIX_OFFSET, 16, 1, | ||
1129 | pin->eld.eld_buffer, pin->eld.eld_size, | ||
1130 | true); | ||
1131 | } else { | ||
1132 | pin->eld.monitor_present = false; | ||
1133 | pin->eld.eld_valid = false; | ||
1134 | |||
1135 | if (pcm) { | ||
1136 | dev_dbg(&edev->hdac.dev, | ||
1137 | "jack report for pcm=%d\n", | ||
1138 | pcm->pcm_id); | ||
1139 | |||
1140 | snd_jack_report(pcm->jack, 0); | ||
1141 | } | ||
1142 | } | ||
1143 | } | 1269 | } |
1144 | |||
1145 | mutex_unlock(&hdmi->pin_mutex); | 1270 | mutex_unlock(&hdmi->pin_mutex); |
1146 | |||
1147 | /* | ||
1148 | * Sometimes the pin_sense may present invalid monitor | ||
1149 | * present and eld_valid. If ELD data is not valid, loop few | ||
1150 | * more times to get correct pin sense and valid ELD. | ||
1151 | */ | ||
1152 | if ((!pin->eld.monitor_present || !pin->eld.eld_valid) && repoll) | ||
1153 | schedule_delayed_work(&pin->work, msecs_to_jiffies(300)); | ||
1154 | |||
1155 | put_hdac_device: | ||
1156 | pm_runtime_put_sync(&edev->hdac.dev); | ||
1157 | } | 1271 | } |
1158 | 1272 | ||
1159 | static void hdac_hdmi_repoll_eld(struct work_struct *work) | 1273 | static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi, |
1274 | struct hdac_hdmi_pin *pin) | ||
1160 | { | 1275 | { |
1161 | struct hdac_hdmi_pin *pin = | 1276 | struct hdac_hdmi_port *ports; |
1162 | container_of(to_delayed_work(work), struct hdac_hdmi_pin, work); | 1277 | int max_ports = HDA_MAX_PORTS; |
1278 | int i; | ||
1279 | |||
1280 | /* | ||
1281 | * FIXME: max_port may vary for each platform, so pass this as | ||
1282 | * as driver data or query from i915 interface when this API is | ||
1283 | * implemented. | ||
1284 | */ | ||
1163 | 1285 | ||
1164 | /* picked from legacy HDA driver */ | 1286 | ports = kcalloc(max_ports, sizeof(*ports), GFP_KERNEL); |
1165 | if (pin->repoll_count++ > 6) | 1287 | if (!ports) |
1166 | pin->repoll_count = 0; | 1288 | return -ENOMEM; |
1167 | 1289 | ||
1168 | hdac_hdmi_present_sense(pin, pin->repoll_count); | 1290 | for (i = 0; i < max_ports; i++) { |
1291 | ports[i].id = i; | ||
1292 | ports[i].pin = pin; | ||
1293 | } | ||
1294 | pin->ports = ports; | ||
1295 | pin->num_ports = max_ports; | ||
1296 | return 0; | ||
1169 | } | 1297 | } |
1170 | 1298 | ||
1171 | static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) | 1299 | static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) |
1172 | { | 1300 | { |
1173 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1301 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1174 | struct hdac_hdmi_pin *pin; | 1302 | struct hdac_hdmi_pin *pin; |
1303 | int ret; | ||
1175 | 1304 | ||
1176 | pin = kzalloc(sizeof(*pin), GFP_KERNEL); | 1305 | pin = kzalloc(sizeof(*pin), GFP_KERNEL); |
1177 | if (!pin) | 1306 | if (!pin) |
1178 | return -ENOMEM; | 1307 | return -ENOMEM; |
1179 | 1308 | ||
1180 | pin->nid = nid; | 1309 | pin->nid = nid; |
1310 | pin->mst_capable = false; | ||
1311 | pin->edev = edev; | ||
1312 | ret = hdac_hdmi_add_ports(hdmi, pin); | ||
1313 | if (ret < 0) | ||
1314 | return ret; | ||
1181 | 1315 | ||
1182 | list_add_tail(&pin->head, &hdmi->pin_list); | 1316 | list_add_tail(&pin->head, &hdmi->pin_list); |
1183 | hdmi->num_pin++; | 1317 | hdmi->num_pin++; |
1184 | 1318 | hdmi->num_ports += pin->num_ports; | |
1185 | pin->edev = edev; | ||
1186 | mutex_init(&pin->lock); | ||
1187 | INIT_DELAYED_WORK(&pin->work, hdac_hdmi_repoll_eld); | ||
1188 | 1319 | ||
1189 | return 0; | 1320 | return 0; |
1190 | } | 1321 | } |
@@ -1233,9 +1364,7 @@ static struct snd_soc_dai_ops hdmi_dai_ops = { | |||
1233 | .startup = hdac_hdmi_pcm_open, | 1364 | .startup = hdac_hdmi_pcm_open, |
1234 | .shutdown = hdac_hdmi_pcm_close, | 1365 | .shutdown = hdac_hdmi_pcm_close, |
1235 | .hw_params = hdac_hdmi_set_hw_params, | 1366 | .hw_params = hdac_hdmi_set_hw_params, |
1236 | .prepare = hdac_hdmi_playback_prepare, | 1367 | .set_tdm_slot = hdac_hdmi_set_tdm_slot, |
1237 | .trigger = hdac_hdmi_trigger, | ||
1238 | .hw_free = hdac_hdmi_playback_cleanup, | ||
1239 | }; | 1368 | }; |
1240 | 1369 | ||
1241 | /* | 1370 | /* |
@@ -1372,13 +1501,16 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) | |||
1372 | { | 1501 | { |
1373 | struct hdac_ext_device *edev = aptr; | 1502 | struct hdac_ext_device *edev = aptr; |
1374 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1503 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1375 | struct hdac_hdmi_pin *pin; | 1504 | struct hdac_hdmi_pin *pin = NULL; |
1505 | struct hdac_hdmi_port *hport = NULL; | ||
1376 | struct snd_soc_codec *codec = edev->scodec; | 1506 | struct snd_soc_codec *codec = edev->scodec; |
1507 | int i; | ||
1377 | 1508 | ||
1378 | /* Don't know how this mapping is derived */ | 1509 | /* Don't know how this mapping is derived */ |
1379 | hda_nid_t pin_nid = port + 0x04; | 1510 | hda_nid_t pin_nid = port + 0x04; |
1380 | 1511 | ||
1381 | dev_dbg(&edev->hdac.dev, "%s: for pin: %d\n", __func__, pin_nid); | 1512 | dev_dbg(&edev->hdac.dev, "%s: for pin:%d port=%d\n", __func__, |
1513 | pin_nid, pipe); | ||
1382 | 1514 | ||
1383 | /* | 1515 | /* |
1384 | * skip notification during system suspend (but not in runtime PM); | 1516 | * skip notification during system suspend (but not in runtime PM); |
@@ -1394,9 +1526,29 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) | |||
1394 | return; | 1526 | return; |
1395 | 1527 | ||
1396 | list_for_each_entry(pin, &hdmi->pin_list, head) { | 1528 | list_for_each_entry(pin, &hdmi->pin_list, head) { |
1397 | if (pin->nid == pin_nid) | 1529 | if (pin->nid != pin_nid) |
1398 | hdac_hdmi_present_sense(pin, 1); | 1530 | continue; |
1531 | |||
1532 | /* In case of non MST pin, pipe is -1 */ | ||
1533 | if (pipe == -1) { | ||
1534 | pin->mst_capable = false; | ||
1535 | /* if not MST, default is port[0] */ | ||
1536 | hport = &pin->ports[0]; | ||
1537 | goto out; | ||
1538 | } else { | ||
1539 | for (i = 0; i < pin->num_ports; i++) { | ||
1540 | pin->mst_capable = true; | ||
1541 | if (pin->ports[i].id == pipe) { | ||
1542 | hport = &pin->ports[i]; | ||
1543 | goto out; | ||
1544 | } | ||
1545 | } | ||
1546 | } | ||
1399 | } | 1547 | } |
1548 | |||
1549 | out: | ||
1550 | if (pin && hport) | ||
1551 | hdac_hdmi_present_sense(pin, hport); | ||
1400 | } | 1552 | } |
1401 | 1553 | ||
1402 | static struct i915_audio_component_audio_ops aops = { | 1554 | static struct i915_audio_component_audio_ops aops = { |
@@ -1416,13 +1568,130 @@ static struct snd_pcm *hdac_hdmi_get_pcm_from_id(struct snd_soc_card *card, | |||
1416 | return NULL; | 1568 | return NULL; |
1417 | } | 1569 | } |
1418 | 1570 | ||
1419 | int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device) | 1571 | /* create jack pin kcontrols */ |
1572 | static int create_fill_jack_kcontrols(struct snd_soc_card *card, | ||
1573 | struct hdac_ext_device *edev) | ||
1574 | { | ||
1575 | struct hdac_hdmi_pin *pin; | ||
1576 | struct snd_kcontrol_new *kc; | ||
1577 | char kc_name[NAME_SIZE], xname[NAME_SIZE]; | ||
1578 | char *name; | ||
1579 | int i = 0, j; | ||
1580 | struct snd_soc_codec *codec = edev->scodec; | ||
1581 | struct hdac_hdmi_priv *hdmi = edev->private_data; | ||
1582 | |||
1583 | kc = devm_kcalloc(codec->dev, hdmi->num_ports, | ||
1584 | sizeof(*kc), GFP_KERNEL); | ||
1585 | |||
1586 | if (!kc) | ||
1587 | return -ENOMEM; | ||
1588 | |||
1589 | list_for_each_entry(pin, &hdmi->pin_list, head) { | ||
1590 | for (j = 0; j < pin->num_ports; j++) { | ||
1591 | snprintf(xname, sizeof(xname), "hif%d-%d Jack", | ||
1592 | pin->nid, pin->ports[j].id); | ||
1593 | name = devm_kstrdup(codec->dev, xname, GFP_KERNEL); | ||
1594 | if (!name) | ||
1595 | return -ENOMEM; | ||
1596 | snprintf(kc_name, sizeof(kc_name), "%s Switch", xname); | ||
1597 | kc[i].name = devm_kstrdup(codec->dev, kc_name, | ||
1598 | GFP_KERNEL); | ||
1599 | if (!kc[i].name) | ||
1600 | return -ENOMEM; | ||
1601 | |||
1602 | kc[i].private_value = (unsigned long)name; | ||
1603 | kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
1604 | kc[i].access = 0; | ||
1605 | kc[i].info = snd_soc_dapm_info_pin_switch; | ||
1606 | kc[i].put = snd_soc_dapm_put_pin_switch; | ||
1607 | kc[i].get = snd_soc_dapm_get_pin_switch; | ||
1608 | i++; | ||
1609 | } | ||
1610 | } | ||
1611 | |||
1612 | return snd_soc_add_card_controls(card, kc, i); | ||
1613 | } | ||
1614 | |||
1615 | int hdac_hdmi_jack_port_init(struct snd_soc_codec *codec, | ||
1616 | struct snd_soc_dapm_context *dapm) | ||
1617 | { | ||
1618 | struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); | ||
1619 | struct hdac_hdmi_priv *hdmi = edev->private_data; | ||
1620 | struct hdac_hdmi_pin *pin; | ||
1621 | struct snd_soc_dapm_widget *widgets; | ||
1622 | struct snd_soc_dapm_route *route; | ||
1623 | char w_name[NAME_SIZE]; | ||
1624 | int i = 0, j, ret; | ||
1625 | |||
1626 | widgets = devm_kcalloc(dapm->dev, hdmi->num_ports, | ||
1627 | sizeof(*widgets), GFP_KERNEL); | ||
1628 | |||
1629 | if (!widgets) | ||
1630 | return -ENOMEM; | ||
1631 | |||
1632 | route = devm_kcalloc(dapm->dev, hdmi->num_ports, | ||
1633 | sizeof(*route), GFP_KERNEL); | ||
1634 | if (!route) | ||
1635 | return -ENOMEM; | ||
1636 | |||
1637 | /* create Jack DAPM widget */ | ||
1638 | list_for_each_entry(pin, &hdmi->pin_list, head) { | ||
1639 | for (j = 0; j < pin->num_ports; j++) { | ||
1640 | snprintf(w_name, sizeof(w_name), "hif%d-%d Jack", | ||
1641 | pin->nid, pin->ports[j].id); | ||
1642 | |||
1643 | ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i], | ||
1644 | snd_soc_dapm_spk, NULL, | ||
1645 | w_name, NULL, NULL, 0, NULL, 0); | ||
1646 | if (ret < 0) | ||
1647 | return ret; | ||
1648 | |||
1649 | pin->ports[j].jack_pin = widgets[i].name; | ||
1650 | pin->ports[j].dapm = dapm; | ||
1651 | |||
1652 | /* add to route from Jack widget to output */ | ||
1653 | hdac_hdmi_fill_route(&route[i], pin->ports[j].jack_pin, | ||
1654 | NULL, pin->ports[j].output_pin, NULL); | ||
1655 | |||
1656 | i++; | ||
1657 | } | ||
1658 | } | ||
1659 | |||
1660 | /* Add Route from Jack widget to the output widget */ | ||
1661 | ret = snd_soc_dapm_new_controls(dapm, widgets, hdmi->num_ports); | ||
1662 | if (ret < 0) | ||
1663 | return ret; | ||
1664 | |||
1665 | ret = snd_soc_dapm_add_routes(dapm, route, hdmi->num_ports); | ||
1666 | if (ret < 0) | ||
1667 | return ret; | ||
1668 | |||
1669 | ret = snd_soc_dapm_new_widgets(dapm->card); | ||
1670 | if (ret < 0) | ||
1671 | return ret; | ||
1672 | |||
1673 | /* Add Jack Pin switch Kcontrol */ | ||
1674 | ret = create_fill_jack_kcontrols(dapm->card, edev); | ||
1675 | |||
1676 | if (ret < 0) | ||
1677 | return ret; | ||
1678 | |||
1679 | /* default set the Jack Pin switch to OFF */ | ||
1680 | list_for_each_entry(pin, &hdmi->pin_list, head) { | ||
1681 | for (j = 0; j < pin->num_ports; j++) | ||
1682 | snd_soc_dapm_disable_pin(pin->ports[j].dapm, | ||
1683 | pin->ports[j].jack_pin); | ||
1684 | } | ||
1685 | |||
1686 | return 0; | ||
1687 | } | ||
1688 | EXPORT_SYMBOL_GPL(hdac_hdmi_jack_port_init); | ||
1689 | |||
1690 | int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, | ||
1691 | struct snd_soc_jack *jack) | ||
1420 | { | 1692 | { |
1421 | char jack_name[NAME_SIZE]; | ||
1422 | struct snd_soc_codec *codec = dai->codec; | 1693 | struct snd_soc_codec *codec = dai->codec; |
1423 | struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); | 1694 | struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); |
1424 | struct snd_soc_dapm_context *dapm = | ||
1425 | snd_soc_component_get_dapm(&codec->component); | ||
1426 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1695 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1427 | struct hdac_hdmi_pcm *pcm; | 1696 | struct hdac_hdmi_pcm *pcm; |
1428 | struct snd_pcm *snd_pcm; | 1697 | struct snd_pcm *snd_pcm; |
@@ -1437,7 +1706,10 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device) | |||
1437 | return -ENOMEM; | 1706 | return -ENOMEM; |
1438 | pcm->pcm_id = device; | 1707 | pcm->pcm_id = device; |
1439 | pcm->cvt = hdmi->dai_map[dai->id].cvt; | 1708 | pcm->cvt = hdmi->dai_map[dai->id].cvt; |
1440 | 1709 | pcm->jack_event = 0; | |
1710 | pcm->jack = jack; | ||
1711 | mutex_init(&pcm->lock); | ||
1712 | INIT_LIST_HEAD(&pcm->port_list); | ||
1441 | snd_pcm = hdac_hdmi_get_pcm_from_id(dai->component->card, device); | 1713 | snd_pcm = hdac_hdmi_get_pcm_from_id(dai->component->card, device); |
1442 | if (snd_pcm) { | 1714 | if (snd_pcm) { |
1443 | err = snd_hdac_add_chmap_ctls(snd_pcm, device, &hdmi->chmap); | 1715 | err = snd_hdac_add_chmap_ctls(snd_pcm, device, &hdmi->chmap); |
@@ -1452,20 +1724,40 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device) | |||
1452 | 1724 | ||
1453 | list_add_tail(&pcm->head, &hdmi->pcm_list); | 1725 | list_add_tail(&pcm->head, &hdmi->pcm_list); |
1454 | 1726 | ||
1455 | sprintf(jack_name, "HDMI/DP, pcm=%d Jack", device); | 1727 | return 0; |
1456 | |||
1457 | return snd_jack_new(dapm->card->snd_card, jack_name, | ||
1458 | SND_JACK_AVOUT, &pcm->jack, true, false); | ||
1459 | } | 1728 | } |
1460 | EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init); | 1729 | EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init); |
1461 | 1730 | ||
1731 | static void hdac_hdmi_present_sense_all_pins(struct hdac_ext_device *edev, | ||
1732 | struct hdac_hdmi_priv *hdmi, bool detect_pin_caps) | ||
1733 | { | ||
1734 | int i; | ||
1735 | struct hdac_hdmi_pin *pin; | ||
1736 | |||
1737 | list_for_each_entry(pin, &hdmi->pin_list, head) { | ||
1738 | if (detect_pin_caps) { | ||
1739 | |||
1740 | if (hdac_hdmi_get_port_len(edev, pin->nid) == 0) | ||
1741 | pin->mst_capable = false; | ||
1742 | else | ||
1743 | pin->mst_capable = true; | ||
1744 | } | ||
1745 | |||
1746 | for (i = 0; i < pin->num_ports; i++) { | ||
1747 | if (!pin->mst_capable && i > 0) | ||
1748 | continue; | ||
1749 | |||
1750 | hdac_hdmi_present_sense(pin, &pin->ports[i]); | ||
1751 | } | ||
1752 | } | ||
1753 | } | ||
1754 | |||
1462 | static int hdmi_codec_probe(struct snd_soc_codec *codec) | 1755 | static int hdmi_codec_probe(struct snd_soc_codec *codec) |
1463 | { | 1756 | { |
1464 | struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); | 1757 | struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); |
1465 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1758 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1466 | struct snd_soc_dapm_context *dapm = | 1759 | struct snd_soc_dapm_context *dapm = |
1467 | snd_soc_component_get_dapm(&codec->component); | 1760 | snd_soc_component_get_dapm(&codec->component); |
1468 | struct hdac_hdmi_pin *pin; | ||
1469 | struct hdac_ext_link *hlink = NULL; | 1761 | struct hdac_ext_link *hlink = NULL; |
1470 | int ret; | 1762 | int ret; |
1471 | 1763 | ||
@@ -1495,9 +1787,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec) | |||
1495 | return ret; | 1787 | return ret; |
1496 | } | 1788 | } |
1497 | 1789 | ||
1498 | list_for_each_entry(pin, &hdmi->pin_list, head) | 1790 | hdac_hdmi_present_sense_all_pins(edev, hdmi, true); |
1499 | hdac_hdmi_present_sense(pin, 1); | ||
1500 | |||
1501 | /* Imp: Store the card pointer in hda_codec */ | 1791 | /* Imp: Store the card pointer in hda_codec */ |
1502 | edev->card = dapm->card->snd_card; | 1792 | edev->card = dapm->card->snd_card; |
1503 | 1793 | ||
@@ -1545,7 +1835,6 @@ static void hdmi_codec_complete(struct device *dev) | |||
1545 | { | 1835 | { |
1546 | struct hdac_ext_device *edev = to_hda_ext_device(dev); | 1836 | struct hdac_ext_device *edev = to_hda_ext_device(dev); |
1547 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1837 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1548 | struct hdac_hdmi_pin *pin; | ||
1549 | struct hdac_device *hdac = &edev->hdac; | 1838 | struct hdac_device *hdac = &edev->hdac; |
1550 | 1839 | ||
1551 | /* Power up afg */ | 1840 | /* Power up afg */ |
@@ -1558,10 +1847,10 @@ static void hdmi_codec_complete(struct device *dev) | |||
1558 | /* | 1847 | /* |
1559 | * As the ELD notify callback request is not entertained while the | 1848 | * As the ELD notify callback request is not entertained while the |
1560 | * device is in suspend state. Need to manually check detection of | 1849 | * device is in suspend state. Need to manually check detection of |
1561 | * all pins here. | 1850 | * all pins here. pin capablity change is not support, so use the |
1851 | * already set pin caps. | ||
1562 | */ | 1852 | */ |
1563 | list_for_each_entry(pin, &hdmi->pin_list, head) | 1853 | hdac_hdmi_present_sense_all_pins(edev, hdmi, false); |
1564 | hdac_hdmi_present_sense(pin, 1); | ||
1565 | 1854 | ||
1566 | pm_runtime_put_sync(&edev->hdac.dev); | 1855 | pm_runtime_put_sync(&edev->hdac.dev); |
1567 | } | 1856 | } |
@@ -1582,13 +1871,8 @@ static void hdac_hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx, | |||
1582 | struct hdac_ext_device *edev = to_ehdac_device(hdac); | 1871 | struct hdac_ext_device *edev = to_ehdac_device(hdac); |
1583 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1872 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1584 | struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); | 1873 | struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); |
1585 | struct hdac_hdmi_pin *pin = pcm->pin; | ||
1586 | |||
1587 | /* chmap is already set to 0 in caller */ | ||
1588 | if (!pin) | ||
1589 | return; | ||
1590 | 1874 | ||
1591 | memcpy(chmap, pin->chmap, ARRAY_SIZE(pin->chmap)); | 1875 | memcpy(chmap, pcm->chmap, ARRAY_SIZE(pcm->chmap)); |
1592 | } | 1876 | } |
1593 | 1877 | ||
1594 | static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, | 1878 | static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, |
@@ -1597,14 +1881,18 @@ static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, | |||
1597 | struct hdac_ext_device *edev = to_ehdac_device(hdac); | 1881 | struct hdac_ext_device *edev = to_ehdac_device(hdac); |
1598 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1882 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1599 | struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); | 1883 | struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); |
1600 | struct hdac_hdmi_pin *pin = pcm->pin; | 1884 | struct hdac_hdmi_port *port; |
1601 | 1885 | ||
1602 | mutex_lock(&pin->lock); | 1886 | if (list_empty(&pcm->port_list)) |
1603 | pin->chmap_set = true; | 1887 | return; |
1604 | memcpy(pin->chmap, chmap, ARRAY_SIZE(pin->chmap)); | 1888 | |
1605 | if (prepared) | 1889 | mutex_lock(&pcm->lock); |
1606 | hdac_hdmi_setup_audio_infoframe(edev, pcm->cvt->nid, pin->nid); | 1890 | pcm->chmap_set = true; |
1607 | mutex_unlock(&pin->lock); | 1891 | memcpy(pcm->chmap, chmap, ARRAY_SIZE(pcm->chmap)); |
1892 | list_for_each_entry(port, &pcm->port_list, head) | ||
1893 | if (prepared) | ||
1894 | hdac_hdmi_setup_audio_infoframe(edev, pcm, port); | ||
1895 | mutex_unlock(&pcm->lock); | ||
1608 | } | 1896 | } |
1609 | 1897 | ||
1610 | static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx) | 1898 | static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx) |
@@ -1612,9 +1900,11 @@ static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx) | |||
1612 | struct hdac_ext_device *edev = to_ehdac_device(hdac); | 1900 | struct hdac_ext_device *edev = to_ehdac_device(hdac); |
1613 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1901 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1614 | struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); | 1902 | struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); |
1615 | struct hdac_hdmi_pin *pin = pcm->pin; | ||
1616 | 1903 | ||
1617 | return pin ? true:false; | 1904 | if (list_empty(&pcm->port_list)) |
1905 | return false; | ||
1906 | |||
1907 | return true; | ||
1618 | } | 1908 | } |
1619 | 1909 | ||
1620 | static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) | 1910 | static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) |
@@ -1622,12 +1912,20 @@ static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) | |||
1622 | struct hdac_ext_device *edev = to_ehdac_device(hdac); | 1912 | struct hdac_ext_device *edev = to_ehdac_device(hdac); |
1623 | struct hdac_hdmi_priv *hdmi = edev->private_data; | 1913 | struct hdac_hdmi_priv *hdmi = edev->private_data; |
1624 | struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); | 1914 | struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); |
1625 | struct hdac_hdmi_pin *pin = pcm->pin; | 1915 | struct hdac_hdmi_port *port; |
1626 | 1916 | ||
1627 | if (!pin || !pin->eld.eld_valid) | 1917 | if (list_empty(&pcm->port_list)) |
1628 | return 0; | 1918 | return 0; |
1629 | 1919 | ||
1630 | return pin->eld.info.spk_alloc; | 1920 | port = list_first_entry(&pcm->port_list, struct hdac_hdmi_port, head); |
1921 | |||
1922 | if (!port) | ||
1923 | return 0; | ||
1924 | |||
1925 | if (!port || !port->eld.eld_valid) | ||
1926 | return 0; | ||
1927 | |||
1928 | return port->eld.info.spk_alloc; | ||
1631 | } | 1929 | } |
1632 | 1930 | ||
1633 | static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) | 1931 | static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) |
@@ -1700,12 +1998,19 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) | |||
1700 | struct hdac_hdmi_pin *pin, *pin_next; | 1998 | struct hdac_hdmi_pin *pin, *pin_next; |
1701 | struct hdac_hdmi_cvt *cvt, *cvt_next; | 1999 | struct hdac_hdmi_cvt *cvt, *cvt_next; |
1702 | struct hdac_hdmi_pcm *pcm, *pcm_next; | 2000 | struct hdac_hdmi_pcm *pcm, *pcm_next; |
2001 | struct hdac_hdmi_port *port; | ||
2002 | int i; | ||
1703 | 2003 | ||
1704 | snd_soc_unregister_codec(&edev->hdac.dev); | 2004 | snd_soc_unregister_codec(&edev->hdac.dev); |
1705 | 2005 | ||
1706 | list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) { | 2006 | list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) { |
1707 | pcm->cvt = NULL; | 2007 | pcm->cvt = NULL; |
1708 | pcm->pin = NULL; | 2008 | if (list_empty(&pcm->port_list)) |
2009 | continue; | ||
2010 | |||
2011 | list_for_each_entry(port, &pcm->port_list, head) | ||
2012 | port = NULL; | ||
2013 | |||
1709 | list_del(&pcm->head); | 2014 | list_del(&pcm->head); |
1710 | kfree(pcm); | 2015 | kfree(pcm); |
1711 | } | 2016 | } |
@@ -1717,6 +2022,9 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) | |||
1717 | } | 2022 | } |
1718 | 2023 | ||
1719 | list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) { | 2024 | list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) { |
2025 | for (i = 0; i < pin->num_ports; i++) | ||
2026 | pin->ports[i].pin = NULL; | ||
2027 | kfree(pin->ports); | ||
1720 | list_del(&pin->head); | 2028 | list_del(&pin->head); |
1721 | kfree(pin); | 2029 | kfree(pin); |
1722 | } | 2030 | } |
@@ -1819,6 +2127,7 @@ static const struct hda_device_id hdmi_list[] = { | |||
1819 | HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0), | 2127 | HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0), |
1820 | HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0), | 2128 | HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0), |
1821 | HDA_CODEC_EXT_ENTRY(0x8086280b, 0x100000, "Kabylake HDMI", 0), | 2129 | HDA_CODEC_EXT_ENTRY(0x8086280b, 0x100000, "Kabylake HDMI", 0), |
2130 | HDA_CODEC_EXT_ENTRY(0x8086280d, 0x100000, "Geminilake HDMI", 0), | ||
1822 | {} | 2131 | {} |
1823 | }; | 2132 | }; |
1824 | 2133 | ||
diff --git a/sound/soc/codecs/hdac_hdmi.h b/sound/soc/codecs/hdac_hdmi.h index 8dfd1e0b57b3..dfc3a9cf7199 100644 --- a/sound/soc/codecs/hdac_hdmi.h +++ b/sound/soc/codecs/hdac_hdmi.h | |||
@@ -1,6 +1,9 @@ | |||
1 | #ifndef __HDAC_HDMI_H__ | 1 | #ifndef __HDAC_HDMI_H__ |
2 | #define __HDAC_HDMI_H__ | 2 | #define __HDAC_HDMI_H__ |
3 | 3 | ||
4 | int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm); | 4 | int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm, |
5 | struct snd_soc_jack *jack); | ||
5 | 6 | ||
7 | int hdac_hdmi_jack_port_init(struct snd_soc_codec *codec, | ||
8 | struct snd_soc_dapm_context *dapm); | ||
6 | #endif /* __HDAC_HDMI_H__ */ | 9 | #endif /* __HDAC_HDMI_H__ */ |
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 90b5948e0ff3..8c5ae1fc23a9 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <sound/pcm.h> | 18 | #include <sound/pcm.h> |
19 | #include <sound/pcm_params.h> | 19 | #include <sound/pcm_params.h> |
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | #include <sound/tlv.h> | ||
21 | #include <sound/pcm_drm_eld.h> | 22 | #include <sound/pcm_drm_eld.h> |
22 | #include <sound/hdmi-codec.h> | 23 | #include <sound/hdmi-codec.h> |
23 | #include <sound/pcm_iec958.h> | 24 | #include <sound/pcm_iec958.h> |
@@ -31,8 +32,261 @@ struct hdmi_device { | |||
31 | }; | 32 | }; |
32 | #define pos_to_hdmi_device(pos) container_of((pos), struct hdmi_device, list) | 33 | #define pos_to_hdmi_device(pos) container_of((pos), struct hdmi_device, list) |
33 | LIST_HEAD(hdmi_device_list); | 34 | LIST_HEAD(hdmi_device_list); |
35 | static DEFINE_MUTEX(hdmi_mutex); | ||
34 | 36 | ||
35 | #define DAI_NAME_SIZE 16 | 37 | #define DAI_NAME_SIZE 16 |
38 | |||
39 | #define HDMI_CODEC_CHMAP_IDX_UNKNOWN -1 | ||
40 | |||
41 | struct hdmi_codec_channel_map_table { | ||
42 | unsigned char map; /* ALSA API channel map position */ | ||
43 | unsigned long spk_mask; /* speaker position bit mask */ | ||
44 | }; | ||
45 | |||
46 | /* | ||
47 | * CEA speaker placement for HDMI 1.4: | ||
48 | * | ||
49 | * FL FLC FC FRC FR FRW | ||
50 | * | ||
51 | * LFE | ||
52 | * | ||
53 | * RL RLC RC RRC RR | ||
54 | * | ||
55 | * Speaker placement has to be extended to support HDMI 2.0 | ||
56 | */ | ||
57 | enum hdmi_codec_cea_spk_placement { | ||
58 | FL = BIT(0), /* Front Left */ | ||
59 | FC = BIT(1), /* Front Center */ | ||
60 | FR = BIT(2), /* Front Right */ | ||
61 | FLC = BIT(3), /* Front Left Center */ | ||
62 | FRC = BIT(4), /* Front Right Center */ | ||
63 | RL = BIT(5), /* Rear Left */ | ||
64 | RC = BIT(6), /* Rear Center */ | ||
65 | RR = BIT(7), /* Rear Right */ | ||
66 | RLC = BIT(8), /* Rear Left Center */ | ||
67 | RRC = BIT(9), /* Rear Right Center */ | ||
68 | LFE = BIT(10), /* Low Frequency Effect */ | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * cea Speaker allocation structure | ||
73 | */ | ||
74 | struct hdmi_codec_cea_spk_alloc { | ||
75 | const int ca_id; | ||
76 | unsigned int n_ch; | ||
77 | unsigned long mask; | ||
78 | }; | ||
79 | |||
80 | /* Channel maps stereo HDMI */ | ||
81 | const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = { | ||
82 | { .channels = 2, | ||
83 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, | ||
84 | { } | ||
85 | }; | ||
86 | |||
87 | /* Channel maps for multi-channel playbacks, up to 8 n_ch */ | ||
88 | const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = { | ||
89 | { .channels = 2, /* CA_ID 0x00 */ | ||
90 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, | ||
91 | { .channels = 4, /* CA_ID 0x01 */ | ||
92 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
93 | SNDRV_CHMAP_NA } }, | ||
94 | { .channels = 4, /* CA_ID 0x02 */ | ||
95 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
96 | SNDRV_CHMAP_FC } }, | ||
97 | { .channels = 4, /* CA_ID 0x03 */ | ||
98 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
99 | SNDRV_CHMAP_FC } }, | ||
100 | { .channels = 6, /* CA_ID 0x04 */ | ||
101 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
102 | SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, | ||
103 | { .channels = 6, /* CA_ID 0x05 */ | ||
104 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
105 | SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, | ||
106 | { .channels = 6, /* CA_ID 0x06 */ | ||
107 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
108 | SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, | ||
109 | { .channels = 6, /* CA_ID 0x07 */ | ||
110 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
111 | SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, | ||
112 | { .channels = 6, /* CA_ID 0x08 */ | ||
113 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
114 | SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
115 | { .channels = 6, /* CA_ID 0x09 */ | ||
116 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
117 | SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
118 | { .channels = 6, /* CA_ID 0x0A */ | ||
119 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
120 | SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
121 | { .channels = 6, /* CA_ID 0x0B */ | ||
122 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
123 | SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
124 | { .channels = 8, /* CA_ID 0x0C */ | ||
125 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
126 | SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
127 | SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, | ||
128 | { .channels = 8, /* CA_ID 0x0D */ | ||
129 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
130 | SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
131 | SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, | ||
132 | { .channels = 8, /* CA_ID 0x0E */ | ||
133 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
134 | SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
135 | SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, | ||
136 | { .channels = 8, /* CA_ID 0x0F */ | ||
137 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
138 | SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
139 | SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, | ||
140 | { .channels = 8, /* CA_ID 0x10 */ | ||
141 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
142 | SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
143 | SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, | ||
144 | { .channels = 8, /* CA_ID 0x11 */ | ||
145 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
146 | SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
147 | SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, | ||
148 | { .channels = 8, /* CA_ID 0x12 */ | ||
149 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
150 | SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
151 | SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, | ||
152 | { .channels = 8, /* CA_ID 0x13 */ | ||
153 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
154 | SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
155 | SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, | ||
156 | { .channels = 8, /* CA_ID 0x14 */ | ||
157 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
158 | SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
159 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
160 | { .channels = 8, /* CA_ID 0x15 */ | ||
161 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
162 | SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
163 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
164 | { .channels = 8, /* CA_ID 0x16 */ | ||
165 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
166 | SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
167 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
168 | { .channels = 8, /* CA_ID 0x17 */ | ||
169 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
170 | SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
171 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
172 | { .channels = 8, /* CA_ID 0x18 */ | ||
173 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
174 | SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
175 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
176 | { .channels = 8, /* CA_ID 0x19 */ | ||
177 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
178 | SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
179 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
180 | { .channels = 8, /* CA_ID 0x1A */ | ||
181 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
182 | SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
183 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
184 | { .channels = 8, /* CA_ID 0x1B */ | ||
185 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
186 | SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
187 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
188 | { .channels = 8, /* CA_ID 0x1C */ | ||
189 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
190 | SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
191 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
192 | { .channels = 8, /* CA_ID 0x1D */ | ||
193 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
194 | SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
195 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
196 | { .channels = 8, /* CA_ID 0x1E */ | ||
197 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, | ||
198 | SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
199 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
200 | { .channels = 8, /* CA_ID 0x1F */ | ||
201 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, | ||
202 | SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, | ||
203 | SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, | ||
204 | { } | ||
205 | }; | ||
206 | |||
207 | /* | ||
208 | * hdmi_codec_channel_alloc: speaker configuration available for CEA | ||
209 | * | ||
210 | * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct | ||
211 | * The preceding ones have better chances to be selected by | ||
212 | * hdmi_codec_get_ch_alloc_table_idx(). | ||
213 | */ | ||
214 | static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { | ||
215 | { .ca_id = 0x00, .n_ch = 2, | ||
216 | .mask = FL | FR}, | ||
217 | /* 2.1 */ | ||
218 | { .ca_id = 0x01, .n_ch = 4, | ||
219 | .mask = FL | FR | LFE}, | ||
220 | /* Dolby Surround */ | ||
221 | { .ca_id = 0x02, .n_ch = 4, | ||
222 | .mask = FL | FR | FC }, | ||
223 | /* surround51 */ | ||
224 | { .ca_id = 0x0b, .n_ch = 6, | ||
225 | .mask = FL | FR | LFE | FC | RL | RR}, | ||
226 | /* surround40 */ | ||
227 | { .ca_id = 0x08, .n_ch = 6, | ||
228 | .mask = FL | FR | RL | RR }, | ||
229 | /* surround41 */ | ||
230 | { .ca_id = 0x09, .n_ch = 6, | ||
231 | .mask = FL | FR | LFE | RL | RR }, | ||
232 | /* surround50 */ | ||
233 | { .ca_id = 0x0a, .n_ch = 6, | ||
234 | .mask = FL | FR | FC | RL | RR }, | ||
235 | /* 6.1 */ | ||
236 | { .ca_id = 0x0f, .n_ch = 8, | ||
237 | .mask = FL | FR | LFE | FC | RL | RR | RC }, | ||
238 | /* surround71 */ | ||
239 | { .ca_id = 0x13, .n_ch = 8, | ||
240 | .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC }, | ||
241 | /* others */ | ||
242 | { .ca_id = 0x03, .n_ch = 8, | ||
243 | .mask = FL | FR | LFE | FC }, | ||
244 | { .ca_id = 0x04, .n_ch = 8, | ||
245 | .mask = FL | FR | RC}, | ||
246 | { .ca_id = 0x05, .n_ch = 8, | ||
247 | .mask = FL | FR | LFE | RC }, | ||
248 | { .ca_id = 0x06, .n_ch = 8, | ||
249 | .mask = FL | FR | FC | RC }, | ||
250 | { .ca_id = 0x07, .n_ch = 8, | ||
251 | .mask = FL | FR | LFE | FC | RC }, | ||
252 | { .ca_id = 0x0c, .n_ch = 8, | ||
253 | .mask = FL | FR | RC | RL | RR }, | ||
254 | { .ca_id = 0x0d, .n_ch = 8, | ||
255 | .mask = FL | FR | LFE | RL | RR | RC }, | ||
256 | { .ca_id = 0x0e, .n_ch = 8, | ||
257 | .mask = FL | FR | FC | RL | RR | RC }, | ||
258 | { .ca_id = 0x10, .n_ch = 8, | ||
259 | .mask = FL | FR | RL | RR | RLC | RRC }, | ||
260 | { .ca_id = 0x11, .n_ch = 8, | ||
261 | .mask = FL | FR | LFE | RL | RR | RLC | RRC }, | ||
262 | { .ca_id = 0x12, .n_ch = 8, | ||
263 | .mask = FL | FR | FC | RL | RR | RLC | RRC }, | ||
264 | { .ca_id = 0x14, .n_ch = 8, | ||
265 | .mask = FL | FR | FLC | FRC }, | ||
266 | { .ca_id = 0x15, .n_ch = 8, | ||
267 | .mask = FL | FR | LFE | FLC | FRC }, | ||
268 | { .ca_id = 0x16, .n_ch = 8, | ||
269 | .mask = FL | FR | FC | FLC | FRC }, | ||
270 | { .ca_id = 0x17, .n_ch = 8, | ||
271 | .mask = FL | FR | LFE | FC | FLC | FRC }, | ||
272 | { .ca_id = 0x18, .n_ch = 8, | ||
273 | .mask = FL | FR | RC | FLC | FRC }, | ||
274 | { .ca_id = 0x19, .n_ch = 8, | ||
275 | .mask = FL | FR | LFE | RC | FLC | FRC }, | ||
276 | { .ca_id = 0x1a, .n_ch = 8, | ||
277 | .mask = FL | FR | RC | FC | FLC | FRC }, | ||
278 | { .ca_id = 0x1b, .n_ch = 8, | ||
279 | .mask = FL | FR | LFE | RC | FC | FLC | FRC }, | ||
280 | { .ca_id = 0x1c, .n_ch = 8, | ||
281 | .mask = FL | FR | RL | RR | FLC | FRC }, | ||
282 | { .ca_id = 0x1d, .n_ch = 8, | ||
283 | .mask = FL | FR | LFE | RL | RR | FLC | FRC }, | ||
284 | { .ca_id = 0x1e, .n_ch = 8, | ||
285 | .mask = FL | FR | FC | RL | RR | FLC | FRC }, | ||
286 | { .ca_id = 0x1f, .n_ch = 8, | ||
287 | .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, | ||
288 | }; | ||
289 | |||
36 | struct hdmi_codec_priv { | 290 | struct hdmi_codec_priv { |
37 | struct hdmi_codec_pdata hcd; | 291 | struct hdmi_codec_pdata hcd; |
38 | struct snd_soc_dai_driver *daidrv; | 292 | struct snd_soc_dai_driver *daidrv; |
@@ -41,6 +295,8 @@ struct hdmi_codec_priv { | |||
41 | struct snd_pcm_substream *current_stream; | 295 | struct snd_pcm_substream *current_stream; |
42 | struct snd_pcm_hw_constraint_list ratec; | 296 | struct snd_pcm_hw_constraint_list ratec; |
43 | uint8_t eld[MAX_ELD_BYTES]; | 297 | uint8_t eld[MAX_ELD_BYTES]; |
298 | struct snd_pcm_chmap *chmap_info; | ||
299 | unsigned int chmap_idx; | ||
44 | }; | 300 | }; |
45 | 301 | ||
46 | static const struct snd_soc_dapm_widget hdmi_widgets[] = { | 302 | static const struct snd_soc_dapm_widget hdmi_widgets[] = { |
@@ -79,6 +335,83 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, | |||
79 | return 0; | 335 | return 0; |
80 | } | 336 | } |
81 | 337 | ||
338 | static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc) | ||
339 | { | ||
340 | int i; | ||
341 | const unsigned long hdmi_codec_eld_spk_alloc_bits[] = { | ||
342 | [0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR, | ||
343 | [4] = RC, [5] = FLC | FRC, [6] = RLC | RRC, | ||
344 | }; | ||
345 | unsigned long spk_mask = 0; | ||
346 | |||
347 | for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) { | ||
348 | if (spk_alloc & (1 << i)) | ||
349 | spk_mask |= hdmi_codec_eld_spk_alloc_bits[i]; | ||
350 | } | ||
351 | |||
352 | return spk_mask; | ||
353 | } | ||
354 | |||
355 | void hdmi_codec_eld_chmap(struct hdmi_codec_priv *hcp) | ||
356 | { | ||
357 | u8 spk_alloc; | ||
358 | unsigned long spk_mask; | ||
359 | |||
360 | spk_alloc = drm_eld_get_spk_alloc(hcp->eld); | ||
361 | spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc); | ||
362 | |||
363 | /* Detect if only stereo supported, else return 8 channels mappings */ | ||
364 | if ((spk_mask & ~(FL | FR)) && hcp->chmap_info->max_channels > 2) | ||
365 | hcp->chmap_info->chmap = hdmi_codec_8ch_chmaps; | ||
366 | else | ||
367 | hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps; | ||
368 | } | ||
369 | |||
370 | static int hdmi_codec_get_ch_alloc_table_idx(struct hdmi_codec_priv *hcp, | ||
371 | unsigned char channels) | ||
372 | { | ||
373 | int i; | ||
374 | u8 spk_alloc; | ||
375 | unsigned long spk_mask; | ||
376 | const struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc; | ||
377 | |||
378 | spk_alloc = drm_eld_get_spk_alloc(hcp->eld); | ||
379 | spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc); | ||
380 | |||
381 | for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) { | ||
382 | /* If spk_alloc == 0, HDMI is unplugged return stereo config*/ | ||
383 | if (!spk_alloc && cap->ca_id == 0) | ||
384 | return i; | ||
385 | if (cap->n_ch != channels) | ||
386 | continue; | ||
387 | if (!(cap->mask == (spk_mask & cap->mask))) | ||
388 | continue; | ||
389 | return i; | ||
390 | } | ||
391 | |||
392 | return -EINVAL; | ||
393 | } | ||
394 | static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol, | ||
395 | struct snd_ctl_elem_value *ucontrol) | ||
396 | { | ||
397 | unsigned const char *map; | ||
398 | unsigned int i; | ||
399 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
400 | struct hdmi_codec_priv *hcp = info->private_data; | ||
401 | |||
402 | map = info->chmap[hcp->chmap_idx].map; | ||
403 | |||
404 | for (i = 0; i < info->max_channels; i++) { | ||
405 | if (hcp->chmap_idx == HDMI_CODEC_CHMAP_IDX_UNKNOWN) | ||
406 | ucontrol->value.integer.value[i] = 0; | ||
407 | else | ||
408 | ucontrol->value.integer.value[i] = map[i]; | ||
409 | } | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | |||
82 | static const struct snd_kcontrol_new hdmi_controls[] = { | 415 | static const struct snd_kcontrol_new hdmi_controls[] = { |
83 | { | 416 | { |
84 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | 417 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
@@ -140,6 +473,8 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, | |||
140 | if (ret) | 473 | if (ret) |
141 | return ret; | 474 | return ret; |
142 | } | 475 | } |
476 | /* Select chmap supported */ | ||
477 | hdmi_codec_eld_chmap(hcp); | ||
143 | } | 478 | } |
144 | return 0; | 479 | return 0; |
145 | } | 480 | } |
@@ -153,6 +488,7 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, | |||
153 | 488 | ||
154 | WARN_ON(hcp->current_stream != substream); | 489 | WARN_ON(hcp->current_stream != substream); |
155 | 490 | ||
491 | hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; | ||
156 | hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data); | 492 | hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data); |
157 | 493 | ||
158 | mutex_lock(&hcp->current_stream_lock); | 494 | mutex_lock(&hcp->current_stream_lock); |
@@ -173,7 +509,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, | |||
173 | .dig_subframe = { 0 }, | 509 | .dig_subframe = { 0 }, |
174 | } | 510 | } |
175 | }; | 511 | }; |
176 | int ret; | 512 | int ret, idx; |
177 | 513 | ||
178 | dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__, | 514 | dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__, |
179 | params_width(params), params_rate(params), | 515 | params_width(params), params_rate(params), |
@@ -200,6 +536,17 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, | |||
200 | hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; | 536 | hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; |
201 | hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; | 537 | hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; |
202 | 538 | ||
539 | /* Select a channel allocation that matches with ELD and pcm channels */ | ||
540 | idx = hdmi_codec_get_ch_alloc_table_idx(hcp, hp.cea.channels); | ||
541 | if (idx < 0) { | ||
542 | dev_err(dai->dev, "Not able to map channels to speakers (%d)\n", | ||
543 | idx); | ||
544 | hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; | ||
545 | return idx; | ||
546 | } | ||
547 | hp.cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id; | ||
548 | hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id; | ||
549 | |||
203 | hp.sample_width = params_width(params); | 550 | hp.sample_width = params_width(params); |
204 | hp.sample_rate = params_rate(params); | 551 | hp.sample_rate = params_rate(params); |
205 | hp.channels = params_channels(params); | 552 | hp.channels = params_channels(params); |
@@ -328,6 +675,32 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = { | |||
328 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ | 675 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ |
329 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) | 676 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) |
330 | 677 | ||
678 | static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, | ||
679 | struct snd_soc_dai *dai) | ||
680 | { | ||
681 | struct snd_soc_dai_driver *drv = dai->driver; | ||
682 | struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); | ||
683 | int ret; | ||
684 | |||
685 | dev_dbg(dai->dev, "%s()\n", __func__); | ||
686 | |||
687 | ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
688 | NULL, drv->playback.channels_max, 0, | ||
689 | &hcp->chmap_info); | ||
690 | if (ret < 0) | ||
691 | return ret; | ||
692 | |||
693 | /* override handlers */ | ||
694 | hcp->chmap_info->private_data = hcp; | ||
695 | hcp->chmap_info->kctl->get = hdmi_codec_chmap_ctl_get; | ||
696 | |||
697 | /* default chmap supported is stereo */ | ||
698 | hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps; | ||
699 | hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; | ||
700 | |||
701 | return 0; | ||
702 | } | ||
703 | |||
331 | static struct snd_soc_dai_driver hdmi_i2s_dai = { | 704 | static struct snd_soc_dai_driver hdmi_i2s_dai = { |
332 | .id = DAI_ID_I2S, | 705 | .id = DAI_ID_I2S, |
333 | .playback = { | 706 | .playback = { |
@@ -339,6 +712,7 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = { | |||
339 | .sig_bits = 24, | 712 | .sig_bits = 24, |
340 | }, | 713 | }, |
341 | .ops = &hdmi_dai_ops, | 714 | .ops = &hdmi_dai_ops, |
715 | .pcm_new = hdmi_codec_pcm_new, | ||
342 | }; | 716 | }; |
343 | 717 | ||
344 | static const struct snd_soc_dai_driver hdmi_spdif_dai = { | 718 | static const struct snd_soc_dai_driver hdmi_spdif_dai = { |
@@ -351,6 +725,7 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = { | |||
351 | .formats = SPDIF_FORMATS, | 725 | .formats = SPDIF_FORMATS, |
352 | }, | 726 | }, |
353 | .ops = &hdmi_dai_ops, | 727 | .ops = &hdmi_dai_ops, |
728 | .pcm_new = hdmi_codec_pcm_new, | ||
354 | }; | 729 | }; |
355 | 730 | ||
356 | static char hdmi_dai_name[][DAI_NAME_SIZE] = { | 731 | static char hdmi_dai_name[][DAI_NAME_SIZE] = { |
@@ -420,6 +795,7 @@ static int hdmi_codec_probe(struct platform_device *pdev) | |||
420 | return -ENOMEM; | 795 | return -ENOMEM; |
421 | 796 | ||
422 | hd = NULL; | 797 | hd = NULL; |
798 | mutex_lock(&hdmi_mutex); | ||
423 | list_for_each(pos, &hdmi_device_list) { | 799 | list_for_each(pos, &hdmi_device_list) { |
424 | struct hdmi_device *tmp = pos_to_hdmi_device(pos); | 800 | struct hdmi_device *tmp = pos_to_hdmi_device(pos); |
425 | 801 | ||
@@ -431,13 +807,16 @@ static int hdmi_codec_probe(struct platform_device *pdev) | |||
431 | 807 | ||
432 | if (!hd) { | 808 | if (!hd) { |
433 | hd = devm_kzalloc(dev, sizeof(*hd), GFP_KERNEL); | 809 | hd = devm_kzalloc(dev, sizeof(*hd), GFP_KERNEL); |
434 | if (!hd) | 810 | if (!hd) { |
811 | mutex_unlock(&hdmi_mutex); | ||
435 | return -ENOMEM; | 812 | return -ENOMEM; |
813 | } | ||
436 | 814 | ||
437 | hd->dev = dev->parent; | 815 | hd->dev = dev->parent; |
438 | 816 | ||
439 | list_add_tail(&hd->list, &hdmi_device_list); | 817 | list_add_tail(&hd->list, &hdmi_device_list); |
440 | } | 818 | } |
819 | mutex_unlock(&hdmi_mutex); | ||
441 | 820 | ||
442 | if (hd->cnt >= ARRAY_SIZE(hdmi_dai_name)) { | 821 | if (hd->cnt >= ARRAY_SIZE(hdmi_dai_name)) { |
443 | dev_err(dev, "too many hdmi codec are deteced\n"); | 822 | dev_err(dev, "too many hdmi codec are deteced\n"); |
@@ -479,7 +858,25 @@ static int hdmi_codec_probe(struct platform_device *pdev) | |||
479 | 858 | ||
480 | static int hdmi_codec_remove(struct platform_device *pdev) | 859 | static int hdmi_codec_remove(struct platform_device *pdev) |
481 | { | 860 | { |
482 | snd_soc_unregister_codec(&pdev->dev); | 861 | struct device *dev = &pdev->dev; |
862 | struct list_head *pos; | ||
863 | struct hdmi_codec_priv *hcp; | ||
864 | |||
865 | mutex_lock(&hdmi_mutex); | ||
866 | list_for_each(pos, &hdmi_device_list) { | ||
867 | struct hdmi_device *tmp = pos_to_hdmi_device(pos); | ||
868 | |||
869 | if (tmp->dev == dev->parent) { | ||
870 | list_del(pos); | ||
871 | break; | ||
872 | } | ||
873 | } | ||
874 | mutex_unlock(&hdmi_mutex); | ||
875 | |||
876 | hcp = dev_get_drvdata(dev); | ||
877 | kfree(hcp->chmap_info); | ||
878 | snd_soc_unregister_codec(dev); | ||
879 | |||
483 | return 0; | 880 | return 0; |
484 | } | 881 | } |
485 | 882 | ||
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 584aab83e478..66828480d484 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -2456,7 +2456,7 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2456 | if (err) { | 2456 | if (err) { |
2457 | micbias = M98090_MBVSEL_2V8; | 2457 | micbias = M98090_MBVSEL_2V8; |
2458 | dev_info(codec->dev, "use default 2.8v micbias\n"); | 2458 | dev_info(codec->dev, "use default 2.8v micbias\n"); |
2459 | } else if (micbias < M98090_MBVSEL_2V2 || micbias > M98090_MBVSEL_2V8) { | 2459 | } else if (micbias > M98090_MBVSEL_2V8) { |
2460 | dev_err(codec->dev, "micbias out of range 0x%x\n", micbias); | 2460 | dev_err(codec->dev, "micbias out of range 0x%x\n", micbias); |
2461 | micbias = M98090_MBVSEL_2V8; | 2461 | micbias = M98090_MBVSEL_2V8; |
2462 | } | 2462 | } |
diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 42e2e407e287..6cdf15ab46de 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c | |||
@@ -309,7 +309,6 @@ static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai, | |||
309 | struct snd_soc_codec *codec = codec_dai->codec; | 309 | struct snd_soc_codec *codec = codec_dai->codec; |
310 | struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); | 310 | struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); |
311 | u8 iface1A = 0, iface1B = 0; | 311 | u8 iface1A = 0, iface1B = 0; |
312 | int ret; | ||
313 | 312 | ||
314 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 313 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
315 | case SND_SOC_DAIFMT_CBM_CFM: | 314 | case SND_SOC_DAIFMT_CBM_CFM: |
@@ -346,8 +345,8 @@ static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai, | |||
346 | return -EINVAL; | 345 | return -EINVAL; |
347 | } | 346 | } |
348 | 347 | ||
349 | ret = regmap_write(max9867->regmap, MAX9867_IFC1A, iface1A); | 348 | regmap_write(max9867->regmap, MAX9867_IFC1A, iface1A); |
350 | ret = regmap_write(max9867->regmap, MAX9867_IFC1B, iface1B); | 349 | regmap_write(max9867->regmap, MAX9867_IFC1B, iface1B); |
351 | return 0; | 350 | return 0; |
352 | } | 351 | } |
353 | 352 | ||
diff --git a/sound/soc/codecs/nau8540.c b/sound/soc/codecs/nau8540.c new file mode 100644 index 000000000000..9e8f0f4aa51a --- /dev/null +++ b/sound/soc/codecs/nau8540.c | |||
@@ -0,0 +1,835 @@ | |||
1 | /* | ||
2 | * NAU85L40 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2016 Nuvoton Technology Corp. | ||
5 | * Author: John Hsu <KCHSU0@nuvoton.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/regmap.h> | ||
19 | #include <linux/regulator/consumer.h> | ||
20 | #include <linux/spi/spi.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/soc-dapm.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/tlv.h> | ||
30 | #include "nau8540.h" | ||
31 | |||
32 | |||
33 | #define NAU_FREF_MAX 13500000 | ||
34 | #define NAU_FVCO_MAX 100000000 | ||
35 | #define NAU_FVCO_MIN 90000000 | ||
36 | |||
37 | /* the maximum frequency of CLK_ADC */ | ||
38 | #define CLK_ADC_MAX 6144000 | ||
39 | |||
40 | /* scaling for mclk from sysclk_src output */ | ||
41 | static const struct nau8540_fll_attr mclk_src_scaling[] = { | ||
42 | { 1, 0x0 }, | ||
43 | { 2, 0x2 }, | ||
44 | { 4, 0x3 }, | ||
45 | { 8, 0x4 }, | ||
46 | { 16, 0x5 }, | ||
47 | { 32, 0x6 }, | ||
48 | { 3, 0x7 }, | ||
49 | { 6, 0xa }, | ||
50 | { 12, 0xb }, | ||
51 | { 24, 0xc }, | ||
52 | }; | ||
53 | |||
54 | /* ratio for input clk freq */ | ||
55 | static const struct nau8540_fll_attr fll_ratio[] = { | ||
56 | { 512000, 0x01 }, | ||
57 | { 256000, 0x02 }, | ||
58 | { 128000, 0x04 }, | ||
59 | { 64000, 0x08 }, | ||
60 | { 32000, 0x10 }, | ||
61 | { 8000, 0x20 }, | ||
62 | { 4000, 0x40 }, | ||
63 | }; | ||
64 | |||
65 | static const struct nau8540_fll_attr fll_pre_scalar[] = { | ||
66 | { 1, 0x0 }, | ||
67 | { 2, 0x1 }, | ||
68 | { 4, 0x2 }, | ||
69 | { 8, 0x3 }, | ||
70 | }; | ||
71 | |||
72 | /* over sampling rate */ | ||
73 | static const struct nau8540_osr_attr osr_adc_sel[] = { | ||
74 | { 32, 3 }, /* OSR 32, SRC 1/8 */ | ||
75 | { 64, 2 }, /* OSR 64, SRC 1/4 */ | ||
76 | { 128, 1 }, /* OSR 128, SRC 1/2 */ | ||
77 | { 256, 0 }, /* OSR 256, SRC 1 */ | ||
78 | }; | ||
79 | |||
80 | static const struct reg_default nau8540_reg_defaults[] = { | ||
81 | {NAU8540_REG_POWER_MANAGEMENT, 0x0000}, | ||
82 | {NAU8540_REG_CLOCK_CTRL, 0x0000}, | ||
83 | {NAU8540_REG_CLOCK_SRC, 0x0000}, | ||
84 | {NAU8540_REG_FLL1, 0x0001}, | ||
85 | {NAU8540_REG_FLL2, 0x3126}, | ||
86 | {NAU8540_REG_FLL3, 0x0008}, | ||
87 | {NAU8540_REG_FLL4, 0x0010}, | ||
88 | {NAU8540_REG_FLL5, 0xC000}, | ||
89 | {NAU8540_REG_FLL6, 0x6000}, | ||
90 | {NAU8540_REG_FLL_VCO_RSV, 0xF13C}, | ||
91 | {NAU8540_REG_PCM_CTRL0, 0x000B}, | ||
92 | {NAU8540_REG_PCM_CTRL1, 0x3010}, | ||
93 | {NAU8540_REG_PCM_CTRL2, 0x0800}, | ||
94 | {NAU8540_REG_PCM_CTRL3, 0x0000}, | ||
95 | {NAU8540_REG_PCM_CTRL4, 0x000F}, | ||
96 | {NAU8540_REG_ALC_CONTROL_1, 0x0000}, | ||
97 | {NAU8540_REG_ALC_CONTROL_2, 0x700B}, | ||
98 | {NAU8540_REG_ALC_CONTROL_3, 0x0022}, | ||
99 | {NAU8540_REG_ALC_CONTROL_4, 0x1010}, | ||
100 | {NAU8540_REG_ALC_CONTROL_5, 0x1010}, | ||
101 | {NAU8540_REG_NOTCH_FIL1_CH1, 0x0000}, | ||
102 | {NAU8540_REG_NOTCH_FIL2_CH1, 0x0000}, | ||
103 | {NAU8540_REG_NOTCH_FIL1_CH2, 0x0000}, | ||
104 | {NAU8540_REG_NOTCH_FIL2_CH2, 0x0000}, | ||
105 | {NAU8540_REG_NOTCH_FIL1_CH3, 0x0000}, | ||
106 | {NAU8540_REG_NOTCH_FIL2_CH3, 0x0000}, | ||
107 | {NAU8540_REG_NOTCH_FIL1_CH4, 0x0000}, | ||
108 | {NAU8540_REG_NOTCH_FIL2_CH4, 0x0000}, | ||
109 | {NAU8540_REG_HPF_FILTER_CH12, 0x0000}, | ||
110 | {NAU8540_REG_HPF_FILTER_CH34, 0x0000}, | ||
111 | {NAU8540_REG_ADC_SAMPLE_RATE, 0x0002}, | ||
112 | {NAU8540_REG_DIGITAL_GAIN_CH1, 0x0400}, | ||
113 | {NAU8540_REG_DIGITAL_GAIN_CH2, 0x0400}, | ||
114 | {NAU8540_REG_DIGITAL_GAIN_CH3, 0x0400}, | ||
115 | {NAU8540_REG_DIGITAL_GAIN_CH4, 0x0400}, | ||
116 | {NAU8540_REG_DIGITAL_MUX, 0x00E4}, | ||
117 | {NAU8540_REG_GPIO_CTRL, 0x0000}, | ||
118 | {NAU8540_REG_MISC_CTRL, 0x0000}, | ||
119 | {NAU8540_REG_I2C_CTRL, 0xEFFF}, | ||
120 | {NAU8540_REG_VMID_CTRL, 0x0000}, | ||
121 | {NAU8540_REG_MUTE, 0x0000}, | ||
122 | {NAU8540_REG_ANALOG_ADC1, 0x0011}, | ||
123 | {NAU8540_REG_ANALOG_ADC2, 0x0020}, | ||
124 | {NAU8540_REG_ANALOG_PWR, 0x0000}, | ||
125 | {NAU8540_REG_MIC_BIAS, 0x0004}, | ||
126 | {NAU8540_REG_REFERENCE, 0x0000}, | ||
127 | {NAU8540_REG_FEPGA1, 0x0000}, | ||
128 | {NAU8540_REG_FEPGA2, 0x0000}, | ||
129 | {NAU8540_REG_FEPGA3, 0x0101}, | ||
130 | {NAU8540_REG_FEPGA4, 0x0101}, | ||
131 | {NAU8540_REG_PWR, 0x0000}, | ||
132 | }; | ||
133 | |||
134 | static bool nau8540_readable_reg(struct device *dev, unsigned int reg) | ||
135 | { | ||
136 | switch (reg) { | ||
137 | case NAU8540_REG_POWER_MANAGEMENT ... NAU8540_REG_FLL_VCO_RSV: | ||
138 | case NAU8540_REG_PCM_CTRL0 ... NAU8540_REG_PCM_CTRL4: | ||
139 | case NAU8540_REG_ALC_CONTROL_1 ... NAU8540_REG_ALC_CONTROL_5: | ||
140 | case NAU8540_REG_ALC_GAIN_CH12 ... NAU8540_REG_ADC_SAMPLE_RATE: | ||
141 | case NAU8540_REG_DIGITAL_GAIN_CH1 ... NAU8540_REG_DIGITAL_MUX: | ||
142 | case NAU8540_REG_P2P_CH1 ... NAU8540_REG_I2C_CTRL: | ||
143 | case NAU8540_REG_I2C_DEVICE_ID: | ||
144 | case NAU8540_REG_VMID_CTRL ... NAU8540_REG_MUTE: | ||
145 | case NAU8540_REG_ANALOG_ADC1 ... NAU8540_REG_PWR: | ||
146 | return true; | ||
147 | default: | ||
148 | return false; | ||
149 | } | ||
150 | |||
151 | } | ||
152 | |||
153 | static bool nau8540_writeable_reg(struct device *dev, unsigned int reg) | ||
154 | { | ||
155 | switch (reg) { | ||
156 | case NAU8540_REG_SW_RESET ... NAU8540_REG_FLL_VCO_RSV: | ||
157 | case NAU8540_REG_PCM_CTRL0 ... NAU8540_REG_PCM_CTRL4: | ||
158 | case NAU8540_REG_ALC_CONTROL_1 ... NAU8540_REG_ALC_CONTROL_5: | ||
159 | case NAU8540_REG_NOTCH_FIL1_CH1 ... NAU8540_REG_ADC_SAMPLE_RATE: | ||
160 | case NAU8540_REG_DIGITAL_GAIN_CH1 ... NAU8540_REG_DIGITAL_MUX: | ||
161 | case NAU8540_REG_GPIO_CTRL ... NAU8540_REG_I2C_CTRL: | ||
162 | case NAU8540_REG_RST: | ||
163 | case NAU8540_REG_VMID_CTRL ... NAU8540_REG_MUTE: | ||
164 | case NAU8540_REG_ANALOG_ADC1 ... NAU8540_REG_PWR: | ||
165 | return true; | ||
166 | default: | ||
167 | return false; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static bool nau8540_volatile_reg(struct device *dev, unsigned int reg) | ||
172 | { | ||
173 | switch (reg) { | ||
174 | case NAU8540_REG_SW_RESET: | ||
175 | case NAU8540_REG_ALC_GAIN_CH12 ... NAU8540_REG_ALC_STATUS: | ||
176 | case NAU8540_REG_P2P_CH1 ... NAU8540_REG_PEAK_CH4: | ||
177 | case NAU8540_REG_I2C_DEVICE_ID: | ||
178 | case NAU8540_REG_RST: | ||
179 | return true; | ||
180 | default: | ||
181 | return false; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | |||
186 | static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -12800, 3600); | ||
187 | static const DECLARE_TLV_DB_MINMAX(fepga_gain_tlv, -100, 3600); | ||
188 | |||
189 | static const struct snd_kcontrol_new nau8540_snd_controls[] = { | ||
190 | SOC_SINGLE_TLV("Mic1 Volume", NAU8540_REG_DIGITAL_GAIN_CH1, | ||
191 | 0, 0x520, 0, adc_vol_tlv), | ||
192 | SOC_SINGLE_TLV("Mic2 Volume", NAU8540_REG_DIGITAL_GAIN_CH2, | ||
193 | 0, 0x520, 0, adc_vol_tlv), | ||
194 | SOC_SINGLE_TLV("Mic3 Volume", NAU8540_REG_DIGITAL_GAIN_CH3, | ||
195 | 0, 0x520, 0, adc_vol_tlv), | ||
196 | SOC_SINGLE_TLV("Mic4 Volume", NAU8540_REG_DIGITAL_GAIN_CH4, | ||
197 | 0, 0x520, 0, adc_vol_tlv), | ||
198 | |||
199 | SOC_SINGLE_TLV("Frontend PGA1 Volume", NAU8540_REG_FEPGA3, | ||
200 | 0, 0x25, 0, fepga_gain_tlv), | ||
201 | SOC_SINGLE_TLV("Frontend PGA2 Volume", NAU8540_REG_FEPGA3, | ||
202 | 8, 0x25, 0, fepga_gain_tlv), | ||
203 | SOC_SINGLE_TLV("Frontend PGA3 Volume", NAU8540_REG_FEPGA4, | ||
204 | 0, 0x25, 0, fepga_gain_tlv), | ||
205 | SOC_SINGLE_TLV("Frontend PGA4 Volume", NAU8540_REG_FEPGA4, | ||
206 | 8, 0x25, 0, fepga_gain_tlv), | ||
207 | }; | ||
208 | |||
209 | static const char * const adc_channel[] = { | ||
210 | "ADC channel 1", "ADC channel 2", "ADC channel 3", "ADC channel 4" | ||
211 | }; | ||
212 | static SOC_ENUM_SINGLE_DECL( | ||
213 | digital_ch4_enum, NAU8540_REG_DIGITAL_MUX, 6, adc_channel); | ||
214 | |||
215 | static const struct snd_kcontrol_new digital_ch4_mux = | ||
216 | SOC_DAPM_ENUM("Digital CH4 Select", digital_ch4_enum); | ||
217 | |||
218 | static SOC_ENUM_SINGLE_DECL( | ||
219 | digital_ch3_enum, NAU8540_REG_DIGITAL_MUX, 4, adc_channel); | ||
220 | |||
221 | static const struct snd_kcontrol_new digital_ch3_mux = | ||
222 | SOC_DAPM_ENUM("Digital CH3 Select", digital_ch3_enum); | ||
223 | |||
224 | static SOC_ENUM_SINGLE_DECL( | ||
225 | digital_ch2_enum, NAU8540_REG_DIGITAL_MUX, 2, adc_channel); | ||
226 | |||
227 | static const struct snd_kcontrol_new digital_ch2_mux = | ||
228 | SOC_DAPM_ENUM("Digital CH2 Select", digital_ch2_enum); | ||
229 | |||
230 | static SOC_ENUM_SINGLE_DECL( | ||
231 | digital_ch1_enum, NAU8540_REG_DIGITAL_MUX, 0, adc_channel); | ||
232 | |||
233 | static const struct snd_kcontrol_new digital_ch1_mux = | ||
234 | SOC_DAPM_ENUM("Digital CH1 Select", digital_ch1_enum); | ||
235 | |||
236 | static const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = { | ||
237 | SND_SOC_DAPM_SUPPLY("MICBIAS2", NAU8540_REG_MIC_BIAS, 11, 0, NULL, 0), | ||
238 | SND_SOC_DAPM_SUPPLY("MICBIAS1", NAU8540_REG_MIC_BIAS, 10, 0, NULL, 0), | ||
239 | |||
240 | SND_SOC_DAPM_INPUT("MIC1"), | ||
241 | SND_SOC_DAPM_INPUT("MIC2"), | ||
242 | SND_SOC_DAPM_INPUT("MIC3"), | ||
243 | SND_SOC_DAPM_INPUT("MIC4"), | ||
244 | |||
245 | SND_SOC_DAPM_PGA("Frontend PGA1", NAU8540_REG_PWR, 12, 0, NULL, 0), | ||
246 | SND_SOC_DAPM_PGA("Frontend PGA2", NAU8540_REG_PWR, 13, 0, NULL, 0), | ||
247 | SND_SOC_DAPM_PGA("Frontend PGA3", NAU8540_REG_PWR, 14, 0, NULL, 0), | ||
248 | SND_SOC_DAPM_PGA("Frontend PGA4", NAU8540_REG_PWR, 15, 0, NULL, 0), | ||
249 | |||
250 | SND_SOC_DAPM_ADC("ADC1", NULL, | ||
251 | NAU8540_REG_POWER_MANAGEMENT, 0, 0), | ||
252 | SND_SOC_DAPM_ADC("ADC2", NULL, | ||
253 | NAU8540_REG_POWER_MANAGEMENT, 1, 0), | ||
254 | SND_SOC_DAPM_ADC("ADC3", NULL, | ||
255 | NAU8540_REG_POWER_MANAGEMENT, 2, 0), | ||
256 | SND_SOC_DAPM_ADC("ADC4", NULL, | ||
257 | NAU8540_REG_POWER_MANAGEMENT, 3, 0), | ||
258 | |||
259 | SND_SOC_DAPM_PGA("ADC CH1", NAU8540_REG_ANALOG_PWR, 0, 0, NULL, 0), | ||
260 | SND_SOC_DAPM_PGA("ADC CH2", NAU8540_REG_ANALOG_PWR, 1, 0, NULL, 0), | ||
261 | SND_SOC_DAPM_PGA("ADC CH3", NAU8540_REG_ANALOG_PWR, 2, 0, NULL, 0), | ||
262 | SND_SOC_DAPM_PGA("ADC CH4", NAU8540_REG_ANALOG_PWR, 3, 0, NULL, 0), | ||
263 | |||
264 | SND_SOC_DAPM_MUX("Digital CH4 Mux", | ||
265 | SND_SOC_NOPM, 0, 0, &digital_ch4_mux), | ||
266 | SND_SOC_DAPM_MUX("Digital CH3 Mux", | ||
267 | SND_SOC_NOPM, 0, 0, &digital_ch3_mux), | ||
268 | SND_SOC_DAPM_MUX("Digital CH2 Mux", | ||
269 | SND_SOC_NOPM, 0, 0, &digital_ch2_mux), | ||
270 | SND_SOC_DAPM_MUX("Digital CH1 Mux", | ||
271 | SND_SOC_NOPM, 0, 0, &digital_ch1_mux), | ||
272 | |||
273 | SND_SOC_DAPM_AIF_OUT("AIFTX", "Capture", 0, SND_SOC_NOPM, 0, 0), | ||
274 | }; | ||
275 | |||
276 | static const struct snd_soc_dapm_route nau8540_dapm_routes[] = { | ||
277 | {"Frontend PGA1", NULL, "MIC1"}, | ||
278 | {"Frontend PGA2", NULL, "MIC2"}, | ||
279 | {"Frontend PGA3", NULL, "MIC3"}, | ||
280 | {"Frontend PGA4", NULL, "MIC4"}, | ||
281 | |||
282 | {"ADC1", NULL, "Frontend PGA1"}, | ||
283 | {"ADC2", NULL, "Frontend PGA2"}, | ||
284 | {"ADC3", NULL, "Frontend PGA3"}, | ||
285 | {"ADC4", NULL, "Frontend PGA4"}, | ||
286 | |||
287 | {"ADC CH1", NULL, "ADC1"}, | ||
288 | {"ADC CH2", NULL, "ADC2"}, | ||
289 | {"ADC CH3", NULL, "ADC3"}, | ||
290 | {"ADC CH4", NULL, "ADC4"}, | ||
291 | |||
292 | {"ADC1", NULL, "MICBIAS1"}, | ||
293 | {"ADC2", NULL, "MICBIAS1"}, | ||
294 | {"ADC3", NULL, "MICBIAS2"}, | ||
295 | {"ADC4", NULL, "MICBIAS2"}, | ||
296 | |||
297 | {"Digital CH1 Mux", "ADC channel 1", "ADC CH1"}, | ||
298 | {"Digital CH1 Mux", "ADC channel 2", "ADC CH2"}, | ||
299 | {"Digital CH1 Mux", "ADC channel 3", "ADC CH3"}, | ||
300 | {"Digital CH1 Mux", "ADC channel 4", "ADC CH4"}, | ||
301 | |||
302 | {"Digital CH2 Mux", "ADC channel 1", "ADC CH1"}, | ||
303 | {"Digital CH2 Mux", "ADC channel 2", "ADC CH2"}, | ||
304 | {"Digital CH2 Mux", "ADC channel 3", "ADC CH3"}, | ||
305 | {"Digital CH2 Mux", "ADC channel 4", "ADC CH4"}, | ||
306 | |||
307 | {"Digital CH3 Mux", "ADC channel 1", "ADC CH1"}, | ||
308 | {"Digital CH3 Mux", "ADC channel 2", "ADC CH2"}, | ||
309 | {"Digital CH3 Mux", "ADC channel 3", "ADC CH3"}, | ||
310 | {"Digital CH3 Mux", "ADC channel 4", "ADC CH4"}, | ||
311 | |||
312 | {"Digital CH4 Mux", "ADC channel 1", "ADC CH1"}, | ||
313 | {"Digital CH4 Mux", "ADC channel 2", "ADC CH2"}, | ||
314 | {"Digital CH4 Mux", "ADC channel 3", "ADC CH3"}, | ||
315 | {"Digital CH4 Mux", "ADC channel 4", "ADC CH4"}, | ||
316 | |||
317 | {"AIFTX", NULL, "Digital CH1 Mux"}, | ||
318 | {"AIFTX", NULL, "Digital CH2 Mux"}, | ||
319 | {"AIFTX", NULL, "Digital CH3 Mux"}, | ||
320 | {"AIFTX", NULL, "Digital CH4 Mux"}, | ||
321 | }; | ||
322 | |||
323 | static int nau8540_clock_check(struct nau8540 *nau8540, int rate, int osr) | ||
324 | { | ||
325 | int osrate; | ||
326 | |||
327 | if (osr >= ARRAY_SIZE(osr_adc_sel)) | ||
328 | return -EINVAL; | ||
329 | osrate = osr_adc_sel[osr].osr; | ||
330 | |||
331 | if (rate * osr > CLK_ADC_MAX) { | ||
332 | dev_err(nau8540->dev, "exceed the maximum frequency of CLK_ADC\n"); | ||
333 | return -EINVAL; | ||
334 | } | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static int nau8540_hw_params(struct snd_pcm_substream *substream, | ||
340 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
341 | { | ||
342 | struct snd_soc_codec *codec = dai->codec; | ||
343 | struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec); | ||
344 | unsigned int val_len = 0, osr; | ||
345 | |||
346 | /* CLK_ADC = OSR * FS | ||
347 | * ADC clock frequency is defined as Over Sampling Rate (OSR) | ||
348 | * multiplied by the audio sample rate (Fs). Note that the OSR and Fs | ||
349 | * values must be selected such that the maximum frequency is less | ||
350 | * than 6.144 MHz. | ||
351 | */ | ||
352 | regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr); | ||
353 | osr &= NAU8540_ADC_OSR_MASK; | ||
354 | if (nau8540_clock_check(nau8540, params_rate(params), osr)) | ||
355 | return -EINVAL; | ||
356 | regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC, | ||
357 | NAU8540_CLK_ADC_SRC_MASK, | ||
358 | osr_adc_sel[osr].clk_src << NAU8540_CLK_ADC_SRC_SFT); | ||
359 | |||
360 | switch (params_width(params)) { | ||
361 | case 16: | ||
362 | val_len |= NAU8540_I2S_DL_16; | ||
363 | break; | ||
364 | case 20: | ||
365 | val_len |= NAU8540_I2S_DL_20; | ||
366 | break; | ||
367 | case 24: | ||
368 | val_len |= NAU8540_I2S_DL_24; | ||
369 | break; | ||
370 | case 32: | ||
371 | val_len |= NAU8540_I2S_DL_32; | ||
372 | break; | ||
373 | default: | ||
374 | return -EINVAL; | ||
375 | } | ||
376 | |||
377 | regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL0, | ||
378 | NAU8540_I2S_DL_MASK, val_len); | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int nau8540_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
384 | { | ||
385 | struct snd_soc_codec *codec = dai->codec; | ||
386 | struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec); | ||
387 | unsigned int ctrl1_val = 0, ctrl2_val = 0; | ||
388 | |||
389 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
390 | case SND_SOC_DAIFMT_CBM_CFM: | ||
391 | ctrl2_val |= NAU8540_I2S_MS_MASTER; | ||
392 | break; | ||
393 | case SND_SOC_DAIFMT_CBS_CFS: | ||
394 | break; | ||
395 | default: | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | |||
399 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
400 | case SND_SOC_DAIFMT_NB_NF: | ||
401 | break; | ||
402 | case SND_SOC_DAIFMT_IB_NF: | ||
403 | ctrl1_val |= NAU8540_I2S_BP_INV; | ||
404 | break; | ||
405 | default: | ||
406 | return -EINVAL; | ||
407 | } | ||
408 | |||
409 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
410 | case SND_SOC_DAIFMT_I2S: | ||
411 | ctrl1_val |= NAU8540_I2S_DF_I2S; | ||
412 | break; | ||
413 | case SND_SOC_DAIFMT_LEFT_J: | ||
414 | ctrl1_val |= NAU8540_I2S_DF_LEFT; | ||
415 | break; | ||
416 | case SND_SOC_DAIFMT_RIGHT_J: | ||
417 | ctrl1_val |= NAU8540_I2S_DF_RIGTH; | ||
418 | break; | ||
419 | case SND_SOC_DAIFMT_DSP_A: | ||
420 | ctrl1_val |= NAU8540_I2S_DF_PCM_AB; | ||
421 | break; | ||
422 | case SND_SOC_DAIFMT_DSP_B: | ||
423 | ctrl1_val |= NAU8540_I2S_DF_PCM_AB; | ||
424 | ctrl1_val |= NAU8540_I2S_PCMB_EN; | ||
425 | break; | ||
426 | default: | ||
427 | return -EINVAL; | ||
428 | } | ||
429 | |||
430 | regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL0, | ||
431 | NAU8540_I2S_DL_MASK | NAU8540_I2S_DF_MASK | | ||
432 | NAU8540_I2S_BP_INV | NAU8540_I2S_PCMB_EN, ctrl1_val); | ||
433 | regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL1, | ||
434 | NAU8540_I2S_MS_MASK | NAU8540_I2S_DO12_OE, ctrl2_val); | ||
435 | regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL2, | ||
436 | NAU8540_I2S_DO34_OE, 0); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | /** | ||
442 | * nau8540_set_tdm_slot - configure DAI TX TDM. | ||
443 | * @dai: DAI | ||
444 | * @tx_mask: bitmask representing active TX slots. Ex. | ||
445 | * 0xf for normal 4 channel TDM. | ||
446 | * 0xf0 for shifted 4 channel TDM | ||
447 | * @rx_mask: no used. | ||
448 | * @slots: Number of slots in use. | ||
449 | * @slot_width: Width in bits for each slot. | ||
450 | * | ||
451 | * Configures a DAI for TDM operation. Only support 4 slots TDM. | ||
452 | */ | ||
453 | static int nau8540_set_tdm_slot(struct snd_soc_dai *dai, | ||
454 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | ||
455 | { | ||
456 | struct snd_soc_codec *codec = dai->codec; | ||
457 | struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec); | ||
458 | unsigned int ctrl2_val = 0, ctrl4_val = 0; | ||
459 | |||
460 | if (slots > 4 || ((tx_mask & 0xf0) && (tx_mask & 0xf))) | ||
461 | return -EINVAL; | ||
462 | |||
463 | ctrl4_val |= (NAU8540_TDM_MODE | NAU8540_TDM_OFFSET_EN); | ||
464 | if (tx_mask & 0xf0) { | ||
465 | ctrl2_val = 4 * slot_width; | ||
466 | ctrl4_val |= (tx_mask >> 4); | ||
467 | } else { | ||
468 | ctrl4_val |= tx_mask; | ||
469 | } | ||
470 | regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL4, | ||
471 | NAU8540_TDM_MODE | NAU8540_TDM_OFFSET_EN | | ||
472 | NAU8540_TDM_TX_MASK, ctrl4_val); | ||
473 | regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL1, | ||
474 | NAU8540_I2S_DO12_OE, NAU8540_I2S_DO12_OE); | ||
475 | regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL2, | ||
476 | NAU8540_I2S_DO34_OE | NAU8540_I2S_TSLOT_L_MASK, | ||
477 | NAU8540_I2S_DO34_OE | ctrl2_val); | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | |||
483 | static const struct snd_soc_dai_ops nau8540_dai_ops = { | ||
484 | .hw_params = nau8540_hw_params, | ||
485 | .set_fmt = nau8540_set_fmt, | ||
486 | .set_tdm_slot = nau8540_set_tdm_slot, | ||
487 | }; | ||
488 | |||
489 | #define NAU8540_RATES SNDRV_PCM_RATE_8000_48000 | ||
490 | #define NAU8540_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ | ||
491 | | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
492 | |||
493 | static struct snd_soc_dai_driver nau8540_dai = { | ||
494 | .name = "nau8540-hifi", | ||
495 | .capture = { | ||
496 | .stream_name = "Capture", | ||
497 | .channels_min = 1, | ||
498 | .channels_max = 4, | ||
499 | .rates = NAU8540_RATES, | ||
500 | .formats = NAU8540_FORMATS, | ||
501 | }, | ||
502 | .ops = &nau8540_dai_ops, | ||
503 | }; | ||
504 | |||
505 | /** | ||
506 | * nau8540_calc_fll_param - Calculate FLL parameters. | ||
507 | * @fll_in: external clock provided to codec. | ||
508 | * @fs: sampling rate. | ||
509 | * @fll_param: Pointer to structure of FLL parameters. | ||
510 | * | ||
511 | * Calculate FLL parameters to configure codec. | ||
512 | * | ||
513 | * Returns 0 for success or negative error code. | ||
514 | */ | ||
515 | static int nau8540_calc_fll_param(unsigned int fll_in, | ||
516 | unsigned int fs, struct nau8540_fll *fll_param) | ||
517 | { | ||
518 | u64 fvco, fvco_max; | ||
519 | unsigned int fref, i, fvco_sel; | ||
520 | |||
521 | /* Ensure the reference clock frequency (FREF) is <= 13.5MHz by dividing | ||
522 | * freq_in by 1, 2, 4, or 8 using FLL pre-scalar. | ||
523 | * FREF = freq_in / NAU8540_FLL_REF_DIV_MASK | ||
524 | */ | ||
525 | for (i = 0; i < ARRAY_SIZE(fll_pre_scalar); i++) { | ||
526 | fref = fll_in / fll_pre_scalar[i].param; | ||
527 | if (fref <= NAU_FREF_MAX) | ||
528 | break; | ||
529 | } | ||
530 | if (i == ARRAY_SIZE(fll_pre_scalar)) | ||
531 | return -EINVAL; | ||
532 | fll_param->clk_ref_div = fll_pre_scalar[i].val; | ||
533 | |||
534 | /* Choose the FLL ratio based on FREF */ | ||
535 | for (i = 0; i < ARRAY_SIZE(fll_ratio); i++) { | ||
536 | if (fref >= fll_ratio[i].param) | ||
537 | break; | ||
538 | } | ||
539 | if (i == ARRAY_SIZE(fll_ratio)) | ||
540 | return -EINVAL; | ||
541 | fll_param->ratio = fll_ratio[i].val; | ||
542 | |||
543 | /* Calculate the frequency of DCO (FDCO) given freq_out = 256 * Fs. | ||
544 | * FDCO must be within the 90MHz - 124MHz or the FFL cannot be | ||
545 | * guaranteed across the full range of operation. | ||
546 | * FDCO = freq_out * 2 * mclk_src_scaling | ||
547 | */ | ||
548 | fvco_max = 0; | ||
549 | fvco_sel = ARRAY_SIZE(mclk_src_scaling); | ||
550 | for (i = 0; i < ARRAY_SIZE(mclk_src_scaling); i++) { | ||
551 | fvco = 256 * fs * 2 * mclk_src_scaling[i].param; | ||
552 | if (fvco > NAU_FVCO_MIN && fvco < NAU_FVCO_MAX && | ||
553 | fvco_max < fvco) { | ||
554 | fvco_max = fvco; | ||
555 | fvco_sel = i; | ||
556 | } | ||
557 | } | ||
558 | if (ARRAY_SIZE(mclk_src_scaling) == fvco_sel) | ||
559 | return -EINVAL; | ||
560 | fll_param->mclk_src = mclk_src_scaling[fvco_sel].val; | ||
561 | |||
562 | /* Calculate the FLL 10-bit integer input and the FLL 16-bit fractional | ||
563 | * input based on FDCO, FREF and FLL ratio. | ||
564 | */ | ||
565 | fvco = div_u64(fvco_max << 16, fref * fll_param->ratio); | ||
566 | fll_param->fll_int = (fvco >> 16) & 0x3FF; | ||
567 | fll_param->fll_frac = fvco & 0xFFFF; | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static void nau8540_fll_apply(struct regmap *regmap, | ||
572 | struct nau8540_fll *fll_param) | ||
573 | { | ||
574 | regmap_update_bits(regmap, NAU8540_REG_CLOCK_SRC, | ||
575 | NAU8540_CLK_SRC_MASK | NAU8540_CLK_MCLK_SRC_MASK, | ||
576 | NAU8540_CLK_SRC_MCLK | fll_param->mclk_src); | ||
577 | regmap_update_bits(regmap, NAU8540_REG_FLL1, | ||
578 | NAU8540_FLL_RATIO_MASK, fll_param->ratio); | ||
579 | /* FLL 16-bit fractional input */ | ||
580 | regmap_write(regmap, NAU8540_REG_FLL2, fll_param->fll_frac); | ||
581 | /* FLL 10-bit integer input */ | ||
582 | regmap_update_bits(regmap, NAU8540_REG_FLL3, | ||
583 | NAU8540_FLL_INTEGER_MASK, fll_param->fll_int); | ||
584 | /* FLL pre-scaler */ | ||
585 | regmap_update_bits(regmap, NAU8540_REG_FLL4, | ||
586 | NAU8540_FLL_REF_DIV_MASK, | ||
587 | fll_param->clk_ref_div << NAU8540_FLL_REF_DIV_SFT); | ||
588 | regmap_update_bits(regmap, NAU8540_REG_FLL5, | ||
589 | NAU8540_FLL_CLK_SW_MASK, NAU8540_FLL_CLK_SW_REF); | ||
590 | regmap_update_bits(regmap, | ||
591 | NAU8540_REG_FLL6, NAU8540_DCO_EN, 0); | ||
592 | if (fll_param->fll_frac) { | ||
593 | regmap_update_bits(regmap, NAU8540_REG_FLL5, | ||
594 | NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN | | ||
595 | NAU8540_FLL_FTR_SW_MASK, | ||
596 | NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN | | ||
597 | NAU8540_FLL_FTR_SW_FILTER); | ||
598 | regmap_update_bits(regmap, NAU8540_REG_FLL6, | ||
599 | NAU8540_SDM_EN, NAU8540_SDM_EN); | ||
600 | } else { | ||
601 | regmap_update_bits(regmap, NAU8540_REG_FLL5, | ||
602 | NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN | | ||
603 | NAU8540_FLL_FTR_SW_MASK, NAU8540_FLL_FTR_SW_ACCU); | ||
604 | regmap_update_bits(regmap, | ||
605 | NAU8540_REG_FLL6, NAU8540_SDM_EN, 0); | ||
606 | } | ||
607 | } | ||
608 | |||
609 | /* freq_out must be 256*Fs in order to achieve the best performance */ | ||
610 | static int nau8540_set_pll(struct snd_soc_codec *codec, int pll_id, int source, | ||
611 | unsigned int freq_in, unsigned int freq_out) | ||
612 | { | ||
613 | struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec); | ||
614 | struct nau8540_fll fll_param; | ||
615 | int ret, fs; | ||
616 | |||
617 | switch (pll_id) { | ||
618 | case NAU8540_CLK_FLL_MCLK: | ||
619 | regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3, | ||
620 | NAU8540_FLL_CLK_SRC_MASK, NAU8540_FLL_CLK_SRC_MCLK); | ||
621 | break; | ||
622 | |||
623 | case NAU8540_CLK_FLL_BLK: | ||
624 | regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3, | ||
625 | NAU8540_FLL_CLK_SRC_MASK, NAU8540_FLL_CLK_SRC_BLK); | ||
626 | break; | ||
627 | |||
628 | case NAU8540_CLK_FLL_FS: | ||
629 | regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3, | ||
630 | NAU8540_FLL_CLK_SRC_MASK, NAU8540_FLL_CLK_SRC_FS); | ||
631 | break; | ||
632 | |||
633 | default: | ||
634 | dev_err(nau8540->dev, "Invalid clock id (%d)\n", pll_id); | ||
635 | return -EINVAL; | ||
636 | } | ||
637 | dev_dbg(nau8540->dev, "Sysclk is %dHz and clock id is %d\n", | ||
638 | freq_out, pll_id); | ||
639 | |||
640 | fs = freq_out / 256; | ||
641 | ret = nau8540_calc_fll_param(freq_in, fs, &fll_param); | ||
642 | if (ret < 0) { | ||
643 | dev_err(nau8540->dev, "Unsupported input clock %d\n", freq_in); | ||
644 | return ret; | ||
645 | } | ||
646 | dev_dbg(nau8540->dev, "mclk_src=%x ratio=%x fll_frac=%x fll_int=%x clk_ref_div=%x\n", | ||
647 | fll_param.mclk_src, fll_param.ratio, fll_param.fll_frac, | ||
648 | fll_param.fll_int, fll_param.clk_ref_div); | ||
649 | |||
650 | nau8540_fll_apply(nau8540->regmap, &fll_param); | ||
651 | mdelay(2); | ||
652 | regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC, | ||
653 | NAU8540_CLK_SRC_MASK, NAU8540_CLK_SRC_VCO); | ||
654 | |||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | static int nau8540_set_sysclk(struct snd_soc_codec *codec, | ||
659 | int clk_id, int source, unsigned int freq, int dir) | ||
660 | { | ||
661 | struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec); | ||
662 | |||
663 | switch (clk_id) { | ||
664 | case NAU8540_CLK_DIS: | ||
665 | case NAU8540_CLK_MCLK: | ||
666 | regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC, | ||
667 | NAU8540_CLK_SRC_MASK, NAU8540_CLK_SRC_MCLK); | ||
668 | regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL6, | ||
669 | NAU8540_DCO_EN, 0); | ||
670 | break; | ||
671 | |||
672 | case NAU8540_CLK_INTERNAL: | ||
673 | regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL6, | ||
674 | NAU8540_DCO_EN, NAU8540_DCO_EN); | ||
675 | regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC, | ||
676 | NAU8540_CLK_SRC_MASK, NAU8540_CLK_SRC_VCO); | ||
677 | break; | ||
678 | |||
679 | default: | ||
680 | dev_err(nau8540->dev, "Invalid clock id (%d)\n", clk_id); | ||
681 | return -EINVAL; | ||
682 | } | ||
683 | |||
684 | dev_dbg(nau8540->dev, "Sysclk is %dHz and clock id is %d\n", | ||
685 | freq, clk_id); | ||
686 | |||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | static void nau8540_reset_chip(struct regmap *regmap) | ||
691 | { | ||
692 | regmap_write(regmap, NAU8540_REG_SW_RESET, 0x00); | ||
693 | regmap_write(regmap, NAU8540_REG_SW_RESET, 0x00); | ||
694 | } | ||
695 | |||
696 | static void nau8540_init_regs(struct nau8540 *nau8540) | ||
697 | { | ||
698 | struct regmap *regmap = nau8540->regmap; | ||
699 | |||
700 | /* Enable Bias/VMID/VMID Tieoff */ | ||
701 | regmap_update_bits(regmap, NAU8540_REG_VMID_CTRL, | ||
702 | NAU8540_VMID_EN | NAU8540_VMID_SEL_MASK, | ||
703 | NAU8540_VMID_EN | (0x2 << NAU8540_VMID_SEL_SFT)); | ||
704 | regmap_update_bits(regmap, NAU8540_REG_REFERENCE, | ||
705 | NAU8540_PRECHARGE_DIS | NAU8540_GLOBAL_BIAS_EN, | ||
706 | NAU8540_PRECHARGE_DIS | NAU8540_GLOBAL_BIAS_EN); | ||
707 | mdelay(2); | ||
708 | regmap_update_bits(regmap, NAU8540_REG_MIC_BIAS, | ||
709 | NAU8540_PU_PRE, NAU8540_PU_PRE); | ||
710 | regmap_update_bits(regmap, NAU8540_REG_CLOCK_CTRL, | ||
711 | NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN, | ||
712 | NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN); | ||
713 | /* ADC OSR selection, CLK_ADC = Fs * OSR */ | ||
714 | regmap_update_bits(regmap, NAU8540_REG_ADC_SAMPLE_RATE, | ||
715 | NAU8540_ADC_OSR_MASK, NAU8540_ADC_OSR_64); | ||
716 | } | ||
717 | |||
718 | static int __maybe_unused nau8540_suspend(struct snd_soc_codec *codec) | ||
719 | { | ||
720 | struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec); | ||
721 | |||
722 | regcache_cache_only(nau8540->regmap, true); | ||
723 | regcache_mark_dirty(nau8540->regmap); | ||
724 | |||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | static int __maybe_unused nau8540_resume(struct snd_soc_codec *codec) | ||
729 | { | ||
730 | struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec); | ||
731 | |||
732 | regcache_cache_only(nau8540->regmap, false); | ||
733 | regcache_sync(nau8540->regmap); | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static struct snd_soc_codec_driver nau8540_codec_driver = { | ||
739 | .set_sysclk = nau8540_set_sysclk, | ||
740 | .set_pll = nau8540_set_pll, | ||
741 | .suspend = nau8540_suspend, | ||
742 | .resume = nau8540_resume, | ||
743 | .suspend_bias_off = true, | ||
744 | |||
745 | .component_driver = { | ||
746 | .controls = nau8540_snd_controls, | ||
747 | .num_controls = ARRAY_SIZE(nau8540_snd_controls), | ||
748 | .dapm_widgets = nau8540_dapm_widgets, | ||
749 | .num_dapm_widgets = ARRAY_SIZE(nau8540_dapm_widgets), | ||
750 | .dapm_routes = nau8540_dapm_routes, | ||
751 | .num_dapm_routes = ARRAY_SIZE(nau8540_dapm_routes), | ||
752 | }, | ||
753 | }; | ||
754 | |||
755 | static const struct regmap_config nau8540_regmap_config = { | ||
756 | .val_bits = 16, | ||
757 | .reg_bits = 16, | ||
758 | |||
759 | .max_register = NAU8540_REG_MAX, | ||
760 | .readable_reg = nau8540_readable_reg, | ||
761 | .writeable_reg = nau8540_writeable_reg, | ||
762 | .volatile_reg = nau8540_volatile_reg, | ||
763 | |||
764 | .cache_type = REGCACHE_RBTREE, | ||
765 | .reg_defaults = nau8540_reg_defaults, | ||
766 | .num_reg_defaults = ARRAY_SIZE(nau8540_reg_defaults), | ||
767 | }; | ||
768 | |||
769 | static int nau8540_i2c_probe(struct i2c_client *i2c, | ||
770 | const struct i2c_device_id *id) | ||
771 | { | ||
772 | struct device *dev = &i2c->dev; | ||
773 | struct nau8540 *nau8540 = dev_get_platdata(dev); | ||
774 | int ret, value; | ||
775 | |||
776 | if (!nau8540) { | ||
777 | nau8540 = devm_kzalloc(dev, sizeof(*nau8540), GFP_KERNEL); | ||
778 | if (!nau8540) | ||
779 | return -ENOMEM; | ||
780 | } | ||
781 | i2c_set_clientdata(i2c, nau8540); | ||
782 | |||
783 | nau8540->regmap = devm_regmap_init_i2c(i2c, &nau8540_regmap_config); | ||
784 | if (IS_ERR(nau8540->regmap)) | ||
785 | return PTR_ERR(nau8540->regmap); | ||
786 | ret = regmap_read(nau8540->regmap, NAU8540_REG_I2C_DEVICE_ID, &value); | ||
787 | if (ret < 0) { | ||
788 | dev_err(dev, "Failed to read device id from the NAU85L40: %d\n", | ||
789 | ret); | ||
790 | return ret; | ||
791 | } | ||
792 | |||
793 | nau8540->dev = dev; | ||
794 | nau8540_reset_chip(nau8540->regmap); | ||
795 | nau8540_init_regs(nau8540); | ||
796 | |||
797 | return snd_soc_register_codec(dev, | ||
798 | &nau8540_codec_driver, &nau8540_dai, 1); | ||
799 | } | ||
800 | |||
801 | static int nau8540_i2c_remove(struct i2c_client *client) | ||
802 | { | ||
803 | snd_soc_unregister_codec(&client->dev); | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | |||
808 | static const struct i2c_device_id nau8540_i2c_ids[] = { | ||
809 | { "nau8540", 0 }, | ||
810 | { } | ||
811 | }; | ||
812 | MODULE_DEVICE_TABLE(i2c, nau8540_i2c_ids); | ||
813 | |||
814 | #ifdef CONFIG_OF | ||
815 | static const struct of_device_id nau8540_of_ids[] = { | ||
816 | { .compatible = "nuvoton,nau8540", }, | ||
817 | {} | ||
818 | }; | ||
819 | MODULE_DEVICE_TABLE(of, nau8540_of_ids); | ||
820 | #endif | ||
821 | |||
822 | static struct i2c_driver nau8540_i2c_driver = { | ||
823 | .driver = { | ||
824 | .name = "nau8540", | ||
825 | .of_match_table = of_match_ptr(nau8540_of_ids), | ||
826 | }, | ||
827 | .probe = nau8540_i2c_probe, | ||
828 | .remove = nau8540_i2c_remove, | ||
829 | .id_table = nau8540_i2c_ids, | ||
830 | }; | ||
831 | module_i2c_driver(nau8540_i2c_driver); | ||
832 | |||
833 | MODULE_DESCRIPTION("ASoC NAU85L40 driver"); | ||
834 | MODULE_AUTHOR("John Hsu <KCHSU0@nuvoton.com>"); | ||
835 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/nau8540.h b/sound/soc/codecs/nau8540.h new file mode 100644 index 000000000000..d06e65188cd5 --- /dev/null +++ b/sound/soc/codecs/nau8540.h | |||
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | * NAU85L40 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2016 Nuvoton Technology Corp. | ||
5 | * Author: John Hsu <KCHSU0@nuvoton.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 __NAU8540_H__ | ||
13 | #define __NAU8540_H__ | ||
14 | |||
15 | #define NAU8540_REG_SW_RESET 0x00 | ||
16 | #define NAU8540_REG_POWER_MANAGEMENT 0x01 | ||
17 | #define NAU8540_REG_CLOCK_CTRL 0x02 | ||
18 | #define NAU8540_REG_CLOCK_SRC 0x03 | ||
19 | #define NAU8540_REG_FLL1 0x04 | ||
20 | #define NAU8540_REG_FLL2 0x05 | ||
21 | #define NAU8540_REG_FLL3 0x06 | ||
22 | #define NAU8540_REG_FLL4 0x07 | ||
23 | #define NAU8540_REG_FLL5 0x08 | ||
24 | #define NAU8540_REG_FLL6 0x09 | ||
25 | #define NAU8540_REG_FLL_VCO_RSV 0x0A | ||
26 | #define NAU8540_REG_PCM_CTRL0 0x10 | ||
27 | #define NAU8540_REG_PCM_CTRL1 0x11 | ||
28 | #define NAU8540_REG_PCM_CTRL2 0x12 | ||
29 | #define NAU8540_REG_PCM_CTRL3 0x13 | ||
30 | #define NAU8540_REG_PCM_CTRL4 0x14 | ||
31 | #define NAU8540_REG_ALC_CONTROL_1 0x20 | ||
32 | #define NAU8540_REG_ALC_CONTROL_2 0x21 | ||
33 | #define NAU8540_REG_ALC_CONTROL_3 0x22 | ||
34 | #define NAU8540_REG_ALC_CONTROL_4 0x23 | ||
35 | #define NAU8540_REG_ALC_CONTROL_5 0x24 | ||
36 | #define NAU8540_REG_ALC_GAIN_CH12 0x2D | ||
37 | #define NAU8540_REG_ALC_GAIN_CH34 0x2E | ||
38 | #define NAU8540_REG_ALC_STATUS 0x2F | ||
39 | #define NAU8540_REG_NOTCH_FIL1_CH1 0x30 | ||
40 | #define NAU8540_REG_NOTCH_FIL2_CH1 0x31 | ||
41 | #define NAU8540_REG_NOTCH_FIL1_CH2 0x32 | ||
42 | #define NAU8540_REG_NOTCH_FIL2_CH2 0x33 | ||
43 | #define NAU8540_REG_NOTCH_FIL1_CH3 0x34 | ||
44 | #define NAU8540_REG_NOTCH_FIL2_CH3 0x35 | ||
45 | #define NAU8540_REG_NOTCH_FIL1_CH4 0x36 | ||
46 | #define NAU8540_REG_NOTCH_FIL2_CH4 0x37 | ||
47 | #define NAU8540_REG_HPF_FILTER_CH12 0x38 | ||
48 | #define NAU8540_REG_HPF_FILTER_CH34 0x39 | ||
49 | #define NAU8540_REG_ADC_SAMPLE_RATE 0x3A | ||
50 | #define NAU8540_REG_DIGITAL_GAIN_CH1 0x40 | ||
51 | #define NAU8540_REG_DIGITAL_GAIN_CH2 0x41 | ||
52 | #define NAU8540_REG_DIGITAL_GAIN_CH3 0x42 | ||
53 | #define NAU8540_REG_DIGITAL_GAIN_CH4 0x43 | ||
54 | #define NAU8540_REG_DIGITAL_MUX 0x44 | ||
55 | #define NAU8540_REG_P2P_CH1 0x48 | ||
56 | #define NAU8540_REG_P2P_CH2 0x49 | ||
57 | #define NAU8540_REG_P2P_CH3 0x4A | ||
58 | #define NAU8540_REG_P2P_CH4 0x4B | ||
59 | #define NAU8540_REG_PEAK_CH1 0x4C | ||
60 | #define NAU8540_REG_PEAK_CH2 0x4D | ||
61 | #define NAU8540_REG_PEAK_CH3 0x4E | ||
62 | #define NAU8540_REG_PEAK_CH4 0x4F | ||
63 | #define NAU8540_REG_GPIO_CTRL 0x50 | ||
64 | #define NAU8540_REG_MISC_CTRL 0x51 | ||
65 | #define NAU8540_REG_I2C_CTRL 0x52 | ||
66 | #define NAU8540_REG_I2C_DEVICE_ID 0x58 | ||
67 | #define NAU8540_REG_RST 0x5A | ||
68 | #define NAU8540_REG_VMID_CTRL 0x60 | ||
69 | #define NAU8540_REG_MUTE 0x61 | ||
70 | #define NAU8540_REG_ANALOG_ADC1 0x64 | ||
71 | #define NAU8540_REG_ANALOG_ADC2 0x65 | ||
72 | #define NAU8540_REG_ANALOG_PWR 0x66 | ||
73 | #define NAU8540_REG_MIC_BIAS 0x67 | ||
74 | #define NAU8540_REG_REFERENCE 0x68 | ||
75 | #define NAU8540_REG_FEPGA1 0x69 | ||
76 | #define NAU8540_REG_FEPGA2 0x6A | ||
77 | #define NAU8540_REG_FEPGA3 0x6B | ||
78 | #define NAU8540_REG_FEPGA4 0x6C | ||
79 | #define NAU8540_REG_PWR 0x6D | ||
80 | #define NAU8540_REG_MAX NAU8540_REG_PWR | ||
81 | |||
82 | |||
83 | /* POWER_MANAGEMENT (0x01) */ | ||
84 | #define NAU8540_ADC4_EN (0x1 << 3) | ||
85 | #define NAU8540_ADC3_EN (0x1 << 2) | ||
86 | #define NAU8540_ADC2_EN (0x1 << 1) | ||
87 | #define NAU8540_ADC1_EN 0x1 | ||
88 | |||
89 | /* CLOCK_CTRL (0x02) */ | ||
90 | #define NAU8540_CLK_ADC_EN (0x1 << 15) | ||
91 | #define NAU8540_CLK_I2S_EN (0x1 << 1) | ||
92 | |||
93 | /* CLOCK_SRC (0x03) */ | ||
94 | #define NAU8540_CLK_SRC_SFT 15 | ||
95 | #define NAU8540_CLK_SRC_MASK (1 << NAU8540_CLK_SRC_SFT) | ||
96 | #define NAU8540_CLK_SRC_VCO (1 << NAU8540_CLK_SRC_SFT) | ||
97 | #define NAU8540_CLK_SRC_MCLK (0 << NAU8540_CLK_SRC_SFT) | ||
98 | #define NAU8540_CLK_ADC_SRC_SFT 6 | ||
99 | #define NAU8540_CLK_ADC_SRC_MASK (0x3 << NAU8540_CLK_ADC_SRC_SFT) | ||
100 | #define NAU8540_CLK_MCLK_SRC_MASK 0xf | ||
101 | |||
102 | /* FLL1 (0x04) */ | ||
103 | #define NAU8540_FLL_RATIO_MASK 0x7f | ||
104 | |||
105 | /* FLL3 (0x06) */ | ||
106 | #define NAU8540_FLL_CLK_SRC_SFT 10 | ||
107 | #define NAU8540_FLL_CLK_SRC_MASK (0x3 << NAU8540_FLL_CLK_SRC_SFT) | ||
108 | #define NAU8540_FLL_CLK_SRC_MCLK (0 << NAU8540_FLL_CLK_SRC_SFT) | ||
109 | #define NAU8540_FLL_CLK_SRC_BLK (0x2 << NAU8540_FLL_CLK_SRC_SFT) | ||
110 | #define NAU8540_FLL_CLK_SRC_FS (0x3 << NAU8540_FLL_CLK_SRC_SFT) | ||
111 | #define NAU8540_FLL_INTEGER_MASK 0x3ff | ||
112 | |||
113 | /* FLL4 (0x07) */ | ||
114 | #define NAU8540_FLL_REF_DIV_SFT 10 | ||
115 | #define NAU8540_FLL_REF_DIV_MASK (0x3 << NAU8540_FLL_REF_DIV_SFT) | ||
116 | |||
117 | /* FLL5 (0x08) */ | ||
118 | #define NAU8540_FLL_PDB_DAC_EN (0x1 << 15) | ||
119 | #define NAU8540_FLL_LOOP_FTR_EN (0x1 << 14) | ||
120 | #define NAU8540_FLL_CLK_SW_MASK (0x1 << 13) | ||
121 | #define NAU8540_FLL_CLK_SW_N2 (0x1 << 13) | ||
122 | #define NAU8540_FLL_CLK_SW_REF (0x0 << 13) | ||
123 | #define NAU8540_FLL_FTR_SW_MASK (0x1 << 12) | ||
124 | #define NAU8540_FLL_FTR_SW_ACCU (0x1 << 12) | ||
125 | #define NAU8540_FLL_FTR_SW_FILTER (0x0 << 12) | ||
126 | |||
127 | /* FLL6 (0x9) */ | ||
128 | #define NAU8540_DCO_EN (0x1 << 15) | ||
129 | #define NAU8540_SDM_EN (0x1 << 14) | ||
130 | |||
131 | /* PCM_CTRL0 (0x10) */ | ||
132 | #define NAU8540_I2S_BP_SFT 7 | ||
133 | #define NAU8540_I2S_BP_INV (0x1 << NAU8540_I2S_BP_SFT) | ||
134 | #define NAU8540_I2S_PCMB_SFT 6 | ||
135 | #define NAU8540_I2S_PCMB_EN (0x1 << NAU8540_I2S_PCMB_SFT) | ||
136 | #define NAU8540_I2S_DL_SFT 2 | ||
137 | #define NAU8540_I2S_DL_MASK (0x3 << NAU8540_I2S_DL_SFT) | ||
138 | #define NAU8540_I2S_DL_16 (0 << NAU8540_I2S_DL_SFT) | ||
139 | #define NAU8540_I2S_DL_20 (0x1 << NAU8540_I2S_DL_SFT) | ||
140 | #define NAU8540_I2S_DL_24 (0x2 << NAU8540_I2S_DL_SFT) | ||
141 | #define NAU8540_I2S_DL_32 (0x3 << NAU8540_I2S_DL_SFT) | ||
142 | #define NAU8540_I2S_DF_MASK 0x3 | ||
143 | #define NAU8540_I2S_DF_RIGTH 0 | ||
144 | #define NAU8540_I2S_DF_LEFT 0x1 | ||
145 | #define NAU8540_I2S_DF_I2S 0x2 | ||
146 | #define NAU8540_I2S_DF_PCM_AB 0x3 | ||
147 | |||
148 | /* PCM_CTRL1 (0x11) */ | ||
149 | #define NAU8540_I2S_LRC_DIV_SFT 12 | ||
150 | #define NAU8540_I2S_LRC_DIV_MASK (0x3 << NAU8540_I2S_LRC_DIV_SFT) | ||
151 | #define NAU8540_I2S_DO12_OE (0x1 << 4) | ||
152 | #define NAU8540_I2S_MS_SFT 3 | ||
153 | #define NAU8540_I2S_MS_MASK (0x1 << NAU8540_I2S_MS_SFT) | ||
154 | #define NAU8540_I2S_MS_MASTER (0x1 << NAU8540_I2S_MS_SFT) | ||
155 | #define NAU8540_I2S_MS_SLAVE (0x0 << NAU8540_I2S_MS_SFT) | ||
156 | #define NAU8540_I2S_BLK_DIV_MASK 0x7 | ||
157 | |||
158 | /* PCM_CTRL1 (0x12) */ | ||
159 | #define NAU8540_I2S_DO34_OE (0x1 << 11) | ||
160 | #define NAU8540_I2S_TSLOT_L_MASK 0x3ff | ||
161 | |||
162 | /* PCM_CTRL4 (0x14) */ | ||
163 | #define NAU8540_TDM_MODE (0x1 << 15) | ||
164 | #define NAU8540_TDM_OFFSET_EN (0x1 << 14) | ||
165 | #define NAU8540_TDM_TX_MASK 0xf | ||
166 | |||
167 | /* ADC_SAMPLE_RATE (0x3A) */ | ||
168 | #define NAU8540_ADC_OSR_MASK 0x3 | ||
169 | #define NAU8540_ADC_OSR_256 0x3 | ||
170 | #define NAU8540_ADC_OSR_128 0x2 | ||
171 | #define NAU8540_ADC_OSR_64 0x1 | ||
172 | #define NAU8540_ADC_OSR_32 0x0 | ||
173 | |||
174 | /* VMID_CTRL (0x60) */ | ||
175 | #define NAU8540_VMID_EN (1 << 6) | ||
176 | #define NAU8540_VMID_SEL_SFT 4 | ||
177 | #define NAU8540_VMID_SEL_MASK (0x3 << NAU8540_VMID_SEL_SFT) | ||
178 | |||
179 | /* MIC_BIAS (0x67) */ | ||
180 | #define NAU8540_PU_PRE (0x1 << 8) | ||
181 | |||
182 | /* REFERENCE (0x68) */ | ||
183 | #define NAU8540_PRECHARGE_DIS (0x1 << 13) | ||
184 | #define NAU8540_GLOBAL_BIAS_EN (0x1 << 12) | ||
185 | |||
186 | |||
187 | /* System Clock Source */ | ||
188 | enum { | ||
189 | NAU8540_CLK_DIS, | ||
190 | NAU8540_CLK_MCLK, | ||
191 | NAU8540_CLK_INTERNAL, | ||
192 | NAU8540_CLK_FLL_MCLK, | ||
193 | NAU8540_CLK_FLL_BLK, | ||
194 | NAU8540_CLK_FLL_FS, | ||
195 | }; | ||
196 | |||
197 | struct nau8540 { | ||
198 | struct device *dev; | ||
199 | struct regmap *regmap; | ||
200 | }; | ||
201 | |||
202 | struct nau8540_fll { | ||
203 | int mclk_src; | ||
204 | int ratio; | ||
205 | int fll_frac; | ||
206 | int fll_int; | ||
207 | int clk_ref_div; | ||
208 | }; | ||
209 | |||
210 | struct nau8540_fll_attr { | ||
211 | unsigned int param; | ||
212 | unsigned int val; | ||
213 | }; | ||
214 | |||
215 | /* over sampling rate */ | ||
216 | struct nau8540_osr_attr { | ||
217 | unsigned int osr; | ||
218 | unsigned int clk_src; | ||
219 | }; | ||
220 | |||
221 | |||
222 | #endif /* __NAU8540_H__ */ | ||
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 4576f987a4a5..97fbeba9498f 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c | |||
@@ -1231,7 +1231,7 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream, | |||
1231 | { | 1231 | { |
1232 | struct snd_soc_codec *codec = dai->codec; | 1232 | struct snd_soc_codec *codec = dai->codec; |
1233 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); | 1233 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); |
1234 | unsigned int val_len = 0, osr; | 1234 | unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div; |
1235 | 1235 | ||
1236 | nau8825_sema_acquire(nau8825, 3 * HZ); | 1236 | nau8825_sema_acquire(nau8825, 3 * HZ); |
1237 | 1237 | ||
@@ -1261,6 +1261,24 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream, | |||
1261 | osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT); | 1261 | osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT); |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | /* make BCLK and LRC divde configuration if the codec as master. */ | ||
1265 | regmap_read(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, &ctrl_val); | ||
1266 | if (ctrl_val & NAU8825_I2S_MS_MASTER) { | ||
1267 | /* get the bclk and fs ratio */ | ||
1268 | bclk_fs = snd_soc_params_to_bclk(params) / params_rate(params); | ||
1269 | if (bclk_fs <= 32) | ||
1270 | bclk_div = 2; | ||
1271 | else if (bclk_fs <= 64) | ||
1272 | bclk_div = 1; | ||
1273 | else if (bclk_fs <= 128) | ||
1274 | bclk_div = 0; | ||
1275 | else | ||
1276 | return -EINVAL; | ||
1277 | regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, | ||
1278 | NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK, | ||
1279 | ((bclk_div + 1) << NAU8825_I2S_LRC_DIV_SFT) | bclk_div); | ||
1280 | } | ||
1281 | |||
1264 | switch (params_width(params)) { | 1282 | switch (params_width(params)) { |
1265 | case 16: | 1283 | case 16: |
1266 | val_len |= NAU8825_I2S_DL_16; | 1284 | val_len |= NAU8825_I2S_DL_16; |
diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 39bc02d5bc5d..b9d1207ccef2 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c | |||
@@ -402,10 +402,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
402 | u32 val, mask, shift, reg; | 402 | u32 val, mask, shift, reg; |
403 | unsigned int rate, fmt, ratio, max_ratio; | 403 | unsigned int rate, fmt, ratio, max_ratio; |
404 | int i, min_frame_size; | 404 | int i, min_frame_size; |
405 | snd_pcm_format_t format; | ||
406 | 405 | ||
407 | rate = params_rate(params); | 406 | rate = params_rate(params); |
408 | format = params_format(params); | ||
409 | 407 | ||
410 | ratio = pcm3168a->sysclk / rate; | 408 | ratio = pcm3168a->sysclk / rate; |
411 | 409 | ||
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 7150a407ffd9..d9e96e65e1c4 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c | |||
@@ -1163,6 +1163,13 @@ static const struct dmi_system_id force_combo_jack_table[] = { | |||
1163 | DMI_MATCH(DMI_PRODUCT_NAME, "Broxton P") | 1163 | DMI_MATCH(DMI_PRODUCT_NAME, "Broxton P") |
1164 | } | 1164 | } |
1165 | }, | 1165 | }, |
1166 | { | ||
1167 | .ident = "Intel Gemini Lake", | ||
1168 | .matches = { | ||
1169 | DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp"), | ||
1170 | DMI_MATCH(DMI_PRODUCT_NAME, "Geminilake") | ||
1171 | } | ||
1172 | }, | ||
1166 | { } | 1173 | { } |
1167 | }; | 1174 | }; |
1168 | 1175 | ||
diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index 0901e25d6db6..7ed62e8c80b4 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
24 | #include <linux/miscdevice.h> | ||
25 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
26 | #include <linux/pm_qos.h> | 25 | #include <linux/pm_qos.h> |
27 | #include <linux/sysfs.h> | 26 | #include <linux/sysfs.h> |
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index e29a6defefa0..1584ccc3a87b 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
@@ -995,7 +995,7 @@ static int rt5640_hp_event(struct snd_soc_dapm_widget *w, | |||
995 | 995 | ||
996 | case SND_SOC_DAPM_PRE_PMD: | 996 | case SND_SOC_DAPM_PRE_PMD: |
997 | rt5640->hp_mute = 1; | 997 | rt5640->hp_mute = 1; |
998 | usleep_range(70000, 75000); | 998 | msleep(70); |
999 | break; | 999 | break; |
1000 | 1000 | ||
1001 | default: | 1001 | default: |
@@ -1059,7 +1059,7 @@ static int rt5640_hp_post_event(struct snd_soc_dapm_widget *w, | |||
1059 | switch (event) { | 1059 | switch (event) { |
1060 | case SND_SOC_DAPM_POST_PMU: | 1060 | case SND_SOC_DAPM_POST_PMU: |
1061 | if (!rt5640->hp_mute) | 1061 | if (!rt5640->hp_mute) |
1062 | usleep_range(80000, 85000); | 1062 | msleep(80); |
1063 | 1063 | ||
1064 | break; | 1064 | break; |
1065 | 1065 | ||
@@ -1227,6 +1227,10 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = { | |||
1227 | RT5640_PWR_DAC_L1_BIT, 0, NULL, 0), | 1227 | RT5640_PWR_DAC_L1_BIT, 0, NULL, 0), |
1228 | SND_SOC_DAPM_SUPPLY("DAC R1 Power", RT5640_PWR_DIG1, | 1228 | SND_SOC_DAPM_SUPPLY("DAC R1 Power", RT5640_PWR_DIG1, |
1229 | RT5640_PWR_DAC_R1_BIT, 0, NULL, 0), | 1229 | RT5640_PWR_DAC_R1_BIT, 0, NULL, 0), |
1230 | SND_SOC_DAPM_SUPPLY("DAC L2 Power", RT5640_PWR_DIG1, | ||
1231 | RT5640_PWR_DAC_L2_BIT, 0, NULL, 0), | ||
1232 | SND_SOC_DAPM_SUPPLY("DAC R2 Power", RT5640_PWR_DIG1, | ||
1233 | RT5640_PWR_DAC_R2_BIT, 0, NULL, 0), | ||
1230 | /* SPK/OUT Mixer */ | 1234 | /* SPK/OUT Mixer */ |
1231 | SND_SOC_DAPM_MIXER("SPK MIXL", RT5640_PWR_MIXER, RT5640_PWR_SM_L_BIT, | 1235 | SND_SOC_DAPM_MIXER("SPK MIXL", RT5640_PWR_MIXER, RT5640_PWR_SM_L_BIT, |
1232 | 0, rt5640_spk_l_mix, ARRAY_SIZE(rt5640_spk_l_mix)), | 1236 | 0, rt5640_spk_l_mix, ARRAY_SIZE(rt5640_spk_l_mix)), |
@@ -1322,10 +1326,6 @@ static const struct snd_soc_dapm_widget rt5640_specific_dapm_widgets[] = { | |||
1322 | rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)), | 1326 | rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)), |
1323 | SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1, | 1327 | SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1, |
1324 | RT5640_PWR_MA_BIT, 0, NULL, 0), | 1328 | RT5640_PWR_MA_BIT, 0, NULL, 0), |
1325 | SND_SOC_DAPM_SUPPLY("DAC L2 Power", RT5640_PWR_DIG1, | ||
1326 | RT5640_PWR_DAC_L2_BIT, 0, NULL, 0), | ||
1327 | SND_SOC_DAPM_SUPPLY("DAC R2 Power", RT5640_PWR_DIG1, | ||
1328 | RT5640_PWR_DAC_R2_BIT, 0, NULL, 0), | ||
1329 | 1329 | ||
1330 | SND_SOC_DAPM_OUTPUT("MONOP"), | 1330 | SND_SOC_DAPM_OUTPUT("MONOP"), |
1331 | SND_SOC_DAPM_OUTPUT("MONON"), | 1331 | SND_SOC_DAPM_OUTPUT("MONON"), |
@@ -2313,6 +2313,7 @@ MODULE_DEVICE_TABLE(of, rt5640_of_match); | |||
2313 | #ifdef CONFIG_ACPI | 2313 | #ifdef CONFIG_ACPI |
2314 | static const struct acpi_device_id rt5640_acpi_match[] = { | 2314 | static const struct acpi_device_id rt5640_acpi_match[] = { |
2315 | { "INT33CA", 0 }, | 2315 | { "INT33CA", 0 }, |
2316 | { "10EC3276", 0 }, | ||
2316 | { "10EC5640", 0 }, | 2317 | { "10EC5640", 0 }, |
2317 | { "10EC5642", 0 }, | 2318 | { "10EC5642", 0 }, |
2318 | { "INTCCFFD", 0 }, | 2319 | { "INTCCFFD", 0 }, |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 1ac96ef9ee20..e149f3ce5401 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -3109,7 +3109,7 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) | |||
3109 | unsigned int val; | 3109 | unsigned int val; |
3110 | 3110 | ||
3111 | if (jack_insert) { | 3111 | if (jack_insert) { |
3112 | regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0006); | 3112 | regmap_write(rt5645->regmap, RT5645_CHARGE_PUMP, 0x0e06); |
3113 | 3113 | ||
3114 | /* for jack type detect */ | 3114 | /* for jack type detect */ |
3115 | snd_soc_dapm_force_enable_pin(dapm, "LDO2"); | 3115 | snd_soc_dapm_force_enable_pin(dapm, "LDO2"); |
@@ -3545,8 +3545,10 @@ MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); | |||
3545 | #ifdef CONFIG_ACPI | 3545 | #ifdef CONFIG_ACPI |
3546 | static const struct acpi_device_id rt5645_acpi_match[] = { | 3546 | static const struct acpi_device_id rt5645_acpi_match[] = { |
3547 | { "10EC5645", 0 }, | 3547 | { "10EC5645", 0 }, |
3548 | { "10EC5648", 0 }, | ||
3548 | { "10EC5650", 0 }, | 3549 | { "10EC5650", 0 }, |
3549 | { "10EC5640", 0 }, | 3550 | { "10EC5640", 0 }, |
3551 | { "10EC3270", 0 }, | ||
3550 | {}, | 3552 | {}, |
3551 | }; | 3553 | }; |
3552 | MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match); | 3554 | MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match); |
@@ -3658,8 +3660,14 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3658 | GPIOD_IN); | 3660 | GPIOD_IN); |
3659 | 3661 | ||
3660 | if (IS_ERR(rt5645->gpiod_hp_det)) { | 3662 | if (IS_ERR(rt5645->gpiod_hp_det)) { |
3661 | dev_err(&i2c->dev, "failed to initialize gpiod\n"); | 3663 | dev_info(&i2c->dev, "failed to initialize gpiod\n"); |
3662 | return PTR_ERR(rt5645->gpiod_hp_det); | 3664 | ret = PTR_ERR(rt5645->gpiod_hp_det); |
3665 | /* | ||
3666 | * Continue if optional gpiod is missing, bail for all other | ||
3667 | * errors, including -EPROBE_DEFER | ||
3668 | */ | ||
3669 | if (ret != -ENOENT) | ||
3670 | return ret; | ||
3663 | } | 3671 | } |
3664 | 3672 | ||
3665 | for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++) | 3673 | for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++) |
diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index db54550aed60..1b7060850340 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c | |||
@@ -1150,28 +1150,28 @@ static const char * const rt5659_data_select[] = { | |||
1150 | "L/R", "R/L", "L/L", "R/R" | 1150 | "L/R", "R/L", "L/L", "R/R" |
1151 | }; | 1151 | }; |
1152 | 1152 | ||
1153 | static const SOC_ENUM_SINGLE_DECL(rt5659_if1_01_adc_enum, | 1153 | static SOC_ENUM_SINGLE_DECL(rt5659_if1_01_adc_enum, |
1154 | RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT01_SFT, rt5659_data_select); | 1154 | RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT01_SFT, rt5659_data_select); |
1155 | 1155 | ||
1156 | static const SOC_ENUM_SINGLE_DECL(rt5659_if1_23_adc_enum, | 1156 | static SOC_ENUM_SINGLE_DECL(rt5659_if1_23_adc_enum, |
1157 | RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT23_SFT, rt5659_data_select); | 1157 | RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT23_SFT, rt5659_data_select); |
1158 | 1158 | ||
1159 | static const SOC_ENUM_SINGLE_DECL(rt5659_if1_45_adc_enum, | 1159 | static SOC_ENUM_SINGLE_DECL(rt5659_if1_45_adc_enum, |
1160 | RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT45_SFT, rt5659_data_select); | 1160 | RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT45_SFT, rt5659_data_select); |
1161 | 1161 | ||
1162 | static const SOC_ENUM_SINGLE_DECL(rt5659_if1_67_adc_enum, | 1162 | static SOC_ENUM_SINGLE_DECL(rt5659_if1_67_adc_enum, |
1163 | RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT67_SFT, rt5659_data_select); | 1163 | RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT67_SFT, rt5659_data_select); |
1164 | 1164 | ||
1165 | static const SOC_ENUM_SINGLE_DECL(rt5659_if2_dac_enum, | 1165 | static SOC_ENUM_SINGLE_DECL(rt5659_if2_dac_enum, |
1166 | RT5659_DIG_INF23_DATA, RT5659_IF2_DAC_SEL_SFT, rt5659_data_select); | 1166 | RT5659_DIG_INF23_DATA, RT5659_IF2_DAC_SEL_SFT, rt5659_data_select); |
1167 | 1167 | ||
1168 | static const SOC_ENUM_SINGLE_DECL(rt5659_if2_adc_enum, | 1168 | static SOC_ENUM_SINGLE_DECL(rt5659_if2_adc_enum, |
1169 | RT5659_DIG_INF23_DATA, RT5659_IF2_ADC_SEL_SFT, rt5659_data_select); | 1169 | RT5659_DIG_INF23_DATA, RT5659_IF2_ADC_SEL_SFT, rt5659_data_select); |
1170 | 1170 | ||
1171 | static const SOC_ENUM_SINGLE_DECL(rt5659_if3_dac_enum, | 1171 | static SOC_ENUM_SINGLE_DECL(rt5659_if3_dac_enum, |
1172 | RT5659_DIG_INF23_DATA, RT5659_IF3_DAC_SEL_SFT, rt5659_data_select); | 1172 | RT5659_DIG_INF23_DATA, RT5659_IF3_DAC_SEL_SFT, rt5659_data_select); |
1173 | 1173 | ||
1174 | static const SOC_ENUM_SINGLE_DECL(rt5659_if3_adc_enum, | 1174 | static SOC_ENUM_SINGLE_DECL(rt5659_if3_adc_enum, |
1175 | RT5659_DIG_INF23_DATA, RT5659_IF3_ADC_SEL_SFT, rt5659_data_select); | 1175 | RT5659_DIG_INF23_DATA, RT5659_IF3_ADC_SEL_SFT, rt5659_data_select); |
1176 | 1176 | ||
1177 | static const struct snd_kcontrol_new rt5659_if1_01_adc_swap_mux = | 1177 | static const struct snd_kcontrol_new rt5659_if1_01_adc_swap_mux = |
@@ -1207,31 +1207,31 @@ static unsigned int rt5659_asrc_clk_map_values[] = { | |||
1207 | 0, 1, 2, 3, 5, 6, | 1207 | 0, 1, 2, 3, 5, 6, |
1208 | }; | 1208 | }; |
1209 | 1209 | ||
1210 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 1210 | static SOC_VALUE_ENUM_SINGLE_DECL( |
1211 | rt5659_da_sto_asrc_enum, RT5659_ASRC_2, RT5659_DA_STO_T_SFT, 0x7, | 1211 | rt5659_da_sto_asrc_enum, RT5659_ASRC_2, RT5659_DA_STO_T_SFT, 0x7, |
1212 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); | 1212 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); |
1213 | 1213 | ||
1214 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 1214 | static SOC_VALUE_ENUM_SINGLE_DECL( |
1215 | rt5659_da_monol_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_L_T_SFT, 0x7, | 1215 | rt5659_da_monol_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_L_T_SFT, 0x7, |
1216 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); | 1216 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); |
1217 | 1217 | ||
1218 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 1218 | static SOC_VALUE_ENUM_SINGLE_DECL( |
1219 | rt5659_da_monor_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_R_T_SFT, 0x7, | 1219 | rt5659_da_monor_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_R_T_SFT, 0x7, |
1220 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); | 1220 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); |
1221 | 1221 | ||
1222 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 1222 | static SOC_VALUE_ENUM_SINGLE_DECL( |
1223 | rt5659_ad_sto1_asrc_enum, RT5659_ASRC_2, RT5659_AD_STO1_T_SFT, 0x7, | 1223 | rt5659_ad_sto1_asrc_enum, RT5659_ASRC_2, RT5659_AD_STO1_T_SFT, 0x7, |
1224 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); | 1224 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); |
1225 | 1225 | ||
1226 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 1226 | static SOC_VALUE_ENUM_SINGLE_DECL( |
1227 | rt5659_ad_sto2_asrc_enum, RT5659_ASRC_3, RT5659_AD_STO2_T_SFT, 0x7, | 1227 | rt5659_ad_sto2_asrc_enum, RT5659_ASRC_3, RT5659_AD_STO2_T_SFT, 0x7, |
1228 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); | 1228 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); |
1229 | 1229 | ||
1230 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 1230 | static SOC_VALUE_ENUM_SINGLE_DECL( |
1231 | rt5659_ad_monol_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_L_T_SFT, 0x7, | 1231 | rt5659_ad_monol_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_L_T_SFT, 0x7, |
1232 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); | 1232 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); |
1233 | 1233 | ||
1234 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 1234 | static SOC_VALUE_ENUM_SINGLE_DECL( |
1235 | rt5659_ad_monor_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_R_T_SFT, 0x7, | 1235 | rt5659_ad_monor_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_R_T_SFT, 0x7, |
1236 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); | 1236 | rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); |
1237 | 1237 | ||
@@ -1930,14 +1930,14 @@ static const char * const rt5659_dac2_src[] = { | |||
1930 | "IF1 DAC2", "IF2 DAC", "IF3 DAC", "Mono ADC MIX" | 1930 | "IF1 DAC2", "IF2 DAC", "IF3 DAC", "Mono ADC MIX" |
1931 | }; | 1931 | }; |
1932 | 1932 | ||
1933 | static const SOC_ENUM_SINGLE_DECL( | 1933 | static SOC_ENUM_SINGLE_DECL( |
1934 | rt5659_dac_l2_enum, RT5659_DAC_CTRL, | 1934 | rt5659_dac_l2_enum, RT5659_DAC_CTRL, |
1935 | RT5659_DAC_L2_SEL_SFT, rt5659_dac2_src); | 1935 | RT5659_DAC_L2_SEL_SFT, rt5659_dac2_src); |
1936 | 1936 | ||
1937 | static const struct snd_kcontrol_new rt5659_dac_l2_mux = | 1937 | static const struct snd_kcontrol_new rt5659_dac_l2_mux = |
1938 | SOC_DAPM_ENUM("DAC L2 Source", rt5659_dac_l2_enum); | 1938 | SOC_DAPM_ENUM("DAC L2 Source", rt5659_dac_l2_enum); |
1939 | 1939 | ||
1940 | static const SOC_ENUM_SINGLE_DECL( | 1940 | static SOC_ENUM_SINGLE_DECL( |
1941 | rt5659_dac_r2_enum, RT5659_DAC_CTRL, | 1941 | rt5659_dac_r2_enum, RT5659_DAC_CTRL, |
1942 | RT5659_DAC_R2_SEL_SFT, rt5659_dac2_src); | 1942 | RT5659_DAC_R2_SEL_SFT, rt5659_dac2_src); |
1943 | 1943 | ||
@@ -1951,7 +1951,7 @@ static const char * const rt5659_sto1_adc1_src[] = { | |||
1951 | "DAC MIX", "ADC" | 1951 | "DAC MIX", "ADC" |
1952 | }; | 1952 | }; |
1953 | 1953 | ||
1954 | static const SOC_ENUM_SINGLE_DECL( | 1954 | static SOC_ENUM_SINGLE_DECL( |
1955 | rt5659_sto1_adc1_enum, RT5659_STO1_ADC_MIXER, | 1955 | rt5659_sto1_adc1_enum, RT5659_STO1_ADC_MIXER, |
1956 | RT5659_STO1_ADC1_SRC_SFT, rt5659_sto1_adc1_src); | 1956 | RT5659_STO1_ADC1_SRC_SFT, rt5659_sto1_adc1_src); |
1957 | 1957 | ||
@@ -1964,7 +1964,7 @@ static const char * const rt5659_sto1_adc_src[] = { | |||
1964 | "ADC1", "ADC2" | 1964 | "ADC1", "ADC2" |
1965 | }; | 1965 | }; |
1966 | 1966 | ||
1967 | static const SOC_ENUM_SINGLE_DECL( | 1967 | static SOC_ENUM_SINGLE_DECL( |
1968 | rt5659_sto1_adc_enum, RT5659_STO1_ADC_MIXER, | 1968 | rt5659_sto1_adc_enum, RT5659_STO1_ADC_MIXER, |
1969 | RT5659_STO1_ADC_SRC_SFT, rt5659_sto1_adc_src); | 1969 | RT5659_STO1_ADC_SRC_SFT, rt5659_sto1_adc_src); |
1970 | 1970 | ||
@@ -1977,7 +1977,7 @@ static const char * const rt5659_sto1_adc2_src[] = { | |||
1977 | "DAC MIX", "DMIC" | 1977 | "DAC MIX", "DMIC" |
1978 | }; | 1978 | }; |
1979 | 1979 | ||
1980 | static const SOC_ENUM_SINGLE_DECL( | 1980 | static SOC_ENUM_SINGLE_DECL( |
1981 | rt5659_sto1_adc2_enum, RT5659_STO1_ADC_MIXER, | 1981 | rt5659_sto1_adc2_enum, RT5659_STO1_ADC_MIXER, |
1982 | RT5659_STO1_ADC2_SRC_SFT, rt5659_sto1_adc2_src); | 1982 | RT5659_STO1_ADC2_SRC_SFT, rt5659_sto1_adc2_src); |
1983 | 1983 | ||
@@ -1990,7 +1990,7 @@ static const char * const rt5659_sto1_dmic_src[] = { | |||
1990 | "DMIC1", "DMIC2" | 1990 | "DMIC1", "DMIC2" |
1991 | }; | 1991 | }; |
1992 | 1992 | ||
1993 | static const SOC_ENUM_SINGLE_DECL( | 1993 | static SOC_ENUM_SINGLE_DECL( |
1994 | rt5659_sto1_dmic_enum, RT5659_STO1_ADC_MIXER, | 1994 | rt5659_sto1_dmic_enum, RT5659_STO1_ADC_MIXER, |
1995 | RT5659_STO1_DMIC_SRC_SFT, rt5659_sto1_dmic_src); | 1995 | RT5659_STO1_DMIC_SRC_SFT, rt5659_sto1_dmic_src); |
1996 | 1996 | ||
@@ -2004,7 +2004,7 @@ static const char * const rt5659_mono_adc_l2_src[] = { | |||
2004 | "Mono DAC MIXL", "DMIC" | 2004 | "Mono DAC MIXL", "DMIC" |
2005 | }; | 2005 | }; |
2006 | 2006 | ||
2007 | static const SOC_ENUM_SINGLE_DECL( | 2007 | static SOC_ENUM_SINGLE_DECL( |
2008 | rt5659_mono_adc_l2_enum, RT5659_MONO_ADC_MIXER, | 2008 | rt5659_mono_adc_l2_enum, RT5659_MONO_ADC_MIXER, |
2009 | RT5659_MONO_ADC_L2_SRC_SFT, rt5659_mono_adc_l2_src); | 2009 | RT5659_MONO_ADC_L2_SRC_SFT, rt5659_mono_adc_l2_src); |
2010 | 2010 | ||
@@ -2018,7 +2018,7 @@ static const char * const rt5659_mono_adc_l1_src[] = { | |||
2018 | "Mono DAC MIXL", "ADC" | 2018 | "Mono DAC MIXL", "ADC" |
2019 | }; | 2019 | }; |
2020 | 2020 | ||
2021 | static const SOC_ENUM_SINGLE_DECL( | 2021 | static SOC_ENUM_SINGLE_DECL( |
2022 | rt5659_mono_adc_l1_enum, RT5659_MONO_ADC_MIXER, | 2022 | rt5659_mono_adc_l1_enum, RT5659_MONO_ADC_MIXER, |
2023 | RT5659_MONO_ADC_L1_SRC_SFT, rt5659_mono_adc_l1_src); | 2023 | RT5659_MONO_ADC_L1_SRC_SFT, rt5659_mono_adc_l1_src); |
2024 | 2024 | ||
@@ -2031,14 +2031,14 @@ static const char * const rt5659_mono_adc_src[] = { | |||
2031 | "ADC1 L", "ADC1 R", "ADC2 L", "ADC2 R" | 2031 | "ADC1 L", "ADC1 R", "ADC2 L", "ADC2 R" |
2032 | }; | 2032 | }; |
2033 | 2033 | ||
2034 | static const SOC_ENUM_SINGLE_DECL( | 2034 | static SOC_ENUM_SINGLE_DECL( |
2035 | rt5659_mono_adc_l_enum, RT5659_MONO_ADC_MIXER, | 2035 | rt5659_mono_adc_l_enum, RT5659_MONO_ADC_MIXER, |
2036 | RT5659_MONO_ADC_L_SRC_SFT, rt5659_mono_adc_src); | 2036 | RT5659_MONO_ADC_L_SRC_SFT, rt5659_mono_adc_src); |
2037 | 2037 | ||
2038 | static const struct snd_kcontrol_new rt5659_mono_adc_l_mux = | 2038 | static const struct snd_kcontrol_new rt5659_mono_adc_l_mux = |
2039 | SOC_DAPM_ENUM("Mono ADC L Source", rt5659_mono_adc_l_enum); | 2039 | SOC_DAPM_ENUM("Mono ADC L Source", rt5659_mono_adc_l_enum); |
2040 | 2040 | ||
2041 | static const SOC_ENUM_SINGLE_DECL( | 2041 | static SOC_ENUM_SINGLE_DECL( |
2042 | rt5659_mono_adcr_enum, RT5659_MONO_ADC_MIXER, | 2042 | rt5659_mono_adcr_enum, RT5659_MONO_ADC_MIXER, |
2043 | RT5659_MONO_ADC_R_SRC_SFT, rt5659_mono_adc_src); | 2043 | RT5659_MONO_ADC_R_SRC_SFT, rt5659_mono_adc_src); |
2044 | 2044 | ||
@@ -2051,7 +2051,7 @@ static const char * const rt5659_mono_dmic_l_src[] = { | |||
2051 | "DMIC1 L", "DMIC2 L" | 2051 | "DMIC1 L", "DMIC2 L" |
2052 | }; | 2052 | }; |
2053 | 2053 | ||
2054 | static const SOC_ENUM_SINGLE_DECL( | 2054 | static SOC_ENUM_SINGLE_DECL( |
2055 | rt5659_mono_dmic_l_enum, RT5659_MONO_ADC_MIXER, | 2055 | rt5659_mono_dmic_l_enum, RT5659_MONO_ADC_MIXER, |
2056 | RT5659_MONO_DMIC_L_SRC_SFT, rt5659_mono_dmic_l_src); | 2056 | RT5659_MONO_DMIC_L_SRC_SFT, rt5659_mono_dmic_l_src); |
2057 | 2057 | ||
@@ -2064,7 +2064,7 @@ static const char * const rt5659_mono_adc_r2_src[] = { | |||
2064 | "Mono DAC MIXR", "DMIC" | 2064 | "Mono DAC MIXR", "DMIC" |
2065 | }; | 2065 | }; |
2066 | 2066 | ||
2067 | static const SOC_ENUM_SINGLE_DECL( | 2067 | static SOC_ENUM_SINGLE_DECL( |
2068 | rt5659_mono_adc_r2_enum, RT5659_MONO_ADC_MIXER, | 2068 | rt5659_mono_adc_r2_enum, RT5659_MONO_ADC_MIXER, |
2069 | RT5659_MONO_ADC_R2_SRC_SFT, rt5659_mono_adc_r2_src); | 2069 | RT5659_MONO_ADC_R2_SRC_SFT, rt5659_mono_adc_r2_src); |
2070 | 2070 | ||
@@ -2077,7 +2077,7 @@ static const char * const rt5659_mono_adc_r1_src[] = { | |||
2077 | "Mono DAC MIXR", "ADC" | 2077 | "Mono DAC MIXR", "ADC" |
2078 | }; | 2078 | }; |
2079 | 2079 | ||
2080 | static const SOC_ENUM_SINGLE_DECL( | 2080 | static SOC_ENUM_SINGLE_DECL( |
2081 | rt5659_mono_adc_r1_enum, RT5659_MONO_ADC_MIXER, | 2081 | rt5659_mono_adc_r1_enum, RT5659_MONO_ADC_MIXER, |
2082 | RT5659_MONO_ADC_R1_SRC_SFT, rt5659_mono_adc_r1_src); | 2082 | RT5659_MONO_ADC_R1_SRC_SFT, rt5659_mono_adc_r1_src); |
2083 | 2083 | ||
@@ -2090,7 +2090,7 @@ static const char * const rt5659_mono_dmic_r_src[] = { | |||
2090 | "DMIC1 R", "DMIC2 R" | 2090 | "DMIC1 R", "DMIC2 R" |
2091 | }; | 2091 | }; |
2092 | 2092 | ||
2093 | static const SOC_ENUM_SINGLE_DECL( | 2093 | static SOC_ENUM_SINGLE_DECL( |
2094 | rt5659_mono_dmic_r_enum, RT5659_MONO_ADC_MIXER, | 2094 | rt5659_mono_dmic_r_enum, RT5659_MONO_ADC_MIXER, |
2095 | RT5659_MONO_DMIC_R_SRC_SFT, rt5659_mono_dmic_r_src); | 2095 | RT5659_MONO_DMIC_R_SRC_SFT, rt5659_mono_dmic_r_src); |
2096 | 2096 | ||
@@ -2104,14 +2104,14 @@ static const char * const rt5659_dac1_src[] = { | |||
2104 | "IF1 DAC1", "IF2 DAC", "IF3 DAC" | 2104 | "IF1 DAC1", "IF2 DAC", "IF3 DAC" |
2105 | }; | 2105 | }; |
2106 | 2106 | ||
2107 | static const SOC_ENUM_SINGLE_DECL( | 2107 | static SOC_ENUM_SINGLE_DECL( |
2108 | rt5659_dac_r1_enum, RT5659_AD_DA_MIXER, | 2108 | rt5659_dac_r1_enum, RT5659_AD_DA_MIXER, |
2109 | RT5659_DAC1_R_SEL_SFT, rt5659_dac1_src); | 2109 | RT5659_DAC1_R_SEL_SFT, rt5659_dac1_src); |
2110 | 2110 | ||
2111 | static const struct snd_kcontrol_new rt5659_dac_r1_mux = | 2111 | static const struct snd_kcontrol_new rt5659_dac_r1_mux = |
2112 | SOC_DAPM_ENUM("DAC R1 Source", rt5659_dac_r1_enum); | 2112 | SOC_DAPM_ENUM("DAC R1 Source", rt5659_dac_r1_enum); |
2113 | 2113 | ||
2114 | static const SOC_ENUM_SINGLE_DECL( | 2114 | static SOC_ENUM_SINGLE_DECL( |
2115 | rt5659_dac_l1_enum, RT5659_AD_DA_MIXER, | 2115 | rt5659_dac_l1_enum, RT5659_AD_DA_MIXER, |
2116 | RT5659_DAC1_L_SEL_SFT, rt5659_dac1_src); | 2116 | RT5659_DAC1_L_SEL_SFT, rt5659_dac1_src); |
2117 | 2117 | ||
@@ -2124,14 +2124,14 @@ static const char * const rt5659_dig_dac_mix_src[] = { | |||
2124 | "Stereo DAC Mixer", "Mono DAC Mixer" | 2124 | "Stereo DAC Mixer", "Mono DAC Mixer" |
2125 | }; | 2125 | }; |
2126 | 2126 | ||
2127 | static const SOC_ENUM_SINGLE_DECL( | 2127 | static SOC_ENUM_SINGLE_DECL( |
2128 | rt5659_dig_dac_mixl_enum, RT5659_DIG_MIXER, | 2128 | rt5659_dig_dac_mixl_enum, RT5659_DIG_MIXER, |
2129 | RT5659_DAC_MIX_L_SFT, rt5659_dig_dac_mix_src); | 2129 | RT5659_DAC_MIX_L_SFT, rt5659_dig_dac_mix_src); |
2130 | 2130 | ||
2131 | static const struct snd_kcontrol_new rt5659_dig_dac_mixl_mux = | 2131 | static const struct snd_kcontrol_new rt5659_dig_dac_mixl_mux = |
2132 | SOC_DAPM_ENUM("DAC Digital Mixer L Source", rt5659_dig_dac_mixl_enum); | 2132 | SOC_DAPM_ENUM("DAC Digital Mixer L Source", rt5659_dig_dac_mixl_enum); |
2133 | 2133 | ||
2134 | static const SOC_ENUM_SINGLE_DECL( | 2134 | static SOC_ENUM_SINGLE_DECL( |
2135 | rt5659_dig_dac_mixr_enum, RT5659_DIG_MIXER, | 2135 | rt5659_dig_dac_mixr_enum, RT5659_DIG_MIXER, |
2136 | RT5659_DAC_MIX_R_SFT, rt5659_dig_dac_mix_src); | 2136 | RT5659_DAC_MIX_R_SFT, rt5659_dig_dac_mix_src); |
2137 | 2137 | ||
@@ -2144,14 +2144,14 @@ static const char * const rt5659_alg_dac1_src[] = { | |||
2144 | "DAC", "Stereo DAC Mixer" | 2144 | "DAC", "Stereo DAC Mixer" |
2145 | }; | 2145 | }; |
2146 | 2146 | ||
2147 | static const SOC_ENUM_SINGLE_DECL( | 2147 | static SOC_ENUM_SINGLE_DECL( |
2148 | rt5659_alg_dac_l1_enum, RT5659_A_DAC_MUX, | 2148 | rt5659_alg_dac_l1_enum, RT5659_A_DAC_MUX, |
2149 | RT5659_A_DACL1_SFT, rt5659_alg_dac1_src); | 2149 | RT5659_A_DACL1_SFT, rt5659_alg_dac1_src); |
2150 | 2150 | ||
2151 | static const struct snd_kcontrol_new rt5659_alg_dac_l1_mux = | 2151 | static const struct snd_kcontrol_new rt5659_alg_dac_l1_mux = |
2152 | SOC_DAPM_ENUM("Analog DACL1 Source", rt5659_alg_dac_l1_enum); | 2152 | SOC_DAPM_ENUM("Analog DACL1 Source", rt5659_alg_dac_l1_enum); |
2153 | 2153 | ||
2154 | static const SOC_ENUM_SINGLE_DECL( | 2154 | static SOC_ENUM_SINGLE_DECL( |
2155 | rt5659_alg_dac_r1_enum, RT5659_A_DAC_MUX, | 2155 | rt5659_alg_dac_r1_enum, RT5659_A_DAC_MUX, |
2156 | RT5659_A_DACR1_SFT, rt5659_alg_dac1_src); | 2156 | RT5659_A_DACR1_SFT, rt5659_alg_dac1_src); |
2157 | 2157 | ||
@@ -2164,14 +2164,14 @@ static const char * const rt5659_alg_dac2_src[] = { | |||
2164 | "Stereo DAC Mixer", "Mono DAC Mixer" | 2164 | "Stereo DAC Mixer", "Mono DAC Mixer" |
2165 | }; | 2165 | }; |
2166 | 2166 | ||
2167 | static const SOC_ENUM_SINGLE_DECL( | 2167 | static SOC_ENUM_SINGLE_DECL( |
2168 | rt5659_alg_dac_l2_enum, RT5659_A_DAC_MUX, | 2168 | rt5659_alg_dac_l2_enum, RT5659_A_DAC_MUX, |
2169 | RT5659_A_DACL2_SFT, rt5659_alg_dac2_src); | 2169 | RT5659_A_DACL2_SFT, rt5659_alg_dac2_src); |
2170 | 2170 | ||
2171 | static const struct snd_kcontrol_new rt5659_alg_dac_l2_mux = | 2171 | static const struct snd_kcontrol_new rt5659_alg_dac_l2_mux = |
2172 | SOC_DAPM_ENUM("Analog DAC L2 Source", rt5659_alg_dac_l2_enum); | 2172 | SOC_DAPM_ENUM("Analog DAC L2 Source", rt5659_alg_dac_l2_enum); |
2173 | 2173 | ||
2174 | static const SOC_ENUM_SINGLE_DECL( | 2174 | static SOC_ENUM_SINGLE_DECL( |
2175 | rt5659_alg_dac_r2_enum, RT5659_A_DAC_MUX, | 2175 | rt5659_alg_dac_r2_enum, RT5659_A_DAC_MUX, |
2176 | RT5659_A_DACR2_SFT, rt5659_alg_dac2_src); | 2176 | RT5659_A_DACR2_SFT, rt5659_alg_dac2_src); |
2177 | 2177 | ||
@@ -2184,7 +2184,7 @@ static const char * const rt5659_if2_adc_in_src[] = { | |||
2184 | "IF_ADC1", "IF_ADC2", "DAC_REF", "IF_ADC3" | 2184 | "IF_ADC1", "IF_ADC2", "DAC_REF", "IF_ADC3" |
2185 | }; | 2185 | }; |
2186 | 2186 | ||
2187 | static const SOC_ENUM_SINGLE_DECL( | 2187 | static SOC_ENUM_SINGLE_DECL( |
2188 | rt5659_if2_adc_in_enum, RT5659_DIG_INF23_DATA, | 2188 | rt5659_if2_adc_in_enum, RT5659_DIG_INF23_DATA, |
2189 | RT5659_IF2_ADC_IN_SFT, rt5659_if2_adc_in_src); | 2189 | RT5659_IF2_ADC_IN_SFT, rt5659_if2_adc_in_src); |
2190 | 2190 | ||
@@ -2197,7 +2197,7 @@ static const char * const rt5659_if3_adc_in_src[] = { | |||
2197 | "IF_ADC1", "IF_ADC2", "DAC_REF", "Stereo2_ADC_L/R" | 2197 | "IF_ADC1", "IF_ADC2", "DAC_REF", "Stereo2_ADC_L/R" |
2198 | }; | 2198 | }; |
2199 | 2199 | ||
2200 | static const SOC_ENUM_SINGLE_DECL( | 2200 | static SOC_ENUM_SINGLE_DECL( |
2201 | rt5659_if3_adc_in_enum, RT5659_DIG_INF23_DATA, | 2201 | rt5659_if3_adc_in_enum, RT5659_DIG_INF23_DATA, |
2202 | RT5659_IF3_ADC_IN_SFT, rt5659_if3_adc_in_src); | 2202 | RT5659_IF3_ADC_IN_SFT, rt5659_if3_adc_in_src); |
2203 | 2203 | ||
@@ -2210,14 +2210,14 @@ static const char * const rt5659_pdm_src[] = { | |||
2210 | "Mono DAC", "Stereo DAC" | 2210 | "Mono DAC", "Stereo DAC" |
2211 | }; | 2211 | }; |
2212 | 2212 | ||
2213 | static const SOC_ENUM_SINGLE_DECL( | 2213 | static SOC_ENUM_SINGLE_DECL( |
2214 | rt5659_pdm_l_enum, RT5659_PDM_OUT_CTRL, | 2214 | rt5659_pdm_l_enum, RT5659_PDM_OUT_CTRL, |
2215 | RT5659_PDM1_L_SFT, rt5659_pdm_src); | 2215 | RT5659_PDM1_L_SFT, rt5659_pdm_src); |
2216 | 2216 | ||
2217 | static const struct snd_kcontrol_new rt5659_pdm_l_mux = | 2217 | static const struct snd_kcontrol_new rt5659_pdm_l_mux = |
2218 | SOC_DAPM_ENUM("PDM L Source", rt5659_pdm_l_enum); | 2218 | SOC_DAPM_ENUM("PDM L Source", rt5659_pdm_l_enum); |
2219 | 2219 | ||
2220 | static const SOC_ENUM_SINGLE_DECL( | 2220 | static SOC_ENUM_SINGLE_DECL( |
2221 | rt5659_pdm_r_enum, RT5659_PDM_OUT_CTRL, | 2221 | rt5659_pdm_r_enum, RT5659_PDM_OUT_CTRL, |
2222 | RT5659_PDM1_R_SFT, rt5659_pdm_src); | 2222 | RT5659_PDM1_R_SFT, rt5659_pdm_src); |
2223 | 2223 | ||
@@ -2230,7 +2230,7 @@ static const char * const rt5659_spdif_src[] = { | |||
2230 | "IF1_DAC1", "IF1_DAC2", "IF2_DAC", "IF3_DAC" | 2230 | "IF1_DAC1", "IF1_DAC2", "IF2_DAC", "IF3_DAC" |
2231 | }; | 2231 | }; |
2232 | 2232 | ||
2233 | static const SOC_ENUM_SINGLE_DECL( | 2233 | static SOC_ENUM_SINGLE_DECL( |
2234 | rt5659_spdif_enum, RT5659_SPDIF_CTRL, | 2234 | rt5659_spdif_enum, RT5659_SPDIF_CTRL, |
2235 | RT5659_SPDIF_SEL_SFT, rt5659_spdif_src); | 2235 | RT5659_SPDIF_SEL_SFT, rt5659_spdif_src); |
2236 | 2236 | ||
@@ -2250,7 +2250,7 @@ static const char * const rt5659_rx_adc_data_src[] = { | |||
2250 | "NUL:AD2:DAC:AD1", "NUL:DAC:DAC:AD2", "NUL:DAC:AD2:DAC" | 2250 | "NUL:AD2:DAC:AD1", "NUL:DAC:DAC:AD2", "NUL:DAC:AD2:DAC" |
2251 | }; | 2251 | }; |
2252 | 2252 | ||
2253 | static const SOC_ENUM_SINGLE_DECL( | 2253 | static SOC_ENUM_SINGLE_DECL( |
2254 | rt5659_rx_adc_data_enum, RT5659_TDM_CTRL_2, | 2254 | rt5659_rx_adc_data_enum, RT5659_TDM_CTRL_2, |
2255 | RT5659_ADCDAT_SRC_SFT, rt5659_rx_adc_data_src); | 2255 | RT5659_ADCDAT_SRC_SFT, rt5659_rx_adc_data_src); |
2256 | 2256 | ||
@@ -4018,7 +4018,7 @@ static int rt5659_i2c_probe(struct i2c_client *i2c, | |||
4018 | GPIOD_OUT_HIGH); | 4018 | GPIOD_OUT_HIGH); |
4019 | 4019 | ||
4020 | /* Sleep for 300 ms miniumum */ | 4020 | /* Sleep for 300 ms miniumum */ |
4021 | usleep_range(300000, 350000); | 4021 | msleep(300); |
4022 | 4022 | ||
4023 | rt5659->regmap = devm_regmap_init_i2c(i2c, &rt5659_regmap); | 4023 | rt5659->regmap = devm_regmap_init_i2c(i2c, &rt5659_regmap); |
4024 | if (IS_ERR(rt5659->regmap)) { | 4024 | if (IS_ERR(rt5659->regmap)) { |
@@ -4230,10 +4230,9 @@ static struct acpi_device_id rt5659_acpi_match[] = { | |||
4230 | MODULE_DEVICE_TABLE(acpi, rt5659_acpi_match); | 4230 | MODULE_DEVICE_TABLE(acpi, rt5659_acpi_match); |
4231 | #endif | 4231 | #endif |
4232 | 4232 | ||
4233 | struct i2c_driver rt5659_i2c_driver = { | 4233 | static struct i2c_driver rt5659_i2c_driver = { |
4234 | .driver = { | 4234 | .driver = { |
4235 | .name = "rt5659", | 4235 | .name = "rt5659", |
4236 | .owner = THIS_MODULE, | ||
4237 | .of_match_table = of_match_ptr(rt5659_of_match), | 4236 | .of_match_table = of_match_ptr(rt5659_of_match), |
4238 | .acpi_match_table = ACPI_PTR(rt5659_acpi_match), | 4237 | .acpi_match_table = ACPI_PTR(rt5659_acpi_match), |
4239 | }, | 4238 | }, |
diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c index 76cf76a2e9b6..c93490d77f2a 100644 --- a/sound/soc/codecs/rt5660.c +++ b/sound/soc/codecs/rt5660.c | |||
@@ -526,10 +526,10 @@ static const char * const rt5660_data_select[] = { | |||
526 | "L/R", "R/L", "L/L", "R/R" | 526 | "L/R", "R/L", "L/L", "R/R" |
527 | }; | 527 | }; |
528 | 528 | ||
529 | static const SOC_ENUM_SINGLE_DECL(rt5660_if1_dac_enum, | 529 | static SOC_ENUM_SINGLE_DECL(rt5660_if1_dac_enum, |
530 | RT5660_DIG_INF1_DATA, RT5660_IF1_DAC_IN_SFT, rt5660_data_select); | 530 | RT5660_DIG_INF1_DATA, RT5660_IF1_DAC_IN_SFT, rt5660_data_select); |
531 | 531 | ||
532 | static const SOC_ENUM_SINGLE_DECL(rt5660_if1_adc_enum, | 532 | static SOC_ENUM_SINGLE_DECL(rt5660_if1_adc_enum, |
533 | RT5660_DIG_INF1_DATA, RT5660_IF1_ADC_IN_SFT, rt5660_data_select); | 533 | RT5660_DIG_INF1_DATA, RT5660_IF1_ADC_IN_SFT, rt5660_data_select); |
534 | 534 | ||
535 | static const struct snd_kcontrol_new rt5660_if1_dac_swap_mux = | 535 | static const struct snd_kcontrol_new rt5660_if1_dac_swap_mux = |
@@ -1152,7 +1152,7 @@ static int rt5660_resume(struct snd_soc_codec *codec) | |||
1152 | struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); | 1152 | struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); |
1153 | 1153 | ||
1154 | if (rt5660->pdata.poweroff_codec_in_suspend) | 1154 | if (rt5660->pdata.poweroff_codec_in_suspend) |
1155 | usleep_range(350000, 400000); | 1155 | msleep(350); |
1156 | 1156 | ||
1157 | regcache_cache_only(rt5660->regmap, false); | 1157 | regcache_cache_only(rt5660->regmap, false); |
1158 | regcache_sync(rt5660->regmap); | 1158 | regcache_sync(rt5660->regmap); |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 97bafac3bc15..17d20b99f041 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -2814,6 +2814,7 @@ MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); | |||
2814 | static const struct acpi_device_id rt5670_acpi_match[] = { | 2814 | static const struct acpi_device_id rt5670_acpi_match[] = { |
2815 | { "10EC5670", 0}, | 2815 | { "10EC5670", 0}, |
2816 | { "10EC5672", 0}, | 2816 | { "10EC5672", 0}, |
2817 | { "10EC5640", 0}, /* quirk */ | ||
2817 | { }, | 2818 | { }, |
2818 | }; | 2819 | }; |
2819 | MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); | 2820 | MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); |
diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index ebd0f7c5ad3b..bd51f3655ee3 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
24 | #include <linux/miscdevice.h> | ||
25 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
26 | #include <linux/pm_qos.h> | 25 | #include <linux/pm_qos.h> |
27 | #include <linux/sysfs.h> | 26 | #include <linux/sysfs.h> |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index bb94d50052d7..29bf8c81ae02 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -1393,6 +1393,12 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) | |||
1393 | snd_soc_write(codec, AIC3X_PLL_PROGC_REG, pll_c); | 1393 | snd_soc_write(codec, AIC3X_PLL_PROGC_REG, pll_c); |
1394 | snd_soc_write(codec, AIC3X_PLL_PROGD_REG, pll_d); | 1394 | snd_soc_write(codec, AIC3X_PLL_PROGD_REG, pll_d); |
1395 | } | 1395 | } |
1396 | |||
1397 | /* | ||
1398 | * Delay is needed to reduce pop-noise after syncing back the | ||
1399 | * registers | ||
1400 | */ | ||
1401 | mdelay(50); | ||
1396 | } else { | 1402 | } else { |
1397 | /* | 1403 | /* |
1398 | * Do soft reset to this codec instance in order to clear | 1404 | * Do soft reset to this codec instance in order to clear |
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 0eb5dcf4c29d..4f5f5710b569 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/firmware.h> | 21 | #include <linux/firmware.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
24 | #include <linux/miscdevice.h> | ||
25 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
26 | #include <linux/regulator/consumer.h> | 25 | #include <linux/regulator/consumer.h> |
27 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index e7ab37d0dd32..1fe358e6be61 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -855,6 +855,8 @@ ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2), | |||
855 | ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2), | 855 | ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2), |
856 | ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2), | 856 | ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2), |
857 | 857 | ||
858 | WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), | ||
859 | |||
858 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), | 860 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), |
859 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), | 861 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), |
860 | 862 | ||
@@ -1944,7 +1946,10 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) | |||
1944 | if (ret) | 1946 | if (ret) |
1945 | goto err_adsp2_codec_probe; | 1947 | goto err_adsp2_codec_probe; |
1946 | 1948 | ||
1947 | arizona_init_spk(codec); | 1949 | ret = arizona_init_spk(codec); |
1950 | if (ret < 0) | ||
1951 | return ret; | ||
1952 | |||
1948 | arizona_init_gpio(codec); | 1953 | arizona_init_gpio(codec); |
1949 | arizona_init_notifiers(codec); | 1954 | arizona_init_notifiers(codec); |
1950 | 1955 | ||
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 585fc706c1b0..1bc942152eff 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -778,6 +778,11 @@ SOC_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]), | |||
778 | SOC_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]), | 778 | SOC_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]), |
779 | SOC_ENUM("ASRC RATE 1", arizona_asrc_rate1), | 779 | SOC_ENUM("ASRC RATE 1", arizona_asrc_rate1), |
780 | 780 | ||
781 | WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), | ||
782 | WM_ADSP2_PRELOAD_SWITCH("DSP2", 2), | ||
783 | WM_ADSP2_PRELOAD_SWITCH("DSP3", 3), | ||
784 | WM_ADSP2_PRELOAD_SWITCH("DSP4", 4), | ||
785 | |||
781 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), | 786 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), |
782 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), | 787 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), |
783 | ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE), | 788 | ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE), |
@@ -2279,7 +2284,10 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) | |||
2279 | 2284 | ||
2280 | priv->core.arizona->dapm = dapm; | 2285 | priv->core.arizona->dapm = dapm; |
2281 | 2286 | ||
2282 | arizona_init_spk(codec); | 2287 | ret = arizona_init_spk(codec); |
2288 | if (ret < 0) | ||
2289 | return ret; | ||
2290 | |||
2283 | arizona_init_gpio(codec); | 2291 | arizona_init_gpio(codec); |
2284 | arizona_init_mono(codec); | 2292 | arizona_init_mono(codec); |
2285 | arizona_init_notifiers(codec); | 2293 | arizona_init_notifiers(codec); |
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index e9c0c76ab73b..c7c6f15b0e42 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h | |||
@@ -31,8 +31,8 @@ | |||
31 | 31 | ||
32 | #define WM8731_CACHEREGNUM 10 | 32 | #define WM8731_CACHEREGNUM 10 |
33 | 33 | ||
34 | #define WM8731_SYSCLK_MCLK 0 | ||
34 | #define WM8731_SYSCLK_XTAL 1 | 35 | #define WM8731_SYSCLK_XTAL 1 |
35 | #define WM8731_SYSCLK_MCLK 2 | ||
36 | 36 | ||
37 | #define WM8731_DAI 0 | 37 | #define WM8731_DAI 0 |
38 | 38 | ||
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 565d477cd790..b8c1940f2243 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -37,8 +37,6 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { | |||
37 | "DVDD", | 37 | "DVDD", |
38 | }; | 38 | }; |
39 | 39 | ||
40 | #define WM8741_NUM_RATES 6 | ||
41 | |||
42 | /* codec private data */ | 40 | /* codec private data */ |
43 | struct wm8741_priv { | 41 | struct wm8741_priv { |
44 | struct wm8741_platform_data pdata; | 42 | struct wm8741_platform_data pdata; |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 9bdf5447f6f6..d05d76e79c70 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -280,6 +280,7 @@ static const DECLARE_TLV_DB_SCALE(voice_mix_tlv, -1200, 300, 0); | |||
280 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); | 280 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); |
281 | 281 | ||
282 | static const struct snd_kcontrol_new wm8753_snd_controls[] = { | 282 | static const struct snd_kcontrol_new wm8753_snd_controls[] = { |
283 | SOC_SINGLE("Hi-Fi DAC Left/Right channel Swap", WM8753_HIFI, 5, 1, 0), | ||
283 | SOC_DOUBLE_R_TLV("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0, dac_tlv), | 284 | SOC_DOUBLE_R_TLV("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0, dac_tlv), |
284 | 285 | ||
285 | SOC_DOUBLE_R_TLV("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0, | 286 | SOC_DOUBLE_R_TLV("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0, |
@@ -1087,7 +1088,7 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec *codec, | |||
1087 | { | 1088 | { |
1088 | u16 ioctl, hifi; | 1089 | u16 ioctl, hifi; |
1089 | 1090 | ||
1090 | hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f; | 1091 | hifi = snd_soc_read(codec, WM8753_HIFI) & 0x013f; |
1091 | ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae; | 1092 | ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae; |
1092 | 1093 | ||
1093 | /* set master/slave audio interface */ | 1094 | /* set master/slave audio interface */ |
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index ee0c8639c743..49401a8aae64 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c | |||
@@ -1062,8 +1062,12 @@ static int wm8997_codec_probe(struct snd_soc_codec *codec) | |||
1062 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | 1062 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
1063 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); | 1063 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); |
1064 | struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); | 1064 | struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); |
1065 | int ret; | ||
1066 | |||
1067 | ret = arizona_init_spk(codec); | ||
1068 | if (ret < 0) | ||
1069 | return ret; | ||
1065 | 1070 | ||
1066 | arizona_init_spk(codec); | ||
1067 | arizona_init_notifiers(codec); | 1071 | arizona_init_notifiers(codec); |
1068 | 1072 | ||
1069 | snd_soc_component_disable_pin(component, "HAPTICS"); | 1073 | snd_soc_component_disable_pin(component, "HAPTICS"); |
diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 3694f5958d86..44f447136e22 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c | |||
@@ -1321,10 +1321,14 @@ static int wm8998_codec_probe(struct snd_soc_codec *codec) | |||
1321 | struct wm8998_priv *priv = snd_soc_codec_get_drvdata(codec); | 1321 | struct wm8998_priv *priv = snd_soc_codec_get_drvdata(codec); |
1322 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | 1322 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
1323 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); | 1323 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); |
1324 | int ret; | ||
1324 | 1325 | ||
1325 | priv->core.arizona->dapm = dapm; | 1326 | priv->core.arizona->dapm = dapm; |
1326 | 1327 | ||
1327 | arizona_init_spk(codec); | 1328 | ret = arizona_init_spk(codec); |
1329 | if (ret < 0) | ||
1330 | return ret; | ||
1331 | |||
1328 | arizona_init_gpio(codec); | 1332 | arizona_init_gpio(codec); |
1329 | arizona_init_notifiers(codec); | 1333 | arizona_init_notifiers(codec); |
1330 | 1334 | ||
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index d72ccef9e238..d151224ffcca 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -2473,7 +2473,7 @@ static void wm_adsp2_boot_work(struct work_struct *work) | |||
2473 | 2473 | ||
2474 | ret = wm_adsp2_ena(dsp); | 2474 | ret = wm_adsp2_ena(dsp); |
2475 | if (ret != 0) | 2475 | if (ret != 0) |
2476 | goto err_mutex; | 2476 | goto err_mem; |
2477 | 2477 | ||
2478 | ret = wm_adsp_load(dsp); | 2478 | ret = wm_adsp_load(dsp); |
2479 | if (ret != 0) | 2479 | if (ret != 0) |
@@ -2492,14 +2492,14 @@ static void wm_adsp2_boot_work(struct work_struct *work) | |||
2492 | if (ret != 0) | 2492 | if (ret != 0) |
2493 | goto err_ena; | 2493 | goto err_ena; |
2494 | 2494 | ||
2495 | dsp->booted = true; | ||
2496 | |||
2497 | /* Turn DSP back off until we are ready to run */ | 2495 | /* Turn DSP back off until we are ready to run */ |
2498 | ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | 2496 | ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, |
2499 | ADSP2_SYS_ENA, 0); | 2497 | ADSP2_SYS_ENA, 0); |
2500 | if (ret != 0) | 2498 | if (ret != 0) |
2501 | goto err_ena; | 2499 | goto err_ena; |
2502 | 2500 | ||
2501 | dsp->booted = true; | ||
2502 | |||
2503 | mutex_unlock(&dsp->pwr_lock); | 2503 | mutex_unlock(&dsp->pwr_lock); |
2504 | 2504 | ||
2505 | return; | 2505 | return; |
@@ -2507,6 +2507,9 @@ static void wm_adsp2_boot_work(struct work_struct *work) | |||
2507 | err_ena: | 2507 | err_ena: |
2508 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | 2508 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, |
2509 | ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); | 2509 | ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); |
2510 | err_mem: | ||
2511 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | ||
2512 | ADSP2_MEM_ENA, 0); | ||
2510 | err_mutex: | 2513 | err_mutex: |
2511 | mutex_unlock(&dsp->pwr_lock); | 2514 | mutex_unlock(&dsp->pwr_lock); |
2512 | } | 2515 | } |
@@ -2523,6 +2526,43 @@ static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq) | |||
2523 | adsp_err(dsp, "Failed to set clock rate: %d\n", ret); | 2526 | adsp_err(dsp, "Failed to set clock rate: %d\n", ret); |
2524 | } | 2527 | } |
2525 | 2528 | ||
2529 | int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, | ||
2530 | struct snd_ctl_elem_value *ucontrol) | ||
2531 | { | ||
2532 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
2533 | struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); | ||
2534 | |||
2535 | ucontrol->value.integer.value[0] = dsp->preloaded; | ||
2536 | |||
2537 | return 0; | ||
2538 | } | ||
2539 | EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get); | ||
2540 | |||
2541 | int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, | ||
2542 | struct snd_ctl_elem_value *ucontrol) | ||
2543 | { | ||
2544 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
2545 | struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); | ||
2546 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
2547 | struct soc_mixer_control *mc = | ||
2548 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2549 | char preload[32]; | ||
2550 | |||
2551 | snprintf(preload, ARRAY_SIZE(preload), "DSP%d Preload", mc->shift); | ||
2552 | |||
2553 | dsp->preloaded = ucontrol->value.integer.value[0]; | ||
2554 | |||
2555 | if (ucontrol->value.integer.value[0]) | ||
2556 | snd_soc_dapm_force_enable_pin(dapm, preload); | ||
2557 | else | ||
2558 | snd_soc_dapm_disable_pin(dapm, preload); | ||
2559 | |||
2560 | snd_soc_dapm_sync(dapm); | ||
2561 | |||
2562 | return 0; | ||
2563 | } | ||
2564 | EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); | ||
2565 | |||
2526 | int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | 2566 | int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, |
2527 | struct snd_kcontrol *kcontrol, int event, | 2567 | struct snd_kcontrol *kcontrol, int event, |
2528 | unsigned int freq) | 2568 | unsigned int freq) |
@@ -2538,6 +2578,8 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | |||
2538 | queue_work(system_unbound_wq, &dsp->boot_work); | 2578 | queue_work(system_unbound_wq, &dsp->boot_work); |
2539 | break; | 2579 | break; |
2540 | case SND_SOC_DAPM_PRE_PMD: | 2580 | case SND_SOC_DAPM_PRE_PMD: |
2581 | mutex_lock(&dsp->pwr_lock); | ||
2582 | |||
2541 | wm_adsp_debugfs_clear(dsp); | 2583 | wm_adsp_debugfs_clear(dsp); |
2542 | 2584 | ||
2543 | dsp->fw_id = 0; | 2585 | dsp->fw_id = 0; |
@@ -2553,6 +2595,8 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | |||
2553 | 2595 | ||
2554 | wm_adsp_free_alg_regions(dsp); | 2596 | wm_adsp_free_alg_regions(dsp); |
2555 | 2597 | ||
2598 | mutex_unlock(&dsp->pwr_lock); | ||
2599 | |||
2556 | adsp_dbg(dsp, "Shutdown complete\n"); | 2600 | adsp_dbg(dsp, "Shutdown complete\n"); |
2557 | break; | 2601 | break; |
2558 | default: | 2602 | default: |
@@ -2575,8 +2619,12 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
2575 | case SND_SOC_DAPM_POST_PMU: | 2619 | case SND_SOC_DAPM_POST_PMU: |
2576 | flush_work(&dsp->boot_work); | 2620 | flush_work(&dsp->boot_work); |
2577 | 2621 | ||
2578 | if (!dsp->booted) | 2622 | mutex_lock(&dsp->pwr_lock); |
2579 | return -EIO; | 2623 | |
2624 | if (!dsp->booted) { | ||
2625 | ret = -EIO; | ||
2626 | goto err; | ||
2627 | } | ||
2580 | 2628 | ||
2581 | ret = wm_adsp2_ena(dsp); | 2629 | ret = wm_adsp2_ena(dsp); |
2582 | if (ret != 0) | 2630 | if (ret != 0) |
@@ -2594,18 +2642,14 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
2594 | if (ret != 0) | 2642 | if (ret != 0) |
2595 | goto err; | 2643 | goto err; |
2596 | 2644 | ||
2597 | dsp->running = true; | ||
2598 | |||
2599 | mutex_lock(&dsp->pwr_lock); | ||
2600 | |||
2601 | if (wm_adsp_fw[dsp->fw].num_caps != 0) { | 2645 | if (wm_adsp_fw[dsp->fw].num_caps != 0) { |
2602 | ret = wm_adsp_buffer_init(dsp); | 2646 | ret = wm_adsp_buffer_init(dsp); |
2603 | if (ret < 0) { | 2647 | if (ret < 0) |
2604 | mutex_unlock(&dsp->pwr_lock); | ||
2605 | goto err; | 2648 | goto err; |
2606 | } | ||
2607 | } | 2649 | } |
2608 | 2650 | ||
2651 | dsp->running = true; | ||
2652 | |||
2609 | mutex_unlock(&dsp->pwr_lock); | 2653 | mutex_unlock(&dsp->pwr_lock); |
2610 | 2654 | ||
2611 | break; | 2655 | break; |
@@ -2648,16 +2692,23 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
2648 | err: | 2692 | err: |
2649 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | 2693 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, |
2650 | ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); | 2694 | ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); |
2695 | mutex_unlock(&dsp->pwr_lock); | ||
2651 | return ret; | 2696 | return ret; |
2652 | } | 2697 | } |
2653 | EXPORT_SYMBOL_GPL(wm_adsp2_event); | 2698 | EXPORT_SYMBOL_GPL(wm_adsp2_event); |
2654 | 2699 | ||
2655 | int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec) | 2700 | int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec) |
2656 | { | 2701 | { |
2657 | dsp->codec = codec; | 2702 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
2703 | char preload[32]; | ||
2704 | |||
2705 | snprintf(preload, ARRAY_SIZE(preload), "DSP%d Preload", dsp->num); | ||
2706 | snd_soc_dapm_disable_pin(dapm, preload); | ||
2658 | 2707 | ||
2659 | wm_adsp2_init_debugfs(dsp, codec); | 2708 | wm_adsp2_init_debugfs(dsp, codec); |
2660 | 2709 | ||
2710 | dsp->codec = codec; | ||
2711 | |||
2661 | return snd_soc_add_codec_controls(codec, | 2712 | return snd_soc_add_codec_controls(codec, |
2662 | &wm_adsp_fw_controls[dsp->num - 1], | 2713 | &wm_adsp_fw_controls[dsp->num - 1], |
2663 | 1); | 2714 | 1); |
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 411d062c13f2..3706b11053a3 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h | |||
@@ -62,6 +62,7 @@ struct wm_adsp { | |||
62 | int fw; | 62 | int fw; |
63 | int fw_ver; | 63 | int fw_ver; |
64 | 64 | ||
65 | bool preloaded; | ||
65 | bool booted; | 66 | bool booted; |
66 | bool running; | 67 | bool running; |
67 | 68 | ||
@@ -86,7 +87,12 @@ struct wm_adsp { | |||
86 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ | 87 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ |
87 | wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) | 88 | wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) |
88 | 89 | ||
90 | #define WM_ADSP2_PRELOAD_SWITCH(wname, num) \ | ||
91 | SOC_SINGLE_EXT(wname " Preload Switch", SND_SOC_NOPM, num, 1, 0, \ | ||
92 | wm_adsp2_preloader_get, wm_adsp2_preloader_put) | ||
93 | |||
89 | #define WM_ADSP2(wname, num, event_fn) \ | 94 | #define WM_ADSP2(wname, num, event_fn) \ |
95 | SND_SOC_DAPM_SPK(wname " Preload", NULL), \ | ||
90 | { .id = snd_soc_dapm_supply, .name = wname " Preloader", \ | 96 | { .id = snd_soc_dapm_supply, .name = wname " Preloader", \ |
91 | .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ | 97 | .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ |
92 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD, \ | 98 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD, \ |
@@ -110,6 +116,11 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | |||
110 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, | 116 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, |
111 | struct snd_kcontrol *kcontrol, int event); | 117 | struct snd_kcontrol *kcontrol, int event); |
112 | 118 | ||
119 | int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, | ||
120 | struct snd_ctl_elem_value *ucontrol); | ||
121 | int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, | ||
122 | struct snd_ctl_elem_value *ucontrol); | ||
123 | |||
113 | int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream); | 124 | int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream); |
114 | int wm_adsp_compr_free(struct snd_compr_stream *stream); | 125 | int wm_adsp_compr_free(struct snd_compr_stream *stream); |
115 | int wm_adsp_compr_set_params(struct snd_compr_stream *stream, | 126 | int wm_adsp_compr_set_params(struct snd_compr_stream *stream, |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 731fb0d86c6a..7a369e0f2093 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -358,13 +358,20 @@ static struct snd_soc_card evm_soc_card = { | |||
358 | static int davinci_evm_probe(struct platform_device *pdev) | 358 | static int davinci_evm_probe(struct platform_device *pdev) |
359 | { | 359 | { |
360 | struct device_node *np = pdev->dev.of_node; | 360 | struct device_node *np = pdev->dev.of_node; |
361 | const struct of_device_id *match = | 361 | const struct of_device_id *match; |
362 | of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); | 362 | struct snd_soc_dai_link *dai; |
363 | struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data; | ||
364 | struct snd_soc_card_drvdata_davinci *drvdata = NULL; | 363 | struct snd_soc_card_drvdata_davinci *drvdata = NULL; |
365 | struct clk *mclk; | 364 | struct clk *mclk; |
366 | int ret = 0; | 365 | int ret = 0; |
367 | 366 | ||
367 | match = of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); | ||
368 | if (!match) { | ||
369 | dev_err(&pdev->dev, "Error: No device match found\n"); | ||
370 | return -ENODEV; | ||
371 | } | ||
372 | |||
373 | dai = (struct snd_soc_dai_link *) match->data; | ||
374 | |||
368 | evm_soc_card.dai_link = dai; | 375 | evm_soc_card.dai_link = dai; |
369 | 376 | ||
370 | dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0); | 377 | dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0); |
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c index bdf8398cbc81..9c46e4112026 100644 --- a/sound/soc/dwc/designware_i2s.c +++ b/sound/soc/dwc/designware_i2s.c | |||
@@ -121,9 +121,14 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id) | |||
121 | irq_valid = true; | 121 | irq_valid = true; |
122 | } | 122 | } |
123 | 123 | ||
124 | /* Data available. Record mode not supported in PIO mode */ | 124 | /* |
125 | if (isr[i] & ISR_RXDA) | 125 | * Data available. Retrieve samples from FIFO |
126 | * NOTE: Only two channels supported | ||
127 | */ | ||
128 | if ((isr[i] & ISR_RXDA) && (i == 0) && dev->use_pio) { | ||
129 | dw_pcm_pop_rx(dev); | ||
126 | irq_valid = true; | 130 | irq_valid = true; |
131 | } | ||
127 | 132 | ||
128 | /* Error Handling: TX */ | 133 | /* Error Handling: TX */ |
129 | if (isr[i] & ISR_TXFO) { | 134 | if (isr[i] & ISR_TXFO) { |
diff --git a/sound/soc/dwc/designware_pcm.c b/sound/soc/dwc/designware_pcm.c index 4a83a22fa3cb..459ec861e6b6 100644 --- a/sound/soc/dwc/designware_pcm.c +++ b/sound/soc/dwc/designware_pcm.c | |||
@@ -41,10 +41,33 @@ static unsigned int dw_pcm_tx_##sample_bits(struct dw_i2s_dev *dev, \ | |||
41 | return tx_ptr; \ | 41 | return tx_ptr; \ |
42 | } | 42 | } |
43 | 43 | ||
44 | #define dw_pcm_rx_fn(sample_bits) \ | ||
45 | static unsigned int dw_pcm_rx_##sample_bits(struct dw_i2s_dev *dev, \ | ||
46 | struct snd_pcm_runtime *runtime, unsigned int rx_ptr, \ | ||
47 | bool *period_elapsed) \ | ||
48 | { \ | ||
49 | u##sample_bits (*p)[2] = (void *)runtime->dma_area; \ | ||
50 | unsigned int period_pos = rx_ptr % runtime->period_size; \ | ||
51 | int i; \ | ||
52 | \ | ||
53 | for (i = 0; i < dev->fifo_th; i++) { \ | ||
54 | p[rx_ptr][0] = ioread32(dev->i2s_base + LRBR_LTHR(0)); \ | ||
55 | p[rx_ptr][1] = ioread32(dev->i2s_base + RRBR_RTHR(0)); \ | ||
56 | period_pos++; \ | ||
57 | if (++rx_ptr >= runtime->buffer_size) \ | ||
58 | rx_ptr = 0; \ | ||
59 | } \ | ||
60 | *period_elapsed = period_pos >= runtime->period_size; \ | ||
61 | return rx_ptr; \ | ||
62 | } | ||
63 | |||
44 | dw_pcm_tx_fn(16); | 64 | dw_pcm_tx_fn(16); |
45 | dw_pcm_tx_fn(32); | 65 | dw_pcm_tx_fn(32); |
66 | dw_pcm_rx_fn(16); | ||
67 | dw_pcm_rx_fn(32); | ||
46 | 68 | ||
47 | #undef dw_pcm_tx_fn | 69 | #undef dw_pcm_tx_fn |
70 | #undef dw_pcm_rx_fn | ||
48 | 71 | ||
49 | static const struct snd_pcm_hardware dw_pcm_hardware = { | 72 | static const struct snd_pcm_hardware dw_pcm_hardware = { |
50 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 73 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
@@ -57,6 +80,7 @@ static const struct snd_pcm_hardware dw_pcm_hardware = { | |||
57 | .rate_min = 32000, | 80 | .rate_min = 32000, |
58 | .rate_max = 48000, | 81 | .rate_max = 48000, |
59 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 82 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
83 | SNDRV_PCM_FMTBIT_S24_LE | | ||
60 | SNDRV_PCM_FMTBIT_S32_LE, | 84 | SNDRV_PCM_FMTBIT_S32_LE, |
61 | .channels_min = 2, | 85 | .channels_min = 2, |
62 | .channels_max = 2, | 86 | .channels_max = 2, |
@@ -68,27 +92,51 @@ static const struct snd_pcm_hardware dw_pcm_hardware = { | |||
68 | .fifo_size = 16, | 92 | .fifo_size = 16, |
69 | }; | 93 | }; |
70 | 94 | ||
71 | void dw_pcm_push_tx(struct dw_i2s_dev *dev) | 95 | static void dw_pcm_transfer(struct dw_i2s_dev *dev, bool push) |
72 | { | 96 | { |
73 | struct snd_pcm_substream *tx_substream; | 97 | struct snd_pcm_substream *substream; |
74 | bool tx_active, period_elapsed; | 98 | bool active, period_elapsed; |
75 | 99 | ||
76 | rcu_read_lock(); | 100 | rcu_read_lock(); |
77 | tx_substream = rcu_dereference(dev->tx_substream); | 101 | if (push) |
78 | tx_active = tx_substream && snd_pcm_running(tx_substream); | 102 | substream = rcu_dereference(dev->tx_substream); |
79 | if (tx_active) { | 103 | else |
80 | unsigned int tx_ptr = READ_ONCE(dev->tx_ptr); | 104 | substream = rcu_dereference(dev->rx_substream); |
81 | unsigned int new_tx_ptr = dev->tx_fn(dev, tx_substream->runtime, | 105 | active = substream && snd_pcm_running(substream); |
82 | tx_ptr, &period_elapsed); | 106 | if (active) { |
83 | cmpxchg(&dev->tx_ptr, tx_ptr, new_tx_ptr); | 107 | unsigned int ptr; |
108 | unsigned int new_ptr; | ||
109 | |||
110 | if (push) { | ||
111 | ptr = READ_ONCE(dev->tx_ptr); | ||
112 | new_ptr = dev->tx_fn(dev, substream->runtime, ptr, | ||
113 | &period_elapsed); | ||
114 | cmpxchg(&dev->tx_ptr, ptr, new_ptr); | ||
115 | } else { | ||
116 | ptr = READ_ONCE(dev->rx_ptr); | ||
117 | new_ptr = dev->rx_fn(dev, substream->runtime, ptr, | ||
118 | &period_elapsed); | ||
119 | cmpxchg(&dev->rx_ptr, ptr, new_ptr); | ||
120 | } | ||
84 | 121 | ||
85 | if (period_elapsed) | 122 | if (period_elapsed) |
86 | snd_pcm_period_elapsed(tx_substream); | 123 | snd_pcm_period_elapsed(substream); |
87 | } | 124 | } |
88 | rcu_read_unlock(); | 125 | rcu_read_unlock(); |
89 | } | 126 | } |
127 | |||
128 | void dw_pcm_push_tx(struct dw_i2s_dev *dev) | ||
129 | { | ||
130 | dw_pcm_transfer(dev, true); | ||
131 | } | ||
90 | EXPORT_SYMBOL_GPL(dw_pcm_push_tx); | 132 | EXPORT_SYMBOL_GPL(dw_pcm_push_tx); |
91 | 133 | ||
134 | void dw_pcm_pop_rx(struct dw_i2s_dev *dev) | ||
135 | { | ||
136 | dw_pcm_transfer(dev, false); | ||
137 | } | ||
138 | EXPORT_SYMBOL_GPL(dw_pcm_pop_rx); | ||
139 | |||
92 | static int dw_pcm_open(struct snd_pcm_substream *substream) | 140 | static int dw_pcm_open(struct snd_pcm_substream *substream) |
93 | { | 141 | { |
94 | struct snd_pcm_runtime *runtime = substream->runtime; | 142 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -126,20 +174,18 @@ static int dw_pcm_hw_params(struct snd_pcm_substream *substream, | |||
126 | switch (params_format(hw_params)) { | 174 | switch (params_format(hw_params)) { |
127 | case SNDRV_PCM_FORMAT_S16_LE: | 175 | case SNDRV_PCM_FORMAT_S16_LE: |
128 | dev->tx_fn = dw_pcm_tx_16; | 176 | dev->tx_fn = dw_pcm_tx_16; |
177 | dev->rx_fn = dw_pcm_rx_16; | ||
129 | break; | 178 | break; |
179 | case SNDRV_PCM_FORMAT_S24_LE: | ||
130 | case SNDRV_PCM_FORMAT_S32_LE: | 180 | case SNDRV_PCM_FORMAT_S32_LE: |
131 | dev->tx_fn = dw_pcm_tx_32; | 181 | dev->tx_fn = dw_pcm_tx_32; |
182 | dev->rx_fn = dw_pcm_rx_32; | ||
132 | break; | 183 | break; |
133 | default: | 184 | default: |
134 | dev_err(dev->dev, "invalid format\n"); | 185 | dev_err(dev->dev, "invalid format\n"); |
135 | return -EINVAL; | 186 | return -EINVAL; |
136 | } | 187 | } |
137 | 188 | ||
138 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) { | ||
139 | dev_err(dev->dev, "only playback is available\n"); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | ret = snd_pcm_lib_malloc_pages(substream, | 189 | ret = snd_pcm_lib_malloc_pages(substream, |
144 | params_buffer_bytes(hw_params)); | 190 | params_buffer_bytes(hw_params)); |
145 | if (ret < 0) | 191 | if (ret < 0) |
@@ -163,13 +209,21 @@ static int dw_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
163 | case SNDRV_PCM_TRIGGER_START: | 209 | case SNDRV_PCM_TRIGGER_START: |
164 | case SNDRV_PCM_TRIGGER_RESUME: | 210 | case SNDRV_PCM_TRIGGER_RESUME: |
165 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 211 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
166 | WRITE_ONCE(dev->tx_ptr, 0); | 212 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
167 | rcu_assign_pointer(dev->tx_substream, substream); | 213 | WRITE_ONCE(dev->tx_ptr, 0); |
214 | rcu_assign_pointer(dev->tx_substream, substream); | ||
215 | } else { | ||
216 | WRITE_ONCE(dev->rx_ptr, 0); | ||
217 | rcu_assign_pointer(dev->rx_substream, substream); | ||
218 | } | ||
168 | break; | 219 | break; |
169 | case SNDRV_PCM_TRIGGER_STOP: | 220 | case SNDRV_PCM_TRIGGER_STOP: |
170 | case SNDRV_PCM_TRIGGER_SUSPEND: | 221 | case SNDRV_PCM_TRIGGER_SUSPEND: |
171 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 222 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
172 | rcu_assign_pointer(dev->tx_substream, NULL); | 223 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
224 | rcu_assign_pointer(dev->tx_substream, NULL); | ||
225 | else | ||
226 | rcu_assign_pointer(dev->rx_substream, NULL); | ||
173 | break; | 227 | break; |
174 | default: | 228 | default: |
175 | ret = -EINVAL; | 229 | ret = -EINVAL; |
@@ -183,7 +237,12 @@ static snd_pcm_uframes_t dw_pcm_pointer(struct snd_pcm_substream *substream) | |||
183 | { | 237 | { |
184 | struct snd_pcm_runtime *runtime = substream->runtime; | 238 | struct snd_pcm_runtime *runtime = substream->runtime; |
185 | struct dw_i2s_dev *dev = runtime->private_data; | 239 | struct dw_i2s_dev *dev = runtime->private_data; |
186 | snd_pcm_uframes_t pos = READ_ONCE(dev->tx_ptr); | 240 | snd_pcm_uframes_t pos; |
241 | |||
242 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
243 | pos = READ_ONCE(dev->tx_ptr); | ||
244 | else | ||
245 | pos = READ_ONCE(dev->rx_ptr); | ||
187 | 246 | ||
188 | return pos < runtime->buffer_size ? pos : 0; | 247 | return pos < runtime->buffer_size ? pos : 0; |
189 | } | 248 | } |
diff --git a/sound/soc/dwc/local.h b/sound/soc/dwc/local.h index 68afd7577343..91dc70a826f8 100644 --- a/sound/soc/dwc/local.h +++ b/sound/soc/dwc/local.h | |||
@@ -105,20 +105,27 @@ struct dw_i2s_dev { | |||
105 | struct i2s_clk_config_data config; | 105 | struct i2s_clk_config_data config; |
106 | int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); | 106 | int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); |
107 | 107 | ||
108 | /* data related to PIO transfers (TX) */ | 108 | /* data related to PIO transfers */ |
109 | bool use_pio; | 109 | bool use_pio; |
110 | struct snd_pcm_substream __rcu *tx_substream; | 110 | struct snd_pcm_substream __rcu *tx_substream; |
111 | struct snd_pcm_substream __rcu *rx_substream; | ||
111 | unsigned int (*tx_fn)(struct dw_i2s_dev *dev, | 112 | unsigned int (*tx_fn)(struct dw_i2s_dev *dev, |
112 | struct snd_pcm_runtime *runtime, unsigned int tx_ptr, | 113 | struct snd_pcm_runtime *runtime, unsigned int tx_ptr, |
113 | bool *period_elapsed); | 114 | bool *period_elapsed); |
115 | unsigned int (*rx_fn)(struct dw_i2s_dev *dev, | ||
116 | struct snd_pcm_runtime *runtime, unsigned int rx_ptr, | ||
117 | bool *period_elapsed); | ||
114 | unsigned int tx_ptr; | 118 | unsigned int tx_ptr; |
119 | unsigned int rx_ptr; | ||
115 | }; | 120 | }; |
116 | 121 | ||
117 | #if IS_ENABLED(CONFIG_SND_DESIGNWARE_PCM) | 122 | #if IS_ENABLED(CONFIG_SND_DESIGNWARE_PCM) |
118 | void dw_pcm_push_tx(struct dw_i2s_dev *dev); | 123 | void dw_pcm_push_tx(struct dw_i2s_dev *dev); |
124 | void dw_pcm_pop_rx(struct dw_i2s_dev *dev); | ||
119 | int dw_pcm_register(struct platform_device *pdev); | 125 | int dw_pcm_register(struct platform_device *pdev); |
120 | #else | 126 | #else |
121 | void dw_pcm_push_tx(struct dw_i2s_dev *dev) { } | 127 | void dw_pcm_push_tx(struct dw_i2s_dev *dev) { } |
128 | void dw_pcm_pop_rx(struct dw_i2s_dev *dev) { } | ||
122 | int dw_pcm_register(struct platform_device *pdev) | 129 | int dw_pcm_register(struct platform_device *pdev) |
123 | { | 130 | { |
124 | return -EINVAL; | 131 | return -EINVAL; |
diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c index f200d1cfc4bd..667f4215dfc0 100644 --- a/sound/soc/fsl/efika-audio-fabric.c +++ b/sound/soc/fsl/efika-audio-fabric.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
27 | 27 | ||
28 | #include "mpc5200_dma.h" | 28 | #include "mpc5200_dma.h" |
29 | #include "mpc5200_psc_ac97.h" | ||
30 | 29 | ||
31 | #define DRV_NAME "efika-audio-fabric" | 30 | #define DRV_NAME "efika-audio-fabric" |
32 | 31 | ||
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 9fadf7e31c5f..18e5ce81527d 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -668,7 +668,7 @@ static struct snd_soc_dai_driver fsl_sai_dai = { | |||
668 | .playback = { | 668 | .playback = { |
669 | .stream_name = "CPU-Playback", | 669 | .stream_name = "CPU-Playback", |
670 | .channels_min = 1, | 670 | .channels_min = 1, |
671 | .channels_max = 2, | 671 | .channels_max = 32, |
672 | .rate_min = 8000, | 672 | .rate_min = 8000, |
673 | .rate_max = 192000, | 673 | .rate_max = 192000, |
674 | .rates = SNDRV_PCM_RATE_KNOT, | 674 | .rates = SNDRV_PCM_RATE_KNOT, |
@@ -677,7 +677,7 @@ static struct snd_soc_dai_driver fsl_sai_dai = { | |||
677 | .capture = { | 677 | .capture = { |
678 | .stream_name = "CPU-Capture", | 678 | .stream_name = "CPU-Capture", |
679 | .channels_min = 1, | 679 | .channels_min = 1, |
680 | .channels_max = 2, | 680 | .channels_max = 32, |
681 | .rate_min = 8000, | 681 | .rate_min = 8000, |
682 | .rate_max = 192000, | 682 | .rate_max = 192000, |
683 | .rates = SNDRV_PCM_RATE_KNOT, | 683 | .rates = SNDRV_PCM_RATE_KNOT, |
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 243700cc29e6..07ee355ee385 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <asm/mpc52xx_psc.h> | 25 | #include <asm/mpc52xx_psc.h> |
26 | 26 | ||
27 | #include "mpc5200_dma.h" | 27 | #include "mpc5200_dma.h" |
28 | #include "mpc5200_psc_ac97.h" | ||
29 | 28 | ||
30 | #define DRV_NAME "mpc5200-psc-ac97" | 29 | #define DRV_NAME "mpc5200-psc-ac97" |
31 | 30 | ||
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.h b/sound/soc/fsl/mpc5200_psc_ac97.h deleted file mode 100644 index e881e784b270..000000000000 --- a/sound/soc/fsl/mpc5200_psc_ac97.h +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | /* | ||
2 | * Freescale MPC5200 PSC in AC97 mode | ||
3 | * ALSA SoC Digital Audio Interface (DAI) driver | ||
4 | * | ||
5 | */ | ||
6 | |||
7 | #ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ | ||
8 | #define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ | ||
9 | |||
10 | #define MPC5200_AC97_NORMAL 0 | ||
11 | #define MPC5200_AC97_SPDIF 1 | ||
12 | |||
13 | #endif /* __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ */ | ||
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index cf026252cd4a..4924575d2e95 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c | |||
@@ -98,7 +98,8 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card, | |||
98 | } | 98 | } |
99 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name); | 99 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name); |
100 | 100 | ||
101 | int asoc_simple_card_parse_clk(struct device_node *node, | 101 | int asoc_simple_card_parse_clk(struct device *dev, |
102 | struct device_node *node, | ||
102 | struct device_node *dai_of_node, | 103 | struct device_node *dai_of_node, |
103 | struct asoc_simple_dai *simple_dai) | 104 | struct asoc_simple_dai *simple_dai) |
104 | { | 105 | { |
@@ -111,14 +112,13 @@ int asoc_simple_card_parse_clk(struct device_node *node, | |||
111 | * or "system-clock-frequency = <xxx>" | 112 | * or "system-clock-frequency = <xxx>" |
112 | * or device's module clock. | 113 | * or device's module clock. |
113 | */ | 114 | */ |
114 | clk = of_clk_get(node, 0); | 115 | clk = devm_get_clk_from_child(dev, node, NULL); |
115 | if (!IS_ERR(clk)) { | 116 | if (!IS_ERR(clk)) { |
116 | simple_dai->sysclk = clk_get_rate(clk); | 117 | simple_dai->sysclk = clk_get_rate(clk); |
117 | simple_dai->clk = clk; | ||
118 | } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { | 118 | } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { |
119 | simple_dai->sysclk = val; | 119 | simple_dai->sysclk = val; |
120 | } else { | 120 | } else { |
121 | clk = of_clk_get(dai_of_node, 0); | 121 | clk = devm_get_clk_from_child(dev, dai_of_node, NULL); |
122 | if (!IS_ERR(clk)) | 122 | if (!IS_ERR(clk)) |
123 | simple_dai->sysclk = clk_get_rate(clk); | 123 | simple_dai->sysclk = clk_get_rate(clk); |
124 | } | 124 | } |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index a385ff6bfa4b..85b4f1806514 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -278,11 +278,11 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
278 | if (ret < 0) | 278 | if (ret < 0) |
279 | goto dai_link_of_err; | 279 | goto dai_link_of_err; |
280 | 280 | ||
281 | ret = asoc_simple_card_parse_clk_cpu(cpu, dai_link, cpu_dai); | 281 | ret = asoc_simple_card_parse_clk_cpu(dev, cpu, dai_link, cpu_dai); |
282 | if (ret < 0) | 282 | if (ret < 0) |
283 | goto dai_link_of_err; | 283 | goto dai_link_of_err; |
284 | 284 | ||
285 | ret = asoc_simple_card_parse_clk_codec(codec, dai_link, codec_dai); | 285 | ret = asoc_simple_card_parse_clk_codec(dev, codec, dai_link, codec_dai); |
286 | if (ret < 0) | 286 | if (ret < 0) |
287 | goto dai_link_of_err; | 287 | goto dai_link_of_err; |
288 | 288 | ||
diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index bb86ee042490..308ff4c11a8d 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c | |||
@@ -128,7 +128,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, | |||
128 | if (ret) | 128 | if (ret) |
129 | return ret; | 129 | return ret; |
130 | 130 | ||
131 | ret = asoc_simple_card_parse_clk_cpu(np, dai_link, dai_props); | 131 | ret = asoc_simple_card_parse_clk_cpu(dev, np, dai_link, dai_props); |
132 | if (ret < 0) | 132 | if (ret < 0) |
133 | return ret; | 133 | return ret; |
134 | 134 | ||
@@ -153,7 +153,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, | |||
153 | if (ret < 0) | 153 | if (ret < 0) |
154 | return ret; | 154 | return ret; |
155 | 155 | ||
156 | ret = asoc_simple_card_parse_clk_codec(np, dai_link, dai_props); | 156 | ret = asoc_simple_card_parse_clk_codec(dev, np, dai_link, dai_props); |
157 | if (ret < 0) | 157 | if (ret < 0) |
158 | return ret; | 158 | return ret; |
159 | 159 | ||
diff --git a/sound/soc/img/img-parallel-out.c b/sound/soc/img/img-parallel-out.c index c1610a054d65..33ceb207ee70 100644 --- a/sound/soc/img/img-parallel-out.c +++ b/sound/soc/img/img-parallel-out.c | |||
@@ -123,10 +123,8 @@ static int img_prl_out_hw_params(struct snd_pcm_substream *substream, | |||
123 | struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai); | 123 | struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai); |
124 | unsigned int rate, channels; | 124 | unsigned int rate, channels; |
125 | u32 reg, control_set = 0; | 125 | u32 reg, control_set = 0; |
126 | snd_pcm_format_t format; | ||
127 | 126 | ||
128 | rate = params_rate(params); | 127 | rate = params_rate(params); |
129 | format = params_format(params); | ||
130 | channels = params_channels(params); | 128 | channels = params_channels(params); |
131 | 129 | ||
132 | switch (params_format(params)) { | 130 | switch (params_format(params)) { |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index fd5d1e091038..526855ad479e 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -2,7 +2,7 @@ config SND_MFLD_MACHINE | |||
2 | tristate "SOC Machine Audio driver for Intel Medfield MID platform" | 2 | tristate "SOC Machine Audio driver for Intel Medfield MID platform" |
3 | depends on INTEL_SCU_IPC | 3 | depends on INTEL_SCU_IPC |
4 | select SND_SOC_SN95031 | 4 | select SND_SOC_SN95031 |
5 | select SND_SST_MFLD_PLATFORM | 5 | select SND_SST_ATOM_HIFI2_PLATFORM |
6 | select SND_SST_IPC_PCI | 6 | select SND_SST_IPC_PCI |
7 | help | 7 | help |
8 | This adds support for ASoC machine driver for Intel(R) MID Medfield platform | 8 | This adds support for ASoC machine driver for Intel(R) MID Medfield platform |
@@ -10,7 +10,7 @@ config SND_MFLD_MACHINE | |||
10 | Say Y if you have such a device. | 10 | Say Y if you have such a device. |
11 | If unsure select "N". | 11 | If unsure select "N". |
12 | 12 | ||
13 | config SND_SST_MFLD_PLATFORM | 13 | config SND_SST_ATOM_HIFI2_PLATFORM |
14 | tristate | 14 | tristate |
15 | select SND_SOC_COMPRESS | 15 | select SND_SOC_COMPRESS |
16 | 16 | ||
@@ -31,13 +31,10 @@ config SND_SOC_INTEL_SST | |||
31 | tristate | 31 | tristate |
32 | select SND_SOC_INTEL_SST_ACPI if ACPI | 32 | select SND_SOC_INTEL_SST_ACPI if ACPI |
33 | select SND_SOC_INTEL_SST_MATCH if ACPI | 33 | select SND_SOC_INTEL_SST_MATCH if ACPI |
34 | depends on (X86 || COMPILE_TEST) | ||
35 | 34 | ||
36 | # firmware stuff depends DW_DMAC_CORE; since there is no depends-on from | ||
37 | # the reverse selection, each machine driver needs to select | ||
38 | # SND_SOC_INTEL_SST_FIRMWARE carefully depending on DW_DMAC_CORE | ||
39 | config SND_SOC_INTEL_SST_FIRMWARE | 35 | config SND_SOC_INTEL_SST_FIRMWARE |
40 | tristate | 36 | tristate |
37 | select DW_DMAC_CORE | ||
41 | 38 | ||
42 | config SND_SOC_INTEL_SST_ACPI | 39 | config SND_SOC_INTEL_SST_ACPI |
43 | tristate | 40 | tristate |
@@ -47,16 +44,18 @@ config SND_SOC_INTEL_SST_MATCH | |||
47 | 44 | ||
48 | config SND_SOC_INTEL_HASWELL | 45 | config SND_SOC_INTEL_HASWELL |
49 | tristate | 46 | tristate |
47 | select SND_SOC_INTEL_SST | ||
50 | select SND_SOC_INTEL_SST_FIRMWARE | 48 | select SND_SOC_INTEL_SST_FIRMWARE |
51 | 49 | ||
52 | config SND_SOC_INTEL_BAYTRAIL | 50 | config SND_SOC_INTEL_BAYTRAIL |
53 | tristate | 51 | tristate |
52 | select SND_SOC_INTEL_SST | ||
53 | select SND_SOC_INTEL_SST_FIRMWARE | ||
54 | 54 | ||
55 | config SND_SOC_INTEL_HASWELL_MACH | 55 | config SND_SOC_INTEL_HASWELL_MACH |
56 | tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" | 56 | tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" |
57 | depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM | 57 | depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM |
58 | depends on DW_DMAC_CORE | 58 | depends on DMADEVICES |
59 | select SND_SOC_INTEL_SST | ||
60 | select SND_SOC_INTEL_HASWELL | 59 | select SND_SOC_INTEL_HASWELL |
61 | select SND_SOC_RT5640 | 60 | select SND_SOC_RT5640 |
62 | help | 61 | help |
@@ -68,7 +67,6 @@ config SND_SOC_INTEL_HASWELL_MACH | |||
68 | config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH | 67 | config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH |
69 | tristate "ASoC Audio driver for Broxton with DA7219 and MAX98357A in I2S Mode" | 68 | tristate "ASoC Audio driver for Broxton with DA7219 and MAX98357A in I2S Mode" |
70 | depends on X86 && ACPI && I2C | 69 | depends on X86 && ACPI && I2C |
71 | select SND_SOC_INTEL_SST | ||
72 | select SND_SOC_INTEL_SKYLAKE | 70 | select SND_SOC_INTEL_SKYLAKE |
73 | select SND_SOC_DA7219 | 71 | select SND_SOC_DA7219 |
74 | select SND_SOC_MAX98357A | 72 | select SND_SOC_MAX98357A |
@@ -84,7 +82,6 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH | |||
84 | config SND_SOC_INTEL_BXT_RT298_MACH | 82 | config SND_SOC_INTEL_BXT_RT298_MACH |
85 | tristate "ASoC Audio driver for Broxton with RT298 I2S mode" | 83 | tristate "ASoC Audio driver for Broxton with RT298 I2S mode" |
86 | depends on X86 && ACPI && I2C | 84 | depends on X86 && ACPI && I2C |
87 | select SND_SOC_INTEL_SST | ||
88 | select SND_SOC_INTEL_SKYLAKE | 85 | select SND_SOC_INTEL_SKYLAKE |
89 | select SND_SOC_RT298 | 86 | select SND_SOC_RT298 |
90 | select SND_SOC_DMIC | 87 | select SND_SOC_DMIC |
@@ -99,9 +96,8 @@ config SND_SOC_INTEL_BXT_RT298_MACH | |||
99 | config SND_SOC_INTEL_BYT_RT5640_MACH | 96 | config SND_SOC_INTEL_BYT_RT5640_MACH |
100 | tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" | 97 | tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" |
101 | depends on X86_INTEL_LPSS && I2C | 98 | depends on X86_INTEL_LPSS && I2C |
102 | depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n) | 99 | depends on DMADEVICES |
103 | select SND_SOC_INTEL_SST | 100 | depends on SND_SST_IPC_ACPI = n |
104 | select SND_SOC_INTEL_SST_FIRMWARE | ||
105 | select SND_SOC_INTEL_BAYTRAIL | 101 | select SND_SOC_INTEL_BAYTRAIL |
106 | select SND_SOC_RT5640 | 102 | select SND_SOC_RT5640 |
107 | help | 103 | help |
@@ -112,9 +108,8 @@ config SND_SOC_INTEL_BYT_RT5640_MACH | |||
112 | config SND_SOC_INTEL_BYT_MAX98090_MACH | 108 | config SND_SOC_INTEL_BYT_MAX98090_MACH |
113 | tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec" | 109 | tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec" |
114 | depends on X86_INTEL_LPSS && I2C | 110 | depends on X86_INTEL_LPSS && I2C |
115 | depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n) | 111 | depends on DMADEVICES |
116 | select SND_SOC_INTEL_SST | 112 | depends on SND_SST_IPC_ACPI = n |
117 | select SND_SOC_INTEL_SST_FIRMWARE | ||
118 | select SND_SOC_INTEL_BAYTRAIL | 113 | select SND_SOC_INTEL_BAYTRAIL |
119 | select SND_SOC_MAX98090 | 114 | select SND_SOC_MAX98090 |
120 | help | 115 | help |
@@ -123,9 +118,8 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH | |||
123 | 118 | ||
124 | config SND_SOC_INTEL_BDW_RT5677_MACH | 119 | config SND_SOC_INTEL_BDW_RT5677_MACH |
125 | tristate "ASoC Audio driver for Intel Broadwell with RT5677 codec" | 120 | tristate "ASoC Audio driver for Intel Broadwell with RT5677 codec" |
126 | depends on X86_INTEL_LPSS && GPIOLIB && I2C && DW_DMAC | 121 | depends on X86_INTEL_LPSS && GPIOLIB && I2C |
127 | depends on DW_DMAC_CORE=y | 122 | depends on DMADEVICES |
128 | select SND_SOC_INTEL_SST | ||
129 | select SND_SOC_INTEL_HASWELL | 123 | select SND_SOC_INTEL_HASWELL |
130 | select SND_SOC_RT5677 | 124 | select SND_SOC_RT5677 |
131 | help | 125 | help |
@@ -134,10 +128,8 @@ config SND_SOC_INTEL_BDW_RT5677_MACH | |||
134 | 128 | ||
135 | config SND_SOC_INTEL_BROADWELL_MACH | 129 | config SND_SOC_INTEL_BROADWELL_MACH |
136 | tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" | 130 | tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" |
137 | depends on X86_INTEL_LPSS && I2C && DW_DMAC && \ | 131 | depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM |
138 | I2C_DESIGNWARE_PLATFORM | 132 | depends on DMADEVICES |
139 | depends on DW_DMAC_CORE | ||
140 | select SND_SOC_INTEL_SST | ||
141 | select SND_SOC_INTEL_HASWELL | 133 | select SND_SOC_INTEL_HASWELL |
142 | select SND_SOC_RT286 | 134 | select SND_SOC_RT286 |
143 | help | 135 | help |
@@ -150,7 +142,7 @@ config SND_SOC_INTEL_BYTCR_RT5640_MACH | |||
150 | tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec" | 142 | tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec" |
151 | depends on X86 && I2C && ACPI | 143 | depends on X86 && I2C && ACPI |
152 | select SND_SOC_RT5640 | 144 | select SND_SOC_RT5640 |
153 | select SND_SST_MFLD_PLATFORM | 145 | select SND_SST_ATOM_HIFI2_PLATFORM |
154 | select SND_SST_IPC_ACPI | 146 | select SND_SST_IPC_ACPI |
155 | select SND_SOC_INTEL_SST_MATCH if ACPI | 147 | select SND_SOC_INTEL_SST_MATCH if ACPI |
156 | help | 148 | help |
@@ -163,7 +155,7 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH | |||
163 | tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5651 codec" | 155 | tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5651 codec" |
164 | depends on X86 && I2C && ACPI | 156 | depends on X86 && I2C && ACPI |
165 | select SND_SOC_RT5651 | 157 | select SND_SOC_RT5651 |
166 | select SND_SST_MFLD_PLATFORM | 158 | select SND_SST_ATOM_HIFI2_PLATFORM |
167 | select SND_SST_IPC_ACPI | 159 | select SND_SST_IPC_ACPI |
168 | select SND_SOC_INTEL_SST_MATCH if ACPI | 160 | select SND_SOC_INTEL_SST_MATCH if ACPI |
169 | help | 161 | help |
@@ -176,7 +168,7 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH | |||
176 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec" | 168 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec" |
177 | depends on X86_INTEL_LPSS && I2C && ACPI | 169 | depends on X86_INTEL_LPSS && I2C && ACPI |
178 | select SND_SOC_RT5670 | 170 | select SND_SOC_RT5670 |
179 | select SND_SST_MFLD_PLATFORM | 171 | select SND_SST_ATOM_HIFI2_PLATFORM |
180 | select SND_SST_IPC_ACPI | 172 | select SND_SST_IPC_ACPI |
181 | select SND_SOC_INTEL_SST_MATCH if ACPI | 173 | select SND_SOC_INTEL_SST_MATCH if ACPI |
182 | help | 174 | help |
@@ -189,7 +181,7 @@ config SND_SOC_INTEL_CHT_BSW_RT5645_MACH | |||
189 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645/5650 codec" | 181 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645/5650 codec" |
190 | depends on X86_INTEL_LPSS && I2C && ACPI | 182 | depends on X86_INTEL_LPSS && I2C && ACPI |
191 | select SND_SOC_RT5645 | 183 | select SND_SOC_RT5645 |
192 | select SND_SST_MFLD_PLATFORM | 184 | select SND_SST_ATOM_HIFI2_PLATFORM |
193 | select SND_SST_IPC_ACPI | 185 | select SND_SST_IPC_ACPI |
194 | select SND_SOC_INTEL_SST_MATCH if ACPI | 186 | select SND_SOC_INTEL_SST_MATCH if ACPI |
195 | help | 187 | help |
@@ -202,7 +194,7 @@ config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH | |||
202 | depends on X86_INTEL_LPSS && I2C && ACPI | 194 | depends on X86_INTEL_LPSS && I2C && ACPI |
203 | select SND_SOC_MAX98090 | 195 | select SND_SOC_MAX98090 |
204 | select SND_SOC_TS3A227E | 196 | select SND_SOC_TS3A227E |
205 | select SND_SST_MFLD_PLATFORM | 197 | select SND_SST_ATOM_HIFI2_PLATFORM |
206 | select SND_SST_IPC_ACPI | 198 | select SND_SST_IPC_ACPI |
207 | select SND_SOC_INTEL_SST_MATCH if ACPI | 199 | select SND_SOC_INTEL_SST_MATCH if ACPI |
208 | help | 200 | help |
@@ -220,7 +212,6 @@ config SND_SOC_INTEL_SKYLAKE | |||
220 | config SND_SOC_INTEL_SKL_RT286_MACH | 212 | config SND_SOC_INTEL_SKL_RT286_MACH |
221 | tristate "ASoC Audio driver for SKL with RT286 I2S mode" | 213 | tristate "ASoC Audio driver for SKL with RT286 I2S mode" |
222 | depends on X86 && ACPI && I2C | 214 | depends on X86 && ACPI && I2C |
223 | select SND_SOC_INTEL_SST | ||
224 | select SND_SOC_INTEL_SKYLAKE | 215 | select SND_SOC_INTEL_SKYLAKE |
225 | select SND_SOC_RT286 | 216 | select SND_SOC_RT286 |
226 | select SND_SOC_DMIC | 217 | select SND_SOC_DMIC |
@@ -234,7 +225,6 @@ config SND_SOC_INTEL_SKL_RT286_MACH | |||
234 | config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH | 225 | config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH |
235 | tristate "ASoC Audio driver for SKL with NAU88L25 and SSM4567 in I2S Mode" | 226 | tristate "ASoC Audio driver for SKL with NAU88L25 and SSM4567 in I2S Mode" |
236 | depends on X86_INTEL_LPSS && I2C | 227 | depends on X86_INTEL_LPSS && I2C |
237 | select SND_SOC_INTEL_SST | ||
238 | select SND_SOC_INTEL_SKYLAKE | 228 | select SND_SOC_INTEL_SKYLAKE |
239 | select SND_SOC_NAU8825 | 229 | select SND_SOC_NAU8825 |
240 | select SND_SOC_SSM4567 | 230 | select SND_SOC_SSM4567 |
@@ -249,7 +239,6 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH | |||
249 | config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH | 239 | config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH |
250 | tristate "ASoC Audio driver for SKL with NAU88L25 and MAX98357A in I2S Mode" | 240 | tristate "ASoC Audio driver for SKL with NAU88L25 and MAX98357A in I2S Mode" |
251 | depends on X86_INTEL_LPSS && I2C | 241 | depends on X86_INTEL_LPSS && I2C |
252 | select SND_SOC_INTEL_SST | ||
253 | select SND_SOC_INTEL_SKYLAKE | 242 | select SND_SOC_INTEL_SKYLAKE |
254 | select SND_SOC_NAU8825 | 243 | select SND_SOC_NAU8825 |
255 | select SND_SOC_MAX98357A | 244 | select SND_SOC_MAX98357A |
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 2b45435e6245..cdd495f7ee2c 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -4,7 +4,7 @@ obj-$(CONFIG_SND_SOC_INTEL_SST) += common/ | |||
4 | # Platform Support | 4 | # Platform Support |
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_ATOM_HIFI2_PLATFORM) += atom/ |
8 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += skylake/ | 8 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += skylake/ |
9 | 9 | ||
10 | # Machine support | 10 | # Machine support |
diff --git a/sound/soc/intel/atom/Makefile b/sound/soc/intel/atom/Makefile index ce8074fa6d66..aa6548c6feab 100644 --- a/sound/soc/intel/atom/Makefile +++ b/sound/soc/intel/atom/Makefile | |||
@@ -1,7 +1,8 @@ | |||
1 | snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o \ | 1 | snd-soc-sst-atom-hifi2-platform-objs := sst-mfld-platform-pcm.o \ |
2 | sst-mfld-platform-compress.o sst-atom-controls.o | 2 | sst-mfld-platform-compress.o \ |
3 | sst-atom-controls.o | ||
3 | 4 | ||
4 | obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o | 5 | obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += snd-soc-sst-atom-hifi2-platform.o |
5 | 6 | ||
6 | # DSP driver | 7 | # DSP driver |
7 | obj-$(CONFIG_SND_SST_IPC) += sst/ | 8 | obj-$(CONFIG_SND_SST_IPC) += sst/ |
diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index c7b3cbf92faf..0f3604b55942 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c | |||
@@ -801,13 +801,11 @@ static int sst_get_frame_sync_polarity(struct snd_soc_dai *dai, | |||
801 | 801 | ||
802 | switch (format) { | 802 | switch (format) { |
803 | case SND_SOC_DAIFMT_NB_NF: | 803 | case SND_SOC_DAIFMT_NB_NF: |
804 | return SSP_FS_ACTIVE_LOW; | 804 | case SND_SOC_DAIFMT_IB_NF: |
805 | case SND_SOC_DAIFMT_NB_IF: | ||
806 | return SSP_FS_ACTIVE_HIGH; | 805 | return SSP_FS_ACTIVE_HIGH; |
806 | case SND_SOC_DAIFMT_NB_IF: | ||
807 | case SND_SOC_DAIFMT_IB_IF: | 807 | case SND_SOC_DAIFMT_IB_IF: |
808 | return SSP_FS_ACTIVE_LOW; | 808 | return SSP_FS_ACTIVE_LOW; |
809 | case SND_SOC_DAIFMT_IB_NF: | ||
810 | return SSP_FS_ACTIVE_HIGH; | ||
811 | default: | 809 | default: |
812 | dev_err(dai->dev, "Invalid frame sync polarity %d\n", format); | 810 | dev_err(dai->dev, "Invalid frame sync polarity %d\n", format); |
813 | } | 811 | } |
@@ -1087,8 +1085,8 @@ static const struct snd_soc_dapm_widget sst_dapm_widgets[] = { | |||
1087 | SST_PATH_INPUT("sprot_loop_in", SST_TASK_SBA, SST_SWM_IN_SPROT_LOOP, NULL), | 1085 | SST_PATH_INPUT("sprot_loop_in", SST_TASK_SBA, SST_SWM_IN_SPROT_LOOP, NULL), |
1088 | SST_PATH_INPUT("media_loop1_in", SST_TASK_SBA, SST_SWM_IN_MEDIA_LOOP1, NULL), | 1086 | SST_PATH_INPUT("media_loop1_in", SST_TASK_SBA, SST_SWM_IN_MEDIA_LOOP1, NULL), |
1089 | SST_PATH_INPUT("media_loop2_in", SST_TASK_SBA, SST_SWM_IN_MEDIA_LOOP2, NULL), | 1087 | SST_PATH_INPUT("media_loop2_in", SST_TASK_SBA, SST_SWM_IN_MEDIA_LOOP2, NULL), |
1090 | SST_PATH_MEDIA_LOOP_OUTPUT("sprot_loop_out", SST_TASK_SBA, SST_SWM_OUT_SPROT_LOOP, SST_FMT_MONO, sst_set_media_loop), | 1088 | SST_PATH_MEDIA_LOOP_OUTPUT("sprot_loop_out", SST_TASK_SBA, SST_SWM_OUT_SPROT_LOOP, SST_FMT_STEREO, sst_set_media_loop), |
1091 | SST_PATH_MEDIA_LOOP_OUTPUT("media_loop1_out", SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP1, SST_FMT_MONO, sst_set_media_loop), | 1089 | SST_PATH_MEDIA_LOOP_OUTPUT("media_loop1_out", SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP1, SST_FMT_STEREO, sst_set_media_loop), |
1092 | SST_PATH_MEDIA_LOOP_OUTPUT("media_loop2_out", SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP2, SST_FMT_STEREO, sst_set_media_loop), | 1090 | SST_PATH_MEDIA_LOOP_OUTPUT("media_loop2_out", SST_TASK_SBA, SST_SWM_OUT_MEDIA_LOOP2, SST_FMT_STEREO, sst_set_media_loop), |
1093 | 1091 | ||
1094 | /* Media Mixers */ | 1092 | /* Media Mixers */ |
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index f5a8050351b5..21cac1c8dd4c 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c | |||
@@ -357,14 +357,14 @@ static void sst_media_close(struct snd_pcm_substream *substream, | |||
357 | struct snd_soc_dai *dai) | 357 | struct snd_soc_dai *dai) |
358 | { | 358 | { |
359 | struct sst_runtime_stream *stream; | 359 | struct sst_runtime_stream *stream; |
360 | int ret_val = 0, str_id; | 360 | int str_id; |
361 | 361 | ||
362 | stream = substream->runtime->private_data; | 362 | stream = substream->runtime->private_data; |
363 | power_down_sst(stream); | 363 | power_down_sst(stream); |
364 | 364 | ||
365 | str_id = stream->stream_info.str_id; | 365 | str_id = stream->stream_info.str_id; |
366 | if (str_id) | 366 | if (str_id) |
367 | ret_val = stream->ops->close(sst->dev, str_id); | 367 | stream->ops->close(sst->dev, str_id); |
368 | module_put(sst->dev->driver->owner); | 368 | module_put(sst->dev->driver->owner); |
369 | kfree(stream); | 369 | kfree(stream); |
370 | } | 370 | } |
@@ -839,4 +839,5 @@ MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver"); | |||
839 | MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); | 839 | MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); |
840 | MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); | 840 | MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); |
841 | MODULE_LICENSE("GPL v2"); | 841 | MODULE_LICENSE("GPL v2"); |
842 | MODULE_ALIAS("platform:sst-atom-hifi2-platform"); | ||
842 | MODULE_ALIAS("platform:sst-mfld-platform"); | 843 | MODULE_ALIAS("platform:sst-mfld-platform"); |
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index f4d92bbc5373..747c0f393d2d 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c | |||
@@ -400,6 +400,7 @@ static int sst_acpi_remove(struct platform_device *pdev) | |||
400 | static unsigned long cht_machine_id; | 400 | static unsigned long cht_machine_id; |
401 | 401 | ||
402 | #define CHT_SURFACE_MACH 1 | 402 | #define CHT_SURFACE_MACH 1 |
403 | #define BYT_THINKPAD_10 2 | ||
403 | 404 | ||
404 | static int cht_surface_quirk_cb(const struct dmi_system_id *id) | 405 | static int cht_surface_quirk_cb(const struct dmi_system_id *id) |
405 | { | 406 | { |
@@ -407,6 +408,23 @@ static int cht_surface_quirk_cb(const struct dmi_system_id *id) | |||
407 | return 1; | 408 | return 1; |
408 | } | 409 | } |
409 | 410 | ||
411 | static int byt_thinkpad10_quirk_cb(const struct dmi_system_id *id) | ||
412 | { | ||
413 | cht_machine_id = BYT_THINKPAD_10; | ||
414 | return 1; | ||
415 | } | ||
416 | |||
417 | |||
418 | static const struct dmi_system_id byt_table[] = { | ||
419 | { | ||
420 | .callback = byt_thinkpad10_quirk_cb, | ||
421 | .matches = { | ||
422 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
423 | DMI_MATCH(DMI_PRODUCT_NAME, "20C3001VHH"), | ||
424 | }, | ||
425 | }, | ||
426 | { } | ||
427 | }; | ||
410 | 428 | ||
411 | static const struct dmi_system_id cht_table[] = { | 429 | static const struct dmi_system_id cht_table[] = { |
412 | { | 430 | { |
@@ -424,6 +442,10 @@ static struct sst_acpi_mach cht_surface_mach = { | |||
424 | "10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 442 | "10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, |
425 | &chv_platform_data }; | 443 | &chv_platform_data }; |
426 | 444 | ||
445 | static struct sst_acpi_mach byt_thinkpad_10 = { | ||
446 | "10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | ||
447 | &byt_rvp_platform_data }; | ||
448 | |||
427 | static struct sst_acpi_mach *cht_quirk(void *arg) | 449 | static struct sst_acpi_mach *cht_quirk(void *arg) |
428 | { | 450 | { |
429 | struct sst_acpi_mach *mach = arg; | 451 | struct sst_acpi_mach *mach = arg; |
@@ -436,8 +458,21 @@ static struct sst_acpi_mach *cht_quirk(void *arg) | |||
436 | return mach; | 458 | return mach; |
437 | } | 459 | } |
438 | 460 | ||
461 | static struct sst_acpi_mach *byt_quirk(void *arg) | ||
462 | { | ||
463 | struct sst_acpi_mach *mach = arg; | ||
464 | |||
465 | dmi_check_system(byt_table); | ||
466 | |||
467 | if (cht_machine_id == BYT_THINKPAD_10) | ||
468 | return &byt_thinkpad_10; | ||
469 | else | ||
470 | return mach; | ||
471 | } | ||
472 | |||
473 | |||
439 | static struct sst_acpi_mach sst_acpi_bytcr[] = { | 474 | static struct sst_acpi_mach sst_acpi_bytcr[] = { |
440 | {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, | 475 | {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk, |
441 | &byt_rvp_platform_data }, | 476 | &byt_rvp_platform_data }, |
442 | {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, | 477 | {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, |
443 | &byt_rvp_platform_data }, | 478 | &byt_rvp_platform_data }, |
@@ -445,6 +480,12 @@ static struct sst_acpi_mach sst_acpi_bytcr[] = { | |||
445 | &byt_rvp_platform_data }, | 480 | &byt_rvp_platform_data }, |
446 | {"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL, | 481 | {"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL, |
447 | &byt_rvp_platform_data }, | 482 | &byt_rvp_platform_data }, |
483 | /* some Baytrail platforms rely on RT5645, use CHT machine driver */ | ||
484 | {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | ||
485 | &byt_rvp_platform_data }, | ||
486 | {"10EC5648", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | ||
487 | &byt_rvp_platform_data }, | ||
488 | |||
448 | {}, | 489 | {}, |
449 | }; | 490 | }; |
450 | 491 | ||
@@ -458,12 +499,19 @@ static struct sst_acpi_mach sst_acpi_chv[] = { | |||
458 | &chv_platform_data }, | 499 | &chv_platform_data }, |
459 | {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 500 | {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, |
460 | &chv_platform_data }, | 501 | &chv_platform_data }, |
502 | {"10EC3270", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | ||
503 | &chv_platform_data }, | ||
504 | |||
461 | {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 505 | {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, |
462 | &chv_platform_data }, | 506 | &chv_platform_data }, |
463 | /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */ | 507 | /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */ |
464 | {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", cht_quirk, | 508 | {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", cht_quirk, |
465 | &chv_platform_data }, | 509 | &chv_platform_data }, |
466 | 510 | {"10EC3276", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL, | |
511 | &chv_platform_data }, | ||
512 | /* some CHT-T platforms rely on RT5651, use Baytrail machine driver */ | ||
513 | {"10EC5651", "bytcr_rt5651", "intel/fw_sst_22a8.bin", "bytcr_rt5651", NULL, | ||
514 | &chv_platform_data }, | ||
467 | {}, | 515 | {}, |
468 | }; | 516 | }; |
469 | 517 | ||
diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c index 374bb61c596d..14c2d9d18180 100644 --- a/sound/soc/intel/atom/sst/sst_ipc.c +++ b/sound/soc/intel/atom/sst/sst_ipc.c | |||
@@ -260,10 +260,8 @@ static void process_fw_async_msg(struct intel_sst_drv *sst_drv_ctx, | |||
260 | u32 data_size, i; | 260 | u32 data_size, i; |
261 | void *data_offset; | 261 | void *data_offset; |
262 | struct stream_info *stream; | 262 | struct stream_info *stream; |
263 | union ipc_header_high msg_high; | ||
264 | u32 msg_low, pipe_id; | 263 | u32 msg_low, pipe_id; |
265 | 264 | ||
266 | msg_high = msg->mrfld_header.p.header_high; | ||
267 | msg_low = msg->mrfld_header.p.header_low_payload; | 265 | msg_low = msg->mrfld_header.p.header_low_payload; |
268 | msg_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->cmd_id; | 266 | msg_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->cmd_id; |
269 | data_offset = (msg->mailbox_data + sizeof(struct ipc_dsp_hdr)); | 267 | data_offset = (msg->mailbox_data + sizeof(struct ipc_dsp_hdr)); |
diff --git a/sound/soc/intel/atom/sst/sst_stream.c b/sound/soc/intel/atom/sst/sst_stream.c index 51bdeeecb7c8..83d8dda15233 100644 --- a/sound/soc/intel/atom/sst/sst_stream.c +++ b/sound/soc/intel/atom/sst/sst_stream.c | |||
@@ -394,7 +394,6 @@ int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) | |||
394 | { | 394 | { |
395 | int retval = 0; | 395 | int retval = 0; |
396 | struct stream_info *str_info; | 396 | struct stream_info *str_info; |
397 | struct intel_sst_ops *ops; | ||
398 | 397 | ||
399 | dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id); | 398 | dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id); |
400 | 399 | ||
@@ -407,7 +406,6 @@ int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) | |||
407 | str_info = get_stream_info(sst_drv_ctx, str_id); | 406 | str_info = get_stream_info(sst_drv_ctx, str_id); |
408 | if (!str_info) | 407 | if (!str_info) |
409 | return -EINVAL; | 408 | return -EINVAL; |
410 | ops = sst_drv_ctx->ops; | ||
411 | 409 | ||
412 | mutex_lock(&str_info->lock); | 410 | mutex_lock(&str_info->lock); |
413 | if (str_info->status != STREAM_UN_INIT) { | 411 | if (str_info->status != STREAM_UN_INIT) { |
diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 4d7e9decfa92..faf865bb1765 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c | |||
@@ -270,6 +270,8 @@ static int broadwell_audio_probe(struct platform_device *pdev) | |||
270 | { | 270 | { |
271 | broadwell_rt286.dev = &pdev->dev; | 271 | broadwell_rt286.dev = &pdev->dev; |
272 | 272 | ||
273 | snd_soc_set_dmi_name(&broadwell_rt286, NULL); | ||
274 | |||
273 | return devm_snd_soc_register_card(&pdev->dev, &broadwell_rt286); | 275 | return devm_snd_soc_register_card(&pdev->dev, &broadwell_rt286); |
274 | } | 276 | } |
275 | 277 | ||
diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 1b4330cd2739..2cda06cde4d1 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c | |||
@@ -33,6 +33,17 @@ | |||
33 | #define QUAD_CHANNEL 4 | 33 | #define QUAD_CHANNEL 4 |
34 | 34 | ||
35 | static struct snd_soc_jack broxton_headset; | 35 | static struct snd_soc_jack broxton_headset; |
36 | static struct snd_soc_jack broxton_hdmi[3]; | ||
37 | |||
38 | struct bxt_hdmi_pcm { | ||
39 | struct list_head head; | ||
40 | struct snd_soc_dai *codec_dai; | ||
41 | int device; | ||
42 | }; | ||
43 | |||
44 | struct bxt_card_private { | ||
45 | struct list_head hdmi_pcm_list; | ||
46 | }; | ||
36 | 47 | ||
37 | enum { | 48 | enum { |
38 | BXT_DPCM_AUDIO_PB = 0, | 49 | BXT_DPCM_AUDIO_PB = 0, |
@@ -84,9 +95,9 @@ static const struct snd_soc_dapm_route broxton_map[] = { | |||
84 | {"codec0_in", NULL, "ssp1 Rx"}, | 95 | {"codec0_in", NULL, "ssp1 Rx"}, |
85 | {"ssp1 Rx", NULL, "Capture"}, | 96 | {"ssp1 Rx", NULL, "Capture"}, |
86 | 97 | ||
87 | {"HDMI1", NULL, "hif5 Output"}, | 98 | {"HDMI1", NULL, "hif5-0 Output"}, |
88 | {"HDMI2", NULL, "hif6 Output"}, | 99 | {"HDMI2", NULL, "hif6-0 Output"}, |
89 | {"HDMI3", NULL, "hif7 Output"}, | 100 | {"HDMI2", NULL, "hif7-0 Output"}, |
90 | 101 | ||
91 | {"hifi3", NULL, "iDisp3 Tx"}, | 102 | {"hifi3", NULL, "iDisp3 Tx"}, |
92 | {"iDisp3 Tx", NULL, "iDisp3_out"}, | 103 | {"iDisp3 Tx", NULL, "iDisp3_out"}, |
@@ -147,9 +158,20 @@ static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) | |||
147 | 158 | ||
148 | static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) | 159 | static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) |
149 | { | 160 | { |
161 | struct bxt_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
150 | struct snd_soc_dai *dai = rtd->codec_dai; | 162 | struct snd_soc_dai *dai = rtd->codec_dai; |
163 | struct bxt_hdmi_pcm *pcm; | ||
164 | |||
165 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
166 | if (!pcm) | ||
167 | return -ENOMEM; | ||
151 | 168 | ||
152 | return hdac_hdmi_jack_init(dai, BXT_DPCM_AUDIO_HDMI1_PB + dai->id); | 169 | pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id; |
170 | pcm->codec_dai = dai; | ||
171 | |||
172 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
173 | |||
174 | return 0; | ||
153 | } | 175 | } |
154 | 176 | ||
155 | static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) | 177 | static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) |
@@ -357,7 +379,6 @@ static struct snd_soc_dai_link broxton_dais[] = { | |||
357 | .platform_name = "0000:00:0e.0", | 379 | .platform_name = "0000:00:0e.0", |
358 | .init = NULL, | 380 | .init = NULL, |
359 | .dpcm_capture = 1, | 381 | .dpcm_capture = 1, |
360 | .ignore_suspend = 1, | ||
361 | .nonatomic = 1, | 382 | .nonatomic = 1, |
362 | .dynamic = 1, | 383 | .dynamic = 1, |
363 | .ops = &broxton_refcap_ops, | 384 | .ops = &broxton_refcap_ops, |
@@ -497,6 +518,40 @@ static struct snd_soc_dai_link broxton_dais[] = { | |||
497 | }, | 518 | }, |
498 | }; | 519 | }; |
499 | 520 | ||
521 | #define NAME_SIZE 32 | ||
522 | static int bxt_card_late_probe(struct snd_soc_card *card) | ||
523 | { | ||
524 | struct bxt_card_private *ctx = snd_soc_card_get_drvdata(card); | ||
525 | struct bxt_hdmi_pcm *pcm; | ||
526 | struct snd_soc_codec *codec = NULL; | ||
527 | int err, i = 0; | ||
528 | char jack_name[NAME_SIZE]; | ||
529 | |||
530 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | ||
531 | codec = pcm->codec_dai->codec; | ||
532 | snprintf(jack_name, sizeof(jack_name), | ||
533 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
534 | err = snd_soc_card_jack_new(card, jack_name, | ||
535 | SND_JACK_AVOUT, &broxton_hdmi[i], | ||
536 | NULL, 0); | ||
537 | |||
538 | if (err) | ||
539 | return err; | ||
540 | |||
541 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
542 | &broxton_hdmi[i]); | ||
543 | if (err < 0) | ||
544 | return err; | ||
545 | |||
546 | i++; | ||
547 | } | ||
548 | |||
549 | if (!codec) | ||
550 | return -EINVAL; | ||
551 | |||
552 | return hdac_hdmi_jack_port_init(codec, &card->dapm); | ||
553 | } | ||
554 | |||
500 | /* broxton audio machine driver for SPT + da7219 */ | 555 | /* broxton audio machine driver for SPT + da7219 */ |
501 | static struct snd_soc_card broxton_audio_card = { | 556 | static struct snd_soc_card broxton_audio_card = { |
502 | .name = "bxtda7219max", | 557 | .name = "bxtda7219max", |
@@ -510,11 +565,22 @@ static struct snd_soc_card broxton_audio_card = { | |||
510 | .dapm_routes = broxton_map, | 565 | .dapm_routes = broxton_map, |
511 | .num_dapm_routes = ARRAY_SIZE(broxton_map), | 566 | .num_dapm_routes = ARRAY_SIZE(broxton_map), |
512 | .fully_routed = true, | 567 | .fully_routed = true, |
568 | .late_probe = bxt_card_late_probe, | ||
513 | }; | 569 | }; |
514 | 570 | ||
515 | static int broxton_audio_probe(struct platform_device *pdev) | 571 | static int broxton_audio_probe(struct platform_device *pdev) |
516 | { | 572 | { |
573 | struct bxt_card_private *ctx; | ||
574 | |||
575 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); | ||
576 | if (!ctx) | ||
577 | return -ENOMEM; | ||
578 | |||
579 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | ||
580 | |||
517 | broxton_audio_card.dev = &pdev->dev; | 581 | broxton_audio_card.dev = &pdev->dev; |
582 | snd_soc_card_set_drvdata(&broxton_audio_card, ctx); | ||
583 | |||
518 | return devm_snd_soc_register_card(&pdev->dev, &broxton_audio_card); | 584 | return devm_snd_soc_register_card(&pdev->dev, &broxton_audio_card); |
519 | } | 585 | } |
520 | 586 | ||
diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 1309405b3808..176c080a9818 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c | |||
@@ -26,8 +26,19 @@ | |||
26 | #include "../../codecs/hdac_hdmi.h" | 26 | #include "../../codecs/hdac_hdmi.h" |
27 | #include "../../codecs/rt298.h" | 27 | #include "../../codecs/rt298.h" |
28 | 28 | ||
29 | static struct snd_soc_jack broxton_headset; | ||
30 | /* Headset jack detection DAPM pins */ | 29 | /* Headset jack detection DAPM pins */ |
30 | static struct snd_soc_jack broxton_headset; | ||
31 | static struct snd_soc_jack broxton_hdmi[3]; | ||
32 | |||
33 | struct bxt_hdmi_pcm { | ||
34 | struct list_head head; | ||
35 | struct snd_soc_dai *codec_dai; | ||
36 | int device; | ||
37 | }; | ||
38 | |||
39 | struct bxt_rt286_private { | ||
40 | struct list_head hdmi_pcm_list; | ||
41 | }; | ||
31 | 42 | ||
32 | enum { | 43 | enum { |
33 | BXT_DPCM_AUDIO_PB = 0, | 44 | BXT_DPCM_AUDIO_PB = 0, |
@@ -82,9 +93,9 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = { | |||
82 | {"DMIC1 Pin", NULL, "DMIC2"}, | 93 | {"DMIC1 Pin", NULL, "DMIC2"}, |
83 | {"DMic", NULL, "SoC DMIC"}, | 94 | {"DMic", NULL, "SoC DMIC"}, |
84 | 95 | ||
85 | {"HDMI1", NULL, "hif5 Output"}, | 96 | {"HDMI1", NULL, "hif5-0 Output"}, |
86 | {"HDMI2", NULL, "hif6 Output"}, | 97 | {"HDMI2", NULL, "hif6-0 Output"}, |
87 | {"HDMI3", NULL, "hif7 Output"}, | 98 | {"HDMI2", NULL, "hif7-0 Output"}, |
88 | 99 | ||
89 | /* CODEC BE connections */ | 100 | /* CODEC BE connections */ |
90 | { "AIF1 Playback", NULL, "ssp5 Tx"}, | 101 | { "AIF1 Playback", NULL, "ssp5 Tx"}, |
@@ -139,9 +150,20 @@ static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd) | |||
139 | 150 | ||
140 | static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) | 151 | static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) |
141 | { | 152 | { |
153 | struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
142 | struct snd_soc_dai *dai = rtd->codec_dai; | 154 | struct snd_soc_dai *dai = rtd->codec_dai; |
155 | struct bxt_hdmi_pcm *pcm; | ||
143 | 156 | ||
144 | return hdac_hdmi_jack_init(dai, BXT_DPCM_AUDIO_HDMI1_PB + dai->id); | 157 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); |
158 | if (!pcm) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id; | ||
162 | pcm->codec_dai = dai; | ||
163 | |||
164 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
165 | |||
166 | return 0; | ||
145 | } | 167 | } |
146 | 168 | ||
147 | static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime *rtd, | 169 | static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime *rtd, |
@@ -432,6 +454,41 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { | |||
432 | }, | 454 | }, |
433 | }; | 455 | }; |
434 | 456 | ||
457 | #define NAME_SIZE 32 | ||
458 | static int bxt_card_late_probe(struct snd_soc_card *card) | ||
459 | { | ||
460 | struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(card); | ||
461 | struct bxt_hdmi_pcm *pcm; | ||
462 | struct snd_soc_codec *codec = NULL; | ||
463 | int err, i = 0; | ||
464 | char jack_name[NAME_SIZE]; | ||
465 | |||
466 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | ||
467 | codec = pcm->codec_dai->codec; | ||
468 | snprintf(jack_name, sizeof(jack_name), | ||
469 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
470 | err = snd_soc_card_jack_new(card, jack_name, | ||
471 | SND_JACK_AVOUT, &broxton_hdmi[i], | ||
472 | NULL, 0); | ||
473 | |||
474 | if (err) | ||
475 | return err; | ||
476 | |||
477 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
478 | &broxton_hdmi[i]); | ||
479 | if (err < 0) | ||
480 | return err; | ||
481 | |||
482 | i++; | ||
483 | } | ||
484 | |||
485 | if (!codec) | ||
486 | return -EINVAL; | ||
487 | |||
488 | return hdac_hdmi_jack_port_init(codec, &card->dapm); | ||
489 | } | ||
490 | |||
491 | |||
435 | /* broxton audio machine driver for SPT + RT298S */ | 492 | /* broxton audio machine driver for SPT + RT298S */ |
436 | static struct snd_soc_card broxton_rt298 = { | 493 | static struct snd_soc_card broxton_rt298 = { |
437 | .name = "broxton-rt298", | 494 | .name = "broxton-rt298", |
@@ -445,11 +502,22 @@ static struct snd_soc_card broxton_rt298 = { | |||
445 | .dapm_routes = broxton_rt298_map, | 502 | .dapm_routes = broxton_rt298_map, |
446 | .num_dapm_routes = ARRAY_SIZE(broxton_rt298_map), | 503 | .num_dapm_routes = ARRAY_SIZE(broxton_rt298_map), |
447 | .fully_routed = true, | 504 | .fully_routed = true, |
505 | .late_probe = bxt_card_late_probe, | ||
506 | |||
448 | }; | 507 | }; |
449 | 508 | ||
450 | static int broxton_audio_probe(struct platform_device *pdev) | 509 | static int broxton_audio_probe(struct platform_device *pdev) |
451 | { | 510 | { |
511 | struct bxt_rt286_private *ctx; | ||
512 | |||
513 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); | ||
514 | if (!ctx) | ||
515 | return -ENOMEM; | ||
516 | |||
517 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | ||
518 | |||
452 | broxton_rt298.dev = &pdev->dev; | 519 | broxton_rt298.dev = &pdev->dev; |
520 | snd_soc_card_set_drvdata(&broxton_rt298, ctx); | ||
453 | 521 | ||
454 | return devm_snd_soc_register_card(&pdev->dev, &broxton_rt298); | 522 | return devm_snd_soc_register_card(&pdev->dev, &broxton_rt298); |
455 | } | 523 | } |
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 8d2fb2d6f532..5c7219fb3aa8 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c | |||
@@ -387,6 +387,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { | |||
387 | BYT_RT5640_SSP0_AIF1), | 387 | BYT_RT5640_SSP0_AIF1), |
388 | 388 | ||
389 | }, | 389 | }, |
390 | { | ||
391 | .callback = byt_rt5640_quirk_cb, | ||
392 | .matches = { | ||
393 | DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), | ||
394 | }, | ||
395 | .driver_data = (unsigned long *)(BYT_RT5640_IN3_MAP | | ||
396 | BYT_RT5640_MCLK_EN | | ||
397 | BYT_RT5640_SSP0_AIF1), | ||
398 | |||
399 | }, | ||
390 | {} | 400 | {} |
391 | }; | 401 | }; |
392 | 402 | ||
@@ -546,7 +556,7 @@ static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, | |||
546 | */ | 556 | */ |
547 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, | 557 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, |
548 | SND_SOC_DAIFMT_I2S | | 558 | SND_SOC_DAIFMT_I2S | |
549 | SND_SOC_DAIFMT_NB_IF | | 559 | SND_SOC_DAIFMT_NB_NF | |
550 | SND_SOC_DAIFMT_CBS_CFS | 560 | SND_SOC_DAIFMT_CBS_CFS |
551 | ); | 561 | ); |
552 | if (ret < 0) { | 562 | if (ret < 0) { |
@@ -572,7 +582,7 @@ static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, | |||
572 | */ | 582 | */ |
573 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, | 583 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, |
574 | SND_SOC_DAIFMT_I2S | | 584 | SND_SOC_DAIFMT_I2S | |
575 | SND_SOC_DAIFMT_NB_IF | | 585 | SND_SOC_DAIFMT_NB_NF | |
576 | SND_SOC_DAIFMT_CBS_CFS | 586 | SND_SOC_DAIFMT_CBS_CFS |
577 | ); | 587 | ); |
578 | if (ret < 0) { | 588 | if (ret < 0) { |
@@ -856,7 +866,6 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) | |||
856 | static struct platform_driver snd_byt_rt5640_mc_driver = { | 866 | static struct platform_driver snd_byt_rt5640_mc_driver = { |
857 | .driver = { | 867 | .driver = { |
858 | .name = "bytcr_rt5640", | 868 | .name = "bytcr_rt5640", |
859 | .pm = &snd_soc_pm_ops, | ||
860 | }, | 869 | }, |
861 | .probe = snd_byt_rt5640_mc_probe, | 870 | .probe = snd_byt_rt5640_mc_probe, |
862 | }; | 871 | }; |
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 2d24dc04b597..3186f015939f 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c | |||
@@ -185,7 +185,7 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, | |||
185 | */ | 185 | */ |
186 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, | 186 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, |
187 | SND_SOC_DAIFMT_I2S | | 187 | SND_SOC_DAIFMT_I2S | |
188 | SND_SOC_DAIFMT_NB_IF | | 188 | SND_SOC_DAIFMT_NB_NF | |
189 | SND_SOC_DAIFMT_CBS_CFS | 189 | SND_SOC_DAIFMT_CBS_CFS |
190 | ); | 190 | ); |
191 | 191 | ||
@@ -319,7 +319,6 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) | |||
319 | static struct platform_driver snd_byt_rt5651_mc_driver = { | 319 | static struct platform_driver snd_byt_rt5651_mc_driver = { |
320 | .driver = { | 320 | .driver = { |
321 | .name = "bytcr_rt5651", | 321 | .name = "bytcr_rt5651", |
322 | .pm = &snd_soc_pm_ops, | ||
323 | }, | 322 | }, |
324 | .probe = snd_byt_rt5651_mc_probe, | 323 | .probe = snd_byt_rt5651_mc_probe, |
325 | }; | 324 | }; |
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index f504a0e18f91..5bcde01d15e6 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c | |||
@@ -23,7 +23,11 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/acpi.h> | 24 | #include <linux/acpi.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/dmi.h> | ||
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <asm/cpu_device_id.h> | ||
29 | #include <asm/platform_sst_audio.h> | ||
30 | #include <linux/clk.h> | ||
27 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
28 | #include <sound/pcm_params.h> | 32 | #include <sound/pcm_params.h> |
29 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
@@ -33,7 +37,8 @@ | |||
33 | #include "../common/sst-acpi.h" | 37 | #include "../common/sst-acpi.h" |
34 | 38 | ||
35 | #define CHT_PLAT_CLK_3_HZ 19200000 | 39 | #define CHT_PLAT_CLK_3_HZ 19200000 |
36 | #define CHT_CODEC_DAI "rt5645-aif1" | 40 | #define CHT_CODEC_DAI1 "rt5645-aif1" |
41 | #define CHT_CODEC_DAI2 "rt5645-aif2" | ||
37 | 42 | ||
38 | struct cht_acpi_card { | 43 | struct cht_acpi_card { |
39 | char *codec_id; | 44 | char *codec_id; |
@@ -45,15 +50,36 @@ struct cht_mc_private { | |||
45 | struct snd_soc_jack jack; | 50 | struct snd_soc_jack jack; |
46 | struct cht_acpi_card *acpi_card; | 51 | struct cht_acpi_card *acpi_card; |
47 | char codec_name[16]; | 52 | char codec_name[16]; |
53 | struct clk *mclk; | ||
48 | }; | 54 | }; |
49 | 55 | ||
56 | #define CHT_RT5645_MAP(quirk) ((quirk) & 0xff) | ||
57 | #define CHT_RT5645_SSP2_AIF2 BIT(16) /* default is using AIF1 */ | ||
58 | #define CHT_RT5645_SSP0_AIF1 BIT(17) | ||
59 | #define CHT_RT5645_SSP0_AIF2 BIT(18) | ||
60 | |||
61 | static unsigned long cht_rt5645_quirk = 0; | ||
62 | |||
63 | static void log_quirks(struct device *dev) | ||
64 | { | ||
65 | if (cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) | ||
66 | dev_info(dev, "quirk SSP2_AIF2 enabled"); | ||
67 | if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) | ||
68 | dev_info(dev, "quirk SSP0_AIF1 enabled"); | ||
69 | if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2) | ||
70 | dev_info(dev, "quirk SSP0_AIF2 enabled"); | ||
71 | } | ||
72 | |||
50 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) | 73 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) |
51 | { | 74 | { |
52 | struct snd_soc_pcm_runtime *rtd; | 75 | struct snd_soc_pcm_runtime *rtd; |
53 | 76 | ||
54 | list_for_each_entry(rtd, &card->rtd_list, list) { | 77 | list_for_each_entry(rtd, &card->rtd_list, list) { |
55 | if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI, | 78 | if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI1, |
56 | strlen(CHT_CODEC_DAI))) | 79 | strlen(CHT_CODEC_DAI1))) |
80 | return rtd->codec_dai; | ||
81 | if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI2, | ||
82 | strlen(CHT_CODEC_DAI2))) | ||
57 | return rtd->codec_dai; | 83 | return rtd->codec_dai; |
58 | } | 84 | } |
59 | return NULL; | 85 | return NULL; |
@@ -65,6 +91,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, | |||
65 | struct snd_soc_dapm_context *dapm = w->dapm; | 91 | struct snd_soc_dapm_context *dapm = w->dapm; |
66 | struct snd_soc_card *card = dapm->card; | 92 | struct snd_soc_card *card = dapm->card; |
67 | struct snd_soc_dai *codec_dai; | 93 | struct snd_soc_dai *codec_dai; |
94 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); | ||
68 | int ret; | 95 | int ret; |
69 | 96 | ||
70 | codec_dai = cht_get_codec_dai(card); | 97 | codec_dai = cht_get_codec_dai(card); |
@@ -73,19 +100,30 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, | |||
73 | return -EIO; | 100 | return -EIO; |
74 | } | 101 | } |
75 | 102 | ||
76 | if (!SND_SOC_DAPM_EVENT_OFF(event)) | 103 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
77 | return 0; | 104 | if (ctx->mclk) { |
105 | ret = clk_prepare_enable(ctx->mclk); | ||
106 | if (ret < 0) { | ||
107 | dev_err(card->dev, | ||
108 | "could not configure MCLK state"); | ||
109 | return ret; | ||
110 | } | ||
111 | } | ||
112 | } else { | ||
113 | /* Set codec sysclk source to its internal clock because codec PLL will | ||
114 | * be off when idle and MCLK will also be off when codec is | ||
115 | * runtime suspended. Codec needs clock for jack detection and button | ||
116 | * press. MCLK is turned off with clock framework or ACPI. | ||
117 | */ | ||
118 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK, | ||
119 | 48000 * 512, SND_SOC_CLOCK_IN); | ||
120 | if (ret < 0) { | ||
121 | dev_err(card->dev, "can't set codec sysclk: %d\n", ret); | ||
122 | return ret; | ||
123 | } | ||
78 | 124 | ||
79 | /* Set codec sysclk source to its internal clock because codec PLL will | 125 | if (ctx->mclk) |
80 | * be off when idle and MCLK will also be off by ACPI when codec is | 126 | clk_disable_unprepare(ctx->mclk); |
81 | * runtime suspended. Codec needs clock for jack detection and button | ||
82 | * press. | ||
83 | */ | ||
84 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK, | ||
85 | 0, SND_SOC_CLOCK_IN); | ||
86 | if (ret < 0) { | ||
87 | dev_err(card->dev, "can't set codec sysclk: %d\n", ret); | ||
88 | return ret; | ||
89 | } | 127 | } |
90 | 128 | ||
91 | return 0; | 129 | return 0; |
@@ -97,7 +135,7 @@ static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { | |||
97 | SND_SOC_DAPM_MIC("Int Mic", NULL), | 135 | SND_SOC_DAPM_MIC("Int Mic", NULL), |
98 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | 136 | SND_SOC_DAPM_SPK("Ext Spk", NULL), |
99 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, | 137 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, |
100 | platform_clock_control, SND_SOC_DAPM_POST_PMD), | 138 | platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
101 | }; | 139 | }; |
102 | 140 | ||
103 | static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = { | 141 | static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = { |
@@ -109,12 +147,6 @@ static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = { | |||
109 | {"Headphone", NULL, "HPOR"}, | 147 | {"Headphone", NULL, "HPOR"}, |
110 | {"Ext Spk", NULL, "SPOL"}, | 148 | {"Ext Spk", NULL, "SPOL"}, |
111 | {"Ext Spk", NULL, "SPOR"}, | 149 | {"Ext Spk", NULL, "SPOR"}, |
112 | {"AIF1 Playback", NULL, "ssp2 Tx"}, | ||
113 | {"ssp2 Tx", NULL, "codec_out0"}, | ||
114 | {"ssp2 Tx", NULL, "codec_out1"}, | ||
115 | {"codec_in0", NULL, "ssp2 Rx" }, | ||
116 | {"codec_in1", NULL, "ssp2 Rx" }, | ||
117 | {"ssp2 Rx", NULL, "AIF1 Capture"}, | ||
118 | {"Headphone", NULL, "Platform Clock"}, | 150 | {"Headphone", NULL, "Platform Clock"}, |
119 | {"Headset Mic", NULL, "Platform Clock"}, | 151 | {"Headset Mic", NULL, "Platform Clock"}, |
120 | {"Int Mic", NULL, "Platform Clock"}, | 152 | {"Int Mic", NULL, "Platform Clock"}, |
@@ -130,16 +162,42 @@ static const struct snd_soc_dapm_route cht_rt5650_audio_map[] = { | |||
130 | {"Headphone", NULL, "HPOR"}, | 162 | {"Headphone", NULL, "HPOR"}, |
131 | {"Ext Spk", NULL, "SPOL"}, | 163 | {"Ext Spk", NULL, "SPOL"}, |
132 | {"Ext Spk", NULL, "SPOR"}, | 164 | {"Ext Spk", NULL, "SPOR"}, |
165 | {"Headphone", NULL, "Platform Clock"}, | ||
166 | {"Headset Mic", NULL, "Platform Clock"}, | ||
167 | {"Int Mic", NULL, "Platform Clock"}, | ||
168 | {"Ext Spk", NULL, "Platform Clock"}, | ||
169 | }; | ||
170 | |||
171 | static const struct snd_soc_dapm_route cht_rt5645_ssp2_aif1_map[] = { | ||
133 | {"AIF1 Playback", NULL, "ssp2 Tx"}, | 172 | {"AIF1 Playback", NULL, "ssp2 Tx"}, |
134 | {"ssp2 Tx", NULL, "codec_out0"}, | 173 | {"ssp2 Tx", NULL, "codec_out0"}, |
135 | {"ssp2 Tx", NULL, "codec_out1"}, | 174 | {"ssp2 Tx", NULL, "codec_out1"}, |
136 | {"codec_in0", NULL, "ssp2 Rx" }, | 175 | {"codec_in0", NULL, "ssp2 Rx" }, |
137 | {"codec_in1", NULL, "ssp2 Rx" }, | 176 | {"codec_in1", NULL, "ssp2 Rx" }, |
138 | {"ssp2 Rx", NULL, "AIF1 Capture"}, | 177 | {"ssp2 Rx", NULL, "AIF1 Capture"}, |
139 | {"Headphone", NULL, "Platform Clock"}, | 178 | }; |
140 | {"Headset Mic", NULL, "Platform Clock"}, | 179 | |
141 | {"Int Mic", NULL, "Platform Clock"}, | 180 | static const struct snd_soc_dapm_route cht_rt5645_ssp2_aif2_map[] = { |
142 | {"Ext Spk", NULL, "Platform Clock"}, | 181 | {"AIF2 Playback", NULL, "ssp2 Tx"}, |
182 | {"ssp2 Tx", NULL, "codec_out0"}, | ||
183 | {"ssp2 Tx", NULL, "codec_out1"}, | ||
184 | {"codec_in0", NULL, "ssp2 Rx" }, | ||
185 | {"codec_in1", NULL, "ssp2 Rx" }, | ||
186 | {"ssp2 Rx", NULL, "AIF2 Capture"}, | ||
187 | }; | ||
188 | |||
189 | static const struct snd_soc_dapm_route cht_rt5645_ssp0_aif1_map[] = { | ||
190 | {"AIF1 Playback", NULL, "ssp0 Tx"}, | ||
191 | {"ssp0 Tx", NULL, "modem_out"}, | ||
192 | {"modem_in", NULL, "ssp0 Rx" }, | ||
193 | {"ssp0 Rx", NULL, "AIF1 Capture"}, | ||
194 | }; | ||
195 | |||
196 | static const struct snd_soc_dapm_route cht_rt5645_ssp0_aif2_map[] = { | ||
197 | {"AIF2 Playback", NULL, "ssp0 Tx"}, | ||
198 | {"ssp0 Tx", NULL, "modem_out"}, | ||
199 | {"modem_in", NULL, "ssp0 Rx" }, | ||
200 | {"ssp0 Rx", NULL, "AIF2 Capture"}, | ||
143 | }; | 201 | }; |
144 | 202 | ||
145 | static const struct snd_kcontrol_new cht_mc_controls[] = { | 203 | static const struct snd_kcontrol_new cht_mc_controls[] = { |
@@ -185,28 +243,65 @@ static int cht_aif1_hw_params(struct snd_pcm_substream *substream, | |||
185 | return 0; | 243 | return 0; |
186 | } | 244 | } |
187 | 245 | ||
246 | /* uncomment when we have a real quirk | ||
247 | static int cht_rt5645_quirk_cb(const struct dmi_system_id *id) | ||
248 | { | ||
249 | cht_rt5645_quirk = (unsigned long)id->driver_data; | ||
250 | return 1; | ||
251 | } | ||
252 | */ | ||
253 | |||
254 | static const struct dmi_system_id cht_rt5645_quirk_table[] = { | ||
255 | { | ||
256 | }, | ||
257 | }; | ||
258 | |||
188 | static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | 259 | static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) |
189 | { | 260 | { |
190 | int ret; | 261 | int ret; |
191 | int jack_type; | 262 | int jack_type; |
192 | struct snd_soc_codec *codec = runtime->codec; | 263 | struct snd_soc_codec *codec = runtime->codec; |
193 | struct snd_soc_dai *codec_dai = runtime->codec_dai; | 264 | struct snd_soc_card *card = runtime->card; |
194 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); | 265 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); |
195 | 266 | ||
196 | /* Select clk_i2s1_asrc as ASRC clock source */ | 267 | if ((cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) || |
197 | rt5645_sel_asrc_clk_src(codec, | 268 | (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) { |
198 | RT5645_DA_STEREO_FILTER | | 269 | /* Select clk_i2s2_asrc as ASRC clock source */ |
199 | RT5645_DA_MONO_L_FILTER | | 270 | rt5645_sel_asrc_clk_src(codec, |
200 | RT5645_DA_MONO_R_FILTER | | 271 | RT5645_DA_STEREO_FILTER | |
201 | RT5645_AD_STEREO_FILTER, | 272 | RT5645_DA_MONO_L_FILTER | |
202 | RT5645_CLK_SEL_I2S1_ASRC); | 273 | RT5645_DA_MONO_R_FILTER | |
274 | RT5645_AD_STEREO_FILTER, | ||
275 | RT5645_CLK_SEL_I2S2_ASRC); | ||
276 | } else { | ||
277 | /* Select clk_i2s1_asrc as ASRC clock source */ | ||
278 | rt5645_sel_asrc_clk_src(codec, | ||
279 | RT5645_DA_STEREO_FILTER | | ||
280 | RT5645_DA_MONO_L_FILTER | | ||
281 | RT5645_DA_MONO_R_FILTER | | ||
282 | RT5645_AD_STEREO_FILTER, | ||
283 | RT5645_CLK_SEL_I2S1_ASRC); | ||
284 | } | ||
203 | 285 | ||
204 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ | 286 | if (cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) { |
205 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); | 287 | ret = snd_soc_dapm_add_routes(&card->dapm, |
206 | if (ret < 0) { | 288 | cht_rt5645_ssp2_aif2_map, |
207 | dev_err(runtime->dev, "can't set codec TDM slot %d\n", ret); | 289 | ARRAY_SIZE(cht_rt5645_ssp2_aif2_map)); |
208 | return ret; | 290 | } else if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) { |
291 | ret = snd_soc_dapm_add_routes(&card->dapm, | ||
292 | cht_rt5645_ssp0_aif1_map, | ||
293 | ARRAY_SIZE(cht_rt5645_ssp0_aif1_map)); | ||
294 | } else if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2) { | ||
295 | ret = snd_soc_dapm_add_routes(&card->dapm, | ||
296 | cht_rt5645_ssp0_aif2_map, | ||
297 | ARRAY_SIZE(cht_rt5645_ssp0_aif2_map)); | ||
298 | } else { | ||
299 | ret = snd_soc_dapm_add_routes(&card->dapm, | ||
300 | cht_rt5645_ssp2_aif1_map, | ||
301 | ARRAY_SIZE(cht_rt5645_ssp2_aif1_map)); | ||
209 | } | 302 | } |
303 | if (ret) | ||
304 | return ret; | ||
210 | 305 | ||
211 | if (ctx->acpi_card->codec_type == CODEC_TYPE_RT5650) | 306 | if (ctx->acpi_card->codec_type == CODEC_TYPE_RT5650) |
212 | jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | | 307 | jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | |
@@ -225,12 +320,33 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
225 | 320 | ||
226 | rt5645_set_jack_detect(codec, &ctx->jack, &ctx->jack, &ctx->jack); | 321 | rt5645_set_jack_detect(codec, &ctx->jack, &ctx->jack, &ctx->jack); |
227 | 322 | ||
323 | if (ctx->mclk) { | ||
324 | /* | ||
325 | * The firmware might enable the clock at | ||
326 | * boot (this information may or may not | ||
327 | * be reflected in the enable clock register). | ||
328 | * To change the rate we must disable the clock | ||
329 | * first to cover these cases. Due to common | ||
330 | * clock framework restrictions that do not allow | ||
331 | * to disable a clock that has not been enabled, | ||
332 | * we need to enable the clock first. | ||
333 | */ | ||
334 | ret = clk_prepare_enable(ctx->mclk); | ||
335 | if (!ret) | ||
336 | clk_disable_unprepare(ctx->mclk); | ||
337 | |||
338 | ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ); | ||
339 | |||
340 | if (ret) | ||
341 | dev_err(runtime->dev, "unable to set MCLK rate\n"); | ||
342 | } | ||
228 | return ret; | 343 | return ret; |
229 | } | 344 | } |
230 | 345 | ||
231 | static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, | 346 | static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, |
232 | struct snd_pcm_hw_params *params) | 347 | struct snd_pcm_hw_params *params) |
233 | { | 348 | { |
349 | int ret; | ||
234 | struct snd_interval *rate = hw_param_interval(params, | 350 | struct snd_interval *rate = hw_param_interval(params, |
235 | SNDRV_PCM_HW_PARAM_RATE); | 351 | SNDRV_PCM_HW_PARAM_RATE); |
236 | struct snd_interval *channels = hw_param_interval(params, | 352 | struct snd_interval *channels = hw_param_interval(params, |
@@ -240,8 +356,67 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, | |||
240 | rate->min = rate->max = 48000; | 356 | rate->min = rate->max = 48000; |
241 | channels->min = channels->max = 2; | 357 | channels->min = channels->max = 2; |
242 | 358 | ||
243 | /* set SSP2 to 24-bit */ | 359 | if ((cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) || |
244 | params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); | 360 | (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) { |
361 | |||
362 | /* set SSP0 to 16-bit */ | ||
363 | params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); | ||
364 | |||
365 | /* | ||
366 | * Default mode for SSP configuration is TDM 4 slot, override config | ||
367 | * with explicit setting to I2S 2ch 16-bit. The word length is set with | ||
368 | * dai_set_tdm_slot() since there is no other API exposed | ||
369 | */ | ||
370 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, | ||
371 | SND_SOC_DAIFMT_I2S | | ||
372 | SND_SOC_DAIFMT_NB_NF | | ||
373 | SND_SOC_DAIFMT_CBS_CFS | ||
374 | ); | ||
375 | if (ret < 0) { | ||
376 | dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); | ||
377 | return ret; | ||
378 | } | ||
379 | |||
380 | ret = snd_soc_dai_set_fmt(rtd->codec_dai, | ||
381 | SND_SOC_DAIFMT_I2S | | ||
382 | SND_SOC_DAIFMT_NB_NF | | ||
383 | SND_SOC_DAIFMT_CBS_CFS | ||
384 | ); | ||
385 | if (ret < 0) { | ||
386 | dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); | ||
387 | return ret; | ||
388 | } | ||
389 | |||
390 | ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); | ||
391 | if (ret < 0) { | ||
392 | dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); | ||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | } else { | ||
397 | |||
398 | /* set SSP2 to 24-bit */ | ||
399 | params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); | ||
400 | |||
401 | /* | ||
402 | * Default mode for SSP configuration is TDM 4 slot | ||
403 | */ | ||
404 | ret = snd_soc_dai_set_fmt(rtd->codec_dai, | ||
405 | SND_SOC_DAIFMT_DSP_B | | ||
406 | SND_SOC_DAIFMT_IB_NF | | ||
407 | SND_SOC_DAIFMT_CBS_CFS); | ||
408 | if (ret < 0) { | ||
409 | dev_err(rtd->dev, "can't set format to TDM %d\n", ret); | ||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ | ||
414 | ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0xF, 0xF, 4, 24); | ||
415 | if (ret < 0) { | ||
416 | dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret); | ||
417 | return ret; | ||
418 | } | ||
419 | } | ||
245 | return 0; | 420 | return 0; |
246 | } | 421 | } |
247 | 422 | ||
@@ -303,8 +478,6 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
303 | .no_pcm = 1, | 478 | .no_pcm = 1, |
304 | .codec_dai_name = "rt5645-aif1", | 479 | .codec_dai_name = "rt5645-aif1", |
305 | .codec_name = "i2c-10EC5645:00", | 480 | .codec_name = "i2c-10EC5645:00", |
306 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | ||
307 | | SND_SOC_DAIFMT_CBS_CFS, | ||
308 | .init = cht_codec_init, | 481 | .init = cht_codec_init, |
309 | .be_hw_params_fixup = cht_codec_fixup, | 482 | .be_hw_params_fixup = cht_codec_fixup, |
310 | .nonatomic = true, | 483 | .nonatomic = true, |
@@ -344,10 +517,31 @@ static struct snd_soc_card snd_soc_card_chtrt5650 = { | |||
344 | static struct cht_acpi_card snd_soc_cards[] = { | 517 | static struct cht_acpi_card snd_soc_cards[] = { |
345 | {"10EC5640", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645}, | 518 | {"10EC5640", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645}, |
346 | {"10EC5645", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645}, | 519 | {"10EC5645", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645}, |
520 | {"10EC5648", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645}, | ||
521 | {"10EC3270", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645}, | ||
347 | {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650}, | 522 | {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650}, |
348 | }; | 523 | }; |
349 | 524 | ||
350 | static char cht_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */ | 525 | static char cht_rt5645_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */ |
526 | static char cht_rt5645_codec_aif_name[12]; /* = "rt5645-aif[1|2]" */ | ||
527 | static char cht_rt5645_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ | ||
528 | |||
529 | static bool is_valleyview(void) | ||
530 | { | ||
531 | static const struct x86_cpu_id cpu_ids[] = { | ||
532 | { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ | ||
533 | {} | ||
534 | }; | ||
535 | |||
536 | if (!x86_match_cpu(cpu_ids)) | ||
537 | return false; | ||
538 | return true; | ||
539 | } | ||
540 | |||
541 | struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ | ||
542 | u64 aif_value; /* 1: AIF1, 2: AIF2 */ | ||
543 | u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ | ||
544 | }; | ||
351 | 545 | ||
352 | static int snd_cht_mc_probe(struct platform_device *pdev) | 546 | static int snd_cht_mc_probe(struct platform_device *pdev) |
353 | { | 547 | { |
@@ -358,22 +552,33 @@ static int snd_cht_mc_probe(struct platform_device *pdev) | |||
358 | struct sst_acpi_mach *mach; | 552 | struct sst_acpi_mach *mach; |
359 | const char *i2c_name = NULL; | 553 | const char *i2c_name = NULL; |
360 | int dai_index = 0; | 554 | int dai_index = 0; |
555 | bool found = false; | ||
556 | bool is_bytcr = false; | ||
361 | 557 | ||
362 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); | 558 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); |
363 | if (!drv) | 559 | if (!drv) |
364 | return -ENOMEM; | 560 | return -ENOMEM; |
365 | 561 | ||
562 | mach = (&pdev->dev)->platform_data; | ||
563 | |||
366 | for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) { | 564 | for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) { |
367 | if (acpi_dev_found(snd_soc_cards[i].codec_id)) { | 565 | if (acpi_dev_found(snd_soc_cards[i].codec_id) && |
566 | (!strncmp(snd_soc_cards[i].codec_id, mach->id, 8))) { | ||
368 | dev_dbg(&pdev->dev, | 567 | dev_dbg(&pdev->dev, |
369 | "found codec %s\n", snd_soc_cards[i].codec_id); | 568 | "found codec %s\n", snd_soc_cards[i].codec_id); |
370 | card = snd_soc_cards[i].soc_card; | 569 | card = snd_soc_cards[i].soc_card; |
371 | drv->acpi_card = &snd_soc_cards[i]; | 570 | drv->acpi_card = &snd_soc_cards[i]; |
571 | found = true; | ||
372 | break; | 572 | break; |
373 | } | 573 | } |
374 | } | 574 | } |
575 | |||
576 | if (!found) { | ||
577 | dev_err(&pdev->dev, "No matching HID found in supported list\n"); | ||
578 | return -ENODEV; | ||
579 | } | ||
580 | |||
375 | card->dev = &pdev->dev; | 581 | card->dev = &pdev->dev; |
376 | mach = card->dev->platform_data; | ||
377 | sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id); | 582 | sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id); |
378 | 583 | ||
379 | /* set correct codec name */ | 584 | /* set correct codec name */ |
@@ -386,9 +591,105 @@ static int snd_cht_mc_probe(struct platform_device *pdev) | |||
386 | /* fixup codec name based on HID */ | 591 | /* fixup codec name based on HID */ |
387 | i2c_name = sst_acpi_find_name_from_hid(mach->id); | 592 | i2c_name = sst_acpi_find_name_from_hid(mach->id); |
388 | if (i2c_name != NULL) { | 593 | if (i2c_name != NULL) { |
389 | snprintf(cht_rt5640_codec_name, sizeof(cht_rt5640_codec_name), | 594 | snprintf(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name), |
390 | "%s%s", "i2c-", i2c_name); | 595 | "%s%s", "i2c-", i2c_name); |
391 | cht_dailink[dai_index].codec_name = cht_rt5640_codec_name; | 596 | cht_dailink[dai_index].codec_name = cht_rt5645_codec_name; |
597 | } | ||
598 | |||
599 | /* | ||
600 | * swap SSP0 if bytcr is detected | ||
601 | * (will be overridden if DMI quirk is detected) | ||
602 | */ | ||
603 | if (is_valleyview()) { | ||
604 | struct sst_platform_info *p_info = mach->pdata; | ||
605 | const struct sst_res_info *res_info = p_info->res_info; | ||
606 | |||
607 | if (res_info->acpi_ipc_irq_index == 0) | ||
608 | is_bytcr = true; | ||
609 | } | ||
610 | |||
611 | if (is_bytcr) { | ||
612 | /* | ||
613 | * Baytrail CR platforms may have CHAN package in BIOS, try | ||
614 | * to find relevant routing quirk based as done on Windows | ||
615 | * platforms. We have to read the information directly from the | ||
616 | * BIOS, at this stage the card is not created and the links | ||
617 | * with the codec driver/pdata are non-existent | ||
618 | */ | ||
619 | |||
620 | struct acpi_chan_package chan_package; | ||
621 | |||
622 | /* format specified: 2 64-bit integers */ | ||
623 | struct acpi_buffer format = {sizeof("NN"), "NN"}; | ||
624 | struct acpi_buffer state = {0, NULL}; | ||
625 | struct sst_acpi_package_context pkg_ctx; | ||
626 | bool pkg_found = false; | ||
627 | |||
628 | state.length = sizeof(chan_package); | ||
629 | state.pointer = &chan_package; | ||
630 | |||
631 | pkg_ctx.name = "CHAN"; | ||
632 | pkg_ctx.length = 2; | ||
633 | pkg_ctx.format = &format; | ||
634 | pkg_ctx.state = &state; | ||
635 | pkg_ctx.data_valid = false; | ||
636 | |||
637 | pkg_found = sst_acpi_find_package_from_hid(mach->id, &pkg_ctx); | ||
638 | if (pkg_found) { | ||
639 | if (chan_package.aif_value == 1) { | ||
640 | dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n"); | ||
641 | cht_rt5645_quirk |= CHT_RT5645_SSP0_AIF1; | ||
642 | } else if (chan_package.aif_value == 2) { | ||
643 | dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n"); | ||
644 | cht_rt5645_quirk |= CHT_RT5645_SSP0_AIF2; | ||
645 | } else { | ||
646 | dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n"); | ||
647 | pkg_found = false; | ||
648 | } | ||
649 | } | ||
650 | |||
651 | if (!pkg_found) { | ||
652 | /* no BIOS indications, assume SSP0-AIF2 connection */ | ||
653 | cht_rt5645_quirk |= CHT_RT5645_SSP0_AIF2; | ||
654 | } | ||
655 | } | ||
656 | |||
657 | /* check quirks before creating card */ | ||
658 | dmi_check_system(cht_rt5645_quirk_table); | ||
659 | log_quirks(&pdev->dev); | ||
660 | |||
661 | if ((cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) || | ||
662 | (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) { | ||
663 | |||
664 | /* fixup codec aif name */ | ||
665 | snprintf(cht_rt5645_codec_aif_name, | ||
666 | sizeof(cht_rt5645_codec_aif_name), | ||
667 | "%s", "rt5645-aif2"); | ||
668 | |||
669 | cht_dailink[dai_index].codec_dai_name = | ||
670 | cht_rt5645_codec_aif_name; | ||
671 | } | ||
672 | |||
673 | if ((cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) || | ||
674 | (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) { | ||
675 | |||
676 | /* fixup cpu dai name name */ | ||
677 | snprintf(cht_rt5645_cpu_dai_name, | ||
678 | sizeof(cht_rt5645_cpu_dai_name), | ||
679 | "%s", "ssp0-port"); | ||
680 | |||
681 | cht_dailink[dai_index].cpu_dai_name = | ||
682 | cht_rt5645_cpu_dai_name; | ||
683 | } | ||
684 | |||
685 | if (is_valleyview()) { | ||
686 | drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); | ||
687 | if (IS_ERR(drv->mclk)) { | ||
688 | dev_err(&pdev->dev, | ||
689 | "Failed to get MCLK from pmc_plt_clk_3: %ld\n", | ||
690 | PTR_ERR(drv->mclk)); | ||
691 | return PTR_ERR(drv->mclk); | ||
692 | } | ||
392 | } | 693 | } |
393 | 694 | ||
394 | snd_soc_card_set_drvdata(card, drv); | 695 | snd_soc_card_set_drvdata(card, drv); |
diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index fddd1cd12f13..3b12bc1fa518 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c | |||
@@ -32,6 +32,7 @@ | |||
32 | static struct snd_soc_jack skylake_headset; | 32 | static struct snd_soc_jack skylake_headset; |
33 | static struct snd_soc_card skylake_audio_card; | 33 | static struct snd_soc_card skylake_audio_card; |
34 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; | 34 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; |
35 | static struct snd_soc_jack skylake_hdmi[3]; | ||
35 | 36 | ||
36 | struct skl_hdmi_pcm { | 37 | struct skl_hdmi_pcm { |
37 | struct list_head head; | 38 | struct list_head head; |
@@ -111,8 +112,8 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = { | |||
111 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | 112 | SND_SOC_DAPM_MIC("Headset Mic", NULL), |
112 | SND_SOC_DAPM_SPK("Spk", NULL), | 113 | SND_SOC_DAPM_SPK("Spk", NULL), |
113 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), | 114 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), |
114 | SND_SOC_DAPM_SPK("DP", NULL), | 115 | SND_SOC_DAPM_SPK("DP1", NULL), |
115 | SND_SOC_DAPM_SPK("HDMI", NULL), | 116 | SND_SOC_DAPM_SPK("DP2", NULL), |
116 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, | 117 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, |
117 | platform_clock_control, SND_SOC_DAPM_PRE_PMU | | 118 | platform_clock_control, SND_SOC_DAPM_PRE_PMU | |
118 | SND_SOC_DAPM_POST_PMD), | 119 | SND_SOC_DAPM_POST_PMD), |
@@ -130,9 +131,6 @@ static const struct snd_soc_dapm_route skylake_map[] = { | |||
130 | { "MIC", NULL, "Headset Mic" }, | 131 | { "MIC", NULL, "Headset Mic" }, |
131 | { "DMic", NULL, "SoC DMIC" }, | 132 | { "DMic", NULL, "SoC DMIC" }, |
132 | 133 | ||
133 | {"HDMI", NULL, "hif5 Output"}, | ||
134 | {"DP", NULL, "hif6 Output"}, | ||
135 | |||
136 | /* CODEC BE connections */ | 134 | /* CODEC BE connections */ |
137 | { "HiFi Playback", NULL, "ssp0 Tx" }, | 135 | { "HiFi Playback", NULL, "ssp0 Tx" }, |
138 | { "ssp0 Tx", NULL, "codec0_out" }, | 136 | { "ssp0 Tx", NULL, "codec0_out" }, |
@@ -603,19 +601,39 @@ static struct snd_soc_dai_link skylake_dais[] = { | |||
603 | }, | 601 | }, |
604 | }; | 602 | }; |
605 | 603 | ||
604 | #define NAME_SIZE 32 | ||
606 | static int skylake_card_late_probe(struct snd_soc_card *card) | 605 | static int skylake_card_late_probe(struct snd_soc_card *card) |
607 | { | 606 | { |
608 | struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(card); | 607 | struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(card); |
609 | struct skl_hdmi_pcm *pcm; | 608 | struct skl_hdmi_pcm *pcm; |
610 | int err; | 609 | struct snd_soc_codec *codec = NULL; |
610 | int err, i = 0; | ||
611 | char jack_name[NAME_SIZE]; | ||
611 | 612 | ||
612 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | 613 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { |
613 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device); | 614 | codec = pcm->codec_dai->codec; |
615 | snprintf(jack_name, sizeof(jack_name), | ||
616 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
617 | err = snd_soc_card_jack_new(card, jack_name, | ||
618 | SND_JACK_AVOUT, | ||
619 | &skylake_hdmi[i], | ||
620 | NULL, 0); | ||
621 | |||
622 | if (err) | ||
623 | return err; | ||
624 | |||
625 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
626 | &skylake_hdmi[i]); | ||
614 | if (err < 0) | 627 | if (err < 0) |
615 | return err; | 628 | return err; |
629 | |||
630 | i++; | ||
616 | } | 631 | } |
617 | 632 | ||
618 | return 0; | 633 | if (!codec) |
634 | return -EINVAL; | ||
635 | |||
636 | return hdac_hdmi_jack_port_init(codec, &card->dapm); | ||
619 | } | 637 | } |
620 | 638 | ||
621 | /* skylake audio machine driver for SPT + NAU88L25 */ | 639 | /* skylake audio machine driver for SPT + NAU88L25 */ |
diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index 8ab865ee0cad..eb7751b0599b 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c | |||
@@ -36,6 +36,7 @@ | |||
36 | static struct snd_soc_jack skylake_headset; | 36 | static struct snd_soc_jack skylake_headset; |
37 | static struct snd_soc_card skylake_audio_card; | 37 | static struct snd_soc_card skylake_audio_card; |
38 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; | 38 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; |
39 | static struct snd_soc_jack skylake_hdmi[3]; | ||
39 | 40 | ||
40 | struct skl_hdmi_pcm { | 41 | struct skl_hdmi_pcm { |
41 | struct list_head head; | 42 | struct list_head head; |
@@ -115,8 +116,8 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = { | |||
115 | SND_SOC_DAPM_SPK("Left Speaker", NULL), | 116 | SND_SOC_DAPM_SPK("Left Speaker", NULL), |
116 | SND_SOC_DAPM_SPK("Right Speaker", NULL), | 117 | SND_SOC_DAPM_SPK("Right Speaker", NULL), |
117 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), | 118 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), |
118 | SND_SOC_DAPM_SPK("DP", NULL), | 119 | SND_SOC_DAPM_SPK("DP1", NULL), |
119 | SND_SOC_DAPM_SPK("HDMI", NULL), | 120 | SND_SOC_DAPM_SPK("DP2", NULL), |
120 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, | 121 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, |
121 | platform_clock_control, SND_SOC_DAPM_PRE_PMU | | 122 | platform_clock_control, SND_SOC_DAPM_PRE_PMU | |
122 | SND_SOC_DAPM_POST_PMD), | 123 | SND_SOC_DAPM_POST_PMD), |
@@ -135,8 +136,6 @@ static const struct snd_soc_dapm_route skylake_map[] = { | |||
135 | {"MIC", NULL, "Headset Mic"}, | 136 | {"MIC", NULL, "Headset Mic"}, |
136 | {"DMic", NULL, "SoC DMIC"}, | 137 | {"DMic", NULL, "SoC DMIC"}, |
137 | 138 | ||
138 | {"HDMI", NULL, "hif5 Output"}, | ||
139 | {"DP", NULL, "hif6 Output"}, | ||
140 | /* CODEC BE connections */ | 139 | /* CODEC BE connections */ |
141 | { "Left Playback", NULL, "ssp0 Tx"}, | 140 | { "Left Playback", NULL, "ssp0 Tx"}, |
142 | { "Right Playback", NULL, "ssp0 Tx"}, | 141 | { "Right Playback", NULL, "ssp0 Tx"}, |
@@ -653,19 +652,39 @@ static struct snd_soc_dai_link skylake_dais[] = { | |||
653 | }, | 652 | }, |
654 | }; | 653 | }; |
655 | 654 | ||
655 | #define NAME_SIZE 32 | ||
656 | static int skylake_card_late_probe(struct snd_soc_card *card) | 656 | static int skylake_card_late_probe(struct snd_soc_card *card) |
657 | { | 657 | { |
658 | struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(card); | 658 | struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(card); |
659 | struct skl_hdmi_pcm *pcm; | 659 | struct skl_hdmi_pcm *pcm; |
660 | int err; | 660 | struct snd_soc_codec *codec = NULL; |
661 | int err, i = 0; | ||
662 | char jack_name[NAME_SIZE]; | ||
661 | 663 | ||
662 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | 664 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { |
663 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device); | 665 | codec = pcm->codec_dai->codec; |
666 | snprintf(jack_name, sizeof(jack_name), | ||
667 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
668 | err = snd_soc_card_jack_new(card, jack_name, | ||
669 | SND_JACK_AVOUT, | ||
670 | &skylake_hdmi[i], | ||
671 | NULL, 0); | ||
672 | |||
673 | if (err) | ||
674 | return err; | ||
675 | |||
676 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
677 | &skylake_hdmi[i]); | ||
664 | if (err < 0) | 678 | if (err < 0) |
665 | return err; | 679 | return err; |
680 | |||
681 | i++; | ||
666 | } | 682 | } |
667 | 683 | ||
668 | return 0; | 684 | if (!codec) |
685 | return -EINVAL; | ||
686 | |||
687 | return hdac_hdmi_jack_port_init(codec, &card->dapm); | ||
669 | } | 688 | } |
670 | 689 | ||
671 | /* skylake audio machine driver for SPT + NAU88L25 */ | 690 | /* skylake audio machine driver for SPT + NAU88L25 */ |
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index dc5c3611a6ff..f5ab7b8d51d1 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "../../codecs/hdac_hdmi.h" | 29 | #include "../../codecs/hdac_hdmi.h" |
30 | 30 | ||
31 | static struct snd_soc_jack skylake_headset; | 31 | static struct snd_soc_jack skylake_headset; |
32 | static struct snd_soc_jack skylake_hdmi[3]; | ||
32 | 33 | ||
33 | struct skl_hdmi_pcm { | 34 | struct skl_hdmi_pcm { |
34 | struct list_head head; | 35 | struct list_head head; |
@@ -94,10 +95,6 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = { | |||
94 | {"DMIC1 Pin", NULL, "DMIC2"}, | 95 | {"DMIC1 Pin", NULL, "DMIC2"}, |
95 | {"DMic", NULL, "SoC DMIC"}, | 96 | {"DMic", NULL, "SoC DMIC"}, |
96 | 97 | ||
97 | {"HDMI1", NULL, "hif5 Output"}, | ||
98 | {"HDMI2", NULL, "hif6 Output"}, | ||
99 | {"HDMI3", NULL, "hif7 Output"}, | ||
100 | |||
101 | /* CODEC BE connections */ | 98 | /* CODEC BE connections */ |
102 | { "AIF1 Playback", NULL, "ssp0 Tx"}, | 99 | { "AIF1 Playback", NULL, "ssp0 Tx"}, |
103 | { "ssp0 Tx", NULL, "codec0_out"}, | 100 | { "ssp0 Tx", NULL, "codec0_out"}, |
@@ -458,19 +455,38 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { | |||
458 | }, | 455 | }, |
459 | }; | 456 | }; |
460 | 457 | ||
458 | #define NAME_SIZE 32 | ||
461 | static int skylake_card_late_probe(struct snd_soc_card *card) | 459 | static int skylake_card_late_probe(struct snd_soc_card *card) |
462 | { | 460 | { |
463 | struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(card); | 461 | struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(card); |
464 | struct skl_hdmi_pcm *pcm; | 462 | struct skl_hdmi_pcm *pcm; |
465 | int err; | 463 | struct snd_soc_codec *codec = NULL; |
464 | int err, i = 0; | ||
465 | char jack_name[NAME_SIZE]; | ||
466 | 466 | ||
467 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | 467 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { |
468 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device); | 468 | codec = pcm->codec_dai->codec; |
469 | snprintf(jack_name, sizeof(jack_name), | ||
470 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
471 | err = snd_soc_card_jack_new(card, jack_name, | ||
472 | SND_JACK_AVOUT, &skylake_hdmi[i], | ||
473 | NULL, 0); | ||
474 | |||
475 | if (err) | ||
476 | return err; | ||
477 | |||
478 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
479 | &skylake_hdmi[i]); | ||
469 | if (err < 0) | 480 | if (err < 0) |
470 | return err; | 481 | return err; |
482 | |||
483 | i++; | ||
471 | } | 484 | } |
472 | 485 | ||
473 | return 0; | 486 | if (!codec) |
487 | return -EINVAL; | ||
488 | |||
489 | return hdac_hdmi_jack_port_init(codec, &card->dapm); | ||
474 | } | 490 | } |
475 | 491 | ||
476 | /* skylake audio machine driver for SPT + RT286S */ | 492 | /* skylake audio machine driver for SPT + RT286S */ |
diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c index c00ede4ea4d7..11c0805393ff 100644 --- a/sound/soc/intel/common/sst-dsp.c +++ b/sound/soc/intel/common/sst-dsp.c | |||
@@ -252,44 +252,44 @@ void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset, | |||
252 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced); | 252 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced); |
253 | 253 | ||
254 | int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask, | 254 | int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask, |
255 | u32 target, u32 timeout, char *operation) | 255 | u32 target, u32 time, char *operation) |
256 | { | 256 | { |
257 | int time, ret; | ||
258 | u32 reg; | 257 | u32 reg; |
259 | bool done = false; | 258 | unsigned long timeout; |
259 | int k = 0, s = 500; | ||
260 | 260 | ||
261 | /* | 261 | /* |
262 | * we will poll for couple of ms using mdelay, if not successful | 262 | * split the loop into sleeps of varying resolution. more accurately, |
263 | * then go to longer sleep using usleep_range | 263 | * the range of wakeups are: |
264 | * Phase 1(first 5ms): min sleep 0.5ms; max sleep 1ms. | ||
265 | * Phase 2:( 5ms to 10ms) : min sleep 0.5ms; max sleep 10ms | ||
266 | * (usleep_range (500, 1000) and usleep_range(5000, 10000) are | ||
267 | * both possible in this phase depending on whether k > 10 or not). | ||
268 | * Phase 3: (beyond 10 ms) min sleep 5ms; max sleep 10ms. | ||
264 | */ | 269 | */ |
265 | 270 | ||
266 | /* check if set state successful */ | 271 | timeout = jiffies + msecs_to_jiffies(time); |
267 | for (time = 0; time < 5; time++) { | 272 | while (((sst_dsp_shim_read_unlocked(ctx, offset) & mask) != target) |
268 | if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) { | 273 | && time_before(jiffies, timeout)) { |
269 | done = true; | 274 | k++; |
270 | break; | 275 | if (k > 10) |
271 | } | 276 | s = 5000; |
272 | mdelay(1); | 277 | |
278 | usleep_range(s, 2*s); | ||
273 | } | 279 | } |
274 | 280 | ||
275 | if (done == false) { | 281 | reg = sst_dsp_shim_read_unlocked(ctx, offset); |
276 | /* sleeping in 10ms steps so adjust timeout value */ | ||
277 | timeout /= 10; | ||
278 | 282 | ||
279 | for (time = 0; time < timeout; time++) { | 283 | if ((reg & mask) == target) { |
280 | if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) | 284 | dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s successful\n", |
281 | break; | 285 | reg, operation); |
282 | 286 | ||
283 | usleep_range(5000, 10000); | 287 | return 0; |
284 | } | ||
285 | } | 288 | } |
286 | 289 | ||
287 | reg = sst_dsp_shim_read_unlocked(ctx, offset); | 290 | dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s timedout\n", |
288 | dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s %s\n", reg, operation, | 291 | reg, operation); |
289 | (time < timeout) ? "successful" : "timedout"); | 292 | return -ETIME; |
290 | ret = time < timeout ? 0 : -ETIME; | ||
291 | |||
292 | return ret; | ||
293 | } | 293 | } |
294 | EXPORT_SYMBOL_GPL(sst_dsp_register_poll); | 294 | EXPORT_SYMBOL_GPL(sst_dsp_register_poll); |
295 | 295 | ||
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 1f9f33d34000..15a063a403cc 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "../common/sst-dsp.h" | 23 | #include "../common/sst-dsp.h" |
24 | #include "../common/sst-dsp-priv.h" | 24 | #include "../common/sst-dsp-priv.h" |
25 | #include "skl-sst-ipc.h" | 25 | #include "skl-sst-ipc.h" |
26 | #include "skl-tplg-interface.h" | ||
27 | 26 | ||
28 | #define BXT_BASEFW_TIMEOUT 3000 | 27 | #define BXT_BASEFW_TIMEOUT 3000 |
29 | #define BXT_INIT_TIMEOUT 500 | 28 | #define BXT_INIT_TIMEOUT 500 |
@@ -52,7 +51,7 @@ static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) | |||
52 | } | 51 | } |
53 | 52 | ||
54 | static int | 53 | static int |
55 | bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo) | 54 | bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) |
56 | { | 55 | { |
57 | struct snd_dma_buffer dmab; | 56 | struct snd_dma_buffer dmab; |
58 | struct skl_sst *skl = ctx->thread_context; | 57 | struct skl_sst *skl = ctx->thread_context; |
@@ -61,11 +60,11 @@ bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo) | |||
61 | int ret = 0, i, dma_id, stream_tag; | 60 | int ret = 0, i, dma_id, stream_tag; |
62 | 61 | ||
63 | /* library indices start from 1 to N. 0 represents base FW */ | 62 | /* library indices start from 1 to N. 0 represents base FW */ |
64 | for (i = 1; i < minfo->lib_count; i++) { | 63 | for (i = 1; i < lib_count; i++) { |
65 | ret = request_firmware(&fw, minfo->lib[i].name, ctx->dev); | 64 | ret = request_firmware(&fw, linfo[i].name, ctx->dev); |
66 | if (ret < 0) { | 65 | if (ret < 0) { |
67 | dev_err(ctx->dev, "Request lib %s failed:%d\n", | 66 | dev_err(ctx->dev, "Request lib %s failed:%d\n", |
68 | minfo->lib[i].name, ret); | 67 | linfo[i].name, ret); |
69 | return ret; | 68 | return ret; |
70 | } | 69 | } |
71 | 70 | ||
@@ -96,7 +95,7 @@ bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo) | |||
96 | ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i); | 95 | ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i); |
97 | if (ret < 0) | 96 | if (ret < 0) |
98 | dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n", | 97 | dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n", |
99 | minfo->lib[i].name, ret); | 98 | linfo[i].name, ret); |
100 | 99 | ||
101 | ctx->dsp_ops.trigger(ctx->dev, false, stream_tag); | 100 | ctx->dsp_ops.trigger(ctx->dev, false, stream_tag); |
102 | ctx->dsp_ops.cleanup(ctx->dev, &dmab, stream_tag); | 101 | ctx->dsp_ops.cleanup(ctx->dev, &dmab, stream_tag); |
@@ -119,8 +118,7 @@ load_library_failed: | |||
119 | static int sst_bxt_prepare_fw(struct sst_dsp *ctx, | 118 | static int sst_bxt_prepare_fw(struct sst_dsp *ctx, |
120 | const void *fwdata, u32 fwsize) | 119 | const void *fwdata, u32 fwsize) |
121 | { | 120 | { |
122 | int stream_tag, ret, i; | 121 | int stream_tag, ret; |
123 | u32 reg; | ||
124 | 122 | ||
125 | stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); | 123 | stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); |
126 | if (stream_tag <= 0) { | 124 | if (stream_tag <= 0) { |
@@ -153,23 +151,13 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, | |||
153 | } | 151 | } |
154 | 152 | ||
155 | /* Step 4: Wait for DONE Bit */ | 153 | /* Step 4: Wait for DONE Bit */ |
156 | for (i = BXT_INIT_TIMEOUT; i > 0; --i) { | 154 | ret = sst_dsp_register_poll(ctx, SKL_ADSP_REG_HIPCIE, |
157 | reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE); | ||
158 | |||
159 | if (reg & SKL_ADSP_REG_HIPCIE_DONE) { | ||
160 | sst_dsp_shim_update_bits_forced(ctx, | ||
161 | SKL_ADSP_REG_HIPCIE, | ||
162 | SKL_ADSP_REG_HIPCIE_DONE, | 155 | SKL_ADSP_REG_HIPCIE_DONE, |
163 | SKL_ADSP_REG_HIPCIE_DONE); | 156 | SKL_ADSP_REG_HIPCIE_DONE, |
164 | break; | 157 | BXT_INIT_TIMEOUT, "HIPCIE Done"); |
165 | } | 158 | if (ret < 0) { |
166 | mdelay(1); | 159 | dev_err(ctx->dev, "Timout for Purge Request%d\n", ret); |
167 | } | 160 | goto base_fw_load_failed; |
168 | if (!i) { | ||
169 | dev_info(ctx->dev, "Waiting for HIPCIE done, reg: 0x%x\n", reg); | ||
170 | sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCIE, | ||
171 | SKL_ADSP_REG_HIPCIE_DONE, | ||
172 | SKL_ADSP_REG_HIPCIE_DONE); | ||
173 | } | 161 | } |
174 | 162 | ||
175 | /* Step 5: power down core1 */ | 163 | /* Step 5: power down core1 */ |
@@ -184,19 +172,10 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, | |||
184 | skl_ipc_op_int_enable(ctx); | 172 | skl_ipc_op_int_enable(ctx); |
185 | 173 | ||
186 | /* Step 7: Wait for ROM init */ | 174 | /* Step 7: Wait for ROM init */ |
187 | for (i = BXT_INIT_TIMEOUT; i > 0; --i) { | 175 | ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK, |
188 | if (SKL_FW_INIT == | 176 | SKL_FW_INIT, BXT_INIT_TIMEOUT, "ROM Load"); |
189 | (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) & | 177 | if (ret < 0) { |
190 | SKL_FW_STS_MASK)) { | 178 | dev_err(ctx->dev, "Timeout for ROM init, ret:%d\n", ret); |
191 | |||
192 | dev_info(ctx->dev, "ROM loaded, continue FW loading\n"); | ||
193 | break; | ||
194 | } | ||
195 | mdelay(1); | ||
196 | } | ||
197 | if (!i) { | ||
198 | dev_err(ctx->dev, "Timeout for ROM init, HIPCIE: 0x%x\n", reg); | ||
199 | ret = -EIO; | ||
200 | goto base_fw_load_failed; | 179 | goto base_fw_load_failed; |
201 | } | 180 | } |
202 | 181 | ||
@@ -432,7 +411,6 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) | |||
432 | int ret; | 411 | int ret; |
433 | struct skl_ipc_dxstate_info dx; | 412 | struct skl_ipc_dxstate_info dx; |
434 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); | 413 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); |
435 | struct skl_dfw_manifest *minfo = &skl->manifest; | ||
436 | 414 | ||
437 | if (skl->fw_loaded == false) { | 415 | if (skl->fw_loaded == false) { |
438 | skl->boot_complete = false; | 416 | skl->boot_complete = false; |
@@ -442,8 +420,9 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) | |||
442 | return ret; | 420 | return ret; |
443 | } | 421 | } |
444 | 422 | ||
445 | if (minfo->lib_count > 1) { | 423 | if (skl->lib_count > 1) { |
446 | ret = bxt_load_library(ctx, minfo); | 424 | ret = bxt_load_library(ctx, skl->lib_info, |
425 | skl->lib_count); | ||
447 | if (ret < 0) { | 426 | if (ret < 0) { |
448 | dev_err(ctx->dev, "reload libs failed: %d\n", ret); | 427 | dev_err(ctx->dev, "reload libs failed: %d\n", ret); |
449 | return ret; | 428 | return ret; |
@@ -640,8 +619,9 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) | |||
640 | 619 | ||
641 | skl_dsp_init_core_state(sst); | 620 | skl_dsp_init_core_state(sst); |
642 | 621 | ||
643 | if (ctx->manifest.lib_count > 1) { | 622 | if (ctx->lib_count > 1) { |
644 | ret = sst->fw_ops.load_library(sst, &ctx->manifest); | 623 | ret = sst->fw_ops.load_library(sst, ctx->lib_info, |
624 | ctx->lib_count); | ||
645 | if (ret < 0) { | 625 | if (ret < 0) { |
646 | dev_err(dev, "Load Library failed : %x\n", ret); | 626 | dev_err(dev, "Load Library failed : %x\n", ret); |
647 | return ret; | 627 | return ret; |
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index e79cbcf6e462..e66870474f10 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c | |||
@@ -220,6 +220,13 @@ static const struct skl_dsp_ops dsp_ops[] = { | |||
220 | .init_fw = bxt_sst_init_fw, | 220 | .init_fw = bxt_sst_init_fw, |
221 | .cleanup = bxt_sst_dsp_cleanup | 221 | .cleanup = bxt_sst_dsp_cleanup |
222 | }, | 222 | }, |
223 | { | ||
224 | .id = 0x3198, | ||
225 | .loader_ops = bxt_get_loader_ops, | ||
226 | .init = bxt_sst_dsp_init, | ||
227 | .init_fw = bxt_sst_init_fw, | ||
228 | .cleanup = bxt_sst_dsp_cleanup | ||
229 | }, | ||
223 | }; | 230 | }; |
224 | 231 | ||
225 | const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) | 232 | const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) |
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index 3f8e6f0b7eb5..7eb9c419dc7f 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c | |||
@@ -102,14 +102,16 @@ static void dump_config(struct device *dev, u32 instance_id, u8 linktype, | |||
102 | } | 102 | } |
103 | 103 | ||
104 | static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, | 104 | static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, |
105 | u32 instance_id, u8 link_type, u8 dirn) | 105 | u32 instance_id, u8 link_type, u8 dirn, u8 dev_type) |
106 | { | 106 | { |
107 | dev_dbg(dev, "vbus_id=%d link_type=%d dir=%d\n", | 107 | dev_dbg(dev, "vbus_id=%d link_type=%d dir=%d dev_type = %d\n", |
108 | epnt->virtual_bus_id, epnt->linktype, epnt->direction); | 108 | epnt->virtual_bus_id, epnt->linktype, |
109 | epnt->direction, epnt->device_type); | ||
109 | 110 | ||
110 | if ((epnt->virtual_bus_id == instance_id) && | 111 | if ((epnt->virtual_bus_id == instance_id) && |
111 | (epnt->linktype == link_type) && | 112 | (epnt->linktype == link_type) && |
112 | (epnt->direction == dirn)) | 113 | (epnt->direction == dirn) && |
114 | (epnt->device_type == dev_type)) | ||
113 | return true; | 115 | return true; |
114 | else | 116 | else |
115 | return false; | 117 | return false; |
@@ -117,7 +119,8 @@ static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, | |||
117 | 119 | ||
118 | struct nhlt_specific_cfg | 120 | struct nhlt_specific_cfg |
119 | *skl_get_ep_blob(struct skl *skl, u32 instance, u8 link_type, | 121 | *skl_get_ep_blob(struct skl *skl, u32 instance, u8 link_type, |
120 | u8 s_fmt, u8 num_ch, u32 s_rate, u8 dirn) | 122 | u8 s_fmt, u8 num_ch, u32 s_rate, |
123 | u8 dirn, u8 dev_type) | ||
121 | { | 124 | { |
122 | struct nhlt_fmt *fmt; | 125 | struct nhlt_fmt *fmt; |
123 | struct nhlt_endpoint *epnt; | 126 | struct nhlt_endpoint *epnt; |
@@ -135,7 +138,8 @@ struct nhlt_specific_cfg | |||
135 | dev_dbg(dev, "endpoint count =%d\n", nhlt->endpoint_count); | 138 | dev_dbg(dev, "endpoint count =%d\n", nhlt->endpoint_count); |
136 | 139 | ||
137 | for (j = 0; j < nhlt->endpoint_count; j++) { | 140 | for (j = 0; j < nhlt->endpoint_count; j++) { |
138 | if (skl_check_ep_match(dev, epnt, instance, link_type, dirn)) { | 141 | if (skl_check_ep_match(dev, epnt, instance, link_type, |
142 | dirn, dev_type)) { | ||
139 | fmt = (struct nhlt_fmt *)(epnt->config.caps + | 143 | fmt = (struct nhlt_fmt *)(epnt->config.caps + |
140 | epnt->config.size); | 144 | epnt->config.size); |
141 | sp_config = skl_get_specific_cfg(dev, fmt, num_ch, | 145 | sp_config = skl_get_specific_cfg(dev, fmt, num_ch, |
@@ -189,9 +193,9 @@ int skl_get_dmic_geo(struct skl *skl) | |||
189 | return dmic_geo; | 193 | return dmic_geo; |
190 | } | 194 | } |
191 | 195 | ||
192 | static void skl_nhlt_trim_space(struct skl *skl) | 196 | static void skl_nhlt_trim_space(char *trim) |
193 | { | 197 | { |
194 | char *s = skl->tplg_name; | 198 | char *s = trim; |
195 | int cnt; | 199 | int cnt; |
196 | int i; | 200 | int i; |
197 | 201 | ||
@@ -218,7 +222,43 @@ int skl_nhlt_update_topology_bin(struct skl *skl) | |||
218 | skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id, | 222 | skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id, |
219 | nhlt->header.oem_revision, "-tplg.bin"); | 223 | nhlt->header.oem_revision, "-tplg.bin"); |
220 | 224 | ||
221 | skl_nhlt_trim_space(skl); | 225 | skl_nhlt_trim_space(skl->tplg_name); |
222 | 226 | ||
223 | return 0; | 227 | return 0; |
224 | } | 228 | } |
229 | |||
230 | static ssize_t skl_nhlt_platform_id_show(struct device *dev, | ||
231 | struct device_attribute *attr, char *buf) | ||
232 | { | ||
233 | struct pci_dev *pci = to_pci_dev(dev); | ||
234 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | ||
235 | struct skl *skl = ebus_to_skl(ebus); | ||
236 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; | ||
237 | char platform_id[32]; | ||
238 | |||
239 | sprintf(platform_id, "%x-%.6s-%.8s-%d", skl->pci_id, | ||
240 | nhlt->header.oem_id, nhlt->header.oem_table_id, | ||
241 | nhlt->header.oem_revision); | ||
242 | |||
243 | skl_nhlt_trim_space(platform_id); | ||
244 | return sprintf(buf, "%s\n", platform_id); | ||
245 | } | ||
246 | |||
247 | static DEVICE_ATTR(platform_id, 0444, skl_nhlt_platform_id_show, NULL); | ||
248 | |||
249 | int skl_nhlt_create_sysfs(struct skl *skl) | ||
250 | { | ||
251 | struct device *dev = &skl->pci->dev; | ||
252 | |||
253 | if (sysfs_create_file(&dev->kobj, &dev_attr_platform_id.attr)) | ||
254 | dev_warn(dev, "Error creating sysfs entry\n"); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | void skl_nhlt_remove_sysfs(struct skl *skl) | ||
260 | { | ||
261 | struct device *dev = &skl->pci->dev; | ||
262 | |||
263 | sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); | ||
264 | } | ||
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 6c6b63a6b338..e12520e142ff 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c | |||
@@ -137,6 +137,80 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, | |||
137 | skl->supend_active--; | 137 | skl->supend_active--; |
138 | } | 138 | } |
139 | 139 | ||
140 | int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) | ||
141 | { | ||
142 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); | ||
143 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
144 | unsigned int format_val; | ||
145 | struct hdac_stream *hstream; | ||
146 | struct hdac_ext_stream *stream; | ||
147 | int err; | ||
148 | |||
149 | hstream = snd_hdac_get_stream(bus, params->stream, | ||
150 | params->host_dma_id + 1); | ||
151 | if (!hstream) | ||
152 | return -EINVAL; | ||
153 | |||
154 | stream = stream_to_hdac_ext_stream(hstream); | ||
155 | snd_hdac_ext_stream_decouple(ebus, stream, true); | ||
156 | |||
157 | format_val = snd_hdac_calc_stream_format(params->s_freq, | ||
158 | params->ch, params->format, 32, 0); | ||
159 | |||
160 | dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", | ||
161 | format_val, params->s_freq, params->ch, params->format); | ||
162 | |||
163 | snd_hdac_stream_reset(hdac_stream(stream)); | ||
164 | err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); | ||
165 | if (err < 0) | ||
166 | return err; | ||
167 | |||
168 | err = snd_hdac_stream_setup(hdac_stream(stream)); | ||
169 | if (err < 0) | ||
170 | return err; | ||
171 | |||
172 | hdac_stream(stream)->prepared = 1; | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) | ||
178 | { | ||
179 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); | ||
180 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
181 | unsigned int format_val; | ||
182 | struct hdac_stream *hstream; | ||
183 | struct hdac_ext_stream *stream; | ||
184 | struct hdac_ext_link *link; | ||
185 | |||
186 | hstream = snd_hdac_get_stream(bus, params->stream, | ||
187 | params->link_dma_id + 1); | ||
188 | if (!hstream) | ||
189 | return -EINVAL; | ||
190 | |||
191 | stream = stream_to_hdac_ext_stream(hstream); | ||
192 | snd_hdac_ext_stream_decouple(ebus, stream, true); | ||
193 | format_val = snd_hdac_calc_stream_format(params->s_freq, | ||
194 | params->ch, params->format, 24, 0); | ||
195 | |||
196 | dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", | ||
197 | format_val, params->s_freq, params->ch, params->format); | ||
198 | |||
199 | snd_hdac_ext_link_stream_reset(stream); | ||
200 | |||
201 | snd_hdac_ext_link_stream_setup(stream, format_val); | ||
202 | |||
203 | list_for_each_entry(link, &ebus->hlink_list, list) { | ||
204 | if (link->index == params->link_index) | ||
205 | snd_hdac_ext_link_set_stream_id(link, | ||
206 | hstream->stream_tag); | ||
207 | } | ||
208 | |||
209 | stream->link_prepared = 1; | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
140 | static int skl_pcm_open(struct snd_pcm_substream *substream, | 214 | static int skl_pcm_open(struct snd_pcm_substream *substream, |
141 | struct snd_soc_dai *dai) | 215 | struct snd_soc_dai *dai) |
142 | { | 216 | { |
@@ -188,32 +262,6 @@ static int skl_pcm_open(struct snd_pcm_substream *substream, | |||
188 | return 0; | 262 | return 0; |
189 | } | 263 | } |
190 | 264 | ||
191 | static int skl_get_format(struct snd_pcm_substream *substream, | ||
192 | struct snd_soc_dai *dai) | ||
193 | { | ||
194 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
195 | struct skl_dma_params *dma_params; | ||
196 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
197 | int format_val = 0; | ||
198 | |||
199 | if ((ebus_to_hbus(ebus))->ppcap) { | ||
200 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
201 | |||
202 | format_val = snd_hdac_calc_stream_format(runtime->rate, | ||
203 | runtime->channels, | ||
204 | runtime->format, | ||
205 | 32, 0); | ||
206 | } else { | ||
207 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
208 | |||
209 | dma_params = snd_soc_dai_get_dma_data(codec_dai, substream); | ||
210 | if (dma_params) | ||
211 | format_val = dma_params->format; | ||
212 | } | ||
213 | |||
214 | return format_val; | ||
215 | } | ||
216 | |||
217 | static int skl_be_prepare(struct snd_pcm_substream *substream, | 265 | static int skl_be_prepare(struct snd_pcm_substream *substream, |
218 | struct snd_soc_dai *dai) | 266 | struct snd_soc_dai *dai) |
219 | { | 267 | { |
@@ -234,37 +282,19 @@ static int skl_be_prepare(struct snd_pcm_substream *substream, | |||
234 | static int skl_pcm_prepare(struct snd_pcm_substream *substream, | 282 | static int skl_pcm_prepare(struct snd_pcm_substream *substream, |
235 | struct snd_soc_dai *dai) | 283 | struct snd_soc_dai *dai) |
236 | { | 284 | { |
237 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | ||
238 | struct skl *skl = get_skl_ctx(dai->dev); | 285 | struct skl *skl = get_skl_ctx(dai->dev); |
239 | unsigned int format_val; | ||
240 | int err; | ||
241 | struct skl_module_cfg *mconfig; | 286 | struct skl_module_cfg *mconfig; |
242 | 287 | ||
243 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | 288 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); |
244 | 289 | ||
245 | mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); | 290 | mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); |
246 | 291 | ||
247 | format_val = skl_get_format(substream, dai); | ||
248 | dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n", | ||
249 | hdac_stream(stream)->stream_tag, format_val); | ||
250 | snd_hdac_stream_reset(hdac_stream(stream)); | ||
251 | |||
252 | /* In case of XRUN recovery, reset the FW pipe to clean state */ | 292 | /* In case of XRUN recovery, reset the FW pipe to clean state */ |
253 | if (mconfig && (substream->runtime->status->state == | 293 | if (mconfig && (substream->runtime->status->state == |
254 | SNDRV_PCM_STATE_XRUN)) | 294 | SNDRV_PCM_STATE_XRUN)) |
255 | skl_reset_pipe(skl->skl_sst, mconfig->pipe); | 295 | skl_reset_pipe(skl->skl_sst, mconfig->pipe); |
256 | 296 | ||
257 | err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); | 297 | return 0; |
258 | if (err < 0) | ||
259 | return err; | ||
260 | |||
261 | err = snd_hdac_stream_setup(hdac_stream(stream)); | ||
262 | if (err < 0) | ||
263 | return err; | ||
264 | |||
265 | hdac_stream(stream)->prepared = 1; | ||
266 | |||
267 | return err; | ||
268 | } | 298 | } |
269 | 299 | ||
270 | static int skl_pcm_hw_params(struct snd_pcm_substream *substream, | 300 | static int skl_pcm_hw_params(struct snd_pcm_substream *substream, |
@@ -295,6 +325,7 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream, | |||
295 | p_params.s_freq = params_rate(params); | 325 | p_params.s_freq = params_rate(params); |
296 | p_params.host_dma_id = dma_id; | 326 | p_params.host_dma_id = dma_id; |
297 | p_params.stream = substream->stream; | 327 | p_params.stream = substream->stream; |
328 | p_params.format = params_format(params); | ||
298 | 329 | ||
299 | m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream); | 330 | m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream); |
300 | if (m_cfg) | 331 | if (m_cfg) |
@@ -438,7 +469,6 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
438 | switch (cmd) { | 469 | switch (cmd) { |
439 | case SNDRV_PCM_TRIGGER_RESUME: | 470 | case SNDRV_PCM_TRIGGER_RESUME: |
440 | if (!w->ignore_suspend) { | 471 | if (!w->ignore_suspend) { |
441 | skl_pcm_prepare(substream, dai); | ||
442 | /* | 472 | /* |
443 | * enable DMA Resume enable bit for the stream, set the | 473 | * enable DMA Resume enable bit for the stream, set the |
444 | * dpib & lpib position to resume before starting the | 474 | * dpib & lpib position to resume before starting the |
@@ -447,7 +477,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
447 | snd_hdac_ext_stream_drsm_enable(ebus, true, | 477 | snd_hdac_ext_stream_drsm_enable(ebus, true, |
448 | hdac_stream(stream)->index); | 478 | hdac_stream(stream)->index); |
449 | snd_hdac_ext_stream_set_dpibr(ebus, stream, | 479 | snd_hdac_ext_stream_set_dpibr(ebus, stream, |
450 | stream->dpib); | 480 | stream->lpib); |
451 | snd_hdac_ext_stream_set_lpib(stream, stream->lpib); | 481 | snd_hdac_ext_stream_set_lpib(stream, stream->lpib); |
452 | } | 482 | } |
453 | 483 | ||
@@ -459,7 +489,6 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
459 | * pipeline is started but there is a delay in starting the | 489 | * pipeline is started but there is a delay in starting the |
460 | * DMA channel on the host. | 490 | * DMA channel on the host. |
461 | */ | 491 | */ |
462 | snd_hdac_ext_stream_decouple(ebus, stream, true); | ||
463 | ret = skl_decoupled_trigger(substream, cmd); | 492 | ret = skl_decoupled_trigger(substream, cmd); |
464 | if (ret < 0) | 493 | if (ret < 0) |
465 | return ret; | 494 | return ret; |
@@ -506,9 +535,10 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, | |||
506 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | 535 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); |
507 | struct hdac_ext_stream *link_dev; | 536 | struct hdac_ext_stream *link_dev; |
508 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | 537 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); |
509 | struct hdac_ext_dma_params *dma_params; | ||
510 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 538 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
511 | struct skl_pipe_params p_params = {0}; | 539 | struct skl_pipe_params p_params = {0}; |
540 | struct hdac_ext_link *link; | ||
541 | int stream_tag; | ||
512 | 542 | ||
513 | link_dev = snd_hdac_ext_stream_assign(ebus, substream, | 543 | link_dev = snd_hdac_ext_stream_assign(ebus, substream, |
514 | HDAC_EXT_STREAM_TYPE_LINK); | 544 | HDAC_EXT_STREAM_TYPE_LINK); |
@@ -517,16 +547,22 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, | |||
517 | 547 | ||
518 | snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); | 548 | snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); |
519 | 549 | ||
550 | link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name); | ||
551 | if (!link) | ||
552 | return -EINVAL; | ||
553 | |||
554 | stream_tag = hdac_stream(link_dev)->stream_tag; | ||
555 | |||
520 | /* set the stream tag in the codec dai dma params */ | 556 | /* set the stream tag in the codec dai dma params */ |
521 | dma_params = snd_soc_dai_get_dma_data(codec_dai, substream); | 557 | snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 0); |
522 | if (dma_params) | ||
523 | dma_params->stream_tag = hdac_stream(link_dev)->stream_tag; | ||
524 | 558 | ||
525 | p_params.s_fmt = snd_pcm_format_width(params_format(params)); | 559 | p_params.s_fmt = snd_pcm_format_width(params_format(params)); |
526 | p_params.ch = params_channels(params); | 560 | p_params.ch = params_channels(params); |
527 | p_params.s_freq = params_rate(params); | 561 | p_params.s_freq = params_rate(params); |
528 | p_params.stream = substream->stream; | 562 | p_params.stream = substream->stream; |
529 | p_params.link_dma_id = hdac_stream(link_dev)->stream_tag - 1; | 563 | p_params.link_dma_id = stream_tag - 1; |
564 | p_params.link_index = link->index; | ||
565 | p_params.format = params_format(params); | ||
530 | 566 | ||
531 | return skl_tplg_be_update_params(dai, &p_params); | 567 | return skl_tplg_be_update_params(dai, &p_params); |
532 | } | 568 | } |
@@ -534,41 +570,15 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, | |||
534 | static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, | 570 | static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, |
535 | struct snd_soc_dai *dai) | 571 | struct snd_soc_dai *dai) |
536 | { | 572 | { |
537 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
538 | struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); | ||
539 | struct hdac_ext_stream *link_dev = | ||
540 | snd_soc_dai_get_dma_data(dai, substream); | ||
541 | unsigned int format_val = 0; | ||
542 | struct skl_dma_params *dma_params; | ||
543 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
544 | struct hdac_ext_link *link; | ||
545 | struct skl *skl = get_skl_ctx(dai->dev); | 573 | struct skl *skl = get_skl_ctx(dai->dev); |
546 | struct skl_module_cfg *mconfig = NULL; | 574 | struct skl_module_cfg *mconfig = NULL; |
547 | 575 | ||
548 | dma_params = (struct skl_dma_params *) | ||
549 | snd_soc_dai_get_dma_data(codec_dai, substream); | ||
550 | if (dma_params) | ||
551 | format_val = dma_params->format; | ||
552 | dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n", | ||
553 | hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name); | ||
554 | |||
555 | link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name); | ||
556 | if (!link) | ||
557 | return -EINVAL; | ||
558 | |||
559 | snd_hdac_ext_link_stream_reset(link_dev); | ||
560 | |||
561 | /* In case of XRUN recovery, reset the FW pipe to clean state */ | 576 | /* In case of XRUN recovery, reset the FW pipe to clean state */ |
562 | mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); | 577 | mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); |
563 | if (mconfig && (substream->runtime->status->state == | 578 | if (mconfig && !mconfig->pipe->passthru && |
564 | SNDRV_PCM_STATE_XRUN)) | 579 | (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) |
565 | skl_reset_pipe(skl->skl_sst, mconfig->pipe); | 580 | skl_reset_pipe(skl->skl_sst, mconfig->pipe); |
566 | 581 | ||
567 | snd_hdac_ext_link_stream_setup(link_dev, format_val); | ||
568 | |||
569 | snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag); | ||
570 | link_dev->link_prepared = 1; | ||
571 | |||
572 | return 0; | 582 | return 0; |
573 | } | 583 | } |
574 | 584 | ||
@@ -583,10 +593,8 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream, | |||
583 | dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd); | 593 | dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd); |
584 | switch (cmd) { | 594 | switch (cmd) { |
585 | case SNDRV_PCM_TRIGGER_RESUME: | 595 | case SNDRV_PCM_TRIGGER_RESUME: |
586 | skl_link_pcm_prepare(substream, dai); | ||
587 | case SNDRV_PCM_TRIGGER_START: | 596 | case SNDRV_PCM_TRIGGER_START: |
588 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 597 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
589 | snd_hdac_ext_stream_decouple(ebus, stream, true); | ||
590 | snd_hdac_ext_link_stream_start(link_dev); | 598 | snd_hdac_ext_link_stream_start(link_dev); |
591 | break; | 599 | break; |
592 | 600 | ||
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 7c272ba0f4b5..849410d0823e 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <sound/memalloc.h> | 20 | #include <sound/memalloc.h> |
21 | #include "skl-sst-cldma.h" | 21 | #include "skl-sst-cldma.h" |
22 | #include "skl-tplg-interface.h" | ||
23 | #include "skl-topology.h" | 22 | #include "skl-topology.h" |
24 | 23 | ||
25 | struct sst_dsp; | 24 | struct sst_dsp; |
@@ -145,7 +144,7 @@ struct skl_dsp_fw_ops { | |||
145 | int (*load_fw)(struct sst_dsp *ctx); | 144 | int (*load_fw)(struct sst_dsp *ctx); |
146 | /* FW module parser/loader */ | 145 | /* FW module parser/loader */ |
147 | int (*load_library)(struct sst_dsp *ctx, | 146 | int (*load_library)(struct sst_dsp *ctx, |
148 | struct skl_dfw_manifest *minfo); | 147 | struct skl_lib_info *linfo, int count); |
149 | int (*parse_fw)(struct sst_dsp *ctx); | 148 | int (*parse_fw)(struct sst_dsp *ctx); |
150 | int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id); | 149 | int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id); |
151 | int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id); | 150 | int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id); |
@@ -236,5 +235,4 @@ int skl_get_pvt_instance_id_map(struct skl_sst *ctx, | |||
236 | void skl_freeup_uuid_list(struct skl_sst *ctx); | 235 | void skl_freeup_uuid_list(struct skl_sst *ctx); |
237 | 236 | ||
238 | int skl_dsp_strip_extended_manifest(struct firmware *fw); | 237 | int skl_dsp_strip_extended_manifest(struct firmware *fw); |
239 | |||
240 | #endif /*__SKL_SST_DSP_H__*/ | 238 | #endif /*__SKL_SST_DSP_H__*/ |
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index cc40341233fa..9660ace379ab 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h | |||
@@ -97,8 +97,9 @@ struct skl_sst { | |||
97 | /* multi-core */ | 97 | /* multi-core */ |
98 | struct skl_dsp_cores cores; | 98 | struct skl_dsp_cores cores; |
99 | 99 | ||
100 | /* tplg manifest */ | 100 | /* library info */ |
101 | struct skl_dfw_manifest manifest; | 101 | struct skl_lib_info lib_info[SKL_MAX_LIB]; |
102 | int lib_count; | ||
102 | 103 | ||
103 | /* Callback to update D0i3C register */ | 104 | /* Callback to update D0i3C register */ |
104 | void (*update_d0i3c)(struct device *dev, bool enable); | 105 | void (*update_d0i3c)(struct device *dev, bool enable); |
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index bd313c907b20..ed58b5b3555a 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c | |||
@@ -330,6 +330,31 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx, | |||
330 | multiplier; | 330 | multiplier; |
331 | } | 331 | } |
332 | 332 | ||
333 | static u8 skl_tplg_be_dev_type(int dev_type) | ||
334 | { | ||
335 | int ret; | ||
336 | |||
337 | switch (dev_type) { | ||
338 | case SKL_DEVICE_BT: | ||
339 | ret = NHLT_DEVICE_BT; | ||
340 | break; | ||
341 | |||
342 | case SKL_DEVICE_DMIC: | ||
343 | ret = NHLT_DEVICE_DMIC; | ||
344 | break; | ||
345 | |||
346 | case SKL_DEVICE_I2S: | ||
347 | ret = NHLT_DEVICE_I2S; | ||
348 | break; | ||
349 | |||
350 | default: | ||
351 | ret = NHLT_DEVICE_INVALID; | ||
352 | break; | ||
353 | } | ||
354 | |||
355 | return ret; | ||
356 | } | ||
357 | |||
333 | static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, | 358 | static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, |
334 | struct skl_sst *ctx) | 359 | struct skl_sst *ctx) |
335 | { | 360 | { |
@@ -338,6 +363,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, | |||
338 | u32 ch, s_freq, s_fmt; | 363 | u32 ch, s_freq, s_fmt; |
339 | struct nhlt_specific_cfg *cfg; | 364 | struct nhlt_specific_cfg *cfg; |
340 | struct skl *skl = get_skl_ctx(ctx->dev); | 365 | struct skl *skl = get_skl_ctx(ctx->dev); |
366 | u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); | ||
341 | 367 | ||
342 | /* check if we already have blob */ | 368 | /* check if we already have blob */ |
343 | if (m_cfg->formats_config.caps_size > 0) | 369 | if (m_cfg->formats_config.caps_size > 0) |
@@ -374,7 +400,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, | |||
374 | 400 | ||
375 | /* update the blob based on virtual bus_id and default params */ | 401 | /* update the blob based on virtual bus_id and default params */ |
376 | cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type, | 402 | cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type, |
377 | s_fmt, ch, s_freq, dir); | 403 | s_fmt, ch, s_freq, dir, dev_type); |
378 | if (cfg) { | 404 | if (cfg) { |
379 | m_cfg->formats_config.caps_size = cfg->size; | 405 | m_cfg->formats_config.caps_size = cfg->size; |
380 | m_cfg->formats_config.caps = (u32 *) &cfg->caps; | 406 | m_cfg->formats_config.caps = (u32 *) &cfg->caps; |
@@ -496,6 +522,20 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) | |||
496 | return 0; | 522 | return 0; |
497 | } | 523 | } |
498 | 524 | ||
525 | static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe, | ||
526 | struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) | ||
527 | { | ||
528 | switch (mcfg->dev_type) { | ||
529 | case SKL_DEVICE_HDAHOST: | ||
530 | return skl_pcm_host_dma_prepare(ctx->dev, pipe->p_params); | ||
531 | |||
532 | case SKL_DEVICE_HDALINK: | ||
533 | return skl_pcm_link_dma_prepare(ctx->dev, pipe->p_params); | ||
534 | } | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
499 | /* | 539 | /* |
500 | * Inside a pipe instance, we can have various modules. These modules need | 540 | * Inside a pipe instance, we can have various modules. These modules need |
501 | * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by | 541 | * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by |
@@ -535,6 +575,11 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) | |||
535 | mconfig->m_state = SKL_MODULE_LOADED; | 575 | mconfig->m_state = SKL_MODULE_LOADED; |
536 | } | 576 | } |
537 | 577 | ||
578 | /* prepare the DMA if the module is gateway cpr */ | ||
579 | ret = skl_tplg_module_prepare(ctx, pipe, w, mconfig); | ||
580 | if (ret < 0) | ||
581 | return ret; | ||
582 | |||
538 | /* update blob if blob is null for be with default value */ | 583 | /* update blob if blob is null for be with default value */ |
539 | skl_tplg_update_be_blob(w, ctx); | 584 | skl_tplg_update_be_blob(w, ctx); |
540 | 585 | ||
@@ -974,7 +1019,6 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, | |||
974 | struct skl_module_cfg *src_module = NULL, *dst_module; | 1019 | struct skl_module_cfg *src_module = NULL, *dst_module; |
975 | struct skl_sst *ctx = skl->skl_sst; | 1020 | struct skl_sst *ctx = skl->skl_sst; |
976 | struct skl_pipe *s_pipe = mconfig->pipe; | 1021 | struct skl_pipe *s_pipe = mconfig->pipe; |
977 | int ret = 0; | ||
978 | 1022 | ||
979 | if (s_pipe->state == SKL_PIPE_INVALID) | 1023 | if (s_pipe->state == SKL_PIPE_INVALID) |
980 | return -EINVAL; | 1024 | return -EINVAL; |
@@ -996,7 +1040,7 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, | |||
996 | src_module = dst_module; | 1040 | src_module = dst_module; |
997 | } | 1041 | } |
998 | 1042 | ||
999 | ret = skl_delete_pipe(ctx, mconfig->pipe); | 1043 | skl_delete_pipe(ctx, mconfig->pipe); |
1000 | 1044 | ||
1001 | return skl_tplg_unload_pipe_modules(ctx, s_pipe); | 1045 | return skl_tplg_unload_pipe_modules(ctx, s_pipe); |
1002 | } | 1046 | } |
@@ -1207,6 +1251,7 @@ static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, | |||
1207 | switch (mcfg->dev_type) { | 1251 | switch (mcfg->dev_type) { |
1208 | case SKL_DEVICE_HDALINK: | 1252 | case SKL_DEVICE_HDALINK: |
1209 | pipe->p_params->link_dma_id = params->link_dma_id; | 1253 | pipe->p_params->link_dma_id = params->link_dma_id; |
1254 | pipe->p_params->link_index = params->link_index; | ||
1210 | break; | 1255 | break; |
1211 | 1256 | ||
1212 | case SKL_DEVICE_HDAHOST: | 1257 | case SKL_DEVICE_HDAHOST: |
@@ -1220,6 +1265,7 @@ static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, | |||
1220 | pipe->p_params->ch = params->ch; | 1265 | pipe->p_params->ch = params->ch; |
1221 | pipe->p_params->s_freq = params->s_freq; | 1266 | pipe->p_params->s_freq = params->s_freq; |
1222 | pipe->p_params->stream = params->stream; | 1267 | pipe->p_params->stream = params->stream; |
1268 | pipe->p_params->format = params->format; | ||
1223 | 1269 | ||
1224 | } else { | 1270 | } else { |
1225 | memcpy(pipe->p_params, params, sizeof(*params)); | 1271 | memcpy(pipe->p_params, params, sizeof(*params)); |
@@ -1428,6 +1474,7 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, | |||
1428 | struct nhlt_specific_cfg *cfg; | 1474 | struct nhlt_specific_cfg *cfg; |
1429 | struct skl *skl = get_skl_ctx(dai->dev); | 1475 | struct skl *skl = get_skl_ctx(dai->dev); |
1430 | int link_type = skl_tplg_be_link_type(mconfig->dev_type); | 1476 | int link_type = skl_tplg_be_link_type(mconfig->dev_type); |
1477 | u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); | ||
1431 | 1478 | ||
1432 | skl_tplg_fill_dma_id(mconfig, params); | 1479 | skl_tplg_fill_dma_id(mconfig, params); |
1433 | 1480 | ||
@@ -1437,7 +1484,8 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, | |||
1437 | /* update the blob based on virtual bus_id*/ | 1484 | /* update the blob based on virtual bus_id*/ |
1438 | cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type, | 1485 | cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type, |
1439 | params->s_fmt, params->ch, | 1486 | params->s_fmt, params->ch, |
1440 | params->s_freq, params->stream); | 1487 | params->s_freq, params->stream, |
1488 | dev_type); | ||
1441 | if (cfg) { | 1489 | if (cfg) { |
1442 | mconfig->formats_config.caps_size = cfg->size; | 1490 | mconfig->formats_config.caps_size = cfg->size; |
1443 | mconfig->formats_config.caps = (u32 *) &cfg->caps; | 1491 | mconfig->formats_config.caps = (u32 *) &cfg->caps; |
@@ -2280,20 +2328,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, | |||
2280 | 2328 | ||
2281 | static int skl_tplg_fill_str_mfest_tkn(struct device *dev, | 2329 | static int skl_tplg_fill_str_mfest_tkn(struct device *dev, |
2282 | struct snd_soc_tplg_vendor_string_elem *str_elem, | 2330 | struct snd_soc_tplg_vendor_string_elem *str_elem, |
2283 | struct skl_dfw_manifest *minfo) | 2331 | struct skl *skl) |
2284 | { | 2332 | { |
2285 | int tkn_count = 0; | 2333 | int tkn_count = 0; |
2286 | static int ref_count; | 2334 | static int ref_count; |
2287 | 2335 | ||
2288 | switch (str_elem->token) { | 2336 | switch (str_elem->token) { |
2289 | case SKL_TKN_STR_LIB_NAME: | 2337 | case SKL_TKN_STR_LIB_NAME: |
2290 | if (ref_count > minfo->lib_count - 1) { | 2338 | if (ref_count > skl->skl_sst->lib_count - 1) { |
2291 | ref_count = 0; | 2339 | ref_count = 0; |
2292 | return -EINVAL; | 2340 | return -EINVAL; |
2293 | } | 2341 | } |
2294 | 2342 | ||
2295 | strncpy(minfo->lib[ref_count].name, str_elem->string, | 2343 | strncpy(skl->skl_sst->lib_info[ref_count].name, |
2296 | ARRAY_SIZE(minfo->lib[ref_count].name)); | 2344 | str_elem->string, |
2345 | ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); | ||
2297 | ref_count++; | 2346 | ref_count++; |
2298 | tkn_count++; | 2347 | tkn_count++; |
2299 | break; | 2348 | break; |
@@ -2308,14 +2357,14 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev, | |||
2308 | 2357 | ||
2309 | static int skl_tplg_get_str_tkn(struct device *dev, | 2358 | static int skl_tplg_get_str_tkn(struct device *dev, |
2310 | struct snd_soc_tplg_vendor_array *array, | 2359 | struct snd_soc_tplg_vendor_array *array, |
2311 | struct skl_dfw_manifest *minfo) | 2360 | struct skl *skl) |
2312 | { | 2361 | { |
2313 | int tkn_count = 0, ret; | 2362 | int tkn_count = 0, ret; |
2314 | struct snd_soc_tplg_vendor_string_elem *str_elem; | 2363 | struct snd_soc_tplg_vendor_string_elem *str_elem; |
2315 | 2364 | ||
2316 | str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; | 2365 | str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; |
2317 | while (tkn_count < array->num_elems) { | 2366 | while (tkn_count < array->num_elems) { |
2318 | ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, minfo); | 2367 | ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl); |
2319 | str_elem++; | 2368 | str_elem++; |
2320 | 2369 | ||
2321 | if (ret < 0) | 2370 | if (ret < 0) |
@@ -2329,13 +2378,13 @@ static int skl_tplg_get_str_tkn(struct device *dev, | |||
2329 | 2378 | ||
2330 | static int skl_tplg_get_int_tkn(struct device *dev, | 2379 | static int skl_tplg_get_int_tkn(struct device *dev, |
2331 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, | 2380 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, |
2332 | struct skl_dfw_manifest *minfo) | 2381 | struct skl *skl) |
2333 | { | 2382 | { |
2334 | int tkn_count = 0; | 2383 | int tkn_count = 0; |
2335 | 2384 | ||
2336 | switch (tkn_elem->token) { | 2385 | switch (tkn_elem->token) { |
2337 | case SKL_TKN_U32_LIB_COUNT: | 2386 | case SKL_TKN_U32_LIB_COUNT: |
2338 | minfo->lib_count = tkn_elem->value; | 2387 | skl->skl_sst->lib_count = tkn_elem->value; |
2339 | tkn_count++; | 2388 | tkn_count++; |
2340 | break; | 2389 | break; |
2341 | 2390 | ||
@@ -2352,7 +2401,7 @@ static int skl_tplg_get_int_tkn(struct device *dev, | |||
2352 | * type. | 2401 | * type. |
2353 | */ | 2402 | */ |
2354 | static int skl_tplg_get_manifest_tkn(struct device *dev, | 2403 | static int skl_tplg_get_manifest_tkn(struct device *dev, |
2355 | char *pvt_data, struct skl_dfw_manifest *minfo, | 2404 | char *pvt_data, struct skl *skl, |
2356 | int block_size) | 2405 | int block_size) |
2357 | { | 2406 | { |
2358 | int tkn_count = 0, ret; | 2407 | int tkn_count = 0, ret; |
@@ -2368,7 +2417,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, | |||
2368 | off += array->size; | 2417 | off += array->size; |
2369 | switch (array->type) { | 2418 | switch (array->type) { |
2370 | case SND_SOC_TPLG_TUPLE_TYPE_STRING: | 2419 | case SND_SOC_TPLG_TUPLE_TYPE_STRING: |
2371 | ret = skl_tplg_get_str_tkn(dev, array, minfo); | 2420 | ret = skl_tplg_get_str_tkn(dev, array, skl); |
2372 | 2421 | ||
2373 | if (ret < 0) | 2422 | if (ret < 0) |
2374 | return ret; | 2423 | return ret; |
@@ -2390,7 +2439,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, | |||
2390 | 2439 | ||
2391 | while (tkn_count <= array->num_elems - 1) { | 2440 | while (tkn_count <= array->num_elems - 1) { |
2392 | ret = skl_tplg_get_int_tkn(dev, | 2441 | ret = skl_tplg_get_int_tkn(dev, |
2393 | tkn_elem, minfo); | 2442 | tkn_elem, skl); |
2394 | if (ret < 0) | 2443 | if (ret < 0) |
2395 | return ret; | 2444 | return ret; |
2396 | 2445 | ||
@@ -2411,7 +2460,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, | |||
2411 | * preceded by descriptors for type and size of data block. | 2460 | * preceded by descriptors for type and size of data block. |
2412 | */ | 2461 | */ |
2413 | static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, | 2462 | static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, |
2414 | struct device *dev, struct skl_dfw_manifest *minfo) | 2463 | struct device *dev, struct skl *skl) |
2415 | { | 2464 | { |
2416 | struct snd_soc_tplg_vendor_array *array; | 2465 | struct snd_soc_tplg_vendor_array *array; |
2417 | int num_blocks, block_size = 0, block_type, off = 0; | 2466 | int num_blocks, block_size = 0, block_type, off = 0; |
@@ -2454,7 +2503,7 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, | |||
2454 | data = (manifest->priv.data + off); | 2503 | data = (manifest->priv.data + off); |
2455 | 2504 | ||
2456 | if (block_type == SKL_TYPE_TUPLE) { | 2505 | if (block_type == SKL_TYPE_TUPLE) { |
2457 | ret = skl_tplg_get_manifest_tkn(dev, data, minfo, | 2506 | ret = skl_tplg_get_manifest_tkn(dev, data, skl, |
2458 | block_size); | 2507 | block_size); |
2459 | 2508 | ||
2460 | if (ret < 0) | 2509 | if (ret < 0) |
@@ -2472,27 +2521,23 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, | |||
2472 | static int skl_manifest_load(struct snd_soc_component *cmpnt, | 2521 | static int skl_manifest_load(struct snd_soc_component *cmpnt, |
2473 | struct snd_soc_tplg_manifest *manifest) | 2522 | struct snd_soc_tplg_manifest *manifest) |
2474 | { | 2523 | { |
2475 | struct skl_dfw_manifest *minfo; | ||
2476 | struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); | 2524 | struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); |
2477 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 2525 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
2478 | struct skl *skl = ebus_to_skl(ebus); | 2526 | struct skl *skl = ebus_to_skl(ebus); |
2479 | int ret = 0; | ||
2480 | 2527 | ||
2481 | /* proceed only if we have private data defined */ | 2528 | /* proceed only if we have private data defined */ |
2482 | if (manifest->priv.size == 0) | 2529 | if (manifest->priv.size == 0) |
2483 | return 0; | 2530 | return 0; |
2484 | 2531 | ||
2485 | minfo = &skl->skl_sst->manifest; | 2532 | skl_tplg_get_manifest_data(manifest, bus->dev, skl); |
2486 | |||
2487 | skl_tplg_get_manifest_data(manifest, bus->dev, minfo); | ||
2488 | 2533 | ||
2489 | if (minfo->lib_count > HDA_MAX_LIB) { | 2534 | if (skl->skl_sst->lib_count > SKL_MAX_LIB) { |
2490 | dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", | 2535 | dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", |
2491 | minfo->lib_count); | 2536 | skl->skl_sst->lib_count); |
2492 | ret = -EINVAL; | 2537 | return -EINVAL; |
2493 | } | 2538 | } |
2494 | 2539 | ||
2495 | return ret; | 2540 | return 0; |
2496 | } | 2541 | } |
2497 | 2542 | ||
2498 | static struct snd_soc_tplg_ops skl_tplg_ops = { | 2543 | static struct snd_soc_tplg_ops skl_tplg_ops = { |
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 08d39280b07b..fefab0e99a3b 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h | |||
@@ -254,6 +254,8 @@ struct skl_pipe_params { | |||
254 | u32 s_freq; | 254 | u32 s_freq; |
255 | u32 s_fmt; | 255 | u32 s_fmt; |
256 | u8 linktype; | 256 | u8 linktype; |
257 | snd_pcm_format_t format; | ||
258 | int link_index; | ||
257 | int stream; | 259 | int stream; |
258 | }; | 260 | }; |
259 | 261 | ||
@@ -332,6 +334,19 @@ struct skl_pipeline { | |||
332 | struct list_head node; | 334 | struct list_head node; |
333 | }; | 335 | }; |
334 | 336 | ||
337 | #define SKL_LIB_NAME_LENGTH 128 | ||
338 | #define SKL_MAX_LIB 16 | ||
339 | |||
340 | struct skl_lib_info { | ||
341 | char name[SKL_LIB_NAME_LENGTH]; | ||
342 | const struct firmware *fw; | ||
343 | }; | ||
344 | |||
345 | struct skl_manifest { | ||
346 | u32 lib_count; | ||
347 | struct skl_lib_info lib[SKL_MAX_LIB]; | ||
348 | }; | ||
349 | |||
335 | static inline struct skl *get_skl_ctx(struct device *dev) | 350 | static inline struct skl *get_skl_ctx(struct device *dev) |
336 | { | 351 | { |
337 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); | 352 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); |
@@ -383,4 +398,8 @@ int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, | |||
383 | struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, | 398 | struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, |
384 | int stream); | 399 | int stream); |
385 | enum skl_bitdepth skl_get_bit_depth(int params); | 400 | enum skl_bitdepth skl_get_bit_depth(int params); |
401 | int skl_pcm_host_dma_prepare(struct device *dev, | ||
402 | struct skl_pipe_params *params); | ||
403 | int skl_pcm_link_dma_prepare(struct device *dev, | ||
404 | struct skl_pipe_params *params); | ||
386 | #endif | 405 | #endif |
diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 2f6281e056d6..7a2febf99019 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h | |||
@@ -157,18 +157,6 @@ struct skl_dfw_algo_data { | |||
157 | char params[0]; | 157 | char params[0]; |
158 | } __packed; | 158 | } __packed; |
159 | 159 | ||
160 | #define LIB_NAME_LENGTH 128 | ||
161 | #define HDA_MAX_LIB 16 | ||
162 | |||
163 | struct lib_info { | ||
164 | char name[LIB_NAME_LENGTH]; | ||
165 | } __packed; | ||
166 | |||
167 | struct skl_dfw_manifest { | ||
168 | u32 lib_count; | ||
169 | struct lib_info lib[HDA_MAX_LIB]; | ||
170 | } __packed; | ||
171 | |||
172 | enum skl_tkn_dir { | 160 | enum skl_tkn_dir { |
173 | SKL_DIR_IN, | 161 | SKL_DIR_IN, |
174 | SKL_DIR_OUT | 162 | SKL_DIR_OUT |
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index da5db5098274..0c57d4eaae3a 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c | |||
@@ -732,6 +732,10 @@ static int skl_probe(struct pci_dev *pci, | |||
732 | goto out_display_power_off; | 732 | goto out_display_power_off; |
733 | } | 733 | } |
734 | 734 | ||
735 | err = skl_nhlt_create_sysfs(skl); | ||
736 | if (err < 0) | ||
737 | goto out_nhlt_free; | ||
738 | |||
735 | skl_nhlt_update_topology_bin(skl); | 739 | skl_nhlt_update_topology_bin(skl); |
736 | 740 | ||
737 | pci_set_drvdata(skl->pci, ebus); | 741 | pci_set_drvdata(skl->pci, ebus); |
@@ -852,6 +856,7 @@ static void skl_remove(struct pci_dev *pci) | |||
852 | skl_free_dsp(skl); | 856 | skl_free_dsp(skl); |
853 | skl_machine_device_unregister(skl); | 857 | skl_machine_device_unregister(skl); |
854 | skl_dmic_device_unregister(skl); | 858 | skl_dmic_device_unregister(skl); |
859 | skl_nhlt_remove_sysfs(skl); | ||
855 | skl_nhlt_free(skl->nhlt); | 860 | skl_nhlt_free(skl->nhlt); |
856 | skl_free(ebus); | 861 | skl_free(ebus); |
857 | dev_set_drvdata(&pci->dev, NULL); | 862 | dev_set_drvdata(&pci->dev, NULL); |
@@ -878,6 +883,10 @@ static struct sst_acpi_mach sst_kbl_devdata[] = { | |||
878 | {} | 883 | {} |
879 | }; | 884 | }; |
880 | 885 | ||
886 | static struct sst_acpi_mach sst_glk_devdata[] = { | ||
887 | { "INT343A", "glk_alc298s_i2s", "intel/dsp_fw_glk.bin", NULL, NULL, NULL }, | ||
888 | }; | ||
889 | |||
881 | /* PCI IDs */ | 890 | /* PCI IDs */ |
882 | static const struct pci_device_id skl_ids[] = { | 891 | static const struct pci_device_id skl_ids[] = { |
883 | /* Sunrise Point-LP */ | 892 | /* Sunrise Point-LP */ |
@@ -889,6 +898,9 @@ static const struct pci_device_id skl_ids[] = { | |||
889 | /* KBL */ | 898 | /* KBL */ |
890 | { PCI_DEVICE(0x8086, 0x9D71), | 899 | { PCI_DEVICE(0x8086, 0x9D71), |
891 | .driver_data = (unsigned long)&sst_kbl_devdata}, | 900 | .driver_data = (unsigned long)&sst_kbl_devdata}, |
901 | /* GLK */ | ||
902 | { PCI_DEVICE(0x8086, 0x3198), | ||
903 | .driver_data = (unsigned long)&sst_glk_devdata}, | ||
892 | { 0, } | 904 | { 0, } |
893 | }; | 905 | }; |
894 | MODULE_DEVICE_TABLE(pci, skl_ids); | 906 | MODULE_DEVICE_TABLE(pci, skl_ids); |
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 4986e3929dd3..bbef77d2b917 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h | |||
@@ -118,7 +118,8 @@ int skl_platform_register(struct device *dev); | |||
118 | struct nhlt_acpi_table *skl_nhlt_init(struct device *dev); | 118 | struct nhlt_acpi_table *skl_nhlt_init(struct device *dev); |
119 | void skl_nhlt_free(struct nhlt_acpi_table *addr); | 119 | void skl_nhlt_free(struct nhlt_acpi_table *addr); |
120 | struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, | 120 | struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, |
121 | u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn); | 121 | u8 link_type, u8 s_fmt, u8 no_ch, |
122 | u32 s_rate, u8 dirn, u8 dev_type); | ||
122 | 123 | ||
123 | int skl_get_dmic_geo(struct skl *skl); | 124 | int skl_get_dmic_geo(struct skl *skl); |
124 | int skl_nhlt_update_topology_bin(struct skl *skl); | 125 | int skl_nhlt_update_topology_bin(struct skl *skl); |
@@ -130,5 +131,7 @@ int skl_resume_dsp(struct skl *skl); | |||
130 | void skl_cleanup_resources(struct skl *skl); | 131 | void skl_cleanup_resources(struct skl *skl); |
131 | const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id); | 132 | const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id); |
132 | void skl_update_d0i3c(struct device *dev, bool enable); | 133 | void skl_update_d0i3c(struct device *dev, bool enable); |
134 | int skl_nhlt_create_sysfs(struct skl *skl); | ||
135 | void skl_nhlt_remove_sysfs(struct skl *skl); | ||
133 | 136 | ||
134 | #endif /* __SOUND_SOC_SKL_H */ | 137 | #endif /* __SOUND_SOC_SKL_H */ |
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index 34a6123480d3..c7fa3e663463 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | |||
@@ -1578,6 +1578,7 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) | |||
1578 | pm_runtime_enable(&pdev->dev); | 1578 | pm_runtime_enable(&pdev->dev); |
1579 | if (!pm_runtime_enabled(&pdev->dev)) | 1579 | if (!pm_runtime_enabled(&pdev->dev)) |
1580 | goto err_pm_disable; | 1580 | goto err_pm_disable; |
1581 | pm_runtime_get_sync(&pdev->dev); | ||
1581 | 1582 | ||
1582 | ret = snd_soc_register_platform(&pdev->dev, &mtk_afe_pcm_platform); | 1583 | ret = snd_soc_register_platform(&pdev->dev, &mtk_afe_pcm_platform); |
1583 | if (ret) { | 1584 | if (ret) { |
@@ -1617,6 +1618,7 @@ static int mt2701_afe_pcm_dev_remove(struct platform_device *pdev) | |||
1617 | pm_runtime_disable(&pdev->dev); | 1618 | pm_runtime_disable(&pdev->dev); |
1618 | if (!pm_runtime_status_suspended(&pdev->dev)) | 1619 | if (!pm_runtime_status_suspended(&pdev->dev)) |
1619 | mt2701_afe_runtime_suspend(&pdev->dev); | 1620 | mt2701_afe_runtime_suspend(&pdev->dev); |
1621 | pm_runtime_put_sync(&pdev->dev); | ||
1620 | 1622 | ||
1621 | snd_soc_unregister_component(&pdev->dev); | 1623 | snd_soc_unregister_component(&pdev->dev); |
1622 | snd_soc_unregister_platform(&pdev->dev); | 1624 | snd_soc_unregister_platform(&pdev->dev); |
diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c index 5524a2c727ec..46c8e6ae00b4 100644 --- a/sound/soc/mediatek/mt8173/mt8173-max98090.c +++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c | |||
@@ -79,17 +79,11 @@ static int mt8173_max98090_init(struct snd_soc_pcm_runtime *runtime) | |||
79 | 79 | ||
80 | /* enable jack detection */ | 80 | /* enable jack detection */ |
81 | ret = snd_soc_card_jack_new(card, "Headphone", SND_JACK_HEADPHONE, | 81 | ret = snd_soc_card_jack_new(card, "Headphone", SND_JACK_HEADPHONE, |
82 | &mt8173_max98090_jack, NULL, 0); | 82 | &mt8173_max98090_jack, |
83 | mt8173_max98090_jack_pins, | ||
84 | ARRAY_SIZE(mt8173_max98090_jack_pins)); | ||
83 | if (ret) { | 85 | if (ret) { |
84 | dev_err(card->dev, "Can't snd_soc_jack_new %d\n", ret); | 86 | dev_err(card->dev, "Can't create a new Jack %d\n", ret); |
85 | return ret; | ||
86 | } | ||
87 | |||
88 | ret = snd_soc_jack_add_pins(&mt8173_max98090_jack, | ||
89 | ARRAY_SIZE(mt8173_max98090_jack_pins), | ||
90 | mt8173_max98090_jack_pins); | ||
91 | if (ret) { | ||
92 | dev_err(card->dev, "Can't snd_soc_jack_add_pins %d\n", ret); | ||
93 | return ret; | 87 | return ret; |
94 | } | 88 | } |
95 | 89 | ||
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index a002ab892772..b42f301c6b96 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -119,23 +119,33 @@ static int mxs_saif_set_clk(struct mxs_saif *saif, | |||
119 | * Set SAIF clock | 119 | * Set SAIF clock |
120 | * | 120 | * |
121 | * The SAIF clock should be either 384*fs or 512*fs. | 121 | * The SAIF clock should be either 384*fs or 512*fs. |
122 | * If MCLK is used, the SAIF clk ratio need to match mclk ratio. | 122 | * If MCLK is used, the SAIF clk ratio needs to match mclk ratio. |
123 | * For 32x mclk, set saif clk as 512*fs. | 123 | * For 256x, 128x, 64x, and 32x sub-rates, set saif clk as 512*fs. |
124 | * For 48x mclk, set saif clk as 384*fs. | 124 | * For 192x, 96x, and 48x sub-rates, set saif clk as 384*fs. |
125 | * | 125 | * |
126 | * If MCLK is not used, we just set saif clk to 512*fs. | 126 | * If MCLK is not used, we just set saif clk to 512*fs. |
127 | */ | 127 | */ |
128 | clk_prepare_enable(master_saif->clk); | 128 | clk_prepare_enable(master_saif->clk); |
129 | 129 | ||
130 | if (master_saif->mclk_in_use) { | 130 | if (master_saif->mclk_in_use) { |
131 | if (mclk % 32 == 0) { | 131 | switch (mclk / rate) { |
132 | case 32: | ||
133 | case 64: | ||
134 | case 128: | ||
135 | case 256: | ||
136 | case 512: | ||
132 | scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; | 137 | scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; |
133 | ret = clk_set_rate(master_saif->clk, 512 * rate); | 138 | ret = clk_set_rate(master_saif->clk, 512 * rate); |
134 | } else if (mclk % 48 == 0) { | 139 | break; |
140 | case 48: | ||
141 | case 96: | ||
142 | case 192: | ||
143 | case 384: | ||
135 | scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE; | 144 | scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE; |
136 | ret = clk_set_rate(master_saif->clk, 384 * rate); | 145 | ret = clk_set_rate(master_saif->clk, 384 * rate); |
137 | } else { | 146 | break; |
138 | /* SAIF MCLK should be either 32x or 48x */ | 147 | default: |
148 | /* SAIF MCLK should be a sub-rate of 512x or 384x */ | ||
139 | clk_disable_unprepare(master_saif->clk); | 149 | clk_disable_unprepare(master_saif->clk); |
140 | return -EINVAL; | 150 | return -EINVAL; |
141 | } | 151 | } |
@@ -299,6 +309,16 @@ static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | |||
299 | return -EBUSY; | 309 | return -EBUSY; |
300 | } | 310 | } |
301 | 311 | ||
312 | /* If SAIF1 is configured as slave, the clk gate needs to be cleared | ||
313 | * before the register can be written. | ||
314 | */ | ||
315 | if (saif->id != saif->master_id) { | ||
316 | __raw_writel(BM_SAIF_CTRL_SFTRST, | ||
317 | saif->base + SAIF_CTRL + MXS_CLR_ADDR); | ||
318 | __raw_writel(BM_SAIF_CTRL_CLKGATE, | ||
319 | saif->base + SAIF_CTRL + MXS_CLR_ADDR); | ||
320 | } | ||
321 | |||
302 | scr0 = __raw_readl(saif->base + SAIF_CTRL); | 322 | scr0 = __raw_readl(saif->base + SAIF_CTRL); |
303 | scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \ | 323 | scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \ |
304 | & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY; | 324 | & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY; |
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index 61e93b1c185d..46ae1269a698 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h | |||
@@ -323,8 +323,11 @@ struct omap_mcbsp { | |||
323 | 323 | ||
324 | unsigned int fmt; | 324 | unsigned int fmt; |
325 | unsigned int in_freq; | 325 | unsigned int in_freq; |
326 | unsigned int latency[2]; | ||
326 | int clk_div; | 327 | int clk_div; |
327 | int wlen; | 328 | int wlen; |
329 | |||
330 | struct pm_qos_request pm_qos_req; | ||
328 | }; | 331 | }; |
329 | 332 | ||
330 | void omap_mcbsp_config(struct omap_mcbsp *mcbsp, | 333 | void omap_mcbsp_config(struct omap_mcbsp *mcbsp, |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index d018e966e533..6b40bdbef336 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -157,6 +157,17 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, | |||
157 | struct snd_soc_dai *cpu_dai) | 157 | struct snd_soc_dai *cpu_dai) |
158 | { | 158 | { |
159 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); | 159 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); |
160 | int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | ||
161 | int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; | ||
162 | int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | ||
163 | |||
164 | if (mcbsp->latency[stream2]) | ||
165 | pm_qos_update_request(&mcbsp->pm_qos_req, | ||
166 | mcbsp->latency[stream2]); | ||
167 | else if (mcbsp->latency[stream1]) | ||
168 | pm_qos_remove_request(&mcbsp->pm_qos_req); | ||
169 | |||
170 | mcbsp->latency[stream1] = 0; | ||
160 | 171 | ||
161 | if (!cpu_dai->active) { | 172 | if (!cpu_dai->active) { |
162 | omap_mcbsp_free(mcbsp); | 173 | omap_mcbsp_free(mcbsp); |
@@ -164,6 +175,28 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, | |||
164 | } | 175 | } |
165 | } | 176 | } |
166 | 177 | ||
178 | static int omap_mcbsp_dai_prepare(struct snd_pcm_substream *substream, | ||
179 | struct snd_soc_dai *cpu_dai) | ||
180 | { | ||
181 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); | ||
182 | struct pm_qos_request *pm_qos_req = &mcbsp->pm_qos_req; | ||
183 | int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | ||
184 | int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; | ||
185 | int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | ||
186 | int latency = mcbsp->latency[stream2]; | ||
187 | |||
188 | /* Prevent omap hardware from hitting off between FIFO fills */ | ||
189 | if (!latency || mcbsp->latency[stream1] < latency) | ||
190 | latency = mcbsp->latency[stream1]; | ||
191 | |||
192 | if (pm_qos_request_active(pm_qos_req)) | ||
193 | pm_qos_update_request(pm_qos_req, latency); | ||
194 | else if (latency) | ||
195 | pm_qos_add_request(pm_qos_req, PM_QOS_CPU_DMA_LATENCY, latency); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
167 | static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, | 200 | static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, |
168 | struct snd_soc_dai *cpu_dai) | 201 | struct snd_soc_dai *cpu_dai) |
169 | { | 202 | { |
@@ -226,6 +259,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
226 | int wlen, channels, wpf; | 259 | int wlen, channels, wpf; |
227 | int pkt_size = 0; | 260 | int pkt_size = 0; |
228 | unsigned int format, div, framesize, master; | 261 | unsigned int format, div, framesize, master; |
262 | unsigned int buffer_size = mcbsp->pdata->buffer_size; | ||
229 | 263 | ||
230 | dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); | 264 | dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); |
231 | channels = params_channels(params); | 265 | channels = params_channels(params); |
@@ -240,7 +274,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
240 | default: | 274 | default: |
241 | return -EINVAL; | 275 | return -EINVAL; |
242 | } | 276 | } |
243 | if (mcbsp->pdata->buffer_size) { | 277 | if (buffer_size) { |
278 | int latency; | ||
279 | |||
244 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { | 280 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { |
245 | int period_words, max_thrsh; | 281 | int period_words, max_thrsh; |
246 | int divider = 0; | 282 | int divider = 0; |
@@ -271,6 +307,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
271 | /* Use packet mode for non mono streams */ | 307 | /* Use packet mode for non mono streams */ |
272 | pkt_size = channels; | 308 | pkt_size = channels; |
273 | } | 309 | } |
310 | |||
311 | latency = ((((buffer_size - pkt_size) / channels) * 1000) | ||
312 | / (params->rate_num / params->rate_den)); | ||
313 | |||
314 | mcbsp->latency[substream->stream] = latency; | ||
315 | |||
274 | omap_mcbsp_set_threshold(substream, pkt_size); | 316 | omap_mcbsp_set_threshold(substream, pkt_size); |
275 | } | 317 | } |
276 | 318 | ||
@@ -554,6 +596,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
554 | static const struct snd_soc_dai_ops mcbsp_dai_ops = { | 596 | static const struct snd_soc_dai_ops mcbsp_dai_ops = { |
555 | .startup = omap_mcbsp_dai_startup, | 597 | .startup = omap_mcbsp_dai_startup, |
556 | .shutdown = omap_mcbsp_dai_shutdown, | 598 | .shutdown = omap_mcbsp_dai_shutdown, |
599 | .prepare = omap_mcbsp_dai_prepare, | ||
557 | .trigger = omap_mcbsp_dai_trigger, | 600 | .trigger = omap_mcbsp_dai_trigger, |
558 | .delay = omap_mcbsp_dai_delay, | 601 | .delay = omap_mcbsp_dai_delay, |
559 | .hw_params = omap_mcbsp_dai_hw_params, | 602 | .hw_params = omap_mcbsp_dai_hw_params, |
@@ -835,6 +878,9 @@ static int asoc_mcbsp_remove(struct platform_device *pdev) | |||
835 | if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) | 878 | if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) |
836 | mcbsp->pdata->ops->free(mcbsp->id); | 879 | mcbsp->pdata->ops->free(mcbsp->id); |
837 | 880 | ||
881 | if (pm_qos_request_active(&mcbsp->pm_qos_req)) | ||
882 | pm_qos_remove_request(&mcbsp->pm_qos_req); | ||
883 | |||
838 | omap_mcbsp_cleanup(mcbsp); | 884 | omap_mcbsp_cleanup(mcbsp); |
839 | 885 | ||
840 | clk_put(mcbsp->fclk); | 886 | clk_put(mcbsp->fclk); |
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 086c37a85630..8ab7032631b7 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c | |||
@@ -22,9 +22,6 @@ | |||
22 | 22 | ||
23 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
24 | 24 | ||
25 | #include "pxa2xx-ac97.h" | ||
26 | |||
27 | |||
28 | #define E740_AUDIO_OUT 1 | 25 | #define E740_AUDIO_OUT 1 |
29 | #define E740_AUDIO_IN 2 | 26 | #define E740_AUDIO_IN 2 |
30 | 27 | ||
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index 7823278012a6..fdcd94adee7c 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c | |||
@@ -22,8 +22,6 @@ | |||
22 | 22 | ||
23 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
24 | 24 | ||
25 | #include "pxa2xx-ac97.h" | ||
26 | |||
27 | static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, | 25 | static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, |
28 | struct snd_kcontrol *kcontrol, int event) | 26 | struct snd_kcontrol *kcontrol, int event) |
29 | { | 27 | { |
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 07b9c6e17df9..2df714f70ec0 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <mach/audio.h> | 21 | #include <mach/audio.h> |
22 | #include <mach/eseries-gpio.h> | 22 | #include <mach/eseries-gpio.h> |
23 | 23 | ||
24 | #include "pxa2xx-ac97.h" | ||
25 | |||
26 | static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, | 24 | static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, |
27 | struct snd_kcontrol *kcontrol, int event) | 25 | struct snd_kcontrol *kcontrol, int event) |
28 | { | 26 | { |
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index 966163d1c813..6f2020f6c8d3 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include <asm/mach-types.h> | 30 | #include <asm/mach-types.h> |
31 | #include <mach/audio.h> | 31 | #include <mach/audio.h> |
32 | 32 | ||
33 | #include "pxa2xx-ac97.h" | ||
34 | |||
35 | static struct snd_soc_dai_link em_x270_dai[] = { | 33 | static struct snd_soc_dai_link em_x270_dai[] = { |
36 | { | 34 | { |
37 | .name = "AC97", | 35 | .name = "AC97", |
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 0fe0abec8fc4..8760a6687885 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c | |||
@@ -53,7 +53,6 @@ | |||
53 | #include <sound/initval.h> | 53 | #include <sound/initval.h> |
54 | #include <sound/ac97_codec.h> | 54 | #include <sound/ac97_codec.h> |
55 | 55 | ||
56 | #include "pxa2xx-ac97.h" | ||
57 | #include "../codecs/wm9713.h" | 56 | #include "../codecs/wm9713.h" |
58 | 57 | ||
59 | #define AC97_GPIO_PULL 0x58 | 58 | #define AC97_GPIO_PULL 0x58 |
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 387492d46b6c..97167048572d 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c | |||
@@ -27,8 +27,6 @@ | |||
27 | #include <mach/audio.h> | 27 | #include <mach/audio.h> |
28 | #include <linux/platform_data/asoc-palm27x.h> | 28 | #include <linux/platform_data/asoc-palm27x.h> |
29 | 29 | ||
30 | #include "pxa2xx-ac97.h" | ||
31 | |||
32 | static struct snd_soc_jack hs_jack; | 30 | static struct snd_soc_jack hs_jack; |
33 | 31 | ||
34 | /* Headphones jack detection DAPM pins */ | 32 | /* Headphones jack detection DAPM pins */ |
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 9615e6de1306..2e2fb1838ec2 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
@@ -27,8 +27,6 @@ | |||
27 | #include <mach/regs-ac97.h> | 27 | #include <mach/regs-ac97.h> |
28 | #include <mach/audio.h> | 28 | #include <mach/audio.h> |
29 | 29 | ||
30 | #include "pxa2xx-ac97.h" | ||
31 | |||
32 | static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) | 30 | static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) |
33 | { | 31 | { |
34 | pxa2xx_ac97_try_warm_reset(ac97); | 32 | pxa2xx_ac97_try_warm_reset(ac97); |
diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h deleted file mode 100644 index a49c21ba3842..000000000000 --- a/sound/soc/pxa/pxa2xx-ac97.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/pxa/pxa2xx-ac97.h | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef _PXA2XX_AC97_H | ||
10 | #define _PXA2XX_AC97_H | ||
11 | |||
12 | /* pxa2xx DAI ID's */ | ||
13 | #define PXA2XX_DAI_AC97_HIFI 0 | ||
14 | #define PXA2XX_DAI_AC97_AUX 1 | ||
15 | #define PXA2XX_DAI_AC97_MIC 2 | ||
16 | |||
17 | #endif | ||
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 2e312c62e3c7..e022b2a777f6 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <mach/tosa.h> | 31 | #include <mach/tosa.h> |
32 | #include <mach/audio.h> | 32 | #include <mach/audio.h> |
33 | 33 | ||
34 | #include "pxa2xx-ac97.h" | ||
35 | |||
36 | #define TOSA_HP 0 | 34 | #define TOSA_HP 0 |
37 | #define TOSA_MIC_INT 1 | 35 | #define TOSA_MIC_INT 1 |
38 | #define TOSA_HEADSET 2 | 36 | #define TOSA_HEADSET 2 |
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 8f301c72ee5e..6fbcdf02c88d 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
23 | 23 | ||
24 | #include "../codecs/wm9713.h" | 24 | #include "../codecs/wm9713.h" |
25 | #include "pxa2xx-ac97.h" | ||
26 | #include "pxa-ssp.h" | 25 | #include "pxa-ssp.h" |
27 | 26 | ||
28 | /* | 27 | /* |
diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c index 3eef0c37ba50..8aed72be3224 100644 --- a/sound/soc/qcom/lpass-apq8016.c +++ b/sound/soc/qcom/lpass-apq8016.c | |||
@@ -175,29 +175,28 @@ static int apq8016_lpass_init(struct platform_device *pdev) | |||
175 | 175 | ||
176 | drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk"); | 176 | drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk"); |
177 | if (IS_ERR(drvdata->pcnoc_mport_clk)) { | 177 | if (IS_ERR(drvdata->pcnoc_mport_clk)) { |
178 | dev_err(&pdev->dev, "%s() error getting pcnoc-mport-clk: %ld\n", | 178 | dev_err(&pdev->dev, "error getting pcnoc-mport-clk: %ld\n", |
179 | __func__, PTR_ERR(drvdata->pcnoc_mport_clk)); | 179 | PTR_ERR(drvdata->pcnoc_mport_clk)); |
180 | return PTR_ERR(drvdata->pcnoc_mport_clk); | 180 | return PTR_ERR(drvdata->pcnoc_mport_clk); |
181 | } | 181 | } |
182 | 182 | ||
183 | ret = clk_prepare_enable(drvdata->pcnoc_mport_clk); | 183 | ret = clk_prepare_enable(drvdata->pcnoc_mport_clk); |
184 | if (ret) { | 184 | if (ret) { |
185 | dev_err(&pdev->dev, "%s() Error enabling pcnoc-mport-clk: %d\n", | 185 | dev_err(&pdev->dev, "Error enabling pcnoc-mport-clk: %d\n", |
186 | __func__, ret); | 186 | ret); |
187 | return ret; | 187 | return ret; |
188 | } | 188 | } |
189 | 189 | ||
190 | drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk"); | 190 | drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk"); |
191 | if (IS_ERR(drvdata->pcnoc_sway_clk)) { | 191 | if (IS_ERR(drvdata->pcnoc_sway_clk)) { |
192 | dev_err(&pdev->dev, "%s() error getting pcnoc-sway-clk: %ld\n", | 192 | dev_err(&pdev->dev, "error getting pcnoc-sway-clk: %ld\n", |
193 | __func__, PTR_ERR(drvdata->pcnoc_sway_clk)); | 193 | PTR_ERR(drvdata->pcnoc_sway_clk)); |
194 | return PTR_ERR(drvdata->pcnoc_sway_clk); | 194 | return PTR_ERR(drvdata->pcnoc_sway_clk); |
195 | } | 195 | } |
196 | 196 | ||
197 | ret = clk_prepare_enable(drvdata->pcnoc_sway_clk); | 197 | ret = clk_prepare_enable(drvdata->pcnoc_sway_clk); |
198 | if (ret) { | 198 | if (ret) { |
199 | dev_err(&pdev->dev, "%s() Error enabling pcnoc_sway_clk: %d\n", | 199 | dev_err(&pdev->dev, "Error enabling pcnoc_sway_clk: %d\n", ret); |
200 | __func__, ret); | ||
201 | return ret; | 200 | return ret; |
202 | } | 201 | } |
203 | 202 | ||
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index eff3f9a8b685..5202a584e0c6 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c | |||
@@ -33,13 +33,10 @@ static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
33 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); | 33 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); |
34 | int ret; | 34 | int ret; |
35 | 35 | ||
36 | if (IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) | ||
37 | return 0; | ||
38 | |||
39 | ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq); | 36 | ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq); |
40 | if (ret) | 37 | if (ret) |
41 | dev_err(dai->dev, "%s() error setting mi2s osrclk to %u: %d\n", | 38 | dev_err(dai->dev, "error setting mi2s osrclk to %u: %d\n", |
42 | __func__, freq, ret); | 39 | freq, ret); |
43 | 40 | ||
44 | return ret; | 41 | return ret; |
45 | } | 42 | } |
@@ -50,23 +47,16 @@ static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream, | |||
50 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); | 47 | struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); |
51 | int ret; | 48 | int ret; |
52 | 49 | ||
53 | if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) { | 50 | ret = clk_prepare_enable(drvdata->mi2s_osr_clk[dai->driver->id]); |
54 | ret = clk_prepare_enable( | 51 | if (ret) { |
55 | drvdata->mi2s_osr_clk[dai->driver->id]); | 52 | dev_err(dai->dev, "error in enabling mi2s osr clk: %d\n", ret); |
56 | if (ret) { | 53 | return ret; |
57 | dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n", | ||
58 | __func__, ret); | ||
59 | return ret; | ||
60 | } | ||
61 | } | 54 | } |
62 | 55 | ||
63 | ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]); | 56 | ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]); |
64 | if (ret) { | 57 | if (ret) { |
65 | dev_err(dai->dev, "%s() error in enabling mi2s bit clk: %d\n", | 58 | dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); |
66 | __func__, ret); | 59 | clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); |
67 | if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) | ||
68 | clk_disable_unprepare( | ||
69 | drvdata->mi2s_osr_clk[dai->driver->id]); | ||
70 | return ret; | 60 | return ret; |
71 | } | 61 | } |
72 | 62 | ||
@@ -80,8 +70,7 @@ static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream, | |||
80 | 70 | ||
81 | clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]); | 71 | clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]); |
82 | 72 | ||
83 | if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) | 73 | clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); |
84 | clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); | ||
85 | } | 74 | } |
86 | 75 | ||
87 | static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, | 76 | static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, |
@@ -96,8 +85,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, | |||
96 | 85 | ||
97 | bitwidth = snd_pcm_format_width(format); | 86 | bitwidth = snd_pcm_format_width(format); |
98 | if (bitwidth < 0) { | 87 | if (bitwidth < 0) { |
99 | dev_err(dai->dev, "%s() invalid bit width given: %d\n", | 88 | dev_err(dai->dev, "invalid bit width given: %d\n", bitwidth); |
100 | __func__, bitwidth); | ||
101 | return bitwidth; | 89 | return bitwidth; |
102 | } | 90 | } |
103 | 91 | ||
@@ -115,8 +103,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, | |||
115 | regval |= LPAIF_I2SCTL_BITWIDTH_32; | 103 | regval |= LPAIF_I2SCTL_BITWIDTH_32; |
116 | break; | 104 | break; |
117 | default: | 105 | default: |
118 | dev_err(dai->dev, "%s() invalid bitwidth given: %d\n", | 106 | dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth); |
119 | __func__, bitwidth); | ||
120 | return -EINVAL; | 107 | return -EINVAL; |
121 | } | 108 | } |
122 | 109 | ||
@@ -143,8 +130,8 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, | |||
143 | regval |= LPAIF_I2SCTL_SPKMONO_STEREO; | 130 | regval |= LPAIF_I2SCTL_SPKMONO_STEREO; |
144 | break; | 131 | break; |
145 | default: | 132 | default: |
146 | dev_err(dai->dev, "%s() invalid channels given: %u\n", | 133 | dev_err(dai->dev, "invalid channels given: %u\n", |
147 | __func__, channels); | 134 | channels); |
148 | return -EINVAL; | 135 | return -EINVAL; |
149 | } | 136 | } |
150 | } else { | 137 | } else { |
@@ -170,8 +157,8 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, | |||
170 | regval |= LPAIF_I2SCTL_MICMONO_STEREO; | 157 | regval |= LPAIF_I2SCTL_MICMONO_STEREO; |
171 | break; | 158 | break; |
172 | default: | 159 | default: |
173 | dev_err(dai->dev, "%s() invalid channels given: %u\n", | 160 | dev_err(dai->dev, "invalid channels given: %u\n", |
174 | __func__, channels); | 161 | channels); |
175 | return -EINVAL; | 162 | return -EINVAL; |
176 | } | 163 | } |
177 | } | 164 | } |
@@ -180,16 +167,15 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, | |||
180 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), | 167 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), |
181 | regval); | 168 | regval); |
182 | if (ret) { | 169 | if (ret) { |
183 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 170 | dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); |
184 | __func__, ret); | ||
185 | return ret; | 171 | return ret; |
186 | } | 172 | } |
187 | 173 | ||
188 | ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id], | 174 | ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id], |
189 | rate * bitwidth * 2); | 175 | rate * bitwidth * 2); |
190 | if (ret) { | 176 | if (ret) { |
191 | dev_err(dai->dev, "%s() error setting mi2s bitclk to %u: %d\n", | 177 | dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n", |
192 | __func__, rate * bitwidth * 2, ret); | 178 | rate * bitwidth * 2, ret); |
193 | return ret; | 179 | return ret; |
194 | } | 180 | } |
195 | 181 | ||
@@ -206,8 +192,7 @@ static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream, | |||
206 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), | 192 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), |
207 | 0); | 193 | 0); |
208 | if (ret) | 194 | if (ret) |
209 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 195 | dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); |
210 | __func__, ret); | ||
211 | 196 | ||
212 | return ret; | 197 | return ret; |
213 | } | 198 | } |
@@ -231,8 +216,7 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream, | |||
231 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), | 216 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), |
232 | mask, val); | 217 | mask, val); |
233 | if (ret) | 218 | if (ret) |
234 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 219 | dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); |
235 | __func__, ret); | ||
236 | 220 | ||
237 | return ret; | 221 | return ret; |
238 | } | 222 | } |
@@ -261,8 +245,8 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, | |||
261 | dai->driver->id), | 245 | dai->driver->id), |
262 | mask, val); | 246 | mask, val); |
263 | if (ret) | 247 | if (ret) |
264 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 248 | dev_err(dai->dev, "error writing to i2sctl reg: %d\n", |
265 | __func__, ret); | 249 | ret); |
266 | break; | 250 | break; |
267 | case SNDRV_PCM_TRIGGER_STOP: | 251 | case SNDRV_PCM_TRIGGER_STOP: |
268 | case SNDRV_PCM_TRIGGER_SUSPEND: | 252 | case SNDRV_PCM_TRIGGER_SUSPEND: |
@@ -280,8 +264,8 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, | |||
280 | dai->driver->id), | 264 | dai->driver->id), |
281 | mask, val); | 265 | mask, val); |
282 | if (ret) | 266 | if (ret) |
283 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 267 | dev_err(dai->dev, "error writing to i2sctl reg: %d\n", |
284 | __func__, ret); | 268 | ret); |
285 | break; | 269 | break; |
286 | } | 270 | } |
287 | 271 | ||
@@ -308,8 +292,7 @@ int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai) | |||
308 | ret = regmap_write(drvdata->lpaif_map, | 292 | ret = regmap_write(drvdata->lpaif_map, |
309 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 0); | 293 | LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 0); |
310 | if (ret) | 294 | if (ret) |
311 | dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", | 295 | dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); |
312 | __func__, ret); | ||
313 | 296 | ||
314 | return ret; | 297 | return ret; |
315 | } | 298 | } |
@@ -451,8 +434,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) | |||
451 | 434 | ||
452 | dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); | 435 | dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); |
453 | if (dsp_of_node) { | 436 | if (dsp_of_node) { |
454 | dev_err(&pdev->dev, "%s() DSP exists and holds audio resources\n", | 437 | dev_err(&pdev->dev, "DSP exists and holds audio resources\n"); |
455 | __func__); | ||
456 | return -EBUSY; | 438 | return -EBUSY; |
457 | } | 439 | } |
458 | 440 | ||
@@ -473,8 +455,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) | |||
473 | 455 | ||
474 | drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); | 456 | drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); |
475 | if (IS_ERR((void const __force *)drvdata->lpaif)) { | 457 | if (IS_ERR((void const __force *)drvdata->lpaif)) { |
476 | dev_err(&pdev->dev, "%s() error mapping reg resource: %ld\n", | 458 | dev_err(&pdev->dev, "error mapping reg resource: %ld\n", |
477 | __func__, | ||
478 | PTR_ERR((void const __force *)drvdata->lpaif)); | 459 | PTR_ERR((void const __force *)drvdata->lpaif)); |
479 | return PTR_ERR((void const __force *)drvdata->lpaif); | 460 | return PTR_ERR((void const __force *)drvdata->lpaif); |
480 | } | 461 | } |
@@ -486,8 +467,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) | |||
486 | drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, | 467 | drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, |
487 | &lpass_cpu_regmap_config); | 468 | &lpass_cpu_regmap_config); |
488 | if (IS_ERR(drvdata->lpaif_map)) { | 469 | if (IS_ERR(drvdata->lpaif_map)) { |
489 | dev_err(&pdev->dev, "%s() error initializing regmap: %ld\n", | 470 | dev_err(&pdev->dev, "error initializing regmap: %ld\n", |
490 | __func__, PTR_ERR(drvdata->lpaif_map)); | 471 | PTR_ERR(drvdata->lpaif_map)); |
491 | return PTR_ERR(drvdata->lpaif_map); | 472 | return PTR_ERR(drvdata->lpaif_map); |
492 | } | 473 | } |
493 | 474 | ||
@@ -505,9 +486,10 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) | |||
505 | clk_name); | 486 | clk_name); |
506 | if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) { | 487 | if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) { |
507 | dev_warn(&pdev->dev, | 488 | dev_warn(&pdev->dev, |
508 | "%s() error getting mi2s-osr-clk: %ld\n", | 489 | "error getting optional mi2s-osr-clk: %ld\n", |
509 | __func__, | ||
510 | PTR_ERR(drvdata->mi2s_osr_clk[dai_id])); | 490 | PTR_ERR(drvdata->mi2s_osr_clk[dai_id])); |
491 | |||
492 | drvdata->mi2s_osr_clk[dai_id] = NULL; | ||
511 | } | 493 | } |
512 | 494 | ||
513 | if (variant->num_dai > 1) | 495 | if (variant->num_dai > 1) |
@@ -519,8 +501,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) | |||
519 | clk_name); | 501 | clk_name); |
520 | if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) { | 502 | if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) { |
521 | dev_err(&pdev->dev, | 503 | dev_err(&pdev->dev, |
522 | "%s() error getting mi2s-bit-clk: %ld\n", | 504 | "error getting mi2s-bit-clk: %ld\n", |
523 | __func__, | ||
524 | PTR_ERR(drvdata->mi2s_bit_clk[dai_id])); | 505 | PTR_ERR(drvdata->mi2s_bit_clk[dai_id])); |
525 | return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); | 506 | return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); |
526 | } | 507 | } |
@@ -528,24 +509,23 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) | |||
528 | 509 | ||
529 | drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk"); | 510 | drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk"); |
530 | if (IS_ERR(drvdata->ahbix_clk)) { | 511 | if (IS_ERR(drvdata->ahbix_clk)) { |
531 | dev_err(&pdev->dev, "%s() error getting ahbix-clk: %ld\n", | 512 | dev_err(&pdev->dev, "error getting ahbix-clk: %ld\n", |
532 | __func__, PTR_ERR(drvdata->ahbix_clk)); | 513 | PTR_ERR(drvdata->ahbix_clk)); |
533 | return PTR_ERR(drvdata->ahbix_clk); | 514 | return PTR_ERR(drvdata->ahbix_clk); |
534 | } | 515 | } |
535 | 516 | ||
536 | ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); | 517 | ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); |
537 | if (ret) { | 518 | if (ret) { |
538 | dev_err(&pdev->dev, "%s() error setting rate on ahbix_clk: %d\n", | 519 | dev_err(&pdev->dev, "error setting rate on ahbix_clk: %d\n", |
539 | __func__, ret); | 520 | ret); |
540 | return ret; | 521 | return ret; |
541 | } | 522 | } |
542 | dev_dbg(&pdev->dev, "%s() set ahbix_clk rate to %lu\n", __func__, | 523 | dev_dbg(&pdev->dev, "set ahbix_clk rate to %lu\n", |
543 | clk_get_rate(drvdata->ahbix_clk)); | 524 | clk_get_rate(drvdata->ahbix_clk)); |
544 | 525 | ||
545 | ret = clk_prepare_enable(drvdata->ahbix_clk); | 526 | ret = clk_prepare_enable(drvdata->ahbix_clk); |
546 | if (ret) { | 527 | if (ret) { |
547 | dev_err(&pdev->dev, "%s() error enabling ahbix_clk: %d\n", | 528 | dev_err(&pdev->dev, "error enabling ahbix_clk: %d\n", ret); |
548 | __func__, ret); | ||
549 | return ret; | 529 | return ret; |
550 | } | 530 | } |
551 | 531 | ||
@@ -554,15 +534,14 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) | |||
554 | variant->dai_driver, | 534 | variant->dai_driver, |
555 | variant->num_dai); | 535 | variant->num_dai); |
556 | if (ret) { | 536 | if (ret) { |
557 | dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n", | 537 | dev_err(&pdev->dev, "error registering cpu driver: %d\n", ret); |
558 | __func__, ret); | ||
559 | goto err_clk; | 538 | goto err_clk; |
560 | } | 539 | } |
561 | 540 | ||
562 | ret = asoc_qcom_lpass_platform_register(pdev); | 541 | ret = asoc_qcom_lpass_platform_register(pdev); |
563 | if (ret) { | 542 | if (ret) { |
564 | dev_err(&pdev->dev, "%s() error registering platform driver: %d\n", | 543 | dev_err(&pdev->dev, "error registering platform driver: %d\n", |
565 | __func__, ret); | 544 | ret); |
566 | goto err_clk; | 545 | goto err_clk; |
567 | } | 546 | } |
568 | 547 | ||
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index dd5bdd0da730..7aabf08de3d4 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c | |||
@@ -89,8 +89,7 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) | |||
89 | LPAIF_DMACTL_REG(v, dma_ch, dir), 0); | 89 | LPAIF_DMACTL_REG(v, dma_ch, dir), 0); |
90 | if (ret) { | 90 | if (ret) { |
91 | dev_err(soc_runtime->dev, | 91 | dev_err(soc_runtime->dev, |
92 | "%s() error writing to rdmactl reg: %d\n", | 92 | "error writing to rdmactl reg: %d\n", ret); |
93 | __func__, ret); | ||
94 | return ret; | 93 | return ret; |
95 | } | 94 | } |
96 | 95 | ||
@@ -103,8 +102,8 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) | |||
103 | ret = snd_pcm_hw_constraint_integer(runtime, | 102 | ret = snd_pcm_hw_constraint_integer(runtime, |
104 | SNDRV_PCM_HW_PARAM_PERIODS); | 103 | SNDRV_PCM_HW_PARAM_PERIODS); |
105 | if (ret < 0) { | 104 | if (ret < 0) { |
106 | dev_err(soc_runtime->dev, "%s() setting constraints failed: %d\n", | 105 | dev_err(soc_runtime->dev, "setting constraints failed: %d\n", |
107 | __func__, ret); | 106 | ret); |
108 | return -EINVAL; | 107 | return -EINVAL; |
109 | } | 108 | } |
110 | 109 | ||
@@ -151,8 +150,8 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, | |||
151 | 150 | ||
152 | bitwidth = snd_pcm_format_width(format); | 151 | bitwidth = snd_pcm_format_width(format); |
153 | if (bitwidth < 0) { | 152 | if (bitwidth < 0) { |
154 | dev_err(soc_runtime->dev, "%s() invalid bit width given: %d\n", | 153 | dev_err(soc_runtime->dev, "invalid bit width given: %d\n", |
155 | __func__, bitwidth); | 154 | bitwidth); |
156 | return bitwidth; | 155 | return bitwidth; |
157 | } | 156 | } |
158 | 157 | ||
@@ -177,8 +176,9 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, | |||
177 | regval |= LPAIF_DMACTL_WPSCNT_FOUR; | 176 | regval |= LPAIF_DMACTL_WPSCNT_FOUR; |
178 | break; | 177 | break; |
179 | default: | 178 | default: |
180 | dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n", | 179 | dev_err(soc_runtime->dev, |
181 | __func__, bitwidth, channels); | 180 | "invalid PCM config given: bw=%d, ch=%u\n", |
181 | bitwidth, channels); | ||
182 | return -EINVAL; | 182 | return -EINVAL; |
183 | } | 183 | } |
184 | break; | 184 | break; |
@@ -201,22 +201,23 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, | |||
201 | regval |= LPAIF_DMACTL_WPSCNT_EIGHT; | 201 | regval |= LPAIF_DMACTL_WPSCNT_EIGHT; |
202 | break; | 202 | break; |
203 | default: | 203 | default: |
204 | dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n", | 204 | dev_err(soc_runtime->dev, |
205 | __func__, bitwidth, channels); | 205 | "invalid PCM config given: bw=%d, ch=%u\n", |
206 | bitwidth, channels); | ||
206 | return -EINVAL; | 207 | return -EINVAL; |
207 | } | 208 | } |
208 | break; | 209 | break; |
209 | default: | 210 | default: |
210 | dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n", | 211 | dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n", |
211 | __func__, bitwidth, channels); | 212 | bitwidth, channels); |
212 | return -EINVAL; | 213 | return -EINVAL; |
213 | } | 214 | } |
214 | 215 | ||
215 | ret = regmap_write(drvdata->lpaif_map, | 216 | ret = regmap_write(drvdata->lpaif_map, |
216 | LPAIF_DMACTL_REG(v, ch, dir), regval); | 217 | LPAIF_DMACTL_REG(v, ch, dir), regval); |
217 | if (ret) { | 218 | if (ret) { |
218 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", | 219 | dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", |
219 | __func__, ret); | 220 | ret); |
220 | return ret; | 221 | return ret; |
221 | } | 222 | } |
222 | 223 | ||
@@ -237,8 +238,8 @@ static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) | |||
237 | reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream); | 238 | reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream); |
238 | ret = regmap_write(drvdata->lpaif_map, reg, 0); | 239 | ret = regmap_write(drvdata->lpaif_map, reg, 0); |
239 | if (ret) | 240 | if (ret) |
240 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", | 241 | dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", |
241 | __func__, ret); | 242 | ret); |
242 | 243 | ||
243 | return ret; | 244 | return ret; |
244 | } | 245 | } |
@@ -260,8 +261,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) | |||
260 | LPAIF_DMABASE_REG(v, ch, dir), | 261 | LPAIF_DMABASE_REG(v, ch, dir), |
261 | runtime->dma_addr); | 262 | runtime->dma_addr); |
262 | if (ret) { | 263 | if (ret) { |
263 | dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n", | 264 | dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n", |
264 | __func__, ret); | 265 | ret); |
265 | return ret; | 266 | return ret; |
266 | } | 267 | } |
267 | 268 | ||
@@ -269,8 +270,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) | |||
269 | LPAIF_DMABUFF_REG(v, ch, dir), | 270 | LPAIF_DMABUFF_REG(v, ch, dir), |
270 | (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); | 271 | (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); |
271 | if (ret) { | 272 | if (ret) { |
272 | dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n", | 273 | dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n", |
273 | __func__, ret); | 274 | ret); |
274 | return ret; | 275 | return ret; |
275 | } | 276 | } |
276 | 277 | ||
@@ -278,8 +279,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) | |||
278 | LPAIF_DMAPER_REG(v, ch, dir), | 279 | LPAIF_DMAPER_REG(v, ch, dir), |
279 | (snd_pcm_lib_period_bytes(substream) >> 2) - 1); | 280 | (snd_pcm_lib_period_bytes(substream) >> 2) - 1); |
280 | if (ret) { | 281 | if (ret) { |
281 | dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n", | 282 | dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n", |
282 | __func__, ret); | 283 | ret); |
283 | return ret; | 284 | return ret; |
284 | } | 285 | } |
285 | 286 | ||
@@ -287,8 +288,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) | |||
287 | LPAIF_DMACTL_REG(v, ch, dir), | 288 | LPAIF_DMACTL_REG(v, ch, dir), |
288 | LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON); | 289 | LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON); |
289 | if (ret) { | 290 | if (ret) { |
290 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", | 291 | dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", |
291 | __func__, ret); | 292 | ret); |
292 | return ret; | 293 | return ret; |
293 | } | 294 | } |
294 | 295 | ||
@@ -317,8 +318,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
317 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), | 318 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), |
318 | LPAIF_IRQ_ALL(ch)); | 319 | LPAIF_IRQ_ALL(ch)); |
319 | if (ret) { | 320 | if (ret) { |
320 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", | 321 | dev_err(soc_runtime->dev, |
321 | __func__, ret); | 322 | "error writing to irqclear reg: %d\n", ret); |
322 | return ret; | 323 | return ret; |
323 | } | 324 | } |
324 | 325 | ||
@@ -327,8 +328,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
327 | LPAIF_IRQ_ALL(ch), | 328 | LPAIF_IRQ_ALL(ch), |
328 | LPAIF_IRQ_ALL(ch)); | 329 | LPAIF_IRQ_ALL(ch)); |
329 | if (ret) { | 330 | if (ret) { |
330 | dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", | 331 | dev_err(soc_runtime->dev, |
331 | __func__, ret); | 332 | "error writing to irqen reg: %d\n", ret); |
332 | return ret; | 333 | return ret; |
333 | } | 334 | } |
334 | 335 | ||
@@ -337,8 +338,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
337 | LPAIF_DMACTL_ENABLE_MASK, | 338 | LPAIF_DMACTL_ENABLE_MASK, |
338 | LPAIF_DMACTL_ENABLE_ON); | 339 | LPAIF_DMACTL_ENABLE_ON); |
339 | if (ret) { | 340 | if (ret) { |
340 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", | 341 | dev_err(soc_runtime->dev, |
341 | __func__, ret); | 342 | "error writing to rdmactl reg: %d\n", ret); |
342 | return ret; | 343 | return ret; |
343 | } | 344 | } |
344 | break; | 345 | break; |
@@ -350,8 +351,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
350 | LPAIF_DMACTL_ENABLE_MASK, | 351 | LPAIF_DMACTL_ENABLE_MASK, |
351 | LPAIF_DMACTL_ENABLE_OFF); | 352 | LPAIF_DMACTL_ENABLE_OFF); |
352 | if (ret) { | 353 | if (ret) { |
353 | dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", | 354 | dev_err(soc_runtime->dev, |
354 | __func__, ret); | 355 | "error writing to rdmactl reg: %d\n", ret); |
355 | return ret; | 356 | return ret; |
356 | } | 357 | } |
357 | 358 | ||
@@ -359,8 +360,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, | |||
359 | LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), | 360 | LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), |
360 | LPAIF_IRQ_ALL(ch), 0); | 361 | LPAIF_IRQ_ALL(ch), 0); |
361 | if (ret) { | 362 | if (ret) { |
362 | dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", | 363 | dev_err(soc_runtime->dev, |
363 | __func__, ret); | 364 | "error writing to irqen reg: %d\n", ret); |
364 | return ret; | 365 | return ret; |
365 | } | 366 | } |
366 | break; | 367 | break; |
@@ -386,16 +387,16 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( | |||
386 | ret = regmap_read(drvdata->lpaif_map, | 387 | ret = regmap_read(drvdata->lpaif_map, |
387 | LPAIF_DMABASE_REG(v, ch, dir), &base_addr); | 388 | LPAIF_DMABASE_REG(v, ch, dir), &base_addr); |
388 | if (ret) { | 389 | if (ret) { |
389 | dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n", | 390 | dev_err(soc_runtime->dev, |
390 | __func__, ret); | 391 | "error reading from rdmabase reg: %d\n", ret); |
391 | return ret; | 392 | return ret; |
392 | } | 393 | } |
393 | 394 | ||
394 | ret = regmap_read(drvdata->lpaif_map, | 395 | ret = regmap_read(drvdata->lpaif_map, |
395 | LPAIF_DMACURR_REG(v, ch, dir), &curr_addr); | 396 | LPAIF_DMACURR_REG(v, ch, dir), &curr_addr); |
396 | if (ret) { | 397 | if (ret) { |
397 | dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n", | 398 | dev_err(soc_runtime->dev, |
398 | __func__, ret); | 399 | "error reading from rdmacurr reg: %d\n", ret); |
399 | return ret; | 400 | return ret; |
400 | } | 401 | } |
401 | 402 | ||
@@ -439,8 +440,8 @@ static irqreturn_t lpass_dma_interrupt_handler( | |||
439 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), | 440 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), |
440 | LPAIF_IRQ_PER(chan)); | 441 | LPAIF_IRQ_PER(chan)); |
441 | if (rv) { | 442 | if (rv) { |
442 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", | 443 | dev_err(soc_runtime->dev, |
443 | __func__, rv); | 444 | "error writing to irqclear reg: %d\n", rv); |
444 | return IRQ_NONE; | 445 | return IRQ_NONE; |
445 | } | 446 | } |
446 | snd_pcm_period_elapsed(substream); | 447 | snd_pcm_period_elapsed(substream); |
@@ -452,11 +453,11 @@ static irqreturn_t lpass_dma_interrupt_handler( | |||
452 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), | 453 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), |
453 | LPAIF_IRQ_XRUN(chan)); | 454 | LPAIF_IRQ_XRUN(chan)); |
454 | if (rv) { | 455 | if (rv) { |
455 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", | 456 | dev_err(soc_runtime->dev, |
456 | __func__, rv); | 457 | "error writing to irqclear reg: %d\n", rv); |
457 | return IRQ_NONE; | 458 | return IRQ_NONE; |
458 | } | 459 | } |
459 | dev_warn(soc_runtime->dev, "%s() xrun warning\n", __func__); | 460 | dev_warn(soc_runtime->dev, "xrun warning\n"); |
460 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); | 461 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); |
461 | ret = IRQ_HANDLED; | 462 | ret = IRQ_HANDLED; |
462 | } | 463 | } |
@@ -466,11 +467,11 @@ static irqreturn_t lpass_dma_interrupt_handler( | |||
466 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), | 467 | LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), |
467 | LPAIF_IRQ_ERR(chan)); | 468 | LPAIF_IRQ_ERR(chan)); |
468 | if (rv) { | 469 | if (rv) { |
469 | dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", | 470 | dev_err(soc_runtime->dev, |
470 | __func__, rv); | 471 | "error writing to irqclear reg: %d\n", rv); |
471 | return IRQ_NONE; | 472 | return IRQ_NONE; |
472 | } | 473 | } |
473 | dev_err(soc_runtime->dev, "%s() bus access error\n", __func__); | 474 | dev_err(soc_runtime->dev, "bus access error\n"); |
474 | snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); | 475 | snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); |
475 | ret = IRQ_HANDLED; | 476 | ret = IRQ_HANDLED; |
476 | } | 477 | } |
@@ -488,8 +489,7 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) | |||
488 | rv = regmap_read(drvdata->lpaif_map, | 489 | rv = regmap_read(drvdata->lpaif_map, |
489 | LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); | 490 | LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); |
490 | if (rv) { | 491 | if (rv) { |
491 | pr_err("%s() error reading from irqstat reg: %d\n", | 492 | pr_err("error reading from irqstat reg: %d\n", rv); |
492 | __func__, rv); | ||
493 | return IRQ_NONE; | 493 | return IRQ_NONE; |
494 | } | 494 | } |
495 | 495 | ||
@@ -571,8 +571,8 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) | |||
571 | 571 | ||
572 | drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); | 572 | drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); |
573 | if (drvdata->lpaif_irq < 0) { | 573 | if (drvdata->lpaif_irq < 0) { |
574 | dev_err(&pdev->dev, "%s() error getting irq handle: %d\n", | 574 | dev_err(&pdev->dev, "error getting irq handle: %d\n", |
575 | __func__, drvdata->lpaif_irq); | 575 | drvdata->lpaif_irq); |
576 | return -ENODEV; | 576 | return -ENODEV; |
577 | } | 577 | } |
578 | 578 | ||
@@ -580,8 +580,7 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) | |||
580 | ret = regmap_write(drvdata->lpaif_map, | 580 | ret = regmap_write(drvdata->lpaif_map, |
581 | LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); | 581 | LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); |
582 | if (ret) { | 582 | if (ret) { |
583 | dev_err(&pdev->dev, "%s() error writing to irqen reg: %d\n", | 583 | dev_err(&pdev->dev, "error writing to irqen reg: %d\n", ret); |
584 | __func__, ret); | ||
585 | return ret; | 584 | return ret; |
586 | } | 585 | } |
587 | 586 | ||
@@ -589,8 +588,7 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) | |||
589 | lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, | 588 | lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, |
590 | "lpass-irq-lpaif", drvdata); | 589 | "lpass-irq-lpaif", drvdata); |
591 | if (ret) { | 590 | if (ret) { |
592 | dev_err(&pdev->dev, "%s() irq request failed: %d\n", | 591 | dev_err(&pdev->dev, "irq request failed: %d\n", ret); |
593 | __func__, ret); | ||
594 | return ret; | 592 | return ret; |
595 | } | 593 | } |
596 | 594 | ||
diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c index 8fcac2ac3aa6..c5207af14104 100644 --- a/sound/soc/qcom/storm.c +++ b/sound/soc/qcom/storm.c | |||
@@ -36,8 +36,7 @@ static int storm_ops_hw_params(struct snd_pcm_substream *substream, | |||
36 | 36 | ||
37 | bitwidth = snd_pcm_format_width(format); | 37 | bitwidth = snd_pcm_format_width(format); |
38 | if (bitwidth < 0) { | 38 | if (bitwidth < 0) { |
39 | dev_err(card->dev, "%s() invalid bit width given: %d\n", | 39 | dev_err(card->dev, "invalid bit width given: %d\n", bitwidth); |
40 | __func__, bitwidth); | ||
41 | return bitwidth; | 40 | return bitwidth; |
42 | } | 41 | } |
43 | 42 | ||
@@ -50,8 +49,8 @@ static int storm_ops_hw_params(struct snd_pcm_substream *substream, | |||
50 | 49 | ||
51 | ret = snd_soc_dai_set_sysclk(soc_runtime->cpu_dai, 0, sysclk_freq, 0); | 50 | ret = snd_soc_dai_set_sysclk(soc_runtime->cpu_dai, 0, sysclk_freq, 0); |
52 | if (ret) { | 51 | if (ret) { |
53 | dev_err(card->dev, "%s() error setting sysclk to %u: %d\n", | 52 | dev_err(card->dev, "error setting sysclk to %u: %d\n", |
54 | __func__, sysclk_freq, ret); | 53 | sysclk_freq, ret); |
55 | return ret; | 54 | return ret; |
56 | } | 55 | } |
57 | 56 | ||
@@ -76,16 +75,14 @@ static int storm_parse_of(struct snd_soc_card *card) | |||
76 | 75 | ||
77 | dai_link->cpu_of_node = of_parse_phandle(np, "cpu", 0); | 76 | dai_link->cpu_of_node = of_parse_phandle(np, "cpu", 0); |
78 | if (!dai_link->cpu_of_node) { | 77 | if (!dai_link->cpu_of_node) { |
79 | dev_err(card->dev, "%s() error getting cpu phandle\n", | 78 | dev_err(card->dev, "error getting cpu phandle\n"); |
80 | __func__); | ||
81 | return -EINVAL; | 79 | return -EINVAL; |
82 | } | 80 | } |
83 | dai_link->platform_of_node = dai_link->cpu_of_node; | 81 | dai_link->platform_of_node = dai_link->cpu_of_node; |
84 | 82 | ||
85 | dai_link->codec_of_node = of_parse_phandle(np, "codec", 0); | 83 | dai_link->codec_of_node = of_parse_phandle(np, "codec", 0); |
86 | if (!dai_link->codec_of_node) { | 84 | if (!dai_link->codec_of_node) { |
87 | dev_err(card->dev, "%s() error getting codec phandle\n", | 85 | dev_err(card->dev, "error getting codec phandle\n"); |
88 | __func__); | ||
89 | return -EINVAL; | 86 | return -EINVAL; |
90 | } | 87 | } |
91 | 88 | ||
@@ -106,8 +103,7 @@ static int storm_platform_probe(struct platform_device *pdev) | |||
106 | 103 | ||
107 | ret = snd_soc_of_parse_card_name(card, "qcom,model"); | 104 | ret = snd_soc_of_parse_card_name(card, "qcom,model"); |
108 | if (ret) { | 105 | if (ret) { |
109 | dev_err(&pdev->dev, "%s() error parsing card name: %d\n", | 106 | dev_err(&pdev->dev, "error parsing card name: %d\n", ret); |
110 | __func__, ret); | ||
111 | return ret; | 107 | return ret; |
112 | } | 108 | } |
113 | 109 | ||
@@ -116,15 +112,13 @@ static int storm_platform_probe(struct platform_device *pdev) | |||
116 | 112 | ||
117 | ret = storm_parse_of(card); | 113 | ret = storm_parse_of(card); |
118 | if (ret) { | 114 | if (ret) { |
119 | dev_err(&pdev->dev, "%s() error resolving dai links: %d\n", | 115 | dev_err(&pdev->dev, "error resolving dai links: %d\n", ret); |
120 | __func__, ret); | ||
121 | return ret; | 116 | return ret; |
122 | } | 117 | } |
123 | 118 | ||
124 | ret = devm_snd_soc_register_card(&pdev->dev, card); | 119 | ret = devm_snd_soc_register_card(&pdev->dev, card); |
125 | if (ret) | 120 | if (ret) |
126 | dev_err(&pdev->dev, "%s() error registering soundcard: %d\n", | 121 | dev_err(&pdev->dev, "error registering soundcard: %d\n", ret); |
127 | __func__, ret); | ||
128 | 122 | ||
129 | return ret; | 123 | return ret; |
130 | 124 | ||
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index c783f9a22595..e3ca1e973de5 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig | |||
@@ -42,6 +42,15 @@ config SND_SOC_ROCKCHIP_RT5645 | |||
42 | Say Y or M here if you want to add support for SoC audio on Rockchip | 42 | Say Y or M here if you want to add support for SoC audio on Rockchip |
43 | boards using the RT5645/RT5650 codec, such as Veyron. | 43 | boards using the RT5645/RT5650 codec, such as Veyron. |
44 | 44 | ||
45 | config SND_SOC_RK3288_HDMI_ANALOG | ||
46 | tristate "ASoC support multiple codecs for Rockchip RK3288 boards" | ||
47 | depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP | ||
48 | select SND_SOC_ROCKCHIP_I2S | ||
49 | select SND_SOC_HDMI_CODEC | ||
50 | help | ||
51 | Say Y or M here if you want to add support for SoC audio on Rockchip | ||
52 | RK3288 boards using an analog output and the built-in HDMI audio. | ||
53 | |||
45 | config SND_SOC_RK3399_GRU_SOUND | 54 | config SND_SOC_RK3399_GRU_SOUND |
46 | tristate "ASoC support multiple codecs for Rockchip RK3399 GRU boards" | 55 | tristate "ASoC support multiple codecs for Rockchip RK3399 GRU boards" |
47 | depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP && SPI | 56 | depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP && SPI |
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile index 84e5c7c700e7..991f91bea9f9 100644 --- a/sound/soc/rockchip/Makefile +++ b/sound/soc/rockchip/Makefile | |||
@@ -7,8 +7,10 @@ obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o | |||
7 | 7 | ||
8 | snd-soc-rockchip-max98090-objs := rockchip_max98090.o | 8 | snd-soc-rockchip-max98090-objs := rockchip_max98090.o |
9 | snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o | 9 | snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o |
10 | snd-soc-rk3288-hdmi-analog-objs := rk3288_hdmi_analog.o | ||
10 | snd-soc-rk3399-gru-sound-objs := rk3399_gru_sound.o | 11 | snd-soc-rk3399-gru-sound-objs := rk3399_gru_sound.o |
11 | 12 | ||
12 | obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o | 13 | obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o |
13 | obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o | 14 | obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o |
15 | obj-$(CONFIG_SND_SOC_RK3288_HDMI_ANALOG) += snd-soc-rk3288-hdmi-analog.o | ||
14 | obj-$(CONFIG_SND_SOC_RK3399_GRU_SOUND) += snd-soc-rk3399-gru-sound.o | 16 | obj-$(CONFIG_SND_SOC_RK3399_GRU_SOUND) += snd-soc-rk3399-gru-sound.o |
diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c new file mode 100644 index 000000000000..b60abf322ce1 --- /dev/null +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * Rockchip machine ASoC driver for RK3288 boards that have an HDMI and analog | ||
3 | * audio output | ||
4 | * | ||
5 | * Copyright (c) 2016, Collabora Ltd. | ||
6 | * | ||
7 | * Authors: Sjoerd Simons <sjoerd.simons@collabora.com>, | ||
8 | * Romain Perier <romain.perier@collabora.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms and conditions of the GNU General Public License, | ||
12 | * version 2, as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
17 | * more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/of_gpio.h> | ||
29 | #include <sound/core.h> | ||
30 | #include <sound/jack.h> | ||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/pcm_params.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include <sound/soc-dapm.h> | ||
35 | |||
36 | #include "rockchip_i2s.h" | ||
37 | |||
38 | #define DRV_NAME "rk3288-snd-hdmi-analog" | ||
39 | |||
40 | struct rk_drvdata { | ||
41 | int gpio_hp_en; | ||
42 | int gpio_hp_det; | ||
43 | }; | ||
44 | |||
45 | static int rk_hp_power(struct snd_soc_dapm_widget *w, | ||
46 | struct snd_kcontrol *k, int event) | ||
47 | { | ||
48 | struct rk_drvdata *machine = snd_soc_card_get_drvdata(w->dapm->card); | ||
49 | |||
50 | if (!gpio_is_valid(machine->gpio_hp_en)) | ||
51 | return 0; | ||
52 | |||
53 | gpio_set_value_cansleep(machine->gpio_hp_en, | ||
54 | SND_SOC_DAPM_EVENT_ON(event)); | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static struct snd_soc_jack headphone_jack; | ||
60 | static struct snd_soc_jack_pin headphone_jack_pins[] = { | ||
61 | { | ||
62 | .pin = "Analog", | ||
63 | .mask = SND_JACK_HEADPHONE | ||
64 | }, | ||
65 | }; | ||
66 | |||
67 | static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { | ||
68 | SND_SOC_DAPM_HP("Analog", rk_hp_power), | ||
69 | SND_SOC_DAPM_LINE("HDMI", NULL), | ||
70 | }; | ||
71 | |||
72 | static const struct snd_kcontrol_new rk_mc_controls[] = { | ||
73 | SOC_DAPM_PIN_SWITCH("Analog"), | ||
74 | SOC_DAPM_PIN_SWITCH("HDMI"), | ||
75 | }; | ||
76 | |||
77 | static int rk_hw_params(struct snd_pcm_substream *substream, | ||
78 | struct snd_pcm_hw_params *params) | ||
79 | { | ||
80 | int ret = 0; | ||
81 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
82 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
83 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
84 | int mclk; | ||
85 | |||
86 | switch (params_rate(params)) { | ||
87 | case 8000: | ||
88 | case 16000: | ||
89 | case 24000: | ||
90 | case 32000: | ||
91 | case 48000: | ||
92 | case 64000: | ||
93 | case 96000: | ||
94 | mclk = 12288000; | ||
95 | break; | ||
96 | case 11025: | ||
97 | case 22050: | ||
98 | case 44100: | ||
99 | case 88200: | ||
100 | mclk = 11289600; | ||
101 | break; | ||
102 | default: | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, | ||
107 | SND_SOC_CLOCK_OUT); | ||
108 | |||
109 | if (ret && ret != -ENOTSUPP) { | ||
110 | dev_err(codec_dai->dev, "Can't set cpu clock %d\n", ret); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | ||
115 | SND_SOC_CLOCK_IN); | ||
116 | if (ret && ret != -ENOTSUPP) { | ||
117 | dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static struct snd_soc_jack_gpio rk_hp_jack_gpio = { | ||
125 | .name = "Headphone detection", | ||
126 | .report = SND_JACK_HEADPHONE, | ||
127 | .debounce_time = 150 | ||
128 | }; | ||
129 | |||
130 | static int rk_init(struct snd_soc_pcm_runtime *runtime) | ||
131 | { | ||
132 | struct rk_drvdata *machine = snd_soc_card_get_drvdata(runtime->card); | ||
133 | |||
134 | /* Enable Headset Jack detection */ | ||
135 | if (gpio_is_valid(machine->gpio_hp_det)) { | ||
136 | snd_soc_card_jack_new(runtime->card, "Headphone Jack", | ||
137 | SND_JACK_HEADPHONE, &headphone_jack, | ||
138 | headphone_jack_pins, | ||
139 | ARRAY_SIZE(headphone_jack_pins)); | ||
140 | rk_hp_jack_gpio.gpio = machine->gpio_hp_det; | ||
141 | snd_soc_jack_add_gpios(&headphone_jack, 1, &rk_hp_jack_gpio); | ||
142 | } | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static struct snd_soc_ops rk_ops = { | ||
148 | .hw_params = rk_hw_params, | ||
149 | }; | ||
150 | |||
151 | static struct snd_soc_dai_link_component rk_codecs[] = { | ||
152 | { }, | ||
153 | { | ||
154 | .name = "hdmi-audio-codec.2.auto", | ||
155 | .dai_name = "hdmi-hifi.0", | ||
156 | }, | ||
157 | }; | ||
158 | |||
159 | static struct snd_soc_dai_link rk_dailink = { | ||
160 | .name = "Codecs", | ||
161 | .stream_name = "Audio", | ||
162 | .init = rk_init, | ||
163 | .ops = &rk_ops, | ||
164 | .codecs = rk_codecs, | ||
165 | .num_codecs = ARRAY_SIZE(rk_codecs), | ||
166 | /* Set codecs as slave */ | ||
167 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
168 | SND_SOC_DAIFMT_CBS_CFS, | ||
169 | }; | ||
170 | |||
171 | static struct snd_soc_card snd_soc_card_rk = { | ||
172 | .name = "ROCKCHIP-I2S", | ||
173 | .dai_link = &rk_dailink, | ||
174 | .num_links = 1, | ||
175 | .num_aux_devs = 0, | ||
176 | .dapm_widgets = rk_dapm_widgets, | ||
177 | .num_dapm_widgets = ARRAY_SIZE(rk_dapm_widgets), | ||
178 | .controls = rk_mc_controls, | ||
179 | .num_controls = ARRAY_SIZE(rk_mc_controls), | ||
180 | }; | ||
181 | |||
182 | static int snd_rk_mc_probe(struct platform_device *pdev) | ||
183 | { | ||
184 | int ret = 0; | ||
185 | struct snd_soc_card *card = &snd_soc_card_rk; | ||
186 | struct device_node *np = pdev->dev.of_node; | ||
187 | struct rk_drvdata *machine; | ||
188 | struct of_phandle_args args; | ||
189 | |||
190 | machine = devm_kzalloc(&pdev->dev, sizeof(struct rk_drvdata), | ||
191 | GFP_KERNEL); | ||
192 | if (!machine) | ||
193 | return -ENOMEM; | ||
194 | |||
195 | card->dev = &pdev->dev; | ||
196 | |||
197 | machine->gpio_hp_det = of_get_named_gpio(np, | ||
198 | "rockchip,hp-det-gpios", 0); | ||
199 | if (!gpio_is_valid(machine->gpio_hp_det) && machine->gpio_hp_det != -ENODEV) | ||
200 | return machine->gpio_hp_det; | ||
201 | |||
202 | machine->gpio_hp_en = of_get_named_gpio(np, | ||
203 | "rockchip,hp-en-gpios", 0); | ||
204 | if (!gpio_is_valid(machine->gpio_hp_en) && machine->gpio_hp_en != -ENODEV) | ||
205 | return machine->gpio_hp_en; | ||
206 | |||
207 | if (gpio_is_valid(machine->gpio_hp_en)) { | ||
208 | ret = devm_gpio_request_one(&pdev->dev, machine->gpio_hp_en, | ||
209 | GPIOF_OUT_INIT_LOW, "hp_en"); | ||
210 | if (ret) { | ||
211 | dev_err(card->dev, "cannot get hp_en gpio\n"); | ||
212 | return ret; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | ret = snd_soc_of_parse_card_name(card, "rockchip,model"); | ||
217 | if (ret) { | ||
218 | dev_err(card->dev, "SoC parse card name failed %d\n", ret); | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | rk_dailink.codecs[0].of_node = of_parse_phandle(np, | ||
223 | "rockchip,audio-codec", | ||
224 | 0); | ||
225 | if (!rk_dailink.codecs[0].of_node) { | ||
226 | dev_err(&pdev->dev, | ||
227 | "Property 'rockchip,audio-codec' missing or invalid\n"); | ||
228 | return -EINVAL; | ||
229 | } | ||
230 | ret = of_parse_phandle_with_fixed_args(np, "rockchip,audio-codec", | ||
231 | 0, 0, &args); | ||
232 | if (ret) { | ||
233 | dev_err(&pdev->dev, | ||
234 | "Unable to parse property 'rockchip,audio-codec'\n"); | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | ret = snd_soc_get_dai_name(&args, &rk_dailink.codecs[0].dai_name); | ||
239 | if (ret) { | ||
240 | dev_err(&pdev->dev, "Unable to get codec_dai_name\n"); | ||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | rk_dailink.cpu_of_node = of_parse_phandle(np, "rockchip,i2s-controller", | ||
245 | 0); | ||
246 | if (!rk_dailink.cpu_of_node) { | ||
247 | dev_err(&pdev->dev, | ||
248 | "Property 'rockchip,i2s-controller' missing or invalid\n"); | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | rk_dailink.platform_of_node = rk_dailink.cpu_of_node; | ||
253 | |||
254 | ret = snd_soc_of_parse_audio_routing(card, "rockchip,routing"); | ||
255 | if (ret) { | ||
256 | dev_err(&pdev->dev, | ||
257 | "Unable to parse 'rockchip,routing' property\n"); | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | snd_soc_card_set_drvdata(card, machine); | ||
262 | |||
263 | ret = devm_snd_soc_register_card(&pdev->dev, card); | ||
264 | if (ret == -EPROBE_DEFER) | ||
265 | return -EPROBE_DEFER; | ||
266 | if (ret) { | ||
267 | dev_err(&pdev->dev, | ||
268 | "Soc register card failed %d\n", ret); | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | platform_set_drvdata(pdev, card); | ||
273 | |||
274 | return ret; | ||
275 | } | ||
276 | |||
277 | static const struct of_device_id rockchip_sound_of_match[] = { | ||
278 | { .compatible = "rockchip,rk3288-hdmi-analog", }, | ||
279 | {}, | ||
280 | }; | ||
281 | |||
282 | MODULE_DEVICE_TABLE(of, rockchip_sound_of_match); | ||
283 | |||
284 | static struct platform_driver rockchip_sound_driver = { | ||
285 | .probe = snd_rk_mc_probe, | ||
286 | .driver = { | ||
287 | .name = DRV_NAME, | ||
288 | .owner = THIS_MODULE, | ||
289 | .pm = &snd_soc_pm_ops, | ||
290 | .of_match_table = rockchip_sound_of_match, | ||
291 | }, | ||
292 | }; | ||
293 | |||
294 | module_platform_driver(rockchip_sound_driver); | ||
295 | |||
296 | MODULE_AUTHOR("Sjoerd Simons <sjoerd.simons@collabora.com>"); | ||
297 | MODULE_DESCRIPTION("Rockchip RK3288 machine ASoC driver"); | ||
298 | MODULE_LICENSE("GPL v2"); | ||
299 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 7c423151ef7d..f1f1d7959a1b 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -111,6 +111,7 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380 | |||
111 | config SND_SOC_SMARTQ | 111 | config SND_SOC_SMARTQ |
112 | tristate "SoC I2S Audio support for SmartQ board" | 112 | tristate "SoC I2S Audio support for SmartQ board" |
113 | depends on MACH_SMARTQ || COMPILE_TEST | 113 | depends on MACH_SMARTQ || COMPILE_TEST |
114 | depends on GPIOLIB || COMPILE_TEST | ||
114 | depends on I2C | 115 | depends on I2C |
115 | select SND_SAMSUNG_I2S | 116 | select SND_SAMSUNG_I2S |
116 | select SND_SOC_WM8750 | 117 | select SND_SOC_WM8750 |
@@ -193,6 +194,7 @@ config SND_SOC_ARNDALE_RT5631_ALC5631 | |||
193 | config SND_SOC_SAMSUNG_TM2_WM5110 | 194 | config SND_SOC_SAMSUNG_TM2_WM5110 |
194 | tristate "SoC I2S Audio support for WM5110 on TM2 board" | 195 | tristate "SoC I2S Audio support for WM5110 on TM2 board" |
195 | depends on SND_SOC_SAMSUNG && MFD_ARIZONA && I2C && SPI_MASTER | 196 | depends on SND_SOC_SAMSUNG && MFD_ARIZONA && I2C && SPI_MASTER |
197 | depends on GPIOLIB || COMPILE_TEST | ||
196 | select SND_SOC_MAX98504 | 198 | select SND_SOC_MAX98504 |
197 | select SND_SOC_WM5110 | 199 | select SND_SOC_WM5110 |
198 | select SND_SAMSUNG_I2S | 200 | select SND_SAMSUNG_I2S |
diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c index cda656e4afc6..9104c98deeb7 100644 --- a/sound/soc/samsung/dmaengine.c +++ b/sound/soc/samsung/dmaengine.c | |||
@@ -37,8 +37,12 @@ int samsung_asoc_dma_platform_register(struct device *dev, dma_filter_fn filter, | |||
37 | pcm_conf->prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config; | 37 | pcm_conf->prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config; |
38 | pcm_conf->compat_filter_fn = filter; | 38 | pcm_conf->compat_filter_fn = filter; |
39 | 39 | ||
40 | pcm_conf->chan_names[SNDRV_PCM_STREAM_PLAYBACK] = tx; | 40 | if (dev->of_node) { |
41 | pcm_conf->chan_names[SNDRV_PCM_STREAM_CAPTURE] = rx; | 41 | pcm_conf->chan_names[SNDRV_PCM_STREAM_PLAYBACK] = tx; |
42 | pcm_conf->chan_names[SNDRV_PCM_STREAM_CAPTURE] = rx; | ||
43 | } else { | ||
44 | flags |= SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME; | ||
45 | } | ||
42 | 46 | ||
43 | return devm_snd_dmaengine_pcm_register(dev, pcm_conf, flags); | 47 | return devm_snd_dmaengine_pcm_register(dev, pcm_conf, flags); |
44 | } | 48 | } |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index e00974bc5616..52a47ed292a4 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -34,11 +34,6 @@ | |||
34 | 34 | ||
35 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) | 35 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) |
36 | 36 | ||
37 | enum samsung_dai_type { | ||
38 | TYPE_PRI, | ||
39 | TYPE_SEC, | ||
40 | }; | ||
41 | |||
42 | struct samsung_i2s_variant_regs { | 37 | struct samsung_i2s_variant_regs { |
43 | unsigned int bfs_off; | 38 | unsigned int bfs_off; |
44 | unsigned int rfs_off; | 39 | unsigned int rfs_off; |
@@ -54,7 +49,6 @@ struct samsung_i2s_variant_regs { | |||
54 | }; | 49 | }; |
55 | 50 | ||
56 | struct samsung_i2s_dai_data { | 51 | struct samsung_i2s_dai_data { |
57 | int dai_type; | ||
58 | u32 quirks; | 52 | u32 quirks; |
59 | const struct samsung_i2s_variant_regs *i2s_variant_regs; | 53 | const struct samsung_i2s_variant_regs *i2s_variant_regs; |
60 | }; | 54 | }; |
@@ -483,6 +477,9 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
483 | unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; | 477 | unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; |
484 | u32 mod, mask, val = 0; | 478 | u32 mod, mask, val = 0; |
485 | unsigned long flags; | 479 | unsigned long flags; |
480 | int ret = 0; | ||
481 | |||
482 | pm_runtime_get_sync(dai->dev); | ||
486 | 483 | ||
487 | spin_lock_irqsave(i2s->lock, flags); | 484 | spin_lock_irqsave(i2s->lock, flags); |
488 | mod = readl(i2s->addr + I2SMOD); | 485 | mod = readl(i2s->addr + I2SMOD); |
@@ -507,7 +504,8 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
507 | && (mod & cdcon_mask))))) { | 504 | && (mod & cdcon_mask))))) { |
508 | dev_err(&i2s->pdev->dev, | 505 | dev_err(&i2s->pdev->dev, |
509 | "%s:%d Other DAI busy\n", __func__, __LINE__); | 506 | "%s:%d Other DAI busy\n", __func__, __LINE__); |
510 | return -EAGAIN; | 507 | ret = -EAGAIN; |
508 | goto err; | ||
511 | } | 509 | } |
512 | 510 | ||
513 | if (dir == SND_SOC_CLOCK_IN) | 511 | if (dir == SND_SOC_CLOCK_IN) |
@@ -535,7 +533,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
535 | } else { | 533 | } else { |
536 | i2s->rclk_srcrate = | 534 | i2s->rclk_srcrate = |
537 | clk_get_rate(i2s->op_clk); | 535 | clk_get_rate(i2s->op_clk); |
538 | return 0; | 536 | goto done; |
539 | } | 537 | } |
540 | } | 538 | } |
541 | 539 | ||
@@ -546,8 +544,11 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
546 | i2s->op_clk = clk_get(&i2s->pdev->dev, | 544 | i2s->op_clk = clk_get(&i2s->pdev->dev, |
547 | "i2s_opclk0"); | 545 | "i2s_opclk0"); |
548 | 546 | ||
549 | if (WARN_ON(IS_ERR(i2s->op_clk))) | 547 | if (WARN_ON(IS_ERR(i2s->op_clk))) { |
550 | return PTR_ERR(i2s->op_clk); | 548 | ret = PTR_ERR(i2s->op_clk); |
549 | i2s->op_clk = NULL; | ||
550 | goto err; | ||
551 | } | ||
551 | 552 | ||
552 | clk_prepare_enable(i2s->op_clk); | 553 | clk_prepare_enable(i2s->op_clk); |
553 | i2s->rclk_srcrate = clk_get_rate(i2s->op_clk); | 554 | i2s->rclk_srcrate = clk_get_rate(i2s->op_clk); |
@@ -561,12 +562,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
561 | || (clk_id && !(mod & rsrc_mask))) { | 562 | || (clk_id && !(mod & rsrc_mask))) { |
562 | dev_err(&i2s->pdev->dev, | 563 | dev_err(&i2s->pdev->dev, |
563 | "%s:%d Other DAI busy\n", __func__, __LINE__); | 564 | "%s:%d Other DAI busy\n", __func__, __LINE__); |
564 | return -EAGAIN; | 565 | ret = -EAGAIN; |
566 | goto err; | ||
565 | } else { | 567 | } else { |
566 | /* Call can't be on the active DAI */ | 568 | /* Call can't be on the active DAI */ |
567 | i2s->op_clk = other->op_clk; | 569 | i2s->op_clk = other->op_clk; |
568 | i2s->rclk_srcrate = other->rclk_srcrate; | 570 | i2s->rclk_srcrate = other->rclk_srcrate; |
569 | return 0; | 571 | goto done; |
570 | } | 572 | } |
571 | 573 | ||
572 | if (clk_id == 1) | 574 | if (clk_id == 1) |
@@ -574,7 +576,8 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
574 | break; | 576 | break; |
575 | default: | 577 | default: |
576 | dev_err(&i2s->pdev->dev, "We don't serve that!\n"); | 578 | dev_err(&i2s->pdev->dev, "We don't serve that!\n"); |
577 | return -EINVAL; | 579 | ret = -EINVAL; |
580 | goto err; | ||
578 | } | 581 | } |
579 | 582 | ||
580 | spin_lock_irqsave(i2s->lock, flags); | 583 | spin_lock_irqsave(i2s->lock, flags); |
@@ -582,8 +585,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
582 | mod = (mod & ~mask) | val; | 585 | mod = (mod & ~mask) | val; |
583 | writel(mod, i2s->addr + I2SMOD); | 586 | writel(mod, i2s->addr + I2SMOD); |
584 | spin_unlock_irqrestore(i2s->lock, flags); | 587 | spin_unlock_irqrestore(i2s->lock, flags); |
588 | done: | ||
589 | pm_runtime_put(dai->dev); | ||
585 | 590 | ||
586 | return 0; | 591 | return 0; |
592 | err: | ||
593 | pm_runtime_put(dai->dev); | ||
594 | return ret; | ||
587 | } | 595 | } |
588 | 596 | ||
589 | static int i2s_set_fmt(struct snd_soc_dai *dai, | 597 | static int i2s_set_fmt(struct snd_soc_dai *dai, |
@@ -652,6 +660,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, | |||
652 | return -EINVAL; | 660 | return -EINVAL; |
653 | } | 661 | } |
654 | 662 | ||
663 | pm_runtime_get_sync(dai->dev); | ||
655 | spin_lock_irqsave(i2s->lock, flags); | 664 | spin_lock_irqsave(i2s->lock, flags); |
656 | mod = readl(i2s->addr + I2SMOD); | 665 | mod = readl(i2s->addr + I2SMOD); |
657 | /* | 666 | /* |
@@ -661,6 +670,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, | |||
661 | if (any_active(i2s) && | 670 | if (any_active(i2s) && |
662 | ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) { | 671 | ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) { |
663 | spin_unlock_irqrestore(i2s->lock, flags); | 672 | spin_unlock_irqrestore(i2s->lock, flags); |
673 | pm_runtime_put(dai->dev); | ||
664 | dev_err(&i2s->pdev->dev, | 674 | dev_err(&i2s->pdev->dev, |
665 | "%s:%d Other DAI busy\n", __func__, __LINE__); | 675 | "%s:%d Other DAI busy\n", __func__, __LINE__); |
666 | return -EAGAIN; | 676 | return -EAGAIN; |
@@ -670,6 +680,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, | |||
670 | mod |= tmp; | 680 | mod |= tmp; |
671 | writel(mod, i2s->addr + I2SMOD); | 681 | writel(mod, i2s->addr + I2SMOD); |
672 | spin_unlock_irqrestore(i2s->lock, flags); | 682 | spin_unlock_irqrestore(i2s->lock, flags); |
683 | pm_runtime_put(dai->dev); | ||
673 | 684 | ||
674 | return 0; | 685 | return 0; |
675 | } | 686 | } |
@@ -681,6 +692,8 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, | |||
681 | u32 mod, mask = 0, val = 0; | 692 | u32 mod, mask = 0, val = 0; |
682 | unsigned long flags; | 693 | unsigned long flags; |
683 | 694 | ||
695 | WARN_ON(!pm_runtime_active(dai->dev)); | ||
696 | |||
684 | if (!is_secondary(i2s)) | 697 | if (!is_secondary(i2s)) |
685 | mask |= (MOD_DC2_EN | MOD_DC1_EN); | 698 | mask |= (MOD_DC2_EN | MOD_DC1_EN); |
686 | 699 | ||
@@ -769,6 +782,8 @@ static int i2s_startup(struct snd_pcm_substream *substream, | |||
769 | struct i2s_dai *other = get_other_dai(i2s); | 782 | struct i2s_dai *other = get_other_dai(i2s); |
770 | unsigned long flags; | 783 | unsigned long flags; |
771 | 784 | ||
785 | pm_runtime_get_sync(dai->dev); | ||
786 | |||
772 | spin_lock_irqsave(&lock, flags); | 787 | spin_lock_irqsave(&lock, flags); |
773 | 788 | ||
774 | i2s->mode |= DAI_OPENED; | 789 | i2s->mode |= DAI_OPENED; |
@@ -806,6 +821,8 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, | |||
806 | i2s->bfs = 0; | 821 | i2s->bfs = 0; |
807 | 822 | ||
808 | spin_unlock_irqrestore(&lock, flags); | 823 | spin_unlock_irqrestore(&lock, flags); |
824 | |||
825 | pm_runtime_put(dai->dev); | ||
809 | } | 826 | } |
810 | 827 | ||
811 | static int config_setup(struct i2s_dai *i2s) | 828 | static int config_setup(struct i2s_dai *i2s) |
@@ -880,6 +897,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream, | |||
880 | case SNDRV_PCM_TRIGGER_START: | 897 | case SNDRV_PCM_TRIGGER_START: |
881 | case SNDRV_PCM_TRIGGER_RESUME: | 898 | case SNDRV_PCM_TRIGGER_RESUME: |
882 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 899 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
900 | pm_runtime_get_sync(dai->dev); | ||
883 | spin_lock_irqsave(i2s->lock, flags); | 901 | spin_lock_irqsave(i2s->lock, flags); |
884 | 902 | ||
885 | if (config_setup(i2s)) { | 903 | if (config_setup(i2s)) { |
@@ -908,6 +926,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream, | |||
908 | } | 926 | } |
909 | 927 | ||
910 | spin_unlock_irqrestore(i2s->lock, flags); | 928 | spin_unlock_irqrestore(i2s->lock, flags); |
929 | pm_runtime_put(dai->dev); | ||
911 | break; | 930 | break; |
912 | } | 931 | } |
913 | 932 | ||
@@ -922,13 +941,16 @@ static int i2s_set_clkdiv(struct snd_soc_dai *dai, | |||
922 | 941 | ||
923 | switch (div_id) { | 942 | switch (div_id) { |
924 | case SAMSUNG_I2S_DIV_BCLK: | 943 | case SAMSUNG_I2S_DIV_BCLK: |
944 | pm_runtime_get_sync(dai->dev); | ||
925 | if ((any_active(i2s) && div && (get_bfs(i2s) != div)) | 945 | if ((any_active(i2s) && div && (get_bfs(i2s) != div)) |
926 | || (other && other->bfs && (other->bfs != div))) { | 946 | || (other && other->bfs && (other->bfs != div))) { |
947 | pm_runtime_put(dai->dev); | ||
927 | dev_err(&i2s->pdev->dev, | 948 | dev_err(&i2s->pdev->dev, |
928 | "%s:%d Other DAI busy\n", __func__, __LINE__); | 949 | "%s:%d Other DAI busy\n", __func__, __LINE__); |
929 | return -EAGAIN; | 950 | return -EAGAIN; |
930 | } | 951 | } |
931 | i2s->bfs = div; | 952 | i2s->bfs = div; |
953 | pm_runtime_put(dai->dev); | ||
932 | break; | 954 | break; |
933 | default: | 955 | default: |
934 | dev_err(&i2s->pdev->dev, | 956 | dev_err(&i2s->pdev->dev, |
@@ -947,6 +969,8 @@ i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) | |||
947 | snd_pcm_sframes_t delay; | 969 | snd_pcm_sframes_t delay; |
948 | const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; | 970 | const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; |
949 | 971 | ||
972 | WARN_ON(!pm_runtime_active(dai->dev)); | ||
973 | |||
950 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 974 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
951 | delay = FIC_RXCOUNT(reg); | 975 | delay = FIC_RXCOUNT(reg); |
952 | else if (is_secondary(i2s)) | 976 | else if (is_secondary(i2s)) |
@@ -960,24 +984,12 @@ i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) | |||
960 | #ifdef CONFIG_PM | 984 | #ifdef CONFIG_PM |
961 | static int i2s_suspend(struct snd_soc_dai *dai) | 985 | static int i2s_suspend(struct snd_soc_dai *dai) |
962 | { | 986 | { |
963 | struct i2s_dai *i2s = to_info(dai); | 987 | return pm_runtime_force_suspend(dai->dev); |
964 | |||
965 | i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); | ||
966 | i2s->suspend_i2scon = readl(i2s->addr + I2SCON); | ||
967 | i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); | ||
968 | |||
969 | return 0; | ||
970 | } | 988 | } |
971 | 989 | ||
972 | static int i2s_resume(struct snd_soc_dai *dai) | 990 | static int i2s_resume(struct snd_soc_dai *dai) |
973 | { | 991 | { |
974 | struct i2s_dai *i2s = to_info(dai); | 992 | return pm_runtime_force_resume(dai->dev); |
975 | |||
976 | writel(i2s->suspend_i2scon, i2s->addr + I2SCON); | ||
977 | writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); | ||
978 | writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); | ||
979 | |||
980 | return 0; | ||
981 | } | 993 | } |
982 | #else | 994 | #else |
983 | #define i2s_suspend NULL | 995 | #define i2s_suspend NULL |
@@ -990,6 +1002,8 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) | |||
990 | struct i2s_dai *other = get_other_dai(i2s); | 1002 | struct i2s_dai *other = get_other_dai(i2s); |
991 | unsigned long flags; | 1003 | unsigned long flags; |
992 | 1004 | ||
1005 | pm_runtime_get_sync(dai->dev); | ||
1006 | |||
993 | if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */ | 1007 | if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */ |
994 | snd_soc_dai_init_dma_data(dai, &other->sec_dai->dma_playback, | 1008 | snd_soc_dai_init_dma_data(dai, &other->sec_dai->dma_playback, |
995 | NULL); | 1009 | NULL); |
@@ -1022,6 +1036,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) | |||
1022 | if (!is_opened(other)) | 1036 | if (!is_opened(other)) |
1023 | i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, | 1037 | i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, |
1024 | 0, SND_SOC_CLOCK_IN); | 1038 | 0, SND_SOC_CLOCK_IN); |
1039 | pm_runtime_put(dai->dev); | ||
1025 | 1040 | ||
1026 | return 0; | 1041 | return 0; |
1027 | } | 1042 | } |
@@ -1031,6 +1046,8 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) | |||
1031 | struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); | 1046 | struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); |
1032 | unsigned long flags; | 1047 | unsigned long flags; |
1033 | 1048 | ||
1049 | pm_runtime_get_sync(dai->dev); | ||
1050 | |||
1034 | if (!is_secondary(i2s)) { | 1051 | if (!is_secondary(i2s)) { |
1035 | if (i2s->quirks & QUIRK_NEED_RSTCLR) { | 1052 | if (i2s->quirks & QUIRK_NEED_RSTCLR) { |
1036 | spin_lock_irqsave(i2s->lock, flags); | 1053 | spin_lock_irqsave(i2s->lock, flags); |
@@ -1039,6 +1056,8 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) | |||
1039 | } | 1056 | } |
1040 | } | 1057 | } |
1041 | 1058 | ||
1059 | pm_runtime_put(dai->dev); | ||
1060 | |||
1042 | return 0; | 1061 | return 0; |
1043 | } | 1062 | } |
1044 | 1063 | ||
@@ -1066,7 +1085,6 @@ static const struct snd_soc_component_driver samsung_i2s_component = { | |||
1066 | static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) | 1085 | static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) |
1067 | { | 1086 | { |
1068 | struct i2s_dai *i2s; | 1087 | struct i2s_dai *i2s; |
1069 | int ret; | ||
1070 | 1088 | ||
1071 | i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL); | 1089 | i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL); |
1072 | if (i2s == NULL) | 1090 | if (i2s == NULL) |
@@ -1091,33 +1109,21 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) | |||
1091 | i2s->i2s_dai_drv.capture.channels_max = 2; | 1109 | i2s->i2s_dai_drv.capture.channels_max = 2; |
1092 | i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES; | 1110 | i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES; |
1093 | i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS; | 1111 | i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS; |
1094 | dev_set_drvdata(&i2s->pdev->dev, i2s); | ||
1095 | } else { /* Create a new platform_device for Secondary */ | ||
1096 | i2s->pdev = platform_device_alloc("samsung-i2s-sec", -1); | ||
1097 | if (!i2s->pdev) | ||
1098 | return NULL; | ||
1099 | |||
1100 | i2s->pdev->dev.parent = &pdev->dev; | ||
1101 | |||
1102 | platform_set_drvdata(i2s->pdev, i2s); | ||
1103 | ret = platform_device_add(i2s->pdev); | ||
1104 | if (ret < 0) | ||
1105 | return NULL; | ||
1106 | } | 1112 | } |
1107 | |||
1108 | return i2s; | 1113 | return i2s; |
1109 | } | 1114 | } |
1110 | 1115 | ||
1111 | static void i2s_free_sec_dai(struct i2s_dai *i2s) | ||
1112 | { | ||
1113 | platform_device_del(i2s->pdev); | ||
1114 | } | ||
1115 | |||
1116 | #ifdef CONFIG_PM | 1116 | #ifdef CONFIG_PM |
1117 | static int i2s_runtime_suspend(struct device *dev) | 1117 | static int i2s_runtime_suspend(struct device *dev) |
1118 | { | 1118 | { |
1119 | struct i2s_dai *i2s = dev_get_drvdata(dev); | 1119 | struct i2s_dai *i2s = dev_get_drvdata(dev); |
1120 | 1120 | ||
1121 | i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); | ||
1122 | i2s->suspend_i2scon = readl(i2s->addr + I2SCON); | ||
1123 | i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); | ||
1124 | |||
1125 | if (i2s->op_clk) | ||
1126 | clk_disable_unprepare(i2s->op_clk); | ||
1121 | clk_disable_unprepare(i2s->clk); | 1127 | clk_disable_unprepare(i2s->clk); |
1122 | 1128 | ||
1123 | return 0; | 1129 | return 0; |
@@ -1128,6 +1134,12 @@ static int i2s_runtime_resume(struct device *dev) | |||
1128 | struct i2s_dai *i2s = dev_get_drvdata(dev); | 1134 | struct i2s_dai *i2s = dev_get_drvdata(dev); |
1129 | 1135 | ||
1130 | clk_prepare_enable(i2s->clk); | 1136 | clk_prepare_enable(i2s->clk); |
1137 | if (i2s->op_clk) | ||
1138 | clk_prepare_enable(i2s->op_clk); | ||
1139 | |||
1140 | writel(i2s->suspend_i2scon, i2s->addr + I2SCON); | ||
1141 | writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); | ||
1142 | writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); | ||
1131 | 1143 | ||
1132 | return 0; | 1144 | return 0; |
1133 | } | 1145 | } |
@@ -1179,13 +1191,13 @@ static int i2s_register_clock_provider(struct platform_device *pdev) | |||
1179 | u32 val = readl(i2s->addr + I2SPSR); | 1191 | u32 val = readl(i2s->addr + I2SPSR); |
1180 | writel(val | PSR_PSREN, i2s->addr + I2SPSR); | 1192 | writel(val | PSR_PSREN, i2s->addr + I2SPSR); |
1181 | 1193 | ||
1182 | i2s->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(NULL, | 1194 | i2s->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev, |
1183 | "i2s_rclksrc", p_names, ARRAY_SIZE(p_names), | 1195 | "i2s_rclksrc", p_names, ARRAY_SIZE(p_names), |
1184 | CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, | 1196 | CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, |
1185 | i2s->addr + I2SMOD, reg_info->rclksrc_off, | 1197 | i2s->addr + I2SMOD, reg_info->rclksrc_off, |
1186 | 1, 0, i2s->lock); | 1198 | 1, 0, i2s->lock); |
1187 | 1199 | ||
1188 | i2s->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(NULL, | 1200 | i2s->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev, |
1189 | "i2s_presc", "i2s_rclksrc", | 1201 | "i2s_presc", "i2s_rclksrc", |
1190 | CLK_SET_RATE_PARENT, | 1202 | CLK_SET_RATE_PARENT, |
1191 | i2s->addr + I2SPSR, 8, 6, 0, i2s->lock); | 1203 | i2s->addr + I2SPSR, 8, 6, 0, i2s->lock); |
@@ -1196,7 +1208,7 @@ static int i2s_register_clock_provider(struct platform_device *pdev) | |||
1196 | of_property_read_string_index(dev->of_node, | 1208 | of_property_read_string_index(dev->of_node, |
1197 | "clock-output-names", 0, &clk_name[0]); | 1209 | "clock-output-names", 0, &clk_name[0]); |
1198 | 1210 | ||
1199 | i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(NULL, clk_name[0], | 1211 | i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev, clk_name[0], |
1200 | p_names[0], CLK_SET_RATE_PARENT, | 1212 | p_names[0], CLK_SET_RATE_PARENT, |
1201 | i2s->addr + I2SMOD, reg_info->cdclkcon_off, | 1213 | i2s->addr + I2SMOD, reg_info->cdclkcon_off, |
1202 | CLK_GATE_SET_TO_DISABLE, i2s->lock); | 1214 | CLK_GATE_SET_TO_DISABLE, i2s->lock); |
@@ -1218,7 +1230,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1218 | { | 1230 | { |
1219 | struct i2s_dai *pri_dai, *sec_dai = NULL; | 1231 | struct i2s_dai *pri_dai, *sec_dai = NULL; |
1220 | struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data; | 1232 | struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data; |
1221 | struct samsung_i2s *i2s_cfg = NULL; | ||
1222 | struct resource *res; | 1233 | struct resource *res; |
1223 | u32 regs_base, quirks = 0, idma_addr = 0; | 1234 | u32 regs_base, quirks = 0, idma_addr = 0; |
1224 | struct device_node *np = pdev->dev.of_node; | 1235 | struct device_node *np = pdev->dev.of_node; |
@@ -1231,22 +1242,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1231 | i2s_dai_data = (struct samsung_i2s_dai_data *) | 1242 | i2s_dai_data = (struct samsung_i2s_dai_data *) |
1232 | platform_get_device_id(pdev)->driver_data; | 1243 | platform_get_device_id(pdev)->driver_data; |
1233 | 1244 | ||
1234 | /* Call during the secondary interface registration */ | ||
1235 | if (i2s_dai_data->dai_type == TYPE_SEC) { | ||
1236 | sec_dai = dev_get_drvdata(&pdev->dev); | ||
1237 | if (!sec_dai) { | ||
1238 | dev_err(&pdev->dev, "Unable to get drvdata\n"); | ||
1239 | return -EFAULT; | ||
1240 | } | ||
1241 | ret = samsung_asoc_dma_platform_register(&pdev->dev, | ||
1242 | sec_dai->filter, "tx-sec", NULL); | ||
1243 | if (ret != 0) | ||
1244 | return ret; | ||
1245 | |||
1246 | return devm_snd_soc_register_component(&sec_dai->pdev->dev, | ||
1247 | &samsung_i2s_component, | ||
1248 | &sec_dai->i2s_dai_drv, 1); | ||
1249 | } | ||
1250 | 1245 | ||
1251 | pri_dai = i2s_alloc_dai(pdev, false); | 1246 | pri_dai = i2s_alloc_dai(pdev, false); |
1252 | if (!pri_dai) { | 1247 | if (!pri_dai) { |
@@ -1267,13 +1262,8 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1267 | pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture; | 1262 | pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture; |
1268 | pri_dai->filter = i2s_pdata->dma_filter; | 1263 | pri_dai->filter = i2s_pdata->dma_filter; |
1269 | 1264 | ||
1270 | if (&i2s_pdata->type) | 1265 | quirks = i2s_pdata->type.quirks; |
1271 | i2s_cfg = &i2s_pdata->type.i2s; | 1266 | idma_addr = i2s_pdata->type.idma_addr; |
1272 | |||
1273 | if (i2s_cfg) { | ||
1274 | quirks = i2s_cfg->quirks; | ||
1275 | idma_addr = i2s_cfg->idma_addr; | ||
1276 | } | ||
1277 | } else { | 1267 | } else { |
1278 | quirks = i2s_dai_data->quirks; | 1268 | quirks = i2s_dai_data->quirks; |
1279 | if (of_property_read_u32(np, "samsung,idma-addr", | 1269 | if (of_property_read_u32(np, "samsung,idma-addr", |
@@ -1305,6 +1295,8 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1305 | } | 1295 | } |
1306 | pri_dai->dma_playback.addr = regs_base + I2STXD; | 1296 | pri_dai->dma_playback.addr = regs_base + I2STXD; |
1307 | pri_dai->dma_capture.addr = regs_base + I2SRXD; | 1297 | pri_dai->dma_capture.addr = regs_base + I2SRXD; |
1298 | pri_dai->dma_playback.chan_name = "tx"; | ||
1299 | pri_dai->dma_capture.chan_name = "rx"; | ||
1308 | pri_dai->dma_playback.addr_width = 4; | 1300 | pri_dai->dma_playback.addr_width = 4; |
1309 | pri_dai->dma_capture.addr_width = 4; | 1301 | pri_dai->dma_capture.addr_width = 4; |
1310 | pri_dai->quirks = quirks; | 1302 | pri_dai->quirks = quirks; |
@@ -1318,6 +1310,12 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1318 | if (ret < 0) | 1310 | if (ret < 0) |
1319 | goto err_disable_clk; | 1311 | goto err_disable_clk; |
1320 | 1312 | ||
1313 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
1314 | &samsung_i2s_component, | ||
1315 | &pri_dai->i2s_dai_drv, 1); | ||
1316 | if (ret < 0) | ||
1317 | goto err_disable_clk; | ||
1318 | |||
1321 | if (quirks & QUIRK_SEC_DAI) { | 1319 | if (quirks & QUIRK_SEC_DAI) { |
1322 | sec_dai = i2s_alloc_dai(pdev, true); | 1320 | sec_dai = i2s_alloc_dai(pdev, true); |
1323 | if (!sec_dai) { | 1321 | if (!sec_dai) { |
@@ -1329,6 +1327,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1329 | sec_dai->lock = &pri_dai->spinlock; | 1327 | sec_dai->lock = &pri_dai->spinlock; |
1330 | sec_dai->variant_regs = pri_dai->variant_regs; | 1328 | sec_dai->variant_regs = pri_dai->variant_regs; |
1331 | sec_dai->dma_playback.addr = regs_base + I2STXDS; | 1329 | sec_dai->dma_playback.addr = regs_base + I2STXDS; |
1330 | sec_dai->dma_playback.chan_name = "tx-sec"; | ||
1332 | 1331 | ||
1333 | if (!np) { | 1332 | if (!np) { |
1334 | sec_dai->dma_playback.filter_data = i2s_pdata->dma_play_sec; | 1333 | sec_dai->dma_playback.filter_data = i2s_pdata->dma_play_sec; |
@@ -1342,6 +1341,17 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1342 | sec_dai->idma_playback.addr = idma_addr; | 1341 | sec_dai->idma_playback.addr = idma_addr; |
1343 | sec_dai->pri_dai = pri_dai; | 1342 | sec_dai->pri_dai = pri_dai; |
1344 | pri_dai->sec_dai = sec_dai; | 1343 | pri_dai->sec_dai = sec_dai; |
1344 | |||
1345 | ret = samsung_asoc_dma_platform_register(&pdev->dev, | ||
1346 | sec_dai->filter, "tx-sec", NULL); | ||
1347 | if (ret < 0) | ||
1348 | goto err_disable_clk; | ||
1349 | |||
1350 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
1351 | &samsung_i2s_component, | ||
1352 | &sec_dai->i2s_dai_drv, 1); | ||
1353 | if (ret < 0) | ||
1354 | goto err_disable_clk; | ||
1345 | } | 1355 | } |
1346 | 1356 | ||
1347 | if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { | 1357 | if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { |
@@ -1350,13 +1360,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1350 | goto err_disable_clk; | 1360 | goto err_disable_clk; |
1351 | } | 1361 | } |
1352 | 1362 | ||
1353 | ret = devm_snd_soc_register_component(&pri_dai->pdev->dev, | 1363 | dev_set_drvdata(&pdev->dev, pri_dai); |
1354 | &samsung_i2s_component, | ||
1355 | &pri_dai->i2s_dai_drv, 1); | ||
1356 | if (ret < 0) | ||
1357 | goto err_free_dai; | ||
1358 | |||
1359 | 1364 | ||
1365 | pm_runtime_set_active(&pdev->dev); | ||
1360 | pm_runtime_enable(&pdev->dev); | 1366 | pm_runtime_enable(&pdev->dev); |
1361 | 1367 | ||
1362 | ret = i2s_register_clock_provider(pdev); | 1368 | ret = i2s_register_clock_provider(pdev); |
@@ -1364,9 +1370,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1364 | return 0; | 1370 | return 0; |
1365 | 1371 | ||
1366 | pm_runtime_disable(&pdev->dev); | 1372 | pm_runtime_disable(&pdev->dev); |
1367 | err_free_dai: | ||
1368 | if (sec_dai) | ||
1369 | i2s_free_sec_dai(sec_dai); | ||
1370 | err_disable_clk: | 1373 | err_disable_clk: |
1371 | clk_disable_unprepare(pri_dai->clk); | 1374 | clk_disable_unprepare(pri_dai->clk); |
1372 | return ret; | 1375 | return ret; |
@@ -1374,25 +1377,20 @@ err_disable_clk: | |||
1374 | 1377 | ||
1375 | static int samsung_i2s_remove(struct platform_device *pdev) | 1378 | static int samsung_i2s_remove(struct platform_device *pdev) |
1376 | { | 1379 | { |
1377 | struct i2s_dai *i2s, *other; | 1380 | struct i2s_dai *pri_dai, *sec_dai; |
1378 | 1381 | ||
1379 | i2s = dev_get_drvdata(&pdev->dev); | 1382 | pri_dai = dev_get_drvdata(&pdev->dev); |
1380 | other = get_other_dai(i2s); | 1383 | sec_dai = pri_dai->sec_dai; |
1381 | 1384 | ||
1382 | if (other) { | 1385 | pri_dai->sec_dai = NULL; |
1383 | other->pri_dai = NULL; | 1386 | sec_dai->pri_dai = NULL; |
1384 | other->sec_dai = NULL; | ||
1385 | } else { | ||
1386 | pm_runtime_disable(&pdev->dev); | ||
1387 | } | ||
1388 | 1387 | ||
1389 | if (!is_secondary(i2s)) { | 1388 | pm_runtime_get_sync(&pdev->dev); |
1390 | i2s_unregister_clock_provider(pdev); | 1389 | pm_runtime_disable(&pdev->dev); |
1391 | clk_disable_unprepare(i2s->clk); | ||
1392 | } | ||
1393 | 1390 | ||
1394 | i2s->pri_dai = NULL; | 1391 | i2s_unregister_clock_provider(pdev); |
1395 | i2s->sec_dai = NULL; | 1392 | clk_disable_unprepare(pri_dai->clk); |
1393 | pm_runtime_put_noidle(&pdev->dev); | ||
1396 | 1394 | ||
1397 | return 0; | 1395 | return 0; |
1398 | } | 1396 | } |
@@ -1454,49 +1452,37 @@ static const struct samsung_i2s_variant_regs i2sv5_i2s1_regs = { | |||
1454 | }; | 1452 | }; |
1455 | 1453 | ||
1456 | static const struct samsung_i2s_dai_data i2sv3_dai_type = { | 1454 | static const struct samsung_i2s_dai_data i2sv3_dai_type = { |
1457 | .dai_type = TYPE_PRI, | ||
1458 | .quirks = QUIRK_NO_MUXPSR, | 1455 | .quirks = QUIRK_NO_MUXPSR, |
1459 | .i2s_variant_regs = &i2sv3_regs, | 1456 | .i2s_variant_regs = &i2sv3_regs, |
1460 | }; | 1457 | }; |
1461 | 1458 | ||
1462 | static const struct samsung_i2s_dai_data i2sv5_dai_type = { | 1459 | static const struct samsung_i2s_dai_data i2sv5_dai_type = { |
1463 | .dai_type = TYPE_PRI, | ||
1464 | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | | 1460 | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | |
1465 | QUIRK_SUPPORTS_IDMA, | 1461 | QUIRK_SUPPORTS_IDMA, |
1466 | .i2s_variant_regs = &i2sv3_regs, | 1462 | .i2s_variant_regs = &i2sv3_regs, |
1467 | }; | 1463 | }; |
1468 | 1464 | ||
1469 | static const struct samsung_i2s_dai_data i2sv6_dai_type = { | 1465 | static const struct samsung_i2s_dai_data i2sv6_dai_type = { |
1470 | .dai_type = TYPE_PRI, | ||
1471 | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | | 1466 | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | |
1472 | QUIRK_SUPPORTS_TDM | QUIRK_SUPPORTS_IDMA, | 1467 | QUIRK_SUPPORTS_TDM | QUIRK_SUPPORTS_IDMA, |
1473 | .i2s_variant_regs = &i2sv6_regs, | 1468 | .i2s_variant_regs = &i2sv6_regs, |
1474 | }; | 1469 | }; |
1475 | 1470 | ||
1476 | static const struct samsung_i2s_dai_data i2sv7_dai_type = { | 1471 | static const struct samsung_i2s_dai_data i2sv7_dai_type = { |
1477 | .dai_type = TYPE_PRI, | ||
1478 | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | | 1472 | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | |
1479 | QUIRK_SUPPORTS_TDM, | 1473 | QUIRK_SUPPORTS_TDM, |
1480 | .i2s_variant_regs = &i2sv7_regs, | 1474 | .i2s_variant_regs = &i2sv7_regs, |
1481 | }; | 1475 | }; |
1482 | 1476 | ||
1483 | static const struct samsung_i2s_dai_data i2sv5_dai_type_i2s1 = { | 1477 | static const struct samsung_i2s_dai_data i2sv5_dai_type_i2s1 = { |
1484 | .dai_type = TYPE_PRI, | ||
1485 | .quirks = QUIRK_PRI_6CHAN | QUIRK_NEED_RSTCLR, | 1478 | .quirks = QUIRK_PRI_6CHAN | QUIRK_NEED_RSTCLR, |
1486 | .i2s_variant_regs = &i2sv5_i2s1_regs, | 1479 | .i2s_variant_regs = &i2sv5_i2s1_regs, |
1487 | }; | 1480 | }; |
1488 | 1481 | ||
1489 | static const struct samsung_i2s_dai_data samsung_dai_type_sec = { | ||
1490 | .dai_type = TYPE_SEC, | ||
1491 | }; | ||
1492 | |||
1493 | static const struct platform_device_id samsung_i2s_driver_ids[] = { | 1482 | static const struct platform_device_id samsung_i2s_driver_ids[] = { |
1494 | { | 1483 | { |
1495 | .name = "samsung-i2s", | 1484 | .name = "samsung-i2s", |
1496 | .driver_data = (kernel_ulong_t)&i2sv3_dai_type, | 1485 | .driver_data = (kernel_ulong_t)&i2sv3_dai_type, |
1497 | }, { | ||
1498 | .name = "samsung-i2s-sec", | ||
1499 | .driver_data = (kernel_ulong_t)&samsung_dai_type_sec, | ||
1500 | }, | 1486 | }, |
1501 | {}, | 1487 | {}, |
1502 | }; | 1488 | }; |
@@ -1528,6 +1514,8 @@ MODULE_DEVICE_TABLE(of, exynos_i2s_match); | |||
1528 | static const struct dev_pm_ops samsung_i2s_pm = { | 1514 | static const struct dev_pm_ops samsung_i2s_pm = { |
1529 | SET_RUNTIME_PM_OPS(i2s_runtime_suspend, | 1515 | SET_RUNTIME_PM_OPS(i2s_runtime_suspend, |
1530 | i2s_runtime_resume, NULL) | 1516 | i2s_runtime_resume, NULL) |
1517 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | ||
1518 | pm_runtime_force_resume) | ||
1531 | }; | 1519 | }; |
1532 | 1520 | ||
1533 | static struct platform_driver samsung_i2s_driver = { | 1521 | static struct platform_driver samsung_i2s_driver = { |
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 6d0b8897fa6c..0a4718207e6e 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c | |||
@@ -35,10 +35,12 @@ | |||
35 | #include <linux/platform_data/asoc-s3c.h> | 35 | #include <linux/platform_data/asoc-s3c.h> |
36 | 36 | ||
37 | static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_out = { | 37 | static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_out = { |
38 | .chan_name = "tx", | ||
38 | .addr_width = 4, | 39 | .addr_width = 4, |
39 | }; | 40 | }; |
40 | 41 | ||
41 | static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_in = { | 42 | static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_in = { |
43 | .chan_name = "rx", | ||
42 | .addr_width = 4, | 44 | .addr_width = 4, |
43 | }; | 45 | }; |
44 | 46 | ||
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 07f5091b33e8..91e6871e5413 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
@@ -31,10 +31,12 @@ | |||
31 | #include "s3c24xx-i2s.h" | 31 | #include "s3c24xx-i2s.h" |
32 | 32 | ||
33 | static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = { | 33 | static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = { |
34 | .chan_name = "tx", | ||
34 | .addr_width = 2, | 35 | .addr_width = 2, |
35 | }; | 36 | }; |
36 | 37 | ||
37 | static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_in = { | 38 | static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_in = { |
39 | .chan_name = "rx", | ||
38 | .addr_width = 2, | 40 | .addr_width = 2, |
39 | }; | 41 | }; |
40 | 42 | ||
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index de724ce7b955..6e4dfa7e2c89 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c | |||
@@ -32,14 +32,11 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, | |||
32 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 32 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
33 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 33 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
34 | unsigned int pll_out; | 34 | unsigned int pll_out; |
35 | int bfs, rfs, ret; | 35 | int rfs, ret; |
36 | 36 | ||
37 | switch (params_width(params)) { | 37 | switch (params_width(params)) { |
38 | case 8: | 38 | case 8: |
39 | bfs = 16; | ||
40 | break; | ||
41 | case 16: | 39 | case 16: |
42 | bfs = 32; | ||
43 | break; | 40 | break; |
44 | default: | 41 | default: |
45 | return -EINVAL; | 42 | return -EINVAL; |
diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 5cdf7d19b87f..24cc9d63ce87 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
14 | #include <linux/gpio.h> | 14 | #include <linux/gpio.h> |
15 | #include <linux/gpio/consumer.h> | ||
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/of.h> | 17 | #include <linux/of.h> |
17 | #include <sound/pcm_params.h> | 18 | #include <sound/pcm_params.h> |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 99b5b0835c1e..47b370cb2d3b 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -363,8 +363,6 @@ struct rsnd_mod *rsnd_mod_next(int *iterator, | |||
363 | if (!mod) | 363 | if (!mod) |
364 | continue; | 364 | continue; |
365 | 365 | ||
366 | (*iterator)++; | ||
367 | |||
368 | return mod; | 366 | return mod; |
369 | } | 367 | } |
370 | 368 | ||
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b90df77662df..7410ec0174db 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -374,10 +374,10 @@ struct rsnd_mod *rsnd_mod_next(int *iterator, | |||
374 | int array_size); | 374 | int array_size); |
375 | #define for_each_rsnd_mod(iterator, pos, io) \ | 375 | #define for_each_rsnd_mod(iterator, pos, io) \ |
376 | for (iterator = 0; \ | 376 | for (iterator = 0; \ |
377 | (pos = rsnd_mod_next(&iterator, io, NULL, 0));) | 377 | (pos = rsnd_mod_next(&iterator, io, NULL, 0)); iterator++) |
378 | #define for_each_rsnd_mod_arrays(iterator, pos, io, array, size) \ | 378 | #define for_each_rsnd_mod_arrays(iterator, pos, io, array, size) \ |
379 | for (iterator = 0; \ | 379 | for (iterator = 0; \ |
380 | (pos = rsnd_mod_next(&iterator, io, array, size));) | 380 | (pos = rsnd_mod_next(&iterator, io, array, size)); iterator++) |
381 | #define for_each_rsnd_mod_array(iterator, pos, io, array) \ | 381 | #define for_each_rsnd_mod_array(iterator, pos, io, array) \ |
382 | for_each_rsnd_mod_arrays(iterator, pos, io, array, ARRAY_SIZE(array)) | 382 | for_each_rsnd_mod_arrays(iterator, pos, io, array, ARRAY_SIZE(array)) |
383 | 383 | ||
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 3a8f65bd1bf9..42db48db09ba 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -390,6 +390,9 @@ static int rsnd_src_init(struct rsnd_mod *mod, | |||
390 | { | 390 | { |
391 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 391 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
392 | 392 | ||
393 | /* reset sync convert_rate */ | ||
394 | src->sync.val = 0; | ||
395 | |||
393 | rsnd_mod_power_on(mod); | 396 | rsnd_mod_power_on(mod); |
394 | 397 | ||
395 | rsnd_src_activation(mod); | 398 | rsnd_src_activation(mod); |
@@ -398,9 +401,6 @@ static int rsnd_src_init(struct rsnd_mod *mod, | |||
398 | 401 | ||
399 | rsnd_src_status_clear(mod); | 402 | rsnd_src_status_clear(mod); |
400 | 403 | ||
401 | /* reset sync convert_rate */ | ||
402 | src->sync.val = 0; | ||
403 | |||
404 | return 0; | 404 | return 0; |
405 | } | 405 | } |
406 | 406 | ||
diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index 6c8b0b0c56ec..36dae41f65fc 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c | |||
@@ -251,7 +251,7 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | |||
251 | 251 | ||
252 | /** | 252 | /** |
253 | * snd_soc_free_ac97_codec - free AC97 codec device | 253 | * snd_soc_free_ac97_codec - free AC97 codec device |
254 | * @codec: audio codec | 254 | * @ac97: snd_ac97 device to be freed |
255 | * | 255 | * |
256 | * Frees AC97 codec device resources. | 256 | * Frees AC97 codec device resources. |
257 | */ | 257 | */ |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index baa1afa41e3d..a110d3987d4a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/dmi.h> | ||
37 | #include <sound/core.h> | 38 | #include <sound/core.h> |
38 | #include <sound/jack.h> | 39 | #include <sound/jack.h> |
39 | #include <sound/pcm.h> | 40 | #include <sound/pcm.h> |
@@ -979,7 +980,7 @@ EXPORT_SYMBOL_GPL(snd_soc_find_dai); | |||
979 | * @card: soc card | 980 | * @card: soc card |
980 | * @id: DAI link ID to match | 981 | * @id: DAI link ID to match |
981 | * @name: DAI link name to match, optional | 982 | * @name: DAI link name to match, optional |
982 | * @stream name: DAI link stream name to match, optional | 983 | * @stream_name: DAI link stream name to match, optional |
983 | * | 984 | * |
984 | * This function will search all existing DAI links of the soc card to | 985 | * This function will search all existing DAI links of the soc card to |
985 | * find the link of the same ID. Since DAI links may not have their | 986 | * find the link of the same ID. Since DAI links may not have their |
@@ -1593,6 +1594,27 @@ static int soc_probe_dai(struct snd_soc_dai *dai, int order) | |||
1593 | return 0; | 1594 | return 0; |
1594 | } | 1595 | } |
1595 | 1596 | ||
1597 | static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais, | ||
1598 | struct snd_soc_pcm_runtime *rtd) | ||
1599 | { | ||
1600 | int i, ret = 0; | ||
1601 | |||
1602 | for (i = 0; i < num_dais; ++i) { | ||
1603 | struct snd_soc_dai_driver *drv = dais[i]->driver; | ||
1604 | |||
1605 | if (!rtd->dai_link->no_pcm && drv->pcm_new) | ||
1606 | ret = drv->pcm_new(rtd, dais[i]); | ||
1607 | if (ret < 0) { | ||
1608 | dev_err(dais[i]->dev, | ||
1609 | "ASoC: Failed to bind %s with pcm device\n", | ||
1610 | dais[i]->name); | ||
1611 | return ret; | ||
1612 | } | ||
1613 | } | ||
1614 | |||
1615 | return 0; | ||
1616 | } | ||
1617 | |||
1596 | static int soc_link_dai_widgets(struct snd_soc_card *card, | 1618 | static int soc_link_dai_widgets(struct snd_soc_card *card, |
1597 | struct snd_soc_dai_link *dai_link, | 1619 | struct snd_soc_dai_link *dai_link, |
1598 | struct snd_soc_pcm_runtime *rtd) | 1620 | struct snd_soc_pcm_runtime *rtd) |
@@ -1704,6 +1726,13 @@ static int soc_probe_link_dais(struct snd_soc_card *card, | |||
1704 | dai_link->stream_name, ret); | 1726 | dai_link->stream_name, ret); |
1705 | return ret; | 1727 | return ret; |
1706 | } | 1728 | } |
1729 | ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); | ||
1730 | if (ret < 0) | ||
1731 | return ret; | ||
1732 | ret = soc_link_dai_pcm_new(rtd->codec_dais, | ||
1733 | rtd->num_codecs, rtd); | ||
1734 | if (ret < 0) | ||
1735 | return ret; | ||
1707 | } else { | 1736 | } else { |
1708 | INIT_DELAYED_WORK(&rtd->delayed_work, | 1737 | INIT_DELAYED_WORK(&rtd->delayed_work, |
1709 | codec2codec_close_delayed_work); | 1738 | codec2codec_close_delayed_work); |
@@ -1888,6 +1917,139 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, | |||
1888 | } | 1917 | } |
1889 | EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt); | 1918 | EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt); |
1890 | 1919 | ||
1920 | |||
1921 | /* Trim special characters, and replace '-' with '_' since '-' is used to | ||
1922 | * separate different DMI fields in the card long name. Only number and | ||
1923 | * alphabet characters and a few separator characters are kept. | ||
1924 | */ | ||
1925 | static void cleanup_dmi_name(char *name) | ||
1926 | { | ||
1927 | int i, j = 0; | ||
1928 | |||
1929 | for (i = 0; name[i]; i++) { | ||
1930 | if (isalnum(name[i]) || (name[i] == '.') | ||
1931 | || (name[i] == '_')) | ||
1932 | name[j++] = name[i]; | ||
1933 | else if (name[i] == '-') | ||
1934 | name[j++] = '_'; | ||
1935 | } | ||
1936 | |||
1937 | name[j] = '\0'; | ||
1938 | } | ||
1939 | |||
1940 | /** | ||
1941 | * snd_soc_set_dmi_name() - Register DMI names to card | ||
1942 | * @card: The card to register DMI names | ||
1943 | * @flavour: The flavour "differentiator" for the card amongst its peers. | ||
1944 | * | ||
1945 | * An Intel machine driver may be used by many different devices but are | ||
1946 | * difficult for userspace to differentiate, since machine drivers ususally | ||
1947 | * use their own name as the card short name and leave the card long name | ||
1948 | * blank. To differentiate such devices and fix bugs due to lack of | ||
1949 | * device-specific configurations, this function allows DMI info to be used | ||
1950 | * as the sound card long name, in the format of | ||
1951 | * "vendor-product-version-board" | ||
1952 | * (Character '-' is used to separate different DMI fields here). | ||
1953 | * This will help the user space to load the device-specific Use Case Manager | ||
1954 | * (UCM) configurations for the card. | ||
1955 | * | ||
1956 | * Possible card long names may be: | ||
1957 | * DellInc.-XPS139343-01-0310JH | ||
1958 | * ASUSTeKCOMPUTERINC.-T100TA-1.0-T100TA | ||
1959 | * Circuitco-MinnowboardMaxD0PLATFORM-D0-MinnowBoardMAX | ||
1960 | * | ||
1961 | * This function also supports flavoring the card longname to provide | ||
1962 | * the extra differentiation, like "vendor-product-version-board-flavor". | ||
1963 | * | ||
1964 | * We only keep number and alphabet characters and a few separator characters | ||
1965 | * in the card long name since UCM in the user space uses the card long names | ||
1966 | * as card configuration directory names and AudoConf cannot support special | ||
1967 | * charactors like SPACE. | ||
1968 | * | ||
1969 | * Returns 0 on success, otherwise a negative error code. | ||
1970 | */ | ||
1971 | int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | ||
1972 | { | ||
1973 | const char *vendor, *product, *product_version, *board; | ||
1974 | size_t longname_buf_size = sizeof(card->snd_card->longname); | ||
1975 | size_t len; | ||
1976 | |||
1977 | if (card->long_name) | ||
1978 | return 0; /* long name already set by driver or from DMI */ | ||
1979 | |||
1980 | /* make up dmi long name as: vendor.product.version.board */ | ||
1981 | vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | ||
1982 | if (!vendor) { | ||
1983 | dev_warn(card->dev, "ASoC: no DMI vendor name!\n"); | ||
1984 | return 0; | ||
1985 | } | ||
1986 | |||
1987 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), | ||
1988 | "%s", vendor); | ||
1989 | cleanup_dmi_name(card->dmi_longname); | ||
1990 | |||
1991 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
1992 | if (product) { | ||
1993 | len = strlen(card->dmi_longname); | ||
1994 | snprintf(card->dmi_longname + len, | ||
1995 | longname_buf_size - len, | ||
1996 | "-%s", product); | ||
1997 | |||
1998 | len++; /* skip the separator "-" */ | ||
1999 | if (len < longname_buf_size) | ||
2000 | cleanup_dmi_name(card->dmi_longname + len); | ||
2001 | |||
2002 | /* some vendors like Lenovo may only put a self-explanatory | ||
2003 | * name in the product version field | ||
2004 | */ | ||
2005 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); | ||
2006 | if (product_version) { | ||
2007 | len = strlen(card->dmi_longname); | ||
2008 | snprintf(card->dmi_longname + len, | ||
2009 | longname_buf_size - len, | ||
2010 | "-%s", product_version); | ||
2011 | |||
2012 | len++; | ||
2013 | if (len < longname_buf_size) | ||
2014 | cleanup_dmi_name(card->dmi_longname + len); | ||
2015 | } | ||
2016 | } | ||
2017 | |||
2018 | board = dmi_get_system_info(DMI_BOARD_NAME); | ||
2019 | if (board) { | ||
2020 | len = strlen(card->dmi_longname); | ||
2021 | snprintf(card->dmi_longname + len, | ||
2022 | longname_buf_size - len, | ||
2023 | "-%s", board); | ||
2024 | |||
2025 | len++; | ||
2026 | if (len < longname_buf_size) | ||
2027 | cleanup_dmi_name(card->dmi_longname + len); | ||
2028 | } else if (!product) { | ||
2029 | /* fall back to using legacy name */ | ||
2030 | dev_warn(card->dev, "ASoC: no DMI board/product name!\n"); | ||
2031 | return 0; | ||
2032 | } | ||
2033 | |||
2034 | /* Add flavour to dmi long name */ | ||
2035 | if (flavour) { | ||
2036 | len = strlen(card->dmi_longname); | ||
2037 | snprintf(card->dmi_longname + len, | ||
2038 | longname_buf_size - len, | ||
2039 | "-%s", flavour); | ||
2040 | |||
2041 | len++; | ||
2042 | if (len < longname_buf_size) | ||
2043 | cleanup_dmi_name(card->dmi_longname + len); | ||
2044 | } | ||
2045 | |||
2046 | /* set the card long name */ | ||
2047 | card->long_name = card->dmi_longname; | ||
2048 | |||
2049 | return 0; | ||
2050 | } | ||
2051 | EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name); | ||
2052 | |||
1891 | static int snd_soc_instantiate_card(struct snd_soc_card *card) | 2053 | static int snd_soc_instantiate_card(struct snd_soc_card *card) |
1892 | { | 2054 | { |
1893 | struct snd_soc_codec *codec; | 2055 | struct snd_soc_codec *codec; |
@@ -2976,6 +3138,8 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, | |||
2976 | component->remove = component->driver->remove; | 3138 | component->remove = component->driver->remove; |
2977 | component->suspend = component->driver->suspend; | 3139 | component->suspend = component->driver->suspend; |
2978 | component->resume = component->driver->resume; | 3140 | component->resume = component->driver->resume; |
3141 | component->pcm_new = component->driver->pcm_new; | ||
3142 | component->pcm_free= component->driver->pcm_free; | ||
2979 | 3143 | ||
2980 | dapm = &component->dapm; | 3144 | dapm = &component->dapm; |
2981 | dapm->dev = dev; | 3145 | dapm->dev = dev; |
@@ -3158,6 +3322,21 @@ static void snd_soc_platform_drv_remove(struct snd_soc_component *component) | |||
3158 | platform->driver->remove(platform); | 3322 | platform->driver->remove(platform); |
3159 | } | 3323 | } |
3160 | 3324 | ||
3325 | static int snd_soc_platform_drv_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
3326 | { | ||
3327 | struct snd_soc_platform *platform = rtd->platform; | ||
3328 | |||
3329 | return platform->driver->pcm_new(rtd); | ||
3330 | } | ||
3331 | |||
3332 | static void snd_soc_platform_drv_pcm_free(struct snd_pcm *pcm) | ||
3333 | { | ||
3334 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | ||
3335 | struct snd_soc_platform *platform = rtd->platform; | ||
3336 | |||
3337 | platform->driver->pcm_free(pcm); | ||
3338 | } | ||
3339 | |||
3161 | /** | 3340 | /** |
3162 | * snd_soc_add_platform - Add a platform to the ASoC core | 3341 | * snd_soc_add_platform - Add a platform to the ASoC core |
3163 | * @dev: The parent device for the platform | 3342 | * @dev: The parent device for the platform |
@@ -3181,6 +3360,10 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, | |||
3181 | platform->component.probe = snd_soc_platform_drv_probe; | 3360 | platform->component.probe = snd_soc_platform_drv_probe; |
3182 | if (platform_drv->remove) | 3361 | if (platform_drv->remove) |
3183 | platform->component.remove = snd_soc_platform_drv_remove; | 3362 | platform->component.remove = snd_soc_platform_drv_remove; |
3363 | if (platform_drv->pcm_new) | ||
3364 | platform->component.pcm_new = snd_soc_platform_drv_pcm_new; | ||
3365 | if (platform_drv->pcm_free) | ||
3366 | platform->component.pcm_free = snd_soc_platform_drv_pcm_free; | ||
3184 | 3367 | ||
3185 | #ifdef CONFIG_DEBUG_FS | 3368 | #ifdef CONFIG_DEBUG_FS |
3186 | platform->component.debugfs_prefix = "platform"; | 3369 | platform->component.debugfs_prefix = "platform"; |
@@ -3492,10 +3675,10 @@ found: | |||
3492 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | 3675 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); |
3493 | 3676 | ||
3494 | /* Retrieve a card's name from device tree */ | 3677 | /* Retrieve a card's name from device tree */ |
3495 | int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card, | 3678 | int snd_soc_of_parse_card_name(struct snd_soc_card *card, |
3496 | struct device_node *np, | 3679 | const char *propname) |
3497 | const char *propname) | ||
3498 | { | 3680 | { |
3681 | struct device_node *np; | ||
3499 | int ret; | 3682 | int ret; |
3500 | 3683 | ||
3501 | if (!card->dev) { | 3684 | if (!card->dev) { |
@@ -3503,8 +3686,7 @@ int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card, | |||
3503 | return -EINVAL; | 3686 | return -EINVAL; |
3504 | } | 3687 | } |
3505 | 3688 | ||
3506 | if (!np) | 3689 | np = card->dev->of_node; |
3507 | np = card->dev->of_node; | ||
3508 | 3690 | ||
3509 | ret = of_property_read_string_index(np, propname, 0, &card->name); | 3691 | ret = of_property_read_string_index(np, propname, 0, &card->name); |
3510 | /* | 3692 | /* |
@@ -3521,7 +3703,7 @@ int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card, | |||
3521 | 3703 | ||
3522 | return 0; | 3704 | return 0; |
3523 | } | 3705 | } |
3524 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name_from_node); | 3706 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); |
3525 | 3707 | ||
3526 | static const struct snd_soc_dapm_widget simple_widgets[] = { | 3708 | static const struct snd_soc_dapm_widget simple_widgets[] = { |
3527 | SND_SOC_DAPM_MIC("Microphone", NULL), | 3709 | SND_SOC_DAPM_MIC("Microphone", NULL), |
@@ -3530,17 +3712,14 @@ static const struct snd_soc_dapm_widget simple_widgets[] = { | |||
3530 | SND_SOC_DAPM_SPK("Speaker", NULL), | 3712 | SND_SOC_DAPM_SPK("Speaker", NULL), |
3531 | }; | 3713 | }; |
3532 | 3714 | ||
3533 | int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card, | 3715 | int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, |
3534 | struct device_node *np, | ||
3535 | const char *propname) | 3716 | const char *propname) |
3536 | { | 3717 | { |
3718 | struct device_node *np = card->dev->of_node; | ||
3537 | struct snd_soc_dapm_widget *widgets; | 3719 | struct snd_soc_dapm_widget *widgets; |
3538 | const char *template, *wname; | 3720 | const char *template, *wname; |
3539 | int i, j, num_widgets, ret; | 3721 | int i, j, num_widgets, ret; |
3540 | 3722 | ||
3541 | if (!np) | ||
3542 | np = card->dev->of_node; | ||
3543 | |||
3544 | num_widgets = of_property_count_strings(np, propname); | 3723 | num_widgets = of_property_count_strings(np, propname); |
3545 | if (num_widgets < 0) { | 3724 | if (num_widgets < 0) { |
3546 | dev_err(card->dev, | 3725 | dev_err(card->dev, |
@@ -3611,7 +3790,7 @@ int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card, | |||
3611 | 3790 | ||
3612 | return 0; | 3791 | return 0; |
3613 | } | 3792 | } |
3614 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets_from_node); | 3793 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); |
3615 | 3794 | ||
3616 | static int snd_soc_of_get_slot_mask(struct device_node *np, | 3795 | static int snd_soc_of_get_slot_mask(struct device_node *np, |
3617 | const char *prop_name, | 3796 | const char *prop_name, |
@@ -3667,18 +3846,15 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np, | |||
3667 | } | 3846 | } |
3668 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); | 3847 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); |
3669 | 3848 | ||
3670 | void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card, | 3849 | void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, |
3671 | struct device_node *np, | ||
3672 | struct snd_soc_codec_conf *codec_conf, | 3850 | struct snd_soc_codec_conf *codec_conf, |
3673 | struct device_node *of_node, | 3851 | struct device_node *of_node, |
3674 | const char *propname) | 3852 | const char *propname) |
3675 | { | 3853 | { |
3854 | struct device_node *np = card->dev->of_node; | ||
3676 | const char *str; | 3855 | const char *str; |
3677 | int ret; | 3856 | int ret; |
3678 | 3857 | ||
3679 | if (!np) | ||
3680 | np = card->dev->of_node; | ||
3681 | |||
3682 | ret = of_property_read_string(np, propname, &str); | 3858 | ret = of_property_read_string(np, propname, &str); |
3683 | if (ret < 0) { | 3859 | if (ret < 0) { |
3684 | /* no prefix is not error */ | 3860 | /* no prefix is not error */ |
@@ -3688,19 +3864,16 @@ void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card, | |||
3688 | codec_conf->of_node = of_node; | 3864 | codec_conf->of_node = of_node; |
3689 | codec_conf->name_prefix = str; | 3865 | codec_conf->name_prefix = str; |
3690 | } | 3866 | } |
3691 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix_from_node); | 3867 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix); |
3692 | 3868 | ||
3693 | int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card, | 3869 | int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, |
3694 | struct device_node *np, | ||
3695 | const char *propname) | 3870 | const char *propname) |
3696 | { | 3871 | { |
3872 | struct device_node *np = card->dev->of_node; | ||
3697 | int num_routes; | 3873 | int num_routes; |
3698 | struct snd_soc_dapm_route *routes; | 3874 | struct snd_soc_dapm_route *routes; |
3699 | int i, ret; | 3875 | int i, ret; |
3700 | 3876 | ||
3701 | if (!np) | ||
3702 | np = card->dev->of_node; | ||
3703 | |||
3704 | num_routes = of_property_count_strings(np, propname); | 3877 | num_routes = of_property_count_strings(np, propname); |
3705 | if (num_routes < 0 || num_routes & 1) { | 3878 | if (num_routes < 0 || num_routes & 1) { |
3706 | dev_err(card->dev, | 3879 | dev_err(card->dev, |
@@ -3747,7 +3920,7 @@ int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card, | |||
3747 | 3920 | ||
3748 | return 0; | 3921 | return 0; |
3749 | } | 3922 | } |
3750 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing_from_node); | 3923 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing); |
3751 | 3924 | ||
3752 | unsigned int snd_soc_of_parse_daifmt(struct device_node *np, | 3925 | unsigned int snd_soc_of_parse_daifmt(struct device_node *np, |
3753 | const char *prefix, | 3926 | const char *prefix, |
@@ -4020,8 +4193,6 @@ static void __exit snd_soc_exit(void) | |||
4020 | snd_soc_util_exit(); | 4193 | snd_soc_util_exit(); |
4021 | snd_soc_debugfs_exit(); | 4194 | snd_soc_debugfs_exit(); |
4022 | 4195 | ||
4023 | #ifdef CONFIG_DEBUG_FS | ||
4024 | #endif | ||
4025 | platform_driver_unregister(&soc_driver); | 4196 | platform_driver_unregister(&soc_driver); |
4026 | } | 4197 | } |
4027 | module_exit(snd_soc_exit); | 4198 | module_exit(snd_soc_exit); |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 27dd02e57b31..dcef67a9bd48 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -363,6 +363,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, | |||
363 | snd_soc_dapm_new_control_unlocked(widget->dapm, | 363 | snd_soc_dapm_new_control_unlocked(widget->dapm, |
364 | &template); | 364 | &template); |
365 | kfree(name); | 365 | kfree(name); |
366 | if (IS_ERR(data->widget)) { | ||
367 | ret = PTR_ERR(data->widget); | ||
368 | goto err_data; | ||
369 | } | ||
366 | if (!data->widget) { | 370 | if (!data->widget) { |
367 | ret = -ENOMEM; | 371 | ret = -ENOMEM; |
368 | goto err_data; | 372 | goto err_data; |
@@ -397,6 +401,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, | |||
397 | data->widget = snd_soc_dapm_new_control_unlocked( | 401 | data->widget = snd_soc_dapm_new_control_unlocked( |
398 | widget->dapm, &template); | 402 | widget->dapm, &template); |
399 | kfree(name); | 403 | kfree(name); |
404 | if (IS_ERR(data->widget)) { | ||
405 | ret = PTR_ERR(data->widget); | ||
406 | goto err_data; | ||
407 | } | ||
400 | if (!data->widget) { | 408 | if (!data->widget) { |
401 | ret = -ENOMEM; | 409 | ret = -ENOMEM; |
402 | goto err_data; | 410 | goto err_data; |
@@ -3403,11 +3411,22 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3403 | 3411 | ||
3404 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 3412 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
3405 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); | 3413 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); |
3414 | /* Do not nag about probe deferrals */ | ||
3415 | if (IS_ERR(w)) { | ||
3416 | int ret = PTR_ERR(w); | ||
3417 | |||
3418 | if (ret != -EPROBE_DEFER) | ||
3419 | dev_err(dapm->dev, | ||
3420 | "ASoC: Failed to create DAPM control %s (%d)\n", | ||
3421 | widget->name, ret); | ||
3422 | goto out_unlock; | ||
3423 | } | ||
3406 | if (!w) | 3424 | if (!w) |
3407 | dev_err(dapm->dev, | 3425 | dev_err(dapm->dev, |
3408 | "ASoC: Failed to create DAPM control %s\n", | 3426 | "ASoC: Failed to create DAPM control %s\n", |
3409 | widget->name); | 3427 | widget->name); |
3410 | 3428 | ||
3429 | out_unlock: | ||
3411 | mutex_unlock(&dapm->card->dapm_mutex); | 3430 | mutex_unlock(&dapm->card->dapm_mutex); |
3412 | return w; | 3431 | return w; |
3413 | } | 3432 | } |
@@ -3430,6 +3449,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | |||
3430 | w->regulator = devm_regulator_get(dapm->dev, w->name); | 3449 | w->regulator = devm_regulator_get(dapm->dev, w->name); |
3431 | if (IS_ERR(w->regulator)) { | 3450 | if (IS_ERR(w->regulator)) { |
3432 | ret = PTR_ERR(w->regulator); | 3451 | ret = PTR_ERR(w->regulator); |
3452 | if (ret == -EPROBE_DEFER) | ||
3453 | return ERR_PTR(ret); | ||
3433 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", | 3454 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", |
3434 | w->name, ret); | 3455 | w->name, ret); |
3435 | return NULL; | 3456 | return NULL; |
@@ -3448,6 +3469,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | |||
3448 | w->clk = devm_clk_get(dapm->dev, w->name); | 3469 | w->clk = devm_clk_get(dapm->dev, w->name); |
3449 | if (IS_ERR(w->clk)) { | 3470 | if (IS_ERR(w->clk)) { |
3450 | ret = PTR_ERR(w->clk); | 3471 | ret = PTR_ERR(w->clk); |
3472 | if (ret == -EPROBE_DEFER) | ||
3473 | return ERR_PTR(ret); | ||
3451 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", | 3474 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", |
3452 | w->name, ret); | 3475 | w->name, ret); |
3453 | return NULL; | 3476 | return NULL; |
@@ -3566,6 +3589,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, | |||
3566 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); | 3589 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); |
3567 | for (i = 0; i < num; i++) { | 3590 | for (i = 0; i < num; i++) { |
3568 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); | 3591 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); |
3592 | if (IS_ERR(w)) { | ||
3593 | ret = PTR_ERR(w); | ||
3594 | /* Do not nag about probe deferrals */ | ||
3595 | if (ret == -EPROBE_DEFER) | ||
3596 | break; | ||
3597 | dev_err(dapm->dev, | ||
3598 | "ASoC: Failed to create DAPM control %s (%d)\n", | ||
3599 | widget->name, ret); | ||
3600 | break; | ||
3601 | } | ||
3569 | if (!w) { | 3602 | if (!w) { |
3570 | dev_err(dapm->dev, | 3603 | dev_err(dapm->dev, |
3571 | "ASoC: Failed to create DAPM control %s\n", | 3604 | "ASoC: Failed to create DAPM control %s\n", |
@@ -3842,6 +3875,15 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, | |||
3842 | dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name); | 3875 | dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name); |
3843 | 3876 | ||
3844 | w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template); | 3877 | w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template); |
3878 | if (IS_ERR(w)) { | ||
3879 | ret = PTR_ERR(w); | ||
3880 | /* Do not nag about probe deferrals */ | ||
3881 | if (ret != -EPROBE_DEFER) | ||
3882 | dev_err(card->dev, | ||
3883 | "ASoC: Failed to create %s widget (%d)\n", | ||
3884 | link_name, ret); | ||
3885 | goto outfree_kcontrol_news; | ||
3886 | } | ||
3845 | if (!w) { | 3887 | if (!w) { |
3846 | dev_err(card->dev, "ASoC: Failed to create %s widget\n", | 3888 | dev_err(card->dev, "ASoC: Failed to create %s widget\n", |
3847 | link_name); | 3889 | link_name); |
@@ -3893,6 +3935,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, | |||
3893 | template.name); | 3935 | template.name); |
3894 | 3936 | ||
3895 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); | 3937 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); |
3938 | if (IS_ERR(w)) { | ||
3939 | int ret = PTR_ERR(w); | ||
3940 | |||
3941 | /* Do not nag about probe deferrals */ | ||
3942 | if (ret != -EPROBE_DEFER) | ||
3943 | dev_err(dapm->dev, | ||
3944 | "ASoC: Failed to create %s widget (%d)\n", | ||
3945 | dai->driver->playback.stream_name, ret); | ||
3946 | return ret; | ||
3947 | } | ||
3896 | if (!w) { | 3948 | if (!w) { |
3897 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", | 3949 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", |
3898 | dai->driver->playback.stream_name); | 3950 | dai->driver->playback.stream_name); |
@@ -3912,6 +3964,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, | |||
3912 | template.name); | 3964 | template.name); |
3913 | 3965 | ||
3914 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); | 3966 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); |
3967 | if (IS_ERR(w)) { | ||
3968 | int ret = PTR_ERR(w); | ||
3969 | |||
3970 | /* Do not nag about probe deferrals */ | ||
3971 | if (ret != -EPROBE_DEFER) | ||
3972 | dev_err(dapm->dev, | ||
3973 | "ASoC: Failed to create %s widget (%d)\n", | ||
3974 | dai->driver->playback.stream_name, ret); | ||
3975 | return ret; | ||
3976 | } | ||
3915 | if (!w) { | 3977 | if (!w) { |
3916 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", | 3978 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", |
3917 | dai->driver->capture.stream_name); | 3979 | dai->driver->capture.stream_name); |
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 17eb14935577..d53786498b61 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -263,6 +263,7 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
263 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); | 263 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); |
264 | const struct snd_dmaengine_pcm_config *config = pcm->config; | 264 | const struct snd_dmaengine_pcm_config *config = pcm->config; |
265 | struct device *dev = rtd->platform->dev; | 265 | struct device *dev = rtd->platform->dev; |
266 | struct snd_dmaengine_dai_dma_data *dma_data; | ||
266 | struct snd_pcm_substream *substream; | 267 | struct snd_pcm_substream *substream; |
267 | size_t prealloc_buffer_size; | 268 | size_t prealloc_buffer_size; |
268 | size_t max_buffer_size; | 269 | size_t max_buffer_size; |
@@ -282,6 +283,13 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
282 | if (!substream) | 283 | if (!substream) |
283 | continue; | 284 | continue; |
284 | 285 | ||
286 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
287 | |||
288 | if (!pcm->chan[i] && | ||
289 | (pcm->flags & SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) | ||
290 | pcm->chan[i] = dma_request_slave_channel(dev, | ||
291 | dma_data->chan_name); | ||
292 | |||
285 | if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) { | 293 | if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) { |
286 | pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd, | 294 | pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd, |
287 | substream); | 295 | substream); |
@@ -350,7 +358,9 @@ static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, | |||
350 | const char *name; | 358 | const char *name; |
351 | struct dma_chan *chan; | 359 | struct dma_chan *chan; |
352 | 360 | ||
353 | if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_DT) || !dev->of_node) | 361 | if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | |
362 | SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || | ||
363 | !dev->of_node) | ||
354 | return 0; | 364 | return 0; |
355 | 365 | ||
356 | if (config && config->dma_dev) { | 366 | if (config && config->dma_dev) { |
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 9fc1a7bb8b95..500f98c730b9 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c | |||
@@ -120,7 +120,7 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | |||
120 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); | 120 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); |
121 | 121 | ||
122 | /** | 122 | /** |
123 | * snd_soc_read_signed - Read a codec register and interprete as signed value | 123 | * snd_soc_read_signed - Read a codec register and interpret as signed value |
124 | * @component: component | 124 | * @component: component |
125 | * @reg: Register to read | 125 | * @reg: Register to read |
126 | * @mask: Mask to use after shifting the register value | 126 | * @mask: Mask to use after shifting the register value |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 6aba14009c92..efc5831f205d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -1055,7 +1055,6 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, | |||
1055 | int cmd) | 1055 | int cmd) |
1056 | { | 1056 | { |
1057 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1057 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1058 | struct snd_soc_platform *platform = rtd->platform; | ||
1059 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1058 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1060 | struct snd_soc_dai *codec_dai; | 1059 | struct snd_soc_dai *codec_dai; |
1061 | int i, ret; | 1060 | int i, ret; |
@@ -1071,12 +1070,6 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, | |||
1071 | } | 1070 | } |
1072 | } | 1071 | } |
1073 | 1072 | ||
1074 | if (platform->driver->bespoke_trigger) { | ||
1075 | ret = platform->driver->bespoke_trigger(substream, cmd); | ||
1076 | if (ret < 0) | ||
1077 | return ret; | ||
1078 | } | ||
1079 | |||
1080 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->bespoke_trigger) { | 1073 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->bespoke_trigger) { |
1081 | ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai); | 1074 | ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai); |
1082 | if (ret < 0) | 1075 | if (ret < 0) |
@@ -1116,13 +1109,6 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | |||
1116 | } | 1109 | } |
1117 | delay += codec_delay; | 1110 | delay += codec_delay; |
1118 | 1111 | ||
1119 | /* | ||
1120 | * None of the existing platform drivers implement delay(), so | ||
1121 | * for now the codec_dai of first multicodec entry is used | ||
1122 | */ | ||
1123 | if (platform->driver->delay) | ||
1124 | delay += platform->driver->delay(substream, rtd->codec_dais[0]); | ||
1125 | |||
1126 | runtime->delay = delay; | 1112 | runtime->delay = delay; |
1127 | 1113 | ||
1128 | return offset; | 1114 | return offset; |
@@ -2642,12 +2628,25 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) | |||
2642 | return ret; | 2628 | return ret; |
2643 | } | 2629 | } |
2644 | 2630 | ||
2631 | static void soc_pcm_free(struct snd_pcm *pcm) | ||
2632 | { | ||
2633 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | ||
2634 | struct snd_soc_component *component; | ||
2635 | |||
2636 | list_for_each_entry(component, &rtd->card->component_dev_list, | ||
2637 | card_list) { | ||
2638 | if (component->pcm_free) | ||
2639 | component->pcm_free(pcm); | ||
2640 | } | ||
2641 | } | ||
2642 | |||
2645 | /* create a new pcm */ | 2643 | /* create a new pcm */ |
2646 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | 2644 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) |
2647 | { | 2645 | { |
2648 | struct snd_soc_platform *platform = rtd->platform; | 2646 | struct snd_soc_platform *platform = rtd->platform; |
2649 | struct snd_soc_dai *codec_dai; | 2647 | struct snd_soc_dai *codec_dai; |
2650 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 2648 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
2649 | struct snd_soc_component *component; | ||
2651 | struct snd_pcm *pcm; | 2650 | struct snd_pcm *pcm; |
2652 | char new_name[64]; | 2651 | char new_name[64]; |
2653 | int ret = 0, playback = 0, capture = 0; | 2652 | int ret = 0, playback = 0, capture = 0; |
@@ -2756,17 +2755,18 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2756 | if (capture) | 2755 | if (capture) |
2757 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops); | 2756 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops); |
2758 | 2757 | ||
2759 | if (platform->driver->pcm_new) { | 2758 | list_for_each_entry(component, &rtd->card->component_dev_list, card_list) { |
2760 | ret = platform->driver->pcm_new(rtd); | 2759 | if (component->pcm_new) { |
2761 | if (ret < 0) { | 2760 | ret = component->pcm_new(rtd); |
2762 | dev_err(platform->dev, | 2761 | if (ret < 0) { |
2763 | "ASoC: pcm constructor failed: %d\n", | 2762 | dev_err(component->dev, |
2764 | ret); | 2763 | "ASoC: pcm constructor failed: %d\n", |
2765 | return ret; | 2764 | ret); |
2765 | return ret; | ||
2766 | } | ||
2766 | } | 2767 | } |
2767 | } | 2768 | } |
2768 | 2769 | pcm->private_free = soc_pcm_free; | |
2769 | pcm->private_free = platform->driver->pcm_free; | ||
2770 | out: | 2770 | out: |
2771 | dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", | 2771 | dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", |
2772 | (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, | 2772 | (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, |
@@ -2874,15 +2874,6 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe, | |||
2874 | } | 2874 | } |
2875 | EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); | 2875 | EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); |
2876 | 2876 | ||
2877 | int snd_soc_platform_trigger(struct snd_pcm_substream *substream, | ||
2878 | int cmd, struct snd_soc_platform *platform) | ||
2879 | { | ||
2880 | if (platform->driver->ops && platform->driver->ops->trigger) | ||
2881 | return platform->driver->ops->trigger(substream, cmd); | ||
2882 | return 0; | ||
2883 | } | ||
2884 | EXPORT_SYMBOL_GPL(snd_soc_platform_trigger); | ||
2885 | |||
2886 | #ifdef CONFIG_DEBUG_FS | 2877 | #ifdef CONFIG_DEBUG_FS |
2887 | static const char *dpcm_state_string(enum snd_soc_dpcm_state state) | 2878 | static const char *dpcm_state_string(enum snd_soc_dpcm_state state) |
2888 | { | 2879 | { |
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index fbfb1fab88d5..aff3d8129ac9 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c | |||
@@ -1555,6 +1555,15 @@ widget: | |||
1555 | widget = snd_soc_dapm_new_control(dapm, &template); | 1555 | widget = snd_soc_dapm_new_control(dapm, &template); |
1556 | else | 1556 | else |
1557 | widget = snd_soc_dapm_new_control_unlocked(dapm, &template); | 1557 | widget = snd_soc_dapm_new_control_unlocked(dapm, &template); |
1558 | if (IS_ERR(widget)) { | ||
1559 | ret = PTR_ERR(widget); | ||
1560 | /* Do not nag about probe deferrals */ | ||
1561 | if (ret != -EPROBE_DEFER) | ||
1562 | dev_err(tplg->dev, | ||
1563 | "ASoC: failed to create widget %s controls (%d)\n", | ||
1564 | w->name, ret); | ||
1565 | goto hdr_err; | ||
1566 | } | ||
1558 | if (widget == NULL) { | 1567 | if (widget == NULL) { |
1559 | dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n", | 1568 | dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n", |
1560 | w->name); | 1569 | w->name); |
@@ -1862,7 +1871,7 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, | |||
1862 | { | 1871 | { |
1863 | struct snd_soc_tplg_pcm *pcm, *_pcm; | 1872 | struct snd_soc_tplg_pcm *pcm, *_pcm; |
1864 | int count = hdr->count; | 1873 | int count = hdr->count; |
1865 | int i, err; | 1874 | int i; |
1866 | bool abi_match; | 1875 | bool abi_match; |
1867 | 1876 | ||
1868 | if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) | 1877 | if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) |
@@ -1896,7 +1905,7 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, | |||
1896 | _pcm = pcm; | 1905 | _pcm = pcm; |
1897 | } else { | 1906 | } else { |
1898 | abi_match = false; | 1907 | abi_match = false; |
1899 | err = pcm_new_ver(tplg, pcm, &_pcm); | 1908 | pcm_new_ver(tplg, pcm, &_pcm); |
1900 | } | 1909 | } |
1901 | 1910 | ||
1902 | /* create the FE DAIs and DAI links */ | 1911 | /* create the FE DAIs and DAI links */ |
@@ -1918,7 +1927,7 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, | |||
1918 | 1927 | ||
1919 | /** | 1928 | /** |
1920 | * set_link_hw_format - Set the HW audio format of the physical DAI link. | 1929 | * set_link_hw_format - Set the HW audio format of the physical DAI link. |
1921 | * @tplg: topology context | 1930 | * @link: &snd_soc_dai_link which should be updated |
1922 | * @cfg: physical link configs. | 1931 | * @cfg: physical link configs. |
1923 | * | 1932 | * |
1924 | * Topology context contains a list of supported HW formats (configs) and | 1933 | * Topology context contains a list of supported HW formats (configs) and |
@@ -1969,7 +1978,7 @@ static void set_link_hw_format(struct snd_soc_dai_link *link, | |||
1969 | /** | 1978 | /** |
1970 | * link_new_ver - Create a new physical link config from the old | 1979 | * link_new_ver - Create a new physical link config from the old |
1971 | * version of source. | 1980 | * version of source. |
1972 | * @toplogy: topology context | 1981 | * @tplg: topology context |
1973 | * @src: old version of phyical link config as a source | 1982 | * @src: old version of phyical link config as a source |
1974 | * @link: latest version of physical link config created from the source | 1983 | * @link: latest version of physical link config created from the source |
1975 | * | 1984 | * |
@@ -2211,7 +2220,7 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg, | |||
2211 | /** | 2220 | /** |
2212 | * manifest_new_ver - Create a new version of manifest from the old version | 2221 | * manifest_new_ver - Create a new version of manifest from the old version |
2213 | * of source. | 2222 | * of source. |
2214 | * @toplogy: topology context | 2223 | * @tplg: topology context |
2215 | * @src: old version of manifest as a source | 2224 | * @src: old version of manifest as a source |
2216 | * @manifest: latest version of manifest created from the source | 2225 | * @manifest: latest version of manifest created from the source |
2217 | * | 2226 | * |
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig index 6c344e16aca4..22408bc2d6ec 100644 --- a/sound/soc/sunxi/Kconfig +++ b/sound/soc/sunxi/Kconfig | |||
@@ -9,9 +9,20 @@ config SND_SUN4I_CODEC | |||
9 | Select Y or M to add support for the Codec embedded in the Allwinner | 9 | Select Y or M to add support for the Codec embedded in the Allwinner |
10 | A10 and affiliated SoCs. | 10 | A10 and affiliated SoCs. |
11 | 11 | ||
12 | config SND_SUN8I_CODEC | ||
13 | tristate "Allwinner SUN8I audio codec" | ||
14 | depends on OF | ||
15 | depends on MACH_SUN8I || COMPILE_TEST | ||
16 | select REGMAP_MMIO | ||
17 | help | ||
18 | This option enables the digital part of the internal audio codec for | ||
19 | Allwinner sun8i SoC (and particularly A33). | ||
20 | |||
21 | Say Y or M if you want to add sun8i digital audio codec support. | ||
22 | |||
12 | config SND_SUN8I_CODEC_ANALOG | 23 | config SND_SUN8I_CODEC_ANALOG |
13 | tristate "Allwinner sun8i Codec Analog Controls Support" | 24 | tristate "Allwinner sun8i Codec Analog Controls Support" |
14 | depends on MACH_SUN8I || COMPILE_TEST | 25 | depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST |
15 | select REGMAP | 26 | select REGMAP |
16 | help | 27 | help |
17 | Say Y or M if you want to add support for the analog controls for | 28 | Say Y or M if you want to add support for the analog controls for |
diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile index 241c0df9ca0c..1f1af6271731 100644 --- a/sound/soc/sunxi/Makefile +++ b/sound/soc/sunxi/Makefile | |||
@@ -2,3 +2,4 @@ obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o | |||
2 | obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o | 2 | obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o |
3 | obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o | 3 | obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o |
4 | obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o | 4 | obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o |
5 | obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o | ||
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 848af01692a0..c3aab10fa085 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c | |||
@@ -1058,6 +1058,7 @@ static const struct snd_soc_dapm_route sun6i_codec_codec_dapm_routes[] = { | |||
1058 | { "Line Out Source Playback Route", "Stereo", "Left Mixer" }, | 1058 | { "Line Out Source Playback Route", "Stereo", "Left Mixer" }, |
1059 | { "Line Out Source Playback Route", "Stereo", "Right Mixer" }, | 1059 | { "Line Out Source Playback Route", "Stereo", "Right Mixer" }, |
1060 | { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" }, | 1060 | { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" }, |
1061 | { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" }, | ||
1061 | { "LINEOUT", NULL, "Line Out Source Playback Route" }, | 1062 | { "LINEOUT", NULL, "Line Out Source Playback Route" }, |
1062 | 1063 | ||
1063 | /* ADC Routes */ | 1064 | /* ADC Routes */ |
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index f24d19526603..3635bbc72cbc 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c | |||
@@ -14,9 +14,11 @@ | |||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/dmaengine.h> | 15 | #include <linux/dmaengine.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/of_device.h> | ||
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
18 | #include <linux/pm_runtime.h> | 19 | #include <linux/pm_runtime.h> |
19 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
21 | #include <linux/reset.h> | ||
20 | 22 | ||
21 | #include <sound/dmaengine_pcm.h> | 23 | #include <sound/dmaengine_pcm.h> |
22 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -92,6 +94,7 @@ struct sun4i_i2s { | |||
92 | struct clk *bus_clk; | 94 | struct clk *bus_clk; |
93 | struct clk *mod_clk; | 95 | struct clk *mod_clk; |
94 | struct regmap *regmap; | 96 | struct regmap *regmap; |
97 | struct reset_control *rst; | ||
95 | 98 | ||
96 | unsigned int mclk_freq; | 99 | unsigned int mclk_freq; |
97 | 100 | ||
@@ -651,9 +654,22 @@ static int sun4i_i2s_runtime_suspend(struct device *dev) | |||
651 | return 0; | 654 | return 0; |
652 | } | 655 | } |
653 | 656 | ||
657 | struct sun4i_i2s_quirks { | ||
658 | bool has_reset; | ||
659 | }; | ||
660 | |||
661 | static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { | ||
662 | .has_reset = false, | ||
663 | }; | ||
664 | |||
665 | static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { | ||
666 | .has_reset = true, | ||
667 | }; | ||
668 | |||
654 | static int sun4i_i2s_probe(struct platform_device *pdev) | 669 | static int sun4i_i2s_probe(struct platform_device *pdev) |
655 | { | 670 | { |
656 | struct sun4i_i2s *i2s; | 671 | struct sun4i_i2s *i2s; |
672 | const struct sun4i_i2s_quirks *quirks; | ||
657 | struct resource *res; | 673 | struct resource *res; |
658 | void __iomem *regs; | 674 | void __iomem *regs; |
659 | int irq, ret; | 675 | int irq, ret; |
@@ -674,6 +690,12 @@ static int sun4i_i2s_probe(struct platform_device *pdev) | |||
674 | return irq; | 690 | return irq; |
675 | } | 691 | } |
676 | 692 | ||
693 | quirks = of_device_get_match_data(&pdev->dev); | ||
694 | if (!quirks) { | ||
695 | dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); | ||
696 | return -ENODEV; | ||
697 | } | ||
698 | |||
677 | i2s->bus_clk = devm_clk_get(&pdev->dev, "apb"); | 699 | i2s->bus_clk = devm_clk_get(&pdev->dev, "apb"); |
678 | if (IS_ERR(i2s->bus_clk)) { | 700 | if (IS_ERR(i2s->bus_clk)) { |
679 | dev_err(&pdev->dev, "Can't get our bus clock\n"); | 701 | dev_err(&pdev->dev, "Can't get our bus clock\n"); |
@@ -692,12 +714,29 @@ static int sun4i_i2s_probe(struct platform_device *pdev) | |||
692 | dev_err(&pdev->dev, "Can't get our mod clock\n"); | 714 | dev_err(&pdev->dev, "Can't get our mod clock\n"); |
693 | return PTR_ERR(i2s->mod_clk); | 715 | return PTR_ERR(i2s->mod_clk); |
694 | } | 716 | } |
695 | 717 | ||
718 | if (quirks->has_reset) { | ||
719 | i2s->rst = devm_reset_control_get(&pdev->dev, NULL); | ||
720 | if (IS_ERR(i2s->rst)) { | ||
721 | dev_err(&pdev->dev, "Failed to get reset control\n"); | ||
722 | return PTR_ERR(i2s->rst); | ||
723 | } | ||
724 | } | ||
725 | |||
726 | if (!IS_ERR(i2s->rst)) { | ||
727 | ret = reset_control_deassert(i2s->rst); | ||
728 | if (ret) { | ||
729 | dev_err(&pdev->dev, | ||
730 | "Failed to deassert the reset control\n"); | ||
731 | return -EINVAL; | ||
732 | } | ||
733 | } | ||
734 | |||
696 | i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG; | 735 | i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG; |
697 | i2s->playback_dma_data.maxburst = 4; | 736 | i2s->playback_dma_data.maxburst = 8; |
698 | 737 | ||
699 | i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG; | 738 | i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG; |
700 | i2s->capture_dma_data.maxburst = 4; | 739 | i2s->capture_dma_data.maxburst = 8; |
701 | 740 | ||
702 | pm_runtime_enable(&pdev->dev); | 741 | pm_runtime_enable(&pdev->dev); |
703 | if (!pm_runtime_enabled(&pdev->dev)) { | 742 | if (!pm_runtime_enabled(&pdev->dev)) { |
@@ -727,23 +766,37 @@ err_suspend: | |||
727 | sun4i_i2s_runtime_suspend(&pdev->dev); | 766 | sun4i_i2s_runtime_suspend(&pdev->dev); |
728 | err_pm_disable: | 767 | err_pm_disable: |
729 | pm_runtime_disable(&pdev->dev); | 768 | pm_runtime_disable(&pdev->dev); |
769 | if (!IS_ERR(i2s->rst)) | ||
770 | reset_control_assert(i2s->rst); | ||
730 | 771 | ||
731 | return ret; | 772 | return ret; |
732 | } | 773 | } |
733 | 774 | ||
734 | static int sun4i_i2s_remove(struct platform_device *pdev) | 775 | static int sun4i_i2s_remove(struct platform_device *pdev) |
735 | { | 776 | { |
777 | struct sun4i_i2s *i2s = dev_get_drvdata(&pdev->dev); | ||
778 | |||
736 | snd_dmaengine_pcm_unregister(&pdev->dev); | 779 | snd_dmaengine_pcm_unregister(&pdev->dev); |
737 | 780 | ||
738 | pm_runtime_disable(&pdev->dev); | 781 | pm_runtime_disable(&pdev->dev); |
739 | if (!pm_runtime_status_suspended(&pdev->dev)) | 782 | if (!pm_runtime_status_suspended(&pdev->dev)) |
740 | sun4i_i2s_runtime_suspend(&pdev->dev); | 783 | sun4i_i2s_runtime_suspend(&pdev->dev); |
741 | 784 | ||
785 | if (!IS_ERR(i2s->rst)) | ||
786 | reset_control_assert(i2s->rst); | ||
787 | |||
742 | return 0; | 788 | return 0; |
743 | } | 789 | } |
744 | 790 | ||
745 | static const struct of_device_id sun4i_i2s_match[] = { | 791 | static const struct of_device_id sun4i_i2s_match[] = { |
746 | { .compatible = "allwinner,sun4i-a10-i2s", }, | 792 | { |
793 | .compatible = "allwinner,sun4i-a10-i2s", | ||
794 | .data = &sun4i_a10_i2s_quirks, | ||
795 | }, | ||
796 | { | ||
797 | .compatible = "allwinner,sun6i-a31-i2s", | ||
798 | .data = &sun6i_a31_i2s_quirks, | ||
799 | }, | ||
747 | {} | 800 | {} |
748 | }; | 801 | }; |
749 | MODULE_DEVICE_TABLE(of, sun4i_i2s_match); | 802 | MODULE_DEVICE_TABLE(of, sun4i_i2s_match); |
diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index 88fbb3a1e660..eaefd07a5ed0 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c | |||
@@ -103,6 +103,8 @@ | |||
103 | #define SUN4I_SPDIF_ISTA_RXOSTA BIT(1) | 103 | #define SUN4I_SPDIF_ISTA_RXOSTA BIT(1) |
104 | #define SUN4I_SPDIF_ISTA_RXASTA BIT(0) | 104 | #define SUN4I_SPDIF_ISTA_RXASTA BIT(0) |
105 | 105 | ||
106 | #define SUN8I_SPDIF_TXFIFO (0x20) | ||
107 | |||
106 | #define SUN4I_SPDIF_TXCNT (0x24) | 108 | #define SUN4I_SPDIF_TXCNT (0x24) |
107 | 109 | ||
108 | #define SUN4I_SPDIF_RXCNT (0x28) | 110 | #define SUN4I_SPDIF_RXCNT (0x28) |
@@ -403,17 +405,38 @@ static struct snd_soc_dai_driver sun4i_spdif_dai = { | |||
403 | .name = "spdif", | 405 | .name = "spdif", |
404 | }; | 406 | }; |
405 | 407 | ||
406 | static const struct snd_soc_dapm_widget dit_widgets[] = { | 408 | struct sun4i_spdif_quirks { |
407 | SND_SOC_DAPM_OUTPUT("spdif-out"), | 409 | unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */ |
410 | bool has_reset; | ||
411 | }; | ||
412 | |||
413 | static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = { | ||
414 | .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, | ||
408 | }; | 415 | }; |
409 | 416 | ||
410 | static const struct snd_soc_dapm_route dit_routes[] = { | 417 | static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = { |
411 | { "spdif-out", NULL, "Playback" }, | 418 | .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, |
419 | .has_reset = true, | ||
420 | }; | ||
421 | |||
422 | static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = { | ||
423 | .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, | ||
424 | .has_reset = true, | ||
412 | }; | 425 | }; |
413 | 426 | ||
414 | static const struct of_device_id sun4i_spdif_of_match[] = { | 427 | static const struct of_device_id sun4i_spdif_of_match[] = { |
415 | { .compatible = "allwinner,sun4i-a10-spdif", }, | 428 | { |
416 | { .compatible = "allwinner,sun6i-a31-spdif", }, | 429 | .compatible = "allwinner,sun4i-a10-spdif", |
430 | .data = &sun4i_a10_spdif_quirks, | ||
431 | }, | ||
432 | { | ||
433 | .compatible = "allwinner,sun6i-a31-spdif", | ||
434 | .data = &sun6i_a31_spdif_quirks, | ||
435 | }, | ||
436 | { | ||
437 | .compatible = "allwinner,sun8i-h3-spdif", | ||
438 | .data = &sun8i_h3_spdif_quirks, | ||
439 | }, | ||
417 | { /* sentinel */ } | 440 | { /* sentinel */ } |
418 | }; | 441 | }; |
419 | MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match); | 442 | MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match); |
@@ -446,6 +469,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev) | |||
446 | { | 469 | { |
447 | struct sun4i_spdif_dev *host; | 470 | struct sun4i_spdif_dev *host; |
448 | struct resource *res; | 471 | struct resource *res; |
472 | const struct sun4i_spdif_quirks *quirks; | ||
449 | int ret; | 473 | int ret; |
450 | void __iomem *base; | 474 | void __iomem *base; |
451 | 475 | ||
@@ -467,6 +491,12 @@ static int sun4i_spdif_probe(struct platform_device *pdev) | |||
467 | if (IS_ERR(base)) | 491 | if (IS_ERR(base)) |
468 | return PTR_ERR(base); | 492 | return PTR_ERR(base); |
469 | 493 | ||
494 | quirks = of_device_get_match_data(&pdev->dev); | ||
495 | if (quirks == NULL) { | ||
496 | dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); | ||
497 | return -ENODEV; | ||
498 | } | ||
499 | |||
470 | host->regmap = devm_regmap_init_mmio(&pdev->dev, base, | 500 | host->regmap = devm_regmap_init_mmio(&pdev->dev, base, |
471 | &sun4i_spdif_regmap_config); | 501 | &sun4i_spdif_regmap_config); |
472 | 502 | ||
@@ -480,23 +510,21 @@ static int sun4i_spdif_probe(struct platform_device *pdev) | |||
480 | host->spdif_clk = devm_clk_get(&pdev->dev, "spdif"); | 510 | host->spdif_clk = devm_clk_get(&pdev->dev, "spdif"); |
481 | if (IS_ERR(host->spdif_clk)) { | 511 | if (IS_ERR(host->spdif_clk)) { |
482 | dev_err(&pdev->dev, "failed to get a spdif clock.\n"); | 512 | dev_err(&pdev->dev, "failed to get a spdif clock.\n"); |
483 | ret = PTR_ERR(host->spdif_clk); | 513 | return PTR_ERR(host->spdif_clk); |
484 | goto err_disable_apb_clk; | ||
485 | } | 514 | } |
486 | 515 | ||
487 | host->dma_params_tx.addr = res->start + SUN4I_SPDIF_TXFIFO; | 516 | host->dma_params_tx.addr = res->start + quirks->reg_dac_txdata; |
488 | host->dma_params_tx.maxburst = 8; | 517 | host->dma_params_tx.maxburst = 8; |
489 | host->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | 518 | host->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; |
490 | 519 | ||
491 | platform_set_drvdata(pdev, host); | 520 | platform_set_drvdata(pdev, host); |
492 | 521 | ||
493 | if (of_device_is_compatible(pdev->dev.of_node, | 522 | if (quirks->has_reset) { |
494 | "allwinner,sun6i-a31-spdif")) { | ||
495 | host->rst = devm_reset_control_get_optional(&pdev->dev, NULL); | 523 | host->rst = devm_reset_control_get_optional(&pdev->dev, NULL); |
496 | if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) { | 524 | if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) { |
497 | ret = -EPROBE_DEFER; | 525 | ret = -EPROBE_DEFER; |
498 | dev_err(&pdev->dev, "Failed to get reset: %d\n", ret); | 526 | dev_err(&pdev->dev, "Failed to get reset: %d\n", ret); |
499 | goto err_disable_apb_clk; | 527 | return ret; |
500 | } | 528 | } |
501 | if (!IS_ERR(host->rst)) | 529 | if (!IS_ERR(host->rst)) |
502 | reset_control_deassert(host->rst); | 530 | reset_control_deassert(host->rst); |
@@ -505,7 +533,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev) | |||
505 | ret = devm_snd_soc_register_component(&pdev->dev, | 533 | ret = devm_snd_soc_register_component(&pdev->dev, |
506 | &sun4i_spdif_component, &sun4i_spdif_dai, 1); | 534 | &sun4i_spdif_component, &sun4i_spdif_dai, 1); |
507 | if (ret) | 535 | if (ret) |
508 | goto err_disable_apb_clk; | 536 | return ret; |
509 | 537 | ||
510 | pm_runtime_enable(&pdev->dev); | 538 | pm_runtime_enable(&pdev->dev); |
511 | if (!pm_runtime_enabled(&pdev->dev)) { | 539 | if (!pm_runtime_enabled(&pdev->dev)) { |
@@ -523,9 +551,6 @@ err_suspend: | |||
523 | sun4i_spdif_runtime_suspend(&pdev->dev); | 551 | sun4i_spdif_runtime_suspend(&pdev->dev); |
524 | err_unregister: | 552 | err_unregister: |
525 | pm_runtime_disable(&pdev->dev); | 553 | pm_runtime_disable(&pdev->dev); |
526 | snd_soc_unregister_component(&pdev->dev); | ||
527 | err_disable_apb_clk: | ||
528 | clk_disable_unprepare(host->apb_clk); | ||
529 | return ret; | 554 | return ret; |
530 | } | 555 | } |
531 | 556 | ||
@@ -535,9 +560,6 @@ static int sun4i_spdif_remove(struct platform_device *pdev) | |||
535 | if (!pm_runtime_status_suspended(&pdev->dev)) | 560 | if (!pm_runtime_status_suspended(&pdev->dev)) |
536 | sun4i_spdif_runtime_suspend(&pdev->dev); | 561 | sun4i_spdif_runtime_suspend(&pdev->dev); |
537 | 562 | ||
538 | snd_soc_unregister_platform(&pdev->dev); | ||
539 | snd_soc_unregister_component(&pdev->dev); | ||
540 | |||
541 | return 0; | 563 | return 0; |
542 | } | 564 | } |
543 | 565 | ||
diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c index af02290ebe49..72331332b72e 100644 --- a/sound/soc/sunxi/sun8i-codec-analog.c +++ b/sound/soc/sunxi/sun8i-codec-analog.c | |||
@@ -398,11 +398,37 @@ static const struct snd_kcontrol_new sun8i_codec_hp_src[] = { | |||
398 | sun8i_codec_hp_src_enum), | 398 | sun8i_codec_hp_src_enum), |
399 | }; | 399 | }; |
400 | 400 | ||
401 | static int sun8i_headphone_amp_event(struct snd_soc_dapm_widget *w, | ||
402 | struct snd_kcontrol *k, int event) | ||
403 | { | ||
404 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | ||
405 | |||
406 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
407 | snd_soc_component_update_bits(component, SUN8I_ADDA_PAEN_HP_CTRL, | ||
408 | BIT(SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN), | ||
409 | BIT(SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN)); | ||
410 | /* | ||
411 | * Need a delay to have the amplifier up. 700ms seems the best | ||
412 | * compromise between the time to let the amplifier up and the | ||
413 | * time not to feel this delay while playing a sound. | ||
414 | */ | ||
415 | msleep(700); | ||
416 | } else if (SND_SOC_DAPM_EVENT_OFF(event)) { | ||
417 | snd_soc_component_update_bits(component, SUN8I_ADDA_PAEN_HP_CTRL, | ||
418 | BIT(SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN), | ||
419 | 0x0); | ||
420 | } | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
401 | static const struct snd_soc_dapm_widget sun8i_codec_headphone_widgets[] = { | 425 | static const struct snd_soc_dapm_widget sun8i_codec_headphone_widgets[] = { |
402 | SND_SOC_DAPM_MUX("Headphone Source Playback Route", | 426 | SND_SOC_DAPM_MUX("Headphone Source Playback Route", |
403 | SND_SOC_NOPM, 0, 0, sun8i_codec_hp_src), | 427 | SND_SOC_NOPM, 0, 0, sun8i_codec_hp_src), |
404 | SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN8I_ADDA_PAEN_HP_CTRL, | 428 | SND_SOC_DAPM_OUT_DRV_E("Headphone Amp", SUN8I_ADDA_PAEN_HP_CTRL, |
405 | SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN, 0, NULL, 0), | 429 | SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN, 0, NULL, 0, |
430 | sun8i_headphone_amp_event, | ||
431 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | ||
406 | SND_SOC_DAPM_SUPPLY("HPCOM Protection", SUN8I_ADDA_PAEN_HP_CTRL, | 432 | SND_SOC_DAPM_SUPPLY("HPCOM Protection", SUN8I_ADDA_PAEN_HP_CTRL, |
407 | SUN8I_ADDA_PAEN_HP_CTRL_COMPTEN, 0, NULL, 0), | 433 | SUN8I_ADDA_PAEN_HP_CTRL_COMPTEN, 0, NULL, 0), |
408 | SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPCOM", SUN8I_ADDA_PAEN_HP_CTRL, | 434 | SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPCOM", SUN8I_ADDA_PAEN_HP_CTRL, |
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c new file mode 100644 index 000000000000..b92bdc8361af --- /dev/null +++ b/sound/soc/sunxi/sun8i-codec.c | |||
@@ -0,0 +1,498 @@ | |||
1 | /* | ||
2 | * This driver supports the digital controls for the internal codec | ||
3 | * found in Allwinner's A33 SoCs. | ||
4 | * | ||
5 | * (C) Copyright 2010-2016 | ||
6 | * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com> | ||
7 | * huangxin <huangxin@Reuuimllatech.com> | ||
8 | * Mylène Josserand <mylene.josserand@free-electrons.com> | ||
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 published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/clk.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/pm_runtime.h> | ||
26 | #include <linux/regmap.h> | ||
27 | |||
28 | #include <sound/pcm_params.h> | ||
29 | #include <sound/soc.h> | ||
30 | #include <sound/soc-dapm.h> | ||
31 | |||
32 | #define SUN8I_SYSCLK_CTL 0x00c | ||
33 | #define SUN8I_SYSCLK_CTL_AIF1CLK_ENA 11 | ||
34 | #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL 9 | ||
35 | #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC 8 | ||
36 | #define SUN8I_SYSCLK_CTL_SYSCLK_ENA 3 | ||
37 | #define SUN8I_SYSCLK_CTL_SYSCLK_SRC 0 | ||
38 | #define SUN8I_MOD_CLK_ENA 0x010 | ||
39 | #define SUN8I_MOD_CLK_ENA_AIF1 15 | ||
40 | #define SUN8I_MOD_CLK_ENA_DAC 2 | ||
41 | #define SUN8I_MOD_RST_CTL 0x014 | ||
42 | #define SUN8I_MOD_RST_CTL_AIF1 15 | ||
43 | #define SUN8I_MOD_RST_CTL_DAC 2 | ||
44 | #define SUN8I_SYS_SR_CTRL 0x018 | ||
45 | #define SUN8I_SYS_SR_CTRL_AIF1_FS 12 | ||
46 | #define SUN8I_SYS_SR_CTRL_AIF2_FS 8 | ||
47 | #define SUN8I_AIF1CLK_CTRL 0x040 | ||
48 | #define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD 15 | ||
49 | #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV 14 | ||
50 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV 13 | ||
51 | #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV 9 | ||
52 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV 6 | ||
53 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16 (1 << 6) | ||
54 | #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ 4 | ||
55 | #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16 (1 << 4) | ||
56 | #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT 2 | ||
57 | #define SUN8I_AIF1_DACDAT_CTRL 0x048 | ||
58 | #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA 15 | ||
59 | #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA 14 | ||
60 | #define SUN8I_DAC_DIG_CTRL 0x120 | ||
61 | #define SUN8I_DAC_DIG_CTRL_ENDA 15 | ||
62 | #define SUN8I_DAC_MXR_SRC 0x130 | ||
63 | #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L 15 | ||
64 | #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L 14 | ||
65 | #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL 13 | ||
66 | #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL 12 | ||
67 | #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R 11 | ||
68 | #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R 10 | ||
69 | #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR 9 | ||
70 | #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR 8 | ||
71 | |||
72 | #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) | ||
73 | #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) | ||
74 | #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) | ||
75 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) | ||
76 | |||
77 | struct sun8i_codec { | ||
78 | struct device *dev; | ||
79 | struct regmap *regmap; | ||
80 | struct clk *clk_module; | ||
81 | struct clk *clk_bus; | ||
82 | }; | ||
83 | |||
84 | static int sun8i_codec_runtime_resume(struct device *dev) | ||
85 | { | ||
86 | struct sun8i_codec *scodec = dev_get_drvdata(dev); | ||
87 | int ret; | ||
88 | |||
89 | ret = clk_prepare_enable(scodec->clk_module); | ||
90 | if (ret) { | ||
91 | dev_err(dev, "Failed to enable the module clock\n"); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | ret = clk_prepare_enable(scodec->clk_bus); | ||
96 | if (ret) { | ||
97 | dev_err(dev, "Failed to enable the bus clock\n"); | ||
98 | goto err_disable_modclk; | ||
99 | } | ||
100 | |||
101 | regcache_cache_only(scodec->regmap, false); | ||
102 | |||
103 | ret = regcache_sync(scodec->regmap); | ||
104 | if (ret) { | ||
105 | dev_err(dev, "Failed to sync regmap cache\n"); | ||
106 | goto err_disable_clk; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | |||
111 | err_disable_clk: | ||
112 | clk_disable_unprepare(scodec->clk_bus); | ||
113 | |||
114 | err_disable_modclk: | ||
115 | clk_disable_unprepare(scodec->clk_module); | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | static int sun8i_codec_runtime_suspend(struct device *dev) | ||
121 | { | ||
122 | struct sun8i_codec *scodec = dev_get_drvdata(dev); | ||
123 | |||
124 | regcache_cache_only(scodec->regmap, true); | ||
125 | regcache_mark_dirty(scodec->regmap); | ||
126 | |||
127 | clk_disable_unprepare(scodec->clk_module); | ||
128 | clk_disable_unprepare(scodec->clk_bus); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params) | ||
134 | { | ||
135 | unsigned int rate = params_rate(params); | ||
136 | |||
137 | switch (rate) { | ||
138 | case 8000: | ||
139 | case 7350: | ||
140 | return 0x0; | ||
141 | case 11025: | ||
142 | return 0x1; | ||
143 | case 12000: | ||
144 | return 0x2; | ||
145 | case 16000: | ||
146 | return 0x3; | ||
147 | case 22050: | ||
148 | return 0x4; | ||
149 | case 24000: | ||
150 | return 0x5; | ||
151 | case 32000: | ||
152 | return 0x6; | ||
153 | case 44100: | ||
154 | return 0x7; | ||
155 | case 48000: | ||
156 | return 0x8; | ||
157 | case 96000: | ||
158 | return 0x9; | ||
159 | case 192000: | ||
160 | return 0xa; | ||
161 | default: | ||
162 | return -EINVAL; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
167 | { | ||
168 | struct sun8i_codec *scodec = snd_soc_codec_get_drvdata(dai->codec); | ||
169 | u32 value; | ||
170 | |||
171 | /* clock masters */ | ||
172 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
173 | case SND_SOC_DAIFMT_CBS_CFS: /* DAI Slave */ | ||
174 | value = 0x0; /* Codec Master */ | ||
175 | break; | ||
176 | case SND_SOC_DAIFMT_CBM_CFM: /* DAI Master */ | ||
177 | value = 0x1; /* Codec Slave */ | ||
178 | break; | ||
179 | default: | ||
180 | return -EINVAL; | ||
181 | } | ||
182 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, | ||
183 | BIT(SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD), | ||
184 | value << SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD); | ||
185 | |||
186 | /* clock inversion */ | ||
187 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
188 | case SND_SOC_DAIFMT_NB_NF: /* Normal */ | ||
189 | value = 0x0; | ||
190 | break; | ||
191 | case SND_SOC_DAIFMT_IB_IF: /* Inversion */ | ||
192 | value = 0x1; | ||
193 | break; | ||
194 | default: | ||
195 | return -EINVAL; | ||
196 | } | ||
197 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, | ||
198 | BIT(SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV), | ||
199 | value << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV); | ||
200 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, | ||
201 | BIT(SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV), | ||
202 | value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV); | ||
203 | |||
204 | /* DAI format */ | ||
205 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
206 | case SND_SOC_DAIFMT_I2S: | ||
207 | value = 0x0; | ||
208 | break; | ||
209 | case SND_SOC_DAIFMT_LEFT_J: | ||
210 | value = 0x1; | ||
211 | break; | ||
212 | case SND_SOC_DAIFMT_RIGHT_J: | ||
213 | value = 0x2; | ||
214 | break; | ||
215 | case SND_SOC_DAIFMT_DSP_A: | ||
216 | case SND_SOC_DAIFMT_DSP_B: | ||
217 | value = 0x3; | ||
218 | break; | ||
219 | default: | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, | ||
223 | BIT(SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT), | ||
224 | value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, | ||
230 | struct snd_pcm_hw_params *params, | ||
231 | struct snd_soc_dai *dai) | ||
232 | { | ||
233 | struct sun8i_codec *scodec = snd_soc_codec_get_drvdata(dai->codec); | ||
234 | int sample_rate; | ||
235 | |||
236 | /* | ||
237 | * The CPU DAI handles only a sample of 16 bits. Configure the | ||
238 | * codec to handle this type of sample resolution. | ||
239 | */ | ||
240 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, | ||
241 | SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK, | ||
242 | SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16); | ||
243 | |||
244 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, | ||
245 | SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, | ||
246 | SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16); | ||
247 | |||
248 | sample_rate = sun8i_codec_get_hw_rate(params); | ||
249 | if (sample_rate < 0) | ||
250 | return sample_rate; | ||
251 | |||
252 | regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, | ||
253 | SUN8I_SYS_SR_CTRL_AIF1_FS_MASK, | ||
254 | sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS); | ||
255 | regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, | ||
256 | SUN8I_SYS_SR_CTRL_AIF2_FS_MASK, | ||
257 | sample_rate << SUN8I_SYS_SR_CTRL_AIF2_FS); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static const struct snd_kcontrol_new sun8i_output_left_mixer_controls[] = { | ||
263 | SOC_DAPM_SINGLE("LSlot 0", SUN8I_DAC_MXR_SRC, | ||
264 | SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L, 1, 0), | ||
265 | SOC_DAPM_SINGLE("LSlot 1", SUN8I_DAC_MXR_SRC, | ||
266 | SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L, 1, 0), | ||
267 | SOC_DAPM_SINGLE("DACL", SUN8I_DAC_MXR_SRC, | ||
268 | SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL, 1, 0), | ||
269 | SOC_DAPM_SINGLE("ADCL", SUN8I_DAC_MXR_SRC, | ||
270 | SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL, 1, 0), | ||
271 | }; | ||
272 | |||
273 | static const struct snd_kcontrol_new sun8i_output_right_mixer_controls[] = { | ||
274 | SOC_DAPM_SINGLE("RSlot 0", SUN8I_DAC_MXR_SRC, | ||
275 | SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0), | ||
276 | SOC_DAPM_SINGLE("RSlot 1", SUN8I_DAC_MXR_SRC, | ||
277 | SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0), | ||
278 | SOC_DAPM_SINGLE("DACR", SUN8I_DAC_MXR_SRC, | ||
279 | SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0), | ||
280 | SOC_DAPM_SINGLE("ADCR", SUN8I_DAC_MXR_SRC, | ||
281 | SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0), | ||
282 | }; | ||
283 | |||
284 | static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = { | ||
285 | /* Digital parts of the DACs */ | ||
286 | SND_SOC_DAPM_SUPPLY("DAC", SUN8I_DAC_DIG_CTRL, SUN8I_DAC_DIG_CTRL_ENDA, | ||
287 | 0, NULL, 0), | ||
288 | |||
289 | /* Analog DAC */ | ||
290 | SND_SOC_DAPM_DAC("Digital Left DAC", "Playback", SUN8I_AIF1_DACDAT_CTRL, | ||
291 | SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0), | ||
292 | SND_SOC_DAPM_DAC("Digital Right DAC", "Playback", SUN8I_AIF1_DACDAT_CTRL, | ||
293 | SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0), | ||
294 | |||
295 | /* DAC Mixers */ | ||
296 | SND_SOC_DAPM_MIXER("Left DAC Mixer", SND_SOC_NOPM, 0, 0, | ||
297 | sun8i_output_left_mixer_controls, | ||
298 | ARRAY_SIZE(sun8i_output_left_mixer_controls)), | ||
299 | SND_SOC_DAPM_MIXER("Right DAC Mixer", SND_SOC_NOPM, 0, 0, | ||
300 | sun8i_output_right_mixer_controls, | ||
301 | ARRAY_SIZE(sun8i_output_right_mixer_controls)), | ||
302 | |||
303 | /* Clocks */ | ||
304 | SND_SOC_DAPM_SUPPLY("MODCLK AFI1", SUN8I_MOD_CLK_ENA, | ||
305 | SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0), | ||
306 | SND_SOC_DAPM_SUPPLY("MODCLK DAC", SUN8I_MOD_CLK_ENA, | ||
307 | SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0), | ||
308 | SND_SOC_DAPM_SUPPLY("AIF1", SUN8I_SYSCLK_CTL, | ||
309 | SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0), | ||
310 | SND_SOC_DAPM_SUPPLY("SYSCLK", SUN8I_SYSCLK_CTL, | ||
311 | SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0), | ||
312 | |||
313 | SND_SOC_DAPM_SUPPLY("AIF1 PLL", SUN8I_SYSCLK_CTL, | ||
314 | SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL, 0, NULL, 0), | ||
315 | /* Inversion as 0=AIF1, 1=AIF2 */ | ||
316 | SND_SOC_DAPM_SUPPLY("SYSCLK AIF1", SUN8I_SYSCLK_CTL, | ||
317 | SUN8I_SYSCLK_CTL_SYSCLK_SRC, 1, NULL, 0), | ||
318 | |||
319 | /* Module reset */ | ||
320 | SND_SOC_DAPM_SUPPLY("RST AIF1", SUN8I_MOD_RST_CTL, | ||
321 | SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0), | ||
322 | SND_SOC_DAPM_SUPPLY("RST DAC", SUN8I_MOD_RST_CTL, | ||
323 | SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0), | ||
324 | |||
325 | SND_SOC_DAPM_OUTPUT("HP"), | ||
326 | }; | ||
327 | |||
328 | static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = { | ||
329 | /* Clock Routes */ | ||
330 | { "AIF1", NULL, "SYSCLK AIF1" }, | ||
331 | { "AIF1 PLL", NULL, "AIF1" }, | ||
332 | { "RST AIF1", NULL, "AIF1 PLL" }, | ||
333 | { "MODCLK AFI1", NULL, "RST AIF1" }, | ||
334 | { "DAC", NULL, "MODCLK AFI1" }, | ||
335 | |||
336 | { "RST DAC", NULL, "SYSCLK" }, | ||
337 | { "MODCLK DAC", NULL, "RST DAC" }, | ||
338 | { "DAC", NULL, "MODCLK DAC" }, | ||
339 | |||
340 | /* DAC Routes */ | ||
341 | { "Digital Left DAC", NULL, "DAC" }, | ||
342 | { "Digital Right DAC", NULL, "DAC" }, | ||
343 | |||
344 | /* DAC Mixer Routes */ | ||
345 | { "Left DAC Mixer", "LSlot 0", "Digital Left DAC"}, | ||
346 | { "Right DAC Mixer", "RSlot 0", "Digital Right DAC"}, | ||
347 | |||
348 | /* End of route : HP out */ | ||
349 | { "HP", NULL, "Left DAC Mixer" }, | ||
350 | { "HP", NULL, "Right DAC Mixer" }, | ||
351 | }; | ||
352 | |||
353 | static struct snd_soc_dai_ops sun8i_codec_dai_ops = { | ||
354 | .hw_params = sun8i_codec_hw_params, | ||
355 | .set_fmt = sun8i_set_fmt, | ||
356 | }; | ||
357 | |||
358 | static struct snd_soc_dai_driver sun8i_codec_dai = { | ||
359 | .name = "sun8i", | ||
360 | /* playback capabilities */ | ||
361 | .playback = { | ||
362 | .stream_name = "Playback", | ||
363 | .channels_min = 1, | ||
364 | .channels_max = 2, | ||
365 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
366 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
367 | }, | ||
368 | /* pcm operations */ | ||
369 | .ops = &sun8i_codec_dai_ops, | ||
370 | }; | ||
371 | |||
372 | static struct snd_soc_codec_driver sun8i_soc_codec = { | ||
373 | .component_driver = { | ||
374 | .dapm_widgets = sun8i_codec_dapm_widgets, | ||
375 | .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets), | ||
376 | .dapm_routes = sun8i_codec_dapm_routes, | ||
377 | .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes), | ||
378 | }, | ||
379 | }; | ||
380 | |||
381 | static const struct regmap_config sun8i_codec_regmap_config = { | ||
382 | .reg_bits = 32, | ||
383 | .reg_stride = 4, | ||
384 | .val_bits = 32, | ||
385 | .max_register = SUN8I_DAC_MXR_SRC, | ||
386 | |||
387 | .cache_type = REGCACHE_FLAT, | ||
388 | }; | ||
389 | |||
390 | static int sun8i_codec_probe(struct platform_device *pdev) | ||
391 | { | ||
392 | struct resource *res_base; | ||
393 | struct sun8i_codec *scodec; | ||
394 | void __iomem *base; | ||
395 | int ret; | ||
396 | |||
397 | scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL); | ||
398 | if (!scodec) | ||
399 | return -ENOMEM; | ||
400 | |||
401 | scodec->dev = &pdev->dev; | ||
402 | |||
403 | scodec->clk_module = devm_clk_get(&pdev->dev, "mod"); | ||
404 | if (IS_ERR(scodec->clk_module)) { | ||
405 | dev_err(&pdev->dev, "Failed to get the module clock\n"); | ||
406 | return PTR_ERR(scodec->clk_module); | ||
407 | } | ||
408 | |||
409 | scodec->clk_bus = devm_clk_get(&pdev->dev, "bus"); | ||
410 | if (IS_ERR(scodec->clk_bus)) { | ||
411 | dev_err(&pdev->dev, "Failed to get the bus clock\n"); | ||
412 | return PTR_ERR(scodec->clk_bus); | ||
413 | } | ||
414 | |||
415 | res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
416 | base = devm_ioremap_resource(&pdev->dev, res_base); | ||
417 | if (IS_ERR(base)) { | ||
418 | dev_err(&pdev->dev, "Failed to map the registers\n"); | ||
419 | return PTR_ERR(base); | ||
420 | } | ||
421 | |||
422 | scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base, | ||
423 | &sun8i_codec_regmap_config); | ||
424 | if (IS_ERR(scodec->regmap)) { | ||
425 | dev_err(&pdev->dev, "Failed to create our regmap\n"); | ||
426 | return PTR_ERR(scodec->regmap); | ||
427 | } | ||
428 | |||
429 | platform_set_drvdata(pdev, scodec); | ||
430 | |||
431 | pm_runtime_enable(&pdev->dev); | ||
432 | if (!pm_runtime_enabled(&pdev->dev)) { | ||
433 | ret = sun8i_codec_runtime_resume(&pdev->dev); | ||
434 | if (ret) | ||
435 | goto err_pm_disable; | ||
436 | } | ||
437 | |||
438 | ret = snd_soc_register_codec(&pdev->dev, &sun8i_soc_codec, | ||
439 | &sun8i_codec_dai, 1); | ||
440 | if (ret) { | ||
441 | dev_err(&pdev->dev, "Failed to register codec\n"); | ||
442 | goto err_suspend; | ||
443 | } | ||
444 | |||
445 | return ret; | ||
446 | |||
447 | err_suspend: | ||
448 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
449 | sun8i_codec_runtime_suspend(&pdev->dev); | ||
450 | |||
451 | err_pm_disable: | ||
452 | pm_runtime_disable(&pdev->dev); | ||
453 | |||
454 | return ret; | ||
455 | } | ||
456 | |||
457 | static int sun8i_codec_remove(struct platform_device *pdev) | ||
458 | { | ||
459 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
460 | struct sun8i_codec *scodec = snd_soc_card_get_drvdata(card); | ||
461 | |||
462 | pm_runtime_disable(&pdev->dev); | ||
463 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
464 | sun8i_codec_runtime_suspend(&pdev->dev); | ||
465 | |||
466 | snd_soc_unregister_codec(&pdev->dev); | ||
467 | clk_disable_unprepare(scodec->clk_module); | ||
468 | clk_disable_unprepare(scodec->clk_bus); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static const struct of_device_id sun8i_codec_of_match[] = { | ||
474 | { .compatible = "allwinner,sun8i-a33-codec" }, | ||
475 | {} | ||
476 | }; | ||
477 | MODULE_DEVICE_TABLE(of, sun8i_codec_of_match); | ||
478 | |||
479 | static const struct dev_pm_ops sun8i_codec_pm_ops = { | ||
480 | SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend, | ||
481 | sun8i_codec_runtime_resume, NULL) | ||
482 | }; | ||
483 | |||
484 | static struct platform_driver sun8i_codec_driver = { | ||
485 | .driver = { | ||
486 | .name = "sun8i-codec", | ||
487 | .of_match_table = sun8i_codec_of_match, | ||
488 | .pm = &sun8i_codec_pm_ops, | ||
489 | }, | ||
490 | .probe = sun8i_codec_probe, | ||
491 | .remove = sun8i_codec_remove, | ||
492 | }; | ||
493 | module_platform_driver(sun8i_codec_driver); | ||
494 | |||
495 | MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver"); | ||
496 | MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>"); | ||
497 | MODULE_LICENSE("GPL"); | ||
498 | MODULE_ALIAS("platform:sun8i-codec"); | ||
diff --git a/sound/soc/zte/zx-i2s.c b/sound/soc/zte/zx-i2s.c index 1cad93dc1fcf..a865f37c2a56 100644 --- a/sound/soc/zte/zx-i2s.c +++ b/sound/soc/zte/zx-i2s.c | |||
@@ -95,7 +95,8 @@ | |||
95 | struct zx_i2s_info { | 95 | struct zx_i2s_info { |
96 | struct snd_dmaengine_dai_dma_data dma_playback; | 96 | struct snd_dmaengine_dai_dma_data dma_playback; |
97 | struct snd_dmaengine_dai_dma_data dma_capture; | 97 | struct snd_dmaengine_dai_dma_data dma_capture; |
98 | struct clk *dai_clk; | 98 | struct clk *dai_wclk; |
99 | struct clk *dai_pclk; | ||
99 | void __iomem *reg_base; | 100 | void __iomem *reg_base; |
100 | int master; | 101 | int master; |
101 | resource_size_t mapbase; | 102 | resource_size_t mapbase; |
@@ -225,7 +226,7 @@ static int zx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
225 | struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai); | 226 | struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai); |
226 | struct snd_dmaengine_dai_dma_data *dma_data; | 227 | struct snd_dmaengine_dai_dma_data *dma_data; |
227 | unsigned int lane, ch_num, len, ret = 0; | 228 | unsigned int lane, ch_num, len, ret = 0; |
228 | unsigned long val, format; | 229 | unsigned long val; |
229 | unsigned long chn_cfg; | 230 | unsigned long chn_cfg; |
230 | 231 | ||
231 | dma_data = snd_soc_dai_get_dma_data(socdai, substream); | 232 | dma_data = snd_soc_dai_get_dma_data(socdai, substream); |
@@ -238,15 +239,12 @@ static int zx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
238 | 239 | ||
239 | switch (params_format(params)) { | 240 | switch (params_format(params)) { |
240 | case SNDRV_PCM_FORMAT_S16_LE: | 241 | case SNDRV_PCM_FORMAT_S16_LE: |
241 | format = 0; | ||
242 | len = 16; | 242 | len = 16; |
243 | break; | 243 | break; |
244 | case SNDRV_PCM_FORMAT_S24_LE: | 244 | case SNDRV_PCM_FORMAT_S24_LE: |
245 | format = 1; | ||
246 | len = 24; | 245 | len = 24; |
247 | break; | 246 | break; |
248 | case SNDRV_PCM_FORMAT_S32_LE: | 247 | case SNDRV_PCM_FORMAT_S32_LE: |
249 | format = 2; | ||
250 | len = 32; | 248 | len = 32; |
251 | break; | 249 | break; |
252 | default: | 250 | default: |
@@ -278,8 +276,9 @@ static int zx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
278 | writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL); | 276 | writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL); |
279 | 277 | ||
280 | if (i2s->master) | 278 | if (i2s->master) |
281 | ret = clk_set_rate(i2s->dai_clk, | 279 | ret = clk_set_rate(i2s->dai_wclk, |
282 | params_rate(params) * ch_num * CLK_RAT); | 280 | params_rate(params) * ch_num * CLK_RAT); |
281 | |||
283 | return ret; | 282 | return ret; |
284 | } | 283 | } |
285 | 284 | ||
@@ -331,8 +330,19 @@ static int zx_i2s_startup(struct snd_pcm_substream *substream, | |||
331 | struct snd_soc_dai *dai) | 330 | struct snd_soc_dai *dai) |
332 | { | 331 | { |
333 | struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); | 332 | struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); |
333 | int ret; | ||
334 | 334 | ||
335 | return clk_prepare_enable(zx_i2s->dai_clk); | 335 | ret = clk_prepare_enable(zx_i2s->dai_wclk); |
336 | if (ret) | ||
337 | return ret; | ||
338 | |||
339 | ret = clk_prepare_enable(zx_i2s->dai_pclk); | ||
340 | if (ret) { | ||
341 | clk_disable_unprepare(zx_i2s->dai_wclk); | ||
342 | return ret; | ||
343 | } | ||
344 | |||
345 | return ret; | ||
336 | } | 346 | } |
337 | 347 | ||
338 | static void zx_i2s_shutdown(struct snd_pcm_substream *substream, | 348 | static void zx_i2s_shutdown(struct snd_pcm_substream *substream, |
@@ -340,7 +350,8 @@ static void zx_i2s_shutdown(struct snd_pcm_substream *substream, | |||
340 | { | 350 | { |
341 | struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); | 351 | struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); |
342 | 352 | ||
343 | clk_disable_unprepare(zx_i2s->dai_clk); | 353 | clk_disable_unprepare(zx_i2s->dai_wclk); |
354 | clk_disable_unprepare(zx_i2s->dai_pclk); | ||
344 | } | 355 | } |
345 | 356 | ||
346 | static struct snd_soc_dai_ops zx_i2s_dai_ops = { | 357 | static struct snd_soc_dai_ops zx_i2s_dai_ops = { |
@@ -384,10 +395,16 @@ static int zx_i2s_probe(struct platform_device *pdev) | |||
384 | if (!zx_i2s) | 395 | if (!zx_i2s) |
385 | return -ENOMEM; | 396 | return -ENOMEM; |
386 | 397 | ||
387 | zx_i2s->dai_clk = devm_clk_get(&pdev->dev, "tx"); | 398 | zx_i2s->dai_wclk = devm_clk_get(&pdev->dev, "wclk"); |
388 | if (IS_ERR(zx_i2s->dai_clk)) { | 399 | if (IS_ERR(zx_i2s->dai_wclk)) { |
389 | dev_err(&pdev->dev, "Fail to get clk\n"); | 400 | dev_err(&pdev->dev, "Fail to get wclk\n"); |
390 | return PTR_ERR(zx_i2s->dai_clk); | 401 | return PTR_ERR(zx_i2s->dai_wclk); |
402 | } | ||
403 | |||
404 | zx_i2s->dai_pclk = devm_clk_get(&pdev->dev, "pclk"); | ||
405 | if (IS_ERR(zx_i2s->dai_pclk)) { | ||
406 | dev_err(&pdev->dev, "Fail to get pclk\n"); | ||
407 | return PTR_ERR(zx_i2s->dai_pclk); | ||
391 | } | 408 | } |
392 | 409 | ||
393 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 410 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |