Commit cee77be0 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'asoc/topic/rt5677', 'asoc/topic/samsung' and...

Merge remote-tracking branches 'asoc/topic/rt5677', 'asoc/topic/samsung' and 'asoc/topic/sgtl5000' into asoc-next
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ Required properties:
Optional properties:

- realtek,pow-ldo2-gpio : The GPIO that controls the CODEC's POW_LDO2 pin.
- realtek,reset-gpio : The GPIO that controls the CODEC's RESET pin.

- realtek,in1-differential
- realtek,in2-differential
@@ -70,6 +71,7 @@ rt5677 {

	realtek,pow-ldo2-gpio =
		<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
	realtek,reset-gpio = <&gpio TEGRA_GPIO(BB, 3) GPIO_ACTIVE_LOW>;
	realtek,in1-differential = "true";
	realtek,gpio-config = /bits/ 8  <0 0 0 0 0 2>;   /* pull up GPIO6 */
	realtek,jd2-gpio = <3>;  /* Enables Jack detection for GPIO6 */
+135 −8
Original line number Diff line number Diff line
@@ -1060,6 +1060,7 @@ int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec,
	unsigned int asrc5_mask = 0, asrc5_value = 0;
	unsigned int asrc6_mask = 0, asrc6_value = 0;
	unsigned int asrc7_mask = 0, asrc7_value = 0;
	unsigned int asrc8_mask = 0, asrc8_value = 0;

	switch (clk_src) {
	case RT5677_CLK_SEL_SYS:
@@ -1196,10 +1197,108 @@ int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec,
		regmap_update_bits(rt5677->regmap, RT5677_ASRC_7, asrc7_mask,
			asrc7_value);

	/* ASRC 8 */
	if (filter_mask & RT5677_I2S1_SOURCE) {
		asrc8_mask |= RT5677_I2S1_CLK_SEL_MASK;
		asrc8_value = (asrc8_value & ~RT5677_I2S1_CLK_SEL_MASK)
			| ((clk_src - 1) << RT5677_I2S1_CLK_SEL_SFT);
	}

	if (filter_mask & RT5677_I2S2_SOURCE) {
		asrc8_mask |= RT5677_I2S2_CLK_SEL_MASK;
		asrc8_value = (asrc8_value & ~RT5677_I2S2_CLK_SEL_MASK)
			| ((clk_src - 1) << RT5677_I2S2_CLK_SEL_SFT);
	}

	if (filter_mask & RT5677_I2S3_SOURCE) {
		asrc8_mask |= RT5677_I2S3_CLK_SEL_MASK;
		asrc8_value = (asrc8_value & ~RT5677_I2S3_CLK_SEL_MASK)
			| ((clk_src - 1) << RT5677_I2S3_CLK_SEL_SFT);
	}

	if (filter_mask & RT5677_I2S4_SOURCE) {
		asrc8_mask |= RT5677_I2S4_CLK_SEL_MASK;
		asrc8_value = (asrc8_value & ~RT5677_I2S4_CLK_SEL_MASK)
			| ((clk_src - 1) << RT5677_I2S4_CLK_SEL_SFT);
	}

	if (asrc8_mask)
		regmap_update_bits(rt5677->regmap, RT5677_ASRC_8, asrc8_mask,
			asrc8_value);

	return 0;
}
EXPORT_SYMBOL_GPL(rt5677_sel_asrc_clk_src);

static int rt5677_dmic_use_asrc(struct snd_soc_dapm_widget *source,
			 struct snd_soc_dapm_widget *sink)
{
	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
	struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
	unsigned int asrc_setting;

	switch (source->shift) {
	case 11:
		regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
		asrc_setting = (asrc_setting & RT5677_AD_STO1_CLK_SEL_MASK) >>
				RT5677_AD_STO1_CLK_SEL_SFT;
		if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
			asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
			return 1;
		break;

	case 10:
		regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
		asrc_setting = (asrc_setting & RT5677_AD_STO2_CLK_SEL_MASK) >>
				RT5677_AD_STO2_CLK_SEL_SFT;
		if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
			asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
			return 1;
		break;

	case 9:
		regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
		asrc_setting = (asrc_setting & RT5677_AD_STO3_CLK_SEL_MASK) >>
				RT5677_AD_STO3_CLK_SEL_SFT;
		if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
			asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
			return 1;
		break;

	case 8:
		regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
		asrc_setting = (asrc_setting & RT5677_AD_STO4_CLK_SEL_MASK) >>
			RT5677_AD_STO4_CLK_SEL_SFT;
		if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
			asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
			return 1;
		break;

	case 7:
		regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting);
		asrc_setting = (asrc_setting & RT5677_AD_MONOL_CLK_SEL_MASK) >>
			RT5677_AD_MONOL_CLK_SEL_SFT;
		if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
			asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
			return 1;
		break;

	case 6:
		regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting);
		asrc_setting = (asrc_setting & RT5677_AD_MONOR_CLK_SEL_MASK) >>
			RT5677_AD_MONOR_CLK_SEL_SFT;
		if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
			asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
			return 1;
		break;

	default:
		break;
	}

	return 0;
}

