diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-02-03 14:33:49 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-02-04 05:43:10 -0500 |
commit | 8c1264740e7c9688c5d11b96d26e4393618ef60e (patch) | |
tree | 89c0cab2621dc358dcbb89987198e1d17111bb41 /sound | |
parent | e4bc669610d75106a00b0f96f2410ac5898ef1ca (diff) |
ASoC: Add WM8912 DAC support
The WM8912 is a DAC only device register compatible with the WM8904
CODEC with ADC portions omitted. Support it within the WM8904 driver
based on the configured I2C device name.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/wm8904.c | 90 |
1 files changed, 72 insertions, 18 deletions
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 80dd8df0b864..593e47d0e0eb 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -33,6 +33,11 @@ | |||
33 | static struct snd_soc_codec *wm8904_codec; | 33 | static struct snd_soc_codec *wm8904_codec; |
34 | struct snd_soc_codec_device soc_codec_dev_wm8904; | 34 | struct snd_soc_codec_device soc_codec_dev_wm8904; |
35 | 35 | ||
36 | enum wm8904_type { | ||
37 | WM8904, | ||
38 | WM8912, | ||
39 | }; | ||
40 | |||
36 | #define WM8904_NUM_DCS_CHANNELS 4 | 41 | #define WM8904_NUM_DCS_CHANNELS 4 |
37 | 42 | ||
38 | #define WM8904_NUM_SUPPLIES 5 | 43 | #define WM8904_NUM_SUPPLIES 5 |
@@ -49,6 +54,8 @@ struct wm8904_priv { | |||
49 | struct snd_soc_codec codec; | 54 | struct snd_soc_codec codec; |
50 | u16 reg_cache[WM8904_MAX_REGISTER + 1]; | 55 | u16 reg_cache[WM8904_MAX_REGISTER + 1]; |
51 | 56 | ||
57 | enum wm8904_type devtype; | ||
58 | |||
52 | struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; | 59 | struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; |
53 | 60 | ||
54 | struct wm8904_pdata *pdata; | 61 | struct wm8904_pdata *pdata; |
@@ -1411,30 +1418,62 @@ static const struct snd_soc_dapm_route wm8904_intercon[] = { | |||
1411 | { "LINER PGA", NULL, "LINER Mux" }, | 1418 | { "LINER PGA", NULL, "LINER Mux" }, |
1412 | }; | 1419 | }; |
1413 | 1420 | ||
1421 | static const struct snd_soc_dapm_route wm8912_intercon[] = { | ||
1422 | { "HPL PGA", NULL, "DACL" }, | ||
1423 | { "HPR PGA", NULL, "DACR" }, | ||
1424 | |||
1425 | { "LINEL PGA", NULL, "DACL" }, | ||
1426 | { "LINER PGA", NULL, "DACR" }, | ||
1427 | }; | ||
1428 | |||
1414 | static int wm8904_add_widgets(struct snd_soc_codec *codec) | 1429 | static int wm8904_add_widgets(struct snd_soc_codec *codec) |
1415 | { | 1430 | { |
1416 | snd_soc_add_controls(codec, wm8904_adc_snd_controls, | 1431 | struct wm8904_priv *wm8904 = codec->private_data; |
1417 | ARRAY_SIZE(wm8904_adc_snd_controls)); | ||
1418 | snd_soc_add_controls(codec, wm8904_dac_snd_controls, | ||
1419 | ARRAY_SIZE(wm8904_dac_snd_controls)); | ||
1420 | snd_soc_add_controls(codec, wm8904_snd_controls, | ||
1421 | ARRAY_SIZE(wm8904_snd_controls)); | ||
1422 | 1432 | ||
1423 | snd_soc_dapm_new_controls(codec, wm8904_core_dapm_widgets, | 1433 | snd_soc_dapm_new_controls(codec, wm8904_core_dapm_widgets, |
1424 | ARRAY_SIZE(wm8904_core_dapm_widgets)); | 1434 | ARRAY_SIZE(wm8904_core_dapm_widgets)); |
1425 | snd_soc_dapm_new_controls(codec, wm8904_adc_dapm_widgets, | ||
1426 | ARRAY_SIZE(wm8904_adc_dapm_widgets)); | ||
1427 | snd_soc_dapm_new_controls(codec, wm8904_dac_dapm_widgets, | ||
1428 | ARRAY_SIZE(wm8904_dac_dapm_widgets)); | ||
1429 | snd_soc_dapm_new_controls(codec, wm8904_dapm_widgets, | ||
1430 | ARRAY_SIZE(wm8904_dapm_widgets)); | ||
1431 | |||
1432 | snd_soc_dapm_add_routes(codec, core_intercon, | 1435 | snd_soc_dapm_add_routes(codec, core_intercon, |
1433 | ARRAY_SIZE(core_intercon)); | 1436 | ARRAY_SIZE(core_intercon)); |
1434 | snd_soc_dapm_add_routes(codec, adc_intercon, ARRAY_SIZE(adc_intercon)); | 1437 | |
1435 | snd_soc_dapm_add_routes(codec, dac_intercon, ARRAY_SIZE(dac_intercon)); | 1438 | switch (wm8904->devtype) { |
1436 | snd_soc_dapm_add_routes(codec, wm8904_intercon, | 1439 | case WM8904: |
1437 | ARRAY_SIZE(wm8904_intercon)); | 1440 | snd_soc_add_controls(codec, wm8904_adc_snd_controls, |
1441 | ARRAY_SIZE(wm8904_adc_snd_controls)); | ||
1442 | snd_soc_add_controls(codec, wm8904_dac_snd_controls, | ||
1443 | ARRAY_SIZE(wm8904_dac_snd_controls)); | ||
1444 | snd_soc_add_controls(codec, wm8904_snd_controls, | ||
1445 | ARRAY_SIZE(wm8904_snd_controls)); | ||
1446 | |||
1447 | snd_soc_dapm_new_controls(codec, wm8904_adc_dapm_widgets, | ||
1448 | ARRAY_SIZE(wm8904_adc_dapm_widgets)); | ||
1449 | snd_soc_dapm_new_controls(codec, wm8904_dac_dapm_widgets, | ||
1450 | ARRAY_SIZE(wm8904_dac_dapm_widgets)); | ||
1451 | snd_soc_dapm_new_controls(codec, wm8904_dapm_widgets, | ||
1452 | ARRAY_SIZE(wm8904_dapm_widgets)); | ||
1453 | |||
1454 | snd_soc_dapm_add_routes(codec, core_intercon, | ||
1455 | ARRAY_SIZE(core_intercon)); | ||
1456 | snd_soc_dapm_add_routes(codec, adc_intercon, | ||
1457 | ARRAY_SIZE(adc_intercon)); | ||
1458 | snd_soc_dapm_add_routes(codec, dac_intercon, | ||
1459 | ARRAY_SIZE(dac_intercon)); | ||
1460 | snd_soc_dapm_add_routes(codec, wm8904_intercon, | ||
1461 | ARRAY_SIZE(wm8904_intercon)); | ||
1462 | break; | ||
1463 | |||
1464 | case WM8912: | ||
1465 | snd_soc_add_controls(codec, wm8904_dac_snd_controls, | ||
1466 | ARRAY_SIZE(wm8904_dac_snd_controls)); | ||
1467 | |||
1468 | snd_soc_dapm_new_controls(codec, wm8904_dac_dapm_widgets, | ||
1469 | ARRAY_SIZE(wm8904_dac_dapm_widgets)); | ||
1470 | |||
1471 | snd_soc_dapm_add_routes(codec, dac_intercon, | ||
1472 | ARRAY_SIZE(dac_intercon)); | ||
1473 | snd_soc_dapm_add_routes(codec, wm8912_intercon, | ||
1474 | ARRAY_SIZE(wm8912_intercon)); | ||
1475 | break; | ||
1476 | } | ||
1438 | 1477 | ||
1439 | snd_soc_dapm_new_widgets(codec); | 1478 | snd_soc_dapm_new_widgets(codec); |
1440 | return 0; | 1479 | return 0; |
@@ -2412,6 +2451,18 @@ static int wm8904_register(struct wm8904_priv *wm8904, | |||
2412 | codec->cache_sync = 1; | 2451 | codec->cache_sync = 1; |
2413 | codec->idle_bias_off = 1; | 2452 | codec->idle_bias_off = 1; |
2414 | 2453 | ||
2454 | switch (wm8904->devtype) { | ||
2455 | case WM8904: | ||
2456 | break; | ||
2457 | case WM8912: | ||
2458 | memset(&wm8904_dai.capture, 0, sizeof(wm8904_dai.capture)); | ||
2459 | break; | ||
2460 | default: | ||
2461 | dev_err(codec->dev, "Unknown device type %d\n", | ||
2462 | wm8904->devtype); | ||
2463 | return -EINVAL; | ||
2464 | } | ||
2465 | |||
2415 | memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); | 2466 | memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); |
2416 | 2467 | ||
2417 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | 2468 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); |
@@ -2542,6 +2593,8 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, | |||
2542 | codec = &wm8904->codec; | 2593 | codec = &wm8904->codec; |
2543 | codec->hw_write = (hw_write_t)i2c_master_send; | 2594 | codec->hw_write = (hw_write_t)i2c_master_send; |
2544 | 2595 | ||
2596 | wm8904->devtype = id->driver_data; | ||
2597 | |||
2545 | i2c_set_clientdata(i2c, wm8904); | 2598 | i2c_set_clientdata(i2c, wm8904); |
2546 | codec->control_data = i2c; | 2599 | codec->control_data = i2c; |
2547 | wm8904->pdata = i2c->dev.platform_data; | 2600 | wm8904->pdata = i2c->dev.platform_data; |
@@ -2559,7 +2612,8 @@ static __devexit int wm8904_i2c_remove(struct i2c_client *client) | |||
2559 | } | 2612 | } |
2560 | 2613 | ||
2561 | static const struct i2c_device_id wm8904_i2c_id[] = { | 2614 | static const struct i2c_device_id wm8904_i2c_id[] = { |
2562 | { "wm8904", 0 }, | 2615 | { "wm8904", WM8904 }, |
2616 | { "wm8912", WM8912 }, | ||
2563 | { } | 2617 | { } |
2564 | }; | 2618 | }; |
2565 | MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); | 2619 | MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); |