static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) { struct snd_soc_codec *codec = codec_dai->codec; u8 mode = 0; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_LEFT_J: mode = LEFT_J_DATA_FORMAT; break; case SND_SOC_DAIFMT_I2S: mode = I2S_DATA_FORMAT; break; case SND_SOC_DAIFMT_RIGHT_J: mode = RIGHT_J_DATA_FORMAT; break; default: return -EINVAL; } snd_soc_update_bits(codec, STA529_S2PCFG0, DATA_FORMAT_MSK, mode); return 0; }
static int mc13783_pcm_hw_params_codec(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; unsigned int rate = params_rate(params); unsigned int val; switch (rate) { case 8000: val = 0; break; case 16000: val = AUDIO_CODEC_CDCFS8K16K; break; default: return -EINVAL; } snd_soc_update_bits(codec, MC13783_AUDIO_CODEC, AUDIO_CODEC_CDCFS8K16K, val); return 0; }
static void wcd9xxx_cfg_clsh_param_common( struct snd_soc_codec *codec) { int i; const struct wcd9xxx_reg_mask_val reg_set[] = { {WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS, 0x3 << 0, 0}, {WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS, 0x3 << 2, 1 << 2}, {WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS, (0x1 << 4), 0}, {WCD9XXX_A_CDC_CLSH_B2_CTL, (0x3 << 0), 0x01}, {WCD9XXX_A_CDC_CLSH_B2_CTL, (0x3 << 2), (0x01 << 2)}, {WCD9XXX_A_CDC_CLSH_B2_CTL, (0xf << 4), (0x03 << 4)}, {WCD9XXX_A_CDC_CLSH_B3_CTL, (0xf << 4), (0x03 << 4)}, {WCD9XXX_A_CDC_CLSH_B3_CTL, (0xf << 0), (0x0B)}, {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 5), (0x01 << 5)}, {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 1), (0x01 << 1)}, }; for (i = 0; i < ARRAY_SIZE(reg_set); i++) snd_soc_update_bits(codec, reg_set[i].reg, reg_set[i].mask, reg_set[i].val); dev_dbg(codec->dev, "%s: Programmed class H controller common parameters", __func__); }
int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec, struct list_head *list, uint16_t reg, uint8_t mask, uint8_t value, int delay) { int rc; struct wcd9xxx_register_save_node *node; node = kmalloc(sizeof(*node), GFP_KERNEL); if (unlikely(!node)) { pr_err("%s: Not enough memory\n", __func__); return -ENOMEM; } node->reg = reg; node->value = snd_soc_read(codec, reg); list_add(&node->lh, list); if (mask == 0xFF) rc = snd_soc_write(codec, reg, value); else rc = snd_soc_update_bits(codec, reg, mask, value); if (delay) usleep_range(delay, delay + USLEEP_RANGE_MARGIN_US); return rc; }
static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = codec_dai->codec; struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); int i; dev_dbg(codec->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n", __func__, clk_id, freq, dir); for (i = 0; aic31xx_divs[i].mclk != freq; i++) if (i == ARRAY_SIZE(aic31xx_divs)) { dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", __func__, freq); return -EINVAL; } /* set clock on MCLK, BCLK, or GPIO1 as PLL input */ snd_soc_update_bits(codec, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK, clk_id << AIC31XX_PLL_CLKIN_SHIFT); aic31xx->sysclk = freq; return 0; }
void cs42l73_bp_detection(struct snd_soc_codec *codec, struct snd_soc_jack *jack, int plug_status) { unsigned int status; unsigned int reg; unsigned int mask = SND_JACK_BTN_0 | SND_JACK_HEADSET; if (plug_status) { pr_err("%s: Invalid interrupt\n", __func__); return; } else { snd_soc_update_bits(codec, CS42L73_IM1, MIC2_SDET, MIC2_SDET); reg = snd_soc_read(codec, CS42L73_IS1); if (reg & MIC2_SDET) { /*button pressed */ pr_debug("%s:Button Pressed\n", __func__); status = SND_JACK_HEADSET | SND_JACK_BTN_0; } else { pr_debug("%s:Button Released\n", __func__); status = SND_JACK_HEADSET; } } snd_soc_jack_report(jack, status, mask); }
void wcd9xxx_enable_high_perf_mode(struct snd_soc_codec *codec, struct wcd9xxx_clsh_cdc_data *clsh_d, u8 req_state, bool req_type) { dev_dbg(codec->dev, "%s: users fclk8 %d, fclk5 %d", __func__, clsh_d->ncp_users[NCP_FCLK_LEVEL_8], clsh_d->ncp_users[NCP_FCLK_LEVEL_5]); if (req_type == WCD9XXX_CLSAB_REQ_ENABLE) { clsh_d->ncp_users[NCP_FCLK_LEVEL_8]++; snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CHOP_CTL, 0x20, 0x00); wcd9xxx_chargepump_request(codec, true); wcd9xxx_enable_anc_delay(codec, true); if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] > 0) snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x08); snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x30, 0x30); /* Enable NCP and wait until settles down */ if (snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x01)) usleep_range(NCP_SETTLE_TIME_US, NCP_SETTLE_TIME_US+10); } else { snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CHOP_CTL, 0x20, 0x20); wcd9xxx_chargepump_request(codec, false); wcd9xxx_enable_anc_delay(codec, false); clsh_d->ncp_users[NCP_FCLK_LEVEL_8]--; if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0 && clsh_d->ncp_users[NCP_FCLK_LEVEL_5] == 0) snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x00); else if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0) snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x05); } dev_dbg(codec->dev, "%s: leave\n", __func__); }
int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, int lineout1_diff, int lineout2_diff, int lineout1fb, int lineout2fb, int jd_scthr, int jd_thr, int micbias1_lvl, int micbias2_lvl) { struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); hubs->lineout1_se = !lineout1_diff; hubs->lineout2_se = !lineout2_diff; if (!lineout1_diff) snd_soc_update_bits(codec, WM8993_LINE_MIXER1, WM8993_LINEOUT1_MODE, WM8993_LINEOUT1_MODE); if (!lineout2_diff) snd_soc_update_bits(codec, WM8993_LINE_MIXER2, WM8993_LINEOUT2_MODE, WM8993_LINEOUT2_MODE); if (!lineout1_diff && !lineout2_diff) snd_soc_update_bits(codec, WM8993_ANTIPOP1, WM8993_LINEOUT_VMID_BUF_ENA, WM8993_LINEOUT_VMID_BUF_ENA); if (lineout1fb) snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB); if (lineout2fb) snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB); snd_soc_update_bits(codec, WM8993_MICBIAS, WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK | WM8993_MICB1_LVL | WM8993_MICB2_LVL, jd_scthr << WM8993_JD_SCTHR_SHIFT | jd_thr << WM8993_JD_THR_SHIFT | micbias1_lvl | micbias2_lvl << WM8993_MICB2_LVL_SHIFT); return 0; }
static void enable_power_depop(struct snd_soc_codec *codec) { snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, ALC5632_PWR_ADD1_SOFTGEN_EN, ALC5632_PWR_ADD1_SOFTGEN_EN); snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3, ALC5632_ADD3_POWER_EN, ALC5632_ADD3_POWER_EN); snd_soc_update_bits(codec, ALC5632_MISC_CTRL, ALC5632_MISC_HP_DEPOP_MODE2_EN, ALC5632_MISC_HP_DEPOP_MODE2_EN); /* "normal" mode: 0 @ 26 */ /* set all PR0-7 mixers to 0 */ snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS, ALC5632_PWR_DOWN_CTRL_STATUS_MASK, 0); msleep(500); snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, ALC5632_ADD2_POWER_EN, ALC5632_ADD2_POWER_EN); snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, ALC5632_ADD1_POWER_EN, ALC5632_ADD1_POWER_EN); /* disable HP Depop2 */ snd_soc_update_bits(codec, ALC5632_MISC_CTRL, ALC5632_MISC_HP_DEPOP_MODE2_EN, 0); }
static void enable_power_depop(struct snd_soc_codec *codec) { snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, ALC5632_PWR_ADD1_SOFTGEN_EN, ALC5632_PWR_ADD1_SOFTGEN_EN); snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3, ALC5632_ADD3_POWER_EN, ALC5632_ADD3_POWER_EN); snd_soc_update_bits(codec, ALC5632_MISC_CTRL, ALC5632_MISC_HP_DEPOP_MODE2_EN, ALC5632_MISC_HP_DEPOP_MODE2_EN); /* */ /* */ snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS, ALC5632_PWR_DOWN_CTRL_STATUS_MASK, 0); msleep(500); snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, ALC5632_ADD2_POWER_EN, ALC5632_ADD2_POWER_EN); snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, ALC5632_ADD1_POWER_EN, ALC5632_ADD1_POWER_EN); /* */ snd_soc_update_bits(codec, ALC5632_MISC_CTRL, ALC5632_MISC_HP_DEPOP_MODE2_EN, 0); }
static int mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { struct snd_soc_codec *codec = w->codec; pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event)); if (SND_SOC_DAPM_EVENT_ON(event)) { if (!strncmp(w->name, "MIC0", 4)) snd_soc_update_bits(codec, ES_MIC0_CTRL, ES_MIC0_ON_MASK, 1); else if (!strncmp(w->name, "MIC1", 4)) snd_soc_update_bits(codec, ES_MIC1_CTRL, ES_MIC1_ON_MASK, 1); else if (!strncmp(w->name, "MIC2", 4)) snd_soc_update_bits(codec, ES_MIC2_CTRL, ES_MIC2_ON_MASK, 1); else { pr_err("%s() Invalid Mic Widget ON = %s\n", __func__, w->name); return -EINVAL; } } else { if (!strncmp(w->name, "MIC0", 4)) snd_soc_update_bits(codec, ES_MIC0_CTRL, ES_MIC0_ON_MASK, 0); else if (!strncmp(w->name, "MIC1", 4)) snd_soc_update_bits(codec, ES_MIC1_CTRL, ES_MIC1_ON_MASK, 0); else if (!strncmp(w->name, "MIC2", 4)) snd_soc_update_bits(codec, ES_MIC2_CTRL, ES_MIC2_ON_MASK, 0); else { pr_err("%s() Invalid Mic Widget OFF = %s\n", __func__, w->name); return -EINVAL; } } return 0; }
static int spkdrv_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { dev_dbg(w->codec->dev, "%s called\n", __func__); switch (event) { case SND_SOC_DAPM_PRE_PMU: snd_soc_update_bits(w->codec, COD3022X_32_VOL_EP_SPK, CTVOL_SPK_PGA_MASK, 0x3); snd_soc_update_bits(w->codec, COD3022X_17_PWAUTO_DA, PW_AUTO_DA_MASK | APW_SPK_MASK, (0x1 << PW_AUTO_DA_SHIFT) | (0x1 << APW_SPK_SHIFT)); snd_soc_update_bits(w->codec, COD3022X_37_MIX_DA2, EN_SPK_MIX_DCTL_MASK | EN_SPK_MIX_DCTR_MASK, (0x1 << EN_SPK_MIX_DCTL_SHIFT) | (0x1 << EN_SPK_MIX_DCTR_SHIFT)); break; case SND_SOC_DAPM_PRE_PMD: snd_soc_update_bits(w->codec, COD3022X_32_VOL_EP_SPK, CTVOL_SPK_PGA_MASK, 0x3); snd_soc_update_bits(w->codec, COD3022X_37_MIX_DA2, EN_SPK_MIX_DCTL_MASK | EN_SPK_MIX_DCTR_MASK, 0); snd_soc_update_bits(w->codec, COD3022X_17_PWAUTO_DA, APW_SPK_MASK, 0); break; default: break; } return 0; }
static int da7210_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct snd_soc_codec *codec = dai->codec; if (is_play) { /* Enable Out */ snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10); snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10); } else { /* Volume 7 */ snd_soc_update_bits(codec, DA7210_MIC_L, 0x7, 0x7); snd_soc_update_bits(codec, DA7210_MIC_R, 0x7, 0x7); /* Enable Mic */ snd_soc_update_bits(codec, DA7210_INMIX_L, 0x1F, 0x1); snd_soc_update_bits(codec, DA7210_INMIX_R, 0x1F, 0x1); } return 0; }
static int pmu3_probe(struct snd_soc_codec *codec) { int ret = 0; printk("aml pmu3 codec probe\n"); pmu3_audio_power_init(codec); pmu3_reset(codec); /* power on device */ pmu3_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Enable DAC soft mute by default */ snd_soc_update_bits(codec, PMU3_SOFT_MUTE, 0x7800, 0x7800); /* Enable ZC */ snd_soc_update_bits(codec, PMU3_BLOCK_ENABLE_2, 0x3c0, 0x0); snd_soc_add_codec_controls(codec, pmu3_snd_controls, ARRAY_SIZE(pmu3_snd_controls)); /* ADC high pass filter Hi-fi mode */ snd_soc_update_bits(codec, PMU3_ADC_DAC, 0xc00, 0xc00); snd_soc_write(codec, PMU3_MIXOUT_L, 0xe000); snd_soc_write(codec, PMU3_MIXOUT_R, 0xe000); snd_soc_write(codec, PMU3_MIXIN_L, 0xf000); snd_soc_write(codec, PMU3_MIXIN_R, 0xf000); snd_soc_write(codec, PMU3_PGA_IN, 0x1616); snd_soc_update_bits(codec, PMU3_BLOCK_ENABLE_1, 0xf0c, 0xf0c); snd_soc_update_bits(codec, PMU3_BLOCK_ENABLE_2, 0xf, 0xf); snd_soc_update_bits(codec, PMU3_LINEOUT_HP_DRV, 0x90, 0x90); snd_soc_write(codec, PMU3_DAC_VOLUME_CTL, 0xb9b9); snd_soc_write(codec, PMU3_ADC_VOLUME_CTL, 0x6a6a); return ret; }
static int es_dac_enable(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; pr_debug("%s DAC%d event %d\n", __func__, w->shift, event); switch (event) { case SND_SOC_DAPM_PRE_PMU: snd_soc_update_bits(codec, w->reg, 1<<w->shift, 1<<w->shift); snd_soc_update_bits(codec, ES_DAC_DIG_EN, ES_DIG_CLK_EN_MASK, ES_DIG_CLK_EN); snd_soc_update_bits(codec, ES_DAC_DIG_EN, ES_DAC_CLK_EN_MASK, ES_DAC_CLK_EN); break; case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, w->reg, 1<<w->shift , 0); snd_soc_update_bits(codec, ES_DAC_DIG_EN, ES_DIG_CLK_EN_MASK, 0); snd_soc_update_bits(codec, ES_DAC_DIG_EN, ES_DAC_CLK_EN_MASK, 0); break; } return 0; }
static int alc5632_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { switch (level) { case SND_SOC_BIAS_ON: enable_power_depop(codec); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* everything off except vref/vmid, */ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, ALC5632_PWR_MANAG_ADD1_MASK, ALC5632_PWR_ADD1_MAIN_BIAS); snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_MANAG_ADD2_MASK, ALC5632_PWR_ADD2_VREF); /* "normal" mode: 0 @ 26 */ snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS, ALC5632_PWR_DOWN_CTRL_STATUS_MASK, 0xffff ^ (ALC5632_PWR_VREF_PR3 | ALC5632_PWR_VREF_PR2)); break; case SND_SOC_BIAS_OFF: /* everything off, dac mute, inactive */ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_MANAG_ADD2_MASK, 0); snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3, ALC5632_PWR_MANAG_ADD3_MASK, 0); snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, ALC5632_PWR_MANAG_ADD1_MASK, 0); break; } codec->dapm.bias_level = level; return 0; }
/** * cs4270_probe - ASoC probe function * @pdev: platform device * * This function is called when ASoC has all the pieces it needs to * instantiate a sound driver. */ static int cs4270_probe(struct snd_soc_codec *codec) { struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); int i, ret; /* Tell ASoC what kind of I/O to use to read the registers. ASoC will * then do the I2C transactions itself. */ ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs4270->control_type); if (ret < 0) { dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); return ret; } /* Disable auto-mute. This feature appears to be buggy. In some * situations, auto-mute will not deactivate when it should, so we want * this feature disabled by default. An application (e.g. alsactl) can * re-enabled it by using the controls. */ ret = snd_soc_update_bits(codec, CS4270_MUTE, CS4270_MUTE_AUTO, 0); if (ret < 0) { dev_err(codec->dev, "i2c write failed\n"); return ret; } /* Disable automatic volume control. The hardware enables, and it * causes volume change commands to be delayed, sometimes until after * playback has started. An application (e.g. alsactl) can * re-enabled it by using the controls. */ ret = snd_soc_update_bits(codec, CS4270_TRANS, CS4270_TRANS_SOFT | CS4270_TRANS_ZERO, 0); if (ret < 0) { dev_err(codec->dev, "i2c write failed\n"); return ret; } /* Add the non-DAPM controls */ ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls, ARRAY_SIZE(cs4270_snd_controls)); if (ret < 0) { dev_err(codec->dev, "failed to add controls\n"); return ret; } /* get the power supply regulators */ for (i = 0; i < ARRAY_SIZE(supply_names); i++) cs4270->supplies[i].supply = supply_names[i]; ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), cs4270->supplies); if (ret < 0) return ret; ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); if (ret < 0) goto error_free_regulators; return 0; error_free_regulators: regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); return ret; }
static int wm8523_probe(struct snd_soc_codec *codec) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); int ret, i; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.count = ARRAY_SIZE(wm8523->rate_constraint_list); ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } 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); return ret; } 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; } /* Change some default settings - latch VU and enable ZC */ snd_soc_update_bits(codec, WM8523_DAC_GAINR, WM8523_DACR_VU, WM8523_DACR_VU); snd_soc_update_bits(codec, WM8523_DAC_CTRL3, WM8523_ZC, 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); return 0; err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); err_get: regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); return ret; }
static int ak4641_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; return snd_soc_update_bits(codec, AK4641_DAC, 0x20, mute ? 0x20 : 0); }
static int wm8985_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { int i; struct snd_soc_codec *codec; struct wm8985_priv *wm8985; u16 blen, srate_idx; unsigned int tmp; int srate_best; codec = dai->codec; wm8985 = snd_soc_codec_get_drvdata(codec); wm8985->bclk = snd_soc_params_to_bclk(params); if ((int)wm8985->bclk < 0) return wm8985->bclk; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: blen = 0x0; break; case SNDRV_PCM_FORMAT_S20_3LE: blen = 0x1; break; case SNDRV_PCM_FORMAT_S24_LE: blen = 0x2; break; case SNDRV_PCM_FORMAT_S32_LE: blen = 0x3; break; default: dev_err(dai->dev, "Unsupported word length %u\n", params_format(params)); return -EINVAL; } snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE, WM8985_WL_MASK, blen << WM8985_WL_SHIFT); /* * match to the nearest possible sample rate and rely * on the array index to configure the SR register */ srate_idx = 0; srate_best = abs(srates[0] - params_rate(params)); for (i = 1; i < ARRAY_SIZE(srates); ++i) { if (abs(srates[i] - params_rate(params)) >= srate_best) continue; srate_idx = i; srate_best = abs(srates[i] - params_rate(params)); } dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]); snd_soc_update_bits(codec, WM8985_ADDITIONAL_CONTROL, WM8985_SR_MASK, srate_idx << WM8985_SR_SHIFT); dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8985->bclk); dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8985->sysclk); for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) { if (wm8985->sysclk / params_rate(params) == fs_ratios[i].ratio) break; } if (i == ARRAY_SIZE(fs_ratios)) { dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n", wm8985->sysclk, params_rate(params)); return -EINVAL; } dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio); snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL, WM8985_MCLKDIV_MASK, i << WM8985_MCLKDIV_SHIFT); /* select the appropriate bclk divider */ tmp = (wm8985->sysclk / fs_ratios[i].div) * 10; for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) { if (wm8985->bclk == tmp / bclk_divs[i]) break; } if (i == ARRAY_SIZE(bclk_divs)) { dev_err(dai->dev, "No matching BCLK divider found\n"); return -EINVAL; } dev_dbg(dai->dev, "BCLK div = %d\n", i); snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL, WM8985_BCLKDIV_MASK, i << WM8985_BCLKDIV_SHIFT); return 0; }
static int wm8985_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_codec *codec; u16 format, master, bcp, lrp; codec = dai->codec; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: format = 0x2; break; case SND_SOC_DAIFMT_RIGHT_J: format = 0x0; break; case SND_SOC_DAIFMT_LEFT_J: format = 0x1; break; case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: format = 0x3; break; default: dev_err(dai->dev, "Unknown dai format\n"); return -EINVAL; } snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE, WM8985_FMT_MASK, format << WM8985_FMT_SHIFT); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: master = 1; break; case SND_SOC_DAIFMT_CBS_CFS: master = 0; break; default: dev_err(dai->dev, "Unknown master/slave configuration\n"); return -EINVAL; } snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL, WM8985_MS_MASK, master << WM8985_MS_SHIFT); /* frame inversion is not valid for dsp modes */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_IB_IF: case SND_SOC_DAIFMT_NB_IF: return -EINVAL; default: break; } break; default: break; } bcp = lrp = 0; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_IB_IF: bcp = lrp = 1; break; case SND_SOC_DAIFMT_IB_NF: bcp = 1; break; case SND_SOC_DAIFMT_NB_IF: lrp = 1; break; default: dev_err(dai->dev, "Unknown polarity configuration\n"); return -EINVAL; } snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE, WM8985_LRP_MASK, lrp << WM8985_LRP_SHIFT); snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE, WM8985_BCP_MASK, bcp << WM8985_BCP_SHIFT); return 0; }
static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); unsigned int serictl = 0x00, seroctl = 0x00; bool invert_lrclk; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: /* master, 64-bits per sample, 1 frame per sample */ seroctl |= ADAU1701_SEROCTL_MASTER | ADAU1701_SEROCTL_OBF16 | ADAU1701_SEROCTL_OLF1024; break; case SND_SOC_DAIFMT_CBS_CFS: break; default: return -EINVAL; } /* clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: invert_lrclk = false; break; case SND_SOC_DAIFMT_NB_IF: invert_lrclk = true; break; case SND_SOC_DAIFMT_IB_NF: invert_lrclk = false; serictl |= ADAU1701_SERICTL_INV_BCLK; seroctl |= ADAU1701_SEROCTL_INV_BCLK; break; case SND_SOC_DAIFMT_IB_IF: invert_lrclk = true; serictl |= ADAU1701_SERICTL_INV_BCLK; seroctl |= ADAU1701_SEROCTL_INV_BCLK; break; default: return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: break; case SND_SOC_DAIFMT_LEFT_J: serictl |= ADAU1701_SERICTL_LEFTJ; seroctl |= ADAU1701_SEROCTL_MSB_DEALY0; invert_lrclk = !invert_lrclk; break; case SND_SOC_DAIFMT_RIGHT_J: serictl |= ADAU1701_SERICTL_RIGHTJ_24; seroctl |= ADAU1701_SEROCTL_MSB_DEALY8; invert_lrclk = !invert_lrclk; break; default: return -EINVAL; } if (invert_lrclk) { seroctl |= ADAU1701_SEROCTL_INV_LRCLK; serictl |= ADAU1701_SERICTL_INV_LRCLK; } adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; snd_soc_write(codec, ADAU1701_SERICTL, serictl); snd_soc_update_bits(codec, ADAU1701_SEROCTL, ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); return 0; }
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; /* Disable PLL power */ 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); /* pll is not used in slave mode */ 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 source from MCLK */ 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) { /* PLL source from Bitclk */ 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) { /* PLL source from voice clock */ gbl_clk = ALC5632_PLL_FR_VBCLK; pll_div = codec_slave_pll_div[i].regvalue; break; } } break; default: return -EINVAL; } if (!pll_div) return -EINVAL; /* choose MCLK/BCLK/VBCLK */ snd_soc_write(codec, ALC5632_GPCR2, gbl_clk); /* choose PLL1 clock rate */ snd_soc_write(codec, ALC5632_PLL1_CTRL, pll_div); /* enable PLL1 */ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_ADD2_PLL1, ALC5632_PWR_ADD2_PLL1); /* enable PLL2 */ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, ALC5632_PWR_ADD2_PLL2, ALC5632_PWR_ADD2_PLL2); /* use PLL1 as main SYSCLK */ snd_soc_update_bits(codec, ALC5632_GPCR1, ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1, ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1); return 0; }
static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct si476x_core *core = i2c_mfd_cell_to_core(codec_dai->dev); int err; u16 format = 0; if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) return -EINVAL; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: format |= SI476X_DAUDIO_MODE_DSP_A; break; case SND_SOC_DAIFMT_DSP_B: format |= SI476X_DAUDIO_MODE_DSP_B; break; case SND_SOC_DAIFMT_I2S: format |= SI476X_DAUDIO_MODE_I2S; break; case SND_SOC_DAIFMT_RIGHT_J: format |= SI476X_DAUDIO_MODE_RIGHT_J; break; case SND_SOC_DAIFMT_LEFT_J: format |= SI476X_DAUDIO_MODE_LEFT_J; break; default: return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_IB_NF: format |= SI476X_DAUDIO_MODE_IB; 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: format |= SI476X_DAUDIO_MODE_IB | SI476X_DAUDIO_MODE_IF; break; case SND_SOC_DAIFMT_IB_NF: format |= SI476X_DAUDIO_MODE_IB; break; case SND_SOC_DAIFMT_NB_IF: format |= SI476X_DAUDIO_MODE_IF; break; default: return -EINVAL; } break; default: return -EINVAL; } si476x_core_lock(core); err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK, format); si476x_core_unlock(core); if (err < 0) { dev_err(codec_dai->codec->dev, "Failed to set output format\n"); return err; } return 0; }
static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; u8 iface_reg1 = 0; u8 iface_reg2 = 0; u8 dsp_a_val = 0; dev_dbg(codec->dev, "## %s: fmt = 0x%x\n", __func__, fmt); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER; break; default: dev_alert(codec->dev, "Invalid DAI master/slave interface\n"); return -EINVAL; } /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: break; case SND_SOC_DAIFMT_DSP_A: dsp_a_val = 0x1; case SND_SOC_DAIFMT_DSP_B: /* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: iface_reg2 |= AIC31XX_BCLKINV_MASK; break; case SND_SOC_DAIFMT_IB_NF: break; default: return -EINVAL; } iface_reg1 |= (AIC31XX_DSP_MODE << AIC31XX_IFACE1_DATATYPE_SHIFT); break; case SND_SOC_DAIFMT_RIGHT_J: iface_reg1 |= (AIC31XX_RIGHT_JUSTIFIED_MODE << AIC31XX_IFACE1_DATATYPE_SHIFT); break; case SND_SOC_DAIFMT_LEFT_J: iface_reg1 |= (AIC31XX_LEFT_JUSTIFIED_MODE << AIC31XX_IFACE1_DATATYPE_SHIFT); break; default: dev_err(codec->dev, "Invalid DAI interface format\n"); return -EINVAL; } snd_soc_update_bits(codec, AIC31XX_IFACE1, AIC31XX_IFACE1_DATATYPE_MASK | AIC31XX_IFACE1_MASTER_MASK, iface_reg1); snd_soc_update_bits(codec, AIC31XX_DATA_OFFSET, AIC31XX_DATA_OFFSET_MASK, dsp_a_val); snd_soc_update_bits(codec, AIC31XX_IFACE2, AIC31XX_BCLKINV_MASK, iface_reg2); return 0; }
static int arizona_spk_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); bool manual_ena = false; int val; switch (arizona->type) { case WM5102: switch (arizona->rev) { case 0: break; default: manual_ena = true; break; } default: break; } switch (event) { case SND_SOC_DAPM_PRE_PMU: if (!priv->spk_ena && manual_ena) { snd_soc_write(codec, 0x4f5, 0x25a); priv->spk_ena_pending = true; } break; case SND_SOC_DAPM_POST_PMU: val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3); if (val & ARIZONA_SPK_SHUTDOWN_STS) { dev_crit(arizona->dev, "Speaker not enabled due to temperature\n"); return -EBUSY; } snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1, 1 << w->shift, 1 << w->shift); if (priv->spk_ena_pending) { msleep(75); snd_soc_write(codec, 0x4f5, 0xda); priv->spk_ena_pending = false; priv->spk_ena++; } break; case SND_SOC_DAPM_PRE_PMD: if (manual_ena) { priv->spk_ena--; if (!priv->spk_ena) snd_soc_write(codec, 0x4f5, 0x25a); } snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1, 1 << w->shift, 0); break; case SND_SOC_DAPM_POST_PMD: if (manual_ena) { if (!priv->spk_ena) snd_soc_write(codec, 0x4f5, 0x0da); } break; } 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 sta32x_probe(struct snd_soc_codec *codec) { struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); int i, ret = 0, thermal = 0; sta32x->codec = codec; sta32x->pdata = dev_get_platdata(codec->dev); ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); return ret; } /* Chip documentation explicitly requires that the reset values * of reserved register bits are left untouched. * Write the register default value to cache for reserved registers, * so the write to the these registers are suppressed by the cache * restore code when it skips writes of default registers. */ regcache_cache_only(sta32x->regmap, true); snd_soc_write(codec, STA32X_CONFC, 0xc2); snd_soc_write(codec, STA32X_CONFE, 0xc2); snd_soc_write(codec, STA32X_CONFF, 0x5c); snd_soc_write(codec, STA32X_MMUTE, 0x10); snd_soc_write(codec, STA32X_AUTO1, 0x60); snd_soc_write(codec, STA32X_AUTO3, 0x00); snd_soc_write(codec, STA32X_C3CFG, 0x40); regcache_cache_only(sta32x->regmap, false); /* set thermal warning adjustment and recovery */ if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) thermal |= STA32X_CONFA_TWAB; if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_RECOVERY_ENABLE)) thermal |= STA32X_CONFA_TWRB; snd_soc_update_bits(codec, STA32X_CONFA, STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, thermal); /* select output configuration */ snd_soc_update_bits(codec, STA32X_CONFF, STA32X_CONFF_OCFG_MASK, sta32x->pdata->output_conf << STA32X_CONFF_OCFG_SHIFT); /* channel to output mapping */ snd_soc_update_bits(codec, STA32X_C1CFG, STA32X_CxCFG_OM_MASK, sta32x->pdata->ch1_output_mapping << STA32X_CxCFG_OM_SHIFT); snd_soc_update_bits(codec, STA32X_C2CFG, STA32X_CxCFG_OM_MASK, sta32x->pdata->ch2_output_mapping << STA32X_CxCFG_OM_SHIFT); snd_soc_update_bits(codec, STA32X_C3CFG, STA32X_CxCFG_OM_MASK, sta32x->pdata->ch3_output_mapping << STA32X_CxCFG_OM_SHIFT); /* initialize coefficient shadow RAM with reset values */ for (i = 4; i <= 49; i += 5) sta32x->coef_shadow[i] = 0x400000; for (i = 50; i <= 54; i++) sta32x->coef_shadow[i] = 0x7fffff; sta32x->coef_shadow[55] = 0x5a9df7; sta32x->coef_shadow[56] = 0x7fffff; sta32x->coef_shadow[59] = 0x7fffff; sta32x->coef_shadow[60] = 0x400000; sta32x->coef_shadow[61] = 0x400000; if (sta32x->pdata->needs_esd_watchdog) INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog); sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Bias level configuration will have done an extra enable */ regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); 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 aic31xx_setup_pll(struct snd_soc_codec *codec, struct snd_pcm_hw_params *params) { struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); int bclk_score = snd_soc_params_to_frame_size(params); int mclk_p = aic31xx->sysclk / aic31xx->p_div; int bclk_n = 0; int match = -1; int i; /* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */ snd_soc_update_bits(codec, AIC31XX_CLKMUX, AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL); snd_soc_update_bits(codec, AIC31XX_IFACE2, AIC31XX_BDIVCLK_MASK, AIC31XX_DAC2BCLK); for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) { if (aic31xx_divs[i].rate == params_rate(params) && aic31xx_divs[i].mclk_p == mclk_p) { int s = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) % snd_soc_params_to_frame_size(params); int bn = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) / snd_soc_params_to_frame_size(params); if (s < bclk_score && bn > 0) { match = i; bclk_n = bn; bclk_score = s; } } } if (match == -1) { dev_err(codec->dev, "%s: Sample rate (%u) and format not supported\n", __func__, params_rate(params)); /* See bellow for details how fix this. */ return -EINVAL; } if (bclk_score != 0) { dev_warn(codec->dev, "Can not produce exact bitclock"); /* This is fine if using dsp format, but if using i2s there may be trouble. To fix the issue edit the aic31xx_divs table for your mclk and sample rate. Details can be found from: http://www.ti.com/lit/ds/symlink/tlv320aic3100.pdf Section: 5.6 CLOCK Generation and PLL */ } i = match; /* PLL configuration */ snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK, (aic31xx->p_div << 4) | 0x01); snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j); snd_soc_write(codec, AIC31XX_PLLDMSB, aic31xx_divs[i].pll_d >> 8); snd_soc_write(codec, AIC31XX_PLLDLSB, aic31xx_divs[i].pll_d & 0xff); /* DAC dividers configuration */ snd_soc_update_bits(codec, AIC31XX_NDAC, AIC31XX_PLL_MASK, aic31xx_divs[i].ndac); snd_soc_update_bits(codec, AIC31XX_MDAC, AIC31XX_PLL_MASK, aic31xx_divs[i].mdac); snd_soc_write(codec, AIC31XX_DOSRMSB, aic31xx_divs[i].dosr >> 8); snd_soc_write(codec, AIC31XX_DOSRLSB, aic31xx_divs[i].dosr & 0xff); /* ADC dividers configuration. Write reset value 1 if not used. */ snd_soc_update_bits(codec, AIC31XX_NADC, AIC31XX_PLL_MASK, aic31xx_divs[i].nadc ? aic31xx_divs[i].nadc : 1); snd_soc_update_bits(codec, AIC31XX_MADC, AIC31XX_PLL_MASK, aic31xx_divs[i].madc ? aic31xx_divs[i].madc : 1); snd_soc_write(codec, AIC31XX_AOSR, aic31xx_divs[i].aosr); /* Bit clock divider configuration. */ snd_soc_update_bits(codec, AIC31XX_BCLKN, AIC31XX_PLL_MASK, bclk_n); aic31xx->rate_div_line = i; dev_dbg(codec->dev, "pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n", aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d, aic31xx->p_div, aic31xx_divs[i].dosr, aic31xx_divs[i].ndac, aic31xx_divs[i].mdac, aic31xx_divs[i].aosr, aic31xx_divs[i].nadc, aic31xx_divs[i].madc, bclk_n); return 0; }