Skip to content

Commit 811e66d

Browse files
PetrKulhavybroonie
authored andcommitted
ASoC: wm8985: add support for WM8758
The WM8758 chip is almost identical to WM8985 with the difference that it doesn't feature the AUX input. This patch adds the WM8758 support into the WM8985 driver. The chip selection is done by the I2C name. The SPI probe supports only the WM8985. Signed-off-by: Petr Kulhavy <[email protected]> Reviewed-by: Charles Keepax <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 68f9eac commit 811e66d

File tree

2 files changed

+109
-36
lines changed

2 files changed

+109
-36
lines changed

sound/soc/codecs/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ config SND_SOC_WM8983
944944
tristate
945945

946946
config SND_SOC_WM8985
947-
tristate
947+
tristate "Wolfson Microelectronics WM8985 and WM8758 codec driver"
948948

949949
config SND_SOC_WM8988
950950
tristate

sound/soc/codecs/wm8985.c

Lines changed: 108 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
/*
2-
* wm8985.c -- WM8985 ALSA SoC Audio driver
2+
* wm8985.c -- WM8985 / WM8758 ALSA SoC Audio driver
33
*
44
* Copyright 2010 Wolfson Microelectronics plc
5-
*
65
* Author: Dimitris Papastamos <[email protected]>
76
*
7+
* WM8758 support:
8+
* Copyright: 2016 Barix AG
9+
* Author: Petr Kulhavy <[email protected]>
10+
*
811
* This program is free software; you can redistribute it and/or modify
912
* it under the terms of the GNU General Public License version 2 as
1013
* published by the Free Software Foundation.
@@ -40,6 +43,11 @@ static const char *wm8985_supply_names[WM8985_NUM_SUPPLIES] = {
4043
"AVDD2"
4144
};
4245

46+
enum wm8985_type {
47+
WM8985,
48+
WM8758,
49+
};
50+
4351
static const struct reg_default wm8985_reg_defaults[] = {
4452
{ 1, 0x0000 }, /* R1 - Power management 1 */
4553
{ 2, 0x0000 }, /* R2 - Power management 2 */
@@ -181,6 +189,7 @@ static const int volume_update_regs[] = {
181189
struct wm8985_priv {
182190
struct regmap *regmap;
183191
struct regulator_bulk_data supplies[WM8985_NUM_SUPPLIES];
192+
enum wm8985_type dev_type;
184193
unsigned int sysclk;
185194
unsigned int bclk;
186195
};
@@ -289,7 +298,7 @@ static const char *depth_3d_text[] = {
289298
};
290299
static SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, depth_3d_text);
291300

