示例#1
0
文件: adau17x1.c 项目: 020gzh/linux
int adau17x1_add_widgets(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct adau *adau = snd_soc_codec_get_drvdata(codec);
	int ret;

	ret = snd_soc_add_codec_controls(codec, adau17x1_controls,
		ARRAY_SIZE(adau17x1_controls));
	if (ret)
		return ret;
	ret = snd_soc_dapm_new_controls(dapm, adau17x1_dapm_widgets,
		ARRAY_SIZE(adau17x1_dapm_widgets));
	if (ret)
		return ret;

	if (adau17x1_has_dsp(adau)) {
		ret = snd_soc_dapm_new_controls(dapm, adau17x1_dsp_dapm_widgets,
			ARRAY_SIZE(adau17x1_dsp_dapm_widgets));
		if (ret)
			return ret;

		if (!adau->sigmadsp)
			return 0;

		ret = sigmadsp_attach(adau->sigmadsp, &codec->component);
		if (ret) {
			dev_err(codec->dev, "Failed to attach firmware: %d\n",
				ret);
			return ret;
		}
	}

	return 0;
}
示例#2
0
static int aic31xx_add_widgets(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
	int ret = 0;

	if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) {
		ret = snd_soc_dapm_new_controls(
			dapm, aic311x_dapm_widgets,
			ARRAY_SIZE(aic311x_dapm_widgets));
		if (ret)
			return ret;

		ret = snd_soc_dapm_add_routes(dapm, aic311x_audio_map,
					      ARRAY_SIZE(aic311x_audio_map));
		if (ret)
			return ret;
	} else {
		ret = snd_soc_dapm_new_controls(
			dapm, aic310x_dapm_widgets,
			ARRAY_SIZE(aic310x_dapm_widgets));
		if (ret)
			return ret;

		ret = snd_soc_dapm_add_routes(dapm, aic310x_audio_map,
					      ARRAY_SIZE(aic310x_audio_map));
		if (ret)
			return ret;
	}

	return 0;
}
示例#3
0
文件: adau17x1.c 项目: 020gzh/linux
static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai,
		int clk_id, unsigned int freq, int dir)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec);
	struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);

	switch (clk_id) {
	case ADAU17X1_CLK_SRC_MCLK:
	case ADAU17X1_CLK_SRC_PLL:
		break;
	default:
		return -EINVAL;
	}

	adau->sysclk = freq;

	if (adau->clk_src != clk_id) {
		if (clk_id == ADAU17X1_CLK_SRC_PLL) {
			snd_soc_dapm_add_routes(dapm,
				&adau17x1_dapm_pll_route, 1);
		} else {
			snd_soc_dapm_del_routes(dapm,
				&adau17x1_dapm_pll_route, 1);
		}
	}

	adau->clk_src = clk_id;

	return 0;
}
示例#4
0
static int txsrc_put(struct snd_kcontrol *kcontrol,
		     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
	unsigned int val = ucontrol->value.enumerated.item[0] << e->shift_l;
	unsigned int mask = 1 << e->shift_l;
	unsigned int txpwr;

	if (val != 0 && val != mask)
		return -EINVAL;

	snd_soc_dapm_mutex_lock(dapm);

	if (snd_soc_test_bits(codec, e->reg, mask, val)) {
		/* save the current power state of the transmitter */
		txpwr = snd_soc_read(codec, WM8804_PWRDN) & 0x4;

		/* power down the transmitter */
		snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x4);

		/* set the tx source */
		snd_soc_update_bits(codec, e->reg, mask, val);

		/* restore the transmitter's configuration */
		snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, txpwr);
	}

	snd_soc_dapm_mutex_unlock(dapm);

	return 0;
}
示例#5
0
文件: adau1761.c 项目: 020gzh/linux
static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct adau *adau = snd_soc_codec_get_drvdata(codec);
	struct adau1761_platform_data *pdata = codec->dev->platform_data;
	enum adau1761_output_mode mode;
	int ret;

	if (pdata)
		mode = pdata->headphone_mode;
	else
		mode = ADAU1761_OUTPUT_MODE_HEADPHONE;

	switch (mode) {
	case ADAU1761_OUTPUT_MODE_LINE:
		break;
	case ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS:
		regmap_update_bits(adau->regmap, ADAU1761_PLAY_MONO_OUTPUT_VOL,
			ADAU1761_PLAY_MONO_OUTPUT_VOL_MODE_HP |
			ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE,
			ADAU1761_PLAY_MONO_OUTPUT_VOL_MODE_HP |
			ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE);
		/* fallthrough */
	case ADAU1761_OUTPUT_MODE_HEADPHONE:
		regmap_update_bits(adau->regmap, ADAU1761_PLAY_HP_RIGHT_VOL,
			ADAU1761_PLAY_HP_RIGHT_VOL_MODE_HP,
			ADAU1761_PLAY_HP_RIGHT_VOL_MODE_HP);
		break;
	default:
		return -EINVAL;
	}

	if (mode == ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS) {
		ret = snd_soc_dapm_new_controls(dapm,
			adau1761_capless_dapm_widgets,
			ARRAY_SIZE(adau1761_capless_dapm_widgets));
		if (ret)
			return ret;
		ret = snd_soc_dapm_add_routes(dapm,
			adau1761_capless_dapm_routes,
			ARRAY_SIZE(adau1761_capless_dapm_routes));
	} else {
		ret = snd_soc_add_codec_controls(codec, adau1761_mono_controls,
			ARRAY_SIZE(adau1761_mono_controls));
		if (ret)
			return ret;
		ret = snd_soc_dapm_new_controls(dapm,
			adau1761_mono_dapm_widgets,
			ARRAY_SIZE(adau1761_mono_dapm_widgets));
		if (ret)
			return ret;
		ret = snd_soc_dapm_add_routes(dapm,
			adau1761_mono_dapm_routes,
			ARRAY_SIZE(adau1761_mono_dapm_routes));
	}

	return ret;
}
示例#6
0
文件: ad193x.c 项目: 020gzh/linux
static int ad193x_codec_probe(struct snd_soc_codec *codec)
{
	struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	int num, ret;

	/* default setting for ad193x */

	/* unmute dac channels */
	regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0);
	/* de-emphasis: 48kHz, powedown dac */
	regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A);
	/* dac in tdm mode */
	regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40);

	/* adc only */
	if (ad193x_has_adc(ad193x)) {
		/* high-pass filter enable */
		regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3);
		/* sata delay=1, adc aux mode */
		regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43);
	}

	/* pll input: mclki/xi */
	regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
	regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04);

	/* adc only */
	if (ad193x_has_adc(ad193x)) {
		/* add adc controls */
		num = ARRAY_SIZE(ad193x_adc_snd_controls);
		ret = snd_soc_add_codec_controls(codec,
						 ad193x_adc_snd_controls,
						 num);
		if (ret)
			return ret;

		/* add adc widgets */
		num = ARRAY_SIZE(ad193x_adc_widgets);
		ret = snd_soc_dapm_new_controls(dapm,
						ad193x_adc_widgets,
						num);
		if (ret)
			return ret;

		/* add adc routes */
		num = ARRAY_SIZE(ad193x_adc_audio_paths);
		ret = snd_soc_dapm_add_routes(dapm,
					      ad193x_adc_audio_paths,
					      num);
		if (ret)
			return ret;
	}

	return 0;
}
示例#7
0
static int ssm2604_codec_probe(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	int ret;

	ret = snd_soc_dapm_new_controls(dapm, ssm2604_dapm_widgets,
			ARRAY_SIZE(ssm2604_dapm_widgets));
	if (ret)
		return ret;

	return snd_soc_dapm_add_routes(dapm, ssm2604_routes,
			ARRAY_SIZE(ssm2604_routes));
}
示例#8
0
文件: wm8997.c 项目: 513855417/linux
static int wm8997_codec_probe(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec);

	arizona_init_spk(codec);

	snd_soc_dapm_disable_pin(dapm, "HAPTICS");

	priv->core.arizona->dapm = dapm;

	return 0;
}
示例#9
0
static int cs53l30_codec_probe(struct snd_soc_codec *codec)
{
	struct cs53l30_private *priv = snd_soc_codec_get_drvdata(codec);
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);

	if (priv->use_sdout2)
		snd_soc_dapm_add_routes(dapm, cs53l30_dapm_routes_sdout2,
					ARRAY_SIZE(cs53l30_dapm_routes_sdout2));
	else
		snd_soc_dapm_add_routes(dapm, cs53l30_dapm_routes_sdout1,
					ARRAY_SIZE(cs53l30_dapm_routes_sdout1));

	return 0;
}
示例#10
0
static int cs35l33_set_hg_data(struct snd_soc_codec *codec,
			       struct cs35l33_pdata *pdata)
{
	struct cs35l33_hg *hg_config = &pdata->hg_config;
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec);

	if (hg_config->enable_hg_algo) {
		regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL,
			CS35L33_MEM_DEPTH_MASK,
			hg_config->mem_depth << CS35L33_MEM_DEPTH_SHIFT);
		regmap_write(priv->regmap, CS35L33_HG_REL_RATE,
			hg_config->release_rate);
		regmap_update_bits(priv->regmap, CS35L33_HG_HEAD,
			CS35L33_HD_RM_MASK,
			hg_config->hd_rm << CS35L33_HD_RM_SHIFT);
		regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL,
			CS35L33_LDO_THLD_MASK,
			hg_config->ldo_thld << CS35L33_LDO_THLD_SHIFT);
		regmap_update_bits(priv->regmap, CS35L33_HG_MEMLDO_CTL,
			CS35L33_LDO_DISABLE_MASK,
			hg_config->ldo_path_disable <<
				CS35L33_LDO_DISABLE_SHIFT);
		regmap_update_bits(priv->regmap, CS35L33_LDO_DEL,
			CS35L33_LDO_ENTRY_DELAY_MASK,
			hg_config->ldo_entry_delay <<
				CS35L33_LDO_ENTRY_DELAY_SHIFT);
		if (hg_config->vp_hg_auto) {
			regmap_update_bits(priv->regmap, CS35L33_HG_EN,
				CS35L33_VP_HG_AUTO_MASK,
				CS35L33_VP_HG_AUTO_MASK);
			snd_soc_dapm_add_routes(dapm, cs35l33_vphg_auto_route,
				ARRAY_SIZE(cs35l33_vphg_auto_route));
		}
		regmap_update_bits(priv->regmap, CS35L33_HG_EN,
			CS35L33_VP_HG_MASK,
			hg_config->vp_hg << CS35L33_VP_HG_SHIFT);
		regmap_update_bits(priv->regmap, CS35L33_LDO_DEL,
			CS35L33_VP_HG_RATE_MASK,
			hg_config->vp_hg_rate << CS35L33_VP_HG_RATE_SHIFT);
		regmap_update_bits(priv->regmap, CS35L33_LDO_DEL,
			CS35L33_VP_HG_VA_MASK,
			hg_config->vp_hg_va << CS35L33_VP_HG_VA_SHIFT);
		regmap_update_bits(priv->regmap, CS35L33_HG_EN,
			CS35L33_CLASS_HG_EN_MASK, CS35L33_CLASS_HG_EN_MASK);
	}
	return 0;
}
示例#11
0
文件: adau17x1.c 项目: 020gzh/linux
/*
 * The MUX register for the Capture and Playback MUXs selects either DSP as
 * source/destination or one of the TDM slots. The TDM slot is selected via
 * snd_soc_dai_set_tdm_slot(), so we only expose whether to go to the DSP or
 * directly to the DAI interface with this control.
 */
