diff options
Diffstat (limited to 'sound/soc/codecs/wm8993.c')
-rw-r--r-- | sound/soc/codecs/wm8993.c | 332 |
1 files changed, 138 insertions, 194 deletions
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index d8d300c6175f..9e5ff789b805 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
25 | #include <sound/tlv.h> | 25 | #include <sound/tlv.h> |
26 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
27 | #include <sound/soc-dapm.h> | ||
28 | #include <sound/initval.h> | 27 | #include <sound/initval.h> |
29 | #include <sound/wm8993.h> | 28 | #include <sound/wm8993.h> |
30 | 29 | ||
@@ -226,10 +225,9 @@ static struct { | |||
226 | 225 | ||
227 | struct wm8993_priv { | 226 | struct wm8993_priv { |
228 | struct wm_hubs_data hubs_data; | 227 | struct wm_hubs_data hubs_data; |
229 | u16 reg_cache[WM8993_REGISTER_COUNT]; | ||
230 | struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; | 228 | struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; |
231 | struct wm8993_platform_data pdata; | 229 | struct wm8993_platform_data pdata; |
232 | struct snd_soc_codec codec; | 230 | enum snd_soc_control_type control_type; |
233 | int master; | 231 | int master; |
234 | int sysclk_source; | 232 | int sysclk_source; |
235 | int tdm_slots; | 233 | int tdm_slots; |
@@ -244,7 +242,7 @@ struct wm8993_priv { | |||
244 | int fll_src; | 242 | int fll_src; |
245 | }; | 243 | }; |
246 | 244 | ||
247 | static int wm8993_volatile(unsigned int reg) | 245 | static int wm8993_volatile(struct snd_soc_codec *codec, unsigned int reg) |
248 | { | 246 | { |
249 | switch (reg) { | 247 | switch (reg) { |
250 | case WM8993_SOFTWARE_RESET: | 248 | case WM8993_SOFTWARE_RESET: |
@@ -326,7 +324,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | |||
326 | 324 | ||
327 | pr_debug("Fvco=%dHz\n", target); | 325 | pr_debug("Fvco=%dHz\n", target); |
328 | 326 | ||
329 | /* Find an appropraite FLL_FRATIO and factor it out of the target */ | 327 | /* Find an appropriate FLL_FRATIO and factor it out of the target */ |
330 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | 328 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { |
331 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | 329 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { |
332 | fll_div->fll_fratio = fll_fratios[i].fll_fratio; | 330 | fll_div->fll_fratio = fll_fratios[i].fll_fratio; |
@@ -367,10 +365,9 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | |||
367 | return 0; | 365 | return 0; |
368 | } | 366 | } |
369 | 367 | ||
370 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | 368 | static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source, |
371 | unsigned int Fref, unsigned int Fout) | 369 | unsigned int Fref, unsigned int Fout) |
372 | { | 370 | { |
373 | struct snd_soc_codec *codec = dai->codec; | ||
374 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 371 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
375 | u16 reg1, reg4, reg5; | 372 | u16 reg1, reg4, reg5; |
376 | struct _fll_div fll_div; | 373 | struct _fll_div fll_div; |
@@ -456,6 +453,12 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | |||
456 | return 0; | 453 | return 0; |
457 | } | 454 | } |
458 | 455 | ||
456 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | ||
457 | unsigned int Fref, unsigned int Fout) | ||
458 | { | ||
459 | return _wm8993_set_fll(dai->codec, fll_id, source, Fref, Fout); | ||
460 | } | ||
461 | |||
459 | static int configure_clock(struct snd_soc_codec *codec) | 462 | static int configure_clock(struct snd_soc_codec *codec) |
460 | { | 463 | { |
461 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 464 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
@@ -715,7 +718,8 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, | |||
715 | static int class_w_put(struct snd_kcontrol *kcontrol, | 718 | static int class_w_put(struct snd_kcontrol *kcontrol, |
716 | struct snd_ctl_elem_value *ucontrol) | 719 | struct snd_ctl_elem_value *ucontrol) |
717 | { | 720 | { |
718 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 721 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
722 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
719 | struct snd_soc_codec *codec = widget->codec; | 723 | struct snd_soc_codec *codec = widget->codec; |
720 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 724 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
721 | int ret; | 725 | int ret; |
@@ -730,6 +734,7 @@ static int class_w_put(struct snd_kcontrol *kcontrol, | |||
730 | 0); | 734 | 0); |
731 | } | 735 | } |
732 | wm8993->class_w_users++; | 736 | wm8993->class_w_users++; |
737 | wm8993->hubs_data.class_w = true; | ||
733 | } | 738 | } |
734 | 739 | ||
735 | /* Implement the change */ | 740 | /* Implement the change */ |
@@ -746,6 +751,7 @@ static int class_w_put(struct snd_kcontrol *kcontrol, | |||
746 | WM8993_CP_DYN_V); | 751 | WM8993_CP_DYN_V); |
747 | } | 752 | } |
748 | wm8993->class_w_users--; | 753 | wm8993->class_w_users--; |
754 | wm8993->hubs_data.class_w = false; | ||
749 | } | 755 | } |
750 | 756 | ||
751 | dev_dbg(codec->dev, "Indirect DAC use count now %d\n", | 757 | dev_dbg(codec->dev, "Indirect DAC use count now %d\n", |
@@ -963,7 +969,7 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec, | |||
963 | break; | 969 | break; |
964 | 970 | ||
965 | case SND_SOC_BIAS_STANDBY: | 971 | case SND_SOC_BIAS_STANDBY: |
966 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 972 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
967 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), | 973 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), |
968 | wm8993->supplies); | 974 | wm8993->supplies); |
969 | if (ret != 0) | 975 | if (ret != 0) |
@@ -1024,6 +1030,12 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec, | |||
1024 | WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA, | 1030 | WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA, |
1025 | 0); | 1031 | 0); |
1026 | 1032 | ||
1033 | snd_soc_update_bits(codec, WM8993_ANTIPOP2, | ||
1034 | WM8993_STARTUP_BIAS_ENA | | ||
1035 | WM8993_VMID_BUF_ENA | | ||
1036 | WM8993_VMID_RAMP_MASK | | ||
1037 | WM8993_BIAS_SRC, 0); | ||
1038 | |||
1027 | #ifdef CONFIG_REGULATOR | 1039 | #ifdef CONFIG_REGULATOR |
1028 | /* Post 2.6.34 we will be able to get a callback when | 1040 | /* Post 2.6.34 we will be able to get a callback when |
1029 | * the regulators are disabled which we can use but | 1041 | * the regulators are disabled which we can use but |
@@ -1038,7 +1050,7 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec, | |||
1038 | break; | 1050 | break; |
1039 | } | 1051 | } |
1040 | 1052 | ||
1041 | codec->bias_level = level; | 1053 | codec->dapm.bias_level = level; |
1042 | 1054 | ||
1043 | return 0; | 1055 | return 0; |
1044 | } | 1056 | } |
@@ -1220,7 +1232,7 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, | |||
1220 | - wm8993->fs); | 1232 | - wm8993->fs); |
1221 | for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) { | 1233 | for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) { |
1222 | cur_val = abs((wm8993->sysclk_rate / | 1234 | cur_val = abs((wm8993->sysclk_rate / |
1223 | clk_sys_rates[i].ratio) - wm8993->fs);; | 1235 | clk_sys_rates[i].ratio) - wm8993->fs); |
1224 | if (cur_val < best_val) { | 1236 | if (cur_val < best_val) { |
1225 | best = i; | 1237 | best = i; |
1226 | best_val = cur_val; | 1238 | best_val = cur_val; |
@@ -1394,8 +1406,8 @@ static struct snd_soc_dai_ops wm8993_ops = { | |||
1394 | SNDRV_PCM_FMTBIT_S24_LE |\ | 1406 | SNDRV_PCM_FMTBIT_S24_LE |\ |
1395 | SNDRV_PCM_FMTBIT_S32_LE) | 1407 | SNDRV_PCM_FMTBIT_S32_LE) |
1396 | 1408 | ||
1397 | struct snd_soc_dai wm8993_dai = { | 1409 | static struct snd_soc_dai_driver wm8993_dai = { |
1398 | .name = "WM8993", | 1410 | .name = "wm8993-hifi", |
1399 | .playback = { | 1411 | .playback = { |
1400 | .stream_name = "Playback", | 1412 | .stream_name = "Playback", |
1401 | .channels_min = 1, | 1413 | .channels_min = 1, |
@@ -1413,32 +1425,82 @@ struct snd_soc_dai wm8993_dai = { | |||
1413 | .ops = &wm8993_ops, | 1425 | .ops = &wm8993_ops, |
1414 | .symmetric_rates = 1, | 1426 | .symmetric_rates = 1, |
1415 | }; | 1427 | }; |
1416 | EXPORT_SYMBOL_GPL(wm8993_dai); | ||
1417 | |||
1418 | static struct snd_soc_codec *wm8993_codec; | ||
1419 | 1428 | ||
1420 | static int wm8993_probe(struct platform_device *pdev) | 1429 | static int wm8993_probe(struct snd_soc_codec *codec) |
1421 | { | 1430 | { |
1422 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1431 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1423 | struct snd_soc_codec *codec; | 1432 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
1424 | struct wm8993_priv *wm8993; | 1433 | int ret, i, val; |
1425 | int ret = 0; | ||
1426 | 1434 | ||
1427 | if (!wm8993_codec) { | 1435 | wm8993->hubs_data.hp_startup_mode = 1; |
1428 | dev_err(&pdev->dev, "I2C device not yet probed\n"); | 1436 | wm8993->hubs_data.dcs_codes = -2; |
1429 | goto err; | 1437 | |
1438 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1439 | if (ret != 0) { | ||
1440 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1441 | return ret; | ||
1430 | } | 1442 | } |
1431 | 1443 | ||
1432 | socdev->card->codec = wm8993_codec; | 1444 | for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) |
1433 | codec = wm8993_codec; | 1445 | wm8993->supplies[i].supply = wm8993_supply_names[i]; |
1434 | wm8993 = snd_soc_codec_get_drvdata(codec); | ||
1435 | 1446 | ||
1436 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1447 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), |
1437 | if (ret < 0) { | 1448 | wm8993->supplies); |
1438 | dev_err(codec->dev, "failed to create pcms\n"); | 1449 | if (ret != 0) { |
1439 | goto err; | 1450 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
1451 | return ret; | ||
1452 | } | ||
1453 | |||
1454 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), | ||
1455 | wm8993->supplies); | ||
1456 | if (ret != 0) { | ||
1457 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1458 | goto err_get; | ||
1440 | } | 1459 | } |
1441 | 1460 | ||
1461 | val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); | ||
1462 | if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { | ||
1463 | dev_err(codec->dev, "Invalid ID register value %x\n", val); | ||
1464 | ret = -EINVAL; | ||
1465 | goto err_enable; | ||
1466 | } | ||
1467 | |||
1468 | ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); | ||
1469 | if (ret != 0) | ||
1470 | goto err_enable; | ||
1471 | |||
1472 | codec->cache_only = 1; | ||
1473 | |||
1474 | /* By default we're using the output mixers */ | ||
1475 | wm8993->class_w_users = 2; | ||
1476 | |||
1477 | /* Latch volume update bits and default ZC on */ | ||
1478 | snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, | ||
1479 | WM8993_DAC_VU, WM8993_DAC_VU); | ||
1480 | snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, | ||
1481 | WM8993_ADC_VU, WM8993_ADC_VU); | ||
1482 | |||
1483 | /* Manualy manage the HPOUT sequencing for independent stereo | ||
1484 | * control. */ | ||
1485 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, | ||
1486 | WM8993_HPOUT1_AUTO_PU, 0); | ||
1487 | |||
1488 | /* Use automatic clock configuration */ | ||
1489 | snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); | ||
1490 | |||
1491 | wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, | ||
1492 | wm8993->pdata.lineout2_diff, | ||
1493 | wm8993->pdata.lineout1fb, | ||
1494 | wm8993->pdata.lineout2fb, | ||
1495 | wm8993->pdata.jd_scthr, | ||
1496 | wm8993->pdata.jd_thr, | ||
1497 | wm8993->pdata.micbias1_lvl, | ||
1498 | wm8993->pdata.micbias2_lvl); | ||
1499 | |||
1500 | ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1501 | if (ret != 0) | ||
1502 | goto err_enable; | ||
1503 | |||
1442 | snd_soc_add_controls(codec, wm8993_snd_controls, | 1504 | snd_soc_add_controls(codec, wm8993_snd_controls, |
1443 | ARRAY_SIZE(wm8993_snd_controls)); | 1505 | ARRAY_SIZE(wm8993_snd_controls)); |
1444 | if (wm8993->pdata.num_retune_configs != 0) { | 1506 | if (wm8993->pdata.num_retune_configs != 0) { |
@@ -1449,44 +1511,44 @@ static int wm8993_probe(struct platform_device *pdev) | |||
1449 | ARRAY_SIZE(wm8993_eq_controls)); | 1511 | ARRAY_SIZE(wm8993_eq_controls)); |
1450 | } | 1512 | } |
1451 | 1513 | ||
1452 | snd_soc_dapm_new_controls(codec, wm8993_dapm_widgets, | 1514 | snd_soc_dapm_new_controls(dapm, wm8993_dapm_widgets, |
1453 | ARRAY_SIZE(wm8993_dapm_widgets)); | 1515 | ARRAY_SIZE(wm8993_dapm_widgets)); |
1454 | wm_hubs_add_analogue_controls(codec); | 1516 | wm_hubs_add_analogue_controls(codec); |
1455 | 1517 | ||
1456 | snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); | 1518 | snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes)); |
1457 | wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, | 1519 | wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, |
1458 | wm8993->pdata.lineout2_diff); | 1520 | wm8993->pdata.lineout2_diff); |
1459 | 1521 | ||
1460 | return ret; | 1522 | return 0; |
1461 | 1523 | ||
1462 | err: | 1524 | err_enable: |
1525 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1526 | err_get: | ||
1527 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1463 | return ret; | 1528 | return ret; |
1464 | } | 1529 | } |
1465 | 1530 | ||
1466 | static int wm8993_remove(struct platform_device *pdev) | 1531 | static int wm8993_remove(struct snd_soc_codec *codec) |
1467 | { | 1532 | { |
1468 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1533 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1469 | |||
1470 | snd_soc_free_pcms(socdev); | ||
1471 | snd_soc_dapm_free(socdev); | ||
1472 | 1534 | ||
1535 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1536 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1473 | return 0; | 1537 | return 0; |
1474 | } | 1538 | } |
1475 | 1539 | ||
1476 | #ifdef CONFIG_PM | 1540 | #ifdef CONFIG_PM |
1477 | static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) | 1541 | static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1478 | { | 1542 | { |
1479 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1480 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1481 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 1543 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1482 | int fll_fout = wm8993->fll_fout; | 1544 | int fll_fout = wm8993->fll_fout; |
1483 | int fll_fref = wm8993->fll_fref; | 1545 | int fll_fref = wm8993->fll_fref; |
1484 | int ret; | 1546 | int ret; |
1485 | 1547 | ||
1486 | /* Stop the FLL in an orderly fashion */ | 1548 | /* Stop the FLL in an orderly fashion */ |
1487 | ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0); | 1549 | ret = _wm8993_set_fll(codec, 0, 0, 0, 0); |
1488 | if (ret != 0) { | 1550 | if (ret != 0) { |
1489 | dev_err(&pdev->dev, "Failed to stop FLL\n"); | 1551 | dev_err(codec->dev, "Failed to stop FLL\n"); |
1490 | return ret; | 1552 | return ret; |
1491 | } | 1553 | } |
1492 | 1554 | ||
@@ -1498,10 +1560,8 @@ static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) | |||
1498 | return 0; | 1560 | return 0; |
1499 | } | 1561 | } |
1500 | 1562 | ||
1501 | static int wm8993_resume(struct platform_device *pdev) | 1563 | static int wm8993_resume(struct snd_soc_codec *codec) |
1502 | { | 1564 | { |
1503 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1504 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1505 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 1565 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1506 | int ret; | 1566 | int ret; |
1507 | 1567 | ||
@@ -1515,7 +1575,7 @@ static int wm8993_resume(struct platform_device *pdev) | |||
1515 | wm8993->fll_fref = 0; | 1575 | wm8993->fll_fref = 0; |
1516 | wm8993->fll_fout = 0; | 1576 | wm8993->fll_fout = 0; |
1517 | 1577 | ||
1518 | ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src, | 1578 | ret = _wm8993_set_fll(codec, 0, wm8993->fll_src, |
1519 | fll_fref, fll_fout); | 1579 | fll_fref, fll_fout); |
1520 | if (ret != 0) | 1580 | if (ret != 0) |
1521 | dev_err(codec->dev, "Failed to restart FLL\n"); | 1581 | dev_err(codec->dev, "Failed to restart FLL\n"); |
@@ -1528,162 +1588,42 @@ static int wm8993_resume(struct platform_device *pdev) | |||
1528 | #define wm8993_resume NULL | 1588 | #define wm8993_resume NULL |
1529 | #endif | 1589 | #endif |
1530 | 1590 | ||
1531 | struct snd_soc_codec_device soc_codec_dev_wm8993 = { | 1591 | static struct snd_soc_codec_driver soc_codec_dev_wm8993 = { |
1532 | .probe = wm8993_probe, | 1592 | .probe = wm8993_probe, |
1533 | .remove = wm8993_remove, | 1593 | .remove = wm8993_remove, |
1534 | .suspend = wm8993_suspend, | 1594 | .suspend = wm8993_suspend, |
1535 | .resume = wm8993_resume, | 1595 | .resume = wm8993_resume, |
1596 | .set_bias_level = wm8993_set_bias_level, | ||
1597 | .reg_cache_size = ARRAY_SIZE(wm8993_reg_defaults), | ||
1598 | .reg_word_size = sizeof(u16), | ||
1599 | .reg_cache_default = wm8993_reg_defaults, | ||
1600 | .volatile_register = wm8993_volatile, | ||
1536 | }; | 1601 | }; |
1537 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); | ||
1538 | 1602 | ||
1539 | static int wm8993_i2c_probe(struct i2c_client *i2c, | 1603 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1540 | const struct i2c_device_id *id) | 1604 | static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, |
1605 | const struct i2c_device_id *id) | ||
1541 | { | 1606 | { |
1542 | struct wm8993_priv *wm8993; | 1607 | struct wm8993_priv *wm8993; |
1543 | struct snd_soc_codec *codec; | ||
1544 | unsigned int val; | ||
1545 | int ret; | 1608 | int ret; |
1546 | int i; | ||
1547 | |||
1548 | if (wm8993_codec) { | ||
1549 | dev_err(&i2c->dev, "A WM8993 is already registered\n"); | ||
1550 | return -EINVAL; | ||
1551 | } | ||
1552 | 1609 | ||
1553 | wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); | 1610 | wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); |
1554 | if (wm8993 == NULL) | 1611 | if (wm8993 == NULL) |
1555 | return -ENOMEM; | 1612 | return -ENOMEM; |
1556 | 1613 | ||
1557 | codec = &wm8993->codec; | ||
1558 | if (i2c->dev.platform_data) | ||
1559 | memcpy(&wm8993->pdata, i2c->dev.platform_data, | ||
1560 | sizeof(wm8993->pdata)); | ||
1561 | |||
1562 | mutex_init(&codec->mutex); | ||
1563 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1564 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1565 | |||
1566 | codec->name = "WM8993"; | ||
1567 | codec->volatile_register = wm8993_volatile; | ||
1568 | codec->reg_cache = wm8993->reg_cache; | ||
1569 | codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache); | ||
1570 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1571 | codec->set_bias_level = wm8993_set_bias_level; | ||
1572 | codec->dai = &wm8993_dai; | ||
1573 | codec->num_dai = 1; | ||
1574 | snd_soc_codec_set_drvdata(codec, wm8993); | ||
1575 | |||
1576 | wm8993->hubs_data.hp_startup_mode = 1; | ||
1577 | wm8993->hubs_data.dcs_codes = -2; | ||
1578 | |||
1579 | memcpy(wm8993->reg_cache, wm8993_reg_defaults, | ||
1580 | sizeof(wm8993->reg_cache)); | ||
1581 | |||
1582 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1583 | if (ret != 0) { | ||
1584 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1585 | goto err; | ||
1586 | } | ||
1587 | |||
1588 | i2c_set_clientdata(i2c, wm8993); | 1614 | i2c_set_clientdata(i2c, wm8993); |
1589 | codec->control_data = i2c; | ||
1590 | wm8993_codec = codec; | ||
1591 | |||
1592 | codec->dev = &i2c->dev; | ||
1593 | |||
1594 | for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) | ||
1595 | wm8993->supplies[i].supply = wm8993_supply_names[i]; | ||
1596 | |||
1597 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), | ||
1598 | wm8993->supplies); | ||
1599 | if (ret != 0) { | ||
1600 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1601 | goto err; | ||
1602 | } | ||
1603 | |||
1604 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), | ||
1605 | wm8993->supplies); | ||
1606 | if (ret != 0) { | ||
1607 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1608 | goto err_get; | ||
1609 | } | ||
1610 | |||
1611 | val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); | ||
1612 | if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { | ||
1613 | dev_err(codec->dev, "Invalid ID register value %x\n", val); | ||
1614 | ret = -EINVAL; | ||
1615 | goto err_enable; | ||
1616 | } | ||
1617 | |||
1618 | ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); | ||
1619 | if (ret != 0) | ||
1620 | goto err_enable; | ||
1621 | |||
1622 | codec->cache_only = 1; | ||
1623 | |||
1624 | /* By default we're using the output mixers */ | ||
1625 | wm8993->class_w_users = 2; | ||
1626 | |||
1627 | /* Latch volume update bits and default ZC on */ | ||
1628 | snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, | ||
1629 | WM8993_DAC_VU, WM8993_DAC_VU); | ||
1630 | snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, | ||
1631 | WM8993_ADC_VU, WM8993_ADC_VU); | ||
1632 | 1615 | ||
1633 | /* Manualy manage the HPOUT sequencing for independent stereo | 1616 | ret = snd_soc_register_codec(&i2c->dev, |
1634 | * control. */ | 1617 | &soc_codec_dev_wm8993, &wm8993_dai, 1); |
1635 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, | 1618 | if (ret < 0) |
1636 | WM8993_HPOUT1_AUTO_PU, 0); | 1619 | kfree(wm8993); |
1637 | |||
1638 | /* Use automatic clock configuration */ | ||
1639 | snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); | ||
1640 | |||
1641 | wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, | ||
1642 | wm8993->pdata.lineout2_diff, | ||
1643 | wm8993->pdata.lineout1fb, | ||
1644 | wm8993->pdata.lineout2fb, | ||
1645 | wm8993->pdata.jd_scthr, | ||
1646 | wm8993->pdata.jd_thr, | ||
1647 | wm8993->pdata.micbias1_lvl, | ||
1648 | wm8993->pdata.micbias2_lvl); | ||
1649 | |||
1650 | ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1651 | if (ret != 0) | ||
1652 | goto err_enable; | ||
1653 | |||
1654 | wm8993_dai.dev = codec->dev; | ||
1655 | |||
1656 | ret = snd_soc_register_dai(&wm8993_dai); | ||
1657 | if (ret != 0) | ||
1658 | goto err_bias; | ||
1659 | |||
1660 | ret = snd_soc_register_codec(codec); | ||
1661 | |||
1662 | return 0; | ||
1663 | |||
1664 | err_bias: | ||
1665 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1666 | err_enable: | ||
1667 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1668 | err_get: | ||
1669 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1670 | err: | ||
1671 | wm8993_codec = NULL; | ||
1672 | kfree(wm8993); | ||
1673 | return ret; | 1620 | return ret; |
1674 | } | 1621 | } |
1675 | 1622 | ||
1676 | static int wm8993_i2c_remove(struct i2c_client *client) | 1623 | static __devexit int wm8993_i2c_remove(struct i2c_client *client) |
1677 | { | 1624 | { |
1678 | struct wm8993_priv *wm8993 = i2c_get_clientdata(client); | 1625 | snd_soc_unregister_codec(&client->dev); |
1679 | 1626 | kfree(i2c_get_clientdata(client)); | |
1680 | snd_soc_unregister_codec(&wm8993->codec); | ||
1681 | snd_soc_unregister_dai(&wm8993_dai); | ||
1682 | |||
1683 | wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF); | ||
1684 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1685 | kfree(wm8993); | ||
1686 | |||
1687 | return 0; | 1627 | return 0; |
1688 | } | 1628 | } |
1689 | 1629 | ||
@@ -1695,30 +1635,34 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); | |||
1695 | 1635 | ||
1696 | static struct i2c_driver wm8993_i2c_driver = { | 1636 | static struct i2c_driver wm8993_i2c_driver = { |
1697 | .driver = { | 1637 | .driver = { |
1698 | .name = "WM8993", | 1638 | .name = "wm8993-codec", |
1699 | .owner = THIS_MODULE, | 1639 | .owner = THIS_MODULE, |
1700 | }, | 1640 | }, |
1701 | .probe = wm8993_i2c_probe, | 1641 | .probe = wm8993_i2c_probe, |
1702 | .remove = wm8993_i2c_remove, | 1642 | .remove = __devexit_p(wm8993_i2c_remove), |
1703 | .id_table = wm8993_i2c_id, | 1643 | .id_table = wm8993_i2c_id, |
1704 | }; | 1644 | }; |
1705 | 1645 | #endif | |
1706 | 1646 | ||
1707 | static int __init wm8993_modinit(void) | 1647 | static int __init wm8993_modinit(void) |
1708 | { | 1648 | { |
1709 | int ret; | 1649 | int ret = 0; |
1710 | 1650 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1711 | ret = i2c_add_driver(&wm8993_i2c_driver); | 1651 | ret = i2c_add_driver(&wm8993_i2c_driver); |
1712 | if (ret != 0) | 1652 | if (ret != 0) { |
1713 | pr_err("WM8993: Unable to register I2C driver: %d\n", ret); | 1653 | pr_err("WM8993: Unable to register I2C driver: %d\n", |
1714 | 1654 | ret); | |
1655 | } | ||
1656 | #endif | ||
1715 | return ret; | 1657 | return ret; |
1716 | } | 1658 | } |
1717 | module_init(wm8993_modinit); | 1659 | module_init(wm8993_modinit); |
1718 | 1660 | ||
1719 | static void __exit wm8993_exit(void) | 1661 | static void __exit wm8993_exit(void) |
1720 | { | 1662 | { |
1663 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1721 | i2c_del_driver(&wm8993_i2c_driver); | 1664 | i2c_del_driver(&wm8993_i2c_driver); |
1665 | #endif | ||
1722 | } | 1666 | } |
1723 | module_exit(wm8993_exit); | 1667 | module_exit(wm8993_exit); |
1724 | 1668 | ||