diff options
Diffstat (limited to 'sound')
27 files changed, 1033 insertions, 425 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 8349f982a586..6ecac1e4428e 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -69,6 +69,7 @@ config SND_SOC_ALL_CODECS | |||
69 | select SND_SOC_MAX98088 if I2C | 69 | select SND_SOC_MAX98088 if I2C |
70 | select SND_SOC_MAX98090 if I2C | 70 | select SND_SOC_MAX98090 if I2C |
71 | select SND_SOC_MAX98095 if I2C | 71 | select SND_SOC_MAX98095 if I2C |
72 | select SND_SOC_MAX98357A | ||
72 | select SND_SOC_MAX9850 if I2C | 73 | select SND_SOC_MAX9850 if I2C |
73 | select SND_SOC_MAX9768 if I2C | 74 | select SND_SOC_MAX9768 if I2C |
74 | select SND_SOC_MAX9877 if I2C | 75 | select SND_SOC_MAX9877 if I2C |
@@ -456,6 +457,9 @@ config SND_SOC_MAX98090 | |||
456 | config SND_SOC_MAX98095 | 457 | config SND_SOC_MAX98095 |
457 | tristate | 458 | tristate |
458 | 459 | ||
460 | config SND_SOC_MAX98357A | ||
461 | tristate | ||
462 | |||
459 | config SND_SOC_MAX9850 | 463 | config SND_SOC_MAX9850 |
460 | tristate | 464 | tristate |
461 | 465 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bbdfd1e1c182..69b8666d187a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -64,6 +64,7 @@ snd-soc-max9768-objs := max9768.o | |||
64 | snd-soc-max98088-objs := max98088.o | 64 | snd-soc-max98088-objs := max98088.o |
65 | snd-soc-max98090-objs := max98090.o | 65 | snd-soc-max98090-objs := max98090.o |
66 | snd-soc-max98095-objs := max98095.o | 66 | snd-soc-max98095-objs := max98095.o |
67 | snd-soc-max98357a-objs := max98357a.o | ||
67 | snd-soc-max9850-objs := max9850.o | 68 | snd-soc-max9850-objs := max9850.o |
68 | snd-soc-mc13783-objs := mc13783.o | 69 | snd-soc-mc13783-objs := mc13783.o |
69 | snd-soc-ml26124-objs := ml26124.o | 70 | snd-soc-ml26124-objs := ml26124.o |
@@ -245,6 +246,7 @@ obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o | |||
245 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o | 246 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o |
246 | obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o | 247 | obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o |
247 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o | 248 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o |
249 | obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o | ||
248 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | 250 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o |
249 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o | 251 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o |
250 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o | 252 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o |
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c new file mode 100644 index 000000000000..1806333ea29e --- /dev/null +++ b/sound/soc/codecs/max98357a.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * max98357a.c -- MAX98357A ALSA SoC Codec driver | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <sound/soc.h> | ||
18 | |||
19 | #define DRV_NAME "max98357a" | ||
20 | |||
21 | static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, | ||
22 | int cmd, struct snd_soc_dai *dai) | ||
23 | { | ||
24 | struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai); | ||
25 | |||
26 | switch (cmd) { | ||
27 | case SNDRV_PCM_TRIGGER_START: | ||
28 | case SNDRV_PCM_TRIGGER_RESUME: | ||
29 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
30 | gpiod_set_value(sdmode, 1); | ||
31 | break; | ||
32 | case SNDRV_PCM_TRIGGER_STOP: | ||
33 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
34 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
35 | gpiod_set_value(sdmode, 0); | ||
36 | break; | ||
37 | } | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = { | ||
43 | SND_SOC_DAPM_DAC("SDMode", NULL, SND_SOC_NOPM, 0, 0), | ||
44 | SND_SOC_DAPM_OUTPUT("Speaker"), | ||
45 | }; | ||
46 | |||
47 | static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { | ||
48 | {"Speaker", NULL, "SDMode"}, | ||
49 | }; | ||
50 | |||
51 | static int max98357a_codec_probe(struct snd_soc_codec *codec) | ||
52 | { | ||
53 | struct gpio_desc *sdmode; | ||
54 | |||
55 | sdmode = devm_gpiod_get(codec->dev, "sdmode"); | ||
56 | if (IS_ERR(sdmode)) { | ||
57 | dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n", | ||
58 | __func__, PTR_ERR(sdmode)); | ||
59 | return PTR_ERR(sdmode); | ||
60 | } | ||
61 | gpiod_direction_output(sdmode, 0); | ||
62 | snd_soc_codec_set_drvdata(codec, sdmode); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static struct snd_soc_codec_driver max98357a_codec_driver = { | ||
68 | .probe = max98357a_codec_probe, | ||
69 | .dapm_widgets = max98357a_dapm_widgets, | ||
70 | .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets), | ||
71 | .dapm_routes = max98357a_dapm_routes, | ||
72 | .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), | ||
73 | }; | ||
74 | |||
75 | static struct snd_soc_dai_ops max98357a_dai_ops = { | ||
76 | .trigger = max98357a_daiops_trigger, | ||
77 | }; | ||
78 | |||
79 | static struct snd_soc_dai_driver max98357a_dai_driver = { | ||
80 | .name = DRV_NAME, | ||
81 | .playback = { | ||
82 | .stream_name = DRV_NAME "-playback", | ||
83 | .formats = SNDRV_PCM_FMTBIT_S16 | | ||
84 | SNDRV_PCM_FMTBIT_S24 | | ||
85 | SNDRV_PCM_FMTBIT_S32, | ||
86 | .rates = SNDRV_PCM_RATE_8000 | | ||
87 | SNDRV_PCM_RATE_16000 | | ||
88 | SNDRV_PCM_RATE_48000 | | ||
89 | SNDRV_PCM_RATE_96000, | ||
90 | .rate_min = 8000, | ||
91 | .rate_max = 96000, | ||
92 | .channels_min = 1, | ||
93 | .channels_max = 2, | ||
94 | }, | ||
95 | .ops = &max98357a_dai_ops, | ||
96 | }; | ||
97 | |||
98 | static int max98357a_platform_probe(struct platform_device *pdev) | ||
99 | { | ||
100 | int ret; | ||
101 | |||
102 | ret = snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver, | ||
103 | &max98357a_dai_driver, 1); | ||
104 | if (ret) | ||
105 | dev_err(&pdev->dev, "%s() error registering codec driver: %d\n", | ||
106 | __func__, ret); | ||
107 | |||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | static int max98357a_platform_remove(struct platform_device *pdev) | ||
112 | { | ||
113 | snd_soc_unregister_codec(&pdev->dev); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | #ifdef CONFIG_OF | ||
119 | static const struct of_device_id max98357a_device_id[] = { | ||
120 | { .compatible = "maxim," DRV_NAME, }, | ||
121 | {} | ||
122 | }; | ||
123 | MODULE_DEVICE_TABLE(of, max98357a_device_id); | ||
124 | #endif | ||
125 | |||
126 | static struct platform_driver max98357a_platform_driver = { | ||
127 | .driver = { | ||
128 | .name = DRV_NAME, | ||
129 | .of_match_table = of_match_ptr(max98357a_device_id), | ||
130 | }, | ||
131 | .probe = max98357a_platform_probe, | ||
132 | .remove = max98357a_platform_remove, | ||
133 | }; | ||
134 | module_platform_driver(max98357a_platform_driver); | ||
135 | |||
136 | MODULE_DESCRIPTION("Maxim MAX98357A Codec Driver"); | ||
137 | MODULE_LICENSE("GPL v2"); | ||
138 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 068dfd5c7640..c9a4c5be083b 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "rt5645.h" | 31 | #include "rt5645.h" |
32 | 32 | ||
33 | #define RT5645_DEVICE_ID 0x6308 | 33 | #define RT5645_DEVICE_ID 0x6308 |
34 | #define RT5650_DEVICE_ID 0x6419 | ||
34 | 35 | ||
35 | #define RT5645_PR_RANGE_BASE (0xff + 1) | 36 | #define RT5645_PR_RANGE_BASE (0xff + 1) |
36 | #define RT5645_PR_SPACING 0x100 | 37 | #define RT5645_PR_SPACING 0x100 |
@@ -59,6 +60,10 @@ static const struct reg_default init_list[] = { | |||
59 | }; | 60 | }; |
60 | #define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list) | 61 | #define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list) |
61 | 62 | ||
63 | static const struct reg_default rt5650_init_list[] = { | ||
64 | {0xf6, 0x0100}, | ||
65 | }; | ||
66 | |||
62 | static const struct reg_default rt5645_reg[] = { | 67 | static const struct reg_default rt5645_reg[] = { |
63 | { 0x00, 0x0000 }, | 68 | { 0x00, 0x0000 }, |
64 | { 0x01, 0xc8c8 }, | 69 | { 0x01, 0xc8c8 }, |
@@ -86,6 +91,7 @@ static const struct reg_default rt5645_reg[] = { | |||
86 | { 0x2a, 0x5656 }, | 91 | { 0x2a, 0x5656 }, |
87 | { 0x2b, 0x5454 }, | 92 | { 0x2b, 0x5454 }, |
88 | { 0x2c, 0xaaa0 }, | 93 | { 0x2c, 0xaaa0 }, |
94 | { 0x2d, 0x0000 }, | ||
89 | { 0x2f, 0x1002 }, | 95 | { 0x2f, 0x1002 }, |
90 | { 0x31, 0x5000 }, | 96 | { 0x31, 0x5000 }, |
91 | { 0x32, 0x0000 }, | 97 | { 0x32, 0x0000 }, |
@@ -193,6 +199,8 @@ static const struct reg_default rt5645_reg[] = { | |||
193 | { 0xdb, 0x0003 }, | 199 | { 0xdb, 0x0003 }, |
194 | { 0xdc, 0x0049 }, | 200 | { 0xdc, 0x0049 }, |
195 | { 0xdd, 0x001b }, | 201 | { 0xdd, 0x001b }, |
202 | { 0xdf, 0x0008 }, | ||
203 | { 0xe0, 0x4000 }, | ||
196 | { 0xe6, 0x8000 }, | 204 | { 0xe6, 0x8000 }, |
197 | { 0xe7, 0x0200 }, | 205 | { 0xe7, 0x0200 }, |
198 | { 0xec, 0xb300 }, | 206 | { 0xec, 0xb300 }, |
@@ -242,6 +250,7 @@ static bool rt5645_volatile_register(struct device *dev, unsigned int reg) | |||
242 | case RT5645_IRQ_CTRL3: | 250 | case RT5645_IRQ_CTRL3: |
243 | case RT5645_INT_IRQ_ST: | 251 | case RT5645_INT_IRQ_ST: |
244 | case RT5645_IL_CMD: | 252 | case RT5645_IL_CMD: |
253 | case RT5650_4BTN_IL_CMD1: | ||
245 | case RT5645_VENDOR_ID: | 254 | case RT5645_VENDOR_ID: |
246 | case RT5645_VENDOR_ID1: | 255 | case RT5645_VENDOR_ID1: |
247 | case RT5645_VENDOR_ID2: | 256 | case RT5645_VENDOR_ID2: |
@@ -287,6 +296,7 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg) | |||
287 | case RT5645_STO_DAC_MIXER: | 296 | case RT5645_STO_DAC_MIXER: |
288 | case RT5645_MONO_DAC_MIXER: | 297 | case RT5645_MONO_DAC_MIXER: |
289 | case RT5645_DIG_MIXER: | 298 | case RT5645_DIG_MIXER: |
299 | case RT5650_A_DAC_SOUR: | ||
290 | case RT5645_DIG_INF1_DATA: | 300 | case RT5645_DIG_INF1_DATA: |
291 | case RT5645_PDM_OUT_CTRL: | 301 | case RT5645_PDM_OUT_CTRL: |
292 | case RT5645_REC_L1_MIXER: | 302 | case RT5645_REC_L1_MIXER: |
@@ -378,6 +388,8 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg) | |||
378 | case RT5645_IL_CMD: | 388 | case RT5645_IL_CMD: |
379 | case RT5645_IL_CMD2: | 389 | case RT5645_IL_CMD2: |
380 | case RT5645_IL_CMD3: | 390 | case RT5645_IL_CMD3: |
391 | case RT5650_4BTN_IL_CMD1: | ||
392 | case RT5650_4BTN_IL_CMD2: | ||
381 | case RT5645_DRC1_HL_CTRL1: | 393 | case RT5645_DRC1_HL_CTRL1: |
382 | case RT5645_DRC2_HL_CTRL1: | 394 | case RT5645_DRC2_HL_CTRL1: |
383 | case RT5645_ADC_MONO_HP_CTRL1: | 395 | case RT5645_ADC_MONO_HP_CTRL1: |
@@ -603,6 +615,87 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, | |||
603 | 615 | ||
604 | } | 616 | } |
605 | 617 | ||
618 | /** | ||
619 | * rt5645_sel_asrc_clk_src - select ASRC clock source for a set of filters | ||
620 | * @codec: SoC audio codec device. | ||
621 | * @filter_mask: mask of filters. | ||
622 | * @clk_src: clock source | ||
623 | * | ||
624 | * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5645 can | ||
625 | * only support standard 32fs or 64fs i2s format, ASRC should be enabled to | ||
626 | * support special i2s clock format such as Intel's 100fs(100 * sampling rate). | ||
627 | * ASRC function will track i2s clock and generate a corresponding system clock | ||
628 | * for codec. This function provides an API to select the clock source for a | ||
629 | * set of filters specified by the mask. And the codec driver will turn on ASRC | ||
630 | * for these filters if ASRC is selected as their clock source. | ||
631 | */ | ||
632 | int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
633 | unsigned int filter_mask, unsigned int clk_src) | ||
634 | { | ||
635 | unsigned int asrc2_mask = 0; | ||
636 | unsigned int asrc2_value = 0; | ||
637 | unsigned int asrc3_mask = 0; | ||
638 | unsigned int asrc3_value = 0; | ||
639 | |||
640 | switch (clk_src) { | ||
641 | case RT5645_CLK_SEL_SYS: | ||
642 | case RT5645_CLK_SEL_I2S1_ASRC: | ||
643 | case RT5645_CLK_SEL_I2S2_ASRC: | ||
644 | case RT5645_CLK_SEL_SYS2: | ||
645 | break; | ||
646 | |||
647 | default: | ||
648 | return -EINVAL; | ||
649 | } | ||
650 | |||
651 | if (filter_mask & RT5645_DA_STEREO_FILTER) { | ||
652 | asrc2_mask |= RT5645_DA_STO_CLK_SEL_MASK; | ||
653 | asrc2_value = (asrc2_value & ~RT5645_DA_STO_CLK_SEL_MASK) | ||
654 | | (clk_src << RT5645_DA_STO_CLK_SEL_SFT); | ||
655 | } | ||
656 | |||
657 | if (filter_mask & RT5645_DA_MONO_L_FILTER) { | ||
658 | asrc2_mask |= RT5645_DA_MONOL_CLK_SEL_MASK; | ||
659 | asrc2_value = (asrc2_value & ~RT5645_DA_MONOL_CLK_SEL_MASK) | ||
660 | | (clk_src << RT5645_DA_MONOL_CLK_SEL_SFT); | ||
661 | } | ||
662 | |||
663 | if (filter_mask & RT5645_DA_MONO_R_FILTER) { | ||
664 | asrc2_mask |= RT5645_DA_MONOR_CLK_SEL_MASK; | ||
665 | asrc2_value = (asrc2_value & ~RT5645_DA_MONOR_CLK_SEL_MASK) | ||
666 | | (clk_src << RT5645_DA_MONOR_CLK_SEL_SFT); | ||
667 | } | ||
668 | |||
669 | if (filter_mask & RT5645_AD_STEREO_FILTER) { | ||
670 | asrc2_mask |= RT5645_AD_STO1_CLK_SEL_MASK; | ||
671 | asrc2_value = (asrc2_value & ~RT5645_AD_STO1_CLK_SEL_MASK) | ||
672 | | (clk_src << RT5645_AD_STO1_CLK_SEL_SFT); | ||
673 | } | ||
674 | |||
675 | if (filter_mask & RT5645_AD_MONO_L_FILTER) { | ||
676 | asrc3_mask |= RT5645_AD_MONOL_CLK_SEL_MASK; | ||
677 | asrc3_value = (asrc3_value & ~RT5645_AD_MONOL_CLK_SEL_MASK) | ||
678 | | (clk_src << RT5645_AD_MONOL_CLK_SEL_SFT); | ||
679 | } | ||
680 | |||
681 | if (filter_mask & RT5645_AD_MONO_R_FILTER) { | ||
682 | asrc3_mask |= RT5645_AD_MONOR_CLK_SEL_MASK; | ||
683 | asrc3_value = (asrc3_value & ~RT5645_AD_MONOR_CLK_SEL_MASK) | ||
684 | | (clk_src << RT5645_AD_MONOR_CLK_SEL_SFT); | ||
685 | } | ||
686 | |||
687 | if (asrc2_mask) | ||
688 | snd_soc_update_bits(codec, RT5645_ASRC_2, | ||
689 | asrc2_mask, asrc2_value); | ||
690 | |||
691 | if (asrc3_mask) | ||
692 | snd_soc_update_bits(codec, RT5645_ASRC_3, | ||
693 | asrc3_mask, asrc3_value); | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | EXPORT_SYMBOL_GPL(rt5645_sel_asrc_clk_src); | ||
698 | |||
606 | /* Digital Mixer */ | 699 | /* Digital Mixer */ |
607 | static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { | 700 | static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { |
608 | SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, | 701 | SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, |
@@ -1009,6 +1102,44 @@ static SOC_ENUM_SINGLE_DECL( | |||
1009 | static const struct snd_kcontrol_new rt5645_if1_adc_in_mux = | 1102 | static const struct snd_kcontrol_new rt5645_if1_adc_in_mux = |
1010 | SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum); | 1103 | SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum); |
1011 | 1104 | ||
1105 | /* MX-2d [3] [2] */ | ||
1106 | static const char * const rt5650_a_dac1_src[] = { | ||
1107 | "DAC1", "Stereo DAC Mixer" | ||
1108 | }; | ||
1109 | |||
1110 | static SOC_ENUM_SINGLE_DECL( | ||
1111 | rt5650_a_dac1_l_enum, RT5650_A_DAC_SOUR, | ||
1112 | RT5650_A_DAC1_L_IN_SFT, rt5650_a_dac1_src); | ||
1113 | |||
1114 | static const struct snd_kcontrol_new rt5650_a_dac1_l_mux = | ||
1115 | SOC_DAPM_ENUM("A DAC1 L source", rt5650_a_dac1_l_enum); | ||
1116 | |||
1117 | static SOC_ENUM_SINGLE_DECL( | ||
1118 | rt5650_a_dac1_r_enum, RT5650_A_DAC_SOUR, | ||
1119 | RT5650_A_DAC1_R_IN_SFT, rt5650_a_dac1_src); | ||
1120 | |||
1121 | static const struct snd_kcontrol_new rt5650_a_dac1_r_mux = | ||
1122 | SOC_DAPM_ENUM("A DAC1 R source", rt5650_a_dac1_r_enum); | ||
1123 | |||
1124 | /* MX-2d [1] [0] */ | ||
1125 | static const char * const rt5650_a_dac2_src[] = { | ||
1126 | "Stereo DAC Mixer", "Mono DAC Mixer" | ||
1127 | }; | ||
1128 | |||
1129 | static SOC_ENUM_SINGLE_DECL( | ||
1130 | rt5650_a_dac2_l_enum, RT5650_A_DAC_SOUR, | ||
1131 | RT5650_A_DAC2_L_IN_SFT, rt5650_a_dac2_src); | ||
1132 | |||
1133 | static const struct snd_kcontrol_new rt5650_a_dac2_l_mux = | ||
1134 | SOC_DAPM_ENUM("A DAC2 L source", rt5650_a_dac2_l_enum); | ||
1135 | |||
1136 | static SOC_ENUM_SINGLE_DECL( | ||
1137 | rt5650_a_dac2_r_enum, RT5650_A_DAC_SOUR, | ||
1138 | RT5650_A_DAC2_R_IN_SFT, rt5650_a_dac2_src); | ||
1139 | |||
1140 | static const struct snd_kcontrol_new rt5650_a_dac2_r_mux = | ||
1141 | SOC_DAPM_ENUM("A DAC2 R source", rt5650_a_dac2_r_enum); | ||
1142 | |||
1012 | /* MX-2F [13:12] */ | 1143 | /* MX-2F [13:12] */ |
1013 | static const char * const rt5645_if2_adc_in_src[] = { | 1144 | static const char * const rt5645_if2_adc_in_src[] = { |
1014 | "IF_ADC1", "IF_ADC2", "VAD_ADC" | 1145 | "IF_ADC1", "IF_ADC2", "VAD_ADC" |
@@ -1153,11 +1284,16 @@ static int rt5645_hp_event(struct snd_soc_dapm_widget *w, | |||
1153 | case SND_SOC_DAPM_POST_PMU: | 1284 | case SND_SOC_DAPM_POST_PMU: |
1154 | hp_amp_power(codec, 1); | 1285 | hp_amp_power(codec, 1); |
1155 | /* headphone unmute sequence */ | 1286 | /* headphone unmute sequence */ |
1156 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, RT5645_CP_FQ1_MASK | | 1287 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { |
1157 | RT5645_CP_FQ2_MASK | RT5645_CP_FQ3_MASK, | 1288 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); |
1158 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) | | 1289 | } else { |
1159 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | 1290 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, |
1160 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT)); | 1291 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | |
1292 | RT5645_CP_FQ3_MASK, | ||
1293 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) | | ||
1294 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | ||
1295 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT)); | ||
1296 | } | ||
1161 | regmap_write(rt5645->regmap, | 1297 | regmap_write(rt5645->regmap, |
1162 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); | 1298 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); |
1163 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | 1299 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, |
@@ -1177,12 +1313,16 @@ static int rt5645_hp_event(struct snd_soc_dapm_widget *w, | |||
1177 | 1313 | ||
1178 | case SND_SOC_DAPM_PRE_PMD: | 1314 | case SND_SOC_DAPM_PRE_PMD: |
1179 | /* headphone mute sequence */ | 1315 | /* headphone mute sequence */ |
1180 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, | 1316 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { |
1181 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | | 1317 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); |
1182 | RT5645_CP_FQ3_MASK, | 1318 | } else { |
1183 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) | | 1319 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, |
1184 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | 1320 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | |
1185 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT)); | 1321 | RT5645_CP_FQ3_MASK, |
1322 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) | | ||
1323 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | ||
1324 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT)); | ||
1325 | } | ||
1186 | regmap_write(rt5645->regmap, | 1326 | regmap_write(rt5645->regmap, |
1187 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); | 1327 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); |
1188 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | 1328 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, |
@@ -1576,6 +1716,17 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { | |||
1576 | SND_SOC_DAPM_OUTPUT("SPOR"), | 1716 | SND_SOC_DAPM_OUTPUT("SPOR"), |
1577 | }; | 1717 | }; |
1578 | 1718 | ||
1719 | static const struct snd_soc_dapm_widget rt5650_specific_dapm_widgets[] = { | ||
1720 | SND_SOC_DAPM_MUX("A DAC1 L Mux", SND_SOC_NOPM, | ||
1721 | 0, 0, &rt5650_a_dac1_l_mux), | ||
1722 | SND_SOC_DAPM_MUX("A DAC1 R Mux", SND_SOC_NOPM, | ||
1723 | 0, 0, &rt5650_a_dac1_r_mux), | ||
1724 | SND_SOC_DAPM_MUX("A DAC2 L Mux", SND_SOC_NOPM, | ||
1725 | 0, 0, &rt5650_a_dac2_l_mux), | ||
1726 | SND_SOC_DAPM_MUX("A DAC2 R Mux", SND_SOC_NOPM, | ||
1727 | 0, 0, &rt5650_a_dac2_r_mux), | ||
1728 | }; | ||
1729 | |||
1579 | static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | 1730 | static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { |
1580 | { "adc stereo1 filter", NULL, "ADC STO1 ASRC", is_using_asrc }, | 1731 | { "adc stereo1 filter", NULL, "ADC STO1 ASRC", is_using_asrc }, |
1581 | { "adc stereo2 filter", NULL, "ADC STO2 ASRC", is_using_asrc }, | 1732 | { "adc stereo2 filter", NULL, "ADC STO2 ASRC", is_using_asrc }, |
@@ -1781,13 +1932,9 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | |||
1781 | { "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, | 1932 | { "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, |
1782 | { "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" }, | 1933 | { "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" }, |
1783 | 1934 | ||
1784 | { "DAC L1", NULL, "Stereo DAC MIXL" }, | ||
1785 | { "DAC L1", NULL, "PLL1", is_sys_clk_from_pll }, | 1935 | { "DAC L1", NULL, "PLL1", is_sys_clk_from_pll }, |
1786 | { "DAC R1", NULL, "Stereo DAC MIXR" }, | ||
1787 | { "DAC R1", NULL, "PLL1", is_sys_clk_from_pll }, | 1936 | { "DAC R1", NULL, "PLL1", is_sys_clk_from_pll }, |
1788 | { "DAC L2", NULL, "Mono DAC MIXL" }, | ||
1789 | { "DAC L2", NULL, "PLL1", is_sys_clk_from_pll }, | 1937 | { "DAC L2", NULL, "PLL1", is_sys_clk_from_pll }, |
1790 | { "DAC R2", NULL, "Mono DAC MIXR" }, | ||
1791 | { "DAC R2", NULL, "PLL1", is_sys_clk_from_pll }, | 1938 | { "DAC R2", NULL, "PLL1", is_sys_clk_from_pll }, |
1792 | 1939 | ||
1793 | { "SPK MIXL", "BST1 Switch", "BST1" }, | 1940 | { "SPK MIXL", "BST1 Switch", "BST1" }, |
@@ -1876,6 +2023,30 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | |||
1876 | { "SPOR", NULL, "SPK amp" }, | 2023 | { "SPOR", NULL, "SPK amp" }, |
1877 | }; | 2024 | }; |
1878 | 2025 | ||
2026 | static const struct snd_soc_dapm_route rt5650_specific_dapm_routes[] = { | ||
2027 | { "A DAC1 L Mux", "DAC1", "DAC1 MIXL"}, | ||
2028 | { "A DAC1 L Mux", "Stereo DAC Mixer", "Stereo DAC MIXL"}, | ||
2029 | { "A DAC1 R Mux", "DAC1", "DAC1 MIXR"}, | ||
2030 | { "A DAC1 R Mux", "Stereo DAC Mixer", "Stereo DAC MIXR"}, | ||
2031 | |||
2032 | { "A DAC2 L Mux", "Stereo DAC Mixer", "Stereo DAC MIXL"}, | ||
2033 | { "A DAC2 L Mux", "Mono DAC Mixer", "Mono DAC MIXL"}, | ||
2034 | { "A DAC2 R Mux", "Stereo DAC Mixer", "Stereo DAC MIXR"}, | ||
2035 | { "A DAC2 R Mux", "Mono DAC Mixer", "Mono DAC MIXR"}, | ||
2036 | |||
2037 | { "DAC L1", NULL, "A DAC1 L Mux" }, | ||
2038 | { "DAC R1", NULL, "A DAC1 R Mux" }, | ||
2039 | { "DAC L2", NULL, "A DAC2 L Mux" }, | ||
2040 | { "DAC R2", NULL, "A DAC2 R Mux" }, | ||
2041 | }; | ||
2042 | |||
2043 | static const struct snd_soc_dapm_route rt5645_specific_dapm_routes[] = { | ||
2044 | { "DAC L1", NULL, "Stereo DAC MIXL" }, | ||
2045 | { "DAC R1", NULL, "Stereo DAC MIXR" }, | ||
2046 | { "DAC L2", NULL, "Mono DAC MIXL" }, | ||
2047 | { "DAC R2", NULL, "Mono DAC MIXR" }, | ||
2048 | }; | ||
2049 | |||
1879 | static int rt5645_hw_params(struct snd_pcm_substream *substream, | 2050 | static int rt5645_hw_params(struct snd_pcm_substream *substream, |
1880 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 2051 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
1881 | { | 2052 | { |
@@ -2295,6 +2466,22 @@ static int rt5645_probe(struct snd_soc_codec *codec) | |||
2295 | 2466 | ||
2296 | rt5645->codec = codec; | 2467 | rt5645->codec = codec; |
2297 | 2468 | ||
2469 | switch (rt5645->codec_type) { | ||
2470 | case CODEC_TYPE_RT5645: | ||
2471 | snd_soc_dapm_add_routes(&codec->dapm, | ||
2472 | rt5645_specific_dapm_routes, | ||
2473 | ARRAY_SIZE(rt5645_specific_dapm_routes)); | ||
2474 | break; | ||
2475 | case CODEC_TYPE_RT5650: | ||
2476 | snd_soc_dapm_new_controls(&codec->dapm, | ||
2477 | rt5650_specific_dapm_widgets, | ||
2478 | ARRAY_SIZE(rt5650_specific_dapm_widgets)); | ||
2479 | snd_soc_dapm_add_routes(&codec->dapm, | ||
2480 | rt5650_specific_dapm_routes, | ||
2481 | ARRAY_SIZE(rt5650_specific_dapm_routes)); | ||
2482 | break; | ||
2483 | } | ||
2484 | |||
2298 | rt5645_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2485 | rt5645_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2299 | 2486 | ||
2300 | snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200); | 2487 | snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200); |
@@ -2426,6 +2613,7 @@ static const struct regmap_config rt5645_regmap = { | |||
2426 | 2613 | ||
2427 | static const struct i2c_device_id rt5645_i2c_id[] = { | 2614 | static const struct i2c_device_id rt5645_i2c_id[] = { |
2428 | { "rt5645", 0 }, | 2615 | { "rt5645", 0 }, |
2616 | { "rt5650", 0 }, | ||
2429 | { } | 2617 | { } |
2430 | }; | 2618 | }; |
2431 | MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); | 2619 | MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); |
@@ -2458,9 +2646,18 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2458 | } | 2646 | } |
2459 | 2647 | ||
2460 | regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val); | 2648 | regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val); |
2461 | if (val != RT5645_DEVICE_ID) { | 2649 | |
2650 | switch (val) { | ||
2651 | case RT5645_DEVICE_ID: | ||
2652 | rt5645->codec_type = CODEC_TYPE_RT5645; | ||
2653 | break; | ||
2654 | case RT5650_DEVICE_ID: | ||
2655 | rt5645->codec_type = CODEC_TYPE_RT5650; | ||
2656 | break; | ||
2657 | default: | ||
2462 | dev_err(&i2c->dev, | 2658 | dev_err(&i2c->dev, |
2463 | "Device with ID register %x is not rt5645\n", val); | 2659 | "Device with ID register %x is not rt5645 or rt5650\n", |
2660 | val); | ||
2464 | return -ENODEV; | 2661 | return -ENODEV; |
2465 | } | 2662 | } |
2466 | 2663 | ||
@@ -2471,6 +2668,14 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2471 | if (ret != 0) | 2668 | if (ret != 0) |
2472 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); | 2669 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); |
2473 | 2670 | ||
2671 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { | ||
2672 | ret = regmap_register_patch(rt5645->regmap, rt5650_init_list, | ||
2673 | ARRAY_SIZE(rt5650_init_list)); | ||
2674 | if (ret != 0) | ||
2675 | dev_warn(&i2c->dev, "Apply rt5650 patch failed: %d\n", | ||
2676 | ret); | ||
2677 | } | ||
2678 | |||
2474 | if (rt5645->pdata.in2_diff) | 2679 | if (rt5645->pdata.in2_diff) |
2475 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, | 2680 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, |
2476 | RT5645_IN_DF2, RT5645_IN_DF2); | 2681 | RT5645_IN_DF2, RT5645_IN_DF2); |
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index a815e36a2bdb..dbfd98c22f4d 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h | |||
@@ -47,6 +47,7 @@ | |||
47 | #define RT5645_STO_DAC_MIXER 0x2a | 47 | #define RT5645_STO_DAC_MIXER 0x2a |
48 | #define RT5645_MONO_DAC_MIXER 0x2b | 48 | #define RT5645_MONO_DAC_MIXER 0x2b |
49 | #define RT5645_DIG_MIXER 0x2c | 49 | #define RT5645_DIG_MIXER 0x2c |
50 | #define RT5650_A_DAC_SOUR 0x2d | ||
50 | #define RT5645_DIG_INF1_DATA 0x2f | 51 | #define RT5645_DIG_INF1_DATA 0x2f |
51 | /* Mixer - PDM */ | 52 | /* Mixer - PDM */ |
52 | #define RT5645_PDM_OUT_CTRL 0x31 | 53 | #define RT5645_PDM_OUT_CTRL 0x31 |
@@ -150,6 +151,8 @@ | |||
150 | #define RT5645_IL_CMD 0xdb | 151 | #define RT5645_IL_CMD 0xdb |
151 | #define RT5645_IL_CMD2 0xdc | 152 | #define RT5645_IL_CMD2 0xdc |
152 | #define RT5645_IL_CMD3 0xdd | 153 | #define RT5645_IL_CMD3 0xdd |
154 | #define RT5650_4BTN_IL_CMD1 0xdf | ||
155 | #define RT5650_4BTN_IL_CMD2 0xe0 | ||
153 | #define RT5645_DRC1_HL_CTRL1 0xe7 | 156 | #define RT5645_DRC1_HL_CTRL1 0xe7 |
154 | #define RT5645_DRC2_HL_CTRL1 0xe9 | 157 | #define RT5645_DRC2_HL_CTRL1 0xe9 |
155 | #define RT5645_MUTI_DRC_CTRL1 0xea | 158 | #define RT5645_MUTI_DRC_CTRL1 0xea |
@@ -472,6 +475,12 @@ | |||
472 | #define RT5645_DAC_L2_DAC_R_VOL_MASK (0x1 << 4) | 475 | #define RT5645_DAC_L2_DAC_R_VOL_MASK (0x1 << 4) |
473 | #define RT5645_DAC_L2_DAC_R_VOL_SFT 4 | 476 | #define RT5645_DAC_L2_DAC_R_VOL_SFT 4 |
474 | 477 | ||
478 | /* Analog DAC1/2 Input Source Control (0x2d) */ | ||
479 | #define RT5650_A_DAC1_L_IN_SFT 3 | ||
480 | #define RT5650_A_DAC1_R_IN_SFT 2 | ||
481 | #define RT5650_A_DAC2_L_IN_SFT 1 | ||
482 | #define RT5650_A_DAC2_R_IN_SFT 0 | ||
483 | |||
475 | /* Digital Interface Data Control (0x2f) */ | 484 | /* Digital Interface Data Control (0x2f) */ |
476 | #define RT5645_IF1_ADC2_IN_SEL (0x1 << 15) | 485 | #define RT5645_IF1_ADC2_IN_SEL (0x1 << 15) |
477 | #define RT5645_IF1_ADC2_IN_SFT 15 | 486 | #define RT5645_IF1_ADC2_IN_SFT 15 |
@@ -1111,50 +1120,27 @@ | |||
1111 | #define RT5645_DMIC_2_M_NOR (0x0 << 8) | 1120 | #define RT5645_DMIC_2_M_NOR (0x0 << 8) |
1112 | #define RT5645_DMIC_2_M_ASYN (0x1 << 8) | 1121 | #define RT5645_DMIC_2_M_ASYN (0x1 << 8) |
1113 | 1122 | ||
1123 | /* ASRC clock source selection (0x84, 0x85) */ | ||
1124 | #define RT5645_CLK_SEL_SYS (0x0) | ||
1125 | #define RT5645_CLK_SEL_I2S1_ASRC (0x1) | ||
1126 | #define RT5645_CLK_SEL_I2S2_ASRC (0x2) | ||
1127 | #define RT5645_CLK_SEL_SYS2 (0x5) | ||
1128 | |||
1114 | /* ASRC Control 2 (0x84) */ | 1129 | /* ASRC Control 2 (0x84) */ |
1115 | #define RT5645_MDA_L_M_MASK (0x1 << 15) | 1130 | #define RT5645_DA_STO_CLK_SEL_MASK (0xf << 12) |
1116 | #define RT5645_MDA_L_M_SFT 15 | 1131 | #define RT5645_DA_STO_CLK_SEL_SFT 12 |
1117 | #define RT5645_MDA_L_M_NOR (0x0 << 15) | 1132 | #define RT5645_DA_MONOL_CLK_SEL_MASK (0xf << 8) |
1118 | #define RT5645_MDA_L_M_ASYN (0x1 << 15) | 1133 | #define RT5645_DA_MONOL_CLK_SEL_SFT 8 |
1119 | #define RT5645_MDA_R_M_MASK (0x1 << 14) | 1134 | #define RT5645_DA_MONOR_CLK_SEL_MASK (0xf << 4) |
1120 | #define RT5645_MDA_R_M_SFT 14 | 1135 | #define RT5645_DA_MONOR_CLK_SEL_SFT 4 |
1121 | #define RT5645_MDA_R_M_NOR (0x0 << 14) | 1136 | #define RT5645_AD_STO1_CLK_SEL_MASK (0xf << 0) |
1122 | #define RT5645_MDA_R_M_ASYN (0x1 << 14) | 1137 | #define RT5645_AD_STO1_CLK_SEL_SFT 0 |
1123 | #define RT5645_MAD_L_M_MASK (0x1 << 13) | ||
1124 | #define RT5645_MAD_L_M_SFT 13 | ||
1125 | #define RT5645_MAD_L_M_NOR (0x0 << 13) | ||
1126 | #define RT5645_MAD_L_M_ASYN (0x1 << 13) | ||
1127 | #define RT5645_MAD_R_M_MASK (0x1 << 12) | ||
1128 | #define RT5645_MAD_R_M_SFT 12 | ||
1129 | #define RT5645_MAD_R_M_NOR (0x0 << 12) | ||
1130 | #define RT5645_MAD_R_M_ASYN (0x1 << 12) | ||
1131 | #define RT5645_ADC_M_MASK (0x1 << 11) | ||
1132 | #define RT5645_ADC_M_SFT 11 | ||
1133 | #define RT5645_ADC_M_NOR (0x0 << 11) | ||
1134 | #define RT5645_ADC_M_ASYN (0x1 << 11) | ||
1135 | #define RT5645_STO_DAC_M_MASK (0x1 << 5) | ||
1136 | #define RT5645_STO_DAC_M_SFT 5 | ||
1137 | #define RT5645_STO_DAC_M_NOR (0x0 << 5) | ||
1138 | #define RT5645_STO_DAC_M_ASYN (0x1 << 5) | ||
1139 | #define RT5645_I2S1_R_D_MASK (0x1 << 4) | ||
1140 | #define RT5645_I2S1_R_D_SFT 4 | ||
1141 | #define RT5645_I2S1_R_D_DIS (0x0 << 4) | ||
1142 | #define RT5645_I2S1_R_D_EN (0x1 << 4) | ||
1143 | #define RT5645_I2S2_R_D_MASK (0x1 << 3) | ||
1144 | #define RT5645_I2S2_R_D_SFT 3 | ||
1145 | #define RT5645_I2S2_R_D_DIS (0x0 << 3) | ||
1146 | #define RT5645_I2S2_R_D_EN (0x1 << 3) | ||
1147 | #define RT5645_PRE_SCLK_MASK (0x3) | ||
1148 | #define RT5645_PRE_SCLK_SFT 0 | ||
1149 | #define RT5645_PRE_SCLK_512 (0x0) | ||
1150 | #define RT5645_PRE_SCLK_1024 (0x1) | ||
1151 | #define RT5645_PRE_SCLK_2048 (0x2) | ||
1152 | 1138 | ||
1153 | /* ASRC Control 3 (0x85) */ | 1139 | /* ASRC Control 3 (0x85) */ |
1154 | #define RT5645_I2S1_RATE_MASK (0xf << 12) | 1140 | #define RT5645_AD_MONOL_CLK_SEL_MASK (0xf << 4) |
1155 | #define RT5645_I2S1_RATE_SFT 12 | 1141 | #define RT5645_AD_MONOL_CLK_SEL_SFT 4 |
1156 | #define RT5645_I2S2_RATE_MASK (0xf << 8) | 1142 | #define RT5645_AD_MONOR_CLK_SEL_MASK (0xf << 0) |
1157 | #define RT5645_I2S2_RATE_SFT 8 | 1143 | #define RT5645_AD_MONOR_CLK_SEL_SFT 0 |
1158 | 1144 | ||
1159 | /* ASRC Control 4 (0x89) */ | 1145 | /* ASRC Control 4 (0x89) */ |
1160 | #define RT5645_I2S1_PD_MASK (0x7 << 12) | 1146 | #define RT5645_I2S1_PD_MASK (0x7 << 12) |
@@ -2175,6 +2161,24 @@ enum { | |||
2175 | RT5645_DMIC_DATA_GPIO11, | 2161 | RT5645_DMIC_DATA_GPIO11, |
2176 | }; | 2162 | }; |
2177 | 2163 | ||
2164 | enum { | ||
2165 | CODEC_TYPE_RT5645, | ||
2166 | CODEC_TYPE_RT5650, | ||
2167 | }; | ||
2168 | |||
2169 | /* filter mask */ | ||
2170 | enum { | ||
2171 | RT5645_DA_STEREO_FILTER = 0x1, | ||
2172 | RT5645_DA_MONO_L_FILTER = (0x1 << 1), | ||
2173 | RT5645_DA_MONO_R_FILTER = (0x1 << 2), | ||
2174 | RT5645_AD_STEREO_FILTER = (0x1 << 3), | ||
2175 | RT5645_AD_MONO_L_FILTER = (0x1 << 4), | ||
2176 | RT5645_AD_MONO_R_FILTER = (0x1 << 5), | ||
2177 | }; | ||
2178 | |||
2179 | int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
2180 | unsigned int filter_mask, unsigned int clk_src); | ||
2181 | |||
2178 | struct rt5645_priv { | 2182 | struct rt5645_priv { |
2179 | struct snd_soc_codec *codec; | 2183 | struct snd_soc_codec *codec; |
2180 | struct rt5645_platform_data pdata; | 2184 | struct rt5645_platform_data pdata; |
@@ -2184,6 +2188,7 @@ struct rt5645_priv { | |||
2184 | struct snd_soc_jack *mic_jack; | 2188 | struct snd_soc_jack *mic_jack; |
2185 | struct delayed_work jack_detect_work; | 2189 | struct delayed_work jack_detect_work; |
2186 | 2190 | ||
2191 | int codec_type; | ||
2187 | int sysclk; | 2192 | int sysclk; |
2188 | int sysclk_src; | 2193 | int sysclk_src; |
2189 | int lrck[RT5645_AIFS]; | 2194 | int lrck[RT5645_AIFS]; |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index f5b054de481e..7b3d6b5992f1 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -592,6 +592,89 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source, | |||
592 | return 0; | 592 | return 0; |
593 | } | 593 | } |
594 | 594 | ||
595 | |||
596 | /** | ||
597 | * rt5670_sel_asrc_clk_src - select ASRC clock source for a set of filters | ||
598 | * @codec: SoC audio codec device. | ||
599 | * @filter_mask: mask of filters. | ||
600 | * @clk_src: clock source | ||
601 | * | ||
602 | * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5670 can | ||
603 | * only support standard 32fs or 64fs i2s format, ASRC should be enabled to | ||
604 | * support special i2s clock format such as Intel's 100fs(100 * sampling rate). | ||
605 | * ASRC function will track i2s clock and generate a corresponding system clock | ||
606 | * for codec. This function provides an API to select the clock source for a | ||
607 | * set of filters specified by the mask. And the codec driver will turn on ASRC | ||
608 | * for these filters if ASRC is selected as their clock source. | ||
609 | */ | ||
610 | int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
611 | unsigned int filter_mask, unsigned int clk_src) | ||
612 | { | ||
613 | unsigned int asrc2_mask = 0, asrc2_value = 0; | ||
614 | unsigned int asrc3_mask = 0, asrc3_value = 0; | ||
615 | |||
616 | if (clk_src > RT5670_CLK_SEL_SYS3) | ||
617 | return -EINVAL; | ||
618 | |||
619 | if (filter_mask & RT5670_DA_STEREO_FILTER) { | ||
620 | asrc2_mask |= RT5670_DA_STO_CLK_SEL_MASK; | ||
621 | asrc2_value = (asrc2_value & ~RT5670_DA_STO_CLK_SEL_MASK) | ||
622 | | (clk_src << RT5670_DA_STO_CLK_SEL_SFT); | ||
623 | } | ||
624 | |||
625 | if (filter_mask & RT5670_DA_MONO_L_FILTER) { | ||
626 | asrc2_mask |= RT5670_DA_MONOL_CLK_SEL_MASK; | ||
627 | asrc2_value = (asrc2_value & ~RT5670_DA_MONOL_CLK_SEL_MASK) | ||
628 | | (clk_src << RT5670_DA_MONOL_CLK_SEL_SFT); | ||
629 | } | ||
630 | |||
631 | if (filter_mask & RT5670_DA_MONO_R_FILTER) { | ||
632 | asrc2_mask |= RT5670_DA_MONOR_CLK_SEL_MASK; | ||
633 | asrc2_value = (asrc2_value & ~RT5670_DA_MONOR_CLK_SEL_MASK) | ||
634 | | (clk_src << RT5670_DA_MONOR_CLK_SEL_SFT); | ||
635 | } | ||
636 | |||
637 | if (filter_mask & RT5670_AD_STEREO_FILTER) { | ||
638 | asrc2_mask |= RT5670_AD_STO1_CLK_SEL_MASK; | ||
639 | asrc2_value = (asrc2_value & ~RT5670_AD_STO1_CLK_SEL_MASK) | ||
640 | | (clk_src << RT5670_AD_STO1_CLK_SEL_SFT); | ||
641 | } | ||
642 | |||
643 | if (filter_mask & RT5670_AD_MONO_L_FILTER) { | ||
644 | asrc3_mask |= RT5670_AD_MONOL_CLK_SEL_MASK; | ||
645 | asrc3_value = (asrc3_value & ~RT5670_AD_MONOL_CLK_SEL_MASK) | ||
646 | | (clk_src << RT5670_AD_MONOL_CLK_SEL_SFT); | ||
647 | } | ||
648 | |||
649 | if (filter_mask & RT5670_AD_MONO_R_FILTER) { | ||
650 | asrc3_mask |= RT5670_AD_MONOR_CLK_SEL_MASK; | ||
651 | asrc3_value = (asrc3_value & ~RT5670_AD_MONOR_CLK_SEL_MASK) | ||
652 | | (clk_src << RT5670_AD_MONOR_CLK_SEL_SFT); | ||
653 | } | ||
654 | |||
655 | if (filter_mask & RT5670_UP_RATE_FILTER) { | ||
656 | asrc3_mask |= RT5670_UP_CLK_SEL_MASK; | ||
657 | asrc3_value = (asrc3_value & ~RT5670_UP_CLK_SEL_MASK) | ||
658 | | (clk_src << RT5670_UP_CLK_SEL_SFT); | ||
659 | } | ||
660 | |||
661 | if (filter_mask & RT5670_DOWN_RATE_FILTER) { | ||
662 | asrc3_mask |= RT5670_DOWN_CLK_SEL_MASK; | ||
663 | asrc3_value = (asrc3_value & ~RT5670_DOWN_CLK_SEL_MASK) | ||
664 | | (clk_src << RT5670_DOWN_CLK_SEL_SFT); | ||
665 | } | ||
666 | |||
667 | if (asrc2_mask) | ||
668 | snd_soc_update_bits(codec, RT5670_ASRC_2, | ||
669 | asrc2_mask, asrc2_value); | ||
670 | |||
671 | if (asrc3_mask) | ||
672 | snd_soc_update_bits(codec, RT5670_ASRC_3, | ||
673 | asrc3_mask, asrc3_value); | ||
674 | return 0; | ||
675 | } | ||
676 | EXPORT_SYMBOL_GPL(rt5670_sel_asrc_clk_src); | ||
677 | |||
595 | /* Digital Mixer */ | 678 | /* Digital Mixer */ |
596 | static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { | 679 | static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { |
597 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, | 680 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, |
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index d11b9c207e26..21f8e18c13c4 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h | |||
@@ -1023,50 +1023,33 @@ | |||
1023 | #define RT5670_DMIC_2_M_NOR (0x0 << 8) | 1023 | #define RT5670_DMIC_2_M_NOR (0x0 << 8) |
1024 | #define RT5670_DMIC_2_M_ASYN (0x1 << 8) | 1024 | #define RT5670_DMIC_2_M_ASYN (0x1 << 8) |
1025 | 1025 | ||
1026 | /* ASRC clock source selection (0x84, 0x85) */ | ||
1027 | #define RT5670_CLK_SEL_SYS (0x0) | ||
1028 | #define RT5670_CLK_SEL_I2S1_ASRC (0x1) | ||
1029 | #define RT5670_CLK_SEL_I2S2_ASRC (0x2) | ||
1030 | #define RT5670_CLK_SEL_I2S3_ASRC (0x3) | ||
1031 | #define RT5670_CLK_SEL_SYS2 (0x5) | ||
1032 | #define RT5670_CLK_SEL_SYS3 (0x6) | ||
1033 | |||
1026 | /* ASRC Control 2 (0x84) */ | 1034 | /* ASRC Control 2 (0x84) */ |
1027 | #define RT5670_MDA_L_M_MASK (0x1 << 15) | 1035 | #define RT5670_DA_STO_CLK_SEL_MASK (0xf << 12) |
1028 | #define RT5670_MDA_L_M_SFT 15 | 1036 | #define RT5670_DA_STO_CLK_SEL_SFT 12 |
1029 | #define RT5670_MDA_L_M_NOR (0x0 << 15) | 1037 | #define RT5670_DA_MONOL_CLK_SEL_MASK (0xf << 8) |
1030 | #define RT5670_MDA_L_M_ASYN (0x1 << 15) | 1038 | #define RT5670_DA_MONOL_CLK_SEL_SFT 8 |
1031 | #define RT5670_MDA_R_M_MASK (0x1 << 14) | 1039 | #define RT5670_DA_MONOR_CLK_SEL_MASK (0xf << 4) |
1032 | #define RT5670_MDA_R_M_SFT 14 | 1040 | #define RT5670_DA_MONOR_CLK_SEL_SFT 4 |
1033 | #define RT5670_MDA_R_M_NOR (0x0 << 14) | 1041 | #define RT5670_AD_STO1_CLK_SEL_MASK (0xf << 0) |
1034 | #define RT5670_MDA_R_M_ASYN (0x1 << 14) | 1042 | #define RT5670_AD_STO1_CLK_SEL_SFT 0 |
1035 | #define RT5670_MAD_L_M_MASK (0x1 << 13) | ||
1036 | #define RT5670_MAD_L_M_SFT 13 | ||
1037 | #define RT5670_MAD_L_M_NOR (0x0 << 13) | ||
1038 | #define RT5670_MAD_L_M_ASYN (0x1 << 13) | ||
1039 | #define RT5670_MAD_R_M_MASK (0x1 << 12) | ||
1040 | #define RT5670_MAD_R_M_SFT 12 | ||
1041 | #define RT5670_MAD_R_M_NOR (0x0 << 12) | ||
1042 | #define RT5670_MAD_R_M_ASYN (0x1 << 12) | ||
1043 | #define RT5670_ADC_M_MASK (0x1 << 11) | ||
1044 | #define RT5670_ADC_M_SFT 11 | ||
1045 | #define RT5670_ADC_M_NOR (0x0 << 11) | ||
1046 | #define RT5670_ADC_M_ASYN (0x1 << 11) | ||
1047 | #define RT5670_STO_DAC_M_MASK (0x1 << 5) | ||
1048 | #define RT5670_STO_DAC_M_SFT 5 | ||
1049 | #define RT5670_STO_DAC_M_NOR (0x0 << 5) | ||
1050 | #define RT5670_STO_DAC_M_ASYN (0x1 << 5) | ||
1051 | #define RT5670_I2S1_R_D_MASK (0x1 << 4) | ||
1052 | #define RT5670_I2S1_R_D_SFT 4 | ||
1053 | #define RT5670_I2S1_R_D_DIS (0x0 << 4) | ||
1054 | #define RT5670_I2S1_R_D_EN (0x1 << 4) | ||
1055 | #define RT5670_I2S2_R_D_MASK (0x1 << 3) | ||
1056 | #define RT5670_I2S2_R_D_SFT 3 | ||
1057 | #define RT5670_I2S2_R_D_DIS (0x0 << 3) | ||
1058 | #define RT5670_I2S2_R_D_EN (0x1 << 3) | ||
1059 | #define RT5670_PRE_SCLK_MASK (0x3) | ||
1060 | #define RT5670_PRE_SCLK_SFT 0 | ||
1061 | #define RT5670_PRE_SCLK_512 (0x0) | ||
1062 | #define RT5670_PRE_SCLK_1024 (0x1) | ||
1063 | #define RT5670_PRE_SCLK_2048 (0x2) | ||
1064 | 1043 | ||
1065 | /* ASRC Control 3 (0x85) */ | 1044 | /* ASRC Control 3 (0x85) */ |
1066 | #define RT5670_I2S1_RATE_MASK (0xf << 12) | 1045 | #define RT5670_UP_CLK_SEL_MASK (0xf << 12) |
1067 | #define RT5670_I2S1_RATE_SFT 12 | 1046 | #define RT5670_UP_CLK_SEL_SFT 12 |
1068 | #define RT5670_I2S2_RATE_MASK (0xf << 8) | 1047 | #define RT5670_DOWN_CLK_SEL_MASK (0xf << 8) |
1069 | #define RT5670_I2S2_RATE_SFT 8 | 1048 | #define RT5670_DOWN_CLK_SEL_SFT 8 |
1049 | #define RT5670_AD_MONOL_CLK_SEL_MASK (0xf << 4) | ||
1050 | #define RT5670_AD_MONOL_CLK_SEL_SFT 4 | ||
1051 | #define RT5670_AD_MONOR_CLK_SEL_MASK (0xf << 0) | ||
1052 | #define RT5670_AD_MONOR_CLK_SEL_SFT 0 | ||
1070 | 1053 | ||
1071 | /* ASRC Control 4 (0x89) */ | 1054 | /* ASRC Control 4 (0x89) */ |
1072 | #define RT5670_I2S1_PD_MASK (0x7 << 12) | 1055 | #define RT5670_I2S1_PD_MASK (0x7 << 12) |
@@ -1983,6 +1966,21 @@ enum { | |||
1983 | RT5670_DMIC_DATA_GPIO5, | 1966 | RT5670_DMIC_DATA_GPIO5, |
1984 | }; | 1967 | }; |
1985 | 1968 | ||
1969 | /* filter mask */ | ||
1970 | enum { | ||
1971 | RT5670_DA_STEREO_FILTER = 0x1, | ||
1972 | RT5670_DA_MONO_L_FILTER = (0x1 << 1), | ||
1973 | RT5670_DA_MONO_R_FILTER = (0x1 << 2), | ||
1974 | RT5670_AD_STEREO_FILTER = (0x1 << 3), | ||
1975 | RT5670_AD_MONO_L_FILTER = (0x1 << 4), | ||
1976 | RT5670_AD_MONO_R_FILTER = (0x1 << 5), | ||
1977 | RT5670_UP_RATE_FILTER = (0x1 << 6), | ||
1978 | RT5670_DOWN_RATE_FILTER = (0x1 << 7), | ||
1979 | }; | ||
1980 | |||
1981 | int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
1982 | unsigned int filter_mask, unsigned int clk_src); | ||
1983 | |||
1986 | struct rt5670_priv { | 1984 | struct rt5670_priv { |
1987 | struct snd_soc_codec *codec; | 1985 | struct snd_soc_codec *codec; |
1988 | struct rt5670_platform_data pdata; | 1986 | struct rt5670_platform_data pdata; |
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 735e2eec52f7..75870c0ea2c9 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -90,7 +90,6 @@ struct spdif_mixer_control { | |||
90 | * @sysclk: system clock for rx clock rate measurement | 90 | * @sysclk: system clock for rx clock rate measurement |
91 | * @dma_params_tx: DMA parameters for transmit channel | 91 | * @dma_params_tx: DMA parameters for transmit channel |
92 | * @dma_params_rx: DMA parameters for receive channel | 92 | * @dma_params_rx: DMA parameters for receive channel |
93 | * @name: driver name | ||
94 | */ | 93 | */ |
95 | struct fsl_spdif_priv { | 94 | struct fsl_spdif_priv { |
96 | struct spdif_mixer_control fsl_spdif_control; | 95 | struct spdif_mixer_control fsl_spdif_control; |
@@ -109,12 +108,8 @@ struct fsl_spdif_priv { | |||
109 | struct clk *sysclk; | 108 | struct clk *sysclk; |
110 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 109 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
111 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 110 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
112 | |||
113 | /* The name space will be allocated dynamically */ | ||
114 | char name[0]; | ||
115 | }; | 111 | }; |
116 | 112 | ||
117 | |||
118 | /* DPLL locked and lock loss interrupt handler */ | 113 | /* DPLL locked and lock loss interrupt handler */ |
119 | static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv) | 114 | static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv) |
120 | { | 115 | { |
@@ -1169,19 +1164,15 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1169 | if (!np) | 1164 | if (!np) |
1170 | return -ENODEV; | 1165 | return -ENODEV; |
1171 | 1166 | ||
1172 | spdif_priv = devm_kzalloc(&pdev->dev, | 1167 | spdif_priv = devm_kzalloc(&pdev->dev, sizeof(*spdif_priv), GFP_KERNEL); |
1173 | sizeof(struct fsl_spdif_priv) + strlen(np->name) + 1, | ||
1174 | GFP_KERNEL); | ||
1175 | if (!spdif_priv) | 1168 | if (!spdif_priv) |
1176 | return -ENOMEM; | 1169 | return -ENOMEM; |
1177 | 1170 | ||
1178 | strcpy(spdif_priv->name, np->name); | ||
1179 | |||
1180 | spdif_priv->pdev = pdev; | 1171 | spdif_priv->pdev = pdev; |
1181 | 1172 | ||
1182 | /* Initialize this copy of the CPU DAI driver structure */ | 1173 | /* Initialize this copy of the CPU DAI driver structure */ |
1183 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); | 1174 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); |
1184 | spdif_priv->cpu_dai_drv.name = spdif_priv->name; | 1175 | spdif_priv->cpu_dai_drv.name = dev_name(&pdev->dev); |
1185 | 1176 | ||
1186 | /* Get the addresses and IRQ */ | 1177 | /* Get the addresses and IRQ */ |
1187 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1178 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1203,7 +1194,7 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1203 | } | 1194 | } |
1204 | 1195 | ||
1205 | ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0, | 1196 | ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0, |
1206 | spdif_priv->name, spdif_priv); | 1197 | dev_name(&pdev->dev), spdif_priv); |
1207 | if (ret) { | 1198 | if (ret) { |
1208 | dev_err(&pdev->dev, "could not claim irq %u\n", irq); | 1199 | dev_err(&pdev->dev, "could not claim irq %u\n", irq); |
1209 | return ret; | 1200 | return ret; |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 65400bef013c..46549de60e50 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -160,7 +160,7 @@ struct fsl_ssi_soc_data { | |||
160 | */ | 160 | */ |
161 | struct fsl_ssi_private { | 161 | struct fsl_ssi_private { |
162 | struct regmap *regs; | 162 | struct regmap *regs; |
163 | unsigned int irq; | 163 | int irq; |
164 | struct snd_soc_dai_driver cpu_dai_drv; | 164 | struct snd_soc_dai_driver cpu_dai_drv; |
165 | 165 | ||
166 | unsigned int dai_fmt; | 166 | unsigned int dai_fmt; |
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index e94704f1b9ee..33da26a12457 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c | |||
@@ -60,6 +60,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) | |||
60 | data->card.dev = &pdev->dev; | 60 | data->card.dev = &pdev->dev; |
61 | data->card.dai_link = &data->dai; | 61 | data->card.dai_link = &data->dai; |
62 | data->card.num_links = 1; | 62 | data->card.num_links = 1; |
63 | data->card.owner = THIS_MODULE; | ||
63 | 64 | ||
64 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | 65 | ret = snd_soc_of_parse_card_name(&data->card, "model"); |
65 | if (ret) | 66 | if (ret) |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index c0813f546d1f..ee03dbdda235 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -110,3 +110,14 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH | |||
110 | platforms with RT5672 audio codec. | 110 | platforms with RT5672 audio codec. |
111 | Say Y if you have such a device | 111 | Say Y if you have such a device |
112 | If unsure select "N". | 112 | If unsure select "N". |
113 | |||
114 | config SND_SOC_INTEL_CHT_BSW_RT5645_MACH | ||
115 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645 codec" | ||
116 | depends on X86_INTEL_LPSS | ||
117 | select SND_SOC_RT5645 | ||
118 | select SND_SST_MFLD_PLATFORM | ||
119 | select SND_SST_IPC_ACPI | ||
120 | help | ||
121 | This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell | ||
122 | platforms with RT5645 audio codec. | ||
123 | If unsure select "N". | ||
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index e928ec385300..a8e53c45c6b6 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -28,6 +28,7 @@ snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o | |||
28 | snd-soc-sst-broadwell-objs := broadwell.o | 28 | snd-soc-sst-broadwell-objs := broadwell.o |
29 | snd-soc-sst-bytcr-dpcm-rt5640-objs := bytcr_dpcm_rt5640.o | 29 | snd-soc-sst-bytcr-dpcm-rt5640-objs := bytcr_dpcm_rt5640.o |
30 | snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o | 30 | snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o |
31 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o | ||
31 | 32 | ||
32 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o | 33 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o |
33 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o | 34 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o |
@@ -35,6 +36,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o | |||
35 | obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o | 36 | obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o |
36 | obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-dpcm-rt5640.o | 37 | obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-dpcm-rt5640.o |
37 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o | 38 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o |
39 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o | ||
38 | 40 | ||
39 | # DSP driver | 41 | # DSP driver |
40 | obj-$(CONFIG_SND_SST_IPC) += sst/ | 42 | obj-$(CONFIG_SND_SST_IPC) += sst/ |
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c index 7cf95d5d5d80..9cf7d01479ad 100644 --- a/sound/soc/intel/broadwell.c +++ b/sound/soc/intel/broadwell.c | |||
@@ -140,8 +140,6 @@ static struct snd_soc_ops broadwell_rt286_ops = { | |||
140 | 140 | ||
141 | static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) | 141 | static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) |
142 | { | 142 | { |
143 | struct snd_soc_codec *codec = rtd->codec; | ||
144 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
145 | struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); | 143 | struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); |
146 | struct sst_hsw *broadwell = pdata->dsp; | 144 | struct sst_hsw *broadwell = pdata->dsp; |
147 | int ret; | 145 | int ret; |
@@ -155,14 +153,6 @@ static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) | |||
155 | return ret; | 153 | return ret; |
156 | } | 154 | } |
157 | 155 | ||
158 | /* always connected - check HP for jack detect */ | ||
159 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | ||
160 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | ||
161 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | ||
162 | snd_soc_dapm_enable_pin(dapm, "Line Jack"); | ||
163 | snd_soc_dapm_enable_pin(dapm, "DMIC1"); | ||
164 | snd_soc_dapm_enable_pin(dapm, "DMIC2"); | ||
165 | |||
166 | return 0; | 156 | return 0; |
167 | } | 157 | } |
168 | 158 | ||
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c index 0cba7830c5e9..354eaad886e1 100644 --- a/sound/soc/intel/byt-rt5640.c +++ b/sound/soc/intel/byt-rt5640.c | |||
@@ -132,7 +132,6 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) | |||
132 | { | 132 | { |
133 | int ret; | 133 | int ret; |
134 | struct snd_soc_codec *codec = runtime->codec; | 134 | struct snd_soc_codec *codec = runtime->codec; |
135 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
136 | struct snd_soc_card *card = runtime->card; | 135 | struct snd_soc_card *card = runtime->card; |
137 | const struct snd_soc_dapm_route *custom_map; | 136 | const struct snd_soc_dapm_route *custom_map; |
138 | int num_routes; | 137 | int num_routes; |
@@ -161,7 +160,7 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) | |||
161 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); | 160 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); |
162 | } | 161 | } |
163 | 162 | ||
164 | ret = snd_soc_dapm_add_routes(dapm, custom_map, num_routes); | 163 | ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); |
165 | if (ret) | 164 | if (ret) |
166 | return ret; | 165 | return ret; |
167 | 166 | ||
@@ -171,13 +170,8 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) | |||
171 | return ret; | 170 | return ret; |
172 | } | 171 | } |
173 | 172 | ||
174 | snd_soc_dapm_ignore_suspend(dapm, "HPOL"); | 173 | snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); |
175 | snd_soc_dapm_ignore_suspend(dapm, "HPOR"); | 174 | snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); |
176 | |||
177 | snd_soc_dapm_ignore_suspend(dapm, "SPOLP"); | ||
178 | snd_soc_dapm_ignore_suspend(dapm, "SPOLN"); | ||
179 | snd_soc_dapm_ignore_suspend(dapm, "SPORP"); | ||
180 | snd_soc_dapm_ignore_suspend(dapm, "SPORN"); | ||
181 | 175 | ||
182 | return ret; | 176 | return ret; |
183 | } | 177 | } |
diff --git a/sound/soc/intel/cht_bsw_rt5645.c b/sound/soc/intel/cht_bsw_rt5645.c new file mode 100644 index 000000000000..bd29617a9ab9 --- /dev/null +++ b/sound/soc/intel/cht_bsw_rt5645.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * cht-bsw-rt5645.c - ASoc Machine driver for Intel Cherryview-based platforms | ||
3 | * Cherrytrail and Braswell, with RT5645 codec. | ||
4 | * | ||
5 | * Copyright (C) 2015 Intel Corp | ||
6 | * Author: Fang, Yang A <yang.a.fang@intel.com> | ||
7 | * N,Harshapriya <harshapriya.n@intel.com> | ||
8 | * This file is modified from cht_bsw_rt5672.c | ||
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; version 2 of the License. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/pcm_params.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/jack.h> | ||
30 | #include "../codecs/rt5645.h" | ||
31 | #include "sst-atom-controls.h" | ||
32 | |||
33 | #define CHT_PLAT_CLK_3_HZ 19200000 | ||
34 | #define CHT_CODEC_DAI "rt5645-aif1" | ||
35 | |||
36 | struct cht_mc_private { | ||
37 | struct snd_soc_jack hp_jack; | ||
38 | struct snd_soc_jack mic_jack; | ||
39 | }; | ||
40 | |||
41 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) | ||
42 | { | ||
43 | int i; | ||
44 | |||
45 | for (i = 0; i < card->num_rtd; i++) { | ||
46 | struct snd_soc_pcm_runtime *rtd; | ||
47 | |||
48 | rtd = card->rtd + i; | ||
49 | if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI, | ||
50 | strlen(CHT_CODEC_DAI))) | ||
51 | return rtd->codec_dai; | ||
52 | } | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | static int platform_clock_control(struct snd_soc_dapm_widget *w, | ||
57 | struct snd_kcontrol *k, int event) | ||
58 | { | ||
59 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
60 | struct snd_soc_card *card = dapm->card; | ||
61 | struct snd_soc_dai *codec_dai; | ||
62 | int ret; | ||
63 | |||
64 | codec_dai = cht_get_codec_dai(card); | ||
65 | if (!codec_dai) { | ||
66 | dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n"); | ||
67 | return -EIO; | ||
68 | } | ||
69 | |||
70 | if (!SND_SOC_DAPM_EVENT_OFF(event)) | ||
71 | return 0; | ||
72 | |||
73 | /* Set codec sysclk source to its internal clock because codec PLL will | ||
74 | * be off when idle and MCLK will also be off by ACPI when codec is | ||
75 | * runtime suspended. Codec needs clock for jack detection and button | ||
76 | * press. | ||
77 | */ | ||
78 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK, | ||
79 | 0, SND_SOC_CLOCK_IN); | ||
80 | if (ret < 0) { | ||
81 | dev_err(card->dev, "can't set codec sysclk: %d\n", ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { | ||
89 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
90 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
91 | SND_SOC_DAPM_MIC("Int Mic", NULL), | ||
92 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
93 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, | ||
94 | platform_clock_control, SND_SOC_DAPM_POST_PMD), | ||
95 | }; | ||
96 | |||
97 | static const struct snd_soc_dapm_route cht_audio_map[] = { | ||
98 | {"IN1P", NULL, "Headset Mic"}, | ||
99 | {"IN1N", NULL, "Headset Mic"}, | ||
100 | {"DMIC L1", NULL, "Int Mic"}, | ||
101 | {"DMIC R1", NULL, "Int Mic"}, | ||
102 | {"Headphone", NULL, "HPOL"}, | ||
103 | {"Headphone", NULL, "HPOR"}, | ||
104 | {"Ext Spk", NULL, "SPOL"}, | ||
105 | {"Ext Spk", NULL, "SPOR"}, | ||
106 | {"AIF1 Playback", NULL, "ssp2 Tx"}, | ||
107 | {"ssp2 Tx", NULL, "codec_out0"}, | ||
108 | {"ssp2 Tx", NULL, "codec_out1"}, | ||
109 | {"codec_in0", NULL, "ssp2 Rx" }, | ||
110 | {"codec_in1", NULL, "ssp2 Rx" }, | ||
111 | {"ssp2 Rx", NULL, "AIF1 Capture"}, | ||
112 | {"Headphone", NULL, "Platform Clock"}, | ||
113 | {"Headset Mic", NULL, "Platform Clock"}, | ||
114 | {"Int Mic", NULL, "Platform Clock"}, | ||
115 | {"Ext Spk", NULL, "Platform Clock"}, | ||
116 | }; | ||
117 | |||
118 | static const struct snd_kcontrol_new cht_mc_controls[] = { | ||
119 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
120 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
121 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
122 | SOC_DAPM_PIN_SWITCH("Ext Spk"), | ||
123 | }; | ||
124 | |||
125 | static int cht_aif1_hw_params(struct snd_pcm_substream *substream, | ||
126 | struct snd_pcm_hw_params *params) | ||
127 | { | ||
128 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
129 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
130 | int ret; | ||
131 | |||
132 | /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ | ||
133 | ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK, | ||
134 | CHT_PLAT_CLK_3_HZ, params_rate(params) * 512); | ||
135 | if (ret < 0) { | ||
136 | dev_err(rtd->dev, "can't set codec pll: %d\n", ret); | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_PLL1, | ||
141 | params_rate(params) * 512, SND_SOC_CLOCK_IN); | ||
142 | if (ret < 0) { | ||
143 | dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | ||
151 | { | ||
152 | int ret; | ||
153 | struct snd_soc_codec *codec = runtime->codec; | ||
154 | struct snd_soc_dai *codec_dai = runtime->codec_dai; | ||
155 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); | ||
156 | |||
157 | /* Select clk_i2s1_asrc as ASRC clock source */ | ||
158 | rt5645_sel_asrc_clk_src(codec, | ||
159 | RT5645_DA_STEREO_FILTER | | ||
160 | RT5645_DA_MONO_L_FILTER | | ||
161 | RT5645_DA_MONO_R_FILTER | | ||
162 | RT5645_AD_STEREO_FILTER, | ||
163 | RT5645_CLK_SEL_I2S1_ASRC); | ||
164 | |||
165 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ | ||
166 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); | ||
167 | if (ret < 0) { | ||
168 | dev_err(runtime->dev, "can't set codec TDM slot %d\n", ret); | ||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | ret = snd_soc_jack_new(codec, "Headphone Jack", | ||
173 | SND_JACK_HEADPHONE, | ||
174 | &ctx->hp_jack); | ||
175 | if (ret) { | ||
176 | dev_err(runtime->dev, "HP jack creation failed %d\n", ret); | ||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | ret = snd_soc_jack_new(codec, "Mic Jack", | ||
181 | SND_JACK_MICROPHONE, | ||
182 | &ctx->mic_jack); | ||
183 | if (ret) { | ||
184 | dev_err(runtime->dev, "Mic jack creation failed %d\n", ret); | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | rt5645_set_jack_detect(codec, &ctx->hp_jack, &ctx->mic_jack); | ||
189 | |||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, | ||
194 | struct snd_pcm_hw_params *params) | ||
195 | { | ||
196 | struct snd_interval *rate = hw_param_interval(params, | ||
197 | SNDRV_PCM_HW_PARAM_RATE); | ||
198 | struct snd_interval *channels = hw_param_interval(params, | ||
199 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
200 | |||
201 | /* The DSP will covert the FE rate to 48k, stereo, 24bits */ | ||
202 | rate->min = rate->max = 48000; | ||
203 | channels->min = channels->max = 2; | ||
204 | |||
205 | /* set SSP2 to 24-bit */ | ||
206 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | ||
207 | SNDRV_PCM_HW_PARAM_FIRST_MASK], | ||
208 | SNDRV_PCM_FORMAT_S24_LE); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static unsigned int rates_48000[] = { | ||
213 | 48000, | ||
214 | }; | ||
215 | |||
216 | static struct snd_pcm_hw_constraint_list constraints_48000 = { | ||
217 | .count = ARRAY_SIZE(rates_48000), | ||
218 | .list = rates_48000, | ||
219 | }; | ||
220 | |||
221 | static int cht_aif1_startup(struct snd_pcm_substream *substream) | ||
222 | { | ||
223 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
224 | SNDRV_PCM_HW_PARAM_RATE, | ||
225 | &constraints_48000); | ||
226 | } | ||
227 | |||
228 | static struct snd_soc_ops cht_aif1_ops = { | ||
229 | .startup = cht_aif1_startup, | ||
230 | }; | ||
231 | |||
232 | static struct snd_soc_ops cht_be_ssp2_ops = { | ||
233 | .hw_params = cht_aif1_hw_params, | ||
234 | }; | ||
235 | |||
236 | static struct snd_soc_dai_link cht_dailink[] = { | ||
237 | [MERR_DPCM_AUDIO] = { | ||
238 | .name = "Audio Port", | ||
239 | .stream_name = "Audio", | ||
240 | .cpu_dai_name = "media-cpu-dai", | ||
241 | .codec_dai_name = "snd-soc-dummy-dai", | ||
242 | .codec_name = "snd-soc-dummy", | ||
243 | .platform_name = "sst-mfld-platform", | ||
244 | .ignore_suspend = 1, | ||
245 | .dynamic = 1, | ||
246 | .dpcm_playback = 1, | ||
247 | .dpcm_capture = 1, | ||
248 | .ops = &cht_aif1_ops, | ||
249 | }, | ||
250 | [MERR_DPCM_COMPR] = { | ||
251 | .name = "Compressed Port", | ||
252 | .stream_name = "Compress", | ||
253 | .cpu_dai_name = "compress-cpu-dai", | ||
254 | .codec_dai_name = "snd-soc-dummy-dai", | ||
255 | .codec_name = "snd-soc-dummy", | ||
256 | .platform_name = "sst-mfld-platform", | ||
257 | }, | ||
258 | /* CODEC<->CODEC link */ | ||
259 | /* back ends */ | ||
260 | { | ||
261 | .name = "SSP2-Codec", | ||
262 | .be_id = 1, | ||
263 | .cpu_dai_name = "ssp2-port", | ||
264 | .platform_name = "sst-mfld-platform", | ||
265 | .no_pcm = 1, | ||
266 | .codec_dai_name = "rt5645-aif1", | ||
267 | .codec_name = "i2c-10EC5645:00", | ||
268 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | ||
269 | | SND_SOC_DAIFMT_CBS_CFS, | ||
270 | .init = cht_codec_init, | ||
271 | .be_hw_params_fixup = cht_codec_fixup, | ||
272 | .ignore_suspend = 1, | ||
273 | .dpcm_playback = 1, | ||
274 | .dpcm_capture = 1, | ||
275 | .ops = &cht_be_ssp2_ops, | ||
276 | }, | ||
277 | }; | ||
278 | |||
279 | /* SoC card */ | ||
280 | static struct snd_soc_card snd_soc_card_cht = { | ||
281 | .name = "chtrt5645", | ||
282 | .dai_link = cht_dailink, | ||
283 | .num_links = ARRAY_SIZE(cht_dailink), | ||
284 | .dapm_widgets = cht_dapm_widgets, | ||
285 | .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets), | ||
286 | .dapm_routes = cht_audio_map, | ||
287 | .num_dapm_routes = ARRAY_SIZE(cht_audio_map), | ||
288 | .controls = cht_mc_controls, | ||
289 | .num_controls = ARRAY_SIZE(cht_mc_controls), | ||
290 | }; | ||
291 | |||
292 | static int snd_cht_mc_probe(struct platform_device *pdev) | ||
293 | { | ||
294 | int ret_val = 0; | ||
295 | struct cht_mc_private *drv; | ||
296 | |||
297 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); | ||
298 | if (!drv) | ||
299 | return -ENOMEM; | ||
300 | |||
301 | snd_soc_card_cht.dev = &pdev->dev; | ||
302 | snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); | ||
303 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); | ||
304 | if (ret_val) { | ||
305 | dev_err(&pdev->dev, | ||
306 | "snd_soc_register_card failed %d\n", ret_val); | ||
307 | return ret_val; | ||
308 | } | ||
309 | platform_set_drvdata(pdev, &snd_soc_card_cht); | ||
310 | return ret_val; | ||
311 | } | ||
312 | |||
313 | static struct platform_driver snd_cht_mc_driver = { | ||
314 | .driver = { | ||
315 | .name = "cht-bsw-rt5645", | ||
316 | .pm = &snd_soc_pm_ops, | ||
317 | }, | ||
318 | .probe = snd_cht_mc_probe, | ||
319 | }; | ||
320 | |||
321 | module_platform_driver(snd_cht_mc_driver) | ||
322 | |||
323 | MODULE_DESCRIPTION("ASoC Intel(R) Braswell Machine driver"); | ||
324 | MODULE_AUTHOR("Fang, Yang A,N,Harshapriya"); | ||
325 | MODULE_LICENSE("GPL v2"); | ||
326 | MODULE_ALIAS("platform:cht-bsw-rt5645"); | ||
diff --git a/sound/soc/intel/cht_bsw_rt5672.c b/sound/soc/intel/cht_bsw_rt5672.c index a406c6104897..ff016621583a 100644 --- a/sound/soc/intel/cht_bsw_rt5672.c +++ b/sound/soc/intel/cht_bsw_rt5672.c | |||
@@ -140,6 +140,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
140 | { | 140 | { |
141 | int ret; | 141 | int ret; |
142 | struct snd_soc_dai *codec_dai = runtime->codec_dai; | 142 | struct snd_soc_dai *codec_dai = runtime->codec_dai; |
143 | struct snd_soc_codec *codec = codec_dai->codec; | ||
143 | 144 | ||
144 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ | 145 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ |
145 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); | 146 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); |
@@ -148,6 +149,19 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
148 | return ret; | 149 | return ret; |
149 | } | 150 | } |
150 | 151 | ||
152 | /* Select codec ASRC clock source to track I2S1 clock, because codec | ||
153 | * is in slave mode and 100fs I2S format (BCLK = 100 * LRCLK) cannot | ||
154 | * be supported by RT5672. Otherwise, ASRC will be disabled and cause | ||
155 | * noise. | ||
156 | */ | ||
157 | rt5670_sel_asrc_clk_src(codec, | ||
158 | RT5670_DA_STEREO_FILTER | ||
159 | | RT5670_DA_MONO_L_FILTER | ||
160 | | RT5670_DA_MONO_R_FILTER | ||
161 | | RT5670_AD_STEREO_FILTER | ||
162 | | RT5670_AD_MONO_L_FILTER | ||
163 | | RT5670_AD_MONO_R_FILTER, | ||
164 | RT5670_CLK_SEL_I2S1_ASRC); | ||
151 | return 0; | 165 | return 0; |
152 | } | 166 | } |
153 | 167 | ||
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c index 3bb6288d8b4d..224c49c9f135 100644 --- a/sound/soc/intel/sst-baytrail-pcm.c +++ b/sound/soc/intel/sst-baytrail-pcm.c | |||
@@ -320,11 +320,6 @@ static struct snd_pcm_ops sst_byt_pcm_ops = { | |||
320 | .mmap = sst_byt_pcm_mmap, | 320 | .mmap = sst_byt_pcm_mmap, |
321 | }; | 321 | }; |
322 | 322 | ||
323 | static void sst_byt_pcm_free(struct snd_pcm *pcm) | ||
324 | { | ||
325 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
326 | } | ||
327 | |||
328 | static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd) | 323 | static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd) |
329 | { | 324 | { |
330 | struct snd_pcm *pcm = rtd->pcm; | 325 | struct snd_pcm *pcm = rtd->pcm; |
@@ -403,7 +398,6 @@ static struct snd_soc_platform_driver byt_soc_platform = { | |||
403 | .remove = sst_byt_pcm_remove, | 398 | .remove = sst_byt_pcm_remove, |
404 | .ops = &sst_byt_pcm_ops, | 399 | .ops = &sst_byt_pcm_ops, |
405 | .pcm_new = sst_byt_pcm_new, | 400 | .pcm_new = sst_byt_pcm_new, |
406 | .pcm_free = sst_byt_pcm_free, | ||
407 | }; | 401 | }; |
408 | 402 | ||
409 | static const struct snd_soc_component_driver byt_dai_component = { | 403 | static const struct snd_soc_component_driver byt_dai_component = { |
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c index 86e410845670..64e94212d2d2 100644 --- a/sound/soc/intel/sst-dsp.c +++ b/sound/soc/intel/sst-dsp.c | |||
@@ -410,8 +410,7 @@ void sst_dsp_free(struct sst_dsp *sst) | |||
410 | if (sst->ops->free) | 410 | if (sst->ops->free) |
411 | sst->ops->free(sst); | 411 | sst->ops->free(sst); |
412 | 412 | ||
413 | if (sst->dma) | 413 | sst_dma_free(sst->dma); |
414 | sst_dma_free(sst->dma); | ||
415 | } | 414 | } |
416 | EXPORT_SYMBOL_GPL(sst_dsp_free); | 415 | EXPORT_SYMBOL_GPL(sst_dsp_free); |
417 | 416 | ||
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index a2ae2c5f2e9f..5f71ef607a57 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c | |||
@@ -791,6 +791,7 @@ int sst_module_alloc_blocks(struct sst_module *module) | |||
791 | struct sst_block_allocator ba; | 791 | struct sst_block_allocator ba; |
792 | int ret; | 792 | int ret; |
793 | 793 | ||
794 | memset(&ba, 0, sizeof(ba)); | ||
794 | ba.size = module->size; | 795 | ba.size = module->size; |
795 | ba.type = module->type; | 796 | ba.type = module->type; |
796 | ba.offset = module->offset; | 797 | ba.offset = module->offset; |
@@ -864,6 +865,7 @@ int sst_module_runtime_alloc_blocks(struct sst_module_runtime *runtime, | |||
864 | if (module->persistent_size == 0) | 865 | if (module->persistent_size == 0) |
865 | return 0; | 866 | return 0; |
866 | 867 | ||
868 | memset(&ba, 0, sizeof(ba)); | ||
867 | ba.size = module->persistent_size; | 869 | ba.size = module->persistent_size; |
868 | ba.type = SST_MEM_DRAM; | 870 | ba.type = SST_MEM_DRAM; |
869 | 871 | ||
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c index 57039b00efc2..c42ffae5fe9f 100644 --- a/sound/soc/intel/sst-haswell-dsp.c +++ b/sound/soc/intel/sst-haswell-dsp.c | |||
@@ -306,7 +306,7 @@ static void hsw_reset(struct sst_dsp *sst) | |||
306 | static int hsw_set_dsp_D0(struct sst_dsp *sst) | 306 | static int hsw_set_dsp_D0(struct sst_dsp *sst) |
307 | { | 307 | { |
308 | int tries = 10; | 308 | int tries = 10; |
309 | u32 reg; | 309 | u32 reg, fw_dump_bit; |
310 | 310 | ||
311 | /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */ | 311 | /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */ |
312 | reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); | 312 | reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); |
@@ -368,7 +368,9 @@ finish: | |||
368 | can't be accessed, please enable each block before accessing. */ | 368 | can't be accessed, please enable each block before accessing. */ |
369 | reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0); | 369 | reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0); |
370 | reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK; | 370 | reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK; |
371 | writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0); | 371 | /* for D0, always enable the block(DSRAM[0]) used for FW dump */ |
372 | fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT; | ||
373 | writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
372 | 374 | ||
373 | 375 | ||
374 | /* disable DMA finish function for SSP0 & SSP1 */ | 376 | /* disable DMA finish function for SSP0 & SSP1 */ |
@@ -491,6 +493,7 @@ static const struct sst_sram_shift sram_shift[] = { | |||
491 | {SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */ | 493 | {SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */ |
492 | {SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */ | 494 | {SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */ |
493 | }; | 495 | }; |
496 | |||
494 | static u32 hsw_block_get_bit(struct sst_mem_block *block) | 497 | static u32 hsw_block_get_bit(struct sst_mem_block *block) |
495 | { | 498 | { |
496 | u32 bit = 0, shift = 0, index; | 499 | u32 bit = 0, shift = 0, index; |
@@ -587,7 +590,9 @@ static int hsw_block_disable(struct sst_mem_block *block) | |||
587 | 590 | ||
588 | val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); | 591 | val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); |
589 | bit = hsw_block_get_bit(block); | 592 | bit = hsw_block_get_bit(block); |
590 | writel(val | bit, sst->addr.pci_cfg + SST_VDRTCTL0); | 593 | /* don't disable DSRAM[0], keep it always enable for FW dump*/ |
594 | if (bit != (1 << SST_VDRTCL0_DSRAMPGE_SHIFT)) | ||
595 | writel(val | bit, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
591 | 596 | ||
592 | /* wait 18 DSP clock ticks */ | 597 | /* wait 18 DSP clock ticks */ |
593 | udelay(10); | 598 | udelay(10); |
@@ -612,7 +617,7 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
612 | const struct sst_adsp_memregion *region; | 617 | const struct sst_adsp_memregion *region; |
613 | struct device *dev; | 618 | struct device *dev; |
614 | int ret = -ENODEV, i, j, region_count; | 619 | int ret = -ENODEV, i, j, region_count; |
615 | u32 offset, size; | 620 | u32 offset, size, fw_dump_bit; |
616 | 621 | ||
617 | dev = sst->dma_dev; | 622 | dev = sst->dma_dev; |
618 | 623 | ||
@@ -669,9 +674,11 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
669 | } | 674 | } |
670 | } | 675 | } |
671 | 676 | ||
677 | /* always enable the block(DSRAM[0]) used for FW dump */ | ||
678 | fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT; | ||
672 | /* set default power gating control, enable power gating control for all blocks. that is, | 679 | /* set default power gating control, enable power gating control for all blocks. that is, |
673 | can't be accessed, please enable each block before accessing. */ | 680 | can't be accessed, please enable each block before accessing. */ |
674 | writel(0xffffffff, sst->addr.pci_cfg + SST_VDRTCTL0); | 681 | writel(0xffffffff & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0); |
675 | 682 | ||
676 | return 0; | 683 | return 0; |
677 | } | 684 | } |
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 8156cc1accb7..0ab1309ef274 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c | |||
@@ -94,6 +94,8 @@ | |||
94 | /* Mailbox */ | 94 | /* Mailbox */ |
95 | #define IPC_MAX_MAILBOX_BYTES 256 | 95 | #define IPC_MAX_MAILBOX_BYTES 256 |
96 | 96 | ||
97 | #define INVALID_STREAM_HW_ID 0xffffffff | ||
98 | |||
97 | /* Global Message - Types and Replies */ | 99 | /* Global Message - Types and Replies */ |
98 | enum ipc_glb_type { | 100 | enum ipc_glb_type { |
99 | IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ | 101 | IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ |
@@ -275,7 +277,6 @@ struct sst_hsw { | |||
275 | /* FW config */ | 277 | /* FW config */ |
276 | struct sst_hsw_ipc_fw_ready fw_ready; | 278 | struct sst_hsw_ipc_fw_ready fw_ready; |
277 | struct sst_hsw_ipc_fw_version version; | 279 | struct sst_hsw_ipc_fw_version version; |
278 | struct sst_module *scratch; | ||
279 | bool fw_done; | 280 | bool fw_done; |
280 | struct sst_fw *sst_fw; | 281 | struct sst_fw *sst_fw; |
281 | 282 | ||
@@ -337,12 +338,6 @@ static inline u32 msg_get_stage_type(u32 msg) | |||
337 | return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; | 338 | return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; |
338 | } | 339 | } |
339 | 340 | ||
340 | static inline u32 msg_set_stage_type(u32 msg, u32 type) | ||
341 | { | ||
342 | return (msg & ~IPC_STG_TYPE_MASK) + | ||
343 | (type << IPC_STG_TYPE_SHIFT); | ||
344 | } | ||
345 | |||
346 | static inline u32 msg_get_stream_id(u32 msg) | 341 | static inline u32 msg_get_stream_id(u32 msg) |
347 | { | 342 | { |
348 | return (msg & IPC_STR_ID_MASK) >> IPC_STR_ID_SHIFT; | 343 | return (msg & IPC_STR_ID_MASK) >> IPC_STR_ID_SHIFT; |
@@ -969,45 +964,6 @@ int sst_hsw_fw_get_version(struct sst_hsw *hsw, | |||
969 | } | 964 | } |
970 | 965 | ||
971 | /* Mixer Controls */ | 966 | /* Mixer Controls */ |
972 | int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
973 | u32 stage_id, u32 channel) | ||
974 | { | ||
975 | int ret; | ||
976 | |||
977 | ret = sst_hsw_stream_get_volume(hsw, stream, stage_id, channel, | ||
978 | &stream->mute_volume[channel]); | ||
979 | if (ret < 0) | ||
980 | return ret; | ||
981 | |||
982 | ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, 0); | ||
983 | if (ret < 0) { | ||
984 | dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", | ||
985 | stream->reply.stream_hw_id, channel); | ||
986 | return ret; | ||
987 | } | ||
988 | |||
989 | stream->mute[channel] = 1; | ||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
994 | u32 stage_id, u32 channel) | ||
995 | |||
996 | { | ||
997 | int ret; | ||
998 | |||
999 | stream->mute[channel] = 0; | ||
1000 | ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, | ||
1001 | stream->mute_volume[channel]); | ||
1002 | if (ret < 0) { | ||
1003 | dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", | ||
1004 | stream->reply.stream_hw_id, channel); | ||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | return 0; | ||
1009 | } | ||
1010 | |||
1011 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | 967 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, |
1012 | u32 stage_id, u32 channel, u32 *volume) | 968 | u32 stage_id, u32 channel, u32 *volume) |
1013 | { | 969 | { |
@@ -1021,17 +977,6 @@ int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream | |||
1021 | return 0; | 977 | return 0; |
1022 | } | 978 | } |
1023 | 979 | ||
1024 | int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, | ||
1025 | struct sst_hsw_stream *stream, u64 curve_duration, | ||
1026 | enum sst_hsw_volume_curve curve) | ||
1027 | { | ||
1028 | /* curve duration in steps of 100ns */ | ||
1029 | stream->vol_req.curve_duration = curve_duration; | ||
1030 | stream->vol_req.curve_type = curve; | ||
1031 | |||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | /* stream volume */ | 980 | /* stream volume */ |
1036 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | 981 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, |
1037 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) | 982 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) |
@@ -1083,42 +1028,6 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | |||
1083 | return 0; | 1028 | return 0; |
1084 | } | 1029 | } |
1085 | 1030 | ||
1086 | int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel) | ||
1087 | { | ||
1088 | int ret; | ||
1089 | |||
1090 | ret = sst_hsw_mixer_get_volume(hsw, stage_id, channel, | ||
1091 | &hsw->mute_volume[channel]); | ||
1092 | if (ret < 0) | ||
1093 | return ret; | ||
1094 | |||
1095 | ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, 0); | ||
1096 | if (ret < 0) { | ||
1097 | dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", | ||
1098 | channel); | ||
1099 | return ret; | ||
1100 | } | ||
1101 | |||
1102 | hsw->mute[channel] = 1; | ||
1103 | return 0; | ||
1104 | } | ||
1105 | |||
1106 | int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel) | ||
1107 | { | ||
1108 | int ret; | ||
1109 | |||
1110 | ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, | ||
1111 | hsw->mixer_info.volume_register_address[channel]); | ||
1112 | if (ret < 0) { | ||
1113 | dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", | ||
1114 | channel); | ||
1115 | return ret; | ||
1116 | } | ||
1117 | |||
1118 | hsw->mute[channel] = 0; | ||
1119 | return 0; | ||
1120 | } | ||
1121 | |||
1122 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | 1031 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, |
1123 | u32 *volume) | 1032 | u32 *volume) |
1124 | { | 1033 | { |
@@ -1132,16 +1041,6 @@ int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | |||
1132 | return 0; | 1041 | return 0; |
1133 | } | 1042 | } |
1134 | 1043 | ||
1135 | int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, | ||
1136 | u64 curve_duration, enum sst_hsw_volume_curve curve) | ||
1137 | { | ||
1138 | /* curve duration in steps of 100ns */ | ||
1139 | hsw->curve_duration = curve_duration; | ||
1140 | hsw->curve_type = curve; | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | /* global mixer volume */ | 1044 | /* global mixer volume */ |
1146 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | 1045 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, |
1147 | u32 volume) | 1046 | u32 volume) |
@@ -1208,6 +1107,7 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, | |||
1208 | return NULL; | 1107 | return NULL; |
1209 | 1108 | ||
1210 | spin_lock_irqsave(&sst->spinlock, flags); | 1109 | spin_lock_irqsave(&sst->spinlock, flags); |
1110 | stream->reply.stream_hw_id = INVALID_STREAM_HW_ID; | ||
1211 | list_add(&stream->node, &hsw->stream_list); | 1111 | list_add(&stream->node, &hsw->stream_list); |
1212 | stream->notify_position = notify_position; | 1112 | stream->notify_position = notify_position; |
1213 | stream->pdata = data; | 1113 | stream->pdata = data; |
@@ -1449,48 +1349,6 @@ int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | |||
1449 | 1349 | ||
1450 | /* Stream Information - these calls could be inline but we want the IPC | 1350 | /* Stream Information - these calls could be inline but we want the IPC |
1451 | ABI to be opaque to client PCM drivers to cope with any future ABI changes */ | 1351 | ABI to be opaque to client PCM drivers to cope with any future ABI changes */ |
1452 | int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, | ||
1453 | struct sst_hsw_stream *stream) | ||
1454 | { | ||
1455 | return stream->reply.stream_hw_id; | ||
1456 | } | ||
1457 | |||
1458 | int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, | ||
1459 | struct sst_hsw_stream *stream) | ||
1460 | { | ||
1461 | return stream->reply.mixer_hw_id; | ||
1462 | } | ||
1463 | |||
1464 | u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, | ||
1465 | struct sst_hsw_stream *stream) | ||
1466 | { | ||
1467 | return stream->reply.read_position_register_address; | ||
1468 | } | ||
1469 | |||
1470 | u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, | ||
1471 | struct sst_hsw_stream *stream) | ||
1472 | { | ||
1473 | return stream->reply.presentation_position_register_address; | ||
1474 | } | ||
1475 | |||
1476 | u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, | ||
1477 | struct sst_hsw_stream *stream, u32 channel) | ||
1478 | { | ||
1479 | if (channel >= 2) | ||
1480 | return 0; | ||
1481 | |||
1482 | return stream->reply.peak_meter_register_address[channel]; | ||
1483 | } | ||
1484 | |||
1485 | u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, | ||
1486 | struct sst_hsw_stream *stream, u32 channel) | ||
1487 | { | ||
1488 | if (channel >= 2) | ||
1489 | return 0; | ||
1490 | |||
1491 | return stream->reply.volume_register_address[channel]; | ||
1492 | } | ||
1493 | |||
1494 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw) | 1352 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw) |
1495 | { | 1353 | { |
1496 | struct sst_hsw_ipc_stream_info_reply *reply; | 1354 | struct sst_hsw_ipc_stream_info_reply *reply; |
@@ -1628,30 +1486,6 @@ u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, | |||
1628 | return ppos; | 1486 | return ppos; |
1629 | } | 1487 | } |
1630 | 1488 | ||
1631 | int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, | ||
1632 | struct sst_hsw_stream *stream, u32 stage_id, u32 position) | ||
1633 | { | ||
1634 | u32 header; | ||
1635 | int ret; | ||
1636 | |||
1637 | trace_stream_write_position(stream->reply.stream_hw_id, position); | ||
1638 | |||
1639 | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | | ||
1640 | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); | ||
1641 | header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); | ||
1642 | header |= (IPC_STG_SET_WRITE_POSITION << IPC_STG_TYPE_SHIFT); | ||
1643 | header |= (stage_id << IPC_STG_ID_SHIFT); | ||
1644 | stream->wpos.position = position; | ||
1645 | |||
1646 | ret = ipc_tx_message_nowait(hsw, header, &stream->wpos, | ||
1647 | sizeof(stream->wpos)); | ||
1648 | if (ret < 0) | ||
1649 | dev_err(hsw->dev, "error: stream %d set position %d failed\n", | ||
1650 | stream->reply.stream_hw_id, position); | ||
1651 | |||
1652 | return ret; | ||
1653 | } | ||
1654 | |||
1655 | /* physical BE config */ | 1489 | /* physical BE config */ |
1656 | int sst_hsw_device_set_config(struct sst_hsw *hsw, | 1490 | int sst_hsw_device_set_config(struct sst_hsw *hsw, |
1657 | enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, | 1491 | enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, |
@@ -2132,7 +1966,6 @@ void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata) | |||
2132 | dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE, | 1966 | dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE, |
2133 | hsw->dx_context, hsw->dx_context_paddr); | 1967 | hsw->dx_context, hsw->dx_context_paddr); |
2134 | sst_dsp_free(hsw->dsp); | 1968 | sst_dsp_free(hsw->dsp); |
2135 | kfree(hsw->scratch); | ||
2136 | kthread_stop(hsw->tx_thread); | 1969 | kthread_stop(hsw->tx_thread); |
2137 | kfree(hsw->msg); | 1970 | kfree(hsw->msg); |
2138 | } | 1971 | } |
diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h index 138e894ab413..c1ad901342f2 100644 --- a/sound/soc/intel/sst-haswell-ipc.h +++ b/sound/soc/intel/sst-haswell-ipc.h | |||
@@ -376,32 +376,17 @@ int sst_hsw_fw_get_version(struct sst_hsw *hsw, | |||
376 | u32 create_channel_map(enum sst_hsw_channel_config config); | 376 | u32 create_channel_map(enum sst_hsw_channel_config config); |
377 | 377 | ||
378 | /* Stream Mixer Controls - */ | 378 | /* Stream Mixer Controls - */ |
379 | int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
380 | u32 stage_id, u32 channel); | ||
381 | int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
382 | u32 stage_id, u32 channel); | ||
383 | |||
384 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | 379 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, |
385 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume); | 380 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume); |
386 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, | 381 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, |
387 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume); | 382 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume); |
388 | 383 | ||
389 | int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, | ||
390 | struct sst_hsw_stream *stream, u64 curve_duration, | ||
391 | enum sst_hsw_volume_curve curve); | ||
392 | |||
393 | /* Global Mixer Controls - */ | 384 | /* Global Mixer Controls - */ |
394 | int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel); | ||
395 | int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel); | ||
396 | |||
397 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | 385 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, |
398 | u32 volume); | 386 | u32 volume); |
399 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | 387 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, |
400 | u32 *volume); | 388 | u32 *volume); |
401 | 389 | ||
402 | int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, | ||
403 | u64 curve_duration, enum sst_hsw_volume_curve curve); | ||
404 | |||
405 | /* Stream API */ | 390 | /* Stream API */ |
406 | struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, | 391 | struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, |
407 | u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data), | 392 | u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data), |
@@ -440,18 +425,6 @@ int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw, | |||
440 | struct sst_hsw_stream *stream, u32 offset, u32 size); | 425 | struct sst_hsw_stream *stream, u32 offset, u32 size); |
441 | int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, | 426 | int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, |
442 | struct sst_hsw_stream *stream, u32 offset, u32 size); | 427 | struct sst_hsw_stream *stream, u32 offset, u32 size); |
443 | int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, | ||
444 | struct sst_hsw_stream *stream); | ||
445 | int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, | ||
446 | struct sst_hsw_stream *stream); | ||
447 | u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, | ||
448 | struct sst_hsw_stream *stream); | ||
449 | u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, | ||
450 | struct sst_hsw_stream *stream); | ||
451 | u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, | ||
452 | struct sst_hsw_stream *stream, u32 channel); | ||
453 | u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, | ||
454 | struct sst_hsw_stream *stream, u32 channel); | ||
455 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw); | 428 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw); |
456 | 429 | ||
457 | /* Stream ALSA trigger operations */ | 430 | /* Stream ALSA trigger operations */ |
@@ -466,8 +439,6 @@ int sst_hsw_stream_get_read_pos(struct sst_hsw *hsw, | |||
466 | struct sst_hsw_stream *stream, u32 *position); | 439 | struct sst_hsw_stream *stream, u32 *position); |
467 | int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw, | 440 | int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw, |
468 | struct sst_hsw_stream *stream, u32 *position); | 441 | struct sst_hsw_stream *stream, u32 *position); |
469 | int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, | ||
470 | struct sst_hsw_stream *stream, u32 stage_id, u32 position); | ||
471 | u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw, | 442 | u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw, |
472 | struct sst_hsw_stream *stream); | 443 | struct sst_hsw_stream *stream); |
473 | u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, | 444 | u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, |
@@ -481,8 +452,6 @@ int sst_hsw_device_set_config(struct sst_hsw *hsw, | |||
481 | /* DX Config */ | 452 | /* DX Config */ |
482 | int sst_hsw_dx_set_state(struct sst_hsw *hsw, | 453 | int sst_hsw_dx_set_state(struct sst_hsw *hsw, |
483 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx); | 454 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx); |
484 | int sst_hsw_dx_get_state(struct sst_hsw *hsw, u32 item, | ||
485 | u32 *offset, u32 *size, u32 *source); | ||
486 | 455 | ||
487 | /* init */ | 456 | /* init */ |
488 | int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata); | 457 | int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata); |
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 619525200705..78fa01be57f2 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c | |||
@@ -78,7 +78,6 @@ static const u32 volume_map[] = { | |||
78 | #define HSW_PCM_DAI_ID_OFFLOAD0 1 | 78 | #define HSW_PCM_DAI_ID_OFFLOAD0 1 |
79 | #define HSW_PCM_DAI_ID_OFFLOAD1 2 | 79 | #define HSW_PCM_DAI_ID_OFFLOAD1 2 |
80 | #define HSW_PCM_DAI_ID_LOOPBACK 3 | 80 | #define HSW_PCM_DAI_ID_LOOPBACK 3 |
81 | #define HSW_PCM_DAI_ID_CAPTURE 4 | ||
82 | 81 | ||
83 | 82 | ||
84 | static const struct snd_pcm_hardware hsw_pcm_hardware = { | 83 | static const struct snd_pcm_hardware hsw_pcm_hardware = { |
@@ -99,6 +98,7 @@ static const struct snd_pcm_hardware hsw_pcm_hardware = { | |||
99 | 98 | ||
100 | struct hsw_pcm_module_map { | 99 | struct hsw_pcm_module_map { |
101 | int dai_id; | 100 | int dai_id; |
101 | int stream; | ||
102 | enum sst_hsw_module_id mod_id; | 102 | enum sst_hsw_module_id mod_id; |
103 | }; | 103 | }; |
104 | 104 | ||
@@ -119,8 +119,9 @@ struct hsw_pcm_data { | |||
119 | }; | 119 | }; |
120 | 120 | ||
121 | enum hsw_pm_state { | 121 | enum hsw_pm_state { |
122 | HSW_PM_STATE_D3 = 0, | 122 | HSW_PM_STATE_D0 = 0, |
123 | HSW_PM_STATE_D0 = 1, | 123 | HSW_PM_STATE_RTD3 = 1, |
124 | HSW_PM_STATE_D3 = 2, | ||
124 | }; | 125 | }; |
125 | 126 | ||
126 | /* private data for the driver */ | 127 | /* private data for the driver */ |
@@ -135,7 +136,17 @@ struct hsw_priv_data { | |||
135 | struct snd_dma_buffer dmab[HSW_PCM_COUNT][2]; | 136 | struct snd_dma_buffer dmab[HSW_PCM_COUNT][2]; |
136 | 137 | ||
137 | /* DAI data */ | 138 | /* DAI data */ |
138 | struct hsw_pcm_data pcm[HSW_PCM_COUNT]; | 139 | struct hsw_pcm_data pcm[HSW_PCM_COUNT][2]; |
140 | }; | ||
141 | |||
142 | |||
143 | /* static mappings between PCMs and modules - may be dynamic in future */ | ||
144 | static struct hsw_pcm_module_map mod_map[] = { | ||
145 | {HSW_PCM_DAI_ID_SYSTEM, 0, SST_HSW_MODULE_PCM_SYSTEM}, | ||
146 | {HSW_PCM_DAI_ID_OFFLOAD0, 0, SST_HSW_MODULE_PCM}, | ||
147 | {HSW_PCM_DAI_ID_OFFLOAD1, 0, SST_HSW_MODULE_PCM}, | ||
148 | {HSW_PCM_DAI_ID_LOOPBACK, 1, SST_HSW_MODULE_PCM_REFERENCE}, | ||
149 | {HSW_PCM_DAI_ID_SYSTEM, 1, SST_HSW_MODULE_PCM_CAPTURE}, | ||
139 | }; | 150 | }; |
140 | 151 | ||
141 | static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data); | 152 | static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data); |
@@ -168,9 +179,14 @@ static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, | |||
168 | (struct soc_mixer_control *)kcontrol->private_value; | 179 | (struct soc_mixer_control *)kcontrol->private_value; |
169 | struct hsw_priv_data *pdata = | 180 | struct hsw_priv_data *pdata = |
170 | snd_soc_platform_get_drvdata(platform); | 181 | snd_soc_platform_get_drvdata(platform); |
171 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; | 182 | struct hsw_pcm_data *pcm_data; |
172 | struct sst_hsw *hsw = pdata->hsw; | 183 | struct sst_hsw *hsw = pdata->hsw; |
173 | u32 volume; | 184 | u32 volume; |
185 | int dai, stream; | ||
186 | |||
187 | dai = mod_map[mc->reg].dai_id; | ||
188 | stream = mod_map[mc->reg].stream; | ||
189 | pcm_data = &pdata->pcm[dai][stream]; | ||
174 | 190 | ||
175 | mutex_lock(&pcm_data->mutex); | 191 | mutex_lock(&pcm_data->mutex); |
176 | pm_runtime_get_sync(pdata->dev); | 192 | pm_runtime_get_sync(pdata->dev); |
@@ -212,9 +228,14 @@ static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol, | |||
212 | (struct soc_mixer_control *)kcontrol->private_value; | 228 | (struct soc_mixer_control *)kcontrol->private_value; |
213 | struct hsw_priv_data *pdata = | 229 | struct hsw_priv_data *pdata = |
214 | snd_soc_platform_get_drvdata(platform); | 230 | snd_soc_platform_get_drvdata(platform); |
215 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; | 231 | struct hsw_pcm_data *pcm_data; |
216 | struct sst_hsw *hsw = pdata->hsw; | 232 | struct sst_hsw *hsw = pdata->hsw; |
217 | u32 volume; | 233 | u32 volume; |
234 | int dai, stream; | ||
235 | |||
236 | dai = mod_map[mc->reg].dai_id; | ||
237 | stream = mod_map[mc->reg].stream; | ||
238 | pcm_data = &pdata->pcm[dai][stream]; | ||
218 | 239 | ||
219 | mutex_lock(&pcm_data->mutex); | 240 | mutex_lock(&pcm_data->mutex); |
220 | pm_runtime_get_sync(pdata->dev); | 241 | pm_runtime_get_sync(pdata->dev); |
@@ -309,7 +330,7 @@ static const struct snd_kcontrol_new hsw_volume_controls[] = { | |||
309 | ARRAY_SIZE(volume_map) - 1, 0, | 330 | ARRAY_SIZE(volume_map) - 1, 0, |
310 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), | 331 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), |
311 | /* Mic Capture volume */ | 332 | /* Mic Capture volume */ |
312 | SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 0, 0, 8, | 333 | SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8, |
313 | ARRAY_SIZE(volume_map) - 1, 0, | 334 | ARRAY_SIZE(volume_map) - 1, 0, |
314 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), | 335 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), |
315 | }; | 336 | }; |
@@ -353,7 +374,7 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, | |||
353 | struct snd_pcm_runtime *runtime = substream->runtime; | 374 | struct snd_pcm_runtime *runtime = substream->runtime; |
354 | struct hsw_priv_data *pdata = | 375 | struct hsw_priv_data *pdata = |
355 | snd_soc_platform_get_drvdata(rtd->platform); | 376 | snd_soc_platform_get_drvdata(rtd->platform); |
356 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | 377 | struct hsw_pcm_data *pcm_data; |
357 | struct sst_hsw *hsw = pdata->hsw; | 378 | struct sst_hsw *hsw = pdata->hsw; |
358 | struct sst_module *module_data; | 379 | struct sst_module *module_data; |
359 | struct sst_dsp *dsp; | 380 | struct sst_dsp *dsp; |
@@ -362,7 +383,10 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, | |||
362 | enum sst_hsw_stream_path_id path_id; | 383 | enum sst_hsw_stream_path_id path_id; |
363 | u32 rate, bits, map, pages, module_id; | 384 | u32 rate, bits, map, pages, module_id; |
364 | u8 channels; | 385 | u8 channels; |
365 | int ret; | 386 | int ret, dai; |
387 | |||
388 | dai = mod_map[rtd->cpu_dai->id].dai_id; | ||
389 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
366 | 390 | ||
367 | /* check if we are being called a subsequent time */ | 391 | /* check if we are being called a subsequent time */ |
368 | if (pcm_data->allocated) { | 392 | if (pcm_data->allocated) { |
@@ -552,8 +576,12 @@ static int hsw_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
552 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 576 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
553 | struct hsw_priv_data *pdata = | 577 | struct hsw_priv_data *pdata = |
554 | snd_soc_platform_get_drvdata(rtd->platform); | 578 | snd_soc_platform_get_drvdata(rtd->platform); |
555 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | 579 | struct hsw_pcm_data *pcm_data; |
556 | struct sst_hsw *hsw = pdata->hsw; | 580 | struct sst_hsw *hsw = pdata->hsw; |
581 | int dai; | ||
582 | |||
583 | dai = mod_map[rtd->cpu_dai->id].dai_id; | ||
584 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
557 | 585 | ||
558 | switch (cmd) { | 586 | switch (cmd) { |
559 | case SNDRV_PCM_TRIGGER_START: | 587 | case SNDRV_PCM_TRIGGER_START: |
@@ -597,11 +625,16 @@ static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream) | |||
597 | struct snd_pcm_runtime *runtime = substream->runtime; | 625 | struct snd_pcm_runtime *runtime = substream->runtime; |
598 | struct hsw_priv_data *pdata = | 626 | struct hsw_priv_data *pdata = |
599 | snd_soc_platform_get_drvdata(rtd->platform); | 627 | snd_soc_platform_get_drvdata(rtd->platform); |
600 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | 628 | struct hsw_pcm_data *pcm_data; |
601 | struct sst_hsw *hsw = pdata->hsw; | 629 | struct sst_hsw *hsw = pdata->hsw; |
602 | snd_pcm_uframes_t offset; | 630 | snd_pcm_uframes_t offset; |
603 | uint64_t ppos; | 631 | uint64_t ppos; |
604 | u32 position = sst_hsw_get_dsp_position(hsw, pcm_data->stream); | 632 | u32 position; |
633 | int dai; | ||
634 | |||
635 | dai = mod_map[rtd->cpu_dai->id].dai_id; | ||
636 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
637 | position = sst_hsw_get_dsp_position(hsw, pcm_data->stream); | ||
605 | 638 | ||
606 | offset = bytes_to_frames(runtime, position); | 639 | offset = bytes_to_frames(runtime, position); |
607 | ppos = sst_hsw_get_dsp_presentation_position(hsw, pcm_data->stream); | 640 | ppos = sst_hsw_get_dsp_presentation_position(hsw, pcm_data->stream); |
@@ -618,8 +651,10 @@ static int hsw_pcm_open(struct snd_pcm_substream *substream) | |||
618 | snd_soc_platform_get_drvdata(rtd->platform); | 651 | snd_soc_platform_get_drvdata(rtd->platform); |
619 | struct hsw_pcm_data *pcm_data; | 652 | struct hsw_pcm_data *pcm_data; |
620 | struct sst_hsw *hsw = pdata->hsw; | 653 | struct sst_hsw *hsw = pdata->hsw; |
654 | int dai; | ||
621 | 655 | ||
622 | pcm_data = &pdata->pcm[rtd->cpu_dai->id]; | 656 | dai = mod_map[rtd->cpu_dai->id].dai_id; |
657 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
623 | 658 | ||
624 | mutex_lock(&pcm_data->mutex); | 659 | mutex_lock(&pcm_data->mutex); |
625 | pm_runtime_get_sync(pdata->dev); | 660 | pm_runtime_get_sync(pdata->dev); |
@@ -648,9 +683,12 @@ static int hsw_pcm_close(struct snd_pcm_substream *substream) | |||
648 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 683 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
649 | struct hsw_priv_data *pdata = | 684 | struct hsw_priv_data *pdata = |
650 | snd_soc_platform_get_drvdata(rtd->platform); | 685 | snd_soc_platform_get_drvdata(rtd->platform); |
651 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | 686 | struct hsw_pcm_data *pcm_data; |
652 | struct sst_hsw *hsw = pdata->hsw; | 687 | struct sst_hsw *hsw = pdata->hsw; |
653 | int ret; | 688 | int ret, dai; |
689 | |||
690 | dai = mod_map[rtd->cpu_dai->id].dai_id; | ||
691 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
654 | 692 | ||
655 | mutex_lock(&pcm_data->mutex); | 693 | mutex_lock(&pcm_data->mutex); |
656 | ret = sst_hsw_stream_reset(hsw, pcm_data->stream); | 694 | ret = sst_hsw_stream_reset(hsw, pcm_data->stream); |
@@ -685,15 +723,6 @@ static struct snd_pcm_ops hsw_pcm_ops = { | |||
685 | .page = snd_pcm_sgbuf_ops_page, | 723 | .page = snd_pcm_sgbuf_ops_page, |
686 | }; | 724 | }; |
687 | 725 | ||
688 | /* static mappings between PCMs and modules - may be dynamic in future */ | ||
689 | static struct hsw_pcm_module_map mod_map[] = { | ||
690 | {HSW_PCM_DAI_ID_SYSTEM, SST_HSW_MODULE_PCM_SYSTEM}, | ||
691 | {HSW_PCM_DAI_ID_OFFLOAD0, SST_HSW_MODULE_PCM}, | ||
692 | {HSW_PCM_DAI_ID_OFFLOAD1, SST_HSW_MODULE_PCM}, | ||
693 | {HSW_PCM_DAI_ID_LOOPBACK, SST_HSW_MODULE_PCM_REFERENCE}, | ||
694 | {HSW_PCM_DAI_ID_CAPTURE, SST_HSW_MODULE_PCM_CAPTURE}, | ||
695 | }; | ||
696 | |||
697 | static int hsw_pcm_create_modules(struct hsw_priv_data *pdata) | 726 | static int hsw_pcm_create_modules(struct hsw_priv_data *pdata) |
698 | { | 727 | { |
699 | struct sst_hsw *hsw = pdata->hsw; | 728 | struct sst_hsw *hsw = pdata->hsw; |
@@ -701,7 +730,7 @@ static int hsw_pcm_create_modules(struct hsw_priv_data *pdata) | |||
701 | int i; | 730 | int i; |
702 | 731 | ||
703 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { | 732 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
704 | pcm_data = &pdata->pcm[i]; | 733 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
705 | 734 | ||
706 | /* create new runtime module, use same offset if recreated */ | 735 | /* create new runtime module, use same offset if recreated */ |
707 | pcm_data->runtime = sst_hsw_runtime_module_create(hsw, | 736 | pcm_data->runtime = sst_hsw_runtime_module_create(hsw, |
@@ -716,7 +745,7 @@ static int hsw_pcm_create_modules(struct hsw_priv_data *pdata) | |||
716 | 745 | ||
717 | err: | 746 | err: |
718 | for (--i; i >= 0; i--) { | 747 | for (--i; i >= 0; i--) { |
719 | pcm_data = &pdata->pcm[i]; | 748 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
720 | sst_hsw_runtime_module_free(pcm_data->runtime); | 749 | sst_hsw_runtime_module_free(pcm_data->runtime); |
721 | } | 750 | } |
722 | 751 | ||
@@ -729,17 +758,12 @@ static void hsw_pcm_free_modules(struct hsw_priv_data *pdata) | |||
729 | int i; | 758 | int i; |
730 | 759 | ||
731 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { | 760 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
732 | pcm_data = &pdata->pcm[i]; | 761 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
733 | 762 | ||
734 | sst_hsw_runtime_module_free(pcm_data->runtime); | 763 | sst_hsw_runtime_module_free(pcm_data->runtime); |
735 | } | 764 | } |
736 | } | 765 | } |
737 | 766 | ||
738 | static void hsw_pcm_free(struct snd_pcm *pcm) | ||
739 | { | ||
740 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
741 | } | ||
742 | |||
743 | static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) | 767 | static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) |
744 | { | 768 | { |
745 | struct snd_pcm *pcm = rtd->pcm; | 769 | struct snd_pcm *pcm = rtd->pcm; |
@@ -762,7 +786,10 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
762 | return ret; | 786 | return ret; |
763 | } | 787 | } |
764 | } | 788 | } |
765 | priv_data->pcm[rtd->cpu_dai->id].hsw_pcm = pcm; | 789 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) |
790 | priv_data->pcm[rtd->cpu_dai->id][SNDRV_PCM_STREAM_PLAYBACK].hsw_pcm = pcm; | ||
791 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) | ||
792 | priv_data->pcm[rtd->cpu_dai->id][SNDRV_PCM_STREAM_CAPTURE].hsw_pcm = pcm; | ||
766 | 793 | ||
767 | return ret; | 794 | return ret; |
768 | } | 795 | } |
@@ -871,10 +898,9 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform) | |||
871 | /* allocate DSP buffer page tables */ | 898 | /* allocate DSP buffer page tables */ |
872 | for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { | 899 | for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { |
873 | 900 | ||
874 | mutex_init(&priv_data->pcm[i].mutex); | ||
875 | |||
876 | /* playback */ | 901 | /* playback */ |
877 | if (hsw_dais[i].playback.channels_min) { | 902 | if (hsw_dais[i].playback.channels_min) { |
903 | mutex_init(&priv_data->pcm[i][SNDRV_PCM_STREAM_PLAYBACK].mutex); | ||
878 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, | 904 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, |
879 | PAGE_SIZE, &priv_data->dmab[i][0]); | 905 | PAGE_SIZE, &priv_data->dmab[i][0]); |
880 | if (ret < 0) | 906 | if (ret < 0) |
@@ -883,6 +909,7 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform) | |||
883 | 909 | ||
884 | /* capture */ | 910 | /* capture */ |
885 | if (hsw_dais[i].capture.channels_min) { | 911 | if (hsw_dais[i].capture.channels_min) { |
912 | mutex_init(&priv_data->pcm[i][SNDRV_PCM_STREAM_CAPTURE].mutex); | ||
886 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, | 913 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, |
887 | PAGE_SIZE, &priv_data->dmab[i][1]); | 914 | PAGE_SIZE, &priv_data->dmab[i][1]); |
888 | if (ret < 0) | 915 | if (ret < 0) |
@@ -936,7 +963,6 @@ static struct snd_soc_platform_driver hsw_soc_platform = { | |||
936 | .remove = hsw_pcm_remove, | 963 | .remove = hsw_pcm_remove, |
937 | .ops = &hsw_pcm_ops, | 964 | .ops = &hsw_pcm_ops, |
938 | .pcm_new = hsw_pcm_new, | 965 | .pcm_new = hsw_pcm_new, |
939 | .pcm_free = hsw_pcm_free, | ||
940 | }; | 966 | }; |
941 | 967 | ||
942 | static const struct snd_soc_component_driver hsw_dai_component = { | 968 | static const struct snd_soc_component_driver hsw_dai_component = { |
@@ -1010,12 +1036,12 @@ static int hsw_pcm_runtime_suspend(struct device *dev) | |||
1010 | struct hsw_priv_data *pdata = dev_get_drvdata(dev); | 1036 | struct hsw_priv_data *pdata = dev_get_drvdata(dev); |
1011 | struct sst_hsw *hsw = pdata->hsw; | 1037 | struct sst_hsw *hsw = pdata->hsw; |
1012 | 1038 | ||
1013 | if (pdata->pm_state == HSW_PM_STATE_D3) | 1039 | if (pdata->pm_state >= HSW_PM_STATE_RTD3) |
1014 | return 0; | 1040 | return 0; |
1015 | 1041 | ||
1016 | sst_hsw_dsp_runtime_suspend(hsw); | 1042 | sst_hsw_dsp_runtime_suspend(hsw); |
1017 | sst_hsw_dsp_runtime_sleep(hsw); | 1043 | sst_hsw_dsp_runtime_sleep(hsw); |
1018 | pdata->pm_state = HSW_PM_STATE_D3; | 1044 | pdata->pm_state = HSW_PM_STATE_RTD3; |
1019 | 1045 | ||
1020 | return 0; | 1046 | return 0; |
1021 | } | 1047 | } |
@@ -1026,7 +1052,7 @@ static int hsw_pcm_runtime_resume(struct device *dev) | |||
1026 | struct sst_hsw *hsw = pdata->hsw; | 1052 | struct sst_hsw *hsw = pdata->hsw; |
1027 | int ret; | 1053 | int ret; |
1028 | 1054 | ||
1029 | if (pdata->pm_state == HSW_PM_STATE_D0) | 1055 | if (pdata->pm_state != HSW_PM_STATE_RTD3) |
1030 | return 0; | 1056 | return 0; |
1031 | 1057 | ||
1032 | ret = sst_hsw_dsp_load(hsw); | 1058 | ret = sst_hsw_dsp_load(hsw); |
@@ -1066,7 +1092,7 @@ static void hsw_pcm_complete(struct device *dev) | |||
1066 | struct hsw_pcm_data *pcm_data; | 1092 | struct hsw_pcm_data *pcm_data; |
1067 | int i, err; | 1093 | int i, err; |
1068 | 1094 | ||
1069 | if (pdata->pm_state == HSW_PM_STATE_D0) | 1095 | if (pdata->pm_state != HSW_PM_STATE_D3) |
1070 | return; | 1096 | return; |
1071 | 1097 | ||
1072 | err = sst_hsw_dsp_load(hsw); | 1098 | err = sst_hsw_dsp_load(hsw); |
@@ -1081,8 +1107,8 @@ static void hsw_pcm_complete(struct device *dev) | |||
1081 | return; | 1107 | return; |
1082 | } | 1108 | } |
1083 | 1109 | ||
1084 | for (i = 0; i < HSW_PCM_DAI_ID_CAPTURE + 1; i++) { | 1110 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
1085 | pcm_data = &pdata->pcm[i]; | 1111 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
1086 | 1112 | ||
1087 | if (!pcm_data->substream) | 1113 | if (!pcm_data->substream) |
1088 | continue; | 1114 | continue; |
@@ -1114,41 +1140,42 @@ static int hsw_pcm_prepare(struct device *dev) | |||
1114 | 1140 | ||
1115 | if (pdata->pm_state == HSW_PM_STATE_D3) | 1141 | if (pdata->pm_state == HSW_PM_STATE_D3) |
1116 | return 0; | 1142 | return 0; |
1117 | /* suspend all active streams */ | 1143 | else if (pdata->pm_state == HSW_PM_STATE_D0) { |
1118 | for (i = 0; i < HSW_PCM_DAI_ID_CAPTURE + 1; i++) { | 1144 | /* suspend all active streams */ |
1119 | pcm_data = &pdata->pcm[i]; | 1145 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
1146 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; | ||
1147 | |||
1148 | if (!pcm_data->substream) | ||
1149 | continue; | ||
1150 | dev_dbg(dev, "suspending pcm %d\n", i); | ||
1151 | snd_pcm_suspend_all(pcm_data->hsw_pcm); | ||
1152 | |||
1153 | /* We need to wait until the DSP FW stops the streams */ | ||
1154 | msleep(2); | ||
1155 | } | ||
1120 | 1156 | ||
1121 | if (!pcm_data->substream) | 1157 | /* preserve persistent memory */ |
1122 | continue; | 1158 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
1123 | dev_dbg(dev, "suspending pcm %d\n", i); | 1159 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
1124 | snd_pcm_suspend_all(pcm_data->hsw_pcm); | 1160 | |
1161 | if (!pcm_data->substream) | ||
1162 | continue; | ||
1125 | 1163 | ||
1126 | /* We need to wait until the DSP FW stops the streams */ | 1164 | dev_dbg(dev, "saving context pcm %d\n", i); |
1127 | msleep(2); | 1165 | err = sst_module_runtime_save(pcm_data->runtime, |
1166 | &pcm_data->context); | ||
1167 | if (err < 0) | ||
1168 | dev_err(dev, "failed to save context for PCM %d\n", i); | ||
1169 | } | ||
1170 | /* enter D3 state and stall */ | ||
1171 | sst_hsw_dsp_runtime_suspend(hsw); | ||
1172 | /* put the DSP to sleep */ | ||
1173 | sst_hsw_dsp_runtime_sleep(hsw); | ||
1128 | } | 1174 | } |
1129 | 1175 | ||
1130 | snd_soc_suspend(pdata->soc_card->dev); | 1176 | snd_soc_suspend(pdata->soc_card->dev); |
1131 | snd_soc_poweroff(pdata->soc_card->dev); | 1177 | snd_soc_poweroff(pdata->soc_card->dev); |
1132 | 1178 | ||
1133 | /* enter D3 state and stall */ | ||
1134 | sst_hsw_dsp_runtime_suspend(hsw); | ||
1135 | |||
1136 | /* preserve persistent memory */ | ||
1137 | for (i = 0; i < HSW_PCM_DAI_ID_CAPTURE + 1; i++) { | ||
1138 | pcm_data = &pdata->pcm[i]; | ||
1139 | |||
1140 | if (!pcm_data->substream) | ||
1141 | continue; | ||
1142 | |||
1143 | dev_dbg(dev, "saving context pcm %d\n", i); | ||
1144 | err = sst_module_runtime_save(pcm_data->runtime, | ||
1145 | &pcm_data->context); | ||
1146 | if (err < 0) | ||
1147 | dev_err(dev, "failed to save context for PCM %d\n", i); | ||
1148 | } | ||
1149 | |||
1150 | /* put the DSP to sleep */ | ||
1151 | sst_hsw_dsp_runtime_sleep(hsw); | ||
1152 | pdata->pm_state = HSW_PM_STATE_D3; | 1179 | pdata->pm_state = HSW_PM_STATE_D3; |
1153 | 1180 | ||
1154 | return 0; | 1181 | return 0; |
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c index a1a8d9d91539..7523cbef8780 100644 --- a/sound/soc/intel/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/sst-mfld-platform-pcm.c | |||
@@ -643,12 +643,6 @@ static struct snd_pcm_ops sst_platform_ops = { | |||
643 | .pointer = sst_platform_pcm_pointer, | 643 | .pointer = sst_platform_pcm_pointer, |
644 | }; | 644 | }; |
645 | 645 | ||
646 | static void sst_pcm_free(struct snd_pcm *pcm) | ||
647 | { | ||
648 | dev_dbg(pcm->dev, "sst_pcm_free called\n"); | ||
649 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
650 | } | ||
651 | |||
652 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | 646 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) |
653 | { | 647 | { |
654 | struct snd_soc_dai *dai = rtd->cpu_dai; | 648 | struct snd_soc_dai *dai = rtd->cpu_dai; |
@@ -679,7 +673,6 @@ static struct snd_soc_platform_driver sst_soc_platform_drv = { | |||
679 | .ops = &sst_platform_ops, | 673 | .ops = &sst_platform_ops, |
680 | .compr_ops = &sst_platform_compr_ops, | 674 | .compr_ops = &sst_platform_compr_ops, |
681 | .pcm_new = sst_pcm_new, | 675 | .pcm_new = sst_pcm_new, |
682 | .pcm_free = sst_pcm_free, | ||
683 | }; | 676 | }; |
684 | 677 | ||
685 | static const struct snd_soc_component_driver sst_component = { | 678 | static const struct snd_soc_component_driver sst_component = { |
diff --git a/sound/soc/intel/sst/sst_acpi.c b/sound/soc/intel/sst/sst_acpi.c index e541d0e69ea2..b782dfdcdbba 100644 --- a/sound/soc/intel/sst/sst_acpi.c +++ b/sound/soc/intel/sst/sst_acpi.c | |||
@@ -352,6 +352,8 @@ static struct sst_machines sst_acpi_bytcr[] = { | |||
352 | static struct sst_machines sst_acpi_chv[] = { | 352 | static struct sst_machines sst_acpi_chv[] = { |
353 | {"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "intel/fw_sst_22a8.bin", | 353 | {"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "intel/fw_sst_22a8.bin", |
354 | &chv_platform_data }, | 354 | &chv_platform_data }, |
355 | {"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin", | ||
356 | &chv_platform_data }, | ||
355 | {}, | 357 | {}, |
356 | }; | 358 | }; |
357 | 359 | ||
diff --git a/sound/soc/intel/sst/sst_loader.c b/sound/soc/intel/sst/sst_loader.c index b580f96e25e5..7888cd707853 100644 --- a/sound/soc/intel/sst/sst_loader.c +++ b/sound/soc/intel/sst/sst_loader.c | |||
@@ -324,8 +324,7 @@ void sst_firmware_load_cb(const struct firmware *fw, void *context) | |||
324 | 324 | ||
325 | if (ctx->sst_state != SST_RESET || | 325 | if (ctx->sst_state != SST_RESET || |
326 | ctx->fw_in_mem != NULL) { | 326 | ctx->fw_in_mem != NULL) { |
327 | if (fw != NULL) | 327 | release_firmware(fw); |
328 | release_firmware(fw); | ||
329 | mutex_unlock(&ctx->sst_lock); | 328 | mutex_unlock(&ctx->sst_lock); |
330 | return; | 329 | return; |
331 | } | 330 | } |
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index d3d45c6f064f..07f77815a586 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/of.h> | ||
18 | #include <linux/of_device.h> | ||
17 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
19 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
@@ -83,6 +85,8 @@ | |||
83 | #define JZ_AIC_I2S_STATUS_BUSY BIT(2) | 85 | #define JZ_AIC_I2S_STATUS_BUSY BIT(2) |
84 | 86 | ||
85 | #define JZ_AIC_CLK_DIV_MASK 0xf | 87 | #define JZ_AIC_CLK_DIV_MASK 0xf |
88 | #define I2SDIV_DV_SHIFT 8 | ||
89 | #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) | ||
86 | 90 | ||
87 | struct jz4740_i2s { | 91 | struct jz4740_i2s { |
88 | struct resource *mem; | 92 | struct resource *mem; |
@@ -237,10 +241,14 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
237 | { | 241 | { |
238 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 242 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
239 | unsigned int sample_size; | 243 | unsigned int sample_size; |
240 | uint32_t ctrl; | 244 | uint32_t ctrl, div_reg; |
245 | int div; | ||
241 | 246 | ||
242 | ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); | 247 | ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); |
243 | 248 | ||
249 | div_reg = jz4740_i2s_read(i2s, JZ_REG_AIC_CLK_DIV); | ||
250 | div = clk_get_rate(i2s->clk_i2s) / (64 * params_rate(params)); | ||
251 | |||
244 | switch (params_format(params)) { | 252 | switch (params_format(params)) { |
245 | case SNDRV_PCM_FORMAT_S8: | 253 | case SNDRV_PCM_FORMAT_S8: |
246 | sample_size = 0; | 254 | sample_size = 0; |
@@ -264,7 +272,10 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
264 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; | 272 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; |
265 | } | 273 | } |
266 | 274 | ||
275 | div_reg &= ~I2SDIV_DV_MASK; | ||
276 | div_reg |= (div - 1) << I2SDIV_DV_SHIFT; | ||
267 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); | 277 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); |
278 | jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div_reg); | ||
268 | 279 | ||
269 | return 0; | 280 | return 0; |
270 | } | 281 | } |
@@ -415,6 +426,13 @@ static const struct snd_soc_component_driver jz4740_i2s_component = { | |||
415 | .name = "jz4740-i2s", | 426 | .name = "jz4740-i2s", |
416 | }; | 427 | }; |
417 | 428 | ||
429 | #ifdef CONFIG_OF | ||
430 | static const struct of_device_id jz4740_of_matches[] = { | ||
431 | { .compatible = "ingenic,jz4740-i2s" }, | ||
432 | { /* sentinel */ } | ||
433 | }; | ||
434 | #endif | ||
435 | |||
418 | static int jz4740_i2s_dev_probe(struct platform_device *pdev) | 436 | static int jz4740_i2s_dev_probe(struct platform_device *pdev) |
419 | { | 437 | { |
420 | struct jz4740_i2s *i2s; | 438 | struct jz4740_i2s *i2s; |
@@ -455,6 +473,7 @@ static struct platform_driver jz4740_i2s_driver = { | |||
455 | .probe = jz4740_i2s_dev_probe, | 473 | .probe = jz4740_i2s_dev_probe, |
456 | .driver = { | 474 | .driver = { |
457 | .name = "jz4740-i2s", | 475 | .name = "jz4740-i2s", |
476 | .of_match_table = of_match_ptr(jz4740_of_matches) | ||
458 | }, | 477 | }, |
459 | }; | 478 | }; |
460 | 479 | ||