summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm5100.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm5100.c')
-rw-r--r--sound/soc/codecs/wm5100.c188
1 files changed, 108 insertions, 80 deletions
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 8ea2089f7aa..4b2c724ed9b 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -50,6 +50,7 @@ struct wm5100_fll {
/* codec private data */
struct wm5100_priv {
+ struct device *dev;
struct regmap *regmap;
struct snd_soc_codec *codec;
@@ -855,48 +856,48 @@ static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w,
}
}
-static void wm5100_log_status3(struct snd_soc_codec *codec, int val)
+static void wm5100_log_status3(struct wm5100_priv *wm5100, int val)
{
if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
- dev_crit(codec->dev, "Speaker shutdown warning\n");
+ dev_crit(wm5100->dev, "Speaker shutdown warning\n");
if (val & WM5100_SPK_SHUTDOWN_EINT)
- dev_crit(codec->dev, "Speaker shutdown\n");
+ dev_crit(wm5100->dev, "Speaker shutdown\n");
if (val & WM5100_CLKGEN_ERR_EINT)
- dev_crit(codec->dev, "SYSCLK underclocked\n");
+ dev_crit(wm5100->dev, "SYSCLK underclocked\n");
if (val & WM5100_CLKGEN_ERR_ASYNC_EINT)
- dev_crit(codec->dev, "ASYNCCLK underclocked\n");
+ dev_crit(wm5100->dev, "ASYNCCLK underclocked\n");
}
-static void wm5100_log_status4(struct snd_soc_codec *codec, int val)
+static void wm5100_log_status4(struct wm5100_priv *wm5100, int val)
{
if (val & WM5100_AIF3_ERR_EINT)
- dev_err(codec->dev, "AIF3 configuration error\n");
+ dev_err(wm5100->dev, "AIF3 configuration error\n");
if (val & WM5100_AIF2_ERR_EINT)
- dev_err(codec->dev, "AIF2 configuration error\n");
+ dev_err(wm5100->dev, "AIF2 configuration error\n");
if (val & WM5100_AIF1_ERR_EINT)
- dev_err(codec->dev, "AIF1 configuration error\n");
+ dev_err(wm5100->dev, "AIF1 configuration error\n");
if (val & WM5100_CTRLIF_ERR_EINT)
- dev_err(codec->dev, "Control interface error\n");
+ dev_err(wm5100->dev, "Control interface error\n");
if (val & WM5100_ISRC2_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "ISRC2 underclocked\n");
+ dev_err(wm5100->dev, "ISRC2 underclocked\n");
if (val & WM5100_ISRC1_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "ISRC1 underclocked\n");
+ dev_err(wm5100->dev, "ISRC1 underclocked\n");
if (val & WM5100_FX_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "FX underclocked\n");
+ dev_err(wm5100->dev, "FX underclocked\n");
if (val & WM5100_AIF3_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "AIF3 underclocked\n");
+ dev_err(wm5100->dev, "AIF3 underclocked\n");
if (val & WM5100_AIF2_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "AIF2 underclocked\n");
+ dev_err(wm5100->dev, "AIF2 underclocked\n");
if (val & WM5100_AIF1_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "AIF1 underclocked\n");
+ dev_err(wm5100->dev, "AIF1 underclocked\n");
if (val & WM5100_ASRC_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "ASRC underclocked\n");
+ dev_err(wm5100->dev, "ASRC underclocked\n");
if (val & WM5100_DAC_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "DAC underclocked\n");
+ dev_err(wm5100->dev, "DAC underclocked\n");
if (val & WM5100_ADC_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "ADC underclocked\n");
+ dev_err(wm5100->dev, "ADC underclocked\n");
if (val & WM5100_MIXER_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "Mixer underclocked\n");
+ dev_err(wm5100->dev, "Mixer underclocked\n");
}
static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
@@ -904,16 +905,17 @@ static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
int ret;
ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3);
ret &= WM5100_SPK_SHUTDOWN_WARN_STS |
WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS |
WM5100_CLKGEN_ERR_ASYNC_STS;
- wm5100_log_status3(codec, ret);
+ wm5100_log_status3(wm5100, ret);
ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4);
- wm5100_log_status4(codec, ret);
+ wm5100_log_status4(wm5100, ret);
return 0;
}
@@ -2123,55 +2125,59 @@ static int wm5100_dig_vu[] = {
WM5100_DAC_DIGITAL_VOLUME_6R,
};
-static void wm5100_set_detect_mode(struct snd_soc_codec *codec, int the_mode)
+static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode)
{
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode];
BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes));
gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
- snd_soc_update_bits(codec, WM5100_ACCESSORY_DETECT_MODE_1,
- WM5100_ACCDET_BIAS_SRC_MASK |
- WM5100_ACCDET_SRC,
- (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
- mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
- snd_soc_update_bits(codec, WM5100_MISC_CONTROL,
- WM5100_HPCOM_SRC,
- mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
+ regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1,
+ WM5100_ACCDET_BIAS_SRC_MASK |
+ WM5100_ACCDET_SRC,
+ (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
+ mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
+ regmap_update_bits(wm5100->regmap, WM5100_MISC_CONTROL,
+ WM5100_HPCOM_SRC,
+ mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
wm5100->jack_mode = the_mode;
- dev_dbg(codec->dev, "Set microphone polarity to %d\n",
+ dev_dbg(wm5100->dev, "Set microphone polarity to %d\n",
wm5100->jack_mode);
}
-static void wm5100_micd_irq(struct snd_soc_codec *codec)
+static void wm5100_micd_irq(struct wm5100_priv *wm5100)
{
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- int val;
+ unsigned int val;
+ int ret;
- val = snd_soc_read(codec, WM5100_MIC_DETECT_3);
+ ret = regmap_read(wm5100->regmap, WM5100_MIC_DETECT_3, &val);
+ if (ret != 0) {
+ dev_err(wm5100->dev, "Failed to read micropone status: %d\n",
+ ret);
+ return;
+ }
- dev_dbg(codec->dev, "Microphone event: %x\n", val);
+ dev_dbg(wm5100->dev, "Microphone event: %x\n", val);
if (!(val & WM5100_ACCDET_VALID)) {
- dev_warn(codec->dev, "Microphone detection state invalid\n");
+ dev_warn(wm5100->dev, "Microphone detection state invalid\n");
return;
}
/* No accessory, reset everything and report removal */
if (!(val & WM5100_ACCDET_STS)) {
- dev_dbg(codec->dev, "Jack removal detected\n");
+ dev_dbg(wm5100->dev, "Jack removal detected\n");
wm5100->jack_mic = false;
wm5100->jack_detecting = true;
snd_soc_jack_report(wm5100->jack, 0,
SND_JACK_LINEOUT | SND_JACK_HEADSET |
SND_JACK_BTN_0);
- snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
- WM5100_ACCDET_RATE_MASK,
- WM5100_ACCDET_RATE_MASK);
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ WM5100_ACCDET_RATE_MASK);
return;
}
@@ -2181,7 +2187,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
*/
if (val & 0x400) {
if (wm5100->jack_detecting) {
- dev_dbg(codec->dev, "Microphone detected\n");
+ dev_dbg(wm5100->dev, "Microphone detected\n");
wm5100->jack_mic = true;
snd_soc_jack_report(wm5100->jack,
SND_JACK_HEADSET,
@@ -2189,11 +2195,11 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
/* Increase poll rate to give better responsiveness
* for buttons */
- snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
- WM5100_ACCDET_RATE_MASK,
- 5 << WM5100_ACCDET_RATE_SHIFT);
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ 5 << WM5100_ACCDET_RATE_SHIFT);
} else {
- dev_dbg(codec->dev, "Mic button up\n");
+ dev_dbg(wm5100->dev, "Mic button up\n");
snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0);
}
@@ -2206,7 +2212,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
* plain headphones.
*/
if (wm5100->jack_detecting && (val & 0x3f8)) {
- wm5100_set_detect_mode(codec, !wm5100->jack_mode);
+ wm5100_set_detect_mode(wm5100, !wm5100->jack_mode);
return;
}
@@ -2216,20 +2222,20 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
*/
if (val & 0x3fc) {
if (wm5100->jack_mic) {
- dev_dbg(codec->dev, "Mic button detected\n");
+ dev_dbg(wm5100->dev, "Mic button detected\n");
snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0,
SND_JACK_BTN_0);
} else if (wm5100->jack_detecting) {
- dev_dbg(codec->dev, "Headphone detected\n");
+ dev_dbg(wm5100->dev, "Headphone detected\n");
snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
SND_JACK_HEADPHONE);
/* Increase the detection rate a bit for
* responsiveness.
*/
- snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
- WM5100_ACCDET_RATE_MASK,
- 7 << WM5100_ACCDET_RATE_SHIFT);
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ 7 << WM5100_ACCDET_RATE_SHIFT);
}
}
}
@@ -2242,7 +2248,7 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
wm5100->jack = jack;
wm5100->jack_detecting = true;
- wm5100_set_detect_mode(codec, 0);
+ wm5100_set_detect_mode(wm5100, 0);
/* Slowest detection rate, gives debounce for initial
* detection */
@@ -2281,52 +2287,70 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
static irqreturn_t wm5100_irq(int irq, void *data)
{
- struct snd_soc_codec *codec = data;
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ struct wm5100_priv *wm5100 = data;
irqreturn_t status = IRQ_NONE;
- int irq_val;
+ unsigned int irq_val, mask_val;
+ int ret;
- irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3);
- if (irq_val < 0) {
- dev_err(codec->dev, "Failed to read IRQ status 3: %d\n",
- irq_val);
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, &irq_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ status 3: %d\n",
+ ret);
irq_val = 0;
}
- irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3_MASK);
- snd_soc_write(codec, WM5100_INTERRUPT_STATUS_3, irq_val);
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3_MASK,
+ &mask_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ mask 3: %d\n",
+ ret);
+ mask_val = 0xffff;
+ }
+
+ irq_val &= ~mask_val;
+
+ regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, irq_val);
if (irq_val)
status = IRQ_HANDLED;
- wm5100_log_status3(codec, irq_val);
+ wm5100_log_status3(wm5100, irq_val);
if (irq_val & WM5100_FLL1_LOCK_EINT) {
- dev_dbg(codec->dev, "FLL1 locked\n");
+ dev_dbg(wm5100->dev, "FLL1 locked\n");
complete(&wm5100->fll[0].lock);
}
if (irq_val & WM5100_FLL2_LOCK_EINT) {
- dev_dbg(codec->dev, "FLL2 locked\n");
+ dev_dbg(wm5100->dev, "FLL2 locked\n");
complete(&wm5100->fll[1].lock);
}
if (irq_val & WM5100_ACCDET_EINT)
- wm5100_micd_irq(codec);
+ wm5100_micd_irq(wm5100);
- irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4);
- if (irq_val < 0) {
- dev_err(codec->dev, "Failed to read IRQ status 4: %d\n",
- irq_val);
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, &irq_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ status 4: %d\n",
+ ret);
irq_val = 0;
}
- irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4_MASK);
+
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4_MASK,
+ &mask_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ mask 4: %d\n",
+ ret);
+ mask_val = 0xffff;
+ }
+
+ irq_val &= ~mask_val;
if (irq_val)
status = IRQ_HANDLED;
- snd_soc_write(codec, WM5100_INTERRUPT_STATUS_4, irq_val);
+ regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, irq_val);
- wm5100_log_status4(codec, irq_val);
+ wm5100_log_status4(wm5100, irq_val);
return status;
}
@@ -2485,11 +2509,12 @@ static int wm5100_probe(struct snd_soc_codec *codec)
if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
ret = request_threaded_irq(i2c->irq, NULL,
- wm5100_edge_irq,
- irq_flags, "wm5100", codec);
+ wm5100_edge_irq, irq_flags,
+ "wm5100", wm5100);
else
ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
- irq_flags, "wm5100", codec);
+ irq_flags, "wm5100",
+ wm5100);
if (ret != 0) {
dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
@@ -2552,7 +2577,7 @@ static int wm5100_probe(struct snd_soc_codec *codec)
err_gpio:
if (i2c->irq)
- free_irq(i2c->irq, codec);
+ free_irq(i2c->irq, wm5100);
return ret;
}
@@ -2566,7 +2591,8 @@ static int wm5100_remove(struct snd_soc_codec *codec)
gpio_free(wm5100->pdata.hp_pol);
}
if (i2c->irq)
- free_irq(i2c->irq, codec);
+ free_irq(i2c->irq, wm5100);
+
return 0;
}
@@ -2622,6 +2648,8 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
if (wm5100 == NULL)
return -ENOMEM;
+ wm5100->dev = &i2c->dev;
+
wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap);
if (IS_ERR(wm5100->regmap)) {
ret = PTR_ERR(wm5100->regmap);