/* Digital Mixer */
static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = {
	SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER,
@@ -3057,12 +3156,12 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = {
};

static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
	{ "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC", can_use_asrc },
	{ "Stereo2 DMIC Mux", NULL, "DMIC STO2 ASRC", can_use_asrc },
	{ "Stereo3 DMIC Mux", NULL, "DMIC STO3 ASRC", can_use_asrc },
	{ "Stereo4 DMIC Mux", NULL, "DMIC STO4 ASRC", can_use_asrc },
	{ "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC", can_use_asrc },
	{ "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC", can_use_asrc },
	{ "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC", rt5677_dmic_use_asrc },
	{ "Stereo2 DMIC Mux", NULL, "DMIC STO2 ASRC", rt5677_dmic_use_asrc },
	{ "Stereo3 DMIC Mux", NULL, "DMIC STO3 ASRC", rt5677_dmic_use_asrc },
	{ "Stereo4 DMIC Mux", NULL, "DMIC STO4 ASRC", rt5677_dmic_use_asrc },
	{ "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC", rt5677_dmic_use_asrc },
	{ "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC", rt5677_dmic_use_asrc },
	{ "I2S1", NULL, "I2S1 ASRC", can_use_asrc},
	{ "I2S2", NULL, "I2S2 ASRC", can_use_asrc},
	{ "I2S3", NULL, "I2S3 ASRC", can_use_asrc},
@@ -4667,6 +4766,8 @@ static int rt5677_remove(struct snd_soc_codec *codec)
	regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec);
	if (gpio_is_valid(rt5677->pow_ldo2))
		gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
	if (gpio_is_valid(rt5677->reset_pin))
		gpio_set_value_cansleep(rt5677->reset_pin, 0);

	return 0;
}
@@ -4682,6 +4783,8 @@ static int rt5677_suspend(struct snd_soc_codec *codec)

		if (gpio_is_valid(rt5677->pow_ldo2))
			gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
		if (gpio_is_valid(rt5677->reset_pin))
			gpio_set_value_cansleep(rt5677->reset_pin, 0);
	}

	return 0;
