+
static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {
SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1),
SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1),
@@ -324,6 +343,13 @@ SND_SOC_DAPM_INPUT("AINL"),
SND_SOC_DAPM_INPUT("AINR"),
};
+static const struct snd_soc_dapm_widget wm8580_dac4_dapm_widgets[] = {
+SND_SOC_DAPM_DAC("DAC4", "Playback", WM8580_PWRDN1, 5, 1),
+
+SND_SOC_DAPM_OUTPUT("VOUT4L"),
+SND_SOC_DAPM_OUTPUT("VOUT4R"),
+};
+
static const struct snd_soc_dapm_route wm8580_dapm_routes[] = {
{ "VOUT1L", NULL, "DAC1" },
{ "VOUT1R", NULL, "DAC1" },
@@ -338,6 +364,11 @@ static const struct snd_soc_dapm_route wm8580_dapm_routes[] = {
{ "ADC", NULL, "AINR" },
};
+static const struct snd_soc_dapm_route wm8580_dac4_dapm_routes[] = {
+ { "VOUT4L", NULL, "DAC4" },
+ { "VOUT4R", NULL, "DAC4" },
+};
+
/* PLL divisors */
struct _pll_div {
u32 prescale:1;
@@ -837,19 +868,16 @@ static const struct snd_soc_dai_ops wm8580_dai_ops_capture = {
static struct snd_soc_dai_driver wm8580_dai[] = {
{
- .name = "wm8580-hifi-playback",
.id = WM8580_DAI_PAIFRX,
.playback = {
.stream_name = "Playback",
.channels_min = 1,
- .channels_max = 6,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = WM8580_FORMATS,
},
.ops = &wm8580_dai_ops_playback,
},
{
- .name = "wm8580-hifi-capture",
.id = WM8580_DAI_PAIFTX,
.capture = {
.stream_name = "Capture",
@@ -865,8 +893,22 @@ static struct snd_soc_dai_driver wm8580_dai[] = {
static int wm8580_probe(struct snd_soc_codec *codec)
{
struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
int ret = 0;
+ switch (wm8580->drvdata->num_dacs) {
+ case 4:
+ snd_soc_add_codec_controls(codec, wm8580_dac4_snd_controls,
+ ARRAY_SIZE(wm8580_dac4_snd_controls));
+ snd_soc_dapm_new_controls(dapm, wm8580_dac4_dapm_widgets,
+ ARRAY_SIZE(wm8580_dac4_dapm_widgets));
+ snd_soc_dapm_add_routes(dapm, wm8580_dac4_dapm_routes,
+ ARRAY_SIZE(wm8580_dac4_dapm_routes));
+ break;
+ default:
+ break;
+ }
+
ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
wm8580->supplies);
if (ret != 0) {
@@ -914,12 +956,6 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
},
};
-static const struct of_device_id wm8580_of_match[] = {
- { .compatible = "wlf,wm8580" },
- { },
-};
-MODULE_DEVICE_TABLE(of, wm8580_of_match);
-
static const struct regmap_config wm8580_regmap = {
.reg_bits = 7,
.val_bits = 9,
@@ -932,10 +968,32 @@ static const struct regmap_config wm8580_regmap = {
.volatile_reg = wm8580_volatile,
};
+const struct wm8580_driver_data wm8580_data = {
+ .name_playback = "wm8580-hifi-playback",
+ .name_capture = "wm8580-hifi-capture",
+ .num_dacs = 3,
+};
+EXPORT_SYMBOL_GPL(wm8580_data);
+
+const struct wm8580_driver_data wm8581_data = {
+ .name_playback = "wm8581-hifi-playback",
+ .name_capture = "wm8581-hifi-capture",
+ .num_dacs = 4,
+};
+EXPORT_SYMBOL_GPL(wm8581_data);
+
+static const struct of_device_id wm8580_of_match[] = {
+ { .compatible = "wlf,wm8580", .data = &wm8580_data },
+ { .compatible = "wlf,wm8581", .data = &wm8581_data },
+ { },
+};
+MODULE_DEVICE_TABLE(of, wm8580_of_match);
+
#if IS_ENABLED(CONFIG_I2C)
static int wm8580_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ const struct of_device_id *of_id;
struct wm8580_priv *wm8580;
int ret, i;
@@ -960,6 +1018,20 @@ static int wm8580_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8580);
+ of_id = of_match_device(wm8580_of_match, &i2c->dev);
+ if (of_id)
+ wm8580->drvdata = of_id->data;
+
+ if (!wm8580->drvdata) {
+ dev_err(&i2c->dev, "failed to find driver data\n");
+ return -EINVAL;
+ }
+
+ /* Each dac supports stereo input */
+ wm8580_dai[0].playback.channels_max = wm8580->drvdata->num_dacs * 2;
+ wm8580_dai[0].name = wm8580->drvdata->name_playback;
+ wm8580_dai[1].name = wm8580->drvdata->name_capture;