diff options
Diffstat (limited to 'sound/soc/codecs/wm8350.c')
-rw-r--r-- | sound/soc/codecs/wm8350.c | 73 |
1 files changed, 54 insertions, 19 deletions
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 07ba7e3f6a8..6d6dc9efe91 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
27 | #include <sound/initval.h> | 27 | #include <sound/initval.h> |
28 | #include <sound/tlv.h> | 28 | #include <sound/tlv.h> |
29 | #include <trace/events/asoc.h> | ||
29 | 30 | ||
30 | #include "wm8350.h" | 31 | #include "wm8350.h" |
31 | 32 | ||
@@ -53,6 +54,7 @@ struct wm8350_output { | |||
53 | 54 | ||
54 | struct wm8350_jack_data { | 55 | struct wm8350_jack_data { |
55 | struct snd_soc_jack *jack; | 56 | struct snd_soc_jack *jack; |
57 | struct delayed_work work; | ||
56 | int report; | 58 | int report; |
57 | int short_report; | 59 | int short_report; |
58 | }; | 60 | }; |
@@ -1335,45 +1337,69 @@ static int wm8350_resume(struct snd_soc_codec *codec) | |||
1335 | return 0; | 1337 | return 0; |
1336 | } | 1338 | } |
1337 | 1339 | ||
1338 | static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) | 1340 | static void wm8350_hp_work(struct wm8350_data *priv, |
1341 | struct wm8350_jack_data *jack, | ||
1342 | u16 mask) | ||
1339 | { | 1343 | { |
1340 | struct wm8350_data *priv = data; | ||
1341 | struct wm8350 *wm8350 = priv->codec.control_data; | 1344 | struct wm8350 *wm8350 = priv->codec.control_data; |
1342 | u16 reg; | 1345 | u16 reg; |
1343 | int report; | 1346 | int report; |
1344 | int mask; | 1347 | |
1348 | reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); | ||
1349 | if (reg & mask) | ||
1350 | report = jack->report; | ||
1351 | else | ||
1352 | report = 0; | ||
1353 | |||
1354 | snd_soc_jack_report(jack->jack, report, jack->report); | ||
1355 | |||
1356 | } | ||
1357 | |||
1358 | static void wm8350_hpl_work(struct work_struct *work) | ||
1359 | { | ||
1360 | struct wm8350_data *priv = | ||
1361 | container_of(work, struct wm8350_data, hpl.work.work); | ||
1362 | |||
1363 | wm8350_hp_work(priv, &priv->hpl, WM8350_JACK_L_LVL); | ||
1364 | } | ||
1365 | |||
1366 | static void wm8350_hpr_work(struct work_struct *work) | ||
1367 | { | ||
1368 | struct wm8350_data *priv = | ||
1369 | container_of(work, struct wm8350_data, hpr.work.work); | ||
1370 | |||
1371 | wm8350_hp_work(priv, &priv->hpr, WM8350_JACK_R_LVL); | ||
1372 | } | ||
1373 | |||
1374 | static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) | ||
1375 | { | ||
1376 | struct wm8350_data *priv = data; | ||
1377 | struct wm8350 *wm8350 = priv->codec.control_data; | ||
1345 | struct wm8350_jack_data *jack = NULL; | 1378 | struct wm8350_jack_data *jack = NULL; |
1346 | 1379 | ||
1347 | switch (irq - wm8350->irq_base) { | 1380 | switch (irq - wm8350->irq_base) { |
1348 | case WM8350_IRQ_CODEC_JCK_DET_L: | 1381 | case WM8350_IRQ_CODEC_JCK_DET_L: |
1382 | #ifndef CONFIG_SND_SOC_WM8350_MODULE | ||
1383 | trace_snd_soc_jack_irq("WM8350 HPL"); | ||
1384 | #endif | ||
1349 | jack = &priv->hpl; | 1385 | jack = &priv->hpl; |
1350 | mask = WM8350_JACK_L_LVL; | ||
1351 | break; | 1386 | break; |
1352 | 1387 | ||
1353 | case WM8350_IRQ_CODEC_JCK_DET_R: | 1388 | case WM8350_IRQ_CODEC_JCK_DET_R: |
1389 | #ifndef CONFIG_SND_SOC_WM8350_MODULE | ||
1390 | trace_snd_soc_jack_irq("WM8350 HPR"); | ||
1391 | #endif | ||
1354 | jack = &priv->hpr; | 1392 | jack = &priv->hpr; |
1355 | mask = WM8350_JACK_R_LVL; | ||
1356 | break; | 1393 | break; |
1357 | 1394 | ||
1358 | default: | 1395 | default: |
1359 | BUG(); | 1396 | BUG(); |
1360 | } | 1397 | } |
1361 | 1398 | ||
1362 | if (!jack->jack) { | 1399 | if (device_may_wakeup(wm8350->dev)) |
1363 | dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); | 1400 | pm_wakeup_event(wm8350->dev, 250); |
1364 | return IRQ_NONE; | ||
1365 | } | ||
1366 | 1401 | ||
1367 | /* Debounce */ | 1402 | schedule_delayed_work(&jack->work, 200); |
1368 | msleep(200); | ||
1369 | |||
1370 | reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); | ||
1371 | if (reg & mask) | ||
1372 | report = jack->report; | ||
1373 | else | ||
1374 | report = 0; | ||
1375 | |||
1376 | snd_soc_jack_report(jack->jack, report, jack->report); | ||
1377 | 1403 | ||
1378 | return IRQ_HANDLED; | 1404 | return IRQ_HANDLED; |
1379 | } | 1405 | } |
@@ -1437,6 +1463,10 @@ static irqreturn_t wm8350_mic_handler(int irq, void *data) | |||
1437 | u16 reg; | 1463 | u16 reg; |
1438 | int report = 0; | 1464 | int report = 0; |
1439 | 1465 | ||
1466 | #ifndef CONFIG_SND_SOC_WM8350_MODULE | ||
1467 | trace_snd_soc_jack_irq("WM8350 mic"); | ||
1468 | #endif | ||
1469 | |||
1440 | reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); | 1470 | reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); |
1441 | if (reg & WM8350_JACK_MICSCD_LVL) | 1471 | if (reg & WM8350_JACK_MICSCD_LVL) |
1442 | report |= priv->mic.short_report; | 1472 | report |= priv->mic.short_report; |
@@ -1552,6 +1582,8 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) | |||
1552 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1582 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
1553 | 1583 | ||
1554 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8350_pga_work); | 1584 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8350_pga_work); |
1585 | INIT_DELAYED_WORK(&priv->hpl.work, wm8350_hpl_work); | ||
1586 | INIT_DELAYED_WORK(&priv->hpr.work, wm8350_hpr_work); | ||
1555 | 1587 | ||
1556 | /* Enable the codec */ | 1588 | /* Enable the codec */ |
1557 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1589 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
@@ -1641,6 +1673,9 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec) | |||
1641 | priv->hpr.jack = NULL; | 1673 | priv->hpr.jack = NULL; |
1642 | priv->mic.jack = NULL; | 1674 | priv->mic.jack = NULL; |
1643 | 1675 | ||
1676 | cancel_delayed_work_sync(&priv->hpl.work); | ||
1677 | cancel_delayed_work_sync(&priv->hpr.work); | ||
1678 | |||
1644 | /* if there was any work waiting then we run it now and | 1679 | /* if there was any work waiting then we run it now and |
1645 | * wait for its completion */ | 1680 | * wait for its completion */ |
1646 | flush_delayed_work_sync(&codec->dapm.delayed_work); | 1681 | flush_delayed_work_sync(&codec->dapm.delayed_work); |