Commit 5439e726 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/asoc' into for-linus

parents 238c6d54 2f423577
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -85,6 +85,10 @@
#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
{	.id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
{	.id = snd_soc_dapm_value_mux, .name = wname, .reg = wreg, \
	.shift = wshift, .invert = winvert, .kcontrols = wcontrols, \
	.num_kcontrols = 1}

/* path domain with event - event handler must return 0 for success */
#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
@@ -172,6 +176,12 @@
 	.get = snd_soc_dapm_get_enum_double, \
 	.put = snd_soc_dapm_put_enum_double, \
  	.private_value = (unsigned long)&xenum }
#define SOC_DAPM_VALUE_ENUM(xname, xenum) \
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
	.info = snd_soc_info_value_enum_double, \
	.get = snd_soc_dapm_get_value_enum_double, \
	.put = snd_soc_dapm_put_value_enum_double, \
	.private_value = (unsigned long)&xenum }

/* dapm stream operations */
#define SND_SOC_DAPM_STREAM_NOP			0x0
@@ -214,6 +224,10 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol);
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol);
int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol);
int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol);
int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
	const struct snd_soc_dapm_widget *widget);
int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
@@ -247,6 +261,7 @@ enum snd_soc_dapm_type {
	snd_soc_dapm_input = 0,		/* input pin */
	snd_soc_dapm_output,		/* output pin */
	snd_soc_dapm_mux,			/* selects 1 analog signal from many inputs */
	snd_soc_dapm_value_mux,			/* selects 1 analog signal from many inputs */
	snd_soc_dapm_mixer,			/* mixes several analog signals together */
	snd_soc_dapm_pga,			/* programmable gain/attenuation (volume) */
	snd_soc_dapm_adc,			/* analog to digital converter */
+30 −0
Original line number Diff line number Diff line
@@ -94,11 +94,22 @@
	SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts)
#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \
{	.max = xmax, .texts = xtexts }
#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \
{	.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
	.mask = xmask, .max = xmax, .texts = xtexts, .values = xvalues}
#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \
	SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xmax, xtexts, xvalues)
#define SOC_ENUM(xname, xenum) \
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
	.info = snd_soc_info_enum_double, \
	.get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
	.private_value = (unsigned long)&xenum }
#define SOC_VALUE_ENUM(xname, xenum) \
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
	.info = snd_soc_info_value_enum_double, \
	.get = snd_soc_get_value_enum_double, \
	.put = snd_soc_put_value_enum_double, \
	.private_value = (unsigned long)&xenum }
#define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\
	 xhandler_get, xhandler_put) \
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -200,6 +211,12 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol);
int snd_soc_info_value_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_info *uinfo);
int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol);
int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_info *uinfo);
int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
@@ -406,6 +423,19 @@ struct soc_enum {
	void *dapm;
};

/* semi enumerated kcontrol */
struct soc_value_enum {
	unsigned short reg;
	unsigned short reg2;
	unsigned char shift_l;
	unsigned char shift_r;
	unsigned int max;
	unsigned int mask;
	const char **texts;
	const unsigned int *values;
	void *dapm;
};

#include <sound/soc-dai.h>

#endif
+16 −9
Original line number Diff line number Diff line
@@ -321,10 +321,6 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
{
	int ret;

	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
	if (ret < 0)
		goto err;

	if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
		pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
@@ -339,7 +335,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
		if (IS_ERR(ac97conf_clk)) {
			ret = PTR_ERR(ac97conf_clk);
			ac97conf_clk = NULL;
			goto err_irq;
			goto err_conf;
		}
	}

@@ -347,19 +343,30 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
	if (IS_ERR(ac97_clk)) {
		ret = PTR_ERR(ac97_clk);
		ac97_clk = NULL;
		goto err_irq;
		goto err_clk;
	}

	return clk_enable(ac97_clk);
	ret = clk_enable(ac97_clk);
	if (ret)
		goto err_clk2;

	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
	if (ret < 0)
		goto err_irq;

	return 0;

err_irq:
	GCR |= GCR_ACLINK_OFF;
err_clk2:
	clk_put(ac97_clk);
	ac97_clk = NULL;
err_clk:
	if (ac97conf_clk) {
		clk_put(ac97conf_clk);
		ac97conf_clk = NULL;
	}
	free_irq(IRQ_AC97, NULL);
err:
err_conf:
	return ret;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);
+55 −63
Original line number Diff line number Diff line
@@ -192,39 +192,51 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)

