Skip to content

Commit

Permalink
Merge remote-tracking branches 'asoc/topic/tas2552', 'asoc/topic/tas5…
Browse files Browse the repository at this point in the history
…720', 'asoc/topic/tegra', 'asoc/topic/tlv320aic32x4' and 'asoc/topic/tlv320aic3x' into asoc-next
  • Loading branch information
Mark Brown committed Sep 1, 2017
6 parents 2e9ac12 + 1bb7cb6 + 86464ef + e4eabf7 + b9045b9 + 19b0fa1 commit 644cbda
Show file tree
Hide file tree
Showing 22 changed files with 330 additions and 45 deletions.
13 changes: 12 additions & 1 deletion Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ Texas Instruments - tlv320aic32x4 Codec module
The tlv320aic32x4 serial control bus communicates through I2C protocols

Required properties:
- compatible: Should be "ti,tlv320aic32x4"
- compatible - "string" - One of:
"ti,tlv320aic32x4" TLV320AIC3204
"ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256
- reg: I2C slave address
- supply-*: Required supply regulators are:
"iov" - digital IO power supply
Expand All @@ -18,6 +20,8 @@ Optional properties:
- reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
- clocks/clock-names: Clock named 'mclk' for the master clock of the codec.
See clock/clock-bindings.txt for information about the detailed format.
- aic32x4-gpio-func - <array of 5 int>
- Types are defined in include/sound/tlv320aic32x4.h


Example:
Expand All @@ -27,4 +31,11 @@ codec: tlv320aic32x4@18 {
reg = <0x18>;
clocks = <&clks 201>;
clock-names = "mclk";
aic32x4-gpio-func= <
0xff /* AIC32X4_MFPX_DEFAULT_VALUE */
0xff /* AIC32X4_MFPX_DEFAULT_VALUE */
0x04 /* MFP3 AIC32X4_MFP3_GPIO_ENABLED */
0xff /* AIC32X4_MFPX_DEFAULT_VALUE */
0x08 /* MFP5 AIC32X4_MFP5_GPIO_INPUT */
>;
};
5 changes: 5 additions & 0 deletions Documentation/devicetree/bindings/sound/tlv320aic3x.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ Optional properties:
3 - MICBIAS output is connected to AVDD,
If this node is not mentioned or if the value is incorrect, then MicBias
is powered down.
- ai3x-ocmv - Output Common-Mode Voltage selection:
0 - 1.35V,
1 - 1.5V,
2 - 1.65V,
3 - 1.8V
- AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the
device as covered in Documentation/devicetree/bindings/regulator/regulator.txt

Expand Down
23 changes: 23 additions & 0 deletions include/sound/tlv320aic32x4.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,30 @@
#define AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K 0x00000001
#define AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K 0x00000002

/* GPIO API */
#define AIC32X4_MFPX_DEFAULT_VALUE 0xff

#define AIC32X4_MFP1_DIN_DISABLED 0
#define AIC32X4_MFP1_DIN_ENABLED 0x2
#define AIC32X4_MFP1_GPIO_IN 0x4

#define AIC32X4_MFP2_GPIO_OUT_LOW 0x0
#define AIC32X4_MFP2_GPIO_OUT_HIGH 0x1

#define AIC32X4_MFP_GPIO_ENABLED 0x4

#define AIC32X4_MFP5_GPIO_DISABLED 0x0
#define AIC32X4_MFP5_GPIO_INPUT 0x8
#define AIC32X4_MFP5_GPIO_OUTPUT 0xc
#define AIC32X4_MFP5_GPIO_OUT_LOW 0x0
#define AIC32X4_MFP5_GPIO_OUT_HIGH 0x1

struct aic32x4_setup_data {
unsigned int gpio_func[5];
};