292-
static const struct snd_kcontrol_new wm8985_snd_controls[] = {
301+
static const struct snd_kcontrol_new wm8985_common_snd_controls[] = {
293302
SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL,
294303
0, 1, 0),
295304

@@ -355,10 +364,6 @@ static const struct snd_kcontrol_new wm8985_snd_controls[] = {
355364
SOC_ENUM("High Pass Filter Mode", filter_mode),
356365
SOC_SINGLE("High Pass Filter Cutoff", WM8985_ADC_CONTROL, 4, 7, 0),
357366

358-
SOC_DOUBLE_R_TLV("Aux Bypass Volume",
359-
WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 6, 7, 0,
360-
aux_tlv),
361-
362367
SOC_DOUBLE_R_TLV("Input PGA Bypass Volume",
363368
WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 2, 7, 0,
364369
bypass_tlv),
@@ -379,20 +384,30 @@ static const struct snd_kcontrol_new wm8985_snd_controls[] = {
379384
SOC_SINGLE_TLV("EQ5 Volume", WM8985_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv),
380385

381386
SOC_ENUM("3D Depth", depth_3d),
387+
};
388+
389+
static const struct snd_kcontrol_new wm8985_specific_snd_controls[] = {
390+
SOC_DOUBLE_R_TLV("Aux Bypass Volume",
391+
WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 6, 7, 0,
392+
aux_tlv),
382393

383394
SOC_ENUM("Speaker Mode", speaker_mode)
384395
};
385396

386397
static const struct snd_kcontrol_new left_out_mixer[] = {
387398
SOC_DAPM_SINGLE("Line Switch", WM8985_LEFT_MIXER_CTRL, 1, 1, 0),
388-
SOC_DAPM_SINGLE("Aux Switch", WM8985_LEFT_MIXER_CTRL, 5, 1, 0),
389399
SOC_DAPM_SINGLE("PCM Switch", WM8985_LEFT_MIXER_CTRL, 0, 1, 0),
400+
401+
/* --- WM8985 only --- */
402+
SOC_DAPM_SINGLE("Aux Switch", WM8985_LEFT_MIXER_CTRL, 5, 1, 0),
390403
};
391404

392405
static const struct snd_kcontrol_new right_out_mixer[] = {
393406
SOC_DAPM_SINGLE("Line Switch", WM8985_RIGHT_MIXER_CTRL, 1, 1, 0),
394-
SOC_DAPM_SINGLE("Aux Switch", WM8985_RIGHT_MIXER_CTRL, 5, 1, 0),
395407
SOC_DAPM_SINGLE("PCM Switch", WM8985_RIGHT_MIXER_CTRL, 0, 1, 0),
408+
409+
/* --- WM8985 only --- */
410+
SOC_DAPM_SINGLE("Aux Switch", WM8985_RIGHT_MIXER_CTRL, 5, 1, 0),
396411
};
397412

398413
static const struct snd_kcontrol_new left_input_mixer[] = {
@@ -410,18 +425,22 @@ static const struct snd_kcontrol_new right_input_mixer[] = {
410425
static const struct snd_kcontrol_new left_boost_mixer[] = {
411426
SOC_DAPM_SINGLE_TLV("L2 Volume", WM8985_LEFT_ADC_BOOST_CTRL,
412427
4, 7, 0, boost_tlv),
428+
429+
/* --- WM8985 only --- */
413430
SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8985_LEFT_ADC_BOOST_CTRL,
414431
0, 7, 0, boost_tlv)
415432
};
416433

417434
static const struct snd_kcontrol_new right_boost_mixer[] = {
418435
SOC_DAPM_SINGLE_TLV("R2 Volume", WM8985_RIGHT_ADC_BOOST_CTRL,
419436
4, 7, 0, boost_tlv),
437+
438+
/* --- WM8985 only --- */
420439
SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8985_RIGHT_ADC_BOOST_CTRL,
421440
0, 7, 0, boost_tlv)
422441
};
423442

424-
static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
443+
static const struct snd_soc_dapm_widget wm8985_common_dapm_widgets[] = {
425444
SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8985_POWER_MANAGEMENT_3,
426445
0, 0),
427446
SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8985_POWER_MANAGEMENT_3,
@@ -431,21 +450,11 @@ static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
431450
SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8985_POWER_MANAGEMENT_2,
432451
1, 0),
433452

434-
SND_SOC_DAPM_MIXER("Left Output Mixer", WM8985_POWER_MANAGEMENT_3,
435-
2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)),
436-
SND_SOC_DAPM_MIXER("Right Output Mixer", WM8985_POWER_MANAGEMENT_3,
437-
3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)),
438-
439453
SND_SOC_DAPM_MIXER("Left Input Mixer", WM8985_POWER_MANAGEMENT_2,
440454
2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)),
441455
SND_SOC_DAPM_MIXER("Right Input Mixer", WM8985_POWER_MANAGEMENT_2,
442456
3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)),
443457

444-
SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8985_POWER_MANAGEMENT_2,
445-
4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)),
446-
SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8985_POWER_MANAGEMENT_2,
447-
5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)),
448-
449458
SND_SOC_DAPM_PGA("Left Capture PGA", WM8985_LEFT_INP_PGA_GAIN_CTRL,
450459
6, 1, NULL, 0),
451460
SND_SOC_DAPM_PGA("Right Capture PGA", WM8985_RIGHT_INP_PGA_GAIN_CTRL,
@@ -468,8 +477,6 @@ static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
468477
SND_SOC_DAPM_INPUT("LIP"),
469478
SND_SOC_DAPM_INPUT("RIN"),
470479
SND_SOC_DAPM_INPUT("RIP"),
471-
SND_SOC_DAPM_INPUT("AUXL"),
472-
SND_SOC_DAPM_INPUT("AUXR"),
473480
SND_SOC_DAPM_INPUT("L2"),
474481
SND_SOC_DAPM_INPUT("R2"),
475482
SND_SOC_DAPM_OUTPUT("HPL"),
@@ -478,13 +485,42 @@ static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
478485
SND_SOC_DAPM_OUTPUT("SPKR")
479486
};
480487