/* Earpiece */
static const char *twl4030_earpiece_texts[] =
		{"Off", "DACL1", "DACL2", "Invalid", "DACR1"};
		{"Off", "DACL1", "DACL2", "DACR1"};

static const struct soc_enum twl4030_earpiece_enum =
	SOC_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1,
static const unsigned int twl4030_earpiece_values[] =
		{0x0, 0x1, 0x2, 0x4};

static const struct soc_value_enum twl4030_earpiece_enum =
	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1, 0x7,
			ARRAY_SIZE(twl4030_earpiece_texts),
			twl4030_earpiece_texts);
			twl4030_earpiece_texts,
			twl4030_earpiece_values);

static const struct snd_kcontrol_new twl4030_dapm_earpiece_control =
SOC_DAPM_ENUM("Route", twl4030_earpiece_enum);
SOC_DAPM_VALUE_ENUM("Route", twl4030_earpiece_enum);

/* PreDrive Left */
static const char *twl4030_predrivel_texts[] =
		{"Off", "DACL1", "DACL2", "Invalid", "DACR2"};
		{"Off", "DACL1", "DACL2", "DACR2"};

static const unsigned int twl4030_predrivel_values[] =
		{0x0, 0x1, 0x2, 0x4};

static const struct soc_enum twl4030_predrivel_enum =
	SOC_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1,
static const struct soc_value_enum twl4030_predrivel_enum =
	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1, 0x7,
			ARRAY_SIZE(twl4030_predrivel_texts),
			twl4030_predrivel_texts);
			twl4030_predrivel_texts,
			twl4030_predrivel_values);

static const struct snd_kcontrol_new twl4030_dapm_predrivel_control =
SOC_DAPM_ENUM("Route", twl4030_predrivel_enum);
SOC_DAPM_VALUE_ENUM("Route", twl4030_predrivel_enum);

/* PreDrive Right */
static const char *twl4030_predriver_texts[] =
		{"Off", "DACR1", "DACR2", "Invalid", "DACL2"};
		{"Off", "DACR1", "DACR2", "DACL2"};

static const struct soc_enum twl4030_predriver_enum =
	SOC_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1,
static const unsigned int twl4030_predriver_values[] =
		{0x0, 0x1, 0x2, 0x4};

static const struct soc_value_enum twl4030_predriver_enum =
	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1, 0x7,
			ARRAY_SIZE(twl4030_predriver_texts),
			twl4030_predriver_texts);
			twl4030_predriver_texts,
			twl4030_predriver_values);

static const struct snd_kcontrol_new twl4030_dapm_predriver_control =
SOC_DAPM_ENUM("Route", twl4030_predriver_enum);
SOC_DAPM_VALUE_ENUM("Route", twl4030_predriver_enum);

/* Headset Left */
static const char *twl4030_hsol_texts[] =
@@ -300,28 +312,35 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);

/* Left analog microphone selection */
static const char *twl4030_analoglmic_texts[] =
		{"Off", "Main mic", "Headset mic", "Invalid", "AUXL",
		 "Invalid", "Invalid", "Invalid", "Carkit mic"};
		{"Off", "Main mic", "Headset mic", "AUXL", "Carkit mic"};

static const unsigned int twl4030_analoglmic_values[] =
		{0x0, 0x1, 0x2, 0x4, 0x8};

static const struct soc_enum twl4030_analoglmic_enum =
	SOC_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0,
static const struct soc_value_enum twl4030_analoglmic_enum =
	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0, 0xf,
			ARRAY_SIZE(twl4030_analoglmic_texts),
			twl4030_analoglmic_texts);
			twl4030_analoglmic_texts,
			twl4030_analoglmic_values);

static const struct snd_kcontrol_new twl4030_dapm_analoglmic_control =
SOC_DAPM_ENUM("Route", twl4030_analoglmic_enum);
SOC_DAPM_VALUE_ENUM("Route", twl4030_analoglmic_enum);

/* Right analog microphone selection */
static const char *twl4030_analogrmic_texts[] =
		{"Off", "Sub mic", "Invalid", "Invalid", "AUXR"};
		{"Off", "Sub mic", "AUXR"};

static const struct soc_enum twl4030_analogrmic_enum =
	SOC_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0,
static const unsigned int twl4030_analogrmic_values[] =
		{0x0, 0x1, 0x4};

static const struct soc_value_enum twl4030_analogrmic_enum =
	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0, 0x5,
			ARRAY_SIZE(twl4030_analogrmic_texts),
			twl4030_analogrmic_texts);
			twl4030_analogrmic_texts,
			twl4030_analogrmic_values);

