15 #include <linux/module.h>
20 #include <linux/i2c.h>
22 #include <linux/slab.h>
37 static const u16 wm8750_reg[] = {
38 0x0097, 0x0097, 0x0079, 0x0079,
39 0x0000, 0x0008, 0x0000, 0x000a,
40 0x0000, 0x0000, 0x00ff, 0x00ff,
41 0x000f, 0x000f, 0x0000, 0x0000,
42 0x0000, 0x007b, 0x0000, 0x0032,
43 0x0000, 0x00c3, 0x00c3, 0x00c0,
44 0x0000, 0x0000, 0x0000, 0x0000,
45 0x0000, 0x0000, 0x0000, 0x0000,
46 0x0000, 0x0000, 0x0050, 0x0050,
47 0x0050, 0x0050, 0x0050, 0x0050,
48 0x0079, 0x0079, 0x0079,
57 #define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
62 static const char *wm8750_bass[] = {
"Linear Control",
"Adaptive Boost"};
63 static const char *wm8750_bass_filter[] = {
"130Hz @ 48kHz",
"200Hz @ 48kHz" };
64 static const char *wm8750_treble[] = {
"8kHz",
"4kHz"};
65 static const char *wm8750_3d_lc[] = {
"200Hz",
"500Hz"};
66 static const char *wm8750_3d_uc[] = {
"2.2kHz",
"1.5kHz"};
67 static const char *wm8750_3d_func[] = {
"Capture",
"Playback"};
68 static const char *wm8750_alc_func[] = {
"Off",
"Right",
"Left",
"Stereo"};
69 static const char *wm8750_ng_type[] = {
"Constant PGA Gain",
71 static const char *wm8750_line_mux[] = {
"Line 1",
"Line 2",
"Line 3",
"PGA",
73 static const char *wm8750_pga_sel[] = {
"Line 1",
"Line 2",
"Line 3",
75 static const char *wm8750_out3[] = {
"VREF",
"ROUT1 + Vol",
"MonoOut",
77 static const char *wm8750_diff_sel[] = {
"Line 1",
"Line 2"};
78 static const char *wm8750_adcpol[] = {
"Normal",
"L Invert",
"R Invert",
80 static const char *wm8750_deemph[] = {
"None",
"32Khz",
"44.1Khz",
"48Khz"};
81 static const char *wm8750_mono_mux[] = {
"Stereo",
"Mono (Left)",
82 "Mono (Right)",
"Digital Mono"};
84 static const struct soc_enum wm8750_enum[] = {
116 SOC_ENUM(
"Playback De-emphasis", wm8750_enum[15]),
118 SOC_ENUM(
"Capture Polarity", wm8750_enum[14]),
124 SOC_ENUM(
"Bass Boost", wm8750_enum[0]),
125 SOC_ENUM(
"Bass Filter", wm8750_enum[1]),
129 SOC_ENUM(
"Treble Cut-off", wm8750_enum[2]),
133 SOC_ENUM(
"3D Lower Cut-off", wm8750_enum[3]),
134 SOC_ENUM(
"3D Upper Cut-off", wm8750_enum[4]),
135 SOC_ENUM(
"3D Mode", wm8750_enum[5]),
139 SOC_ENUM(
"ALC Capture Function", wm8750_enum[6]),
145 SOC_ENUM(
"ALC Capture NG Type", wm8750_enum[4]),
248 &wm8750_left_mixer_controls[0],
251 &wm8750_right_mixer_controls[0],
254 &wm8750_mono_mixer_controls[0],
269 &wm8750_left_pga_controls),
271 &wm8750_right_pga_controls),
273 &wm8750_left_line_controls),
275 &wm8750_right_line_controls),
282 &wm8750_diffmux_controls),
284 &wm8750_monomux_controls),
286 &wm8750_monomux_controls),
306 {
"Left Mixer",
"Playback Switch",
"Left DAC"},
307 {
"Left Mixer",
"Left Bypass Switch",
"Left Line Mux"},
308 {
"Left Mixer",
"Right Playback Switch",
"Right DAC"},
309 {
"Left Mixer",
"Right Bypass Switch",
"Right Line Mux"},
312 {
"Right Mixer",
"Left Playback Switch",
"Left DAC"},
313 {
"Right Mixer",
"Left Bypass Switch",
"Left Line Mux"},
314 {
"Right Mixer",
"Playback Switch",
"Right DAC"},
315 {
"Right Mixer",
"Right Bypass Switch",
"Right Line Mux"},
318 {
"Left Out 1",
NULL,
"Left Mixer"},
319 {
"LOUT1",
NULL,
"Left Out 1"},
322 {
"Left Out 2",
NULL,
"Left Mixer"},
323 {
"LOUT2",
NULL,
"Left Out 2"},
326 {
"Right Out 1",
NULL,
"Right Mixer"},
327 {
"ROUT1",
NULL,
"Right Out 1"},
330 {
"Right Out 2",
NULL,
"Right Mixer"},
331 {
"ROUT2",
NULL,
"Right Out 2"},
334 {
"Mono Mixer",
"Left Playback Switch",
"Left DAC"},
335 {
"Mono Mixer",
"Left Bypass Switch",
"Left Line Mux"},
336 {
"Mono Mixer",
"Right Playback Switch",
"Right DAC"},
337 {
"Mono Mixer",
"Right Bypass Switch",
"Right Line Mux"},
340 {
"Mono Out 1",
NULL,
"Mono Mixer"},
341 {
"MONO1",
NULL,
"Mono Out 1"},
344 {
"Out3 Mux",
"VREF",
"VREF"},
345 {
"Out3 Mux",
"ROUT1 + Vol",
"ROUT1"},
346 {
"Out3 Mux",
"ROUT1",
"Right Mixer"},
347 {
"Out3 Mux",
"MonoOut",
"MONO1"},
348 {
"Out 3",
NULL,
"Out3 Mux"},
349 {
"OUT3",
NULL,
"Out 3"},
352 {
"Left Line Mux",
"Line 1",
"LINPUT1"},
353 {
"Left Line Mux",
"Line 2",
"LINPUT2"},
354 {
"Left Line Mux",
"Line 3",
"LINPUT3"},
355 {
"Left Line Mux",
"PGA",
"Left PGA Mux"},
356 {
"Left Line Mux",
"Differential",
"Differential Mux"},
359 {
"Right Line Mux",
"Line 1",
"RINPUT1"},
360 {
"Right Line Mux",
"Line 2",
"RINPUT2"},
361 {
"Right Line Mux",
"Line 3",
"RINPUT3"},
362 {
"Right Line Mux",
"PGA",
"Right PGA Mux"},
363 {
"Right Line Mux",
"Differential",
"Differential Mux"},
366 {
"Left PGA Mux",
"Line 1",
"LINPUT1"},
367 {
"Left PGA Mux",
"Line 2",
"LINPUT2"},
368 {
"Left PGA Mux",
"Line 3",
"LINPUT3"},
369 {
"Left PGA Mux",
"Differential",
"Differential Mux"},
372 {
"Right PGA Mux",
"Line 1",
"RINPUT1"},
373 {
"Right PGA Mux",
"Line 2",
"RINPUT2"},
374 {
"Right PGA Mux",
"Line 3",
"RINPUT3"},
375 {
"Right PGA Mux",
"Differential",
"Differential Mux"},
378 {
"Differential Mux",
"Line 1",
"LINPUT1"},
379 {
"Differential Mux",
"Line 1",
"RINPUT1"},
380 {
"Differential Mux",
"Line 2",
"LINPUT2"},
381 {
"Differential Mux",
"Line 2",
"RINPUT2"},
384 {
"Left ADC Mux",
"Stereo",
"Left PGA Mux"},
385 {
"Left ADC Mux",
"Mono (Left)",
"Left PGA Mux"},
386 {
"Left ADC Mux",
"Digital Mono",
"Left PGA Mux"},
389 {
"Right ADC Mux",
"Stereo",
"Right PGA Mux"},
390 {
"Right ADC Mux",
"Mono (Right)",
"Right PGA Mux"},
391 {
"Right ADC Mux",
"Digital Mono",
"Right PGA Mux"},
394 {
"Left ADC",
NULL,
"Left ADC Mux"},
395 {
"Right ADC",
NULL,
"Right ADC Mux"},
407 static const struct _coeff_div coeff_div[] = {
409 {12288000, 8000, 1536, 0x6, 0x0},
410 {11289600, 8000, 1408, 0x16, 0x0},
411 {18432000, 8000, 2304, 0x7, 0x0},
412 {16934400, 8000, 2112, 0x17, 0x0},
413 {12000000, 8000, 1500, 0x6, 0x1},
416 {11289600, 11025, 1024, 0x18, 0x0},
417 {16934400, 11025, 1536, 0x19, 0x0},
418 {12000000, 11025, 1088, 0x19, 0x1},
421 {12288000, 16000, 768, 0xa, 0x0},
422 {18432000, 16000, 1152, 0xb, 0x0},
423 {12000000, 16000, 750, 0xa, 0x1},
426 {11289600, 22050, 512, 0x1a, 0x0},
427 {16934400, 22050, 768, 0x1b, 0x0},
428 {12000000, 22050, 544, 0x1b, 0x1},
431 {12288000, 32000, 384, 0xc, 0x0},
432 {18432000, 32000, 576, 0xd, 0x0},
433 {12000000, 32000, 375, 0xa, 0x1},
436 {11289600, 44100, 256, 0x10, 0x0},
437 {16934400, 44100, 384, 0x11, 0x0},
438 {12000000, 44100, 272, 0x11, 0x1},
441 {12288000, 48000, 256, 0x0, 0x0},
442 {18432000, 48000, 384, 0x1, 0x0},
443 {12000000, 48000, 250, 0x0, 0x1},
446 {11289600, 88200, 128, 0x1e, 0x0},
447 {16934400, 88200, 192, 0x1f, 0x0},
448 {12000000, 88200, 136, 0x1f, 0x1},
451 {12288000, 96000, 128, 0xe, 0x0},
452 {18432000, 96000, 192, 0xf, 0x0},
453 {12000000, 96000, 125, 0xe, 0x1},
456 static inline int get_coeff(
int mclk,
int rate)
461 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
465 printk(
KERN_ERR "wm8750: could not get coeff for mclk %d @ rate %d\n",
470 static int wm8750_set_dai_sysclk(
struct snd_soc_dai *codec_dai,
471 int clk_id,
unsigned int freq,
int dir)
474 struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
488 static int wm8750_set_dai_fmt(
struct snd_soc_dai *codec_dai,
551 struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
575 (coeff_div[coeff].
sr << 1) | coeff_div[coeff].
usb);
592 static int wm8750_set_bias_level(
struct snd_soc_codec *codec,
626 #define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
627 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
628 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
630 #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
631 SNDRV_PCM_FMTBIT_S24_LE)
634 .hw_params = wm8750_pcm_hw_params,
635 .digital_mute = wm8750_mute,
636 .set_fmt = wm8750_set_dai_fmt,
637 .set_sysclk = wm8750_set_dai_sysclk,
641 .name =
"wm8750-hifi",
643 .stream_name =
"Playback",
649 .stream_name =
"Capture",
654 .ops = &wm8750_dai_ops,
671 struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
709 .probe = wm8750_probe,
710 .remove = wm8750_remove,
711 .suspend = wm8750_suspend,
712 .resume = wm8750_resume,
713 .set_bias_level = wm8750_set_bias_level,
715 .reg_word_size =
sizeof(
u16),
720 .dapm_widgets = wm8750_dapm_widgets,
721 .num_dapm_widgets =
ARRAY_SIZE(wm8750_dapm_widgets),
722 .dapm_routes = wm8750_dapm_routes,
723 .num_dapm_routes =
ARRAY_SIZE(wm8750_dapm_routes),
727 { .compatible =
"wlf,wm8750", },
728 { .compatible =
"wlf,wm8987", },
733 #if defined(CONFIG_SPI_MASTER)
745 spi_set_drvdata(spi, wm8750);
748 &soc_codec_dev_wm8750, &wm8750_dai, 1);
765 static struct spi_driver wm8750_spi_driver = {
769 .of_match_table = wm8750_of_match,
771 .id_table = wm8750_spi_ids,
772 .probe = wm8750_spi_probe,
777 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
789 i2c_set_clientdata(i2c, wm8750);
793 &soc_codec_dev_wm8750, &wm8750_dai, 1);
810 static struct i2c_driver wm8750_i2c_driver = {
814 .of_match_table = wm8750_of_match,
816 .probe = wm8750_i2c_probe,
818 .id_table = wm8750_i2c_id,
822 static int __init wm8750_modinit(
void)
825 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
826 ret = i2c_add_driver(&wm8750_i2c_driver);
832 #if defined(CONFIG_SPI_MASTER)
843 static void __exit wm8750_exit(
void)
845 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
848 #if defined(CONFIG_SPI_MASTER)
849 spi_unregister_driver(&wm8750_spi_driver);