struct aic32x4_pdata {
struct aic32x4_setup_data *setup;
u32 power_cfg;
u32 micpga_routing;
bool swapdacs;
Expand Down
11 changes: 7 additions & 4 deletions sound/soc/codecs/tas2552.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,17 +192,20 @@ static int tas2552_setup_pll(struct snd_soc_codec *codec,
* pll_clk = (.5 * pll_clkin * J.D) / 2^p
* Need to fill in J and D here based on incoming freq
*/
unsigned int d;
unsigned int d, q, t;
u8 j;
u8 pll_sel = (tas2552->pll_clk_id << 3) & TAS2552_PLL_SRC_MASK;
u8 p = snd_soc_read(codec, TAS2552_PLL_CTRL_1);

p = (p >> 7);

recalc:
j = (pll_clk * 2 * (1 << p)) / pll_clkin;
d = (pll_clk * 2 * (1 << p)) % pll_clkin;
d /= (pll_clkin / 10000);
t = (pll_clk * 2) << p;
j = t / pll_clkin;
d = t % pll_clkin;
t = pll_clkin / 10000;
q = d / (t + 1);
d = q + ((9999 - pll_clkin % 10000) * (d / t - q)) / 10000;

if (d && (pll_clkin < 512000 || pll_clkin > 9200000)) {
if (tas2552->pll_clk_id == TAS2552_PLL_CLKIN_BCLK) {
Expand Down
2 changes: 2 additions & 0 deletions sound/soc/codecs/tlv320aic32x4-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ static int aic32x4_i2c_remove(struct i2c_client *i2c)

static const struct i2c_device_id aic32x4_i2c_id[] = {
{ "tlv320aic32x4", 0 },
{ "tlv320aic32x6", 1 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id);

static const struct of_device_id aic32x4_of_id[] = {
{ .compatible = "ti,tlv320aic32x4", },
{ .compatible = "ti,tlv320aic32x6", },
{ /* senitel */ }
};
MODULE_DEVICE_TABLE(of, aic32x4_of_id);
Expand Down
2 changes: 2 additions & 0 deletions sound/soc/codecs/tlv320aic32x4-spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,14 @@ static int aic32x4_spi_remove(struct spi_device *spi)

static const struct spi_device_id aic32x4_spi_id[] = {
{ "tlv320aic32x4", 0 },
{ "tlv320aic32x6", 1 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(spi, aic32x4_spi_id);

static const struct of_device_id aic32x4_of_id[] = {
{ .compatible = "ti,tlv320aic32x4", },
{ .compatible = "ti,tlv320aic32x6", },
{ /* senitel */ }
};
MODULE_DEVICE_TABLE(of, aic32x4_of_id);
Expand Down
206 changes: 206 additions & 0 deletions sound/soc/codecs/tlv320aic32x4.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,152 @@ struct aic32x4_priv {
struct regulator *supply_iov;
struct regulator *supply_dv;
struct regulator *supply_av;

struct aic32x4_setup_data *setup;
struct device *dev;
};

static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
u8 val;

val = snd_soc_read(codec, AIC32X4_DINCTL);

ucontrol->value.integer.value[0] = (val & 0x01);

return 0;
};

static int aic32x4_set_mfp2_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
u8 val;
u8 gpio_check;

val = snd_soc_read(codec, AIC32X4_DOUTCTL);
gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED);
if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) {
printk(KERN_ERR "%s: MFP2 is not configure as a GPIO output\n",
__func__);
return -EINVAL;
}

if (ucontrol->value.integer.value[0] == (val & AIC32X4_MFP2_GPIO_OUT_HIGH))
return 0;

if (ucontrol->value.integer.value[0])
val |= ucontrol->value.integer.value[0];
else
val &= ~AIC32X4_MFP2_GPIO_OUT_HIGH;

snd_soc_write(codec, AIC32X4_DOUTCTL, val);

return 0;
};

static int aic32x4_get_mfp3_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
u8 val;

val = snd_soc_read(codec, AIC32X4_SCLKCTL);

ucontrol->value.integer.value[0] = (val & 0x01);

return 0;
};

static int aic32x4_set_mfp4_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
u8 val;
u8 gpio_check;

val = snd_soc_read(codec, AIC32X4_MISOCTL);
gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED);
if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) {
printk(KERN_ERR "%s: MFP4 is not configure as a GPIO output\n",
__func__);
return -EINVAL;
}

if (ucontrol->value.integer.value[0] == (val & AIC32X4_MFP5_GPIO_OUT_HIGH))
return 0;

if (ucontrol->value.integer.value[0])
val |= ucontrol->value.integer.value[0];
else
val &= ~AIC32X4_MFP5_GPIO_OUT_HIGH;

snd_soc_write(codec, AIC32X4_MISOCTL, val);

return 0;
};

static int aic32x4_get_mfp5_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
u8 val;

val = snd_soc_read(codec, AIC32X4_GPIOCTL);
ucontrol->value.integer.value[0] = ((val & 0x2) >> 1);

return 0;
};

static int aic32x4_set_mfp5_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
u8 val;
u8 gpio_check;

val = snd_soc_read(codec, AIC32X4_GPIOCTL);
gpio_check = (val & AIC32X4_MFP5_GPIO_OUTPUT);
if (gpio_check != AIC32X4_MFP5_GPIO_OUTPUT) {
printk(KERN_ERR "%s: MFP5 is not configure as a GPIO output\n",
__func__);
return -EINVAL;
}

if (ucontrol->value.integer.value[0] == (val & 0x1))
return 0;

if (ucontrol->value.integer.value[0])
val |= ucontrol->value.integer.value[0];
else
val &= 0xfe;

snd_soc_write(codec, AIC32X4_GPIOCTL, val);

return 0;
};

static const struct snd_kcontrol_new aic32x4_mfp1[] = {
SOC_SINGLE_BOOL_EXT("MFP1 GPIO", 0, aic32x4_get_mfp1_gpio, NULL),
};

static const struct snd_kcontrol_new aic32x4_mfp2[] = {
SOC_SINGLE_BOOL_EXT("MFP2 GPIO", 0, NULL, aic32x4_set_mfp2_gpio),
};

