Commit 67a3adab authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/wm8955', 'asoc/topic/wm8960',...

Merge remote-tracking branches 'asoc/topic/wm8955', 'asoc/topic/wm8960', 'asoc/topic/wm8961', 'asoc/topic/wm8962' and 'asoc/topic/wm8974' into asoc-next
WM8960 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "wlf,wm8960"
- reg : the I2C address of the device.
Optional properties:
- wlf,shared-lrclk: This is a boolean property. If present, the LRCM bit of
R24 (Additional control 2) gets set, indicating that ADCLRC and DACLRC pins
will be disabled only when ADC (Left and Right) and DAC (Left and Right)
are disabled.
When wm8960 works on synchronize mode and DACLRC pin is used to supply
frame clock, it will no frame clock for captrue unless enable DAC to enable
DACLRC pin. If shared-lrclk is present, no need to enable DAC for captrue.
- wlf,capless: This is a boolean property. If present, OUT3 pin will be
enabled and disabled together with HP_L and HP_R pins in response to jack
detect events.
Example:
codec: wm8960@1a {
compatible = "wlf,wm8960";
reg = <0x1a>;
wlf,shared-lrclk;
};
......@@ -866,29 +866,6 @@ static struct snd_soc_dai_driver wm8955_dai = {
.ops = &wm8955_dai_ops,
};
#ifdef CONFIG_PM
static int wm8955_suspend(struct snd_soc_codec *codec)
{
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
regcache_mark_dirty(wm8955->regmap);
return 0;
}
static int wm8955_resume(struct snd_soc_codec *codec)
{
wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
#else
#define wm8955_suspend NULL
#define wm8955_resume NULL
#endif
static int wm8955_probe(struct snd_soc_codec *codec)
{
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
......@@ -964,18 +941,10 @@ static int wm8955_probe(struct snd_soc_codec *codec)
return ret;
}
static int wm8955_remove(struct snd_soc_codec *codec)
{
wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
.probe = wm8955_probe,
.remove = wm8955_remove,
.suspend = wm8955_suspend,
.resume = wm8955_resume,
.set_bias_level = wm8955_set_bias_level,
.suspend_bias_off = true,
.controls = wm8955_snd_controls,
.num_controls = ARRAY_SIZE(wm8955_snd_controls),
......
......@@ -125,9 +125,10 @@ struct wm8960_priv {
struct snd_soc_dapm_widget *out3;
bool deemph;
int playback_fs;
struct wm8960_data pdata;
};
#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
#define wm8960_reset(c) regmap_write(c, WM8960_RESET, 0)
/* enumerated controls */
static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",
......@@ -440,8 +441,8 @@ static const struct snd_soc_dapm_route audio_paths_capless[] = {
static int wm8960_add_widgets(struct snd_soc_codec *codec)
{
struct wm8960_data *pdata = codec->dev->platform_data;
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
struct wm8960_data *pdata = &wm8960->pdata;
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct snd_soc_dapm_widget *w;
......@@ -942,56 +943,15 @@ static struct snd_soc_dai_driver wm8960_dai = {
.symmetric_rates = 1,
};
static int wm8960_suspend(struct snd_soc_codec *codec)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int wm8960_resume(struct snd_soc_codec *codec)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int wm8960_probe(struct snd_soc_codec *codec)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
struct wm8960_data *pdata = dev_get_platdata(codec->dev);
int ret;
wm8960->set_bias_level = wm8960_set_bias_level_out3;
struct wm8960_data *pdata = &wm8960->pdata;
if (!pdata) {
dev_warn(codec->dev, "No platform data supplied\n");
} else {
if (pdata->capless)
wm8960->set_bias_level = wm8960_set_bias_level_capless;
}
ret = wm8960_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
return ret;
}
wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Latch the update bits */
snd_soc_update_bits(codec, WM8960_LINVOL, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_RINVOL, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_LADC, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_RADC, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_LDAC, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_RDAC, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_LOUT1, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_ROUT1, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100);
else
wm8960->set_bias_level = wm8960_set_bias_level_out3;
snd_soc_add_codec_controls(codec, wm8960_snd_controls,
ARRAY_SIZE(wm8960_snd_controls));
......@@ -1000,21 +960,10 @@ static int wm8960_probe(struct snd_soc_codec *codec)
return 0;
}
/* power down chip */
static int wm8960_remove(struct snd_soc_codec *codec)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
.probe = wm8960_probe,
.remove = wm8960_remove,
.suspend = wm8960_suspend,
.resume = wm8960_resume,
.set_bias_level = wm8960_set_bias_level,
.suspend_bias_off = true,
};
static const struct regmap_config wm8960_regmap = {
......@@ -1029,6 +978,18 @@ static const struct regmap_config wm8960_regmap = {
.volatile_reg = wm8960_volatile,
};
static void wm8960_set_pdata_from_of(struct i2c_client *i2c,
struct wm8960_data *pdata)
{
const struct device_node *np = i2c->dev.of_node;
if (of_property_read_bool(np, "wlf,capless"))
pdata->capless = true;
if (of_property_read_bool(np, "wlf,shared-lrclk"))
pdata->shared_lrclk = true;
}
static int wm8960_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
......@@ -1045,7 +1006,18 @@ static int wm8960_i2c_probe(struct i2c_client *i2c,
if (IS_ERR(wm8960->regmap))
return PTR_ERR(wm8960->regmap);
if (pdata && pdata->shared_lrclk) {
if (pdata)
memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data));
else if (i2c->dev.of_node)
wm8960_set_pdata_from_of(i2c, &wm8960->pdata);
ret = wm8960_reset(wm8960->regmap);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
return ret;
}
if (wm8960->pdata.shared_lrclk) {
ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2,
0x4, 0x4);
if (ret != 0) {
......@@ -1055,6 +1027,18 @@ static int wm8960_i2c_probe(struct i2c_client *i2c,
}
}
/* Latch the update bits */
regmap_update_bits(wm8960->regmap, WM8960_LINVOL, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_RINVOL, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LADC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_RADC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LDAC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_RDAC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LOUT1, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_ROUT1, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LOUT2, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_ROUT2, 0x100, 0x100);
i2c_set_clientdata(i2c, wm8960);
ret = snd_soc_register_codec(&i2c->dev,
......@@ -1075,10 +1059,17 @@ static const struct i2c_device_id wm8960_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
static const struct of_device_id wm8960_of_match[] = {
{ .compatible = "wlf,wm8960", },
{ }
};
MODULE_DEVICE_TABLE(of, wm8960_of_match);
static struct i2c_driver wm8960_i2c_driver = {
.driver = {
.name = "wm8960",
.owner = THIS_MODULE,
.of_match_table = wm8960_of_match,
},
.probe = wm8960_i2c_probe,
.remove = wm8960_i2c_remove,
......
......@@ -835,7 +835,6 @@ static struct snd_soc_dai_driver wm8961_dai = {
static int wm8961_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = &codec->dapm;
u16 reg;
/* Enable class W */
......@@ -871,50 +870,33 @@ static int wm8961_probe(struct snd_soc_codec *codec)
reg &= ~WM8961_MANUAL_MODE;
snd_soc_write(codec, WM8961_CLOCKING_3, reg);
wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
snd_soc_add_codec_controls(codec, wm8961_snd_controls,
ARRAY_SIZE(wm8961_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets,
ARRAY_SIZE(wm8961_dapm_widgets));
snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
return 0;
}
static int wm8961_remove(struct snd_soc_codec *codec)
{
wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
#ifdef CONFIG_PM
static int wm8961_suspend(struct snd_soc_codec *codec)
{
wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int wm8961_resume(struct snd_soc_codec *codec)
{
snd_soc_cache_sync(codec);
wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
#else
#define wm8961_suspend NULL
#define wm8961_resume NULL
#endif
static struct snd_soc_codec_driver soc_codec_dev_wm8961 = {
.probe = wm8961_probe,
.remove = wm8961_remove,
.suspend = wm8961_suspend,
.resume = wm8961_resume,
.set_bias_level = wm8961_set_bias_level,
.suspend_bias_off = true,
.controls = wm8961_snd_controls,
.num_controls = ARRAY_SIZE(wm8961_snd_controls),
.dapm_widgets = wm8961_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(wm8961_dapm_widgets),
.dapm_routes = audio_paths,
.num_dapm_routes = ARRAY_SIZE(audio_paths),
};
static const struct regmap_config wm8961_regmap = {
......
......@@ -3554,8 +3554,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
unsigned int reg;
int ret, i, irq_pol, trigger;
wm8962 = devm_kzalloc(&i2c->dev, sizeof(struct wm8962_priv),
GFP_KERNEL);
wm8962 = devm_kzalloc(&i2c->dev, sizeof(*wm8962), GFP_KERNEL);
if (wm8962 == NULL)
return -ENOMEM;
......
......@@ -568,18 +568,6 @@ static struct snd_soc_dai_driver wm8974_dai = {
.symmetric_rates = 1,
};
static int wm8974_suspend(struct snd_soc_codec *codec)
{
wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int wm8974_resume(struct snd_soc_codec *codec)
{
wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static const struct regmap_config wm8974_regmap = {
.reg_bits = 7,
.val_bits = 9,
......@@ -599,24 +587,13 @@ static int wm8974_probe(struct snd_soc_codec *codec)
return ret;
}
wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return ret;
}
/* power down chip */
static int wm8974_remove(struct snd_soc_codec *codec)
{
wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
.probe = wm8974_probe,
.remove = wm8974_remove,
.suspend = wm8974_suspend,
.resume = wm8974_resume,
.set_bias_level = wm8974_set_bias_level,
.suspend_bias_off = true,
.controls = wm8974_snd_controls,
.num_controls = ARRAY_SIZE(wm8974_snd_controls),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment