1010 */
1111
1212#include <linux/acpi.h>
13+ #include <linux/bitfield.h>
1314#include <linux/clk.h>
1415#include <linux/device.h>
1516#include <linux/init.h>
1617#include <linux/module.h>
1718#include <linux/moduleparam.h>
19+ #include <linux/platform_data/x86/soc.h>
1820#include <linux/platform_device.h>
1921#include <linux/slab.h>
2022#include <linux/spi/spi.h>
2628#include "../../codecs/wm5102.h"
2729#include "../atom/sst-atom-controls.h"
2830
29- #define MCLK_FREQ 25000000
30-
3131#define WM5102_MAX_SYSCLK_4K 49152000 /* max sysclk for 4K family */
3232#define WM5102_MAX_SYSCLK_11025 45158400 /* max sysclk for 11.025K family */
3333
3434struct byt_wm5102_private {
3535 struct snd_soc_jack jack ;
3636 struct clk * mclk ;
3737 struct gpio_desc * spkvdd_en_gpio ;
38+ int mclk_freq ;
3839};
3940
41+ #define BYT_WM5102_IN_MAP GENMASK(3, 0)
42+ #define BYT_WM5102_OUT_MAP GENMASK(7, 4)
43+ #define BYT_WM5102_SSP2 BIT(16)
44+ #define BYT_WM5102_MCLK_19_2MHZ BIT(17)
45+
46+ enum {
47+ BYT_WM5102_INTMIC_IN3L_HSMIC_IN1L ,
48+ BYT_WM5102_INTMIC_IN1L_HSMIC_IN2L ,
49+ };
50+
51+ /* Note these values are pre-shifted for easy use of setting quirks */
52+ enum {
53+ BYT_WM5102_SPK_SPK_MAP = FIELD_PREP_CONST (BYT_WM5102_OUT_MAP , 0 ),
54+ BYT_WM5102_SPK_HPOUT2_MAP = FIELD_PREP_CONST (BYT_WM5102_OUT_MAP , 1 ),
55+ };
56+
57+ static unsigned long quirk ;
58+
59+ static int quirk_override = -1 ;
60+ module_param_named (quirk , quirk_override , int , 0444 );
61+ MODULE_PARM_DESC (quirk , "Board-specific quirk override" );
62+
63+ static void log_quirks (struct device * dev )
64+ {
65+ switch (quirk & BYT_WM5102_IN_MAP ) {
66+ case BYT_WM5102_INTMIC_IN3L_HSMIC_IN1L :
67+ dev_info_once (dev , "quirk INTMIC_IN3L_HSMIC_IN1L enabled\n" );
68+ break ;
69+ case BYT_WM5102_INTMIC_IN1L_HSMIC_IN2L :
70+ dev_info_once (dev , "quirk INTMIC_IN1L_HSMIC_IN2L enabled\n" );
71+ break ;
72+ default :
73+ dev_warn_once (dev , "quirk sets invalid input map: 0x%lx, defaulting to INTMIC_IN3L_HSMIC_IN1L\n" ,
74+ quirk & BYT_WM5102_IN_MAP );
75+ quirk &= ~BYT_WM5102_IN_MAP ;
76+ quirk |= BYT_WM5102_INTMIC_IN3L_HSMIC_IN1L ;
77+ break ;
78+ }
79+ switch (quirk & BYT_WM5102_OUT_MAP ) {
80+ case BYT_WM5102_SPK_SPK_MAP :
81+ dev_info_once (dev , "quirk SPK_SPK_MAP enabled\n" );
82+ break ;
83+ case BYT_WM5102_SPK_HPOUT2_MAP :
84+ dev_info_once (dev , "quirk SPK_HPOUT2_MAP enabled\n" );
85+ break ;
86+ default :
87+ dev_warn_once (dev , "quirk sets invalid output map: 0x%lx, defaulting to SPK_SPK_MAP\n" ,
88+ quirk & BYT_WM5102_OUT_MAP );
89+ quirk &= ~BYT_WM5102_OUT_MAP ;
90+ quirk |= BYT_WM5102_SPK_SPK_MAP ;
91+ break ;
92+ }
93+ if (quirk & BYT_WM5102_SSP2 )
94+ dev_info_once (dev , "quirk SSP2 enabled" );
95+ if (quirk & BYT_WM5102_MCLK_19_2MHZ )
96+ dev_info_once (dev , "quirk MCLK 19.2MHz enabled" );
97+ }
98+
4099static int byt_wm5102_spkvdd_power_event (struct snd_soc_dapm_widget * w ,
41100 struct snd_kcontrol * kcontrol , int event )
42101{
@@ -52,6 +111,7 @@ static int byt_wm5102_spkvdd_power_event(struct snd_soc_dapm_widget *w,
52111static int byt_wm5102_prepare_and_enable_pll1 (struct snd_soc_dai * codec_dai , int rate )
53112{
54113 struct snd_soc_component * codec_component = codec_dai -> component ;
114+ struct byt_wm5102_private * priv = snd_soc_card_get_drvdata (codec_component -> card );
55115 int sr_mult = ((rate % 4000 ) == 0 ) ?
56116 (WM5102_MAX_SYSCLK_4K / rate ) :
57117 (WM5102_MAX_SYSCLK_11025 / rate );
@@ -63,7 +123,7 @@ static int byt_wm5102_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, int
63123
64124 /* Configure the FLL1 PLL before selecting it */
65125 ret = snd_soc_dai_set_pll (codec_dai , WM5102_FLL1 , ARIZONA_CLK_SRC_MCLK1 ,
66- MCLK_FREQ , rate * sr_mult );
126+ priv -> mclk_freq , rate * sr_mult );
67127 if (ret ) {
68128 dev_err (codec_component -> dev , "Error setting PLL: %d\n" , ret );
69129 return ret ;
@@ -145,35 +205,58 @@ static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = {
145205 {"Headset Mic" , NULL , "Platform Clock" },
146206 {"Internal Mic" , NULL , "Platform Clock" },
147207 {"Speaker" , NULL , "Platform Clock" },
148- {"Line Out" , NULL , "Platform Clock" },
149-
150- {"Speaker" , NULL , "SPKOUTLP" },
151- {"Speaker" , NULL , "SPKOUTLN" },
152- {"Speaker" , NULL , "SPKOUTRP" },
153- {"Speaker" , NULL , "SPKOUTRN" },
154208 {"Speaker" , NULL , "Speaker VDD" },
155209
156210 {"Headphone" , NULL , "HPOUT1L" },
157211 {"Headphone" , NULL , "HPOUT1R" },
158212
159- {"Internal Mic" , NULL , "MICBIAS3" },
160- {"IN3L" , NULL , "Internal Mic" },
161-
162213 /*
163214 * The Headset Mix uses MICBIAS1 or 2 depending on if a CTIA/OMTP Headset
164215 * is connected, as the MICBIAS is applied after the CTIA/OMTP cross-switch.
165216 */
166217 {"Headset Mic" , NULL , "MICBIAS1" },
167218 {"Headset Mic" , NULL , "MICBIAS2" },
168- {"IN1L" , NULL , "Headset Mic" },
219+ {"Internal Mic" , NULL , "MICBIAS3" },
220+ };
169221
222+ static const struct snd_soc_dapm_route bytcr_wm5102_ssp0_map [] = {
170223 {"AIF1 Playback" , NULL , "ssp0 Tx" },
171224 {"ssp0 Tx" , NULL , "modem_out" },
172-
173225 {"modem_in" , NULL , "ssp0 Rx" },
174226 {"ssp0 Rx" , NULL , "AIF1 Capture" },
175227};
176228
229+ static const struct snd_soc_dapm_route bytcr_wm5102_ssp2_map [] = {
230+ {"AIF1 Playback" , NULL , "ssp2 Tx" },
231+ {"ssp2 Tx" , NULL , "codec_out0" },
232+ {"ssp2 Tx" , NULL , "codec_out1" },
233+ {"codec_in0" , NULL , "ssp2 Rx" },
234+ {"codec_in1" , NULL , "ssp2 Rx" },
235+ {"ssp2 Rx" , NULL , "AIF1 Capture" },
236+ };
237+
238+ static const struct snd_soc_dapm_route byt_wm5102_spk_spk_map [] = {
239+ {"Speaker" , NULL , "SPKOUTLP" },
240+ {"Speaker" , NULL , "SPKOUTLN" },
241+ {"Speaker" , NULL , "SPKOUTRP" },
242+ {"Speaker" , NULL , "SPKOUTRN" },
243+ };
244+
245+ static const struct snd_soc_dapm_route byt_wm5102_spk_hpout2_map [] = {
246+ {"Speaker" , NULL , "HPOUT2L" },
247+ {"Speaker" , NULL , "HPOUT2R" },
248+ };
249+
250+ static const struct snd_soc_dapm_route byt_wm5102_intmic_in3l_hsmic_in1l_map [] = {
251+ {"IN3L" , NULL , "Internal Mic" },
252+ {"IN1L" , NULL , "Headset Mic" },
253+ };
254+
255+ static const struct snd_soc_dapm_route byt_wm5102_intmic_in1l_hsmic_in2l_map [] = {
256+ {"IN1L" , NULL , "Internal Mic" },
257+ {"IN2L" , NULL , "Headset Mic" },
258+ };
259+
177260static const struct snd_kcontrol_new byt_wm5102_controls [] = {
178261 SOC_DAPM_PIN_SWITCH ("Headphone" ),
179262 SOC_DAPM_PIN_SWITCH ("Headset Mic" ),
@@ -202,7 +285,8 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
202285 struct snd_soc_card * card = runtime -> card ;
203286 struct byt_wm5102_private * priv = snd_soc_card_get_drvdata (card );
204287 struct snd_soc_component * component = snd_soc_rtd_to_codec (runtime , 0 )-> component ;
205- int ret , jack_type ;
288+ const struct snd_soc_dapm_route * custom_map = NULL ;
289+ int ret , jack_type , num_routes = 0 ;
206290
207291 card -> dapm .idle_bias_off = true;
208292
@@ -213,6 +297,50 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
213297 return ret ;
214298 }
215299
300+ switch (quirk & BYT_WM5102_IN_MAP ) {
301+ case BYT_WM5102_INTMIC_IN3L_HSMIC_IN1L :
302+ custom_map = byt_wm5102_intmic_in3l_hsmic_in1l_map ;
303+ num_routes = ARRAY_SIZE (byt_wm5102_intmic_in3l_hsmic_in1l_map );
304+ break ;
305+ case BYT_WM5102_INTMIC_IN1L_HSMIC_IN2L :
306+ custom_map = byt_wm5102_intmic_in1l_hsmic_in2l_map ;
307+ num_routes = ARRAY_SIZE (byt_wm5102_intmic_in1l_hsmic_in2l_map );
308+ break ;
309+ }
310+ ret = snd_soc_dapm_add_routes (& card -> dapm , custom_map , num_routes );
311+ if (ret )
312+ return ret ;
313+
314+ switch (quirk & BYT_WM5102_OUT_MAP ) {
315+ case BYT_WM5102_SPK_SPK_MAP :
316+ custom_map = byt_wm5102_spk_spk_map ;
317+ num_routes = ARRAY_SIZE (byt_wm5102_spk_spk_map );
318+ break ;
319+ case BYT_WM5102_SPK_HPOUT2_MAP :
320+ custom_map = byt_wm5102_spk_hpout2_map ;
321+ num_routes = ARRAY_SIZE (byt_wm5102_spk_hpout2_map );
322+ break ;
323+ }
324+ ret = snd_soc_dapm_add_routes (& card -> dapm , custom_map , num_routes );
325+ if (ret )
326+ return ret ;
327+
328+ if (quirk & BYT_WM5102_SSP2 ) {
329+ custom_map = bytcr_wm5102_ssp2_map ;
330+ num_routes = ARRAY_SIZE (bytcr_wm5102_ssp2_map );
331+ } else {
332+ custom_map = bytcr_wm5102_ssp0_map ;
333+ num_routes = ARRAY_SIZE (bytcr_wm5102_ssp0_map );
334+ }
335+ ret = snd_soc_dapm_add_routes (& card -> dapm , custom_map , num_routes );
336+ if (ret )
337+ return ret ;
338+
339+ if (quirk & BYT_WM5102_MCLK_19_2MHZ )
340+ priv -> mclk_freq = 19200000 ;
341+ else
342+ priv -> mclk_freq = 25000000 ;
343+
216344 /*
217345 * The firmware might enable the clock at boot (this information
218346 * may or may not be reflected in the enable clock register).
@@ -225,7 +353,7 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
225353 if (!ret )
226354 clk_disable_unprepare (priv -> mclk );
227355
228- ret = clk_set_rate (priv -> mclk , MCLK_FREQ );
356+ ret = clk_set_rate (priv -> mclk , priv -> mclk_freq );
229357 if (ret ) {
230358 dev_err (card -> dev , "Error setting MCLK rate: %d\n" , ret );
231359 return ret ;
@@ -253,16 +381,23 @@ static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd,
253381 SNDRV_PCM_HW_PARAM_RATE );
254382 struct snd_interval * channels = hw_param_interval (params ,
255383 SNDRV_PCM_HW_PARAM_CHANNELS );
256- int ret ;
384+ int ret , bits ;
257385
258386 /* The DSP will convert the FE rate to 48k, stereo */
259387 rate -> min = 48000 ;
260388 rate -> max = 48000 ;
261389 channels -> min = 2 ;
262390 channels -> max = 2 ;
263391
264- /* set SSP0 to 16-bit */
265- params_set_format (params , SNDRV_PCM_FORMAT_S16_LE );
392+ if (quirk & BYT_WM5102_SSP2 ) {
393+ /* set SSP2 to 24-bit */
394+ params_set_format (params , SNDRV_PCM_FORMAT_S24_LE );
395+ bits = 24 ;
396+ } else {
397+ /* set SSP0 to 16-bit */
398+ params_set_format (params , SNDRV_PCM_FORMAT_S16_LE );
399+ bits = 16 ;
400+ }
266401
267402 /*
268403 * Default mode for SSP configuration is TDM 4 slot, override config
@@ -278,7 +413,7 @@ static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd,
278413 return ret ;
279414 }
280415
281- ret = snd_soc_dai_set_tdm_slot (snd_soc_rtd_to_cpu (rtd , 0 ), 0x3 , 0x3 , 2 , 16 );
416+ ret = snd_soc_dai_set_tdm_slot (snd_soc_rtd_to_cpu (rtd , 0 ), 0x3 , 0x3 , 2 , bits );
282417 if (ret ) {
283418 dev_err (rtd -> dev , "Error setting I2S config: %d\n" , ret );
284419 return ret ;
@@ -345,12 +480,9 @@ static struct snd_soc_dai_link byt_wm5102_dais[] = {
345480 /* back ends */
346481 {
347482 /*
348- * This must be named SSP2-Codec even though this machine driver
349- * always uses SSP0. Most machine drivers support both and dynamically
350- * update the dailink to point to SSP0 or SSP2, while keeping the name
351- * as "SSP2-Codec". The SOF tplg files hardcode the "SSP2-Codec" even
352- * in the byt-foo-ssp0.tplg versions because the other machine-drivers
353- * use "SSP2-Codec" even when SSP0 is used.
483+ * This dailink is updated dynamically to point to SSP0 or SSP2.
484+ * Yet its name is always kept as "SSP2-Codec" because the SOF
485+ * tplg files hardcode "SSP2-Codec" even in byt-foo-ssp0.tplg.
354486 */
355487 .name = "SSP2-Codec" ,
356488 .id = 0 ,
@@ -384,17 +516,23 @@ static struct snd_soc_card byt_wm5102_card = {
384516 .fully_routed = true,
385517};
386518
519+ static char byt_wm5102_components [64 ]; /* = "cfg-spk:* cfg-int-mic:* cfg-hs-mic:* ..." */
520+
387521static int snd_byt_wm5102_mc_probe (struct platform_device * pdev )
388522{
523+ static const char * const out_map_name [] = { "spk" , "hpout2" };
524+ static const char * const intmic_map_name [] = { "in3l" , "in1l" };
525+ static const char * const hsmic_map_name [] = { "in1l" , "in2l" };
389526 char codec_name [SND_ACPI_I2C_ID_LEN ];
390527 struct device * dev = & pdev -> dev ;
391528 struct byt_wm5102_private * priv ;
392529 struct snd_soc_acpi_mach * mach ;
393530 const char * platform_name ;
394531 struct acpi_device * adev ;
395532 struct device * codec_dev ;
533+ int dai_index = 0 ;
396534 bool sof_parent ;
397- int ret ;
535+ int i , ret ;
398536
399537 priv = devm_kzalloc (dev , sizeof (* priv ), GFP_KERNEL );
400538 if (!priv )
@@ -441,13 +579,50 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
441579 return dev_err_probe (dev , ret , "getting spkvdd-GPIO\n" );
442580 }
443581
582+ if (soc_intel_is_cht ()) {
583+ /*
584+ * CHT always uses SSP2 and 19.2 MHz; and
585+ * the one currently supported CHT design uses HPOUT2 as
586+ * speaker output and has the intmic on IN1L + hsmic on IN2L.
587+ */
588+ quirk = BYT_WM5102_SSP2 | BYT_WM5102_MCLK_19_2MHZ |
589+ BYT_WM5102_INTMIC_IN1L_HSMIC_IN2L |
590+ BYT_WM5102_SPK_HPOUT2_MAP ;
591+ }
592+ if (quirk_override != -1 ) {
593+ dev_info_once (dev , "Overriding quirk 0x%lx => 0x%x\n" ,
594+ quirk , quirk_override );
595+ quirk = quirk_override ;
596+ }
597+ log_quirks (dev );
598+
599+ snprintf (byt_wm5102_components , sizeof (byt_wm5102_components ),
600+ "cfg-spk:%s cfg-intmic:%s cfg-hsmic:%s" ,
601+ out_map_name [FIELD_GET (BYT_WM5102_OUT_MAP , quirk )],
602+ intmic_map_name [FIELD_GET (BYT_WM5102_IN_MAP , quirk )],
603+ hsmic_map_name [FIELD_GET (BYT_WM5102_IN_MAP , quirk )]);
604+ byt_wm5102_card .components = byt_wm5102_components ;
605+
606+ /* find index of codec dai */
607+ for (i = 0 ; i < ARRAY_SIZE (byt_wm5102_dais ); i ++ ) {
608+ if (!strcmp (byt_wm5102_dais [i ].codecs -> name ,
609+ "wm5102-codec" )) {
610+ dai_index = i ;
611+ break ;
612+ }
613+ }
614+
444615 /* override platform name, if required */
445616 byt_wm5102_card .dev = dev ;
446617 platform_name = mach -> mach_params .platform ;
447618 ret = snd_soc_fixup_dai_links_platform_name (& byt_wm5102_card , platform_name );
448619 if (ret )
449620 goto out_put_gpio ;
450621
622+ /* override SSP port, if required */
623+ if (quirk & BYT_WM5102_SSP2 )
624+ byt_wm5102_dais [dai_index ].cpus -> dai_name = "ssp2-port" ;
625+
451626 /* set card and driver name and pm-ops */
452627 sof_parent = snd_soc_acpi_sof_parent (dev );
453628 if (sof_parent ) {
0 commit comments