aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/Kconfig1
-rw-r--r--sound/soc/codecs/twl6040.c425
-rw-r--r--sound/soc/codecs/twl6040.h118
-rw-r--r--sound/soc/omap/sdp4430.c2
4 files changed, 90 insertions, 456 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0002220bbc3..922f59f9b82 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -240,6 +240,7 @@ config SND_SOC_TWL4030
240 tristate 240 tristate
241 241
242config SND_SOC_TWL6040 242config SND_SOC_TWL6040
243 select TWL6040_CORE
243 tristate 244 tristate
244 245
245config SND_SOC_UDA134X 246config SND_SOC_UDA134X
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index ade6616bb79..a20e293b27b 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -24,11 +24,10 @@
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/delay.h> 25#include <linux/delay.h>
26#include <linux/pm.h> 26#include <linux/pm.h>
27#include <linux/i2c.h>
28#include <linux/gpio.h>
29#include <linux/platform_device.h> 27#include <linux/platform_device.h>
30#include <linux/slab.h> 28#include <linux/slab.h>
31#include <linux/i2c/twl.h> 29#include <linux/i2c/twl.h>
30#include <linux/mfd/twl6040.h>
32 31
33#include <sound/core.h> 32#include <sound/core.h>
34#include <sound/pcm.h> 33#include <sound/pcm.h>
@@ -77,14 +76,12 @@ struct twl6040_jack_data {
77 76
78/* codec private data */ 77/* codec private data */
79struct twl6040_data { 78struct twl6040_data {
80 int audpwron;
81 int naudint;
82 int codec_powered; 79 int codec_powered;
83 int pll; 80 int pll;
84 int non_lp; 81 int non_lp;
82 unsigned int clk_in;
85 unsigned int sysclk; 83 unsigned int sysclk;
86 struct snd_pcm_hw_constraint_list *sysclk_constraints; 84 struct snd_pcm_hw_constraint_list *sysclk_constraints;
87 struct completion ready;
88 struct twl6040_jack_data hs_jack; 85 struct twl6040_jack_data hs_jack;
89 struct snd_soc_codec *codec; 86 struct snd_soc_codec *codec;
90 struct workqueue_struct *workqueue; 87 struct workqueue_struct *workqueue;
@@ -239,12 +236,13 @@ static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
239static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, 236static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
240 unsigned int reg) 237 unsigned int reg)
241{ 238{
239 struct twl6040 *twl6040 = codec->control_data;
242 u8 value; 240 u8 value;
243 241
244 if (reg >= TWL6040_CACHEREGNUM) 242 if (reg >= TWL6040_CACHEREGNUM)
245 return -EIO; 243 return -EIO;
246 244
247 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &value, reg); 245 value = twl6040_reg_read(twl6040, reg);
248 twl6040_write_reg_cache(codec, reg, value); 246 twl6040_write_reg_cache(codec, reg, value);
249 247
250 return value; 248 return value;
@@ -256,11 +254,13 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
256static int twl6040_write(struct snd_soc_codec *codec, 254static int twl6040_write(struct snd_soc_codec *codec,
257 unsigned int reg, unsigned int value) 255 unsigned int reg, unsigned int value)
258{ 256{
257 struct twl6040 *twl6040 = codec->control_data;
258
259 if (reg >= TWL6040_CACHEREGNUM) 259 if (reg >= TWL6040_CACHEREGNUM)
260 return -EIO; 260 return -EIO;
261 261
262 twl6040_write_reg_cache(codec, reg, value); 262 twl6040_write_reg_cache(codec, reg, value);
263 return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, value, reg); 263 return twl6040_reg_write(twl6040, reg, value);
264} 264}
265 265
266static void twl6040_init_vio_regs(struct snd_soc_codec *codec) 266static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
@@ -268,15 +268,21 @@ static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
268 u8 *cache = codec->reg_cache; 268 u8 *cache = codec->reg_cache;
269 int reg, i; 269 int reg, i;
270 270
271 /* allow registers to be accessed by i2c */
272 twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]);
273
274 for (i = 0; i < TWL6040_VIOREGNUM; i++) { 271 for (i = 0; i < TWL6040_VIOREGNUM; i++) {
275 reg = twl6040_vio_reg[i]; 272 reg = twl6040_vio_reg[i];
276 /* skip read-only registers (ASICID, ASICREV, STATUS) */ 273 /*
274 * skip read-only registers (ASICID, ASICREV, STATUS)
275 * and registers shared among MFD children
276 */
277 switch (reg) { 277 switch (reg) {
278 case TWL6040_REG_ASICID: 278 case TWL6040_REG_ASICID:
279 case TWL6040_REG_ASICREV: 279 case TWL6040_REG_ASICREV:
280 case TWL6040_REG_INTID:
281 case TWL6040_REG_INTMR:
282 case TWL6040_REG_NCPCTL:
283 case TWL6040_REG_LDOCTL:
284 case TWL6040_REG_GPOCTL:
285 case TWL6040_REG_ACCCTL:
280 case TWL6040_REG_STATUS: 286 case TWL6040_REG_STATUS:
281 continue; 287 continue;
282 default: 288 default:
@@ -293,6 +299,20 @@ static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
293 299
294 for (i = 0; i < TWL6040_VDDREGNUM; i++) { 300 for (i = 0; i < TWL6040_VDDREGNUM; i++) {
295 reg = twl6040_vdd_reg[i]; 301 reg = twl6040_vdd_reg[i];
302 /* skip vibra and PLL registers */
303 switch (reg) {
304 case TWL6040_REG_VIBCTLL:
305 case TWL6040_REG_VIBDATL:
306 case TWL6040_REG_VIBCTLR:
307 case TWL6040_REG_VIBDATR:
308 case TWL6040_REG_HPPLLCTL:
309 case TWL6040_REG_LPPLLCTL:
310 case TWL6040_REG_LPPLLDIV:
311 continue;
312 default:
313 break;
314 }
315
296 twl6040_write(codec, reg, cache[reg]); 316 twl6040_write(codec, reg, cache[reg]);
297 } 317 }
298} 318}
@@ -596,88 +616,6 @@ static int pga_event(struct snd_soc_dapm_widget *w,
596 return 0; 616 return 0;
597} 617}
598 618
599/* twl6040 codec manual power-up sequence */
600static void twl6040_power_up(struct snd_soc_codec *codec)
601{
602 u8 ncpctl, ldoctl, lppllctl, accctl;
603
604 ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
605 ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
606 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
607 accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
608
609 /* enable reference system */
610 ldoctl |= TWL6040_REFENA;
611 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
612 msleep(10);
613 /* enable internal oscillator */
614 ldoctl |= TWL6040_OSCENA;
615 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
616 udelay(10);
617 /* enable high-side ldo */
618 ldoctl |= TWL6040_HSLDOENA;
619 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
620 udelay(244);
621 /* enable negative charge pump */
622 ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
623 twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
624 udelay(488);
625 /* enable low-side ldo */
626 ldoctl |= TWL6040_LSLDOENA;
627 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
628 udelay(244);
629 /* enable low-power pll */
630 lppllctl |= TWL6040_LPLLENA;
631 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
632 /* reset state machine */
633 accctl |= TWL6040_RESETSPLIT;
634 twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
635 mdelay(5);
636 accctl &= ~TWL6040_RESETSPLIT;
637 twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
638 /* disable internal oscillator */
639 ldoctl &= ~TWL6040_OSCENA;
640 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
641}
642
643/* twl6040 codec manual power-down sequence */
644static void twl6040_power_down(struct snd_soc_codec *codec)
645{
646 u8 ncpctl, ldoctl, lppllctl, accctl;
647
648 ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
649 ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
650 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
651 accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
652
653 /* enable internal oscillator */
654 ldoctl |= TWL6040_OSCENA;
655 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
656 udelay(10);
657 /* disable low-power pll */
658 lppllctl &= ~TWL6040_LPLLENA;
659 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
660 /* disable low-side ldo */
661 ldoctl &= ~TWL6040_LSLDOENA;
662 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
663 udelay(244);
664 /* disable negative charge pump */
665 ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN);
666 twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
667 udelay(488);
668 /* disable high-side ldo */
669 ldoctl &= ~TWL6040_HSLDOENA;
670 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
671 udelay(244);
672 /* disable internal oscillator */
673 ldoctl &= ~TWL6040_OSCENA;
674 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
675 /* disable reference system */
676 ldoctl &= ~TWL6040_REFENA;
677 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
678 msleep(10);
679}
680
681/* set headset dac and driver power mode */ 619/* set headset dac and driver power mode */
682static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) 620static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
683{ 621{
@@ -766,33 +704,19 @@ static void twl6040_accessory_work(struct work_struct *work)
766} 704}
767 705
768/* audio interrupt handler */ 706/* audio interrupt handler */
769static irqreturn_t twl6040_naudint_handler(int irq, void *data) 707static irqreturn_t twl6040_audio_handler(int irq, void *data)
770{ 708{
771 struct snd_soc_codec *codec = data; 709 struct snd_soc_codec *codec = data;
710 struct twl6040 *twl6040 = codec->control_data;
772 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 711 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
773 u8 intid; 712 u8 intid;
774 713
775 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID); 714 intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
776
777 if (intid & TWL6040_THINT)
778 dev_alert(codec->dev, "die temp over-limit detection\n");
779 715
780 if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT)) 716 if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
781 queue_delayed_work(priv->workqueue, &priv->delayed_work, 717 queue_delayed_work(priv->workqueue, &priv->delayed_work,
782 msecs_to_jiffies(200)); 718 msecs_to_jiffies(200));
783 719
784 if (intid & TWL6040_HOOKINT)
785 dev_info(codec->dev, "hook detection\n");
786
787 if (intid & TWL6040_HFINT)
788 dev_alert(codec->dev, "hf drivers over current detection\n");
789
790 if (intid & TWL6040_VIBINT)
791 dev_alert(codec->dev, "vib drivers over current detection\n");
792
793 if (intid & TWL6040_READYINT)
794 complete(&priv->ready);
795
796 return IRQ_HANDLED; 720 return IRQ_HANDLED;
797} 721}
798 722
@@ -1231,36 +1155,11 @@ static int twl6040_add_widgets(struct snd_soc_codec *codec)
1231 return 0; 1155 return 0;
1232} 1156}
1233 1157
1234static int twl6040_power_up_completion(struct snd_soc_codec *codec,
1235 int naudint)
1236{
1237 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1238 int time_left;
1239 u8 intid;
1240
1241 time_left = wait_for_completion_timeout(&priv->ready,
1242 msecs_to_jiffies(144));
1243
1244 if (!time_left) {
1245 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid,
1246 TWL6040_REG_INTID);
1247 if (!(intid & TWL6040_READYINT)) {
1248 dev_err(codec->dev, "timeout waiting for READYINT\n");
1249 return -ETIMEDOUT;
1250 }
1251 }
1252
1253 priv->codec_powered = 1;
1254
1255 return 0;
1256}
1257
1258static int twl6040_set_bias_level(struct snd_soc_codec *codec, 1158static int twl6040_set_bias_level(struct snd_soc_codec *codec,
1259 enum snd_soc_bias_level level) 1159 enum snd_soc_bias_level level)
1260{ 1160{
1161 struct twl6040 *twl6040 = codec->control_data;
1261 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1162 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1262 int audpwron = priv->audpwron;
1263 int naudint = priv->naudint;
1264 int ret; 1163 int ret;
1265 1164
1266 switch (level) { 1165 switch (level) {
@@ -1272,62 +1171,30 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
1272 if (priv->codec_powered) 1171 if (priv->codec_powered)
1273 break; 1172 break;
1274 1173
1275 if (gpio_is_valid(audpwron)) { 1174 ret = twl6040_power(twl6040, 1);
1276 /* use AUDPWRON line */ 1175 if (ret)
1277 gpio_set_value(audpwron, 1); 1176 return ret;
1278
1279 /* wait for power-up completion */
1280 ret = twl6040_power_up_completion(codec, naudint);
1281 if (ret)
1282 return ret;
1283 1177
1284 /* sync registers updated during power-up sequence */ 1178 priv->codec_powered = 1;
1285 twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
1286 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
1287 twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL);
1288 } else {
1289 /* use manual power-up sequence */
1290 twl6040_power_up(codec);
1291 priv->codec_powered = 1;
1292 }
1293 1179
1294 /* initialize vdd/vss registers with reg_cache */ 1180 /* initialize vdd/vss registers with reg_cache */
1295 twl6040_init_vdd_regs(codec); 1181 twl6040_init_vdd_regs(codec);
1296 1182
1297 /* Set external boost GPO */ 1183 /* Set external boost GPO */
1298 twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); 1184 twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
1299
1300 /* Set initial minimal gain values */
1301 twl6040_write(codec, TWL6040_REG_HSGAIN, 0xFF);
1302 twl6040_write(codec, TWL6040_REG_EARCTL, 0x1E);
1303 twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1D);
1304 twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1D);
1305 break; 1185 break;
1306 case SND_SOC_BIAS_OFF: 1186 case SND_SOC_BIAS_OFF:
1307 if (!priv->codec_powered) 1187 if (!priv->codec_powered)
1308 break; 1188 break;
1309 1189
1310 if (gpio_is_valid(audpwron)) { 1190 twl6040_power(twl6040, 0);
1311 /* use AUDPWRON line */
1312 gpio_set_value(audpwron, 0);
1313
1314 /* power-down sequence latency */
1315 udelay(500);
1316
1317 /* sync registers updated during power-down sequence */
1318 twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
1319 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
1320 twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL,
1321 0x00);
1322 } else {
1323 /* use manual power-down sequence */
1324 twl6040_power_down(codec);
1325 }
1326
1327 priv->codec_powered = 0; 1191 priv->codec_powered = 0;
1328 break; 1192 break;
1329 } 1193 }
1330 1194
1195 /* get PLL and sysclk after power transition */
1196 priv->pll = twl6040_get_pll(twl6040);
1197 priv->sysclk = twl6040_get_sysclk(twl6040);
1331 codec->dapm.bias_level = level; 1198 codec->dapm.bias_level = level;
1332 1199
1333 return 0; 1200 return 0;
@@ -1374,39 +1241,40 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
1374{ 1241{
1375 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1242 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1376 struct snd_soc_codec *codec = rtd->codec; 1243 struct snd_soc_codec *codec = rtd->codec;
1244 struct twl6040 *twl6040 = codec->control_data;
1377 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1245 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1378 u8 lppllctl; 1246 unsigned int sysclk;
1379 int rate; 1247 int rate, ret;
1380 1248
1381 /* nothing to do for high-perf pll, it supports only 48 kHz */ 1249 /* nothing to do for high-perf pll, it supports only 48 kHz */
1382 if (priv->pll == TWL6040_HPPLL_ID) 1250 if (priv->pll == TWL6040_HPPLL_ID)
1383 return 0; 1251 return 0;
1384 1252
1385 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
1386
1387 rate = params_rate(params); 1253 rate = params_rate(params);
1388 switch (rate) { 1254 switch (rate) {
1389 case 11250: 1255 case 11250:
1390 case 22500: 1256 case 22500:
1391 case 44100: 1257 case 44100:
1392 case 88200: 1258 case 88200:
1393 lppllctl |= TWL6040_LPLLFIN; 1259 sysclk = 17640000;
1394 priv->sysclk = 17640000;
1395 break; 1260 break;
1396 case 8000: 1261 case 8000:
1397 case 16000: 1262 case 16000:
1398 case 32000: 1263 case 32000:
1399 case 48000: 1264 case 48000:
1400 case 96000: 1265 case 96000:
1401 lppllctl &= ~TWL6040_LPLLFIN; 1266 sysclk = 19200000;
1402 priv->sysclk = 19200000;
1403 break; 1267 break;
1404 default: 1268 default:
1405 dev_err(codec->dev, "unsupported rate %d\n", rate); 1269 dev_err(codec->dev, "unsupported rate %d\n", rate);
1406 return -EINVAL; 1270 return -EINVAL;
1407 } 1271 }
1408 1272
1409 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); 1273 ret = twl6040_set_pll(twl6040, TWL6040_LPPLL_ID, priv->clk_in, sysclk);
1274 if (ret)
1275 return ret;
1276
1277 priv->sysclk = twl6040_get_sysclk(twl6040);
1410 1278
1411 return 0; 1279 return 0;
1412} 1280}
@@ -1449,99 +1317,27 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1449 int clk_id, unsigned int freq, int dir) 1317 int clk_id, unsigned int freq, int dir)
1450{ 1318{
1451 struct snd_soc_codec *codec = codec_dai->codec; 1319 struct snd_soc_codec *codec = codec_dai->codec;
1320 struct twl6040 *twl6040 = codec->control_data;
1452 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1321 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1453 u8 hppllctl, lppllctl; 1322 int ret = 0;
1454
1455 hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL);
1456 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
1457 1323
1458 switch (clk_id) { 1324 switch (clk_id) {
1459 case TWL6040_SYSCLK_SEL_LPPLL: 1325 case TWL6040_SYSCLK_SEL_LPPLL:
1460 switch (freq) { 1326 ret = twl6040_set_pll(twl6040, TWL6040_LPPLL_ID,
1461 case 32768: 1327 freq, priv->sysclk);
1462 /* headset dac and driver must be in low-power mode */ 1328 if (ret)
1463 headset_power_mode(codec, 0); 1329 return ret;
1464
1465 /* clk32k input requires low-power pll */
1466 lppllctl |= TWL6040_LPLLENA;
1467 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
1468 mdelay(5);
1469 lppllctl &= ~TWL6040_HPLLSEL;
1470 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
1471 hppllctl &= ~TWL6040_HPLLENA;
1472 twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
1473 break;
1474 default:
1475 dev_err(codec->dev, "unknown mclk freq %d\n", freq);
1476 return -EINVAL;
1477 }
1478
1479 /* lppll divider */
1480 switch (priv->sysclk) {
1481 case 17640000:
1482 lppllctl |= TWL6040_LPLLFIN;
1483 break;
1484 case 19200000:
1485 lppllctl &= ~TWL6040_LPLLFIN;
1486 break;
1487 default:
1488 /* sysclk not yet configured */
1489 lppllctl &= ~TWL6040_LPLLFIN;
1490 priv->sysclk = 19200000;
1491 break;
1492 }
1493
1494 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
1495 1330
1496 priv->pll = TWL6040_LPPLL_ID; 1331 headset_power_mode(codec, 0);
1497 priv->sysclk_constraints = &lp_constraints; 1332 priv->sysclk_constraints = &lp_constraints;
1498 break; 1333 break;
1499 case TWL6040_SYSCLK_SEL_HPPLL: 1334 case TWL6040_SYSCLK_SEL_HPPLL:
1500 hppllctl &= ~TWL6040_MCLK_MSK; 1335 ret = twl6040_set_pll(twl6040, TWL6040_HPPLL_ID,
1501 1336 freq, priv->sysclk);
1502 switch (freq) { 1337 if (ret)
1503 case 12000000: 1338 return ret;
1504 /* mclk input, pll enabled */
1505 hppllctl |= TWL6040_MCLK_12000KHZ |
1506 TWL6040_HPLLSQRBP |
1507 TWL6040_HPLLENA;
1508 break;
1509 case 19200000:
1510 /* mclk input, pll disabled */
1511 hppllctl |= TWL6040_MCLK_19200KHZ |
1512 TWL6040_HPLLSQRENA |
1513 TWL6040_HPLLBP;
1514 break;
1515 case 26000000:
1516 /* mclk input, pll enabled */
1517 hppllctl |= TWL6040_MCLK_26000KHZ |
1518 TWL6040_HPLLSQRBP |
1519 TWL6040_HPLLENA;
1520 break;
1521 case 38400000:
1522 /* clk slicer, pll disabled */
1523 hppllctl |= TWL6040_MCLK_38400KHZ |
1524 TWL6040_HPLLSQRENA |
1525 TWL6040_HPLLBP;
1526 break;
1527 default:
1528 dev_err(codec->dev, "unknown mclk freq %d\n", freq);
1529 return -EINVAL;
1530 }
1531 1339
1532 /* headset dac and driver must be in high-performance mode */
1533 headset_power_mode(codec, 1); 1340 headset_power_mode(codec, 1);
1534
1535 twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
1536 udelay(500);
1537 lppllctl |= TWL6040_HPLLSEL;
1538 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
1539 lppllctl &= ~TWL6040_LPLLENA;
1540 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
1541
1542 /* high-performance pll can provide only 19.2 MHz */
1543 priv->pll = TWL6040_HPPLL_ID;
1544 priv->sysclk = 19200000;
1545 priv->sysclk_constraints = &hp_constraints; 1341 priv->sysclk_constraints = &hp_constraints;
1546 break; 1342 break;
1547 default: 1343 default:
@@ -1549,6 +1345,10 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1549 return -EINVAL; 1345 return -EINVAL;
1550 } 1346 }
1551 1347
1348 priv->pll = twl6040_get_pll(twl6040);
1349 priv->clk_in = freq;
1350 priv->sysclk = twl6040_get_sysclk(twl6040);
1351
1552 return 0; 1352 return 0;
1553} 1353}
1554 1354
@@ -1600,11 +1400,8 @@ static int twl6040_resume(struct snd_soc_codec *codec)
1600 1400
1601static int twl6040_probe(struct snd_soc_codec *codec) 1401static int twl6040_probe(struct snd_soc_codec *codec)
1602{ 1402{
1603 struct twl4030_audio_data *twl_codec = codec->dev->platform_data;
1604 struct twl6040_data *priv; 1403 struct twl6040_data *priv;
1605 int audpwron, naudint;
1606 int ret = 0; 1404 int ret = 0;
1607 u8 icrev, intmr = TWL6040_ALLINT_MSK;
1608 1405
1609 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); 1406 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
1610 if (priv == NULL) 1407 if (priv == NULL)
@@ -1612,23 +1409,9 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1612 snd_soc_codec_set_drvdata(codec, priv); 1409 snd_soc_codec_set_drvdata(codec, priv);
1613 1410
1614 priv->codec = codec; 1411 priv->codec = codec;
1412 codec->control_data = dev_get_drvdata(codec->dev->parent);
1615 1413
1616 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &icrev, TWL6040_REG_ASICREV);
1617
1618 if (twl_codec && (icrev > 0))
1619 audpwron = twl_codec->audpwron_gpio;
1620 else
1621 audpwron = -EINVAL;
1622
1623 if (twl_codec)
1624 naudint = twl_codec->naudint_irq;
1625 else
1626 naudint = 0;
1627
1628 priv->audpwron = audpwron;
1629 priv->naudint = naudint;
1630 priv->workqueue = create_singlethread_workqueue("twl6040-codec"); 1414 priv->workqueue = create_singlethread_workqueue("twl6040-codec");
1631
1632 if (!priv->workqueue) { 1415 if (!priv->workqueue) {
1633 ret = -ENOMEM; 1416 ret = -ENOMEM;
1634 goto work_err; 1417 goto work_err;
@@ -1638,56 +1421,34 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1638 1421
1639 mutex_init(&priv->mutex); 1422 mutex_init(&priv->mutex);
1640 1423
1641 init_completion(&priv->ready);
1642 init_completion(&priv->headset.ramp_done); 1424 init_completion(&priv->headset.ramp_done);
1643 init_completion(&priv->handsfree.ramp_done); 1425 init_completion(&priv->handsfree.ramp_done);
1644 1426
1645 if (gpio_is_valid(audpwron)) {
1646 ret = gpio_request(audpwron, "audpwron");
1647 if (ret)
1648 goto gpio1_err;
1649
1650 ret = gpio_direction_output(audpwron, 0);
1651 if (ret)
1652 goto gpio2_err;
1653
1654 priv->codec_powered = 0;
1655
1656 /* enable only codec ready interrupt */
1657 intmr &= ~(TWL6040_READYMSK | TWL6040_PLUGMSK);
1658
1659 /* reset interrupt status to allow correct power up sequence */
1660 twl6040_read_reg_volatile(codec, TWL6040_REG_INTID);
1661 }
1662 twl6040_write(codec, TWL6040_REG_INTMR, intmr);
1663
1664 if (naudint) {
1665 /* audio interrupt */
1666 ret = request_threaded_irq(naudint, NULL,
1667 twl6040_naudint_handler,
1668 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
1669 "twl6040_codec", codec);
1670 if (ret)
1671 goto gpio2_err;
1672 }
1673
1674 /* init vio registers */
1675 twl6040_init_vio_regs(codec);
1676
1677 priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf"); 1427 priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
1678 if (priv->hf_workqueue == NULL) { 1428 if (priv->hf_workqueue == NULL) {
1679 ret = -ENOMEM; 1429 ret = -ENOMEM;
1680 goto irq_err; 1430 goto hfwq_err;
1681 } 1431 }
1682 priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs"); 1432 priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
1683 if (priv->hs_workqueue == NULL) { 1433 if (priv->hs_workqueue == NULL) {
1684 ret = -ENOMEM; 1434 ret = -ENOMEM;
1685 goto wq_err; 1435 goto hswq_err;
1686 } 1436 }
1687 1437
1688 INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work); 1438 INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
1689 INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work); 1439 INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
1690 1440
1441 ret = twl6040_request_irq(codec->control_data, TWL6040_IRQ_PLUG,
1442 twl6040_audio_handler, 0,
1443 "twl6040_irq_plug", codec);
1444 if (ret) {
1445 dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret);
1446 goto plugirq_err;
1447 }
1448
1449 /* init vio registers */
1450 twl6040_init_vio_regs(codec);
1451
1691 /* power on device */ 1452 /* power on device */
1692 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1453 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1693 if (ret) 1454 if (ret)
@@ -1700,16 +1461,12 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1700 return 0; 1461 return 0;
1701 1462
1702bias_err: 1463bias_err:
1464 twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec);
1465plugirq_err:
1703 destroy_workqueue(priv->hs_workqueue); 1466 destroy_workqueue(priv->hs_workqueue);
1704wq_err: 1467hswq_err:
1705 destroy_workqueue(priv->hf_workqueue); 1468 destroy_workqueue(priv->hf_workqueue);
1706irq_err: 1469hfwq_err:
1707 if (naudint)
1708 free_irq(naudint, codec);
1709gpio2_err:
1710 if (gpio_is_valid(audpwron))
1711 gpio_free(audpwron);
1712gpio1_err:
1713 destroy_workqueue(priv->workqueue); 1470 destroy_workqueue(priv->workqueue);
1714work_err: 1471work_err:
1715 kfree(priv); 1472 kfree(priv);
@@ -1719,17 +1476,9 @@ work_err:
1719static int twl6040_remove(struct snd_soc_codec *codec) 1476static int twl6040_remove(struct snd_soc_codec *codec)
1720{ 1477{
1721 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1478 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1722 int audpwron = priv->audpwron;
1723 int naudint = priv->naudint;
1724 1479
1725 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); 1480 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1726 1481 twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec);
1727 if (gpio_is_valid(audpwron))
1728 gpio_free(audpwron);
1729
1730 if (naudint)
1731 free_irq(naudint, codec);
1732
1733 destroy_workqueue(priv->workqueue); 1482 destroy_workqueue(priv->workqueue);
1734 destroy_workqueue(priv->hf_workqueue); 1483 destroy_workqueue(priv->hf_workqueue);
1735 destroy_workqueue(priv->hs_workqueue); 1484 destroy_workqueue(priv->hs_workqueue);
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index 23aeed0963e..234bfad24e6 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -22,124 +22,6 @@
22#ifndef __TWL6040_H__ 22#ifndef __TWL6040_H__
23#define __TWL6040_H__ 23#define __TWL6040_H__
24 24
25#define TWL6040_REG_ASICID 0x01
26#define TWL6040_REG_ASICREV 0x02
27#define TWL6040_REG_INTID 0x03
28#define TWL6040_REG_INTMR 0x04
29#define TWL6040_REG_NCPCTL 0x05
30#define TWL6040_REG_LDOCTL 0x06
31#define TWL6040_REG_HPPLLCTL 0x07
32#define TWL6040_REG_LPPLLCTL 0x08
33#define TWL6040_REG_LPPLLDIV 0x09
34#define TWL6040_REG_AMICBCTL 0x0A
35#define TWL6040_REG_DMICBCTL 0x0B
36#define TWL6040_REG_MICLCTL 0x0C
37#define TWL6040_REG_MICRCTL 0x0D
38#define TWL6040_REG_MICGAIN 0x0E
39#define TWL6040_REG_LINEGAIN 0x0F
40#define TWL6040_REG_HSLCTL 0x10
41#define TWL6040_REG_HSRCTL 0x11
42#define TWL6040_REG_HSGAIN 0x12
43#define TWL6040_REG_EARCTL 0x13
44#define TWL6040_REG_HFLCTL 0x14
45#define TWL6040_REG_HFLGAIN 0x15
46#define TWL6040_REG_HFRCTL 0x16
47#define TWL6040_REG_HFRGAIN 0x17
48#define TWL6040_REG_VIBCTLL 0x18
49#define TWL6040_REG_VIBDATL 0x19
50#define TWL6040_REG_VIBCTLR 0x1A
51#define TWL6040_REG_VIBDATR 0x1B
52#define TWL6040_REG_HKCTL1 0x1C
53#define TWL6040_REG_HKCTL2 0x1D
54#define TWL6040_REG_GPOCTL 0x1E
55#define TWL6040_REG_ALB 0x1F
56#define TWL6040_REG_DLB 0x20
57#define TWL6040_REG_TRIM1 0x28
58#define TWL6040_REG_TRIM2 0x29
59#define TWL6040_REG_TRIM3 0x2A
60#define TWL6040_REG_HSOTRIM 0x2B
61#define TWL6040_REG_HFOTRIM 0x2C
62#define TWL6040_REG_ACCCTL 0x2D
63#define TWL6040_REG_STATUS 0x2E
64
65#define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1)
66
67#define TWL6040_VIOREGNUM 18
68#define TWL6040_VDDREGNUM 21
69
70/* INTID (0x03) fields */
71
72#define TWL6040_THINT 0x01
73#define TWL6040_PLUGINT 0x02
74#define TWL6040_UNPLUGINT 0x04
75#define TWL6040_HOOKINT 0x08
76#define TWL6040_HFINT 0x10
77#define TWL6040_VIBINT 0x20
78#define TWL6040_READYINT 0x40
79
80/* INTMR (0x04) fields */
81
82#define TWL6040_PLUGMSK 0x02
83#define TWL6040_READYMSK 0x40
84#define TWL6040_ALLINT_MSK 0x7B
85
86/* NCPCTL (0x05) fields */
87
88#define TWL6040_NCPENA 0x01
89#define TWL6040_NCPOPEN 0x40
90
91/* LDOCTL (0x06) fields */
92
93#define TWL6040_LSLDOENA 0x01
94#define TWL6040_HSLDOENA 0x04
95#define TWL6040_REFENA 0x40
96#define TWL6040_OSCENA 0x80
97
98/* HPPLLCTL (0x07) fields */
99
100#define TWL6040_HPLLENA 0x01
101#define TWL6040_HPLLRST 0x02
102#define TWL6040_HPLLBP 0x04
103#define TWL6040_HPLLSQRENA 0x08
104#define TWL6040_HPLLSQRBP 0x10
105#define TWL6040_MCLK_12000KHZ (0 << 5)
106#define TWL6040_MCLK_19200KHZ (1 << 5)
107#define TWL6040_MCLK_26000KHZ (2 << 5)
108#define TWL6040_MCLK_38400KHZ (3 << 5)
109#define TWL6040_MCLK_MSK 0x60
110
111/* LPPLLCTL (0x08) fields */
112
113#define TWL6040_LPLLENA 0x01
114#define TWL6040_LPLLRST 0x02
115#define TWL6040_LPLLSEL 0x04
116#define TWL6040_LPLLFIN 0x08
117#define TWL6040_HPLLSEL 0x10
118
119/* HSLCTL (0x10) fields */
120
121#define TWL6040_HSDACMODEL 0x02
122#define TWL6040_HSDRVMODEL 0x08
123
124/* HSRCTL (0x11) fields */
125
126#define TWL6040_HSDACMODER 0x02
127#define TWL6040_HSDRVMODER 0x08
128
129/* ACCCTL (0x2D) fields */
130
131#define TWL6040_RESETSPLIT 0x04
132
133#define TWL6040_SYSCLK_SEL_LPPLL 1
134#define TWL6040_SYSCLK_SEL_HPPLL 2
135
136#define TWL6040_HPPLL_ID 1
137#define TWL6040_LPPLL_ID 2
138
139/* STATUS (0x2E) fields */
140
141#define TWL6040_PLUGCOMP 0x02
142
143void twl6040_hs_jack_detect(struct snd_soc_codec *codec, 25void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
144 struct snd_soc_jack *jack, int report); 26 struct snd_soc_jack *jack, int report);
145 27
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index 189e0390063..5d67c25bca5 100644
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -21,6 +21,8 @@
21 21
22#include <linux/clk.h> 22#include <linux/clk.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/mfd/twl6040.h>
25
24#include <sound/core.h> 26#include <sound/core.h>
25#include <sound/pcm.h> 27#include <sound/pcm.h>
26#include <sound/soc.h> 28#include <sound/soc.h>