aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tlv320aic3x.c
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2008-04-30 10:20:52 -0400
committerJaroslav Kysela <perex@perex.cz>2008-05-19 07:19:14 -0400
commit54e7e6167d29a4a98207884b2fbd28b0b3fe91f6 (patch)
tree84ada6a443d563fbb3d0a58a18768aeefe24f33e /sound/soc/codecs/tlv320aic3x.c
parent4f9c16ccfa26691dbb9a5d9e7d5098eb934ccdbe (diff)
[ALSA] soc - tlv320aic3x - add GPIO support
This patch adds support for AIC3x GPIO lines. They can be configured for many possible functions as well as be driven manually. I also introduced i2c read functionality since the GPIO state register has to be read from hardware every time and can not be served from cache. Signed-off-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r--sound/soc/codecs/tlv320aic3x.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 738b3b634d74..957996e0eba2 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -138,6 +138,20 @@ static int aic3x_write(struct snd_soc_codec *codec, unsigned int reg,
138 return -EIO; 138 return -EIO;
139} 139}
140 140
141/*
142 * read from the aic3x register space
143 */
144static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
145 u8 *value)
146{
147 *value = reg & 0xff;
148 if (codec->hw_read(codec->control_data, value, 1) != 1)
149 return -EIO;
150
151 aic3x_write_reg_cache(codec, reg, *value);
152 return 0;
153}
154
141#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ 155#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
142{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 156{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
143 .info = snd_soc_info_volsw, \ 157 .info = snd_soc_info_volsw, \
@@ -911,6 +925,33 @@ static int aic3x_dapm_event(struct snd_soc_codec *codec, int event)
911 return 0; 925 return 0;
912} 926}
913 927
928void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
929{
930 u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
931 u8 bit = gpio ? 3: 0;
932 u8 val = aic3x_read_reg_cache(codec, reg) & ~(1 << bit);
933 aic3x_write(codec, reg, val | (!!state << bit));
934}
935EXPORT_SYMBOL_GPL(aic3x_set_gpio);
936
937int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
938{
939 u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
940 u8 val, bit = gpio ? 2: 1;
941
942 aic3x_read(codec, reg, &val);
943 return (val >> bit) & 1;
944}
945EXPORT_SYMBOL_GPL(aic3x_get_gpio);
946
947int aic3x_headset_detected(struct snd_soc_codec *codec)
948{
949 u8 val;
950 aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val);
951 return (val >> 2) & 1;
952}
953EXPORT_SYMBOL_GPL(aic3x_headset_detected);
954
914#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 955#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
915#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 956#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
916 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) 957 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -977,6 +1018,7 @@ static int aic3x_resume(struct platform_device *pdev)
977static int aic3x_init(struct snd_soc_device *socdev) 1018static int aic3x_init(struct snd_soc_device *socdev)
978{ 1019{
979 struct snd_soc_codec *codec = socdev->codec; 1020 struct snd_soc_codec *codec = socdev->codec;
1021 struct aic3x_setup_data *setup = socdev->codec_data;
980 int reg, ret = 0; 1022 int reg, ret = 0;
981 1023
982 codec->name = "aic3x"; 1024 codec->name = "aic3x";
@@ -1067,6 +1109,10 @@ static int aic3x_init(struct snd_soc_device *socdev)
1067 /* off, with power on */ 1109 /* off, with power on */
1068 aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 1110 aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
1069 1111
1112 /* setup GPIO functions */
1113 aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4);
1114 aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4);
1115
1070 aic3x_add_controls(codec); 1116 aic3x_add_controls(codec);
1071 aic3x_add_widgets(codec); 1117 aic3x_add_widgets(codec);
1072 ret = snd_soc_register_card(socdev); 1118 ret = snd_soc_register_card(socdev);
@@ -1174,6 +1220,12 @@ static struct i2c_client client_template = {
1174 .name = "AIC3X", 1220 .name = "AIC3X",
1175 .driver = &aic3x_i2c_driver, 1221 .driver = &aic3x_i2c_driver,
1176}; 1222};
1223
1224static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
1225{
1226 value[0] = i2c_smbus_read_byte_data(client, value[0]);
1227 return (len == 1);
1228}
1177#endif 1229#endif
1178 1230
1179static int aic3x_probe(struct platform_device *pdev) 1231static int aic3x_probe(struct platform_device *pdev)
@@ -1208,6 +1260,7 @@ static int aic3x_probe(struct platform_device *pdev)
1208 if (setup->i2c_address) { 1260 if (setup->i2c_address) {
1209 normal_i2c[0] = setup->i2c_address; 1261 normal_i2c[0] = setup->i2c_address;
1210 codec->hw_write = (hw_write_t) i2c_master_send; 1262 codec->hw_write = (hw_write_t) i2c_master_send;
1263 codec->hw_read = (hw_read_t) aic3x_i2c_read;
1211 ret = i2c_add_driver(&aic3x_i2c_driver); 1264 ret = i2c_add_driver(&aic3x_i2c_driver);
1212 if (ret != 0) 1265 if (ret != 0)
1213 printk(KERN_ERR "can't add i2c driver"); 1266 printk(KERN_ERR "can't add i2c driver");