aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8350.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2009-03-28 16:29:51 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-03-28 16:29:51 -0400
commited40d0c472b136682b2fcba05f89762859c7374f (patch)
tree076b83a26bcd63d6158463735dd34c10bbc591dc /sound/soc/codecs/wm8350.c
parent9e495834e59ca9b29f1a1f63b9f5533bb022ac49 (diff)
parent5d80f8e5a9dc9c9a94d4aeaa567e219a808b8a4a (diff)
Merge branch 'origin' into devel
Conflicts: sound/soc/pxa/pxa2xx-i2s.c
Diffstat (limited to 'sound/soc/codecs/wm8350.c')
-rw-r--r--sound/soc/codecs/wm8350.c166
1 files changed, 135 insertions, 31 deletions
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 35d99750c383..3b1d0993bed9 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
@@ -775,21 +782,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
775 {"Beep", NULL, "IN3R PGA"}, 782 {"Beep", NULL, "IN3R PGA"},
776}; 783};
777 784
778static int wm8350_add_controls(struct snd_soc_codec *codec)
779{
780 int err, i;
781
782 for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) {
783 err = snd_ctl_add(codec->card,
784 snd_soc_cnew(&wm8350_snd_controls[i],
785 codec, NULL));
786 if (err < 0)
787 return err;
788 }
789
790 return 0;
791}
792
793static int wm8350_add_widgets(struct snd_soc_codec *codec) 785static int wm8350_add_widgets(struct snd_soc_codec *codec)
794{ 786{
795 int ret; 787 int ret;
@@ -1309,7 +1301,7 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec,
1309static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) 1301static int wm8350_suspend(struct platform_device *pdev, pm_message_t state)
1310{ 1302{
1311 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1303 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1312 struct snd_soc_codec *codec = socdev->codec; 1304 struct snd_soc_codec *codec = socdev->card->codec;
1313 1305
1314 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); 1306 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
1315 return 0; 1307 return 0;
@@ -1318,7 +1310,7 @@ static int wm8350_suspend(struct platform_device *pdev, pm_message_t state)
1318static int wm8350_resume(struct platform_device *pdev) 1310static int wm8350_resume(struct platform_device *pdev)
1319{ 1311{
1320 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1312 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1321 struct snd_soc_codec *codec = socdev->codec; 1313 struct snd_soc_codec *codec = socdev->card->codec;
1322 1314
1323 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1315 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1324 1316
@@ -1328,6 +1320,95 @@ static int wm8350_resume(struct platform_device *pdev)
1328 return 0; 1320 return 0;
1329} 1321}
1330 1322
1323static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data)
1324{
1325 struct wm8350_data *priv = data;
1326 u16 reg;
1327 int report;
1328 int mask;
1329 struct wm8350_jack_data *jack = NULL;
1330
1331 switch (irq) {
1332 case WM8350_IRQ_CODEC_JCK_DET_L:
1333 jack = &priv->hpl;
1334 mask = WM8350_JACK_L_LVL;
1335 break;
1336
1337 case WM8350_IRQ_CODEC_JCK_DET_R:
1338 jack = &priv->hpr;
1339 mask = WM8350_JACK_R_LVL;
1340 break;
1341
1342 default:
1343 BUG();
1344 }
1345
1346 if (!jack->jack) {
1347 dev_warn(wm8350->dev, "Jack interrupt called with no jack\n");
1348 return;
1349 }
1350
1351 /* Debounce */
1352 msleep(200);
1353
1354 reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS);
1355 if (reg & mask)
1356 report = jack->report;
1357 else
1358 report = 0;
1359
1360 snd_soc_jack_report(jack->jack, report, jack->report);
1361}
1362
1363/**
1364 * wm8350_hp_jack_detect - Enable headphone jack detection.
1365 *
1366 * @codec: WM8350 codec
1367 * @which: left or right jack detect signal
1368 * @jack: jack to report detection events on
1369 * @report: value to report
1370 *
1371 * Enables the headphone jack detection of the WM8350.
1372 */
1373int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
1374 struct snd_soc_jack *jack, int report)
1375{
1376 struct wm8350_data *priv = codec->private_data;
1377 struct wm8350 *wm8350 = codec->control_data;
1378 int irq;
1379 int ena;
1380
1381 switch (which) {
1382 case WM8350_JDL:
1383 priv->hpl.jack = jack;
1384 priv->hpl.report = report;
1385 irq = WM8350_IRQ_CODEC_JCK_DET_L;
1386 ena = WM8350_JDL_ENA;
1387 break;
1388
1389 case WM8350_JDR:
1390 priv->hpr.jack = jack;
1391 priv->hpr.report = report;
1392 irq = WM8350_IRQ_CODEC_JCK_DET_R;
1393 ena = WM8350_JDR_ENA;
1394 break;
1395
1396 default:
1397 return -EINVAL;
1398 }
1399
1400 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1401 wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena);
1402
1403 /* Sync status */
1404 wm8350_hp_jack_handler(wm8350, irq, priv);
1405
1406 wm8350_unmask_irq(wm8350, irq);
1407
1408 return 0;
1409}
1410EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect);
1411
1331static struct snd_soc_codec *wm8350_codec; 1412static struct snd_soc_codec *wm8350_codec;
1332 1413
1333static int wm8350_probe(struct platform_device *pdev) 1414static int wm8350_probe(struct platform_device *pdev)
@@ -1342,8 +1423,8 @@ static int wm8350_probe(struct platform_device *pdev)
1342 1423
1343 BUG_ON(!wm8350_codec); 1424 BUG_ON(!wm8350_codec);
1344 1425
1345 socdev->codec = wm8350_codec; 1426 socdev->card->codec = wm8350_codec;
1346 codec = socdev->codec; 1427 codec = socdev->card->codec;
1347 wm8350 = codec->control_data; 1428 wm8350 = codec->control_data;
1348 priv = codec->private_data; 1429 priv = codec->private_data;
1349 1430
@@ -1381,13 +1462,21 @@ static int wm8350_probe(struct platform_device *pdev)
1381 wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, 1462 wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME,
1382 WM8350_OUT2_VU | WM8350_OUT2R_MUTE); 1463 WM8350_OUT2_VU | WM8350_OUT2R_MUTE);
1383 1464
1465 wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
1466 wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
1467 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L,
1468 wm8350_hp_jack_handler, priv);
1469 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
1470 wm8350_hp_jack_handler, priv);
1471
1384 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 1472 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1385 if (ret < 0) { 1473 if (ret < 0) {
1386 dev_err(&pdev->dev, "failed to create pcms\n"); 1474 dev_err(&pdev->dev, "failed to create pcms\n");
1387 return ret; 1475 return ret;
1388 } 1476 }
1389 1477
1390 wm8350_add_controls(codec); 1478 snd_soc_add_controls(codec, wm8350_snd_controls,
1479 ARRAY_SIZE(wm8350_snd_controls));
1391 wm8350_add_widgets(codec); 1480 wm8350_add_widgets(codec);
1392 1481
1393 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1482 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1409,10 +1498,23 @@ card_err:
1409static int wm8350_remove(struct platform_device *pdev) 1498static int wm8350_remove(struct platform_device *pdev)
1410{ 1499{
1411 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1500 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1412 struct snd_soc_codec *codec = socdev->codec; 1501 struct snd_soc_codec *codec = socdev->card->codec;
1413 struct wm8350 *wm8350 = codec->control_data; 1502 struct wm8350 *wm8350 = codec->control_data;
1503 struct wm8350_data *priv = codec->private_data;
1414 int ret; 1504 int ret;
1415 1505
1506 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
1507 WM8350_JDL_ENA | WM8350_JDR_ENA);
1508 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1509
1510 wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
1511 wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
1512 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
1513 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
1514
1515 priv->hpl.jack = NULL;
1516 priv->hpr.jack = NULL;
1517
1416 /* cancel any work waiting to be queued. */ 1518 /* cancel any work waiting to be queued. */
1417 ret = cancel_delayed_work(&codec->delayed_work); 1519 ret = cancel_delayed_work(&codec->delayed_work);
1418 1520
@@ -1436,6 +1538,16 @@ static int wm8350_remove(struct platform_device *pdev)
1436 SNDRV_PCM_FMTBIT_S20_3LE |\ 1538 SNDRV_PCM_FMTBIT_S20_3LE |\
1437 SNDRV_PCM_FMTBIT_S24_LE) 1539 SNDRV_PCM_FMTBIT_S24_LE)
1438 1540
1541static struct snd_soc_dai_ops wm8350_dai_ops = {
1542 .hw_params = wm8350_pcm_hw_params,
1543 .digital_mute = wm8350_mute,
1544 .trigger = wm8350_pcm_trigger,
1545 .set_fmt = wm8350_set_dai_fmt,
1546 .set_sysclk = wm8350_set_dai_sysclk,
1547 .set_pll = wm8350_set_fll,
1548 .set_clkdiv = wm8350_set_clkdiv,
1549};
1550
1439struct snd_soc_dai wm8350_dai = { 1551struct snd_soc_dai wm8350_dai = {
1440 .name = "WM8350", 1552 .name = "WM8350",
1441 .playback = { 1553 .playback = {
@@ -1452,15 +1564,7 @@ struct snd_soc_dai wm8350_dai = {
1452 .rates = WM8350_RATES, 1564 .rates = WM8350_RATES,
1453 .formats = WM8350_FORMATS, 1565 .formats = WM8350_FORMATS,
1454 }, 1566 },
1455 .ops = { 1567 .ops = &wm8350_dai_ops,
1456 .hw_params = wm8350_pcm_hw_params,
1457 .digital_mute = wm8350_mute,
1458 .trigger = wm8350_pcm_trigger,
1459 .set_fmt = wm8350_set_dai_fmt,
1460 .set_sysclk = wm8350_set_dai_sysclk,
1461 .set_pll = wm8350_set_fll,
1462 .set_clkdiv = wm8350_set_clkdiv,
1463 },
1464}; 1568};
1465EXPORT_SYMBOL_GPL(wm8350_dai); 1569EXPORT_SYMBOL_GPL(wm8350_dai);
1466 1570
@@ -1472,7 +1576,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8350 = {
1472}; 1576};
1473EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350); 1577EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350);
1474 1578
1475static int wm8350_codec_probe(struct platform_device *pdev) 1579static __devinit int wm8350_codec_probe(struct platform_device *pdev)
1476{ 1580{
1477 struct wm8350 *wm8350 = platform_get_drvdata(pdev); 1581 struct wm8350 *wm8350 = platform_get_drvdata(pdev);
1478 struct wm8350_data *priv; 1582 struct wm8350_data *priv;