aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/arizona.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/arizona.c')
-rw-r--r--sound/soc/codecs/arizona.c264
1 files changed, 206 insertions, 58 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index ef62c435848e..ac948a671ea6 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -56,14 +56,14 @@
56#define arizona_fll_warn(_fll, fmt, ...) \ 56#define arizona_fll_warn(_fll, fmt, ...) \
57 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) 57 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
58#define arizona_fll_dbg(_fll, fmt, ...) \ 58#define arizona_fll_dbg(_fll, fmt, ...) \
59 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) 59 dev_dbg(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
60 60
61#define arizona_aif_err(_dai, fmt, ...) \ 61#define arizona_aif_err(_dai, fmt, ...) \
62 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) 62 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
63#define arizona_aif_warn(_dai, fmt, ...) \ 63#define arizona_aif_warn(_dai, fmt, ...) \
64 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) 64 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
65#define arizona_aif_dbg(_dai, fmt, ...) \ 65#define arizona_aif_dbg(_dai, fmt, ...) \
66 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) 66 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
67 67
68const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { 68const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
69 "None", 69 "None",
@@ -141,6 +141,30 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
141 "ASRC1R", 141 "ASRC1R",
142 "ASRC2L", 142 "ASRC2L",
143 "ASRC2R", 143 "ASRC2R",
144 "ISRC1INT1",
145 "ISRC1INT2",
146 "ISRC1INT3",
147 "ISRC1INT4",
148 "ISRC1DEC1",
149 "ISRC1DEC2",
150 "ISRC1DEC3",
151 "ISRC1DEC4",
152 "ISRC2INT1",
153 "ISRC2INT2",
154 "ISRC2INT3",
155 "ISRC2INT4",
156 "ISRC2DEC1",
157 "ISRC2DEC2",
158 "ISRC2DEC3",
159 "ISRC2DEC4",
160 "ISRC3INT1",
161 "ISRC3INT2",
162 "ISRC3INT3",
163 "ISRC3INT4",
164 "ISRC3DEC1",
165 "ISRC3DEC2",
166 "ISRC3DEC3",
167 "ISRC3DEC4",
144}; 168};
145EXPORT_SYMBOL_GPL(arizona_mixer_texts); 169EXPORT_SYMBOL_GPL(arizona_mixer_texts);
146 170
@@ -220,6 +244,30 @@ int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
220 0x91, 244 0x91,
221 0x92, 245 0x92,
222 0x93, 246 0x93,
247 0xa0, /* ISRC1INT1 */
248 0xa1,
249 0xa2,
250 0xa3,
251 0xa4, /* ISRC1DEC1 */
252 0xa5,
253 0xa6,
254 0xa7,
255 0xa8, /* ISRC2DEC1 */
256 0xa9,
257 0xaa,
258 0xab,
259 0xac, /* ISRC2INT1 */
260 0xad,
261 0xae,
262 0xaf,
263 0xb0, /* ISRC3DEC1 */
264 0xb1,
265 0xb2,
266 0xb3,
267 0xb4, /* ISRC3INT1 */
268 0xb5,
269 0xb6,
270 0xb7,
223}; 271};
224EXPORT_SYMBOL_GPL(arizona_mixer_values); 272EXPORT_SYMBOL_GPL(arizona_mixer_values);
225 273
@@ -275,9 +323,35 @@ const struct soc_enum arizona_lhpf4_mode =
275 arizona_lhpf_mode_text); 323 arizona_lhpf_mode_text);
276EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); 324EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
277 325
326static const char *arizona_ng_hold_text[] = {
327 "30ms", "120ms", "250ms", "500ms",
328};
329
330const struct soc_enum arizona_ng_hold =
331 SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT,
332 4, arizona_ng_hold_text);
333EXPORT_SYMBOL_GPL(arizona_ng_hold);
334
278int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, 335int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
279 int event) 336 int event)
280{ 337{
338 unsigned int reg;
339
340 if (w->shift % 2)
341 reg = ARIZONA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
342 else
343 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
344
345 switch (event) {
346 case SND_SOC_DAPM_POST_PMU:
347 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
348 break;
349 case SND_SOC_DAPM_PRE_PMD:
350 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE,
351 ARIZONA_IN1L_MUTE);
352 break;
353 }
354
281 return 0; 355 return 0;
282} 356}
283EXPORT_SYMBOL_GPL(arizona_in_ev); 357EXPORT_SYMBOL_GPL(arizona_in_ev);
@@ -417,6 +491,10 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
417 case 147456000: 491 case 147456000:
418 val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT; 492 val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
419 break; 493 break;
494 case 0:
495 dev_dbg(arizona->dev, "%s cleared\n", name);
496 *clk = freq;
497 return 0;
420 default: 498 default:
421 return -EINVAL; 499 return -EINVAL;
422 } 500 }
@@ -635,6 +713,9 @@ static int arizona_startup(struct snd_pcm_substream *substream,
635 return 0; 713 return 0;
636 } 714 }
637 715
716 if (base_rate == 0)
717 return 0;
718
638 if (base_rate % 8000) 719 if (base_rate % 8000)
639 constraint = &arizona_44k1_constraint; 720 constraint = &arizona_44k1_constraint;
640 else 721 else
@@ -645,25 +726,81 @@ static int arizona_startup(struct snd_pcm_substream *substream,
645 constraint); 726 constraint);
646} 727}
647 728
729static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
730 struct snd_pcm_hw_params *params,
731 struct snd_soc_dai *dai)
732{
733 struct snd_soc_codec *codec = dai->codec;
734 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
735 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
736 int base = dai->driver->base;
737 int i, sr_val;
738
739 /*
740 * We will need to be more flexible than this in future,
741 * currently we use a single sample rate for SYSCLK.
742 */
743 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
744 if (arizona_sr_vals[i] == params_rate(params))
745 break;
746 if (i == ARRAY_SIZE(arizona_sr_vals)) {
747 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
748 params_rate(params));
749 return -EINVAL;
750 }
751 sr_val = i;
752
753 switch (dai_priv->clk) {
754 case ARIZONA_CLK_SYSCLK:
755 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
756 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
757 if (base)
758 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
759 ARIZONA_AIF1_RATE_MASK, 0);
760 break;
761 case ARIZONA_CLK_ASYNCCLK:
762 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
763 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
764 if (base)
765 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
766 ARIZONA_AIF1_RATE_MASK,
767 8 << ARIZONA_AIF1_RATE_SHIFT);
768 break;
769 default:
770 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
771 return -EINVAL;
772 }
773
774 return 0;
775}
776
648static int arizona_hw_params(struct snd_pcm_substream *substream, 777static int arizona_hw_params(struct snd_pcm_substream *substream,
649 struct snd_pcm_hw_params *params, 778 struct snd_pcm_hw_params *params,
650 struct snd_soc_dai *dai) 779 struct snd_soc_dai *dai)
651{ 780{
652 struct snd_soc_codec *codec = dai->codec; 781 struct snd_soc_codec *codec = dai->codec;
653 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); 782 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
654 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; 783 struct arizona *arizona = priv->arizona;
655 int base = dai->driver->base; 784 int base = dai->driver->base;
656 const int *rates; 785 const int *rates;
657 int i; 786 int i, ret;
658 int bclk, lrclk, wl, frame, sr_val; 787 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
788 int bclk, lrclk, wl, frame, bclk_target;
659 789
660 if (params_rate(params) % 8000) 790 if (params_rate(params) % 8000)
661 rates = &arizona_44k1_bclk_rates[0]; 791 rates = &arizona_44k1_bclk_rates[0];
662 else 792 else
663 rates = &arizona_48k_bclk_rates[0]; 793 rates = &arizona_48k_bclk_rates[0];
664 794
795 bclk_target = snd_soc_params_to_bclk(params);
796 if (chan_limit && chan_limit < params_channels(params)) {
797 arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
798 bclk_target /= params_channels(params);
799 bclk_target *= chan_limit;
800 }
801
665 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { 802 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
666 if (rates[i] >= snd_soc_params_to_bclk(params) && 803 if (rates[i] >= bclk_target &&
667 rates[i] % params_rate(params) == 0) { 804 rates[i] % params_rate(params) == 0) {
668 bclk = i; 805 bclk = i;
669 break; 806 break;
@@ -675,16 +812,6 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
675 return -EINVAL; 812 return -EINVAL;
676 } 813 }
677 814
678 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
679 if (arizona_sr_vals[i] == params_rate(params))
680 break;
681 if (i == ARRAY_SIZE(arizona_sr_vals)) {
682 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
683 params_rate(params));
684 return -EINVAL;
685 }
686 sr_val = i;
687
688 lrclk = rates[bclk] / params_rate(params); 815 lrclk = rates[bclk] / params_rate(params);
689 816
690 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", 817 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
@@ -693,28 +820,9 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
693 wl = snd_pcm_format_width(params_format(params)); 820 wl = snd_pcm_format_width(params_format(params));
694 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; 821 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
695 822
696 /* 823 ret = arizona_hw_params_rate(substream, params, dai);
697 * We will need to be more flexible than this in future, 824 if (ret != 0)
698 * currently we use a single sample rate for SYSCLK. 825 return ret;
699 */
700 switch (dai_priv->clk) {
701 case ARIZONA_CLK_SYSCLK:
702 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
703 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
704 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
705 ARIZONA_AIF1_RATE_MASK, 0);
706 break;
707 case ARIZONA_CLK_ASYNCCLK:
708 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
709 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
710 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
711 ARIZONA_AIF1_RATE_MASK,
712 8 << ARIZONA_AIF1_RATE_SHIFT);
713 break;
714 default:
715 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
716 return -EINVAL;
717 }
718 826
719 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, 827 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
720 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); 828 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
@@ -789,11 +897,27 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
789 return snd_soc_dapm_sync(&codec->dapm); 897 return snd_soc_dapm_sync(&codec->dapm);
790} 898}
791 899
900static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
901{
902 struct snd_soc_codec *codec = dai->codec;
903 int base = dai->driver->base;
904 unsigned int reg;
905
906 if (tristate)
907 reg = ARIZONA_AIF1_TRI;
908 else
909 reg = 0;
910
911 return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
912 ARIZONA_AIF1_TRI, reg);
913}
914
792const struct snd_soc_dai_ops arizona_dai_ops = { 915const struct snd_soc_dai_ops arizona_dai_ops = {
793 .startup = arizona_startup, 916 .startup = arizona_startup,
794 .set_fmt = arizona_set_fmt, 917 .set_fmt = arizona_set_fmt,
795 .hw_params = arizona_hw_params, 918 .hw_params = arizona_hw_params,
796 .set_sysclk = arizona_dai_set_sysclk, 919 .set_sysclk = arizona_dai_set_sysclk,
920 .set_tristate = arizona_set_tristate,
797}; 921};
798EXPORT_SYMBOL_GPL(arizona_dai_ops); 922EXPORT_SYMBOL_GPL(arizona_dai_ops);
799 923
@@ -807,17 +931,6 @@ int arizona_init_dai(struct arizona_priv *priv, int id)
807} 931}
808EXPORT_SYMBOL_GPL(arizona_init_dai); 932EXPORT_SYMBOL_GPL(arizona_init_dai);
809 933
810static irqreturn_t arizona_fll_lock(int irq, void *data)
811{
812 struct arizona_fll *fll = data;
813
814 arizona_fll_dbg(fll, "Lock status changed\n");
815
816 complete(&fll->lock);
817
818 return IRQ_HANDLED;
819}
820
821static irqreturn_t arizona_fll_clock_ok(int irq, void *data) 934static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
822{ 935{
823 struct arizona_fll *fll = data; 936 struct arizona_fll *fll = data;
@@ -910,7 +1023,7 @@ static int arizona_calc_fll(struct arizona_fll *fll,
910 1023
911 cfg->n = target / (ratio * Fref); 1024 cfg->n = target / (ratio * Fref);
912 1025
913 if (target % Fref) { 1026 if (target % (ratio * Fref)) {
914 gcd_fll = gcd(target, ratio * Fref); 1027 gcd_fll = gcd(target, ratio * Fref);
915 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll); 1028 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
916 1029
@@ -922,6 +1035,15 @@ static int arizona_calc_fll(struct arizona_fll *fll,
922 cfg->lambda = 0; 1035 cfg->lambda = 0;
923 } 1036 }
924 1037
1038 /* Round down to 16bit range with cost of accuracy lost.
1039 * Denominator must be bigger than numerator so we only
1040 * take care of it.
1041 */
1042 while (cfg->lambda >= (1 << 16)) {
1043 cfg->theta >>= 1;
1044 cfg->lambda >>= 1;
1045 }
1046
925 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", 1047 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
926 cfg->n, cfg->theta, cfg->lambda); 1048 cfg->n, cfg->theta, cfg->lambda);
927 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", 1049 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
@@ -1057,7 +1179,6 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1057{ 1179{
1058 int ret; 1180 int ret;
1059 1181
1060 init_completion(&fll->lock);
1061 init_completion(&fll->ok); 1182 init_completion(&fll->ok);
1062 1183
1063 fll->id = id; 1184 fll->id = id;
@@ -1068,13 +1189,6 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1068 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), 1189 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
1069 "FLL%d clock OK", id); 1190 "FLL%d clock OK", id);
1070 1191
1071 ret = arizona_request_irq(arizona, lock_irq, fll->lock_name,
1072 arizona_fll_lock, fll);
1073 if (ret != 0) {
1074 dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n",
1075 id, ret);
1076 }
1077
1078 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name, 1192 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
1079 arizona_fll_clock_ok, fll); 1193 arizona_fll_clock_ok, fll);
1080 if (ret != 0) { 1194 if (ret != 0) {
@@ -1089,6 +1203,40 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1089} 1203}
1090EXPORT_SYMBOL_GPL(arizona_init_fll); 1204EXPORT_SYMBOL_GPL(arizona_init_fll);
1091 1205
1206/**
1207 * arizona_set_output_mode - Set the mode of the specified output
1208 *
1209 * @codec: Device to configure
1210 * @output: Output number
1211 * @diff: True to set the output to differential mode
1212 *
1213 * Some systems use external analogue switches to connect more
1214 * analogue devices to the CODEC than are supported by the device. In
1215 * some systems this requires changing the switched output from single
1216 * ended to differential mode dynamically at runtime, an operation
1217 * supported using this function.
1218 *
1219 * Most systems have a single static configuration and should use
1220 * platform data instead.
1221 */
1222int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
1223{
1224 unsigned int reg, val;
1225
1226 if (output < 1 || output > 6)
1227 return -EINVAL;
1228
1229 reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
1230
1231 if (diff)
1232 val = ARIZONA_OUT1_MONO;
1233 else
1234 val = 0;
1235
1236 return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
1237}
1238EXPORT_SYMBOL_GPL(arizona_set_output_mode);
1239
1092MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); 1240MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
1093MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 1241MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1094MODULE_LICENSE("GPL"); 1242MODULE_LICENSE("GPL");