1515#include <linux/init.h>
1616#include <linux/module.h>
1717#include <linux/moduleparam.h>
18+ #include <linux/platform_data/x86/soc.h>
1819#include <linux/platform_device.h>
1920#include <linux/slab.h>
2021#include <linux/spi/spi.h>
@@ -37,6 +38,21 @@ struct byt_wm5102_private {
3738 struct gpio_desc * spkvdd_en_gpio ;
3839};
3940
41+ /* Bits 0-15 are reserved for things like an input-map */
42+ #define BYT_WM5102_SSP2 BIT(16)
43+
44+ static unsigned long quirk ;
45+
46+ static int quirk_override = -1 ;
47+ module_param_named (quirk , quirk_override , int , 0444 );
48+ MODULE_PARM_DESC (quirk , "Board-specific quirk override" );
49+
50+ static void log_quirks (struct device * dev )
51+ {
52+ if (quirk & BYT_WM5102_SSP2 )
53+ dev_info_once (dev , "quirk SSP2 enabled" );
54+ }
55+
4056static int byt_wm5102_spkvdd_power_event (struct snd_soc_dapm_widget * w ,
4157 struct snd_kcontrol * kcontrol , int event )
4258{
@@ -166,14 +182,24 @@ static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = {
166182 {"Headset Mic" , NULL , "MICBIAS1" },
167183 {"Headset Mic" , NULL , "MICBIAS2" },
168184 {"IN1L" , NULL , "Headset Mic" },
185+ };
169186
187+ static const struct snd_soc_dapm_route bytcr_wm5102_ssp0_map [] = {
170188 {"AIF1 Playback" , NULL , "ssp0 Tx" },
171189 {"ssp0 Tx" , NULL , "modem_out" },
172-
173190 {"modem_in" , NULL , "ssp0 Rx" },
174191 {"ssp0 Rx" , NULL , "AIF1 Capture" },
175192};
176193
194+ static const struct snd_soc_dapm_route bytcr_wm5102_ssp2_map [] = {
195+ {"AIF1 Playback" , NULL , "ssp2 Tx" },
196+ {"ssp2 Tx" , NULL , "codec_out0" },
197+ {"ssp2 Tx" , NULL , "codec_out1" },
198+ {"codec_in0" , NULL , "ssp2 Rx" },
199+ {"codec_in1" , NULL , "ssp2 Rx" },
200+ {"ssp2 Rx" , NULL , "AIF1 Capture" },
201+ };
202+
177203static const struct snd_kcontrol_new byt_wm5102_controls [] = {
178204 SOC_DAPM_PIN_SWITCH ("Headphone" ),
179205 SOC_DAPM_PIN_SWITCH ("Headset Mic" ),
@@ -202,7 +228,8 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
202228 struct snd_soc_card * card = runtime -> card ;
203229 struct byt_wm5102_private * priv = snd_soc_card_get_drvdata (card );
204230 struct snd_soc_component * component = snd_soc_rtd_to_codec (runtime , 0 )-> component ;
205- int ret , jack_type ;
231+ const struct snd_soc_dapm_route * custom_map = NULL ;
232+ int ret , jack_type , num_routes = 0 ;
206233
207234 card -> dapm .idle_bias_off = true;
208235
@@ -213,6 +240,17 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
213240 return ret ;
214241 }
215242
243+ if (quirk & BYT_WM5102_SSP2 ) {
244+ custom_map = bytcr_wm5102_ssp2_map ;
245+ num_routes = ARRAY_SIZE (bytcr_wm5102_ssp2_map );
246+ } else {
247+ custom_map = bytcr_wm5102_ssp0_map ;
248+ num_routes = ARRAY_SIZE (bytcr_wm5102_ssp0_map );
249+ }
250+ ret = snd_soc_dapm_add_routes (& card -> dapm , custom_map , num_routes );
251+ if (ret )
252+ return ret ;
253+
216254 /*
217255 * The firmware might enable the clock at boot (this information
218256 * may or may not be reflected in the enable clock register).
@@ -253,16 +291,23 @@ static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd,
253291 SNDRV_PCM_HW_PARAM_RATE );
254292 struct snd_interval * channels = hw_param_interval (params ,
255293 SNDRV_PCM_HW_PARAM_CHANNELS );
256- int ret ;
294+ int ret , bits ;
257295
258296 /* The DSP will convert the FE rate to 48k, stereo */
259297 rate -> min = 48000 ;
260298 rate -> max = 48000 ;
261299 channels -> min = 2 ;
262300 channels -> max = 2 ;
263301
264- /* set SSP0 to 16-bit */
265- params_set_format (params , SNDRV_PCM_FORMAT_S16_LE );
302+ if (quirk & BYT_WM5102_SSP2 ) {
303+ /* set SSP2 to 24-bit */
304+ params_set_format (params , SNDRV_PCM_FORMAT_S24_LE );
305+ bits = 24 ;
306+ } else {
307+ /* set SSP0 to 16-bit */
308+ params_set_format (params , SNDRV_PCM_FORMAT_S16_LE );
309+ bits = 16 ;
310+ }
266311
267312 /*
268313 * Default mode for SSP configuration is TDM 4 slot, override config
@@ -278,7 +323,7 @@ static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd,
278323 return ret ;
279324 }
280325
281- ret = snd_soc_dai_set_tdm_slot (snd_soc_rtd_to_cpu (rtd , 0 ), 0x3 , 0x3 , 2 , 16 );
326+ ret = snd_soc_dai_set_tdm_slot (snd_soc_rtd_to_cpu (rtd , 0 ), 0x3 , 0x3 , 2 , bits );
282327 if (ret ) {
283328 dev_err (rtd -> dev , "Error setting I2S config: %d\n" , ret );
284329 return ret ;
@@ -345,12 +390,9 @@ static struct snd_soc_dai_link byt_wm5102_dais[] = {
345390 /* back ends */
346391 {
347392 /*
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.
393+ * This dailink is updated dynamically to point to SSP0 or SSP2.
394+ * Yet its name is always kept as "SSP2-Codec" because the SOF
395+ * tplg files hardcode "SSP2-Codec" even in byt-foo-ssp0.tplg.
354396 */
355397 .name = "SSP2-Codec" ,
356398 .id = 0 ,
@@ -393,8 +435,9 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
393435 const char * platform_name ;
394436 struct acpi_device * adev ;
395437 struct device * codec_dev ;
438+ int dai_index = 0 ;
396439 bool sof_parent ;
397- int ret ;
440+ int i , ret ;
398441
399442 priv = devm_kzalloc (dev , sizeof (* priv ), GFP_KERNEL );
400443 if (!priv )
@@ -441,13 +484,37 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
441484 return dev_err_probe (dev , ret , "getting spkvdd-GPIO\n" );
442485 }
443486
487+ if (soc_intel_is_cht ()) {
488+ /* On CHT default to SSP2 */
489+ quirk = BYT_WM5102_SSP2 ;
490+ }
491+ if (quirk_override != -1 ) {
492+ dev_info_once (dev , "Overriding quirk 0x%lx => 0x%x\n" ,
493+ quirk , quirk_override );
494+ quirk = quirk_override ;
495+ }
496+ log_quirks (dev );
497+
498+ /* find index of codec dai */
499+ for (i = 0 ; i < ARRAY_SIZE (byt_wm5102_dais ); i ++ ) {
500+ if (!strcmp (byt_wm5102_dais [i ].codecs -> name ,
501+ "wm5102-codec" )) {
502+ dai_index = i ;
503+ break ;
504+ }
505+ }
506+
444507 /* override platform name, if required */
445508 byt_wm5102_card .dev = dev ;
446509 platform_name = mach -> mach_params .platform ;
447510 ret = snd_soc_fixup_dai_links_platform_name (& byt_wm5102_card , platform_name );
448511 if (ret )
449512 goto out_put_gpio ;
450513
514+ /* override SSP port, if required */
515+ if (quirk & BYT_WM5102_SSP2 )
516+ byt_wm5102_dais [dai_index ].cpus -> dai_name = "ssp2-port" ;
517+
451518 /* set card and driver name and pm-ops */
452519 sof_parent = snd_soc_acpi_sof_parent (dev );
453520 if (sof_parent ) {
0 commit comments