@@ -4692,10 +4795,13 @@ static int rt5677_resume(struct snd_soc_codec *codec)
	struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);

	if (!rt5677->dsp_vad_en) {
		if (gpio_is_valid(rt5677->pow_ldo2)) {
		if (gpio_is_valid(rt5677->pow_ldo2))
			gpio_set_value_cansleep(rt5677->pow_ldo2, 1);
		if (gpio_is_valid(rt5677->reset_pin))
			gpio_set_value_cansleep(rt5677->reset_pin, 1);
		if (gpio_is_valid(rt5677->pow_ldo2) ||
		    gpio_is_valid(rt5677->reset_pin))
			msleep(10);
		}

		regcache_cache_only(rt5677->regmap, false);
		regcache_sync(rt5677->regmap);
@@ -4933,6 +5039,8 @@ static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np)

	rt5677->pow_ldo2 = of_get_named_gpio(np,
					"realtek,pow-ldo2-gpio", 0);
	rt5677->reset_pin = of_get_named_gpio(np,
					"realtek,reset-gpio", 0);

	/*
	 * POW_LDO2 is optional (it may be statically tied on the board).
@@ -4943,6 +5051,9 @@ static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np)
	if (!gpio_is_valid(rt5677->pow_ldo2) &&
			(rt5677->pow_ldo2 != -ENOENT))
		return rt5677->pow_ldo2;
	if (!gpio_is_valid(rt5677->reset_pin) &&
			(rt5677->reset_pin != -ENOENT))
		return rt5677->reset_pin;

	of_property_read_u8_array(np, "realtek,gpio-config",
		rt5677->pdata.gpio_config, RT5677_GPIO_NUM);
@@ -5044,6 +5155,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
		}
	} else {
		rt5677->pow_ldo2 = -EINVAL;
		rt5677->reset_pin = -EINVAL;
	}

	if (gpio_is_valid(rt5677->pow_ldo2)) {
@@ -5055,6 +5167,21 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
				rt5677->pow_ldo2, ret);
			return ret;
		}
	}

	if (gpio_is_valid(rt5677->reset_pin)) {
		ret = devm_gpio_request_one(&i2c->dev, rt5677->reset_pin,
					    GPIOF_OUT_INIT_HIGH,
					    "RT5677 RESET");
		if (ret < 0) {
			dev_err(&i2c->dev, "Failed to request RESET %d: %d\n",
				rt5677->reset_pin, ret);
			return ret;
		}
	}

	if (gpio_is_valid(rt5677->pow_ldo2) ||
	    gpio_is_valid(rt5677->reset_pin)) {
		/* Wait a while until I2C bus becomes available. The datasheet
		 * does not specify the exact we should wait but startup
		 * sequence mentiones at least a few milliseconds.
+15 −0
Original line number Diff line number Diff line
@@ -1446,6 +1446,16 @@
#define RT5677_DSP_OB_4_7_CLK_SEL_MASK		(0xf << 8)
#define RT5677_DSP_OB_4_7_CLK_SEL_SFT		8

/* ASRC Control 8 (0x8a) */
#define RT5677_I2S1_CLK_SEL_MASK		(0xf << 12)
#define RT5677_I2S1_CLK_SEL_SFT			12
#define RT5677_I2S2_CLK_SEL_MASK		(0xf << 8)
#define RT5677_I2S2_CLK_SEL_SFT			8
#define RT5677_I2S3_CLK_SEL_MASK		(0xf << 4)
#define RT5677_I2S3_CLK_SEL_SFT			4
#define RT5677_I2S4_CLK_SEL_MASK		(0xf)
#define RT5677_I2S4_CLK_SEL_SFT			0

/* VAD Function Control 4 (0x9f) */
#define RT5677_VAD_SRC_MASK			(0x7 << 8)
#define RT5677_VAD_SRC_SFT			8
@@ -1744,6 +1754,10 @@ enum {
	RT5677_AD_MONO_R_FILTER = (0x1 << 12),
	RT5677_DSP_OB_0_3_FILTER = (0x1 << 13),
	RT5677_DSP_OB_4_7_FILTER = (0x1 << 14),
	RT5677_I2S1_SOURCE = (0x1 << 15),
	RT5677_I2S2_SOURCE = (0x1 << 16),
	RT5677_I2S3_SOURCE = (0x1 << 17),
	RT5677_I2S4_SOURCE = (0x1 << 18),
};

struct rt5677_priv {
@@ -1762,6 +1776,7 @@ struct rt5677_priv {
	int pll_in;
	int pll_out;
	int pow_ldo2; /* POW_LDO2 pin */
	int reset_pin; /* RESET pin */
	enum rt5677_type type;
#ifdef CONFIG_GPIOLIB
	struct gpio_chip gpio_chip;
+46 −7
Original line number Diff line number Diff line
@@ -1090,6 +1090,19 @@ static bool sgtl5000_readable(struct device *dev, unsigned int reg)
	}
}

/*
 * This precalculated table contains all (vag_val * 100 / lo_calcntrl) results
 * to select an appropriate lo_vol_* in SGTL5000_CHIP_LINE_OUT_VOL
 * The calculatation was done for all possible register values which
 * is the array index and the following formula: 10^((idx−15)/40) * 100
 */
static const u8 vol_quot_table[] = {
	42, 45, 47, 50, 53, 56, 60, 63,
	67, 71, 75, 79, 84, 89, 94, 100,
	106, 112, 119, 126, 133, 141, 150, 158,
	168, 178, 188, 200, 211, 224, 237, 251
};

