forked from Minki/linux
Merge remote-tracking branches 'asoc/topic/adau1977', 'asoc/topic/ak4642', 'asoc/topic/ak5386' and 'asoc/topic/arizona' into asoc-next
This commit is contained in:
commit
a486f183da
@ -10,10 +10,14 @@ Optional properties:
|
||||
|
||||
- reset-gpio : a GPIO spec for the reset/power down pin.
|
||||
If specified, it will be deasserted at probe time.
|
||||
- va-supply : a regulator spec, providing 5.0V
|
||||
- vd-supply : a regulator spec, providing 3.3V
|
||||
|
||||
Example:
|
||||
|
||||
spdif: ak5386@0 {
|
||||
compatible = "asahi-kasei,ak5386";
|
||||
reset-gpio = <&gpio0 23>;
|
||||
va-supply = <&vdd_5v0_reg>;
|
||||
vd-supply = <&vdd_3v3_reg>;
|
||||
};
|
||||
|
@ -110,6 +110,12 @@ struct arizona {
|
||||
int clk32k_ref;
|
||||
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
|
||||
int tdm_width[ARIZONA_MAX_AIF];
|
||||
int tdm_slots[ARIZONA_MAX_AIF];
|
||||
|
||||
uint16_t dac_comp_coeff;
|
||||
uint8_t dac_comp_enabled;
|
||||
};
|
||||
|
||||
int arizona_clk32k_enable(struct arizona *arizona);
|
||||
|
@ -968,7 +968,7 @@ int adau1977_probe(struct device *dev, struct regmap *regmap,
|
||||
if (adau1977->dvdd_reg)
|
||||
power_off_mask = ~0;
|
||||
else
|
||||
power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
|
||||
power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
|
||||
|
||||
ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
|
||||
power_off_mask, 0x00);
|
||||
|
@ -547,7 +547,7 @@ static const struct ak4642_drvdata ak4648_drvdata = {
|
||||
.extended_frequencies = 1,
|
||||
};
|
||||
|
||||
static struct of_device_id ak4642_of_match[];
|
||||
static const struct of_device_id ak4642_of_match[];
|
||||
static int ak4642_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@ -593,7 +593,7 @@ static int ak4642_i2c_remove(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id ak4642_of_match[] = {
|
||||
static const struct of_device_id ak4642_of_match[] = {
|
||||
{ .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata},
|
||||
{ .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata},
|
||||
{ .compatible = "asahi-kasei,ak4648", .data = &ak4648_drvdata},
|
||||
|
@ -14,12 +14,18 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
static const char * const supply_names[] = {
|
||||
"va", "vd"
|
||||
};
|
||||
|
||||
struct ak5386_priv {
|
||||
int reset_gpio;
|
||||
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = {
|
||||
@ -32,7 +38,42 @@ static const struct snd_soc_dapm_route ak5386_dapm_routes[] = {
|
||||
{ "Capture", NULL, "AINR" },
|
||||
};
|
||||
|
||||
static int ak5386_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
}
|
||||
|
||||
static int ak5386_soc_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ak5386_soc_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ak5386_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
}
|
||||
#else
|
||||
#define ak5386_soc_suspend NULL
|
||||
#define ak5386_soc_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_ak5386 = {
|
||||
.probe = ak5386_soc_probe,
|
||||
.remove = ak5386_soc_remove,
|
||||
.suspend = ak5386_soc_suspend,
|
||||
.resume = ak5386_soc_resume,
|
||||
.dapm_widgets = ak5386_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets),
|
||||
.dapm_routes = ak5386_dapm_routes,
|
||||
@ -122,6 +163,7 @@ static int ak5386_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ak5386_priv *priv;
|
||||
int ret, i;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
@ -130,6 +172,14 @@ static int ak5386_probe(struct platform_device *pdev)
|
||||
priv->reset_gpio = -EINVAL;
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
|
||||
priv->supplies[i].supply = supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
|
||||
priv->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (of_match_device(of_match_ptr(ak5386_dt_ids), dev))
|
||||
priv->reset_gpio = of_get_named_gpio(dev->of_node,
|
||||
"reset-gpio", 0);
|
||||
|
@ -1152,6 +1152,31 @@ static int arizona_startup(struct snd_pcm_substream *substream,
|
||||
constraint);
|
||||
}
|
||||
|
||||
static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
|
||||
unsigned int rate)
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
struct reg_default dac_comp[] = {
|
||||
{ 0x80, 0x3 },
|
||||
{ ARIZONA_DAC_COMP_1, 0 },
|
||||
{ ARIZONA_DAC_COMP_2, 0 },
|
||||
{ 0x80, 0x0 },
|
||||
};
|
||||
|
||||
mutex_lock(&codec->mutex);
|
||||
|
||||
dac_comp[1].def = arizona->dac_comp_coeff;
|
||||
if (rate >= 176400)
|
||||
dac_comp[2].def = arizona->dac_comp_enabled;
|
||||
|
||||
mutex_unlock(&codec->mutex);
|
||||
|
||||
regmap_multi_reg_write(arizona->regmap,
|
||||
dac_comp,
|
||||
ARRAY_SIZE(dac_comp));
|
||||
}
|
||||
|
||||
static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
@ -1178,6 +1203,15 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
||||
|
||||
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)
|
||||
@ -1200,6 +1234,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
|
||||
int base, int bclk, int lrclk, int frame)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
|
||||
if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
|
||||
return true;
|
||||
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
|
||||
if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
|
||||
return true;
|
||||
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
|
||||
if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
|
||||
ARIZONA_AIF1TX_SLOT_LEN_MASK)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int arizona_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
@ -1210,26 +1265,40 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
|
||||
int base = dai->driver->base;
|
||||
const int *rates;
|
||||
int i, ret, val;
|
||||
int channels = params_channels(params);
|
||||
int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
|
||||
int tdm_width = arizona->tdm_width[dai->id - 1];
|
||||
int tdm_slots = arizona->tdm_slots[dai->id - 1];
|
||||
int bclk, lrclk, wl, frame, bclk_target;
|
||||
bool reconfig;
|
||||
unsigned int aif_tx_state, aif_rx_state;
|
||||
|
||||
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)) {
|
||||
if (tdm_slots) {
|
||||
arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
|
||||
tdm_slots, tdm_width);
|
||||
bclk_target = tdm_slots * tdm_width * params_rate(params);
|
||||
channels = tdm_slots;
|
||||
} else {
|
||||
bclk_target = snd_soc_params_to_bclk(params);
|
||||
}
|
||||
|
||||
if (chan_limit && chan_limit < channels) {
|
||||
arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
|
||||
bclk_target /= params_channels(params);
|
||||
bclk_target /= channels;
|
||||
bclk_target *= chan_limit;
|
||||
}
|
||||
|
||||
/* Force stereo for I2S mode */
|
||||
/* Force multiple of 2 channels for I2S mode */
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
|
||||
if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
|
||||
if ((channels & 1) && (val & ARIZONA_AIF1_FMT_MASK)) {
|
||||
arizona_aif_dbg(dai, "Forcing stereo mode\n");
|
||||
bclk_target *= 2;
|
||||
bclk_target /= channels;
|
||||
bclk_target *= channels + 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
|
||||
@ -1253,28 +1322,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
|
||||
wl = snd_pcm_format_width(params_format(params));
|
||||
frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
|
||||
|
||||
reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
|
||||
|
||||
if (reconfig) {
|
||||
/* Save AIF TX/RX state */
|
||||
aif_tx_state = snd_soc_read(codec,
|
||||
base + ARIZONA_AIF_TX_ENABLES);
|
||||
aif_rx_state = snd_soc_read(codec,
|
||||
base + ARIZONA_AIF_RX_ENABLES);
|
||||
/* Disable AIF TX/RX before reconfiguring it */
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
|
||||
regmap_update_bits(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
|
||||
}
|
||||
|
||||
ret = arizona_hw_params_rate(substream, params, dai);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
goto restore_aif;
|
||||
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_BCLK_CTRL,
|
||||
ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_BCLK_RATE,
|
||||
ARIZONA_AIF1TX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_BCLK_RATE,
|
||||
ARIZONA_AIF1RX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_FRAME_CTRL_1,
|
||||
ARIZONA_AIF1TX_WL_MASK |
|
||||
ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
|
||||
regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2,
|
||||
ARIZONA_AIF1RX_WL_MASK |
|
||||
ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
|
||||
if (reconfig) {
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_BCLK_CTRL,
|
||||
ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_BCLK_RATE,
|
||||
ARIZONA_AIF1TX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_BCLK_RATE,
|
||||
ARIZONA_AIF1RX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_FRAME_CTRL_1,
|
||||
ARIZONA_AIF1TX_WL_MASK |
|
||||
ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
|
||||
regmap_update_bits(arizona->regmap,
|
||||
base + ARIZONA_AIF_FRAME_CTRL_2,
|
||||
ARIZONA_AIF1RX_WL_MASK |
|
||||
ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
|
||||
}
|
||||
|
||||
return 0;
|
||||
restore_aif:
|
||||
if (reconfig) {
|
||||
/* Restore AIF TX/RX state */
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_ENABLES,
|
||||
0xff, aif_tx_state);
|
||||
regmap_update_bits(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_ENABLES,
|
||||
0xff, aif_rx_state);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *arizona_dai_clk_str(int clk_id)
|
||||
@ -1349,9 +1446,63 @@ static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
|
||||
ARIZONA_AIF1_TRI, reg);
|
||||
}
|
||||
|
||||
static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
|
||||
unsigned int base,
|
||||
int channels, unsigned int mask)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int slot, i;
|
||||
|
||||
for (i = 0; i < channels; ++i) {
|
||||
slot = ffs(mask) - 1;
|
||||
if (slot < 0)
|
||||
return;
|
||||
|
||||
regmap_write(arizona->regmap, base + i, slot);
|
||||
|
||||
mask &= ~(1 << slot);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
arizona_aif_warn(dai, "Too many channels in TDM mask\n");
|
||||
}
|
||||
|
||||
static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||
unsigned int rx_mask, int slots, int slot_width)
|
||||
{
|
||||
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;
|
||||
int rx_max_chan = dai->driver->playback.channels_max;
|
||||
int tx_max_chan = dai->driver->capture.channels_max;
|
||||
|
||||
/* Only support TDM for the physical AIFs */
|
||||
if (dai->id > ARIZONA_MAX_AIF)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (slots == 0) {
|
||||
tx_mask = (1 << tx_max_chan) - 1;
|
||||
rx_mask = (1 << rx_max_chan) - 1;
|
||||
}
|
||||
|
||||
arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
|
||||
tx_max_chan, tx_mask);
|
||||
arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
|
||||
rx_max_chan, rx_mask);
|
||||
|
||||
arizona->tdm_width[dai->id - 1] = slot_width;
|
||||
arizona->tdm_slots[dai->id - 1] = slots;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct snd_soc_dai_ops arizona_dai_ops = {
|
||||
.startup = arizona_startup,
|
||||
.set_fmt = arizona_set_fmt,
|
||||
.set_tdm_slot = arizona_set_tdm_slot,
|
||||
.hw_params = arizona_hw_params,
|
||||
.set_sysclk = arizona_dai_set_sysclk,
|
||||
.set_tristate = arizona_set_tristate,
|
||||
@ -1425,6 +1576,12 @@ static int arizona_validate_fll(struct arizona_fll *fll,
|
||||
{
|
||||
unsigned int Fvco_min;
|
||||
|
||||
if (fll->fout && Fout != fll->fout) {
|
||||
arizona_fll_err(fll,
|
||||
"Can't change output on active FLL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
|
||||
arizona_fll_err(fll,
|
||||
"Can't scale %dMHz in to <=13.5MHz\n",
|
||||
@ -1503,6 +1660,10 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
|
||||
while (div <= ARIZONA_FLL_MAX_REFDIV) {
|
||||
for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
|
||||
ratio++) {
|
||||
if ((ARIZONA_FLL_VCO_CORNER / 2) /
|
||||
(fll->vco_mult * ratio) < Fref)
|
||||
break;
|
||||
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
@ -1510,11 +1671,7 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
|
||||
}
|
||||
}
|
||||
|
||||
for (ratio = init_ratio - 1; ratio >= 0; ratio--) {
|
||||
if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) <
|
||||
Fref)
|
||||
break;
|
||||
|
||||
for (ratio = init_ratio - 1; ratio > 0; ratio--) {
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
@ -1641,7 +1798,7 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
|
||||
ARIZONA_FLL1_CTRL_UPD | cfg->n);
|
||||
}
|
||||
|
||||
static bool arizona_is_enabled_fll(struct arizona_fll *fll)
|
||||
static int arizona_is_enabled_fll(struct arizona_fll *fll)
|
||||
{
|
||||
struct arizona *arizona = fll->arizona;
|
||||
unsigned int reg;
|
||||
@ -1657,13 +1814,26 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll)
|
||||
return reg & ARIZONA_FLL1_ENA;
|
||||
}
|
||||
|
||||
static void arizona_enable_fll(struct arizona_fll *fll)
|
||||
static int arizona_enable_fll(struct arizona_fll *fll)
|
||||
{
|
||||
struct arizona *arizona = fll->arizona;
|
||||
int ret;
|
||||
bool use_sync = false;
|
||||
int already_enabled = arizona_is_enabled_fll(fll);
|
||||
struct arizona_fll_cfg cfg;
|
||||
|
||||
if (already_enabled < 0)
|
||||
return already_enabled;
|
||||
|
||||
if (already_enabled) {
|
||||
/* Facilitate smooth refclk across the transition */
|
||||
regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7,
|
||||
ARIZONA_FLL1_GAIN_MASK, 0);
|
||||
regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN,
|
||||
ARIZONA_FLL1_FREERUN);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have both REFCLK and SYNCCLK then enable both,
|
||||
* otherwise apply the SYNCCLK settings to REFCLK.
|
||||
@ -1691,7 +1861,7 @@ static void arizona_enable_fll(struct arizona_fll *fll)
|
||||
ARIZONA_FLL1_SYNC_ENA, 0);
|
||||
} else {
|
||||
arizona_fll_err(fll, "No clocks provided\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1706,14 +1876,12 @@ static void arizona_enable_fll(struct arizona_fll *fll)
|
||||
ARIZONA_FLL1_SYNC_BW,
|
||||
ARIZONA_FLL1_SYNC_BW);
|
||||
|
||||
if (!arizona_is_enabled_fll(fll))
|
||||
if (!already_enabled)
|
||||
pm_runtime_get(arizona->dev);
|
||||
|
||||
/* Clear any pending completions */
|
||||
try_wait_for_completion(&fll->ok);
|
||||
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN, 0);
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
|
||||
if (use_sync)
|
||||
@ -1721,10 +1889,16 @@ static void arizona_enable_fll(struct arizona_fll *fll)
|
||||
ARIZONA_FLL1_SYNC_ENA,
|
||||
ARIZONA_FLL1_SYNC_ENA);
|
||||
|
||||
if (already_enabled)
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN, 0);
|
||||
|
||||
ret = wait_for_completion_timeout(&fll->ok,
|
||||
msecs_to_jiffies(250));
|
||||
if (ret == 0)
|
||||
arizona_fll_warn(fll, "Timed out waiting for lock\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void arizona_disable_fll(struct arizona_fll *fll)
|
||||
@ -1738,6 +1912,8 @@ static void arizona_disable_fll(struct arizona_fll *fll)
|
||||
ARIZONA_FLL1_ENA, 0, &change);
|
||||
regmap_update_bits(arizona->regmap, fll->base + 0x11,
|
||||
ARIZONA_FLL1_SYNC_ENA, 0);
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN, 0);
|
||||
|
||||
if (change)
|
||||
pm_runtime_put_autosuspend(arizona->dev);
|
||||
@ -1746,7 +1922,7 @@ static void arizona_disable_fll(struct arizona_fll *fll)
|
||||
int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
||||
unsigned int Fref, unsigned int Fout)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (fll->ref_src == source && fll->ref_freq == Fref)
|
||||
return 0;
|
||||
@ -1761,17 +1937,17 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
||||
fll->ref_freq = Fref;
|
||||
|
||||
if (fll->fout && Fref > 0) {
|
||||
arizona_enable_fll(fll);
|
||||
ret = arizona_enable_fll(fll);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
|
||||
|
||||
int arizona_set_fll(struct arizona_fll *fll, int source,
|
||||
unsigned int Fref, unsigned int Fout)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (fll->sync_src == source &&
|
||||
fll->sync_freq == Fref && fll->fout == Fout)
|
||||
@ -1793,13 +1969,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
|
||||
fll->sync_freq = Fref;
|
||||
fll->fout = Fout;
|
||||
|
||||
if (Fout) {
|
||||
arizona_enable_fll(fll);
|
||||
} else {
|
||||
if (Fout)
|
||||
ret = arizona_enable_fll(fll);
|
||||
else
|
||||
arizona_disable_fll(fll);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_set_fll);
|
||||
|
||||
|
@ -735,8 +735,7 @@ WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE),
|
||||
static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_dapm_type event, int subseq)
|
||||
{
|
||||
struct snd_soc_codec *codec = container_of(dapm,
|
||||
struct snd_soc_codec, dapm);
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
|
||||
struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
|
||||
u16 val, expect, i;
|
||||
|
||||
|
@ -612,6 +612,62 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
|
||||
uint16_t data;
|
||||
|
||||
mutex_lock(&codec->mutex);
|
||||
data = cpu_to_be16(arizona->dac_comp_coeff);
|
||||
memcpy(ucontrol->value.bytes.data, &data, sizeof(data));
|
||||
mutex_unlock(&codec->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm5102_out_comp_coeff_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
|
||||
|
||||
mutex_lock(&codec->mutex);
|
||||
memcpy(&arizona->dac_comp_coeff, ucontrol->value.bytes.data,
|
||||
sizeof(arizona->dac_comp_coeff));
|
||||
arizona->dac_comp_coeff = be16_to_cpu(arizona->dac_comp_coeff);
|
||||
mutex_unlock(&codec->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm5102_out_comp_switch_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
|
||||
|
||||
mutex_lock(&codec->mutex);
|
||||
ucontrol->value.integer.value[0] = arizona->dac_comp_enabled;
|
||||
mutex_unlock(&codec->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm5102_out_comp_switch_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
|
||||
|
||||
mutex_lock(&codec->mutex);
|
||||
arizona->dac_comp_enabled = ucontrol->value.integer.value[0];
|
||||
mutex_unlock(&codec->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *wm5102_osr_text[] = {
|
||||
"Low power", "Normal", "High performance",
|
||||
};
|
||||
@ -843,6 +899,12 @@ SOC_SINGLE_TLV("Noise Gate Threshold Volume", ARIZONA_NOISE_GATE_CONTROL,
|
||||
ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv),
|
||||
SOC_ENUM("Noise Gate Hold", arizona_ng_hold),
|
||||
|
||||
SND_SOC_BYTES_EXT("Output Compensation Coefficient", 2,
|
||||
wm5102_out_comp_coeff_get, wm5102_out_comp_coeff_put),
|
||||
|
||||
SOC_SINGLE_EXT("Output Compensation Switch", 0, 0, 1, 0,
|
||||
wm5102_out_comp_switch_get, wm5102_out_comp_switch_put),
|
||||
|
||||
WM5102_NG_SRC("HPOUT1L", ARIZONA_NOISE_GATE_SELECT_1L),
|
||||
WM5102_NG_SRC("HPOUT1R", ARIZONA_NOISE_GATE_SELECT_1R),
|
||||
WM5102_NG_SRC("HPOUT2L", ARIZONA_NOISE_GATE_SELECT_2L),
|
||||
|
@ -281,8 +281,7 @@ static int wm8903_dcs_event(struct snd_soc_dapm_widget *w,
|
||||
static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_dapm_type event, int subseq)
|
||||
{
|
||||
struct snd_soc_codec *codec = container_of(dapm,
|
||||
struct snd_soc_codec, dapm);
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
|
||||
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
|
||||
int dcs_mode = WM8903_DCS_MODE_WRITE_STOP;
|
||||
int i, val;
|
||||
|
@ -690,8 +690,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask)
|
||||
static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_dapm_type event, int subseq)
|
||||
{
|
||||
struct snd_soc_codec *codec = container_of(dapm,
|
||||
struct snd_soc_codec, dapm);
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
|
||||
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
|
||||
u16 val, mask;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user