aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8904.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8904.c')
-rw-r--r--sound/soc/codecs/wm8904.c208
1 files changed, 60 insertions, 148 deletions
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index f7dcabf6283c..33be84e506ea 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -31,9 +31,6 @@
31 31
32#include "wm8904.h" 32#include "wm8904.h"
33 33
34static struct snd_soc_codec *wm8904_codec;
35struct snd_soc_codec_device soc_codec_dev_wm8904;
36
37enum wm8904_type { 34enum wm8904_type {
38 WM8904, 35 WM8904,
39 WM8912, 36 WM8912,
@@ -52,10 +49,11 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
52 49
53/* codec private data */ 50/* codec private data */
54struct wm8904_priv { 51struct wm8904_priv {
55 struct snd_soc_codec codec; 52
56 u16 reg_cache[WM8904_MAX_REGISTER + 1]; 53 u16 reg_cache[WM8904_MAX_REGISTER + 1];
57 54
58 enum wm8904_type devtype; 55 enum wm8904_type devtype;
56 void *control_data;
59 57
60 struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; 58 struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES];
61 59
@@ -689,7 +687,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
689 struct snd_ctl_elem_value *ucontrol) 687 struct snd_ctl_elem_value *ucontrol)
690{ 688{
691 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 689 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
692 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 690 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
693 struct wm8904_pdata *pdata = wm8904->pdata; 691 struct wm8904_pdata *pdata = wm8904->pdata;
694 int value = ucontrol->value.integer.value[0]; 692 int value = ucontrol->value.integer.value[0];
695 693
@@ -760,7 +758,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
760 struct snd_ctl_elem_value *ucontrol) 758 struct snd_ctl_elem_value *ucontrol)
761{ 759{
762 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 760 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
763 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 761 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
764 struct wm8904_pdata *pdata = wm8904->pdata; 762 struct wm8904_pdata *pdata = wm8904->pdata;
765 int value = ucontrol->value.integer.value[0]; 763 int value = ucontrol->value.integer.value[0];
766 764
@@ -2218,8 +2216,8 @@ static struct snd_soc_dai_ops wm8904_dai_ops = {
2218 .digital_mute = wm8904_digital_mute, 2216 .digital_mute = wm8904_digital_mute,
2219}; 2217};
2220 2218
2221struct snd_soc_dai wm8904_dai = { 2219static struct snd_soc_dai_driver wm8904_dai = {
2222 .name = "WM8904", 2220 .name = "wm8904-hifi",
2223 .playback = { 2221 .playback = {
2224 .stream_name = "Playback", 2222 .stream_name = "Playback",
2225 .channels_min = 2, 2223 .channels_min = 2,
@@ -2237,24 +2235,17 @@ struct snd_soc_dai wm8904_dai = {
2237 .ops = &wm8904_dai_ops, 2235 .ops = &wm8904_dai_ops,
2238 .symmetric_rates = 1, 2236 .symmetric_rates = 1,
2239}; 2237};
2240EXPORT_SYMBOL_GPL(wm8904_dai);
2241 2238
2242#ifdef CONFIG_PM 2239#ifdef CONFIG_PM
2243static int wm8904_suspend(struct platform_device *pdev, pm_message_t state) 2240static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state)
2244{ 2241{
2245 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2246 struct snd_soc_codec *codec = socdev->card->codec;
2247
2248 wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); 2242 wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
2249 2243
2250 return 0; 2244 return 0;
2251} 2245}
2252 2246
2253static int wm8904_resume(struct platform_device *pdev) 2247static int wm8904_resume(struct snd_soc_codec *codec)
2254{ 2248{
2255 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2256 struct snd_soc_codec *codec = socdev->card->codec;
2257
2258 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 2249 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2259 2250
2260 return 0; 2251 return 0;
@@ -2264,9 +2255,9 @@ static int wm8904_resume(struct platform_device *pdev)
2264#define wm8904_resume NULL 2255#define wm8904_resume NULL
2265#endif 2256#endif
2266 2257
2267static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) 2258static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
2268{ 2259{
2269 struct snd_soc_codec *codec = &wm8904->codec; 2260 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2270 struct wm8904_pdata *pdata = wm8904->pdata; 2261 struct wm8904_pdata *pdata = wm8904->pdata;
2271 struct snd_kcontrol_new control = 2262 struct snd_kcontrol_new control =
2272 SOC_ENUM_EXT("EQ Mode", 2263 SOC_ENUM_EXT("EQ Mode",
@@ -2315,20 +2306,20 @@ static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904)
2315 wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; 2306 wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
2316 wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; 2307 wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
2317 2308
2318 ret = snd_soc_add_controls(&wm8904->codec, &control, 1); 2309 ret = snd_soc_add_controls(codec, &control, 1);
2319 if (ret != 0) 2310 if (ret != 0)
2320 dev_err(wm8904->codec.dev, 2311 dev_err(codec->dev,
2321 "Failed to add ReTune Mobile control: %d\n", ret); 2312 "Failed to add ReTune Mobile control: %d\n", ret);
2322} 2313}
2323 2314
2324static void wm8904_handle_pdata(struct wm8904_priv *wm8904) 2315static void wm8904_handle_pdata(struct snd_soc_codec *codec)
2325{ 2316{
2326 struct snd_soc_codec *codec = &wm8904->codec; 2317 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2327 struct wm8904_pdata *pdata = wm8904->pdata; 2318 struct wm8904_pdata *pdata = wm8904->pdata;
2328 int ret, i; 2319 int ret, i;
2329 2320
2330 if (!pdata) { 2321 if (!pdata) {
2331 snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, 2322 snd_soc_add_controls(codec, wm8904_eq_controls,
2332 ARRAY_SIZE(wm8904_eq_controls)); 2323 ARRAY_SIZE(wm8904_eq_controls));
2333 return; 2324 return;
2334 } 2325 }
@@ -2344,7 +2335,7 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
2344 wm8904->drc_texts = kmalloc(sizeof(char *) 2335 wm8904->drc_texts = kmalloc(sizeof(char *)
2345 * pdata->num_drc_cfgs, GFP_KERNEL); 2336 * pdata->num_drc_cfgs, GFP_KERNEL);
2346 if (!wm8904->drc_texts) { 2337 if (!wm8904->drc_texts) {
2347 dev_err(wm8904->codec.dev, 2338 dev_err(codec->dev,
2348 "Failed to allocate %d DRC config texts\n", 2339 "Failed to allocate %d DRC config texts\n",
2349 pdata->num_drc_cfgs); 2340 pdata->num_drc_cfgs);
2350 return; 2341 return;
@@ -2356,9 +2347,9 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
2356 wm8904->drc_enum.max = pdata->num_drc_cfgs; 2347 wm8904->drc_enum.max = pdata->num_drc_cfgs;
2357 wm8904->drc_enum.texts = wm8904->drc_texts; 2348 wm8904->drc_enum.texts = wm8904->drc_texts;
2358 2349
2359 ret = snd_soc_add_controls(&wm8904->codec, &control, 1); 2350 ret = snd_soc_add_controls(codec, &control, 1);
2360 if (ret != 0) 2351 if (ret != 0)
2361 dev_err(wm8904->codec.dev, 2352 dev_err(codec->dev,
2362 "Failed to add DRC mode control: %d\n", ret); 2353 "Failed to add DRC mode control: %d\n", ret);
2363 2354
2364 wm8904_set_drc(codec); 2355 wm8904_set_drc(codec);
@@ -2368,89 +2359,19 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
2368 pdata->num_retune_mobile_cfgs); 2359 pdata->num_retune_mobile_cfgs);
2369 2360
2370 if (pdata->num_retune_mobile_cfgs) 2361 if (pdata->num_retune_mobile_cfgs)
2371 wm8904_handle_retune_mobile_pdata(wm8904); 2362 wm8904_handle_retune_mobile_pdata(codec);
2372 else 2363 else
2373 snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, 2364 snd_soc_add_controls(codec, wm8904_eq_controls,
2374 ARRAY_SIZE(wm8904_eq_controls)); 2365 ARRAY_SIZE(wm8904_eq_controls));
2375} 2366}
2376 2367
2377static int wm8904_probe(struct platform_device *pdev)
2378{
2379 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2380 struct snd_soc_codec *codec;
2381 int ret = 0;
2382
2383 if (wm8904_codec == NULL) {
2384 dev_err(&pdev->dev, "Codec device not registered\n");
2385 return -ENODEV;
2386 }
2387 2368
2388 socdev->card->codec = wm8904_codec; 2369static int wm8904_probe(struct snd_soc_codec *codec)
2389 codec = wm8904_codec;
2390
2391 /* register pcms */
2392 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
2393 if (ret < 0) {
2394 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
2395 goto pcm_err;
2396 }
2397
2398 wm8904_handle_pdata(snd_soc_codec_get_drvdata(codec));
2399
2400 wm8904_add_widgets(codec);
2401
2402 return ret;
2403
2404pcm_err:
2405 return ret;
2406}
2407
2408static int wm8904_remove(struct platform_device *pdev)
2409{
2410 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2411
2412 snd_soc_free_pcms(socdev);
2413 snd_soc_dapm_free(socdev);
2414
2415 return 0;
2416}
2417
2418struct snd_soc_codec_device soc_codec_dev_wm8904 = {
2419 .probe = wm8904_probe,
2420 .remove = wm8904_remove,
2421 .suspend = wm8904_suspend,
2422 .resume = wm8904_resume,
2423};
2424EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904);
2425
2426static int wm8904_register(struct wm8904_priv *wm8904,
2427 enum snd_soc_control_type control)
2428{ 2370{
2371 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2429 struct wm8904_pdata *pdata = wm8904->pdata; 2372 struct wm8904_pdata *pdata = wm8904->pdata;
2430 int ret; 2373 int ret, i;
2431 struct snd_soc_codec *codec = &wm8904->codec;
2432 int i;
2433
2434 if (wm8904_codec) {
2435 dev_err(codec->dev, "Another WM8904 is registered\n");
2436 ret = -EINVAL;
2437 goto err;
2438 }
2439 2374
2440 mutex_init(&codec->mutex);
2441 INIT_LIST_HEAD(&codec->dapm_widgets);
2442 INIT_LIST_HEAD(&codec->dapm_paths);
2443
2444 snd_soc_codec_set_drvdata(codec, wm8904);
2445 codec->name = "WM8904";
2446 codec->owner = THIS_MODULE;
2447 codec->bias_level = SND_SOC_BIAS_OFF;
2448 codec->set_bias_level = wm8904_set_bias_level;
2449 codec->dai = &wm8904_dai;
2450 codec->num_dai = 1;
2451 codec->reg_cache_size = WM8904_MAX_REGISTER;
2452 codec->reg_cache = &wm8904->reg_cache;
2453 codec->volatile_register = wm8904_volatile_register;
2454 codec->cache_sync = 1; 2375 codec->cache_sync = 1;
2455 codec->idle_bias_off = 1; 2376 codec->idle_bias_off = 1;
2456 2377
@@ -2463,16 +2384,13 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2463 default: 2384 default:
2464 dev_err(codec->dev, "Unknown device type %d\n", 2385 dev_err(codec->dev, "Unknown device type %d\n",
2465 wm8904->devtype); 2386 wm8904->devtype);
2466 ret = -EINVAL; 2387 return -EINVAL;
2467 goto err;
2468 } 2388 }
2469 2389
2470 memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); 2390 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
2471
2472 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
2473 if (ret != 0) { 2391 if (ret != 0) {
2474 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 2392 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
2475 goto err; 2393 return ret;
2476 } 2394 }
2477 2395
2478 for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) 2396 for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++)
@@ -2482,7 +2400,7 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2482 wm8904->supplies); 2400 wm8904->supplies);
2483 if (ret != 0) { 2401 if (ret != 0) {
2484 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 2402 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
2485 goto err; 2403 return ret;
2486 } 2404 }
2487 2405
2488 ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), 2406 ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies),
@@ -2517,8 +2435,6 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2517 goto err_enable; 2435 goto err_enable;
2518 } 2436 }
2519 2437
2520 wm8904_dai.dev = codec->dev;
2521
2522 /* Change some default settings - latch VU and enable ZC */ 2438 /* Change some default settings - latch VU and enable ZC */
2523 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; 2439 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
2524 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; 2440 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
@@ -2563,72 +2479,68 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2563 /* Bias level configuration will have done an extra enable */ 2479 /* Bias level configuration will have done an extra enable */
2564 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); 2480 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2565 2481
2566 wm8904_codec = codec; 2482 wm8904_handle_pdata(codec);
2567 2483
2568 ret = snd_soc_register_codec(codec); 2484 wm8904_add_widgets(codec);
2569 if (ret != 0) {
2570 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
2571 goto err_enable;
2572 }
2573
2574 ret = snd_soc_register_dai(&wm8904_dai);
2575 if (ret != 0) {
2576 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
2577 goto err_codec;
2578 }
2579 2485
2580 return 0; 2486 return 0;
2581 2487
2582err_codec:
2583 snd_soc_unregister_codec(codec);
2584err_enable: 2488err_enable:
2585 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); 2489 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2586err_get: 2490err_get:
2587 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); 2491 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2588err:
2589 kfree(wm8904);
2590 return ret; 2492 return ret;
2591} 2493}
2592 2494
2593static void wm8904_unregister(struct wm8904_priv *wm8904) 2495static int wm8904_remove(struct snd_soc_codec *codec)
2594{ 2496{
2595 wm8904_set_bias_level(&wm8904->codec, SND_SOC_BIAS_OFF); 2497 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2498
2499 wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
2596 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); 2500 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2597 snd_soc_unregister_dai(&wm8904_dai); 2501
2598 snd_soc_unregister_codec(&wm8904->codec); 2502 return 0;
2599 kfree(wm8904);
2600 wm8904_codec = NULL;
2601} 2503}
2602 2504
2505static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
2506 .probe = wm8904_probe,
2507 .remove = wm8904_remove,
2508 .suspend = wm8904_suspend,
2509 .resume = wm8904_resume,
2510 .set_bias_level = wm8904_set_bias_level,
2511 .reg_cache_size = ARRAY_SIZE(wm8904_reg),
2512 .reg_word_size = sizeof(u16),
2513 .reg_cache_default = wm8904_reg,
2514 .volatile_register = wm8904_volatile_register,
2515};
2516
2603#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 2517#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
2604static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, 2518static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
2605 const struct i2c_device_id *id) 2519 const struct i2c_device_id *id)
2606{ 2520{
2607 struct wm8904_priv *wm8904; 2521 struct wm8904_priv *wm8904;
2608 struct snd_soc_codec *codec; 2522 int ret;
2609 2523
2610 wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL); 2524 wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL);
2611 if (wm8904 == NULL) 2525 if (wm8904 == NULL)
2612 return -ENOMEM; 2526 return -ENOMEM;
2613 2527
2614 codec = &wm8904->codec;
2615 codec->hw_write = (hw_write_t)i2c_master_send;
2616
2617 wm8904->devtype = id->driver_data; 2528 wm8904->devtype = id->driver_data;
2618
2619 i2c_set_clientdata(i2c, wm8904); 2529 i2c_set_clientdata(i2c, wm8904);
2620 codec->control_data = i2c; 2530 wm8904->control_data = i2c;
2621 wm8904->pdata = i2c->dev.platform_data; 2531 wm8904->pdata = i2c->dev.platform_data;
2622 2532
2623 codec->dev = &i2c->dev; 2533 ret = snd_soc_register_codec(&i2c->dev,
2624 2534 &soc_codec_dev_wm8904, &wm8904_dai, 1);
2625 return wm8904_register(wm8904, SND_SOC_I2C); 2535 if (ret < 0)
2536 kfree(wm8904);
2537 return ret;
2626} 2538}
2627 2539
2628static __devexit int wm8904_i2c_remove(struct i2c_client *client) 2540static __devexit int wm8904_i2c_remove(struct i2c_client *client)
2629{ 2541{
2630 struct wm8904_priv *wm8904 = i2c_get_clientdata(client); 2542 snd_soc_unregister_codec(&client->dev);
2631 wm8904_unregister(wm8904); 2543 kfree(i2c_get_clientdata(client));
2632 return 0; 2544 return 0;
2633} 2545}
2634 2546
@@ -2641,7 +2553,7 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);
2641 2553
2642static struct i2c_driver wm8904_i2c_driver = { 2554static struct i2c_driver wm8904_i2c_driver = {
2643 .driver = { 2555 .driver = {
2644 .name = "WM8904", 2556 .name = "wm8904-codec",
2645 .owner = THIS_MODULE, 2557 .owner = THIS_MODULE,
2646 }, 2558 },
2647 .probe = wm8904_i2c_probe, 2559 .probe = wm8904_i2c_probe,
@@ -2652,15 +2564,15 @@ static struct i2c_driver wm8904_i2c_driver = {
2652 2564
2653static int __init wm8904_modinit(void) 2565static int __init wm8904_modinit(void)
2654{ 2566{
2655 int ret; 2567 int ret = 0;
2656#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 2568#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
2657 ret = i2c_add_driver(&wm8904_i2c_driver); 2569 ret = i2c_add_driver(&wm8904_i2c_driver);
2658 if (ret != 0) { 2570 if (ret != 0) {
2659 printk(KERN_ERR "Failed to register WM8904 I2C driver: %d\n", 2571 printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",
2660 ret); 2572 ret);
2661 } 2573 }
2662#endif 2574#endif
2663 return 0; 2575 return ret;
2664} 2576}
2665module_init(wm8904_modinit); 2577module_init(wm8904_modinit);
2666 2578