481-
static const struct snd_soc_dapm_route wm8985_dapm_routes[] = {
488+
static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
489+
SND_SOC_DAPM_MIXER("Left Output Mixer", WM8985_POWER_MANAGEMENT_3,
490+
2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)),
491+
SND_SOC_DAPM_MIXER("Right Output Mixer", WM8985_POWER_MANAGEMENT_3,
492+
3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)),
493+
494+
SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8985_POWER_MANAGEMENT_2,
495+
4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)),
496+
SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8985_POWER_MANAGEMENT_2,
497+
5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)),
498+
499+
SND_SOC_DAPM_INPUT("AUXL"),
500+
SND_SOC_DAPM_INPUT("AUXR"),
501+
};
502+
503+
static const struct snd_soc_dapm_widget wm8758_dapm_widgets[] = {
504+
SND_SOC_DAPM_MIXER("Left Output Mixer", WM8985_POWER_MANAGEMENT_3,
505+
2, 0, left_out_mixer,
506+
ARRAY_SIZE(left_out_mixer) - 1),
507+
SND_SOC_DAPM_MIXER("Right Output Mixer", WM8985_POWER_MANAGEMENT_3,
508+
3, 0, right_out_mixer,
509+
ARRAY_SIZE(right_out_mixer) - 1),
510+
511+
SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8985_POWER_MANAGEMENT_2,
512+
4, 0, left_boost_mixer,
513+
ARRAY_SIZE(left_boost_mixer) - 1),
514+
SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8985_POWER_MANAGEMENT_2,
515+
5, 0, right_boost_mixer,
516+
ARRAY_SIZE(right_boost_mixer) - 1),
517+
};
518+
519+
static const struct snd_soc_dapm_route wm8985_common_dapm_routes[] = {
482520
{ "Right Output Mixer", "PCM Switch", "Right DAC" },
483-
{ "Right Output Mixer", "Aux Switch", "AUXR" },
484521
{ "Right Output Mixer", "Line Switch", "Right Boost Mixer" },
485522

486523
{ "Left Output Mixer", "PCM Switch", "Left DAC" },
487-
{ "Left Output Mixer", "Aux Switch", "AUXL" },
488524
{ "Left Output Mixer", "Line Switch", "Left Boost Mixer" },
489525

490526
{ "Right Headphone Out", NULL, "Right Output Mixer" },
@@ -501,13 +537,11 @@ static const struct snd_soc_dapm_route wm8985_dapm_routes[] = {
501537

502538
{ "Right ADC", NULL, "Right Boost Mixer" },
503539

504-
{ "Right Boost Mixer", "AUXR Volume", "AUXR" },
505540
{ "Right Boost Mixer", NULL, "Right Capture PGA" },
506541
{ "Right Boost Mixer", "R2 Volume", "R2" },
507542

508543
{ "Left ADC", NULL, "Left Boost Mixer" },
509544

510-
{ "Left Boost Mixer", "AUXL Volume", "AUXL" },
511545
{ "Left Boost Mixer", NULL, "Left Capture PGA" },
512546
{ "Left Boost Mixer", "L2 Volume", "L2" },
513547

@@ -522,6 +556,38 @@ static const struct snd_soc_dapm_route wm8985_dapm_routes[] = {
522556
{ "Left Input Mixer", "MicN Switch", "LIN" },
523557
{ "Left Input Mixer", "MicP Switch", "LIP" },
524558
};
559+
static const struct snd_soc_dapm_route wm8985_aux_dapm_routes[] = {
560+
{ "Right Output Mixer", "Aux Switch", "AUXR" },
561+
{ "Left Output Mixer", "Aux Switch", "AUXL" },
562+
563+
{ "Right Boost Mixer", "AUXR Volume", "AUXR" },
564+
{ "Left Boost Mixer", "AUXL Volume", "AUXL" },
565+
};
566+
567+
static int wm8985_add_widgets(struct snd_soc_codec *codec)
568+
{
569+
struct wm8985_priv *wm8985 = snd_soc_codec_get_drvdata(codec);
570+
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
571+
572+
switch (wm8985->dev_type) {
573+
case WM8758:
574+
snd_soc_dapm_new_controls(dapm, wm8758_dapm_widgets,
575+
ARRAY_SIZE(wm8758_dapm_widgets));
576+
break;
577+
578+
case WM8985:
579+
snd_soc_add_codec_controls(codec, wm8985_specific_snd_controls,
580+
ARRAY_SIZE(wm8985_specific_snd_controls));
581+
582+
snd_soc_dapm_new_controls(dapm, wm8985_dapm_widgets,
583+
ARRAY_SIZE(wm8985_dapm_widgets));
584+
snd_soc_dapm_add_routes(dapm, wm8985_aux_dapm_routes,
585+
ARRAY_SIZE(wm8985_aux_dapm_routes));
586+
break;
587+
}
588+
589+
return 0;
590+
}
525591

526592
static int eqmode_get(struct snd_kcontrol *kcontrol,
527593
struct snd_ctl_elem_value *ucontrol)
@@ -999,6 +1065,8 @@ static int wm8985_probe(struct snd_soc_codec *codec)
9991065
snd_soc_update_bits(codec, WM8985_BIAS_CTRL, WM8985_BIASCUT,
10001066
WM8985_BIASCUT);
10011067

1068+
wm8985_add_widgets(codec);
1069+
10021070
return 0;
10031071

10041072
err_reg_enable:
@@ -1042,12 +1110,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8985 = {
10421110
.set_bias_level = wm8985_set_bias_level,
10431111
.suspend_bias_off = true,
10441112

1045-
.controls = wm8985_snd_controls,
1046-
.num_controls = ARRAY_SIZE(wm8985_snd_controls),
1047-
.dapm_widgets = wm8985_dapm_widgets,
1048-
.num_dapm_widgets = ARRAY_SIZE(wm8985_dapm_widgets),
1049-
.dapm_routes = wm8985_dapm_routes,
1050-
.num_dapm_routes = ARRAY_SIZE(wm8985_dapm_routes),
1113+
.controls = wm8985_common_snd_controls,
1114+
.num_controls = ARRAY_SIZE(wm8985_common_snd_controls),
1115+
.dapm_widgets = wm8985_common_dapm_widgets,
1116+
.num_dapm_widgets = ARRAY_SIZE(wm8985_common_dapm_widgets),
1117+
.dapm_routes = wm8985_common_dapm_routes,
1118+
.num_dapm_routes = ARRAY_SIZE(wm8985_common_dapm_routes),
10511119
};
10521120

10531121
static const struct regmap_config wm8985_regmap = {
@@ -1074,6 +1142,8 @@ static int wm8985_spi_probe(struct spi_device *spi)
10741142

10751143
spi_set_drvdata(spi, wm8985);
10761144

1145+
wm8985->dev_type = WM8985;
1146+
10771147
wm8985->regmap = devm_regmap_init_spi(spi, &wm8985_regmap);
10781148
if (IS_ERR(wm8985->regmap)) {
10791149
ret = PTR_ERR(wm8985->regmap);
@@ -1115,6 +1185,8 @@ static int wm8985_i2c_probe(struct i2c_client *i2c,
11151185

11161186
i2c_set_clientdata(i2c, wm8985);
11171187

1188+
wm8985->dev_type = id->driver_data;
1189+
11181190
wm8985->regmap = devm_regmap_init_i2c(i2c, &wm8985_regmap);
11191191
if (IS_ERR(wm8985->regmap)) {
11201192
ret = PTR_ERR(wm8985->regmap);
@@ -1135,7 +1207,8 @@ static int wm8985_i2c_remove(struct i2c_client *i2c)
11351207
}
11361208

11371209
static const struct i2c_device_id wm8985_i2c_id[] = {
1138-
{ "wm8985", 0 },
1210+
{ "wm8985", WM8985 },
1211+
{ "wm8758", WM8758 },
11391212
{ }
11401213
};
11411214
MODULE_DEVICE_TABLE(i2c, wm8985_i2c_id);
@@ -1183,6 +1256,6 @@ static void __exit wm8985_exit(void)
11831256
}
11841257
module_exit(wm8985_exit);
11851258

1186-
MODULE_DESCRIPTION("ASoC WM8985 driver");
1259+
MODULE_DESCRIPTION("ASoC WM8985 / WM8758 driver");
11871260
MODULE_AUTHOR("Dimitris Papastamos <[email protected]>");
11881261
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)