aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/uda1380.c
diff options
context:
space:
mode:
authorVasily Khoruzhick <anarsoul@gmail.com>2010-08-30 04:28:07 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-08-31 08:25:17 -0400
commit8614d310a2ba78cfc73ab12da112c3115801f94e (patch)
treec5a4b21a132d0931393bf74e59bde1c24453d897 /sound/soc/codecs/uda1380.c
parent4e48541676f019145b555761d89bf4f8607d3de0 (diff)
ASoC: uda1380: make driver more powersave-friendly
Disable some codec modules in standby mode, completely disable codec in off mode to save some power. Fix suspend/resume: mark mixer regs as dirty on resume to restore mixer values, otherwise driver produces no sound (master is muted by default). Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> Acked-by: Marek Vasut <marek.vasut@gmail.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/uda1380.c')
-rw-r--r--sound/soc/codecs/uda1380.c145
1 files changed, 105 insertions, 40 deletions
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 1a51c816e542..488f8010e405 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -39,6 +39,7 @@ struct uda1380_priv {
39 u16 reg_cache[UDA1380_CACHEREGNUM]; 39 u16 reg_cache[UDA1380_CACHEREGNUM];
40 unsigned int dac_clk; 40 unsigned int dac_clk;
41 struct work_struct work; 41 struct work_struct work;
42 void *control_data;
42}; 43};
43 44
44/* 45/*
@@ -129,7 +130,46 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
129 return -EIO; 130 return -EIO;
130} 131}
131 132
132#define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0) 133static void uda1380_sync_cache(struct snd_soc_codec *codec)
134{
135 int reg;
136 u8 data[3];
137 u16 *cache = codec->reg_cache;
138
139 /* Sync reg_cache with the hardware */
140 for (reg = 0; reg < UDA1380_MVOL; reg++) {
141 data[0] = reg;
142 data[1] = (cache[reg] & 0xff00) >> 8;
143 data[2] = cache[reg] & 0x00ff;
144 if (codec->hw_write(codec->control_data, data, 3) != 3)
145 dev_err(codec->dev, "%s: write to reg 0x%x failed\n",
146 __func__, reg);
147 }
148}
149
150static int uda1380_reset(struct snd_soc_codec *codec)
151{
152 struct uda1380_platform_data *pdata = codec->dev->platform_data;
153
154 if (gpio_is_valid(pdata->gpio_reset)) {
155 gpio_set_value(pdata->gpio_reset, 1);
156 mdelay(1);
157 gpio_set_value(pdata->gpio_reset, 0);
158 } else {
159 u8 data[3];
160
161 data[0] = UDA1380_RESET;
162 data[1] = 0;
163 data[2] = 0;
164
165 if (codec->hw_write(codec->control_data, data, 3) != 3) {
166 dev_err(codec->dev, "%s: failed\n", __func__);
167 return -EIO;
168 }
169 }
170
171 return 0;
172}
133 173
134static void uda1380_flush_work(struct work_struct *work) 174static void uda1380_flush_work(struct work_struct *work)
135{ 175{
@@ -560,18 +600,40 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec,
560 enum snd_soc_bias_level level) 600 enum snd_soc_bias_level level)
561{ 601{
562 int pm = uda1380_read_reg_cache(codec, UDA1380_PM); 602 int pm = uda1380_read_reg_cache(codec, UDA1380_PM);
603 int reg;
604 struct uda1380_platform_data *pdata = codec->dev->platform_data;
605
606 if (codec->bias_level == level)
607 return 0;
563 608
564 switch (level) { 609 switch (level) {
565 case SND_SOC_BIAS_ON: 610 case SND_SOC_BIAS_ON:
566 case SND_SOC_BIAS_PREPARE: 611 case SND_SOC_BIAS_PREPARE:
612 /* ADC, DAC on */
567 uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm); 613 uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm);
568 break; 614 break;
569 case SND_SOC_BIAS_STANDBY: 615 case SND_SOC_BIAS_STANDBY:
570 uda1380_write(codec, UDA1380_PM, R02_PON_BIAS); 616 if (codec->bias_level == SND_SOC_BIAS_OFF) {
571 break; 617 if (gpio_is_valid(pdata->gpio_power)) {
572 case SND_SOC_BIAS_OFF: 618 gpio_set_value(pdata->gpio_power, 1);
619 uda1380_reset(codec);
620 }
621
622 uda1380_sync_cache(codec);
623 }
573 uda1380_write(codec, UDA1380_PM, 0x0); 624 uda1380_write(codec, UDA1380_PM, 0x0);
574 break; 625 break;
626 case SND_SOC_BIAS_OFF:
627 if (!gpio_is_valid(pdata->gpio_power))
628 break;
629
630 gpio_set_value(pdata->gpio_power, 0);
631
632 /* Mark mixer regs cache dirty to sync them with
633 * codec regs on power on.
634 */
635 for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++)
636 set_bit(reg - 0x10, &uda1380_cache_dirty);
575 } 637 }
576 codec->bias_level = level; 638 codec->bias_level = level;
577 return 0; 639 return 0;
@@ -651,16 +713,6 @@ static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state)
651 713
652static int uda1380_resume(struct snd_soc_codec *codec) 714static int uda1380_resume(struct snd_soc_codec *codec)
653{ 715{
654 int i;
655 u8 data[2];
656 u16 *cache = codec->reg_cache;
657
658 /* Sync reg_cache with the hardware */
659 for (i = 0; i < ARRAY_SIZE(uda1380_reg); i++) {
660 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
661 data[1] = cache[i] & 0x00ff;
662 codec->hw_write(codec->control_data, data, 2);
663 }
664 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 716 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
665 return 0; 717 return 0;
666} 718}
@@ -671,29 +723,36 @@ static int uda1380_probe(struct snd_soc_codec *codec)
671 struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); 723 struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
672 int ret; 724 int ret;
673 725
726 uda1380->codec = codec;
727
674 codec->hw_write = (hw_write_t)i2c_master_send; 728 codec->hw_write = (hw_write_t)i2c_master_send;
729 codec->control_data = uda1380->control_data;
675 730
676 if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) 731 if (!pdata)
677 return -EINVAL; 732 return -EINVAL;
678 733
679 ret = gpio_request(pdata->gpio_power, "uda1380 power"); 734 if (gpio_is_valid(pdata->gpio_reset)) {
680 if (ret) 735 ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
681 return ret; 736 if (ret)
682 ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); 737 goto err_out;
683 if (ret) 738 ret = gpio_direction_output(pdata->gpio_reset, 0);
684 goto err_gpio; 739 if (ret)
685 740 goto err_gpio_reset_conf;
686 gpio_direction_output(pdata->gpio_power, 1); 741 }
687
688 /* we may need to have the clock running here - pH5 */
689 gpio_direction_output(pdata->gpio_reset, 1);
690 udelay(5);
691 gpio_set_value(pdata->gpio_reset, 0);
692 742
693 ret = uda1380_reset(codec); 743 if (gpio_is_valid(pdata->gpio_power)) {
694 if (ret < 0) { 744 ret = gpio_request(pdata->gpio_power, "uda1380 power");
695 dev_err(codec->dev, "Failed to issue reset\n"); 745 if (ret)
696 goto err_reset; 746 goto err_gpio;
747 ret = gpio_direction_output(pdata->gpio_power, 0);
748 if (ret)
749 goto err_gpio_power_conf;
750 } else {
751 ret = uda1380_reset(codec);
752 if (ret) {
753 dev_err(codec->dev, "Failed to issue reset\n");
754 goto err_reset;
755 }
697 } 756 }
698 757
699 INIT_WORK(&uda1380->work, uda1380_flush_work); 758 INIT_WORK(&uda1380->work, uda1380_flush_work);
@@ -703,10 +762,11 @@ static int uda1380_probe(struct snd_soc_codec *codec)
703 /* set clock input */ 762 /* set clock input */
704 switch (pdata->dac_clk) { 763 switch (pdata->dac_clk) {
705 case UDA1380_DAC_CLK_SYSCLK: 764 case UDA1380_DAC_CLK_SYSCLK:
706 uda1380_write(codec, UDA1380_CLK, 0); 765 uda1380_write_reg_cache(codec, UDA1380_CLK, 0);
707 break; 766 break;
708 case UDA1380_DAC_CLK_WSPLL: 767 case UDA1380_DAC_CLK_WSPLL:
709 uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); 768 uda1380_write_reg_cache(codec, UDA1380_CLK,
769 R00_DAC_CLK);
710 break; 770 break;
711 } 771 }
712 772
@@ -717,10 +777,15 @@ static int uda1380_probe(struct snd_soc_codec *codec)
717 return 0; 777 return 0;
718 778
719err_reset: 779err_reset:
720 gpio_set_value(pdata->gpio_power, 0); 780err_gpio_power_conf:
721 gpio_free(pdata->gpio_reset); 781 if (gpio_is_valid(pdata->gpio_power))
782 gpio_free(pdata->gpio_power);
783
784err_gpio_reset_conf:
722err_gpio: 785err_gpio:
723 gpio_free(pdata->gpio_power); 786 if (gpio_is_valid(pdata->gpio_reset))
787 gpio_free(pdata->gpio_reset);
788err_out:
724 return ret; 789 return ret;
725} 790}
726 791
@@ -731,7 +796,6 @@ static int uda1380_remove(struct snd_soc_codec *codec)
731 796
732 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); 797 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
733 798
734 gpio_set_value(pdata->gpio_power, 0);
735 gpio_free(pdata->gpio_reset); 799 gpio_free(pdata->gpio_reset);
736 gpio_free(pdata->gpio_power); 800 gpio_free(pdata->gpio_power);
737 801
@@ -743,8 +807,8 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
743 .remove = uda1380_remove, 807 .remove = uda1380_remove,
744 .suspend = uda1380_suspend, 808 .suspend = uda1380_suspend,
745 .resume = uda1380_resume, 809 .resume = uda1380_resume,
746 .read = uda1380_read_reg_cache, 810 .read = uda1380_read_reg_cache,
747 .write = uda1380_write, 811 .write = uda1380_write,
748 .set_bias_level = uda1380_set_bias_level, 812 .set_bias_level = uda1380_set_bias_level,
749 .reg_cache_size = ARRAY_SIZE(uda1380_reg), 813 .reg_cache_size = ARRAY_SIZE(uda1380_reg),
750 .reg_word_size = sizeof(u16), 814 .reg_word_size = sizeof(u16),
@@ -764,6 +828,7 @@ static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
764 return -ENOMEM; 828 return -ENOMEM;
765 829
766 i2c_set_clientdata(i2c, uda1380); 830 i2c_set_clientdata(i2c, uda1380);
831 uda1380->control_data = i2c;
767 832
768 ret = snd_soc_register_codec(&i2c->dev, 833 ret = snd_soc_register_codec(&i2c->dev,
769 &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); 834 &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai));