static int msm_dai_stub_add_route(struct snd_soc_dai *dai)
{
	struct snd_soc_dapm_route intercon;
	struct snd_soc_dapm_context *dapm;

	if (!dai || !dai->driver) {
		pr_err("%s Invalid params\n", __func__);
		return -EINVAL;
	}
	dapm = snd_soc_component_get_dapm(dai->component);
	memset(&intercon, 0 , sizeof(intercon));
	if (dai->driver->playback.stream_name &&
		dai->driver->playback.aif_name) {
		dev_dbg(dai->dev, "%s add route for widget %s",
			__func__, dai->driver->playback.stream_name);
		intercon.source = dai->driver->playback.aif_name;
		intercon.sink = dai->driver->playback.stream_name;
		dev_dbg(dai->dev, "%s src %s sink %s\n",
			__func__, intercon.source, intercon.sink);
		snd_soc_dapm_add_routes(dapm, &intercon, 1);
	}
	if (dai->driver->capture.stream_name &&
		dai->driver->capture.aif_name) {
		dev_dbg(dai->dev, "%s add route for widget %s",
			__func__, dai->driver->capture.stream_name);
		intercon.sink = dai->driver->capture.aif_name;
		intercon.source = dai->driver->capture.stream_name;
		dev_dbg(dai->dev, "%s src %s sink %s\n",
			__func__, intercon.source, intercon.sink);
		snd_soc_dapm_add_routes(dapm, &intercon, 1);
	}
	return 0;
}
예제 #2
0
파일: adau17x1.c 프로젝트: krzk/linux
int adau17x1_add_widgets(struct snd_soc_component *component)
{
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
	struct adau *adau = snd_soc_component_get_drvdata(component);
	int ret;

	ret = snd_soc_add_component_controls(component, 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, component);
		if (ret) {
			dev_err(component->dev, "Failed to attach firmware: %d\n",
				ret);
			return ret;
		}
	}

	return 0;
}
예제 #3
0
static int sun8i_codec_add_mic2(struct snd_soc_component *cmpnt)
{
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
	struct device *dev = cmpnt->dev;
	int ret;

	ret = snd_soc_add_component_controls(cmpnt,
					     sun8i_codec_mic2_controls,
					     ARRAY_SIZE(sun8i_codec_mic2_controls));
	if (ret) {
		dev_err(dev, "Failed to add MIC2 controls: %d\n", ret);
		return ret;
	}

	ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_mic2_widgets,
					ARRAY_SIZE(sun8i_codec_mic2_widgets));
	if (ret) {
		dev_err(dev, "Failed to add MIC2 DAPM widgets: %d\n", ret);
		return ret;
	}

	ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_mic2_routes,
				      ARRAY_SIZE(sun8i_codec_mic2_routes));
	if (ret) {
		dev_err(dev, "Failed to add MIC2 DAPM routes: %d\n", ret);
		return ret;
	}

	return 0;
}
예제 #4
0
파일: wm8804.c 프로젝트: AlexShiLucky/linux
static int txsrc_put(struct snd_kcontrol *kcontrol,
		     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
	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_component_test_bits(component, e->reg, mask, val)) {
		/* save the current power state of the transmitter */
		txpwr = snd_soc_component_read32(component, WM8804_PWRDN) & 0x4;

		/* power down the transmitter */
		snd_soc_component_update_bits(component, WM8804_PWRDN, 0x4, 0x4);

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

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

	snd_soc_dapm_mutex_unlock(dapm);

	return 0;
}
예제 #5
0
static int sun8i_codec_add_hmic(struct snd_soc_component *cmpnt)
{
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
	struct device *dev = cmpnt->dev;
	int ret;

	ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_hmic_widgets,
					ARRAY_SIZE(sun8i_codec_hmic_widgets));
	if (ret)
		dev_err(dev, "Failed to add Mic3 DAPM widgets: %d\n", ret);

	return ret;
}
예제 #6
0
파일: adau17x1.c 프로젝트: krzk/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_component_get_dapm(dai->component);
	struct adau *adau = snd_soc_component_get_drvdata(dai->component);
	bool is_pll;
	bool was_pll;

	switch (clk_id) {
	case ADAU17X1_CLK_SRC_MCLK:
		is_pll = false;
		break;
	case ADAU17X1_CLK_SRC_PLL_AUTO:
		if (!adau->mclk)
			return -EINVAL;
		/* Fall-through */
	case ADAU17X1_CLK_SRC_PLL:
		is_pll = true;
		break;
	default:
		return -EINVAL;
	}

	switch (adau->clk_src) {
	case ADAU17X1_CLK_SRC_MCLK:
		was_pll = false;
		break;
	case ADAU17X1_CLK_SRC_PLL:
	case ADAU17X1_CLK_SRC_PLL_AUTO:
		was_pll = true;
		break;
	default:
		return -EINVAL;
	}

	adau->sysclk = freq;

	if (is_pll != was_pll) {
		if (is_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;
}
예제 #7
0
파일: cs35l33.c 프로젝트: Lyude/linux
static int cs35l33_set_hg_data(struct snd_soc_component *component,
			       struct cs35l33_pdata *pdata)
{
	struct cs35l33_hg *hg_config = &pdata->hg_config;
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
	struct cs35l33_private *priv = snd_soc_component_get_drvdata(component);

	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;
}
예제 #8
0
파일: adau17x1.c 프로젝트: krzk/linux
int adau17x1_setup_firmware(struct snd_soc_component *component,
	unsigned int rate)
{
	int ret;
	int dspsr, dsp_run;
	struct adau *adau = snd_soc_component_get_drvdata(component);
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);

	/* Check if sample rate is the same as before. If it is there is no
	 * point in performing the below steps as the call to
	 * sigmadsp_setup(...) will return directly when it finds the sample
	 * rate to be the same as before. By checking this we can prevent an
	 * audiable popping noise which occours when toggling DSP_RUN.
	 */
	if (adau->sigmadsp->current_samplerate == rate)
		return 0;

	snd_soc_dapm_mutex_lock(dapm);

	ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr);
	if (ret)
		goto err;

	ret = regmap_read(adau->regmap, ADAU17X1_DSP_RUN, &dsp_run);
	if (ret)
		goto err;

	regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1);
	regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf);
	regmap_write(adau->regmap, ADAU17X1_DSP_RUN, 0);

	ret = sigmadsp_setup(adau->sigmadsp, rate);
	if (ret) {
		regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0);
		goto err;
	}
	regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr);
	regmap_write(adau->regmap, ADAU17X1_DSP_RUN, dsp_run);

