本文整理汇总了C++中snd_soc_read函数的典型用法代码示例。如果您正苦于以下问题:C++ snd_soc_read函数的具体用法?C++ snd_soc_read怎么用?C++ snd_soc_read使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了snd_soc_read函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。
示例1: cs4270_hw_params
/*
* Program the CS4270 with the given hardware parameters.
*
* The .dai_ops functions are used to provide board-specific data, like
* input frequencies, to this driver. This function takes that information,
* combines it with the hardware parameters provided, and programs the
* hardware accordingly.
*/
static int cs4270_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
struct cs4270_private *cs4270 = codec->private_data;
unsigned int ret = 0;
unsigned int i;
unsigned int rate;
unsigned int ratio;
int reg;
/* Figure out which MCLK/LRCK ratio to use */
rate = params_rate(params); /* Sampling rate, in Hz */
ratio = cs4270->mclk / rate; /* MCLK/LRCK ratio */
for (i = 0; i < NUM_MCLK_RATIOS; i++) {
if (mclk_ratios[i] == ratio)
break;
}
if (i == NUM_MCLK_RATIOS) {
/* We did not find a matching ratio */
printk(KERN_ERR "cs4270: could not find matching ratio\n");
return -EINVAL;
}
/* Freeze and power-down the codec */
ret = snd_soc_write(codec, CS4270_PWRCTL, CS4270_PWRCTL_FREEZE |
CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC |
CS4270_PWRCTL_PDN);
if (ret < 0) {
printk(KERN_ERR "cs4270: I2C write failed\n");
return ret;
}
/* Program the mode control register */
reg = snd_soc_read(codec, CS4270_MODE);
reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK);
reg |= cs4270_mode_ratios[i].speed_mode | cs4270_mode_ratios[i].mclk;
ret = snd_soc_write(codec, CS4270_MODE, reg);
if (ret < 0) {
printk(KERN_ERR "cs4270: I2C write failed\n");
return ret;
}
/* Program the format register */
reg = snd_soc_read(codec, CS4270_FORMAT);
reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK);
switch (cs4270->mode) {
case SND_SOC_DAIFMT_I2S:
reg |= CS4270_FORMAT_DAC_I2S | CS4270_FORMAT_ADC_I2S;
break;
case SND_SOC_DAIFMT_LEFT_J:
reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ;
break;
default:
printk(KERN_ERR "cs4270: unknown format\n");
return -EINVAL;
}
ret = snd_soc_write(codec, CS4270_FORMAT, reg);
if (ret < 0) {
printk(KERN_ERR "cs4270: I2C write failed\n");
return ret;
}
/* Disable auto-mute. This feature appears to be buggy, because in
some situations, auto-mute will not deactivate when it should. */
reg = snd_soc_read(codec, CS4270_MUTE);
reg &= ~CS4270_MUTE_AUTO;
ret = snd_soc_write(codec, CS4270_MUTE, reg);
if (ret < 0) {
printk(KERN_ERR "cs4270: I2C write failed\n");
return ret;
}
/* Thaw and power-up the codec */
ret = snd_soc_write(codec, CS4270_PWRCTL, 0);
if (ret < 0) {
printk(KERN_ERR "cs4270: I2C write failed\n");
return ret;
}
//.........这里部分代码省略.........
开发者ID:acassis,项目名称:emlinux-ssd1935,代码行数:101,代码来源:cs4270.c
示例2: wm8961_hw_params
static int wm8961_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 wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec);
int i, best, target, fs;
u16 reg;
fs = params_rate(params);
if (!wm8961->sysclk) {
dev_err(codec->dev, "MCLK has not been specified\n");
return -EINVAL;
}
best = 0;
for (i = 0; i < ARRAY_SIZE(wm8961_srate); i++) {
if (abs(wm8961_srate[i].rate - fs) <
abs(wm8961_srate[best].rate - fs))
best = i;
}
reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_3);
reg &= ~WM8961_SAMPLE_RATE_MASK;
reg |= wm8961_srate[best].val;
snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_3, reg);
dev_dbg(codec->dev, "Selected SRATE %dHz for %dHz\n",
wm8961_srate[best].rate, fs);
target = wm8961->sysclk / fs;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && target < 64) {
dev_err(codec->dev,
"SYSCLK must be at least 64*fs for DAC\n");
return -EINVAL;
}
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && target < 256) {
dev_err(codec->dev,
"SYSCLK must be at least 256*fs for ADC\n");
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(wm8961_clk_sys_ratio); i++) {
if (wm8961_clk_sys_ratio[i].ratio >= target)
break;
}
if (i == ARRAY_SIZE(wm8961_clk_sys_ratio)) {
dev_err(codec->dev, "Unable to generate CLK_SYS_RATE\n");
return -EINVAL;
}
dev_dbg(codec->dev, "Selected CLK_SYS_RATE of %d for %d/%d=%d\n",
wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs,
wm8961->sysclk / fs);
reg = snd_soc_read(codec, WM8961_CLOCKING_4);
reg &= ~WM8961_CLK_SYS_RATE_MASK;
reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT;
snd_soc_write(codec, WM8961_CLOCKING_4, reg);
reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0);
reg &= ~WM8961_WL_MASK;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
break;
case SNDRV_PCM_FORMAT_S20_3LE:
reg |= 1 << WM8961_WL_SHIFT;
break;
case SNDRV_PCM_FORMAT_S24_LE:
reg |= 2 << WM8961_WL_SHIFT;
break;
case SNDRV_PCM_FORMAT_S32_LE:
reg |= 3 << WM8961_WL_SHIFT;
break;
default:
return -EINVAL;
}
snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, reg);
reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2);
if (fs <= 24000)
reg |= WM8961_DACSLOPE;
else
reg &= ~WM8961_DACSLOPE;
snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
return 0;
}
开发者ID:MiniBlu,项目名称:cm11_kernel_htc_msm8974a3ul,代码行数:90,代码来源:wm8961.c
示例3: wm9081_set_dai_fmt
static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = dai->codec;
struct wm9081_priv *wm9081 = codec->private_data;
unsigned int aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2);
aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV |
WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
wm9081->master = 0;
break;
case SND_SOC_DAIFMT_CBS_CFM:
aif2 |= WM9081_LRCLK_DIR;
wm9081->master = 1;
break;
case SND_SOC_DAIFMT_CBM_CFS:
aif2 |= WM9081_BCLK_DIR;
wm9081->master = 1;
break;
case SND_SOC_DAIFMT_CBM_CFM:
aif2 |= WM9081_LRCLK_DIR | WM9081_BCLK_DIR;
wm9081->master = 1;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_B:
aif2 |= WM9081_AIF_LRCLK_INV;
case SND_SOC_DAIFMT_DSP_A:
aif2 |= 0x3;
break;
case SND_SOC_DAIFMT_I2S:
aif2 |= 0x2;
break;
case SND_SOC_DAIFMT_RIGHT_J:
break;
case SND_SOC_DAIFMT_LEFT_J:
aif2 |= 0x1;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_A:
case SND_SOC_DAIFMT_DSP_B:
/* frame inversion not valid for DSP modes */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_IB_NF:
aif2 |= WM9081_AIF_BCLK_INV;
break;
default:
return -EINVAL;
}
break;
case SND_SOC_DAIFMT_I2S:
case SND_SOC_DAIFMT_RIGHT_J:
case SND_SOC_DAIFMT_LEFT_J:
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_IB_IF:
aif2 |= WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV;
break;
case SND_SOC_DAIFMT_IB_NF:
aif2 |= WM9081_AIF_BCLK_INV;
break;
case SND_SOC_DAIFMT_NB_IF:
aif2 |= WM9081_AIF_LRCLK_INV;
break;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
return 0;
}
开发者ID:A2109devs,项目名称:lenovo_a2109a_kernel,代码行数:90,代码来源:wm9081.c
示例4: sdp4430_twl6040_init
static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct twl6040 *twl6040 = codec->control_data;
struct snd_soc_dapm_context *dapm = &codec->dapm;
int hsotrim, left_offset, right_offset, mode, ret;
/* Add SDP4430 specific controls */
ret = snd_soc_add_controls(codec, sdp4430_controls,
ARRAY_SIZE(sdp4430_controls));
if (ret)
return ret;
/* Add SDP4430 specific widgets */
ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
if (ret)
return ret;
/* Set up SDP4430 specific audio path audio_map */
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
/* SDP4430 connected pins */
snd_soc_dapm_enable_pin(dapm, "Ext Mic");
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
snd_soc_dapm_enable_pin(dapm, "AFML");
snd_soc_dapm_enable_pin(dapm, "AFMR");
snd_soc_dapm_enable_pin(dapm, "Headset Mic");
snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
/* allow audio paths from the audio modem to run during suspend */
snd_soc_dapm_ignore_suspend(dapm, "Ext Mic");
snd_soc_dapm_ignore_suspend(dapm, "Ext Spk");
snd_soc_dapm_ignore_suspend(dapm, "AFML");
snd_soc_dapm_ignore_suspend(dapm, "AFMR");
snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
snd_soc_dapm_ignore_suspend(dapm, "Headset Stereophone");
snd_soc_dapm_ignore_suspend(dapm, "Digital Mic 0");
snd_soc_dapm_ignore_suspend(dapm, "Digital Mic 1");
snd_soc_dapm_ignore_suspend(dapm, "Digital Mic 2");
ret = snd_soc_dapm_sync(dapm);
if (ret)
return ret;
/* Headset jack detection */
ret = snd_soc_jack_new(codec, "Headset Jack",
SND_JACK_HEADSET, &hs_jack);
if (ret)
return ret;
ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
hs_jack_pins);
if (machine_is_omap_4430sdp() || machine_is_omap_tabletblaze()
|| machine_is_omap4_panda())
twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
else
snd_soc_jack_report(&hs_jack, SND_JACK_HEADSET, SND_JACK_HEADSET);
/* DC offset cancellation computation */
hsotrim = snd_soc_read(codec, TWL6040_REG_HSOTRIM);
right_offset = (hsotrim & TWL6040_HSRO) >> TWL6040_HSRO_OFFSET;
left_offset = hsotrim & TWL6040_HSLO;
if (twl6040_get_icrev(twl6040) < TWL6040_REV_1_3)
/* For ES under ES_1.3 HS step is 2 mV */
mode = 2;
else
/* For ES_1.3 HS step is 1 mV */
mode = 1;
abe_dsp_set_hs_offset(left_offset, right_offset, mode);
/* don't wait before switching of HS power */
rtd->pmdown_time = 0;
return ret;
}
开发者ID:Pesach85,项目名称:lge-kernel-omap4,代码行数:80,代码来源:sdp4430.c
示例5: cs4270_hw_params
/**
* cs4270_hw_params - program the CS4270 with the given hardware parameters.
* @substream: the audio stream
* @params: the hardware parameters to set
* @dai: the SOC DAI (ignored)
*
* This function programs the hardware with the values provided.
* Specifically, the sample rate and the data format.
*
* The .ops functions are used to provide board-specific data, like input
* frequencies, to this driver. This function takes that information,
* combines it with the hardware parameters provided, and programs the
* hardware accordingly.
*/
static int cs4270_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec;
struct cs4270_private *cs4270 = codec->private_data;
int ret;
unsigned int i;
unsigned int rate;
unsigned int ratio;
int reg;
/* Figure out which MCLK/LRCK ratio to use */
rate = params_rate(params); /* Sampling rate, in Hz */
ratio = cs4270->mclk / rate; /* MCLK/LRCK ratio */
for (i = 0; i < NUM_MCLK_RATIOS; i++) {
if (cs4270_mode_ratios[i].ratio == ratio)
break;
}
if (i == NUM_MCLK_RATIOS) {
/* We did not find a matching ratio */
dev_err(codec->dev, "could not find matching ratio\n");
return -EINVAL;
}
/* Set the sample rate */
reg = snd_soc_read(codec, CS4270_MODE);
reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK);
reg |= cs4270_mode_ratios[i].mclk;
if (cs4270->slave_mode)
reg |= CS4270_MODE_SLAVE;
else
reg |= cs4270_mode_ratios[i].speed_mode;
ret = snd_soc_write(codec, CS4270_MODE, reg);
if (ret < 0) {
dev_err(codec->dev, "i2c write failed\n");
return ret;
}
/* Set the DAI format */
reg = snd_soc_read(codec, CS4270_FORMAT);
reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK);
switch (cs4270->mode) {
case SND_SOC_DAIFMT_I2S:
reg |= CS4270_FORMAT_DAC_I2S | CS4270_FORMAT_ADC_I2S;
break;
case SND_SOC_DAIFMT_LEFT_J:
reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ;
break;
default:
dev_err(codec->dev, "unknown dai format\n");
return -EINVAL;
}
ret = snd_soc_write(codec, CS4270_FORMAT, reg);
if (ret < 0) {
dev_err(codec->dev, "i2c write failed\n");
return ret;
}
return ret;
}
开发者ID:325116067,项目名称:semc-qsd8x50,代码行数:86,代码来源:cs4270.c
示例6: configure_clock
static int configure_clock(struct snd_soc_codec *codec)
{
struct wm9081_priv *wm9081 = codec->private_data;
int new_sysclk, i, target;
unsigned int reg;
int ret = 0;
int mclkdiv = 0;
int fll = 0;
switch (wm9081->sysclk_source) {
case WM9081_SYSCLK_MCLK:
if (wm9081->mclk_rate > 12225000) {
mclkdiv = 1;
wm9081->sysclk_rate = wm9081->mclk_rate / 2;
} else {
wm9081->sysclk_rate = wm9081->mclk_rate;
}
wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK, 0, 0);
break;
case WM9081_SYSCLK_FLL_MCLK:
/* If we have a sample rate calculate a CLK_SYS that
* gives us a suitable DAC configuration, plus BCLK.
* Ideally we would check to see if we can clock
* directly from MCLK and only use the FLL if this is
* not the case, though care must be taken with free
* running mode.
*/
if (wm9081->master && wm9081->bclk) {
/* Make sure we can generate CLK_SYS and BCLK
* and that we've got 3MHz for optimal
* performance. */
for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
target = wm9081->fs * clk_sys_rates[i].ratio;
new_sysclk = target;
if (target >= wm9081->bclk &&
target > 3000000)
break;
}
if (i == ARRAY_SIZE(clk_sys_rates))
return -EINVAL;
} else if (wm9081->fs) {
for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
new_sysclk = clk_sys_rates[i].ratio
* wm9081->fs;
if (new_sysclk > 3000000)
break;
}
if (i == ARRAY_SIZE(clk_sys_rates))
return -EINVAL;
} else {
new_sysclk = 12288000;
}
ret = wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK,
wm9081->mclk_rate, new_sysclk);
if (ret == 0) {
wm9081->sysclk_rate = new_sysclk;
/* Switch SYSCLK over to FLL */
fll = 1;
} else {
wm9081->sysclk_rate = wm9081->mclk_rate;
}
break;
default:
return -EINVAL;
}
reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_1);
if (mclkdiv)
reg |= WM9081_MCLKDIV2;
else
reg &= ~WM9081_MCLKDIV2;
snd_soc_write(codec, WM9081_CLOCK_CONTROL_1, reg);
reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3);
if (fll)
reg |= WM9081_CLK_SRC_SEL;
else
reg &= ~WM9081_CLK_SRC_SEL;
snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, reg);
dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm9081->sysclk_rate);
return ret;
}
开发者ID:A2109devs,项目名称:lenovo_a2109a_kernel,代码行数:92,代码来源:wm9081.c
示例7: out_pga_event
static int out_pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
int reg, val;
int dcs_mask;
int dcs_l, dcs_r;
int dcs_l_reg, dcs_r_reg;
int timeout;
int pwr_reg;
/* This code is shared between HP and LINEOUT; we do all our
* power management in stereo pairs to avoid latency issues so
* we reuse shift to identify which rather than strcmp() the
* name. */
reg = w->shift;
switch (reg) {
case WM8904_ANALOGUE_HP_0:
pwr_reg = WM8904_POWER_MANAGEMENT_2;
dcs_mask = WM8904_DCS_ENA_CHAN_0 | WM8904_DCS_ENA_CHAN_1;
dcs_r_reg = WM8904_DC_SERVO_8;
dcs_l_reg = WM8904_DC_SERVO_9;
dcs_l = 0;
dcs_r = 1;
break;
case WM8904_ANALOGUE_LINEOUT_0:
pwr_reg = WM8904_POWER_MANAGEMENT_3;
dcs_mask = WM8904_DCS_ENA_CHAN_2 | WM8904_DCS_ENA_CHAN_3;
dcs_r_reg = WM8904_DC_SERVO_6;
dcs_l_reg = WM8904_DC_SERVO_7;
dcs_l = 2;
dcs_r = 3;
break;
default:
WARN(1, "Invalid reg %d\n", reg);
return -EINVAL;
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* Power on the PGAs */
snd_soc_update_bits(codec, pwr_reg,
WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA,
WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA);
/* Power on the amplifier */
snd_soc_update_bits(codec, reg,
WM8904_HPL_ENA | WM8904_HPR_ENA,
WM8904_HPL_ENA | WM8904_HPR_ENA);
/* Enable the first stage */
snd_soc_update_bits(codec, reg,
WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY,
WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY);
/* Power up the DC servo */
snd_soc_update_bits(codec, WM8904_DC_SERVO_0,
dcs_mask, dcs_mask);
/* Either calibrate the DC servo or restore cached state
* if we have that.
*/
if (wm8904->dcs_state[dcs_l] || wm8904->dcs_state[dcs_r]) {
dev_dbg(codec->dev, "Restoring DC servo state\n");
snd_soc_write(codec, dcs_l_reg,
wm8904->dcs_state[dcs_l]);
snd_soc_write(codec, dcs_r_reg,
wm8904->dcs_state[dcs_r]);
snd_soc_write(codec, WM8904_DC_SERVO_1, dcs_mask);
timeout = 20;
} else {
dev_dbg(codec->dev, "Calibrating DC servo\n");
snd_soc_write(codec, WM8904_DC_SERVO_1,
dcs_mask << WM8904_DCS_TRIG_STARTUP_0_SHIFT);
timeout = 500;
}
/* Wait for DC servo to complete */
dcs_mask <<= WM8904_DCS_CAL_COMPLETE_SHIFT;
do {
val = snd_soc_read(codec, WM8904_DC_SERVO_READBACK_0);
if ((val & dcs_mask) == dcs_mask)
break;
msleep(1);
} while (--timeout);
if ((val & dcs_mask) != dcs_mask)
dev_warn(codec->dev, "DC servo timed out\n");
else
dev_dbg(codec->dev, "DC servo ready\n");
//.........这里部分代码省略.........
开发者ID:rajat1994,项目名称:linux,代码行数:101,代码来源:wm8904.c
示例8: alc5632_set_dai_pll
static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
int source, unsigned int freq_in, unsigned int freq_out)
{
int i;
struct snd_soc_codec *codec = codec_dai->codec;
int gbl_clk = 0, pll_div = 0;
u16 reg;
if (pll_id < ALC5632_PLL_FR_MCLK || pll_id > ALC5632_PLL_FR_VBCLK)
return -EINVAL;
/* */
snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
ALC5632_PWR_ADD2_PLL1,
0);
snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
ALC5632_PWR_ADD2_PLL2,
0);
/* */
reg = snd_soc_read(codec, ALC5632_DAI_CONTROL);
if (reg & ALC5632_DAI_SDP_SLAVE_MODE)
return 0;
if (!freq_in || !freq_out)
return 0;
switch (pll_id) {
case ALC5632_PLL_FR_MCLK:
for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) {
if (codec_master_pll_div[i].pll_in == freq_in
&& codec_master_pll_div[i].pll_out == freq_out) {
/* */
pll_div = codec_master_pll_div[i].regvalue;
break;
}
}
break;
case ALC5632_PLL_FR_BCLK:
for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
if (codec_slave_pll_div[i].pll_in == freq_in
&& codec_slave_pll_div[i].pll_out == freq_out) {
/* */
gbl_clk = ALC5632_PLL_FR_BCLK;
pll_div = codec_slave_pll_div[i].regvalue;
break;
}
}
break;
case ALC5632_PLL_FR_VBCLK:
for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
if (codec_slave_pll_div[i].pll_in == freq_in
&& codec_slave_pll_div[i].pll_out == freq_out) {
/* */
gbl_clk = ALC5632_PLL_FR_VBCLK;
pll_div = codec_slave_pll_div[i].regvalue;
break;
}
}
break;
default:
return -EINVAL;
}
if (!pll_div)
return -EINVAL;
/* */
snd_soc_write(codec, ALC5632_GPCR2, gbl_clk);
/* */
snd_soc_write(codec, ALC5632_PLL1_CTRL, pll_div);
/* */
snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
ALC5632_PWR_ADD2_PLL1,
ALC5632_PWR_ADD2_PLL1);
/* */
snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
ALC5632_PWR_ADD2_PLL2,
ALC5632_PWR_ADD2_PLL2);
/* */
snd_soc_update_bits(codec, ALC5632_GPCR1,
ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1,
ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1);
return 0;
}
开发者ID:romanbb,项目名称:android_kernel_lge_d851,代码行数:86,代码来源:alc5632.c
示例9: rt_codec_hwdep_ioctl_common
static int rt_codec_hwdep_ioctl_common(struct snd_hwdep *hw,
struct file *file, unsigned int cmd, unsigned long arg)
{
struct snd_soc_codec *codec = hw->private_data;
struct rt_codec_cmd __user *_rt_codec = (struct rt_codec_cmd *)arg;
struct rt_codec_cmd rt_codec;
int *buf, *p;
if (copy_from_user(&rt_codec, _rt_codec, sizeof(rt_codec))) {
dev_err(codec->dev, "copy_from_user faild\n");
return -EFAULT;
}
dev_dbg(codec->dev, "%s(): rt_codec.number=%d, cmd=%d\n",
__func__, rt_codec.number, cmd);
buf = kmalloc(sizeof(*buf) * rt_codec.number, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
if (copy_from_user(buf, rt_codec.buf, sizeof(*buf) * rt_codec.number))
goto err;
switch (cmd) {
case RT_READ_CODEC_REG_IOCTL:
for (p = buf; p < buf + rt_codec.number / 2; p++)
*(p + rt_codec.number / 2) = snd_soc_read(codec, *p);
if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number))
goto err;
break;
case RT_WRITE_CODEC_REG_IOCTL:
for (p = buf; p < buf + rt_codec.number / 2; p++)
snd_soc_write(codec, *p, *(p + rt_codec.number / 2));
break;
case RT_READ_CODEC_INDEX_IOCTL:
if (NULL == rt_codec_ioctl_ops.index_read)
goto err;
for (p = buf; p < buf + rt_codec.number / 2; p++)
*(p+rt_codec.number / 2) = rt_codec_ioctl_ops.index_read(
codec, *p);
if (copy_to_user(rt_codec.buf, buf,
sizeof(*buf) * rt_codec.number))
goto err;
break;
case RT_WRITE_CODEC_INDEX_IOCTL:
if (NULL == rt_codec_ioctl_ops.index_write)
goto err;
for (p = buf; p < buf + rt_codec.number / 2; p++) {
dev_dbg(codec->dev, "%x , %x\n",
*p, *(p+rt_codec.number / 2));
rt_codec_ioctl_ops.index_write(codec, *p,
*(p+rt_codec.number / 2));
}
break;
default:
if (NULL == rt_codec_ioctl_ops.ioctl_common)
goto err;
rt_codec_ioctl_ops.ioctl_common(hw, file, cmd, arg);
break;
}
kfree(buf);
return 0;
err:
kfree(buf);
return -EFAULT;
}
开发者ID:matheusgcdj,项目名称:android_kernel_asus_T00F,代码行数:70,代码来源:rt_codec_ioctl.c
示例10: sta32x_hw_params
/**
* sta32x_hw_params - program the STA32X with the given hardware parameters.
* @substream: the audio stream
* @params: the hardware parameters to set
* @dai: the SOC DAI (ignored)
*
* This function programs the hardware with the values provided.
* Specifically, the sample rate and the data format.
*/
static int sta32x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
unsigned int rate;
int i, mcs = -1, ir = -1;
u8 confa, confb;
rate = params_rate(params);
pr_debug("rate: %u\n", rate);
for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++)
if (interpolation_ratios[i].fs == rate) {
ir = interpolation_ratios[i].ir;
break;
}
if (ir < 0)
return -EINVAL;
for (i = 0; mclk_ratios[ir][i].ratio; i++)
if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) {
mcs = mclk_ratios[ir][i].mcs;
break;
}
if (mcs < 0)
return -EINVAL;
confa = snd_soc_read(codec, STA32X_CONFA);
confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK);
confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT);
confb = snd_soc_read(codec, STA32X_CONFB);
confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB);
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_S24_3BE:
pr_debug("24bit\n");
/* fall through */
case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S32_BE:
pr_debug("24bit or 32bit\n");
switch (sta32x->format) {
case SND_SOC_DAIFMT_I2S:
confb |= 0x0;
break;
case SND_SOC_DAIFMT_LEFT_J:
confb |= 0x1;
break;
case SND_SOC_DAIFMT_RIGHT_J:
confb |= 0x2;
break;
}
break;
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S20_3BE:
pr_debug("20bit\n");
switch (sta32x->format) {
case SND_SOC_DAIFMT_I2S:
confb |= 0x4;
break;
case SND_SOC_DAIFMT_LEFT_J:
confb |= 0x5;
break;
case SND_SOC_DAIFMT_RIGHT_J:
confb |= 0x6;
break;
}
break;
case SNDRV_PCM_FORMAT_S18_3LE:
case SNDRV_PCM_FORMAT_S18_3BE:
pr_debug("18bit\n");
switch (sta32x->format) {
case SND_SOC_DAIFMT_I2S:
confb |= 0x8;
break;
case SND_SOC_DAIFMT_LEFT_J:
confb |= 0x9;
break;
case SND_SOC_DAIFMT_RIGHT_J:
confb |= 0xa;
break;
}
break;
case SNDRV_PCM_FORMAT_S16_LE:
case SNDRV_PCM_FORMAT_S16_BE:
//.........这里部分代码省略.........
开发者ID:openube,项目名称:android_kernel_sony_c2305,代码行数:101,代码来源:sta32x.c
示例11: cs42l73_set_dai_fmt
static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
u8 id = codec_dai->id;
unsigned int inv, format;
u8 spc, mmcc;
spc = snd_soc_read(codec, CS42L73_SPC(id));
mmcc = snd_soc_read(codec, CS42L73_MMCC(id));
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
mmcc |= CS42L73_MS_MASTER;
break;
case SND_SOC_DAIFMT_CBS_CFS:
mmcc &= ~CS42L73_MS_MASTER;
break;
default:
return -EINVAL;
}
format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
inv = (fmt & SND_SOC_DAIFMT_INV_MASK);
switch (format) {
case SND_SOC_DAIFMT_I2S:
spc &= ~CS42L73_SPDIF_PCM;
break;
case SND_SOC_DAIFMT_DSP_A:
case SND_SOC_DAIFMT_DSP_B:
if (mmcc & CS42L73_MS_MASTER) {
dev_err(codec->dev,
"PCM format in slave mode only\n");
return -EINVAL;
}
if (id == CS42L73_ASP) {
dev_err(codec->dev,
"PCM format is not supported on ASP port\n");
return -EINVAL;
}
spc |= CS42L73_SPDIF_PCM;
break;
default:
return -EINVAL;
}
if (spc & CS42L73_SPDIF_PCM) {
/* Clear PCM mode, clear PCM_BIT_ORDER bit for MSB->LSB */
spc &= ~(CS42L73_PCM_MODE_MASK | CS42L73_PCM_BIT_ORDER);
switch (format) {
case SND_SOC_DAIFMT_DSP_B:
if (inv == SND_SOC_DAIFMT_IB_IF)
spc |= CS42L73_PCM_MODE0;
if (inv == SND_SOC_DAIFMT_IB_NF)
spc |= CS42L73_PCM_MODE1;
break;
case SND_SOC_DAIFMT_DSP_A:
if (inv == SND_SOC_DAIFMT_IB_IF)
spc |= CS42L73_PCM_MODE1;
break;
default:
return -EINVAL;
}
}
priv->config[id].spc = spc;
priv->config[id].mmcc = mmcc;
return 0;
}
开发者ID:acton393,项目名称:linux,代码行数:73,代码来源:cs42l73.c
示例12: most2120_codec_hw_params
//.........这里部分代码省略.........
ddiv = WM8960_DAC_DIV_2;
adiv = WM8960_ADC_DIV_2;
bdiv = WM8960_BCLK_DIV_8;
pll_out = 11289600;
break;
case 44100:
ddiv = WM8960_DAC_DIV_1;
adiv = WM8960_ADC_DIV_1;
bdiv = WM8960_BCLK_DIV_4;
pll_out = 11289600;
break;
default :
ddiv = WM8960_DAC_DIV_1;
adiv = WM8960_ADC_DIV_1;
bdiv = WM8960_BCLK_DIV_4;
pll_out = 11289600;
}
/* NEXELL's nxp2120 has limited clock generation function, so it would be better
Nxp2120 only generate reference clock from PLL1, 192MHz / 16 = 12 MHz...
And then let WM8960 generate required clock for itself. */
/* set codec DAI configuration */
ret = snd_soc_dai_set_fmt(codec_dai,
SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM); /* Set master mode for generate bitclk and fs(lrclk) */
if (ret < 0)
return ret;
/* set cpu DAI configuration */
ret = snd_soc_dai_set_fmt(cpu_dai,
SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS); /* Set slave mode for bitclk, and fs(lrclk) */
if (ret < 0)
return ret;
/* set CPU generate reference clock for Codec's PLL. So Set PLL1 as clock source. */
ret = snd_soc_dai_set_sysclk(cpu_dai, NX_I2S_CLKSRC_0, NX_I2S_CLKSRC0_PLL1, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
/* Our I2S is Slave, So Set to EXT_BIT. */
ret = snd_soc_dai_set_sysclk(cpu_dai, NX_I2S_CLKSRC_1, NX_I2S_CLKSRC1_EXT_BIT, SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
/* Set prescaler set to 16 to generate 12MHz around clock */
ret = snd_soc_dai_set_clkdiv(cpu_dai, NX_I2S_CLKDIV_0, 16 - 1); /* PLL1 192MHz -> 12MHz with 1/16 */
if (ret < 0)
return ret;
/* Use Bitclk as Clock Source and no division. */
ret = snd_soc_dai_set_clkdiv(cpu_dai, NX_I2S_CLKDIV_1, 1 - 1); /* No div as BITCLK */
if (ret < 0)
return ret;
/* Set fs as 64fs(256fs). */
ret = snd_soc_dai_set_clkdiv(cpu_dai, NX_I2S_CLKDIV_SYNC_PERIOD, NX_I2S_PERDIV_64);
if (ret < 0)
return ret;
/* set codec sysclock from PLL source */
ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_SYSCLKSEL, WM8960_SYSCLK_PLL);
if (ret < 0)
return ret;
/* Now All the bit rate and rootclock should be set. */
/* set codec sysclock from PLL source */
ret = snd_soc_dai_set_pll(codec_dai, 0, 0, iis_clk / 16, pll_out);
if (ret < 0)
return ret;
/* set codec speaker DCLK for SYSCLK/2. -> SYSCLK/16 */
ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_DCLKDIV, WM8960_DCLK_DIV_16);
if (ret < 0)
return ret;
/* set codec DAC div factor to ddiv. */
ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_DACDIV, ddiv);
if (ret < 0)
return ret;
/* set codec ADC div factor to adiv. */
ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_ADCDIV, adiv);
if (ret < 0)
return ret;
/* Bit Clock should be devided for NEXELL 256fs machine */
ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_BCLKDIV, bdiv);
if (ret < 0)
return ret;
#if MOST2120_WM8960_DEBUG
for (i=0; i<56;i++) {
printk("codec addr = 0x%x(%d) val= %x\n", i, i, snd_soc_read(codec_dai->codec, i));
}
#endif
return 0;
}
开发者ID:vlasenko,项目名称:kernel.rk,代码行数:101,代码来源:nexell-wm8960.c
示例13: wm8961_register
static int wm8961_register(struct wm8961_priv *wm8961)
{
struct snd_soc_codec *codec = &wm8961->codec;
int ret;
u16 reg;
if (wm8961_codec) {
dev_err(codec->dev, "Another WM8961 is registered\n");
ret = -EINVAL;
goto err;
}
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
snd_soc_codec_set_drvdata(codec, wm8961);
codec->name = "WM8961";
codec->owner = THIS_MODULE;
codec->dai = &wm8961_dai;
codec->num_dai = 1;
codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache);
codec->reg_cache = &wm8961->reg_cache;
codec->bias_level = SND_SOC_BIAS_OFF;
codec->set_bias_level = wm8961_set_bias_level;
codec->volatile_register = wm8961_volatile_register;
memcpy(codec->reg_cache, wm8961_reg_defaults,
sizeof(wm8961_reg_defaults));
ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
goto err;
}
reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET);
if (reg != 0x1801) {
dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg);
ret = -EINVAL;
goto err;
}
/* This isn't volatile - readback doesn't correspond to write */
reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME);
dev_info(codec->dev, "WM8961 family %d revision %c\n",
(reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
+ 'A');
ret = wm8961_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
return ret;
}
/* Enable class W */
reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B);
reg |= WM8961_CP_DYN_PWR_MASK;
snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg);
/* Latch volume update bits (right channel only, we always
* write both out) and default ZC on. */
reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME);
snd_soc_write(codec, WM8961_ROUT1_VOLUME,
reg | WM8961_LO1ZC | WM8961_OUT1VU);
snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC);
reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME);
snd_soc_write(codec, WM8961_ROUT2_VOLUME,
reg | WM8961_SPKRZC | WM8961_SPKVU);
snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC);
reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME);
snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU);
reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME);
snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU);
/* Use soft mute by default */
reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2);
reg |= WM8961_DACSMM;
snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
/* Use automatic clocking mode by default; for now this is all
* we support.
*/
reg = snd_soc_read(codec, WM8961_CLOCKING_3);
reg &= ~WM8961_MANUAL_MODE;
snd_soc_write(codec, WM8961_CLOCKING_3, reg);
wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm8961_dai.dev = codec->dev;
wm8961_codec = codec;
ret = snd_soc_register_codec(codec);
if (ret != 0) {
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
return ret;
}
//.........这里部分代码省略.........
开发者ID:12rafael,项目名称:jellytimekernel,代码行数:101,代码来源:wm8961.c
示例14: wm8523_register
static int wm8523_register(struct wm8523_priv *wm8523,
enum snd_soc_control_type control)
{
int ret;
struct snd_soc_codec *codec = &wm8523->codec;
int i;
if (wm8523_codec) {
dev_err(codec->dev, "Another WM8523 is registered\n");
return -EINVAL;
}
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
snd_soc_codec_set_drvdata(codec, wm8523);
codec->name = "WM8523";
codec->owner = THIS_MODULE;
codec->bias_level = SND_SOC_BIAS_OFF;
codec->set_bias_level = wm8523_set_bias_level;
codec->dai = &wm8523_dai;
codec->num_dai = 1;
codec->reg_cache_size = WM8523_REGISTER_COUNT;
codec->reg_cache = &wm8523->reg_cache;
codec->volatile_register = wm8523_volatile_register;
wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
wm8523->rate_constraint.count =
ARRAY_SIZE(wm8523->rate_constraint_list);
memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg));
ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
goto err;
}
for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
wm8523->supplies[i].supply = wm8523_supply_names[i];
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies),
wm8523->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
goto err;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
wm8523->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
goto err_get;
}
ret = snd_soc_read(codec, WM8523_DEVICE_ID);
if (ret < 0) {
dev_err(codec->dev, "Failed to read ID register\n");
goto err_enable;
}
if (ret != wm8523_reg[WM8523_DEVICE_ID]) {
dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret);
ret = -EINVAL;
goto err_enable;
}
ret = snd_soc_read(codec, WM8523_REVISION);
if (ret < 0) {
dev_err(codec->dev, "Failed to read revision register\n");
goto err_enable;
}
dev_info(codec->dev, "revision %c\n",
(ret & WM8523_CHIP_REV_MASK) + 'A');
ret = wm8523_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
goto err_enable;
}
wm8523_dai.dev = codec->dev;
/* Change some default settings - latch VU and enable ZC */
wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
wm8523_codec = codec;
ret = snd_soc_register_codec(codec);
if (ret != 0) {
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
return ret;
}
//.........这里部分代码省略.........
开发者ID:12rafael,项目名称:jellytimekernel,代码行数:101,代码来源:wm8523.c
示例15: wm8961_hp_event
/*
* The headphone output supports special anti-pop sequences giving
* silent power up and power down.
*/
static int wm8961_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
u16 hp_reg = snd_soc_read(codec, WM8961_ANALOGUE_HP_0);
u16 cp_reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_1);
u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2);
u16 dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1);
int timeout = 500;
if (event & SND_SOC_DAPM_POST_PMU) {
/* Make sure the output is shorted */
hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
/* Enable the charge pump */
cp_reg |= WM8961_CP_ENA;
snd_soc_write(codec, WM8961_CHARGE_PUMP_1, cp_reg);
mdelay(5);
/* Enable the PGA */
pwr_reg |= WM8961_LOUT1_PGA | WM8961_ROUT1_PGA;
snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
/* Enable the amplifier */
hp_reg |= WM8961_HPR_ENA | WM8961_HPL_ENA;
snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
/* Second stage enable */
hp_reg |= WM8961_HPR_ENA_DLY | WM8961_HPL_ENA_DLY;
snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
/* Enable the DC servo & trigger startup */
dcs_reg |=
WM8961_DCS_ENA_CHAN_HPR | WM8961_DCS_TRIG_STARTUP_HPR |
WM8961_DCS_ENA_CHAN_HPL | WM8961_DCS_TRIG_STARTUP_HPL;
dev_dbg(codec->dev, "Enabling DC servo\n");
snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg);
do {
msleep(1);
dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1);
} while (--timeout &&
dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
WM8961_DCS_TRIG_STARTUP_HPL));
if (dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
WM8961_DCS_TRIG_STARTUP_HPL))
dev_err(codec->dev, "DC servo timed out\n");
else
dev_dbg(codec->dev, "DC servo startup complete\n");
/* Enable the output stage */
hp_reg |= WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP;
snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
/* Remove the short on the output stage */
hp_reg |= WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT;
snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
}
if (event & SND_SOC_DAPM_PRE_PMD) {
/* Short the output */
hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
/* Disable the output stage */
hp_reg &= ~(WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP);
snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
/* Disable DC offset cancellation */
dcs_reg &= ~(WM8961_DCS_ENA_CHAN_HPR |
WM8961_DCS_ENA_CHAN_HPL);
snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg);
/* Finish up */
hp_reg &= ~(WM8961_HPR_ENA_DLY | WM8961_HPR_ENA |
WM8961_HPL_ENA_DLY | WM8961_HPL_ENA);
snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
/* Disable the PGA */
pwr_reg &= ~(WM8961_LOUT1_PGA | WM8961_ROUT1_PGA);
snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
/* Disable the charge pump */
dev_dbg(codec->dev, "Disabling charge pump\n");
snd_soc_write(codec, WM8961_CHARGE_PUMP_1,
cp_reg & ~WM8961_CP_ENA);
}
return 0;
}
开发者ID:12rafael,项目名称:jellytimekernel,代码行数:95,代码来源:wm8961.c
示例16: wm8900_hp_event
static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* Clamp headphone outputs */
hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP |
WM8900_REG_HPCTL1_HP_CLAMP_OP;
snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
break;
case SND_SOC_DAPM_POST_PMU:
/* Enable the input stage */
hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_IP;
hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT |
WM8900_REG_HPCTL1_HP_SHORT2 |
WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
msleep(400);
/* Enable the output stage */
hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP;
hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
/* Remove the shorts */
hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2;
snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT;
snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
break;
case SND_SOC_DAPM_PRE_PMD:
/* Short the output */
hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT;
snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
/* Disable the output stage */
hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
/* Clamp the outputs and power down input */
hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP |
WM8900_REG_HPCTL1_HP_CLAMP_OP;
hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
break;
case SND_SOC_DAPM_POST_PMD:
/* Disable everything */
snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
break;
default:
BUG();
}
return 0;
}
开发者ID:12rafael,项目名称:jellytimekernel,代码行数:63,代码来源:wm8900.c
|
请发表评论