static int arizona_hw_params_rate(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; int base = dai->driver->base; int i, sr_val; /* * We will need to be more flexible than this in future, * currently we use a single sample rate for SYSCLK. */ for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++) if (arizona_sr_vals[i] == params_rate(params)) break; if (i == ARRAY_SIZE(arizona_sr_vals)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } sr_val = i; switch (dai_priv->clk) { case ARIZONA_CLK_SYSCLK: switch (priv->arizona->type) { case WM5102: arizona_wm5102_set_dac_comp(codec, params_rate(params)); break; default: break; } snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, ARIZONA_SAMPLE_RATE_1_MASK, sr_val); if (base) snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 0); break; case ARIZONA_CLK_ASYNCCLK: snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); if (base) snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 8 << ARIZONA_AIF1_RATE_SHIFT); break; default: arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); return -EINVAL; } return 0; }
static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_codec *codec = dai->codec; int lrclk, bclk, mode, base; base = dai->driver->base; lrclk = 0; bclk = 0; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: mode = 0; break; case SND_SOC_DAIFMT_I2S: mode = 2; break; default: arizona_aif_err(dai, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: break; case SND_SOC_DAIFMT_CBS_CFM: lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR; break; case SND_SOC_DAIFMT_CBM_CFS: bclk |= ARIZONA_AIF1_BCLK_MSTR; break; case SND_SOC_DAIFMT_CBM_CFM: bclk |= ARIZONA_AIF1_BCLK_MSTR; lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR; break; default: arizona_aif_err(dai, "Unsupported master mode %d\n", fmt & SND_SOC_DAIFMT_MASTER_MASK); return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_IB_IF: bclk |= ARIZONA_AIF1_BCLK_INV; lrclk |= ARIZONA_AIF1TX_LRCLK_INV; break; case SND_SOC_DAIFMT_IB_NF: bclk |= ARIZONA_AIF1_BCLK_INV; break; case SND_SOC_DAIFMT_NB_IF: lrclk |= ARIZONA_AIF1TX_LRCLK_INV; break; default: return -EINVAL; } snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR, bclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL, ARIZONA_AIF1TX_LRCLK_INV | ARIZONA_AIF1TX_LRCLK_MSTR, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL, ARIZONA_AIF1RX_LRCLK_INV | ARIZONA_AIF1RX_LRCLK_MSTR, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT, ARIZONA_AIF1_FMT_MASK, mode); return 0; }
static int arizona_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona *arizona = priv->arizona; int base = dai->driver->base; const int *rates; int i, ret, val; int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1]; int bclk, lrclk, wl, frame, bclk_target; if (params_rate(params) % 8000) rates = &arizona_44k1_bclk_rates[0]; else rates = &arizona_48k_bclk_rates[0]; bclk_target = snd_soc_params_to_bclk(params); if (chan_limit && chan_limit < params_channels(params)) { arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit); bclk_target /= params_channels(params); bclk_target *= chan_limit; } /* Force stereo for I2S mode */ val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) { arizona_aif_dbg(dai, "Forcing stereo mode\n"); bclk_target *= 2; } for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { if (rates[i] >= bclk_target && rates[i] % params_rate(params) == 0) { bclk = i; break; } } if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } lrclk = rates[bclk] / params_rate(params); arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", rates[bclk], rates[bclk] / lrclk); wl = snd_pcm_format_width(params_format(params)); frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; ret = arizona_hw_params_rate(substream, params, dai); if (ret != 0) return ret; snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE, ARIZONA_AIF1TX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE, ARIZONA_AIF1RX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1, ARIZONA_AIF1TX_WL_MASK | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2, ARIZONA_AIF1RX_WL_MASK | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); return 0; }
static int arizona_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; unsigned int val; int base = dai->driver->base; const int *rates; int i, ret, bclk_target; int bclk, lrclk, wl, frame, sr_val; //printk("Arizona: hw params start\n"); if (params_rate(params) % 8000) rates = &arizona_44k1_bclk_rates[0]; else rates = &arizona_48k_bclk_rates[0]; /* Force BCLK to stereo for I2S */ bclk_target = snd_soc_params_to_bclk(params); val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); if (val & ARIZONA_AIF1_FMT_MASK && params_channels(params) == 1) { arizona_aif_err(dai, "Forcing stereo mode\n"); bclk_target *= 2; } for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { if (rates[i] >= bclk_target && rates[i] % params_rate(params) == 0) { bclk = i; break; } } if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++) if (arizona_sr_vals[i] == params_rate(params)) break; if (i == ARRAY_SIZE(arizona_sr_vals)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } sr_val = i; lrclk = rates[bclk] / params_rate(params); arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", rates[bclk], rates[bclk] / lrclk); wl = snd_pcm_format_width(params_format(params)); frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; /* * We will need to be more flexible than this in future, * currently we use a single sample rate for SYSCLK. */ switch (dai_priv->clk) { case ARIZONA_CLK_SYSCLK: /* SR2 is forced to 8kHz */ if (params_rate(params) != 8000) { snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, ARIZONA_SAMPLE_RATE_1_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 0); } else { snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_2, ARIZONA_SAMPLE_RATE_2_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 1); } break; case ARIZONA_CLK_ASYNCCLK: snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 8); break; default: arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); return -EINVAL; } snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE, ARIZONA_AIF1TX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE, ARIZONA_AIF1RX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1, ARIZONA_AIF1TX_WL_MASK | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2, ARIZONA_AIF1RX_WL_MASK | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); // HLL will add this in //ret=wm2000_check_poll(); //printk("Arizona: hw params start 1\n"); return 0; //ret; }
static int arizona_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; int base = dai->driver->base; const int *rates; int i; int bclk, lrclk, wl, frame, sr_val; if (params_rate(params) % 8000) rates = &arizona_44k1_bclk_rates[0]; else rates = &arizona_48k_bclk_rates[0]; for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { if (rates[i] >= snd_soc_params_to_bclk(params) && rates[i] % params_rate(params) == 0) { bclk = i; break; } } if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++) if (arizona_sr_vals[i] == params_rate(params)) break; if (i == ARRAY_SIZE(arizona_sr_vals)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } sr_val = i; lrclk = snd_soc_params_to_bclk(params) / params_rate(params); arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", rates[bclk], rates[bclk] / lrclk); wl = snd_pcm_format_width(params_format(params)); frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; /* * We will need to be more flexible than this in future, * currently we use a single sample rate for SYSCLK. */ switch (dai_priv->clk) { case ARIZONA_CLK_SYSCLK: snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, ARIZONA_SAMPLE_RATE_1_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 0); break; case ARIZONA_CLK_ASYNCCLK: snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 8); break; default: arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); return -EINVAL; } snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE, ARIZONA_AIF1TX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE, ARIZONA_AIF1RX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1, ARIZONA_AIF1TX_WL_MASK | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2, ARIZONA_AIF1RX_WL_MASK | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); return 0; }