/*
 * sgtl5000 has 3 internal power supplies:
 * 1. VAG, normally set to vdda/2
@@ -1110,6 +1123,10 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
	u16 ana_pwr;
	u16 lreg_ctrl;
	int vag;
	int lo_vag;
	int vol_quot;
	int lo_vol;
	size_t i;
	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);

	vdda  = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer);
@@ -1197,23 +1214,45 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
			SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT);

	/* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */
	vag = vddio / 2;
	if (vag <= SGTL5000_LINE_OUT_GND_BASE)
		vag = 0;
	else if (vag >= SGTL5000_LINE_OUT_GND_BASE +
	lo_vag = vddio / 2;
	if (lo_vag <= SGTL5000_LINE_OUT_GND_BASE)
		lo_vag = 0;
	else if (lo_vag >= SGTL5000_LINE_OUT_GND_BASE +
		SGTL5000_LINE_OUT_GND_STP * SGTL5000_LINE_OUT_GND_MAX)
		vag = SGTL5000_LINE_OUT_GND_MAX;
		lo_vag = SGTL5000_LINE_OUT_GND_MAX;
	else
		vag = (vag - SGTL5000_LINE_OUT_GND_BASE) /
		lo_vag = (lo_vag - SGTL5000_LINE_OUT_GND_BASE) /
		    SGTL5000_LINE_OUT_GND_STP;

	snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
			SGTL5000_LINE_OUT_CURRENT_MASK |
			SGTL5000_LINE_OUT_GND_MASK,
			vag << SGTL5000_LINE_OUT_GND_SHIFT |
			lo_vag << SGTL5000_LINE_OUT_GND_SHIFT |
			SGTL5000_LINE_OUT_CURRENT_360u <<
				SGTL5000_LINE_OUT_CURRENT_SHIFT);

	/*
	 * Set lineout output level in range (0..31)
	 * the same value is used for right and left channel
	 *
	 * Searching for a suitable index solving this formula:
	 * idx = 40 * log10(vag_val / lo_cagcntrl) + 15
	 */
	vol_quot = (vag * 100) / lo_vag;
	lo_vol = 0;
	for (i = 0; i < ARRAY_SIZE(vol_quot_table); i++) {
		if (vol_quot >= vol_quot_table[i])
			lo_vol = i;
		else
			break;
	}

	snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_VOL,
		SGTL5000_LINE_OUT_VOL_RIGHT_MASK |
		SGTL5000_LINE_OUT_VOL_LEFT_MASK,
		lo_vol << SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT |
		lo_vol << SGTL5000_LINE_OUT_VOL_LEFT_SHIFT);

	return 0;
}

+10 −5
Original line number Diff line number Diff line
@@ -174,7 +174,8 @@ config SND_SOC_SMDK_WM8994_PCM

config SND_SOC_SPEYSIDE
	tristate "Audio support for Wolfson Speyside"
	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C && SPI_MASTER
	depends on SND_SOC_SAMSUNG && I2C && SPI_MASTER
	depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
	select SND_SAMSUNG_I2S
	select SND_SOC_WM8996
	select SND_SOC_WM9081
@@ -183,13 +184,15 @@ config SND_SOC_SPEYSIDE

config SND_SOC_TOBERMORY
	tristate "Audio support for Wolfson Tobermory"
	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT && I2C
	depends on SND_SOC_SAMSUNG && INPUT && I2C
	depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
	select SND_SAMSUNG_I2S
	select SND_SOC_WM8962

config SND_SOC_BELLS
	tristate "Audio support for Wolfson Bells"
	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && MFD_ARIZONA && I2C && SPI_MASTER
	depends on SND_SOC_SAMSUNG && MFD_ARIZONA && I2C && SPI_MASTER
	depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
	select SND_SAMSUNG_I2S
	select SND_SOC_WM5102
	select SND_SOC_WM5110
@@ -199,14 +202,16 @@ config SND_SOC_BELLS

config SND_SOC_LOWLAND
	tristate "Audio support for Wolfson Lowland"
	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C
	depends on SND_SOC_SAMSUNG && I2C
	depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
	select SND_SAMSUNG_I2S
	select SND_SOC_WM5100
	select SND_SOC_WM9081

config SND_SOC_LITTLEMILL
	tristate "Audio support for Wolfson Littlemill"
	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C
	depends on SND_SOC_SAMSUNG && I2C
	depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
	select SND_SAMSUNG_I2S
	select MFD_WM8994
	select SND_SOC_WM8994
Loading