|
@@ -138,6 +138,20 @@ static int aic3x_write(struct snd_soc_codec *codec, unsigned int reg,
|
|
return -EIO;
|
|
return -EIO;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * read from the aic3x register space
|
|
|
|
+ */
|
|
|
|
+static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
|
|
|
|
+ u8 *value)
|
|
|
|
+{
|
|
|
|
+ *value = reg & 0xff;
|
|
|
|
+ if (codec->hw_read(codec->control_data, value, 1) != 1)
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ aic3x_write_reg_cache(codec, reg, *value);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
|
|
#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
|
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
|
.info = snd_soc_info_volsw, \
|
|
.info = snd_soc_info_volsw, \
|
|
@@ -911,6 +925,33 @@ static int aic3x_dapm_event(struct snd_soc_codec *codec, int event)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
|
|
|
|
+{
|
|
|
|
+ u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
|
|
|
|
+ u8 bit = gpio ? 3: 0;
|
|
|
|
+ u8 val = aic3x_read_reg_cache(codec, reg) & ~(1 << bit);
|
|
|
|
+ aic3x_write(codec, reg, val | (!!state << bit));
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(aic3x_set_gpio);
|
|
|
|
+
|
|
|
|
+int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
|
|
|
|
+{
|
|
|
|
+ u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
|
|
|
|
+ u8 val, bit = gpio ? 2: 1;
|
|
|
|
+
|
|
|
|
+ aic3x_read(codec, reg, &val);
|
|
|
|
+ return (val >> bit) & 1;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(aic3x_get_gpio);
|
|
|
|
+
|
|
|
|
+int aic3x_headset_detected(struct snd_soc_codec *codec)
|
|
|
|
+{
|
|
|
|
+ u8 val;
|
|
|
|
+ aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val);
|
|
|
|
+ return (val >> 2) & 1;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(aic3x_headset_detected);
|
|
|
|
+
|
|
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
|
|
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
|
|
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
|
|
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
|
|
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
|
|
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
|
|
@@ -977,6 +1018,7 @@ static int aic3x_resume(struct platform_device *pdev)
|
|
static int aic3x_init(struct snd_soc_device *socdev)
|
|
static int aic3x_init(struct snd_soc_device *socdev)
|
|
{
|
|
{
|
|
struct snd_soc_codec *codec = socdev->codec;
|
|
struct snd_soc_codec *codec = socdev->codec;
|
|
|
|
+ struct aic3x_setup_data *setup = socdev->codec_data;
|
|
int reg, ret = 0;
|
|
int reg, ret = 0;
|
|
|
|
|
|
codec->name = "aic3x";
|
|
codec->name = "aic3x";
|
|
@@ -1067,6 +1109,10 @@ static int aic3x_init(struct snd_soc_device *socdev)
|
|
/* off, with power on */
|
|
/* off, with power on */
|
|
aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
|
|
aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
|
|
|
|
|
|
|
|
+ /* setup GPIO functions */
|
|
|
|
+ aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4);
|
|
|
|
+ aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4);
|
|
|
|
+
|
|
aic3x_add_controls(codec);
|
|
aic3x_add_controls(codec);
|
|
aic3x_add_widgets(codec);
|
|
aic3x_add_widgets(codec);
|
|
ret = snd_soc_register_card(socdev);
|
|
ret = snd_soc_register_card(socdev);
|
|
@@ -1174,6 +1220,12 @@ static struct i2c_client client_template = {
|
|
.name = "AIC3X",
|
|
.name = "AIC3X",
|
|
.driver = &aic3x_i2c_driver,
|
|
.driver = &aic3x_i2c_driver,
|
|
};
|
|
};
|
|
|
|
+
|
|
|
|
+static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
|
|
|
|
+{
|
|
|
|
+ value[0] = i2c_smbus_read_byte_data(client, value[0]);
|
|
|
|
+ return (len == 1);
|
|
|
|
+}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
static int aic3x_probe(struct platform_device *pdev)
|
|
static int aic3x_probe(struct platform_device *pdev)
|
|
@@ -1208,6 +1260,7 @@ static int aic3x_probe(struct platform_device *pdev)
|
|
if (setup->i2c_address) {
|
|
if (setup->i2c_address) {
|
|
normal_i2c[0] = setup->i2c_address;
|
|
normal_i2c[0] = setup->i2c_address;
|
|
codec->hw_write = (hw_write_t) i2c_master_send;
|
|
codec->hw_write = (hw_write_t) i2c_master_send;
|
|
|
|
+ codec->hw_read = (hw_read_t) aic3x_i2c_read;
|
|
ret = i2c_add_driver(&aic3x_i2c_driver);
|
|
ret = i2c_add_driver(&aic3x_i2c_driver);
|
|
if (ret != 0)
|
|
if (ret != 0)
|
|
printk(KERN_ERR "can't add i2c driver");
|
|
printk(KERN_ERR "can't add i2c driver");
|