aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFang, Yang A <yang.a.fang@intel.com>2015-07-07 17:21:47 -0400
committerMark Brown <broonie@kernel.org>2015-07-08 13:40:08 -0400
commitc4a99a4b4f6ef56e9c8182920680b84a7129ca80 (patch)
tree3a2a93d2f414a9360ef52f25d9b91f3c889d03c0
parentd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754 (diff)
ASoC: ts3a227e: do not report jack status when there is i2c read err
After suspend -> resume the ts3a227e_interrupt sometimes comes before i2c controller resume is called .regmap_read will return incorrect status and report a wrong jack status.This patch will disable irq on suspend and enable irq again on the resume to make sure interrupt is coming after TI resumes. Also We should return if there is read err,the interrupt will come again since it is level triggered and we are not yet clear the interrupt. In addtion,cht_bsw_max98090_ti machine driver registered additional notifier base on jack event which will program the audio codec.there will be codec timeout err if such event occurs prior to i2c controller is resumed. Signed-off-by: Fang, Yang A <yang.a.fang@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/ts3a227e.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c
index 12232d7db4c5..ffc6f3028cc5 100644
--- a/sound/soc/codecs/ts3a227e.c
+++ b/sound/soc/codecs/ts3a227e.c
@@ -23,11 +23,13 @@
23#include "ts3a227e.h" 23#include "ts3a227e.h"
24 24
25struct ts3a227e { 25struct ts3a227e {
26 struct device *dev;
26 struct regmap *regmap; 27 struct regmap *regmap;
27 struct snd_soc_jack *jack; 28 struct snd_soc_jack *jack;
28 bool plugged; 29 bool plugged;
29 bool mic_present; 30 bool mic_present;
30 unsigned int buttons_held; 31 unsigned int buttons_held;
32 int irq;
31}; 33};
32 34
33/* Button values to be reported on the jack */ 35/* Button values to be reported on the jack */
@@ -189,16 +191,28 @@ static irqreturn_t ts3a227e_interrupt(int irq, void *data)
189 struct ts3a227e *ts3a227e = (struct ts3a227e *)data; 191 struct ts3a227e *ts3a227e = (struct ts3a227e *)data;
190 struct regmap *regmap = ts3a227e->regmap; 192 struct regmap *regmap = ts3a227e->regmap;
191 unsigned int int_reg, kp_int_reg, acc_reg, i; 193 unsigned int int_reg, kp_int_reg, acc_reg, i;
194 struct device *dev = ts3a227e->dev;
195 int ret;
192 196
193 /* Check for plug/unplug. */ 197 /* Check for plug/unplug. */
194 regmap_read(regmap, TS3A227E_REG_INTERRUPT, &int_reg); 198 ret = regmap_read(regmap, TS3A227E_REG_INTERRUPT, &int_reg);
199 if (ret) {
200 dev_err(dev, "failed to clear interrupt ret=%d\n", ret);
201 return IRQ_NONE;
202 }
203
195 if (int_reg & (DETECTION_COMPLETE_EVENT | INS_REM_EVENT)) { 204 if (int_reg & (DETECTION_COMPLETE_EVENT | INS_REM_EVENT)) {
196 regmap_read(regmap, TS3A227E_REG_ACCESSORY_STATUS, &acc_reg); 205 regmap_read(regmap, TS3A227E_REG_ACCESSORY_STATUS, &acc_reg);
197 ts3a227e_new_jack_state(ts3a227e, acc_reg); 206 ts3a227e_new_jack_state(ts3a227e, acc_reg);
198 } 207 }
199 208
200 /* Report any key events. */ 209 /* Report any key events. */
201 regmap_read(regmap, TS3A227E_REG_KP_INTERRUPT, &kp_int_reg); 210 ret = regmap_read(regmap, TS3A227E_REG_KP_INTERRUPT, &kp_int_reg);
211 if (ret) {
212 dev_err(dev, "failed to clear key interrupt ret=%d\n", ret);
213 return IRQ_NONE;
214 }
215
202 for (i = 0; i < TS3A227E_NUM_BUTTONS; i++) { 216 for (i = 0; i < TS3A227E_NUM_BUTTONS; i++) {
203 if (kp_int_reg & PRESS_MASK(i)) 217 if (kp_int_reg & PRESS_MASK(i))
204 ts3a227e->buttons_held |= (1 << i); 218 ts3a227e->buttons_held |= (1 << i);
@@ -283,6 +297,8 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c,
283 return -ENOMEM; 297 return -ENOMEM;
284 298
285 i2c_set_clientdata(i2c, ts3a227e); 299 i2c_set_clientdata(i2c, ts3a227e);
300 ts3a227e->dev = dev;
301 ts3a227e->irq = i2c->irq;
286 302
287 ts3a227e->regmap = devm_regmap_init_i2c(i2c, &ts3a227e_regmap_config); 303 ts3a227e->regmap = devm_regmap_init_i2c(i2c, &ts3a227e_regmap_config);
288 if (IS_ERR(ts3a227e->regmap)) 304 if (IS_ERR(ts3a227e->regmap))
@@ -320,6 +336,32 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c,
320 return 0; 336 return 0;
321} 337}
322 338
339#ifdef CONFIG_PM_SLEEP
340static int ts3a227e_suspend(struct device *dev)
341{
342 struct ts3a227e *ts3a227e = dev_get_drvdata(dev);
343
344 dev_dbg(ts3a227e->dev, "suspend disable irq\n");
345 disable_irq(ts3a227e->irq);
346
347 return 0;
348}
349
350static int ts3a227e_resume(struct device *dev)
351{
352 struct ts3a227e *ts3a227e = dev_get_drvdata(dev);
353
354 dev_dbg(ts3a227e->dev, "resume enable irq\n");
355 enable_irq(ts3a227e->irq);
356
357 return 0;
358}
359#endif
360
361static const struct dev_pm_ops ts3a227e_pm = {
362 SET_SYSTEM_SLEEP_PM_OPS(ts3a227e_suspend, ts3a227e_resume)
363};
364
323static const struct i2c_device_id ts3a227e_i2c_ids[] = { 365static const struct i2c_device_id ts3a227e_i2c_ids[] = {
324 { "ts3a227e", 0 }, 366 { "ts3a227e", 0 },
325 { } 367 { }
@@ -336,6 +378,7 @@ static struct i2c_driver ts3a227e_driver = {
336 .driver = { 378 .driver = {
337 .name = "ts3a227e", 379 .name = "ts3a227e",
338 .owner = THIS_MODULE, 380 .owner = THIS_MODULE,
381 .pm = &ts3a227e_pm,
339 .of_match_table = of_match_ptr(ts3a227e_of_match), 382 .of_match_table = of_match_ptr(ts3a227e_of_match),
340 }, 383 },
341 .probe = ts3a227e_i2c_probe, 384 .probe = ts3a227e_i2c_probe,