aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8350.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-01-08 10:16:16 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-01-09 05:31:32 -0500
commita6ba2b2dabb583e7820e567fb309d771b50cb9ff (patch)
tree3d99d525cc1826810ac56c11f79bd69131e7c68e /sound/soc/codecs/wm8350.c
parent8a2cd6180f8fa00111843c2f4a4f4361995358e0 (diff)
ASoC: Implement WM8350 headphone jack detection
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8350.c')
-rw-r--r--sound/soc/codecs/wm8350.c116
1 files changed, 116 insertions, 0 deletions
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
54struct wm8350_jack_data {
55 struct snd_soc_jack *jack;
56 int report;
57};
58
54struct wm8350_data { 59struct 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
1338static 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 */
1388int 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}
1425EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect);
1426
1331static struct snd_soc_codec *wm8350_codec; 1427static struct snd_soc_codec *wm8350_codec;
1332 1428
1333static int wm8350_probe(struct platform_device *pdev) 1429static 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