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.c129
1 files changed, 98 insertions, 31 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 802e05eae3e9..8a2221ab3d10 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1366,7 +1366,7 @@ static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
1366{ 1366{
1367 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); 1367 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1368 struct arizona *arizona = priv->arizona; 1368 struct arizona *arizona = priv->arizona;
1369 struct reg_default dac_comp[] = { 1369 struct reg_sequence dac_comp[] = {
1370 { 0x80, 0x3 }, 1370 { 0x80, 0x3 },
1371 { ARIZONA_DAC_COMP_1, 0 }, 1371 { ARIZONA_DAC_COMP_1, 0 },
1372 { ARIZONA_DAC_COMP_2, 0 }, 1372 { ARIZONA_DAC_COMP_2, 0 },
@@ -1504,7 +1504,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
1504 else 1504 else
1505 rates = &arizona_48k_bclk_rates[0]; 1505 rates = &arizona_48k_bclk_rates[0];
1506 1506
1507 wl = snd_pcm_format_width(params_format(params)); 1507 wl = params_width(params);
1508 1508
1509 if (tdm_slots) { 1509 if (tdm_slots) {
1510 arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n", 1510 arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
@@ -1756,17 +1756,6 @@ int arizona_init_dai(struct arizona_priv *priv, int id)
1756} 1756}
1757EXPORT_SYMBOL_GPL(arizona_init_dai); 1757EXPORT_SYMBOL_GPL(arizona_init_dai);
1758 1758
1759static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
1760{
1761 struct arizona_fll *fll = data;
1762
1763 arizona_fll_dbg(fll, "clock OK\n");
1764
1765 complete(&fll->ok);
1766
1767 return IRQ_HANDLED;
1768}
1769
1770static struct { 1759static struct {
1771 unsigned int min; 1760 unsigned int min;
1772 unsigned int max; 1761 unsigned int max;
@@ -2048,17 +2037,18 @@ static int arizona_is_enabled_fll(struct arizona_fll *fll)
2048static int arizona_enable_fll(struct arizona_fll *fll) 2037static int arizona_enable_fll(struct arizona_fll *fll)
2049{ 2038{
2050 struct arizona *arizona = fll->arizona; 2039 struct arizona *arizona = fll->arizona;
2051 unsigned long time_left;
2052 bool use_sync = false; 2040 bool use_sync = false;
2053 int already_enabled = arizona_is_enabled_fll(fll); 2041 int already_enabled = arizona_is_enabled_fll(fll);
2054 struct arizona_fll_cfg cfg; 2042 struct arizona_fll_cfg cfg;
2043 int i;
2044 unsigned int val;
2055 2045
2056 if (already_enabled < 0) 2046 if (already_enabled < 0)
2057 return already_enabled; 2047 return already_enabled;
2058 2048
2059 if (already_enabled) { 2049 if (already_enabled) {
2060 /* Facilitate smooth refclk across the transition */ 2050 /* Facilitate smooth refclk across the transition */
2061 regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7, 2051 regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
2062 ARIZONA_FLL1_GAIN_MASK, 0); 2052 ARIZONA_FLL1_GAIN_MASK, 0);
2063 regmap_update_bits_async(fll->arizona->regmap, fll->base + 1, 2053 regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
2064 ARIZONA_FLL1_FREERUN, 2054 ARIZONA_FLL1_FREERUN,
@@ -2110,9 +2100,6 @@ static int arizona_enable_fll(struct arizona_fll *fll)
2110 if (!already_enabled) 2100 if (!already_enabled)
2111 pm_runtime_get(arizona->dev); 2101 pm_runtime_get(arizona->dev);
2112 2102
2113 /* Clear any pending completions */
2114 try_wait_for_completion(&fll->ok);
2115
2116 regmap_update_bits_async(arizona->regmap, fll->base + 1, 2103 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2117 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); 2104 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
2118 if (use_sync) 2105 if (use_sync)
@@ -2124,10 +2111,24 @@ static int arizona_enable_fll(struct arizona_fll *fll)
2124 regmap_update_bits_async(arizona->regmap, fll->base + 1, 2111 regmap_update_bits_async(arizona->regmap, fll->base + 1,
2125 ARIZONA_FLL1_FREERUN, 0); 2112 ARIZONA_FLL1_FREERUN, 0);
2126 2113
2127 time_left = wait_for_completion_timeout(&fll->ok, 2114 arizona_fll_dbg(fll, "Waiting for FLL lock...\n");
2128 msecs_to_jiffies(250)); 2115 val = 0;
2129 if (time_left == 0) 2116 for (i = 0; i < 15; i++) {
2117 if (i < 5)
2118 usleep_range(200, 400);
2119 else
2120 msleep(20);
2121
2122 regmap_read(arizona->regmap,
2123 ARIZONA_INTERRUPT_RAW_STATUS_5,
2124 &val);
2125 if (val & (ARIZONA_FLL1_CLOCK_OK_STS << (fll->id - 1)))
2126 break;
2127 }
2128 if (i == 15)
2130 arizona_fll_warn(fll, "Timed out waiting for lock\n"); 2129 arizona_fll_warn(fll, "Timed out waiting for lock\n");
2130 else
2131 arizona_fll_dbg(fll, "FLL locked (%d polls)\n", i);
2131 2132
2132 return 0; 2133 return 0;
2133} 2134}
@@ -2212,11 +2213,8 @@ EXPORT_SYMBOL_GPL(arizona_set_fll);
2212int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, 2213int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
2213 int ok_irq, struct arizona_fll *fll) 2214 int ok_irq, struct arizona_fll *fll)
2214{ 2215{
2215 int ret;
2216 unsigned int val; 2216 unsigned int val;
2217 2217
2218 init_completion(&fll->ok);
2219
2220 fll->id = id; 2218 fll->id = id;
2221 fll->base = base; 2219 fll->base = base;
2222 fll->arizona = arizona; 2220 fll->arizona = arizona;
@@ -2238,13 +2236,6 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
2238 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), 2236 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
2239 "FLL%d clock OK", id); 2237 "FLL%d clock OK", id);
2240 2238
2241 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
2242 arizona_fll_clock_ok, fll);
2243 if (ret != 0) {
2244 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
2245 id, ret);
2246 }
2247
2248 regmap_update_bits(arizona->regmap, fll->base + 1, 2239 regmap_update_bits(arizona->regmap, fll->base + 1,
2249 ARIZONA_FLL1_FREERUN, 0); 2240 ARIZONA_FLL1_FREERUN, 0);
2250 2241
@@ -2313,6 +2304,82 @@ const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = {
2313}; 2304};
2314EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls); 2305EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls);
2315 2306
2307static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
2308{
2309 s16 a = be16_to_cpu(_a);
2310 s16 b = be16_to_cpu(_b);
2311
2312 if (!mode) {
2313 return abs(a) >= 4096;
2314 } else {
2315 if (abs(b) >= 4096)
2316 return true;
2317
2318 return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
2319 }
2320}
2321
2322int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
2323 struct snd_ctl_elem_value *ucontrol)
2324{
2325 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2326 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2327 struct soc_bytes *params = (void *)kcontrol->private_value;
2328 unsigned int val;
2329 __be16 *data;
2330 int len;
2331 int ret;
2332
2333 len = params->num_regs * regmap_get_val_bytes(arizona->regmap);
2334
2335 data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
2336 if (!data)
2337 return -ENOMEM;
2338
2339 data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE);
2340
2341 if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) ||
2342 arizona_eq_filter_unstable(true, data[4], data[5]) ||
2343 arizona_eq_filter_unstable(true, data[8], data[9]) ||
2344 arizona_eq_filter_unstable(true, data[12], data[13]) ||
2345 arizona_eq_filter_unstable(false, data[16], data[17])) {
2346 dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n");
2347 ret = -EINVAL;
2348 goto out;
2349 }
2350
2351 ret = regmap_read(arizona->regmap, params->base, &val);
2352 if (ret != 0)
2353 goto out;
2354
2355 val &= ~ARIZONA_EQ1_B1_MODE;
2356 data[0] |= cpu_to_be16(val);
2357
2358 ret = regmap_raw_write(arizona->regmap, params->base, data, len);
2359
2360out:
2361 kfree(data);
2362 return ret;
2363}
2364EXPORT_SYMBOL_GPL(arizona_eq_coeff_put);
2365
2366int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
2367 struct snd_ctl_elem_value *ucontrol)
2368{
2369 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2370 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2371 __be16 *data = (__be16 *)ucontrol->value.bytes.data;
2372 s16 val = be16_to_cpu(*data);
2373
2374 if (abs(val) >= 4096) {
2375 dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n");
2376 return -EINVAL;
2377 }
2378
2379 return snd_soc_bytes_put(kcontrol, ucontrol);
2380}
2381EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
2382
2316MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); 2383MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
2317MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 2384MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2318MODULE_LICENSE("GPL"); 2385MODULE_LICENSE("GPL");