static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct adau *adau = snd_soc_codec_get_drvdata(codec);
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
	struct snd_soc_dapm_update update;
	unsigned int stream = e->shift_l;
	unsigned int val, change;
	int reg;

	if (ucontrol->value.enumerated.item[0] >= e->items)
		return -EINVAL;

	switch (ucontrol->value.enumerated.item[0]) {
	case 0:
		val = 0;
		adau->dsp_bypass[stream] = false;
		break;
	default:
		val = (adau->tdm_slot[stream] * 2) + 1;
		adau->dsp_bypass[stream] = true;
		break;
	}

	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
		reg = ADAU17X1_SERIAL_INPUT_ROUTE;
	else
		reg = ADAU17X1_SERIAL_OUTPUT_ROUTE;

	change = snd_soc_test_bits(codec, reg, 0xff, val);
	if (change) {
		update.kcontrol = kcontrol;
		update.mask = 0xff;
		update.reg = reg;
		update.val = val;

		snd_soc_dapm_mux_update_power(dapm, kcontrol,
				ucontrol->value.enumerated.item[0], e, &update);
	}

	return change;
}
示例#12
0
文件: adau17x1.c 项目: 020gzh/linux
int adau17x1_add_routes(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct adau *adau = snd_soc_codec_get_drvdata(codec);
	int ret;

	ret = snd_soc_dapm_add_routes(dapm, adau17x1_dapm_routes,
		ARRAY_SIZE(adau17x1_dapm_routes));
	if (ret)
		return ret;

	if (adau17x1_has_dsp(adau)) {
		ret = snd_soc_dapm_add_routes(dapm, adau17x1_dsp_dapm_routes,
			ARRAY_SIZE(adau17x1_dsp_dapm_routes));
	} else {
		ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes,
			ARRAY_SIZE(adau17x1_no_dsp_dapm_routes));
	}
	return ret;
}
示例#13
0
static int adau1977_codec_probe(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec);
	int ret;

	switch (adau1977->type) {
	case ADAU1977:
		ret = snd_soc_dapm_new_controls(dapm,
			adau1977_micbias_dapm_widgets,
			ARRAY_SIZE(adau1977_micbias_dapm_widgets));
		if (ret < 0)
			return ret;
		break;
	default:
		break;
	}

	return 0;
}
示例#14
0
static int ssm2602_codec_probe(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
	int ret;

	regmap_update_bits(ssm2602->regmap, SSM2602_LOUT1V,
			    LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH);
	regmap_update_bits(ssm2602->regmap, SSM2602_ROUT1V,
			    ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);

	ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls,
			ARRAY_SIZE(ssm2602_snd_controls));
	if (ret)
		return ret;

	ret = snd_soc_dapm_new_controls(dapm, ssm2602_dapm_widgets,
			ARRAY_SIZE(ssm2602_dapm_widgets));
	if (ret)
		return ret;

	return snd_soc_dapm_add_routes(dapm, ssm2602_routes,
			ARRAY_SIZE(ssm2602_routes));
}
示例#15
0
static int cs35l33_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 snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct cs35l33_private *priv = snd_soc_codec_get_drvdata(codec);
	unsigned int reg, bit_pos, i;
	int slot, slot_num;

	if (slot_width != 8)
		return -EINVAL;

	/* scan rx_mask for aud slot */
	slot = ffs(rx_mask) - 1;
	if (slot >= 0) {
		regmap_update_bits(priv->regmap, CS35L33_RX_AUD,
			CS35L33_X_LOC, slot);
		dev_dbg(codec->dev, "Audio starts from slots %d", slot);
	}

	/*
	 * scan tx_mask: vmon(2 slots); imon (2 slots);
	 * vpmon (1 slot) vbstmon (1 slot)
	 */
	slot = ffs(tx_mask) - 1;
	slot_num = 0;

	for (i = 0; i < 2 ; i++) {
		/* disable vpmon/vbstmon: enable later if set in tx_mask */
		regmap_update_bits(priv->regmap, CS35L33_TX_VPMON + i,
			CS35L33_X_STATE | CS35L33_X_LOC, CS35L33_X_STATE
			| CS35L33_X_LOC);
	}

	/* disconnect {vp,vbst}_mon routes: eanble later if set in tx_mask*/
	snd_soc_dapm_del_routes(dapm, cs35l33_vp_vbst_mon_route,
		ARRAY_SIZE(cs35l33_vp_vbst_mon_route));

	while (slot >= 0) {
		/* configure VMON_TX_LOC */
		if (slot_num == 0) {
			regmap_update_bits(priv->regmap, CS35L33_TX_VMON,
				CS35L33_X_STATE | CS35L33_X_LOC, slot);
			dev_dbg(codec->dev, "VMON enabled in slots %d-%d",
				slot, slot + 1);
		}

		/* configure IMON_TX_LOC */
		if (slot_num == 3) {
			regmap_update_bits(priv->regmap, CS35L33_TX_IMON,
				CS35L33_X_STATE | CS35L33_X_LOC, slot);
			dev_dbg(codec->dev, "IMON enabled in slots %d-%d",
				slot, slot + 1);
		}

		/* configure VPMON_TX_LOC */
		if (slot_num == 4) {
			regmap_update_bits(priv->regmap, CS35L33_TX_VPMON,
				CS35L33_X_STATE | CS35L33_X_LOC, slot);
			snd_soc_dapm_add_routes(dapm,
				&cs35l33_vp_vbst_mon_route[0], 2);
			dev_dbg(codec->dev, "VPMON enabled in slots %d", slot);
		}

		/* configure VBSTMON_TX_LOC */
		if (slot_num == 5) {
			regmap_update_bits(priv->regmap, CS35L33_TX_VBSTMON,
				CS35L33_X_STATE | CS35L33_X_LOC, slot);
			snd_soc_dapm_add_routes(dapm,
				&cs35l33_vp_vbst_mon_route[2], 2);
			dev_dbg(codec->dev,
				"VBSTMON enabled in slots %d", slot);
		}

		/* Enable the relevant tx slot */
		reg = CS35L33_TX_EN4 - (slot/8);
		bit_pos = slot - ((slot / 8) * (8));
		regmap_update_bits(priv->regmap, reg,
			1 << bit_pos, 1 << bit_pos);

		tx_mask &= ~(1 << slot);
		slot = ffs(tx_mask) - 1;
		slot_num++;
	}

	return 0;
}
示例#16
0
文件: uda134x.c 项目: 020gzh/linux
static int uda134x_soc_probe(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
	struct uda134x_platform_data *pd = uda134x->pd;
	const struct snd_soc_dapm_widget *widgets;
	unsigned num_widgets;
	int ret;

	printk(KERN_INFO "UDA134X SoC Audio Codec\n");

	switch (pd->model) {
	case UDA134X_UDA1340:
	case UDA134X_UDA1341:
	case UDA134X_UDA1344:
	case UDA134X_UDA1345:
		break;
	default:
		printk(KERN_ERR "UDA134X SoC codec: "
		       "unsupported model %d\n",
			pd->model);
		return -EINVAL;
	}

	if (pd->power)
		pd->power(1);

	uda134x_reset(codec);

	if (pd->model == UDA134X_UDA1341) {
		widgets = uda1341_dapm_widgets;
		num_widgets = ARRAY_SIZE(uda1341_dapm_widgets);
	} else {
		widgets = uda1340_dapm_widgets;
		num_widgets = ARRAY_SIZE(uda1340_dapm_widgets);
	}

	ret = snd_soc_dapm_new_controls(dapm, widgets, num_widgets);
	if (ret) {
		printk(KERN_ERR "%s failed to register dapm controls: %d",
			__func__, ret);
		return ret;
	}

	switch (pd->model) {
	case UDA134X_UDA1340:
	case UDA134X_UDA1344:
		ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls,
					ARRAY_SIZE(uda1340_snd_controls));
	break;
	case UDA134X_UDA1341:
		ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls,
					ARRAY_SIZE(uda1341_snd_controls));
	break;
	case UDA134X_UDA1345:
		ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
					ARRAY_SIZE(uda1345_snd_controls));
	break;
	default:
		printk(KERN_ERR "%s unknown codec type: %d",
			__func__, pd->model);
		return -EINVAL;
	}

	if (ret < 0) {
		printk(KERN_ERR "UDA134X: failed to register controls\n");
		return ret;
	}

	return 0;
}
示例#17
0
文件: ad1836.c 项目: DenisLug/mptcp
static int ad1836_probe(struct snd_soc_codec *codec)
{
	struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	int num_dacs, num_adcs;
	int ret = 0;
	int i;

	num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2;
	num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2;

	/* default setting for ad1836 */
	/* de-emphasis: 48kHz, power-on dac */
	regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300);
	/* unmute dac channels */
	regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0);
	/* high-pass filter enable, power-on adc */
	regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100);
	/* unmute adc channles, adc aux mode */
	regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180);
	/* volume */
	for (i = 1; i <= num_dacs; ++i) {
		regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF);
		regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF);
	}

	if (ad1836->type == AD1836) {
		/* left/right diff:PGA/MUX */
		regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A);
		ret = snd_soc_add_codec_controls(codec, ad1836_controls,
				ARRAY_SIZE(ad1836_controls));
		if (ret)
			return ret;
	} else {
		regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00);
	}

	ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2);
	if (ret)
		return ret;

	ret = snd_soc_add_codec_controls(codec, ad183x_adc_controls, num_adcs);
	if (ret)
		return ret;

	ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs);
	if (ret)
		return ret;

	ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs);
	if (ret)
		return ret;

	ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs);
	if (ret)
		return ret;

	ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs);
	if (ret)
		return ret;

	return ret;
}
示例#18
0
static int cs53l30_set_bias_level(struct snd_soc_codec *codec,
				  enum snd_soc_bias_level level)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct cs53l30_private *priv = snd_soc_codec_get_drvdata(codec);
	unsigned int reg;
	int i, inter_max_check, ret;

	switch (level) {
	case SND_SOC_BIAS_ON:
		break;
	case SND_SOC_BIAS_PREPARE:
		if (dapm->bias_level == SND_SOC_BIAS_STANDBY)
			regmap_update_bits(priv->regmap, CS53L30_PWRCTL,
					   CS53L30_PDN_LP_MASK, 0);
		break;
	case SND_SOC_BIAS_STANDBY:
		if (dapm->bias_level == SND_SOC_BIAS_OFF) {
			ret = clk_prepare_enable(priv->mclk);
			if (ret) {
				dev_err(codec->dev,
					"failed to enable MCLK: %d\n", ret);
				return ret;
			}
			regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,
					   CS53L30_MCLK_DIS_MASK, 0);
			regmap_update_bits(priv->regmap, CS53L30_PWRCTL,
					   CS53L30_PDN_ULP_MASK, 0);
			msleep(50);
		} else {
			regmap_update_bits(priv->regmap, CS53L30_PWRCTL,
					   CS53L30_PDN_ULP_MASK,
					   CS53L30_PDN_ULP);
		}
		break;
	case SND_SOC_BIAS_OFF:
		regmap_update_bits(priv->regmap, CS53L30_INT_MASK,
				   CS53L30_PDN_DONE, 0);
		/*
		 * If digital softramp is set, the amount of time required
		 * for power down increases and depends on the digital
		 * volume setting.
		 */

		/* Set the max possible time if digsft is set */
		regmap_read(priv->regmap, CS53L30_SFT_RAMP, &reg);
		if (reg & CS53L30_DIGSFT_MASK)
			inter_max_check = CS53L30_PDN_POLL_MAX;
		else
			inter_max_check = 10;

		regmap_update_bits(priv->regmap, CS53L30_PWRCTL,
				   CS53L30_PDN_ULP_MASK,
				   CS53L30_PDN_ULP);
		/* PDN_DONE will take a min of 20ms to be set.*/
		msleep(20);
		/* Clr status */
		regmap_read(priv->regmap, CS53L30_IS, &reg);
		for (i = 0; i < inter_max_check; i++) {
			if (inter_max_check < 10) {
				usleep_range(1000, 1100);
				regmap_read(priv->regmap, CS53L30_IS, &reg);
				if (reg & CS53L30_PDN_DONE)
					break;
			} else {
				usleep_range(10000, 10100);
				regmap_read(priv->regmap, CS53L30_IS, &reg);
				if (reg & CS53L30_PDN_DONE)
					break;
			}
		}
		/* PDN_DONE is set. We now can disable the MCLK */
		regmap_update_bits(priv->regmap, CS53L30_INT_MASK,
				   CS53L30_PDN_DONE, CS53L30_PDN_DONE);
		regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,
				   CS53L30_MCLK_DIS_MASK,
				   CS53L30_MCLK_DIS);
		clk_disable_unprepare(priv->mclk);
		break;
	}

	return 0;
}
示例#19
0
文件: adau1761.c 项目: 020gzh/linux
static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct adau1761_platform_data *pdata = codec->dev->platform_data;
	struct adau *adau = snd_soc_codec_get_drvdata(codec);
	enum adau1761_digmic_jackdet_pin_mode mode;
	unsigned int val = 0;
	int ret;

	if (pdata)
		mode = pdata->digmic_jackdetect_pin_mode;
	else
		mode = ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE;

	switch (mode) {
	case ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT:
		switch (pdata->jackdetect_debounce_time) {
		case ADAU1761_JACKDETECT_DEBOUNCE_5MS:
		case ADAU1761_JACKDETECT_DEBOUNCE_10MS:
		case ADAU1761_JACKDETECT_DEBOUNCE_20MS:
		case ADAU1761_JACKDETECT_DEBOUNCE_40MS:
			val |= pdata->jackdetect_debounce_time << 6;
			break;
		default:
			return -EINVAL;
		}
		if (pdata->jackdetect_active_low)
			val |= ADAU1761_DIGMIC_JACKDETECT_ACTIVE_LOW;

		ret = snd_soc_add_codec_controls(codec,
			adau1761_jack_detect_controls,
			ARRAY_SIZE(adau1761_jack_detect_controls));
		if (ret)
			return ret;
	case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: /* fallthrough */
		ret = snd_soc_dapm_add_routes(dapm, adau1761_no_dmic_routes,
			ARRAY_SIZE(adau1761_no_dmic_routes));
		if (ret)
			return ret;
		break;
	case ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC:
		ret = snd_soc_dapm_new_controls(dapm, adau1761_dmic_widgets,
			ARRAY_SIZE(adau1761_dmic_widgets));
		if (ret)
			return ret;

		ret = snd_soc_dapm_add_routes(dapm, adau1761_dmic_routes,
			ARRAY_SIZE(adau1761_dmic_routes));
		if (ret)
			return ret;

		val |= ADAU1761_DIGMIC_JACKDETECT_DIGMIC;
		break;
	default:
		return -EINVAL;
	}

	regmap_write(adau->regmap, ADAU1761_DIGMIC_JACKDETECT, val);

	return 0;
}
示例#20
0
文件: adau1761.c 项目: 020gzh/linux
static int adau1761_codec_probe(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	struct adau1761_platform_data *pdata = codec->dev->platform_data;
	struct adau *adau = snd_soc_codec_get_drvdata(codec);
	int ret;

	ret = adau17x1_add_widgets(codec);
	if (ret < 0)
		return ret;

	if (pdata && pdata->input_differential) {
		regmap_update_bits(adau->regmap, ADAU1761_LEFT_DIFF_INPUT_VOL,
			ADAU1761_DIFF_INPUT_VOL_LDEN,
			ADAU1761_DIFF_INPUT_VOL_LDEN);
		regmap_update_bits(adau->regmap, ADAU1761_RIGHT_DIFF_INPUT_VOL,
			ADAU1761_DIFF_INPUT_VOL_LDEN,
			ADAU1761_DIFF_INPUT_VOL_LDEN);
		ret = snd_soc_add_codec_controls(codec,
			adau1761_differential_mode_controls,
			ARRAY_SIZE(adau1761_differential_mode_controls));
		if (ret)
			return ret;
	} else {
		ret = snd_soc_add_codec_controls(codec,
			adau1761_single_mode_controls,
			ARRAY_SIZE(adau1761_single_mode_controls));
		if (ret)
			return ret;
	}

	switch (adau1761_get_lineout_mode(codec)) {
	case ADAU1761_OUTPUT_MODE_LINE:
		break;
	case ADAU1761_OUTPUT_MODE_HEADPHONE:
		regmap_update_bits(adau->regmap, ADAU1761_PLAY_LINE_LEFT_VOL,
			ADAU1761_PLAY_LINE_LEFT_VOL_MODE_HP,
			ADAU1761_PLAY_LINE_LEFT_VOL_MODE_HP);
		regmap_update_bits(adau->regmap, ADAU1761_PLAY_LINE_RIGHT_VOL,
			ADAU1761_PLAY_LINE_RIGHT_VOL_MODE_HP,
			ADAU1761_PLAY_LINE_RIGHT_VOL_MODE_HP);
		break;
	default:
		return -EINVAL;
	}

	ret = adau1761_setup_headphone_mode(codec);
	if (ret)
		return ret;

	ret = adau1761_setup_digmic_jackdetect(codec);
	if (ret)
		return ret;

	if (adau->type == ADAU1761) {
		ret = snd_soc_dapm_new_controls(dapm, adau1761_dapm_widgets,
			ARRAY_SIZE(adau1761_dapm_widgets));
		if (ret)
			return ret;

		ret = snd_soc_dapm_add_routes(dapm, adau1761_dapm_routes,
			ARRAY_SIZE(adau1761_dapm_routes));
		if (ret)
			return ret;
	}

	ret = adau17x1_add_routes(codec);
	if (ret < 0)
		return ret;

	return 0;
}