static const struct snd_kcontrol_new twl4030_dapm_analogrmic_control =
SOC_DAPM_ENUM("Route", twl4030_analogrmic_enum);
SOC_DAPM_VALUE_ENUM("Route", twl4030_analogrmic_enum);

/* TX1 L/R Analog/Digital microphone selection */
static const char *twl4030_micpathtx1_texts[] =
@@ -347,28 +366,6 @@ static const struct soc_enum twl4030_micpathtx2_enum =
static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control =
SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum);

/*
 * This function filters out the non valid mux settings, named as "Invalid"
 * in the enum texts.
 * Just refuse to set an invalid mux mode.
 */
static int twl4030_enum_event(struct snd_soc_dapm_widget *w,
	struct snd_kcontrol *kcontrol, int event)
{
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
	int ret = 0;
	int val;

	val = w->value >> e->shift_l;
	if (!strcmp("Invalid", e->texts[val])) {
		printk(KERN_WARNING "Invalid MUX setting on 0x%02x (%d)\n",
			e->reg, val);
		ret = -1;
	}

	return ret;
}

static int micpath_event(struct snd_soc_dapm_widget *w,
	struct snd_kcontrol *kcontrol, int event)
{
@@ -737,16 +734,13 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {

	/* Output MUX controls */
	/* Earpiece */
	SND_SOC_DAPM_MUX_E("Earpiece Mux", SND_SOC_NOPM, 0, 0,
		&twl4030_dapm_earpiece_control, twl4030_enum_event,
		SND_SOC_DAPM_PRE_REG),
	SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0,
		&twl4030_dapm_earpiece_control),
	/* PreDrivL/R */
	SND_SOC_DAPM_MUX_E("PredriveL Mux", SND_SOC_NOPM, 0, 0,
		&twl4030_dapm_predrivel_control, twl4030_enum_event,
		SND_SOC_DAPM_PRE_REG),
	SND_SOC_DAPM_MUX_E("PredriveR Mux", SND_SOC_NOPM, 0, 0,
		&twl4030_dapm_predriver_control, twl4030_enum_event,
		SND_SOC_DAPM_PRE_REG),
	SND_SOC_DAPM_VALUE_MUX("PredriveL Mux", SND_SOC_NOPM, 0, 0,
		&twl4030_dapm_predrivel_control),
	SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0,
		&twl4030_dapm_predriver_control),
	/* HeadsetL/R */
	SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
		&twl4030_dapm_hsol_control),
@@ -789,12 +783,10 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
		SND_SOC_DAPM_POST_REG),

	/* Analog input muxes with power switch for the physical ADCL/R */
	SND_SOC_DAPM_MUX_E("Analog Left Capture Route",
		TWL4030_REG_AVADC_CTL, 3, 0, &twl4030_dapm_analoglmic_control,
		twl4030_enum_event, SND_SOC_DAPM_PRE_REG),
	SND_SOC_DAPM_MUX_E("Analog Right Capture Route",
		TWL4030_REG_AVADC_CTL, 1, 0, &twl4030_dapm_analogrmic_control,
		twl4030_enum_event, SND_SOC_DAPM_PRE_REG),
	SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route",
		TWL4030_REG_AVADC_CTL, 3, 0, &twl4030_dapm_analoglmic_control),
	SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route",
		TWL4030_REG_AVADC_CTL, 1, 0, &twl4030_dapm_analogrmic_control),

	SND_SOC_DAPM_PGA("Analog Left Amplifier",
		TWL4030_REG_ANAMICL, 4, 0, NULL, 0),
+16 −3
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@
#include "davinci-pcm.h"
#include "davinci-i2s.h"

#define EVM_CODEC_CLOCK 22579200

#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
		SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
@@ -37,6 +36,21 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
	int ret = 0;
	unsigned sysclk;

	/* ASP1 on DM355 EVM is clocked by an external oscillator */
	if (machine_is_davinci_dm355_evm())
		sysclk = 27000000;

	/* ASP0 in DM6446 EVM is clocked by U55, as configured by
	 * board-dm644x-evm.c using GPIOs from U18.  There are six
	 * options; here we "know" we use a 48 KHz sample rate.
	 */
	else if (machine_is_davinci_evm())
		sysclk = 12288000;

	else
		return -EINVAL;

	/* set codec DAI configuration */
	ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
@@ -49,8 +63,7 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
		return ret;

	/* set the codec system clock */
	ret = snd_soc_dai_set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK,
					    SND_SOC_CLOCK_OUT);
	ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
	if (ret < 0)
		return ret;

Loading