aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tlv320aic3x.c
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@slimlogic.co.uk>2010-08-23 07:58:01 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2010-08-23 07:58:01 -0400
commit97e15b1fcf79a60cb146d4123e7c72ac2736e258 (patch)
tree5923cd4d4f2e1945b66a7aab27acf684f8590c47 /sound/soc/codecs/tlv320aic3x.c
parenta8165e0e6f0511d14132423b4bce2d285e890fc8 (diff)
parent38fec7272bc033b75a0eb8976c56c2024d371b7d (diff)
Merge remote branch 'broonie-asoc/for-2.6.37' into for-2.6.37
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r--sound/soc/codecs/tlv320aic3x.c80
1 files changed, 70 insertions, 10 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 0b80e242a66d..efae8b53fd64 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -12,11 +12,11 @@
12 * 12 *
13 * Notes: 13 * Notes:
14 * The AIC3X is a driver for a low power stereo audio 14 * The AIC3X is a driver for a low power stereo audio
15 * codecs aic31, aic32, aic33. 15 * codecs aic31, aic32, aic33, aic3007.
16 * 16 *
17 * It supports full aic33 codec functionality. 17 * It supports full aic33 codec functionality.
18 * The compatibility with aic32, aic31 is as follows: 18 * The compatibility with aic32, aic31 and aic3007 is as follows:
19 * aic32 | aic31 19 * aic32/aic3007 | aic31
20 * --------------------------------------- 20 * ---------------------------------------
21 * MONO_LOUT -> N/A | MONO_LOUT -> N/A 21 * MONO_LOUT -> N/A | MONO_LOUT -> N/A
22 * | IN1L -> LINE1L 22 * | IN1L -> LINE1L
@@ -70,6 +70,10 @@ struct aic3x_priv {
70 unsigned int sysclk; 70 unsigned int sysclk;
71 int master; 71 int master;
72 int gpio_reset; 72 int gpio_reset;
73#define AIC3X_MODEL_3X 0
74#define AIC3X_MODEL_33 1
75#define AIC3X_MODEL_3007 2
76 u16 model;
73}; 77};
74 78
75/* 79/*
@@ -361,6 +365,14 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
361 SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), 365 SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
362}; 366};
363 367
368/*
369 * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps
370 */
371static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0);
372
373static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl =
374 SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv);
375
364/* Left DAC Mux */ 376/* Left DAC Mux */
365static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = 377static const struct snd_kcontrol_new aic3x_left_dac_mux_controls =
366SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); 378SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]);
@@ -589,6 +601,15 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
589 SND_SOC_DAPM_INPUT("LINE2R"), 601 SND_SOC_DAPM_INPUT("LINE2R"),
590}; 602};
591 603
604static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = {
605 /* Class-D outputs */
606 SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0),
607 SND_SOC_DAPM_PGA("Right Class-D Out", CLASSD_CTRL, 2, 0, NULL, 0),
608
609 SND_SOC_DAPM_OUTPUT("SPOP"),
610 SND_SOC_DAPM_OUTPUT("SPOM"),
611};
612
592static const struct snd_soc_dapm_route intercon[] = { 613static const struct snd_soc_dapm_route intercon[] = {
593 /* Left Output */ 614 /* Left Output */
594 {"Left DAC Mux", "DAC_L1", "Left DAC"}, 615 {"Left DAC Mux", "DAC_L1", "Left DAC"},
@@ -759,14 +780,30 @@ static const struct snd_soc_dapm_route intercon[] = {
759 {"GPIO1 dmic modclk", NULL, "DMic Rate 32"}, 780 {"GPIO1 dmic modclk", NULL, "DMic Rate 32"},
760}; 781};
761 782
783static const struct snd_soc_dapm_route intercon_3007[] = {
784 /* Class-D outputs */
785 {"Left Class-D Out", NULL, "Left Line Out"},
786 {"Right Class-D Out", NULL, "Left Line Out"},
787 {"SPOP", NULL, "Left Class-D Out"},
788 {"SPOM", NULL, "Right Class-D Out"},
789};
790
762static int aic3x_add_widgets(struct snd_soc_codec *codec) 791static int aic3x_add_widgets(struct snd_soc_codec *codec)
763{ 792{
793 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
794
764 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, 795 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
765 ARRAY_SIZE(aic3x_dapm_widgets)); 796 ARRAY_SIZE(aic3x_dapm_widgets));
766 797
767 /* set up audio path interconnects */ 798 /* set up audio path interconnects */
768 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 799 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
769 800
801 if (aic3x->model == AIC3X_MODEL_3007) {
802 snd_soc_dapm_new_controls(codec, aic3007_dapm_widgets,
803 ARRAY_SIZE(aic3007_dapm_widgets));
804 snd_soc_dapm_add_routes(codec, intercon_3007, ARRAY_SIZE(intercon_3007));
805 }
806
770 return 0; 807 return 0;
771} 808}
772 809
@@ -1117,6 +1154,7 @@ static struct snd_soc_dai_driver aic3x_dai = {
1117 .rates = AIC3X_RATES, 1154 .rates = AIC3X_RATES,
1118 .formats = AIC3X_FORMATS,}, 1155 .formats = AIC3X_FORMATS,},
1119 .ops = &aic3x_dai_ops, 1156 .ops = &aic3x_dai_ops,
1157 .symmetric_rates = 1,
1120}; 1158};
1121 1159
1122static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state) 1160static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)
@@ -1150,6 +1188,7 @@ static int aic3x_resume(struct snd_soc_codec *codec)
1150 */ 1188 */
1151static int aic3x_init(struct snd_soc_codec *codec) 1189static int aic3x_init(struct snd_soc_codec *codec)
1152{ 1190{
1191 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1153 int reg; 1192 int reg;
1154 1193
1155 aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); 1194 aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
@@ -1218,6 +1257,17 @@ static int aic3x_init(struct snd_soc_codec *codec)
1218 aic3x_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL); 1257 aic3x_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
1219 aic3x_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); 1258 aic3x_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
1220 1259
1260 if (aic3x->model == AIC3X_MODEL_3007) {
1261 /* Class-D speaker driver init; datasheet p. 46 */
1262 aic3x_write(codec, AIC3X_PAGE_SELECT, 0x0D);
1263 aic3x_write(codec, 0xD, 0x0D);
1264 aic3x_write(codec, 0x8, 0x5C);
1265 aic3x_write(codec, 0x8, 0x5D);
1266 aic3x_write(codec, 0x8, 0x5C);
1267 aic3x_write(codec, AIC3X_PAGE_SELECT, 0x00);
1268 aic3x_write(codec, CLASSD_CTRL, 0);
1269 }
1270
1221 /* off, with power on */ 1271 /* off, with power on */
1222 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1272 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1223 1273
@@ -1243,6 +1293,8 @@ static int aic3x_probe(struct snd_soc_codec *codec)
1243 1293
1244 snd_soc_add_controls(codec, aic3x_snd_controls, 1294 snd_soc_add_controls(codec, aic3x_snd_controls,
1245 ARRAY_SIZE(aic3x_snd_controls)); 1295 ARRAY_SIZE(aic3x_snd_controls));
1296 if (aic3x->model == AIC3X_MODEL_3007)
1297 snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
1246 1298
1247 aic3x_add_widgets(codec); 1299 aic3x_add_widgets(codec);
1248 1300
@@ -1274,6 +1326,14 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
1274 * 0x18, 0x19, 0x1A, 0x1B 1326 * 0x18, 0x19, 0x1A, 0x1B
1275 */ 1327 */
1276 1328
1329static const struct i2c_device_id aic3x_i2c_id[] = {
1330 [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 },
1331 [AIC3X_MODEL_33] = { "tlv320aic33", 0 },
1332 [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 },
1333 { }
1334};
1335MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
1336
1277/* 1337/*
1278 * If the i2c layer weren't so broken, we could pass this kind of data 1338 * If the i2c layer weren't so broken, we could pass this kind of data
1279 * around 1339 * around
@@ -1285,6 +1345,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1285 struct aic3x_setup_data *setup = pdata->setup; 1345 struct aic3x_setup_data *setup = pdata->setup;
1286 struct aic3x_priv *aic3x; 1346 struct aic3x_priv *aic3x;
1287 int ret, i; 1347 int ret, i;
1348 const struct i2c_device_id *tbl;
1288 1349
1289 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); 1350 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
1290 if (aic3x == NULL) { 1351 if (aic3x == NULL) {
@@ -1305,6 +1366,12 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1305 gpio_direction_output(aic3x->gpio_reset, 0); 1366 gpio_direction_output(aic3x->gpio_reset, 0);
1306 } 1367 }
1307 1368
1369 for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
1370 if (!strcmp(tbl->name, id->name))
1371 break;
1372 }
1373 aic3x->model = tbl - aic3x_i2c_id;
1374
1308 for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) 1375 for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
1309 aic3x->supplies[i].supply = aic3x_supply_names[i]; 1376 aic3x->supplies[i].supply = aic3x_supply_names[i];
1310 1377
@@ -1359,13 +1426,6 @@ static int aic3x_i2c_remove(struct i2c_client *client)
1359 return 0; 1426 return 0;
1360} 1427}
1361 1428
1362static const struct i2c_device_id aic3x_i2c_id[] = {
1363 { "tlv320aic3x", 0 },
1364 { "tlv320aic33", 0 },
1365 { }
1366};
1367MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
1368
1369/* machine i2c codec control layer */ 1429/* machine i2c codec control layer */
1370static struct i2c_driver aic3x_i2c_driver = { 1430static struct i2c_driver aic3x_i2c_driver = {
1371 .driver = { 1431 .driver = {