err:
	snd_soc_dapm_mutex_unlock(dapm);

	return ret;
}
예제 #9
0
파일: adau17x1.c 프로젝트: krzk/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_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
	struct adau *adau = snd_soc_component_get_drvdata(component);
	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_component_test_bits(component, 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;
}
예제 #10
0
int snd_soc_component_disable_pin(struct snd_soc_component *component,
				  const char *pin)
{
	struct snd_soc_dapm_context *dapm =
		snd_soc_component_get_dapm(component);
	char *full_name;
	int ret;

	if (!component->name_prefix)
		return snd_soc_dapm_disable_pin(dapm, pin);

	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
	if (!full_name)
		return -ENOMEM;

	ret = snd_soc_dapm_disable_pin(dapm, full_name);
	kfree(full_name);

	return ret;
}
예제 #11
0
파일: adau17x1.c 프로젝트: krzk/linux
int adau17x1_add_routes(struct snd_soc_component *component)
{
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
	struct adau *adau = snd_soc_component_get_drvdata(component);
	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));
	}

	if (adau->clk_src != ADAU17X1_CLK_SRC_MCLK)
		snd_soc_dapm_add_routes(dapm, &adau17x1_dapm_pll_route, 1);

	return ret;
}
예제 #12
0
파일: cs35l33.c 프로젝트: Lyude/linux
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_component *component = dai->component;
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
	struct cs35l33_private *priv = snd_soc_component_get_drvdata(component);
	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(component->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(component->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(component->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(component->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(component->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;
}
예제 #13
0
static int uda134x_soc_probe(struct snd_soc_component *component)
{
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
	struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(component);
	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(component);

	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_component_controls(component, uda1340_snd_controls,
					ARRAY_SIZE(uda1340_snd_controls));
	break;
	case UDA134X_UDA1341:
		ret = snd_soc_add_component_controls(component, uda1341_snd_controls,
					ARRAY_SIZE(uda1341_snd_controls));
	break;
	case UDA134X_UDA1345:
		ret = snd_soc_add_component_controls(component, 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;
}