static const struct snd_kcontrol_new aic32x4_mfp3[] = {
SOC_SINGLE_BOOL_EXT("MFP3 GPIO", 0, aic32x4_get_mfp3_gpio, NULL),
};

static const struct snd_kcontrol_new aic32x4_mfp4[] = {
SOC_SINGLE_BOOL_EXT("MFP4 GPIO", 0, NULL, aic32x4_set_mfp4_gpio),
};

static const struct snd_kcontrol_new aic32x4_mfp5[] = {
SOC_SINGLE_BOOL_EXT("MFP5 GPIO", 0, aic32x4_get_mfp5_gpio,
aic32x4_set_mfp5_gpio),
};

/* 0dB min, 0.5dB steps */
Expand Down Expand Up @@ -734,6 +880,52 @@ static struct snd_soc_dai_driver aic32x4_dai = {
.symmetric_rates = 1,
};

static void aic32x4_setup_gpios(struct snd_soc_codec *codec)
{
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);

/* setup GPIO functions */
/* MFP1 */
if (aic32x4->setup->gpio_func[0] != AIC32X4_MFPX_DEFAULT_VALUE) {
snd_soc_write(codec, AIC32X4_DINCTL,
aic32x4->setup->gpio_func[0]);
snd_soc_add_codec_controls(codec, aic32x4_mfp1,
ARRAY_SIZE(aic32x4_mfp1));
}

/* MFP2 */
if (aic32x4->setup->gpio_func[1] != AIC32X4_MFPX_DEFAULT_VALUE) {
snd_soc_write(codec, AIC32X4_DOUTCTL,
aic32x4->setup->gpio_func[1]);
snd_soc_add_codec_controls(codec, aic32x4_mfp2,
ARRAY_SIZE(aic32x4_mfp2));
}

/* MFP3 */
if (aic32x4->setup->gpio_func[2] != AIC32X4_MFPX_DEFAULT_VALUE) {
snd_soc_write(codec, AIC32X4_SCLKCTL,
aic32x4->setup->gpio_func[2]);
snd_soc_add_codec_controls(codec, aic32x4_mfp3,
ARRAY_SIZE(aic32x4_mfp3));
}

/* MFP4 */
if (aic32x4->setup->gpio_func[3] != AIC32X4_MFPX_DEFAULT_VALUE) {
snd_soc_write(codec, AIC32X4_MISOCTL,
aic32x4->setup->gpio_func[3]);
snd_soc_add_codec_controls(codec, aic32x4_mfp4,
ARRAY_SIZE(aic32x4_mfp4));
}

/* MFP5 */
if (aic32x4->setup->gpio_func[4] != AIC32X4_MFPX_DEFAULT_VALUE) {
snd_soc_write(codec, AIC32X4_GPIOCTL,
aic32x4->setup->gpio_func[4]);
snd_soc_add_codec_controls(codec, aic32x4_mfp5,
ARRAY_SIZE(aic32x4_mfp5));
}
}

static int aic32x4_codec_probe(struct snd_soc_codec *codec)
{
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
Expand All @@ -746,6 +938,9 @@ static int aic32x4_codec_probe(struct snd_soc_codec *codec)

snd_soc_write(codec, AIC32X4_RESET, 0x01);

if (aic32x4->setup)
aic32x4_setup_gpios(codec);

/* Power platform configuration */
if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
Expand Down Expand Up @@ -810,10 +1005,20 @@ static const struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4,
struct device_node *np)
{
struct aic32x4_setup_data *aic32x4_setup;

aic32x4_setup = devm_kzalloc(aic32x4->dev, sizeof(*aic32x4_setup),
GFP_KERNEL);
if (!aic32x4_setup)
return -ENOMEM;

aic32x4->swapdacs = false;
aic32x4->micpga_routing = 0;
aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0);

if (of_property_read_u32_array(np, "aic32x4-gpio-func",
aic32x4_setup->gpio_func, 5) >= 0)
aic32x4->setup = aic32x4_setup;
return 0;
}

Expand Down Expand Up @@ -932,6 +1137,7 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap)
if (aic32x4 == NULL)
return -ENOMEM;

aic32x4->dev = dev;
dev_set_drvdata(dev, aic32x4);

if (pdata) {
Expand Down
3 changes: 3 additions & 0 deletions sound/soc/codecs/tlv320aic32x4.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ int aic32x4_remove(struct device *dev);
#define AIC32X4_IFACE4 31
#define AIC32X4_IFACE5 32
#define AIC32X4_IFACE6 33
#define AIC32X4_GPIOCTL 52
#define AIC32X4_DOUTCTL 53
#define AIC32X4_DINCTL 54
#define AIC32X4_MISOCTL 55
#define AIC32X4_SCLKCTL 56
#define AIC32X4_DACSPB 60
#define AIC32X4_ADCSPB 61
#define AIC32X4_DACSETUP 63
Expand Down
Loading

0 comments on commit 644cbda

Please sign in to comment.