aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs4270.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-08 18:07:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-08 18:07:14 -0400
commitf5a246eab9a268f51ba8189ea5b098a1bfff200e (patch)
treea6ff7169e0bcaca498d9aec8b0624de1b74eaecb /sound/soc/codecs/cs4270.c
parentd5bbd43d5f450c3fca058f5b85f3dfb4e8cc88c9 (diff)
parent7ff34ad80b7080fafaac8efa9ef0061708eddd51 (diff)
Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "This contains pretty many small commits covering fairly large range of files in sound/ directory. Partly because of additional API support and partly because of constantly developed ASoC and ARM stuff. Some highlights: - Introduced the helper function and documentation for exposing the channel map via control API, as discussed in Plumbers; most of PCI drivers are covered, will follow more drivers later - Most of drivers have been replaced with the new PM callbacks (if the bus is supported) - HD-audio controller got the support of runtime PM and the support of D3 clock-stop. Also changing the power_save option in sysfs kicks off immediately to enable / disable the power-save mode. - Another significant code change in HD-audio is the rewrite of firmware loading code. Other than that, most of changes in HD-audio are continued cleanups and standardization for the generic auto parser and bug fixes (HBR, device-specific fixups), in addition to the support of channel-map API. - Addition of ASoC bindings for the compressed API, used by the mid-x86 drivers. - Lots of cleanups and API refreshes for ASoC codec drivers and DaVinci. - Conversion of OMAP to dmaengine. - New machine driver for Wolfson Microelectronics Bells. - New CODEC driver for Wolfson Microelectronics WM0010. - Enhancements to the ux500 and wm2000 drivers - A new driver for DA9055 and the support for regulator bypass mode." Fix up various arm soc header file reorg conflicts. * tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (339 commits) ALSA: hda - Add new codec ALC283 ALC290 support ALSA: hda - avoid unneccesary indices on "Headphone Jack" controls ALSA: hda - fix indices on boost volume on Conexant ALSA: aloop - add locking to timer access ALSA: hda - Fix hang caused by race during suspend. sound: Remove unnecessary semicolon ALSA: hda/realtek - Fix detection of ALC271X codec ALSA: hda - Add inverted internal mic quirk for Lenovo IdeaPad U310 ALSA: hda - make Realtek/Sigmatel/Conexant use the generic unsol event ALSA: hda - make a generic unsol event handler ASoC: codecs: Add DA9055 codec driver ASoC: eukrea-tlv320: Convert it to platform driver ALSA: ASoC: add DT bindings for CS4271 ASoC: wm_hubs: Ensure volume updates are handled during class W startup ASoC: wm5110: Adding missing volume update bits ASoC: wm5110: Add OUT3R support ASoC: wm5110: Add AEC loopback support ASoC: wm5110: Rename EPOUT to HPOUT3 ASoC: arizona: Add more clock rates ASoC: arizona: Add more DSP options for mixer input muxes ...
Diffstat (limited to 'sound/soc/codecs/cs4270.c')
-rw-r--r--sound/soc/codecs/cs4270.c156
1 files changed, 86 insertions, 70 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 047917f0b8ae..8e4779812b96 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -29,6 +29,8 @@
29#include <linux/i2c.h> 29#include <linux/i2c.h>
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/regulator/consumer.h> 31#include <linux/regulator/consumer.h>
32#include <linux/of_device.h>
33#include <linux/of_gpio.h>
32 34
33/* 35/*
34 * The codec isn't really big-endian or little-endian, since the I2S 36 * The codec isn't really big-endian or little-endian, since the I2S
@@ -110,14 +112,15 @@
110 * This array contains the power-on default values of the registers, with the 112 * This array contains the power-on default values of the registers, with the
111 * exception of the "CHIPID" register (01h). The lower four bits of that 113 * exception of the "CHIPID" register (01h). The lower four bits of that
112 * register contain the hardware revision, so it is treated as volatile. 114 * register contain the hardware revision, so it is treated as volatile.
113 *
114 * Also note that on the CS4270, the first readable register is 1, but ASoC
115 * assumes the first register is 0. Therfore, the array must have an entry for
116 * register 0, but we use cs4270_reg_is_readable() to tell ASoC that it can't
117 * be read.
118 */ 115 */
119static const u8 cs4270_default_reg_cache[CS4270_LASTREG + 1] = { 116static const struct reg_default cs4270_reg_defaults[] = {
120 0x00, 0x00, 0x00, 0x30, 0x00, 0x60, 0x20, 0x00, 0x00 117 { 2, 0x00 },
118 { 3, 0x30 },
119 { 4, 0x00 },
120 { 5, 0x60 },
121 { 6, 0x20 },
122 { 7, 0x00 },
123 { 8, 0x00 },
121}; 124};
122 125
123static const char *supply_names[] = { 126static const char *supply_names[] = {
@@ -126,7 +129,7 @@ static const char *supply_names[] = {
126 129
127/* Private data for the CS4270 */ 130/* Private data for the CS4270 */
128struct cs4270_private { 131struct cs4270_private {
129 enum snd_soc_control_type control_type; 132 struct regmap *regmap;
130 unsigned int mclk; /* Input frequency of the MCLK pin */ 133 unsigned int mclk; /* Input frequency of the MCLK pin */
131 unsigned int mode; /* The mode (I2S or left-justified) */ 134 unsigned int mode; /* The mode (I2S or left-justified) */
132 unsigned int slave_mode; 135 unsigned int slave_mode;
@@ -191,12 +194,12 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = {
191/* The number of MCLK/LRCK ratios supported by the CS4270 */ 194/* The number of MCLK/LRCK ratios supported by the CS4270 */
192#define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) 195#define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios)
193 196
194static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg) 197static bool cs4270_reg_is_readable(struct device *dev, unsigned int reg)
195{ 198{
196 return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); 199 return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG);
197} 200}
198 201
199static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg) 202static bool cs4270_reg_is_volatile(struct device *dev, unsigned int reg)
200{ 203{
201 /* Unreadable registers are considered volatile */ 204 /* Unreadable registers are considered volatile */
202 if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) 205 if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
@@ -456,7 +459,7 @@ static struct snd_soc_dai_driver cs4270_dai = {
456 .name = "cs4270-hifi", 459 .name = "cs4270-hifi",
457 .playback = { 460 .playback = {
458 .stream_name = "Playback", 461 .stream_name = "Playback",
459 .channels_min = 1, 462 .channels_min = 2,
460 .channels_max = 2, 463 .channels_max = 2,
461 .rates = SNDRV_PCM_RATE_CONTINUOUS, 464 .rates = SNDRV_PCM_RATE_CONTINUOUS,
462 .rate_min = 4000, 465 .rate_min = 4000,
@@ -465,7 +468,7 @@ static struct snd_soc_dai_driver cs4270_dai = {
465 }, 468 },
466 .capture = { 469 .capture = {
467 .stream_name = "Capture", 470 .stream_name = "Capture",
468 .channels_min = 1, 471 .channels_min = 2,
469 .channels_max = 2, 472 .channels_max = 2,
470 .rates = SNDRV_PCM_RATE_CONTINUOUS, 473 .rates = SNDRV_PCM_RATE_CONTINUOUS,
471 .rate_min = 4000, 474 .rate_min = 4000,
@@ -485,12 +488,12 @@ static struct snd_soc_dai_driver cs4270_dai = {
485static int cs4270_probe(struct snd_soc_codec *codec) 488static int cs4270_probe(struct snd_soc_codec *codec)
486{ 489{
487 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); 490 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
488 int i, ret; 491 int ret;
489 492
490 /* Tell ASoC what kind of I/O to use to read the registers. ASoC will 493 /* Tell ASoC what kind of I/O to use to read the registers. ASoC will
491 * then do the I2C transactions itself. 494 * then do the I2C transactions itself.
492 */ 495 */
493 ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs4270->control_type); 496 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
494 if (ret < 0) { 497 if (ret < 0) {
495 dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); 498 dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret);
496 return ret; 499 return ret;
@@ -519,33 +522,8 @@ static int cs4270_probe(struct snd_soc_codec *codec)
519 return ret; 522 return ret;
520 } 523 }
521 524
522 /* Add the non-DAPM controls */
523 ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls,
524 ARRAY_SIZE(cs4270_snd_controls));
525 if (ret < 0) {
526 dev_err(codec->dev, "failed to add controls\n");
527 return ret;
528 }
529
530 /* get the power supply regulators */
531 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
532 cs4270->supplies[i].supply = supply_names[i];
533
534 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
535 cs4270->supplies);
536 if (ret < 0)
537 return ret;
538
539 ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), 525 ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
540 cs4270->supplies); 526 cs4270->supplies);
541 if (ret < 0)
542 goto error_free_regulators;
543
544 return 0;
545
546error_free_regulators:
547 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
548 cs4270->supplies);
549 527
550 return ret; 528 return ret;
551} 529}
@@ -561,7 +539,6 @@ static int cs4270_remove(struct snd_soc_codec *codec)
561 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); 539 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
562 540
563 regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); 541 regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
564 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
565 542
566 return 0; 543 return 0;
567}; 544};
@@ -611,7 +588,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec)
611 ndelay(500); 588 ndelay(500);
612 589
613 /* first restore the entire register cache ... */ 590 /* first restore the entire register cache ... */
614 snd_soc_cache_sync(codec); 591 regcache_sync(cs4270->regmap);
615 592
616 /* ... then disable the power-down bits */ 593 /* ... then disable the power-down bits */
617 reg = snd_soc_read(codec, CS4270_PWRCTL); 594 reg = snd_soc_read(codec, CS4270_PWRCTL);
@@ -632,11 +609,30 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = {
632 .remove = cs4270_remove, 609 .remove = cs4270_remove,
633 .suspend = cs4270_soc_suspend, 610 .suspend = cs4270_soc_suspend,
634 .resume = cs4270_soc_resume, 611 .resume = cs4270_soc_resume,
635 .volatile_register = cs4270_reg_is_volatile, 612
636 .readable_register = cs4270_reg_is_readable, 613 .controls = cs4270_snd_controls,
637 .reg_cache_size = CS4270_LASTREG + 1, 614 .num_controls = ARRAY_SIZE(cs4270_snd_controls),
638 .reg_word_size = sizeof(u8), 615};
639 .reg_cache_default = cs4270_default_reg_cache, 616
617/*
618 * cs4270_of_match - the device tree bindings
619 */
620static const struct of_device_id cs4270_of_match[] = {
621 { .compatible = "cirrus,cs4270", },
622 { }
623};
624MODULE_DEVICE_TABLE(of, cs4270_of_match);
625
626static const struct regmap_config cs4270_regmap = {
627 .reg_bits = 8,
628 .val_bits = 8,
629 .max_register = CS4270_LASTREG,
630 .reg_defaults = cs4270_reg_defaults,
631 .num_reg_defaults = ARRAY_SIZE(cs4270_reg_defaults),
632 .cache_type = REGCACHE_RBTREE,
633
634 .readable_reg = cs4270_reg_is_readable,
635 .volatile_reg = cs4270_reg_is_volatile,
640}; 636};
641 637
642/** 638/**
@@ -650,19 +646,56 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = {
650static int cs4270_i2c_probe(struct i2c_client *i2c_client, 646static int cs4270_i2c_probe(struct i2c_client *i2c_client,
651 const struct i2c_device_id *id) 647 const struct i2c_device_id *id)
652{ 648{
649 struct device_node *np = i2c_client->dev.of_node;
653 struct cs4270_private *cs4270; 650 struct cs4270_private *cs4270;
654 int ret; 651 unsigned int val;
652 int ret, i;
655 653
656 /* Verify that we have a CS4270 */ 654 cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private),
655 GFP_KERNEL);
656 if (!cs4270) {
657 dev_err(&i2c_client->dev, "could not allocate codec\n");
658 return -ENOMEM;
659 }
660
661 /* get the power supply regulators */
662 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
663 cs4270->supplies[i].supply = supply_names[i];
664
665 ret = devm_regulator_bulk_get(&i2c_client->dev,
666 ARRAY_SIZE(cs4270->supplies),
667 cs4270->supplies);
668 if (ret < 0)
669 return ret;
670
671 /* See if we have a way to bring the codec out of reset */
672 if (np) {
673 enum of_gpio_flags flags;
674 int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);
675
676 if (gpio_is_valid(gpio)) {
677 ret = devm_gpio_request_one(&i2c_client->dev, gpio,
678 flags & OF_GPIO_ACTIVE_LOW ?
679 GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
680 "cs4270 reset");
681 if (ret < 0)
682 return ret;
683 }
684 }
685
686 cs4270->regmap = devm_regmap_init_i2c(i2c_client, &cs4270_regmap);
687 if (IS_ERR(cs4270->regmap))
688 return PTR_ERR(cs4270->regmap);
657 689
658 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); 690 /* Verify that we have a CS4270 */
691 ret = regmap_read(cs4270->regmap, CS4270_CHIPID, &val);
659 if (ret < 0) { 692 if (ret < 0) {
660 dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", 693 dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n",
661 i2c_client->addr); 694 i2c_client->addr);
662 return ret; 695 return ret;
663 } 696 }
664 /* The top four bits of the chip ID should be 1100. */ 697 /* The top four bits of the chip ID should be 1100. */
665 if ((ret & 0xF0) != 0xC0) { 698 if ((val & 0xF0) != 0xC0) {
666 dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", 699 dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n",
667 i2c_client->addr); 700 i2c_client->addr);
668 return -ENODEV; 701 return -ENODEV;
@@ -670,17 +703,9 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
670 703
671 dev_info(&i2c_client->dev, "found device at i2c address %X\n", 704 dev_info(&i2c_client->dev, "found device at i2c address %X\n",
672 i2c_client->addr); 705 i2c_client->addr);
673 dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); 706 dev_info(&i2c_client->dev, "hardware revision %X\n", val & 0xF);
674
675 cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private),
676 GFP_KERNEL);
677 if (!cs4270) {
678 dev_err(&i2c_client->dev, "could not allocate codec\n");
679 return -ENOMEM;
680 }
681 707
682 i2c_set_clientdata(i2c_client, cs4270); 708 i2c_set_clientdata(i2c_client, cs4270);
683 cs4270->control_type = SND_SOC_I2C;
684 709
685 ret = snd_soc_register_codec(&i2c_client->dev, 710 ret = snd_soc_register_codec(&i2c_client->dev,
686 &soc_codec_device_cs4270, &cs4270_dai, 1); 711 &soc_codec_device_cs4270, &cs4270_dai, 1);
@@ -718,23 +743,14 @@ static struct i2c_driver cs4270_i2c_driver = {
718 .driver = { 743 .driver = {
719 .name = "cs4270", 744 .name = "cs4270",
720 .owner = THIS_MODULE, 745 .owner = THIS_MODULE,
746 .of_match_table = cs4270_of_match,
721 }, 747 },
722 .id_table = cs4270_id, 748 .id_table = cs4270_id,
723 .probe = cs4270_i2c_probe, 749 .probe = cs4270_i2c_probe,
724 .remove = cs4270_i2c_remove, 750 .remove = cs4270_i2c_remove,
725}; 751};
726 752
727static int __init cs4270_init(void) 753module_i2c_driver(cs4270_i2c_driver);
728{
729 return i2c_add_driver(&cs4270_i2c_driver);
730}
731module_init(cs4270_init);
732
733static void __exit cs4270_exit(void)
734{
735 i2c_del_driver(&cs4270_i2c_driver);
736}
737module_exit(cs4270_exit);
738 754
739MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 755MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
740MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); 756MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver");