diff options
| author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-01-08 10:16:16 -0500 |
|---|---|---|
| committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-01-09 05:31:32 -0500 |
| commit | a6ba2b2dabb583e7820e567fb309d771b50cb9ff (patch) | |
| tree | 3d99d525cc1826810ac56c11f79bd69131e7c68e | |
| parent | 8a2cd6180f8fa00111843c2f4a4f4361995358e0 (diff) | |
ASoC: Implement WM8350 headphone jack detection
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
| -rw-r--r-- | include/linux/mfd/wm8350/audio.h | 1 | ||||
| -rw-r--r-- | sound/soc/codecs/wm8350.c | 116 | ||||
| -rw-r--r-- | sound/soc/codecs/wm8350.h | 8 |
3 files changed, 125 insertions, 0 deletions
diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h index af95a1d2f3a1..d899dc0223ba 100644 --- a/include/linux/mfd/wm8350/audio.h +++ b/include/linux/mfd/wm8350/audio.h | |||
| @@ -490,6 +490,7 @@ | |||
| 490 | /* | 490 | /* |
| 491 | * R231 (0xE7) - Jack Status | 491 | * R231 (0xE7) - Jack Status |
| 492 | */ | 492 | */ |
| 493 | #define WM8350_JACK_L_LVL 0x0800 | ||
| 493 | #define WM8350_JACK_R_LVL 0x0400 | 494 | #define WM8350_JACK_R_LVL 0x0400 |
| 494 | 495 | ||
| 495 | /* | 496 | /* |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index e3989d406f54..47a9dabb5235 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
| @@ -51,10 +51,17 @@ struct wm8350_output { | |||
| 51 | u16 mute; | 51 | u16 mute; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | struct wm8350_jack_data { | ||
| 55 | struct snd_soc_jack *jack; | ||
| 56 | int report; | ||
| 57 | }; | ||
| 58 | |||
| 54 | struct wm8350_data { | 59 | struct wm8350_data { |
| 55 | struct snd_soc_codec codec; | 60 | struct snd_soc_codec codec; |
| 56 | struct wm8350_output out1; | 61 | struct wm8350_output out1; |
| 57 | struct wm8350_output out2; | 62 | struct wm8350_output out2; |
| 63 | struct wm8350_jack_data hpl; | ||
| 64 | struct wm8350_jack_data hpr; | ||
| 58 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | 65 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; |
| 59 | }; | 66 | }; |
| 60 | 67 | ||
| @@ -1328,6 +1335,95 @@ static int wm8350_resume(struct platform_device *pdev) | |||
| 1328 | return 0; | 1335 | return 0; |
| 1329 | } | 1336 | } |
| 1330 | 1337 | ||
| 1338 | static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) | ||
| 1339 | { | ||
| 1340 | struct wm8350_data *priv = data; | ||
| 1341 | u16 reg; | ||
| 1342 | int report; | ||
| 1343 | int mask; | ||
| 1344 | struct wm8350_jack_data *jack = NULL; | ||
| 1345 | |||
| 1346 | switch (irq) { | ||
| 1347 | case WM8350_IRQ_CODEC_JCK_DET_L: | ||
| 1348 | jack = &priv->hpl; | ||
| 1349 | mask = WM8350_JACK_L_LVL; | ||
| 1350 | break; | ||
| 1351 | |||
| 1352 | case WM8350_IRQ_CODEC_JCK_DET_R: | ||
| 1353 | jack = &priv->hpr; | ||
| 1354 | mask = WM8350_JACK_R_LVL; | ||
| 1355 | break; | ||
| 1356 | |||
| 1357 | default: | ||
| 1358 | BUG(); | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | if (!jack->jack) { | ||
| 1362 | dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); | ||
| 1363 | return; | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | /* Debounce */ | ||
| 1367 | msleep(200); | ||
| 1368 | |||
| 1369 | reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); | ||
| 1370 | if (reg & mask) | ||
| 1371 | report = jack->report; | ||
| 1372 | else | ||
| 1373 | report = 0; | ||
| 1374 | |||
| 1375 | snd_soc_jack_report(jack->jack, report, jack->report); | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | /** | ||
| 1379 | * wm8350_hp_jack_detect - Enable headphone jack detection. | ||
| 1380 | * | ||
| 1381 | * @codec: WM8350 codec | ||
| 1382 | * @which: left or right jack detect signal | ||
| 1383 | * @jack: jack to report detection events on | ||
| 1384 | * @report: value to report | ||
| 1385 | * | ||
| 1386 | * Enables the headphone jack detection of the WM8350. | ||
| 1387 | */ | ||
| 1388 | int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, | ||
| 1389 | struct snd_soc_jack *jack, int report) | ||
| 1390 | { | ||
| 1391 | struct wm8350_data *priv = codec->private_data; | ||
| 1392 | struct wm8350 *wm8350 = codec->control_data; | ||
| 1393 | int irq; | ||
| 1394 | int ena; | ||
| 1395 | |||
| 1396 | switch (which) { | ||
| 1397 | case WM8350_JDL: | ||
| 1398 | priv->hpl.jack = jack; | ||
| 1399 | priv->hpl.report = report; | ||
| 1400 | irq = WM8350_IRQ_CODEC_JCK_DET_L; | ||
| 1401 | ena = WM8350_JDL_ENA; | ||
| 1402 | break; | ||
| 1403 | |||
| 1404 | case WM8350_JDR: | ||
| 1405 | priv->hpr.jack = jack; | ||
| 1406 | priv->hpr.report = report; | ||
| 1407 | irq = WM8350_IRQ_CODEC_JCK_DET_R; | ||
| 1408 | ena = WM8350_JDR_ENA; | ||
| 1409 | break; | ||
| 1410 | |||
| 1411 | default: | ||
| 1412 | return -EINVAL; | ||
| 1413 | } | ||
| 1414 | |||
| 1415 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); | ||
| 1416 | wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); | ||
| 1417 | |||
| 1418 | /* Sync status */ | ||
| 1419 | wm8350_hp_jack_handler(wm8350, irq, priv); | ||
| 1420 | |||
| 1421 | wm8350_unmask_irq(wm8350, irq); | ||
| 1422 | |||
| 1423 | return 0; | ||
| 1424 | } | ||
| 1425 | EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); | ||
| 1426 | |||
| 1331 | static struct snd_soc_codec *wm8350_codec; | 1427 | static struct snd_soc_codec *wm8350_codec; |
| 1332 | 1428 | ||
| 1333 | static int wm8350_probe(struct platform_device *pdev) | 1429 | static int wm8350_probe(struct platform_device *pdev) |
| @@ -1381,6 +1477,13 @@ static int wm8350_probe(struct platform_device *pdev) | |||
| 1381 | wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, | 1477 | wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, |
| 1382 | WM8350_OUT2_VU | WM8350_OUT2R_MUTE); | 1478 | WM8350_OUT2_VU | WM8350_OUT2R_MUTE); |
| 1383 | 1479 | ||
| 1480 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | ||
| 1481 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | ||
| 1482 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, | ||
| 1483 | wm8350_hp_jack_handler, priv); | ||
| 1484 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, | ||
| 1485 | wm8350_hp_jack_handler, priv); | ||
| 1486 | |||
| 1384 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1487 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
| 1385 | if (ret < 0) { | 1488 | if (ret < 0) { |
| 1386 | dev_err(&pdev->dev, "failed to create pcms\n"); | 1489 | dev_err(&pdev->dev, "failed to create pcms\n"); |
| @@ -1411,8 +1514,21 @@ static int wm8350_remove(struct platform_device *pdev) | |||
| 1411 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1514 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
| 1412 | struct snd_soc_codec *codec = socdev->codec; | 1515 | struct snd_soc_codec *codec = socdev->codec; |
| 1413 | struct wm8350 *wm8350 = codec->control_data; | 1516 | struct wm8350 *wm8350 = codec->control_data; |
| 1517 | struct wm8350_data *priv = codec->private_data; | ||
| 1414 | int ret; | 1518 | int ret; |
| 1415 | 1519 | ||
| 1520 | wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, | ||
| 1521 | WM8350_JDL_ENA | WM8350_JDR_ENA); | ||
| 1522 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); | ||
| 1523 | |||
| 1524 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | ||
| 1525 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | ||
| 1526 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | ||
| 1527 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | ||
| 1528 | |||
| 1529 | priv->hpl.jack = NULL; | ||
| 1530 | priv->hpr.jack = NULL; | ||
| 1531 | |||
| 1416 | /* cancel any work waiting to be queued. */ | 1532 | /* cancel any work waiting to be queued. */ |
| 1417 | ret = cancel_delayed_work(&codec->delayed_work); | 1533 | ret = cancel_delayed_work(&codec->delayed_work); |
| 1418 | 1534 | ||
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h index cc2887aa6c38..d11bd9288cf9 100644 --- a/sound/soc/codecs/wm8350.h +++ b/sound/soc/codecs/wm8350.h | |||
| @@ -17,4 +17,12 @@ | |||
| 17 | extern struct snd_soc_dai wm8350_dai; | 17 | extern struct snd_soc_dai wm8350_dai; |
| 18 | extern struct snd_soc_codec_device soc_codec_dev_wm8350; | 18 | extern struct snd_soc_codec_device soc_codec_dev_wm8350; |
| 19 | 19 | ||
| 20 | enum wm8350_jack { | ||
| 21 | WM8350_JDL = 1, | ||
| 22 | WM8350_JDR = 2, | ||
| 23 | }; | ||
| 24 | |||
| 25 | int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, | ||
| 26 | struct snd_soc_jack *jack, int report); | ||
| 27 | |||
| 20 | #endif | 28 | #endif |
