diff options
author | Fang, Yang A <yang.a.fang@intel.com> | 2015-04-23 13:23:02 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-05-04 13:13:59 -0400 |
commit | c4ba51ba1c8f8e9dd51f63069eec88580f0e1d01 (patch) | |
tree | 6d3db2682fabb1222acb658f642726b978e4a387 | |
parent | 17119a4657066ccefd9a530ab1b07073d97776f8 (diff) |
ASoC: Intel: Support rt5650 codec for Cherrytrail & Braswell
rt5650 and rt5645 are similar codec so reuse the cht_bsw_rt5645 driver
Signed-off-by: Fang, Yang A <yang.a.fang@intel.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/intel/Kconfig | 4 | ||||
-rw-r--r-- | sound/soc/intel/boards/cht_bsw_rt5645.c | 93 |
2 files changed, 84 insertions, 13 deletions
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 01b2b53be0b3..4419d760ed68 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -112,14 +112,14 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH | |||
112 | If unsure select "N". | 112 | If unsure select "N". |
113 | 113 | ||
114 | config SND_SOC_INTEL_CHT_BSW_RT5645_MACH | 114 | config SND_SOC_INTEL_CHT_BSW_RT5645_MACH |
115 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645 codec" | 115 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645/5650 codec" |
116 | depends on X86_INTEL_LPSS | 116 | depends on X86_INTEL_LPSS |
117 | select SND_SOC_RT5645 | 117 | select SND_SOC_RT5645 |
118 | select SND_SST_MFLD_PLATFORM | 118 | select SND_SST_MFLD_PLATFORM |
119 | select SND_SST_IPC_ACPI | 119 | select SND_SST_IPC_ACPI |
120 | help | 120 | help |
121 | This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell | 121 | This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell |
122 | platforms with RT5645 audio codec. | 122 | platforms with RT5645/5650 audio codec. |
123 | If unsure select "N". | 123 | If unsure select "N". |
124 | 124 | ||
125 | config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH | 125 | config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH |
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 20a28b22e30f..7d23ead3fd40 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c | |||
@@ -21,6 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/acpi.h> | ||
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
@@ -33,9 +34,16 @@ | |||
33 | #define CHT_PLAT_CLK_3_HZ 19200000 | 34 | #define CHT_PLAT_CLK_3_HZ 19200000 |
34 | #define CHT_CODEC_DAI "rt5645-aif1" | 35 | #define CHT_CODEC_DAI "rt5645-aif1" |
35 | 36 | ||
37 | struct cht_acpi_card { | ||
38 | char *codec_id; | ||
39 | int codec_type; | ||
40 | struct snd_soc_card *soc_card; | ||
41 | }; | ||
42 | |||
36 | struct cht_mc_private { | 43 | struct cht_mc_private { |
37 | struct snd_soc_jack hp_jack; | 44 | struct snd_soc_jack hp_jack; |
38 | struct snd_soc_jack mic_jack; | 45 | struct snd_soc_jack mic_jack; |
46 | struct cht_acpi_card *acpi_card; | ||
39 | }; | 47 | }; |
40 | 48 | ||
41 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) | 49 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) |
@@ -94,7 +102,7 @@ static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { | |||
94 | platform_clock_control, SND_SOC_DAPM_POST_PMD), | 102 | platform_clock_control, SND_SOC_DAPM_POST_PMD), |
95 | }; | 103 | }; |
96 | 104 | ||
97 | static const struct snd_soc_dapm_route cht_audio_map[] = { | 105 | static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = { |
98 | {"IN1P", NULL, "Headset Mic"}, | 106 | {"IN1P", NULL, "Headset Mic"}, |
99 | {"IN1N", NULL, "Headset Mic"}, | 107 | {"IN1N", NULL, "Headset Mic"}, |
100 | {"DMIC L1", NULL, "Int Mic"}, | 108 | {"DMIC L1", NULL, "Int Mic"}, |
@@ -115,6 +123,27 @@ static const struct snd_soc_dapm_route cht_audio_map[] = { | |||
115 | {"Ext Spk", NULL, "Platform Clock"}, | 123 | {"Ext Spk", NULL, "Platform Clock"}, |
116 | }; | 124 | }; |
117 | 125 | ||
126 | static const struct snd_soc_dapm_route cht_rt5650_audio_map[] = { | ||
127 | {"IN1P", NULL, "Headset Mic"}, | ||
128 | {"IN1N", NULL, "Headset Mic"}, | ||
129 | {"DMIC L2", NULL, "Int Mic"}, | ||
130 | {"DMIC R2", NULL, "Int Mic"}, | ||
131 | {"Headphone", NULL, "HPOL"}, | ||
132 | {"Headphone", NULL, "HPOR"}, | ||
133 | {"Ext Spk", NULL, "SPOL"}, | ||
134 | {"Ext Spk", NULL, "SPOR"}, | ||
135 | {"AIF1 Playback", NULL, "ssp2 Tx"}, | ||
136 | {"ssp2 Tx", NULL, "codec_out0"}, | ||
137 | {"ssp2 Tx", NULL, "codec_out1"}, | ||
138 | {"codec_in0", NULL, "ssp2 Rx" }, | ||
139 | {"codec_in1", NULL, "ssp2 Rx" }, | ||
140 | {"ssp2 Rx", NULL, "AIF1 Capture"}, | ||
141 | {"Headphone", NULL, "Platform Clock"}, | ||
142 | {"Headset Mic", NULL, "Platform Clock"}, | ||
143 | {"Int Mic", NULL, "Platform Clock"}, | ||
144 | {"Ext Spk", NULL, "Platform Clock"}, | ||
145 | }; | ||
146 | |||
118 | static const struct snd_kcontrol_new cht_mc_controls[] = { | 147 | static const struct snd_kcontrol_new cht_mc_controls[] = { |
119 | SOC_DAPM_PIN_SWITCH("Headphone"), | 148 | SOC_DAPM_PIN_SWITCH("Headphone"), |
120 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | 149 | SOC_DAPM_PIN_SWITCH("Headset Mic"), |
@@ -239,7 +268,7 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
239 | .codec_dai_name = "snd-soc-dummy-dai", | 268 | .codec_dai_name = "snd-soc-dummy-dai", |
240 | .codec_name = "snd-soc-dummy", | 269 | .codec_name = "snd-soc-dummy", |
241 | .platform_name = "sst-mfld-platform", | 270 | .platform_name = "sst-mfld-platform", |
242 | .ignore_suspend = 1, | 271 | .nonatomic = true, |
243 | .dynamic = 1, | 272 | .dynamic = 1, |
244 | .dpcm_playback = 1, | 273 | .dpcm_playback = 1, |
245 | .dpcm_capture = 1, | 274 | .dpcm_capture = 1, |
@@ -267,7 +296,7 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
267 | | SND_SOC_DAIFMT_CBS_CFS, | 296 | | SND_SOC_DAIFMT_CBS_CFS, |
268 | .init = cht_codec_init, | 297 | .init = cht_codec_init, |
269 | .be_hw_params_fixup = cht_codec_fixup, | 298 | .be_hw_params_fixup = cht_codec_fixup, |
270 | .ignore_suspend = 1, | 299 | .nonatomic = true, |
271 | .dpcm_playback = 1, | 300 | .dpcm_playback = 1, |
272 | .dpcm_capture = 1, | 301 | .dpcm_capture = 1, |
273 | .ops = &cht_be_ssp2_ops, | 302 | .ops = &cht_be_ssp2_ops, |
@@ -275,43 +304,85 @@ static struct snd_soc_dai_link cht_dailink[] = { | |||
275 | }; | 304 | }; |
276 | 305 | ||
277 | /* SoC card */ | 306 | /* SoC card */ |
278 | static struct snd_soc_card snd_soc_card_cht = { | 307 | static struct snd_soc_card snd_soc_card_chtrt5645 = { |
279 | .name = "chtrt5645", | 308 | .name = "chtrt5645", |
280 | .dai_link = cht_dailink, | 309 | .dai_link = cht_dailink, |
281 | .num_links = ARRAY_SIZE(cht_dailink), | 310 | .num_links = ARRAY_SIZE(cht_dailink), |
282 | .dapm_widgets = cht_dapm_widgets, | 311 | .dapm_widgets = cht_dapm_widgets, |
283 | .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets), | 312 | .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets), |
284 | .dapm_routes = cht_audio_map, | 313 | .dapm_routes = cht_rt5645_audio_map, |
285 | .num_dapm_routes = ARRAY_SIZE(cht_audio_map), | 314 | .num_dapm_routes = ARRAY_SIZE(cht_rt5645_audio_map), |
286 | .controls = cht_mc_controls, | 315 | .controls = cht_mc_controls, |
287 | .num_controls = ARRAY_SIZE(cht_mc_controls), | 316 | .num_controls = ARRAY_SIZE(cht_mc_controls), |
288 | }; | 317 | }; |
289 | 318 | ||
319 | static struct snd_soc_card snd_soc_card_chtrt5650 = { | ||
320 | .name = "chtrt5650", | ||
321 | .dai_link = cht_dailink, | ||
322 | .num_links = ARRAY_SIZE(cht_dailink), | ||
323 | .dapm_widgets = cht_dapm_widgets, | ||
324 | .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets), | ||
325 | .dapm_routes = cht_rt5650_audio_map, | ||
326 | .num_dapm_routes = ARRAY_SIZE(cht_rt5650_audio_map), | ||
327 | .controls = cht_mc_controls, | ||
328 | .num_controls = ARRAY_SIZE(cht_mc_controls), | ||
329 | }; | ||
330 | |||
331 | static struct cht_acpi_card snd_soc_cards[] = { | ||
332 | {"10EC5645", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645}, | ||
333 | {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650}, | ||
334 | }; | ||
335 | |||
336 | static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level, | ||
337 | void *context, void **ret) | ||
338 | { | ||
339 | *(bool *)context = true; | ||
340 | return AE_OK; | ||
341 | } | ||
342 | |||
290 | static int snd_cht_mc_probe(struct platform_device *pdev) | 343 | static int snd_cht_mc_probe(struct platform_device *pdev) |
291 | { | 344 | { |
292 | int ret_val = 0; | 345 | int ret_val = 0; |
346 | int i; | ||
293 | struct cht_mc_private *drv; | 347 | struct cht_mc_private *drv; |
348 | struct snd_soc_card *card = snd_soc_cards[0].soc_card; | ||
349 | bool found = false; | ||
350 | char codec_name[16]; | ||
294 | 351 | ||
295 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); | 352 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); |
296 | if (!drv) | 353 | if (!drv) |
297 | return -ENOMEM; | 354 | return -ENOMEM; |
298 | 355 | ||
299 | snd_soc_card_cht.dev = &pdev->dev; | 356 | for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) { |
300 | snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); | 357 | if (ACPI_SUCCESS(acpi_get_devices( |
301 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); | 358 | snd_soc_cards[i].codec_id, |
359 | snd_acpi_codec_match, | ||
360 | &found, NULL)) && found) { | ||
361 | dev_dbg(&pdev->dev, | ||
362 | "found codec %s\n", snd_soc_cards[i].codec_id); | ||
363 | card = snd_soc_cards[i].soc_card; | ||
364 | drv->acpi_card = &snd_soc_cards[i]; | ||
365 | break; | ||
366 | } | ||
367 | } | ||
368 | card->dev = &pdev->dev; | ||
369 | sprintf(codec_name, "i2c-%s:00", drv->acpi_card->codec_id); | ||
370 | /* set correct codec name */ | ||
371 | strcpy((char *)card->dai_link[2].codec_name, codec_name); | ||
372 | snd_soc_card_set_drvdata(card, drv); | ||
373 | ret_val = devm_snd_soc_register_card(&pdev->dev, card); | ||
302 | if (ret_val) { | 374 | if (ret_val) { |
303 | dev_err(&pdev->dev, | 375 | dev_err(&pdev->dev, |
304 | "snd_soc_register_card failed %d\n", ret_val); | 376 | "snd_soc_register_card failed %d\n", ret_val); |
305 | return ret_val; | 377 | return ret_val; |
306 | } | 378 | } |
307 | platform_set_drvdata(pdev, &snd_soc_card_cht); | 379 | platform_set_drvdata(pdev, card); |
308 | return ret_val; | 380 | return ret_val; |
309 | } | 381 | } |
310 | 382 | ||
311 | static struct platform_driver snd_cht_mc_driver = { | 383 | static struct platform_driver snd_cht_mc_driver = { |
312 | .driver = { | 384 | .driver = { |
313 | .name = "cht-bsw-rt5645", | 385 | .name = "cht-bsw-rt5645", |
314 | .pm = &snd_soc_pm_ops, | ||
315 | }, | 386 | }, |
316 | .probe = snd_cht_mc_probe, | 387 | .probe = snd_cht_mc_probe, |
317 | }; | 388 | }; |