diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-04-07 06:28:00 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-04-07 06:28:00 -0400 |
commit | c38f62b08d800104fa9b0e9d6e9141459986c06d (patch) | |
tree | 1d04d768c8aa0c1a544d1f068317c7beb0101be2 /drivers/mfd/wm8994-core.c | |
parent | 250f32747e62cb415b85083e247184188f24e566 (diff) | |
parent | 8abe05c6eb358967f16bce8a02c88d57c82cfbd6 (diff) |
Merge tag 'asoc-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: fixes for 3.4
A bunch of driver-specific fixes and one generic fix for the new support
for platform DAPM contexts - we were picking the wrong default for the
idle_bias_off setting which was meaning we weren't actually achieving
any useful runtime PM on platform devices.
Diffstat (limited to 'drivers/mfd/wm8994-core.c')
-rw-r--r-- | drivers/mfd/wm8994-core.c | 108 |
1 files changed, 91 insertions, 17 deletions
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index f117e7fb9321..9d7ca1e978fa 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -256,6 +256,20 @@ static int wm8994_suspend(struct device *dev) | |||
256 | break; | 256 | break; |
257 | } | 257 | } |
258 | 258 | ||
259 | switch (wm8994->type) { | ||
260 | case WM1811: | ||
261 | ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2); | ||
262 | if (ret < 0) { | ||
263 | dev_err(dev, "Failed to read jackdet: %d\n", ret); | ||
264 | } else if (ret & WM1811_JACKDET_MODE_MASK) { | ||
265 | dev_dbg(dev, "CODEC still active, ignoring suspend\n"); | ||
266 | return 0; | ||
267 | } | ||
268 | break; | ||
269 | default: | ||
270 | break; | ||
271 | } | ||
272 | |||
259 | /* Disable LDO pulldowns while the device is suspended if we | 273 | /* Disable LDO pulldowns while the device is suspended if we |
260 | * don't know that something will be driving them. */ | 274 | * don't know that something will be driving them. */ |
261 | if (!wm8994->ldo_ena_always_driven) | 275 | if (!wm8994->ldo_ena_always_driven) |
@@ -345,15 +359,38 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) | |||
345 | } | 359 | } |
346 | #endif | 360 | #endif |
347 | 361 | ||
362 | static const __devinitdata struct reg_default wm8994_revc_patch[] = { | ||
363 | { 0x102, 0x3 }, | ||
364 | { 0x56, 0x3 }, | ||
365 | { 0x817, 0x0 }, | ||
366 | { 0x102, 0x0 }, | ||
367 | }; | ||
368 | |||
369 | static const __devinitdata struct reg_default wm8958_reva_patch[] = { | ||
370 | { 0x102, 0x3 }, | ||
371 | { 0xcb, 0x81 }, | ||
372 | { 0x817, 0x0 }, | ||
373 | { 0x102, 0x0 }, | ||
374 | }; | ||
375 | |||
376 | static const __devinitdata struct reg_default wm1811_reva_patch[] = { | ||
377 | { 0x102, 0x3 }, | ||
378 | { 0x56, 0x7 }, | ||
379 | { 0x5d, 0x7e }, | ||
380 | { 0x5e, 0x0 }, | ||
381 | { 0x102, 0x0 }, | ||
382 | }; | ||
383 | |||
348 | /* | 384 | /* |
349 | * Instantiate the generic non-control parts of the device. | 385 | * Instantiate the generic non-control parts of the device. |
350 | */ | 386 | */ |
351 | static int wm8994_device_init(struct wm8994 *wm8994, int irq) | 387 | static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) |
352 | { | 388 | { |
353 | struct wm8994_pdata *pdata = wm8994->dev->platform_data; | 389 | struct wm8994_pdata *pdata = wm8994->dev->platform_data; |
354 | struct regmap_config *regmap_config; | 390 | struct regmap_config *regmap_config; |
391 | const struct reg_default *regmap_patch = NULL; | ||
355 | const char *devname; | 392 | const char *devname; |
356 | int ret, i; | 393 | int ret, i, patch_regs; |
357 | int pulls = 0; | 394 | int pulls = 0; |
358 | 395 | ||
359 | dev_set_drvdata(wm8994->dev, wm8994); | 396 | dev_set_drvdata(wm8994->dev, wm8994); |
@@ -365,7 +402,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
365 | NULL, 0); | 402 | NULL, 0); |
366 | if (ret != 0) { | 403 | if (ret != 0) { |
367 | dev_err(wm8994->dev, "Failed to add children: %d\n", ret); | 404 | dev_err(wm8994->dev, "Failed to add children: %d\n", ret); |
368 | goto err_regmap; | 405 | goto err; |
369 | } | 406 | } |
370 | 407 | ||
371 | switch (wm8994->type) { | 408 | switch (wm8994->type) { |
@@ -380,7 +417,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
380 | break; | 417 | break; |
381 | default: | 418 | default: |
382 | BUG(); | 419 | BUG(); |
383 | goto err_regmap; | 420 | goto err; |
384 | } | 421 | } |
385 | 422 | ||
386 | wm8994->supplies = devm_kzalloc(wm8994->dev, | 423 | wm8994->supplies = devm_kzalloc(wm8994->dev, |
@@ -388,7 +425,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
388 | wm8994->num_supplies, GFP_KERNEL); | 425 | wm8994->num_supplies, GFP_KERNEL); |
389 | if (!wm8994->supplies) { | 426 | if (!wm8994->supplies) { |
390 | ret = -ENOMEM; | 427 | ret = -ENOMEM; |
391 | goto err_regmap; | 428 | goto err; |
392 | } | 429 | } |
393 | 430 | ||
394 | switch (wm8994->type) { | 431 | switch (wm8994->type) { |
@@ -406,14 +443,14 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
406 | break; | 443 | break; |
407 | default: | 444 | default: |
408 | BUG(); | 445 | BUG(); |
409 | goto err_regmap; | 446 | goto err; |
410 | } | 447 | } |
411 | 448 | ||
412 | ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, | 449 | ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, |
413 | wm8994->supplies); | 450 | wm8994->supplies); |
414 | if (ret != 0) { | 451 | if (ret != 0) { |
415 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); | 452 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); |
416 | goto err_regmap; | 453 | goto err; |
417 | } | 454 | } |
418 | 455 | ||
419 | ret = regulator_bulk_enable(wm8994->num_supplies, | 456 | ret = regulator_bulk_enable(wm8994->num_supplies, |
@@ -474,15 +511,44 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
474 | "revision %c not fully supported\n", | 511 | "revision %c not fully supported\n", |
475 | 'A' + wm8994->revision); | 512 | 'A' + wm8994->revision); |
476 | break; | 513 | break; |
514 | case 2: | ||
515 | case 3: | ||
516 | regmap_patch = wm8994_revc_patch; | ||
517 | patch_regs = ARRAY_SIZE(wm8994_revc_patch); | ||
518 | break; | ||
477 | default: | 519 | default: |
478 | break; | 520 | break; |
479 | } | 521 | } |
480 | break; | 522 | break; |
523 | |||
524 | case WM8958: | ||
525 | switch (wm8994->revision) { | ||
526 | case 0: | ||
527 | regmap_patch = wm8958_reva_patch; | ||
528 | patch_regs = ARRAY_SIZE(wm8958_reva_patch); | ||
529 | break; | ||
530 | default: | ||
531 | break; | ||
532 | } | ||
533 | break; | ||
534 | |||
481 | case WM1811: | 535 | case WM1811: |
482 | /* Revision C did not change the relevant layer */ | 536 | /* Revision C did not change the relevant layer */ |
483 | if (wm8994->revision > 1) | 537 | if (wm8994->revision > 1) |
484 | wm8994->revision++; | 538 | wm8994->revision++; |
539 | switch (wm8994->revision) { | ||
540 | case 0: | ||
541 | case 1: | ||
542 | case 2: | ||
543 | case 3: | ||
544 | regmap_patch = wm1811_reva_patch; | ||
545 | patch_regs = ARRAY_SIZE(wm1811_reva_patch); | ||
546 | break; | ||
547 | default: | ||
548 | break; | ||
549 | } | ||
485 | break; | 550 | break; |
551 | |||
486 | default: | 552 | default: |
487 | break; | 553 | break; |
488 | } | 554 | } |
@@ -512,6 +578,16 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
512 | return ret; | 578 | return ret; |
513 | } | 579 | } |
514 | 580 | ||
581 | if (regmap_patch) { | ||
582 | ret = regmap_register_patch(wm8994->regmap, regmap_patch, | ||
583 | patch_regs); | ||
584 | if (ret != 0) { | ||
585 | dev_err(wm8994->dev, "Failed to register patch: %d\n", | ||
586 | ret); | ||
587 | goto err; | ||
588 | } | ||
589 | } | ||
590 | |||
515 | if (pdata) { | 591 | if (pdata) { |
516 | wm8994->irq_base = pdata->irq_base; | 592 | wm8994->irq_base = pdata->irq_base; |
517 | wm8994->gpio_base = pdata->gpio_base; | 593 | wm8994->gpio_base = pdata->gpio_base; |
@@ -563,7 +639,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
563 | } | 639 | } |
564 | 640 | ||
565 | pm_runtime_enable(wm8994->dev); | 641 | pm_runtime_enable(wm8994->dev); |
566 | pm_runtime_resume(wm8994->dev); | 642 | pm_runtime_idle(wm8994->dev); |
567 | 643 | ||
568 | return 0; | 644 | return 0; |
569 | 645 | ||
@@ -574,13 +650,12 @@ err_enable: | |||
574 | wm8994->supplies); | 650 | wm8994->supplies); |
575 | err_get: | 651 | err_get: |
576 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); | 652 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); |
577 | err_regmap: | 653 | err: |
578 | regmap_exit(wm8994->regmap); | ||
579 | mfd_remove_devices(wm8994->dev); | 654 | mfd_remove_devices(wm8994->dev); |
580 | return ret; | 655 | return ret; |
581 | } | 656 | } |
582 | 657 | ||
583 | static void wm8994_device_exit(struct wm8994 *wm8994) | 658 | static __devexit void wm8994_device_exit(struct wm8994 *wm8994) |
584 | { | 659 | { |
585 | pm_runtime_disable(wm8994->dev); | 660 | pm_runtime_disable(wm8994->dev); |
586 | mfd_remove_devices(wm8994->dev); | 661 | mfd_remove_devices(wm8994->dev); |
@@ -588,7 +663,6 @@ static void wm8994_device_exit(struct wm8994 *wm8994) | |||
588 | regulator_bulk_disable(wm8994->num_supplies, | 663 | regulator_bulk_disable(wm8994->num_supplies, |
589 | wm8994->supplies); | 664 | wm8994->supplies); |
590 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); | 665 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); |
591 | regmap_exit(wm8994->regmap); | ||
592 | } | 666 | } |
593 | 667 | ||
594 | static const struct of_device_id wm8994_of_match[] = { | 668 | static const struct of_device_id wm8994_of_match[] = { |
@@ -599,8 +673,8 @@ static const struct of_device_id wm8994_of_match[] = { | |||
599 | }; | 673 | }; |
600 | MODULE_DEVICE_TABLE(of, wm8994_of_match); | 674 | MODULE_DEVICE_TABLE(of, wm8994_of_match); |
601 | 675 | ||
602 | static int wm8994_i2c_probe(struct i2c_client *i2c, | 676 | static __devinit int wm8994_i2c_probe(struct i2c_client *i2c, |
603 | const struct i2c_device_id *id) | 677 | const struct i2c_device_id *id) |
604 | { | 678 | { |
605 | struct wm8994 *wm8994; | 679 | struct wm8994 *wm8994; |
606 | int ret; | 680 | int ret; |
@@ -614,7 +688,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, | |||
614 | wm8994->irq = i2c->irq; | 688 | wm8994->irq = i2c->irq; |
615 | wm8994->type = id->driver_data; | 689 | wm8994->type = id->driver_data; |
616 | 690 | ||
617 | wm8994->regmap = regmap_init_i2c(i2c, &wm8994_base_regmap_config); | 691 | wm8994->regmap = devm_regmap_init_i2c(i2c, &wm8994_base_regmap_config); |
618 | if (IS_ERR(wm8994->regmap)) { | 692 | if (IS_ERR(wm8994->regmap)) { |
619 | ret = PTR_ERR(wm8994->regmap); | 693 | ret = PTR_ERR(wm8994->regmap); |
620 | dev_err(wm8994->dev, "Failed to allocate register map: %d\n", | 694 | dev_err(wm8994->dev, "Failed to allocate register map: %d\n", |
@@ -625,7 +699,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, | |||
625 | return wm8994_device_init(wm8994, i2c->irq); | 699 | return wm8994_device_init(wm8994, i2c->irq); |
626 | } | 700 | } |
627 | 701 | ||
628 | static int wm8994_i2c_remove(struct i2c_client *i2c) | 702 | static __devexit int wm8994_i2c_remove(struct i2c_client *i2c) |
629 | { | 703 | { |
630 | struct wm8994 *wm8994 = i2c_get_clientdata(i2c); | 704 | struct wm8994 *wm8994 = i2c_get_clientdata(i2c); |
631 | 705 | ||
@@ -654,7 +728,7 @@ static struct i2c_driver wm8994_i2c_driver = { | |||
654 | .of_match_table = wm8994_of_match, | 728 | .of_match_table = wm8994_of_match, |
655 | }, | 729 | }, |
656 | .probe = wm8994_i2c_probe, | 730 | .probe = wm8994_i2c_probe, |
657 | .remove = wm8994_i2c_remove, | 731 | .remove = __devexit_p(wm8994_i2c_remove), |
658 | .id_table = wm8994_i2c_id, | 732 | .id_table = wm8994_i2c_id, |
659 | }; | 733 | }; |
660 | 734 | ||