Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: sound/soc/codecs/twl6040.c

Issue 6577007: CHROMIUM: ASoC: Import entire upstream ASoC tree (Closed)
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sound/soc/codecs/twl6040.h ('k') | sound/soc/codecs/uda134x.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * ALSA SoC TWL6040 codec driver 2 * ALSA SoC TWL6040 codec driver
3 * 3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com> 4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License 7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation. 8 * version 2 as published by the Free Software Foundation.
9 * 9 *
10 * This program is distributed in the hope that it will be useful, but 10 * This program is distributed in the hope that it will be useful, but
(...skipping 16 matching lines...) Expand all
27 #include <linux/i2c.h> 27 #include <linux/i2c.h>
28 #include <linux/gpio.h> 28 #include <linux/gpio.h>
29 #include <linux/platform_device.h> 29 #include <linux/platform_device.h>
30 #include <linux/slab.h> 30 #include <linux/slab.h>
31 #include <linux/i2c/twl.h> 31 #include <linux/i2c/twl.h>
32 32
33 #include <sound/core.h> 33 #include <sound/core.h>
34 #include <sound/pcm.h> 34 #include <sound/pcm.h>
35 #include <sound/pcm_params.h> 35 #include <sound/pcm_params.h>
36 #include <sound/soc.h> 36 #include <sound/soc.h>
37 #include <sound/soc-dapm.h>
38 #include <sound/initval.h> 37 #include <sound/initval.h>
39 #include <sound/tlv.h> 38 #include <sound/tlv.h>
40 39
41 #include "twl6040.h" 40 #include "twl6040.h"
42 41
43 #define TWL6040_RATES» (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 42 #define TWL6040_RATES» » SNDRV_PCM_RATE_8000_96000
44 #define TWL6040_FORMATS» (SNDRV_PCM_FMTBIT_S32_LE) 43 #define TWL6040_FORMATS»(SNDRV_PCM_FMTBIT_S32_LE)
44
45 #define TWL6040_OUTHS_0dB 0x00
46 #define TWL6040_OUTHS_M30dB 0x0F
47 #define TWL6040_OUTHF_0dB 0x03
48 #define TWL6040_OUTHF_M52dB 0x1D
49
50 #define TWL6040_RAMP_NONE» 0
51 #define TWL6040_RAMP_UP»» 1
52 #define TWL6040_RAMP_DOWN» 2
53
54 #define TWL6040_HSL_VOL_MASK» 0x0F
55 #define TWL6040_HSL_VOL_SHIFT» 0
56 #define TWL6040_HSR_VOL_MASK» 0xF0
57 #define TWL6040_HSR_VOL_SHIFT» 4
58 #define TWL6040_HF_VOL_MASK» 0x1F
59 #define TWL6040_HF_VOL_SHIFT» 0
60
61 struct twl6040_output {
62 » u16 active;
63 » u16 left_vol;
64 » u16 right_vol;
65 » u16 left_step;
66 » u16 right_step;
67 » unsigned int step_delay;
68 » u16 ramp;
69 » u16 mute;
70 » struct completion ramp_done;
71 };
72
73 struct twl6040_jack_data {
74 » struct snd_soc_jack *jack;
75 » int report;
76 };
45 77
46 /* codec private data */ 78 /* codec private data */
47 struct twl6040_data { 79 struct twl6040_data {
48 int audpwron; 80 int audpwron;
49 int naudint; 81 int naudint;
50 int codec_powered; 82 int codec_powered;
51 int pll; 83 int pll;
52 int non_lp; 84 int non_lp;
53 unsigned int sysclk; 85 unsigned int sysclk;
54 struct snd_pcm_hw_constraint_list *sysclk_constraints; 86 struct snd_pcm_hw_constraint_list *sysclk_constraints;
55 struct completion ready; 87 struct completion ready;
88 struct twl6040_jack_data hs_jack;
89 struct snd_soc_codec *codec;
90 struct workqueue_struct *workqueue;
91 struct delayed_work delayed_work;
92 struct mutex mutex;
93 struct twl6040_output headset;
94 struct twl6040_output handsfree;
95 struct workqueue_struct *hf_workqueue;
96 struct workqueue_struct *hs_workqueue;
97 struct delayed_work hs_delayed_work;
98 struct delayed_work hf_delayed_work;
56 }; 99 };
57 100
58 /* 101 /*
59 * twl6040 register cache & default register settings 102 * twl6040 register cache & default register settings
60 */ 103 */
61 static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = { 104 static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
62 0x00, /* not used 0x00 */ 105 0x00, /* not used 0x00 */
63 0x4B, /* TWL6040_ASICID (ro) 0x01 */ 106 0x4B, /* TWL6040_ASICID (ro) 0x01 */
64 0x00, /* TWL6040_ASICREV (ro) 0x02 */ 107 0x00, /* TWL6040_ASICREV (ro) 0x02 */
65 0x00, /* TWL6040_INTID 0x03 */ 108 0x00, /* TWL6040_INTID 0x03 */
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 * read from twl6040 hardware register 237 * read from twl6040 hardware register
195 */ 238 */
196 static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, 239 static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
197 unsigned int reg) 240 unsigned int reg)
198 { 241 {
199 u8 value; 242 u8 value;
200 243
201 if (reg >= TWL6040_CACHEREGNUM) 244 if (reg >= TWL6040_CACHEREGNUM)
202 return -EIO; 245 return -EIO;
203 246
204 » twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &value, reg); 247 » twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &value, reg);
205 twl6040_write_reg_cache(codec, reg, value); 248 twl6040_write_reg_cache(codec, reg, value);
206 249
207 return value; 250 return value;
208 } 251 }
209 252
210 /* 253 /*
211 * write to the twl6040 register space 254 * write to the twl6040 register space
212 */ 255 */
213 static int twl6040_write(struct snd_soc_codec *codec, 256 static int twl6040_write(struct snd_soc_codec *codec,
214 unsigned int reg, unsigned int value) 257 unsigned int reg, unsigned int value)
215 { 258 {
216 if (reg >= TWL6040_CACHEREGNUM) 259 if (reg >= TWL6040_CACHEREGNUM)
217 return -EIO; 260 return -EIO;
218 261
219 twl6040_write_reg_cache(codec, reg, value); 262 twl6040_write_reg_cache(codec, reg, value);
220 » return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); 263 » return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, value, reg);
221 } 264 }
222 265
223 static void twl6040_init_vio_regs(struct snd_soc_codec *codec) 266 static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
224 { 267 {
225 u8 *cache = codec->reg_cache; 268 u8 *cache = codec->reg_cache;
226 int reg, i; 269 int reg, i;
227 270
228 /* allow registers to be accessed by i2c */ 271 /* allow registers to be accessed by i2c */
229 twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]); 272 twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]);
230 273
(...skipping 16 matching lines...) Expand all
247 { 290 {
248 u8 *cache = codec->reg_cache; 291 u8 *cache = codec->reg_cache;
249 int reg, i; 292 int reg, i;
250 293
251 for (i = 0; i < TWL6040_VDDREGNUM; i++) { 294 for (i = 0; i < TWL6040_VDDREGNUM; i++) {
252 reg = twl6040_vdd_reg[i]; 295 reg = twl6040_vdd_reg[i];
253 twl6040_write(codec, reg, cache[reg]); 296 twl6040_write(codec, reg, cache[reg]);
254 } 297 }
255 } 298 }
256 299
300 /*
301 * Ramp HS PGA volume to minimise pops at stream startup and shutdown.
302 */
303 static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
304 unsigned int left_step, unsigned int right_step)
305 {
306
307 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
308 struct twl6040_output *headset = &priv->headset;
309 int left_complete = 0, right_complete = 0;
310 u8 reg, val;
311
312 /* left channel */
313 left_step = (left_step > 0xF) ? 0xF : left_step;
314 reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);
315 val = (~reg & TWL6040_HSL_VOL_MASK);
316
317 if (headset->ramp == TWL6040_RAMP_UP) {
318 /* ramp step up */
319 if (val < headset->left_vol) {
320 val += left_step;
321 reg &= ~TWL6040_HSL_VOL_MASK;
322 twl6040_write(codec, TWL6040_REG_HSGAIN,
323 (reg | (~val & TWL6040_HSL_VOL_MASK)));
324 } else {
325 left_complete = 1;
326 }
327 } else if (headset->ramp == TWL6040_RAMP_DOWN) {
328 /* ramp step down */
329 if (val > 0x0) {
330 val -= left_step;
331 reg &= ~TWL6040_HSL_VOL_MASK;
332 twl6040_write(codec, TWL6040_REG_HSGAIN, reg |
333 (~val & TWL6040_HSL_VOL_MASK));
334 } else {
335 left_complete = 1;
336 }
337 }
338
339 /* right channel */
340 right_step = (right_step > 0xF) ? 0xF : right_step;
341 reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);
342 val = (~reg & TWL6040_HSR_VOL_MASK) >> TWL6040_HSR_VOL_SHIFT;
343
344 if (headset->ramp == TWL6040_RAMP_UP) {
345 /* ramp step up */
346 if (val < headset->right_vol) {
347 val += right_step;
348 reg &= ~TWL6040_HSR_VOL_MASK;
349 twl6040_write(codec, TWL6040_REG_HSGAIN,
350 (reg | (~val << TWL6040_HSR_VOL_SHIFT)));
351 } else {
352 right_complete = 1;
353 }
354 } else if (headset->ramp == TWL6040_RAMP_DOWN) {
355 /* ramp step down */
356 if (val > 0x0) {
357 val -= right_step;
358 reg &= ~TWL6040_HSR_VOL_MASK;
359 twl6040_write(codec, TWL6040_REG_HSGAIN,
360 reg | (~val << TWL6040_HSR_VOL_SHIFT));
361 } else {
362 right_complete = 1;
363 }
364 }
365
366 return left_complete & right_complete;
367 }
368
369 /*
370 * Ramp HF PGA volume to minimise pops at stream startup and shutdown.
371 */
372 static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
373 unsigned int left_step, unsigned int right_step)
374 {
375 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
376 struct twl6040_output *handsfree = &priv->handsfree;
377 int left_complete = 0, right_complete = 0;
378 u16 reg, val;
379
380 /* left channel */
381 left_step = (left_step > 0x1D) ? 0x1D : left_step;
382 reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN);
383 reg = 0x1D - reg;
384 val = (reg & TWL6040_HF_VOL_MASK);
385 if (handsfree->ramp == TWL6040_RAMP_UP) {
386 /* ramp step up */
387 if (val < handsfree->left_vol) {
388 val += left_step;
389 reg &= ~TWL6040_HF_VOL_MASK;
390 twl6040_write(codec, TWL6040_REG_HFLGAIN,
391 reg | (0x1D - val));
392 } else {
393 left_complete = 1;
394 }
395 } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
396 /* ramp step down */
397 if (val > 0) {
398 val -= left_step;
399 reg &= ~TWL6040_HF_VOL_MASK;
400 twl6040_write(codec, TWL6040_REG_HFLGAIN,
401 reg | (0x1D - val));
402 } else {
403 left_complete = 1;
404 }
405 }
406
407 /* right channel */
408 right_step = (right_step > 0x1D) ? 0x1D : right_step;
409 reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN);
410 reg = 0x1D - reg;
411 val = (reg & TWL6040_HF_VOL_MASK);
412 if (handsfree->ramp == TWL6040_RAMP_UP) {
413 /* ramp step up */
414 if (val < handsfree->right_vol) {
415 val += right_step;
416 reg &= ~TWL6040_HF_VOL_MASK;
417 twl6040_write(codec, TWL6040_REG_HFRGAIN,
418 reg | (0x1D - val));
419 } else {
420 right_complete = 1;
421 }
422 } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
423 /* ramp step down */
424 if (val > 0) {
425 val -= right_step;
426 reg &= ~TWL6040_HF_VOL_MASK;
427 twl6040_write(codec, TWL6040_REG_HFRGAIN,
428 reg | (0x1D - val));
429 }
430 }
431
432 return left_complete & right_complete;
433 }
434
435 /*
436 * This work ramps both output PGAs at stream start/stop time to
437 * minimise pop associated with DAPM power switching.
438 */
439 static void twl6040_pga_hs_work(struct work_struct *work)
440 {
441 struct twl6040_data *priv =
442 container_of(work, struct twl6040_data, hs_delayed_work.work);
443 struct snd_soc_codec *codec = priv->codec;
444 struct twl6040_output *headset = &priv->headset;
445 unsigned int delay = headset->step_delay;
446 int i, headset_complete;
447
448 /* do we need to ramp at all ? */
449 if (headset->ramp == TWL6040_RAMP_NONE)
450 return;
451
452 /* HS PGA volumes have 4 bits of resolution to ramp */
453 for (i = 0; i <= 16; i++) {
454 headset_complete = 1;
455 if (headset->ramp != TWL6040_RAMP_NONE)
456 headset_complete = twl6040_hs_ramp_step(codec,
457 headset->left_step,
458 headset->right_step);
459
460 /* ramp finished ? */
461 if (headset_complete)
462 break;
463
464 /*
465 * TODO: tune: delay is longer over 0dB
466 * as increases are larger.
467 */
468 if (i >= 8)
469 schedule_timeout_interruptible(msecs_to_jiffies(delay +
470 (delay >> 1)));
471 else
472 schedule_timeout_interruptible(msecs_to_jiffies(delay));
473 }
474
475 if (headset->ramp == TWL6040_RAMP_DOWN) {
476 headset->active = 0;
477 complete(&headset->ramp_done);
478 } else {
479 headset->active = 1;
480 }
481 headset->ramp = TWL6040_RAMP_NONE;
482 }
483
484 static void twl6040_pga_hf_work(struct work_struct *work)
485 {
486 struct twl6040_data *priv =
487 container_of(work, struct twl6040_data, hf_delayed_work.work);
488 struct snd_soc_codec *codec = priv->codec;
489 struct twl6040_output *handsfree = &priv->handsfree;
490 unsigned int delay = handsfree->step_delay;
491 int i, handsfree_complete;
492
493 /* do we need to ramp at all ? */
494 if (handsfree->ramp == TWL6040_RAMP_NONE)
495 return;
496
497 /* HF PGA volumes have 5 bits of resolution to ramp */
498 for (i = 0; i <= 32; i++) {
499 handsfree_complete = 1;
500 if (handsfree->ramp != TWL6040_RAMP_NONE)
501 handsfree_complete = twl6040_hf_ramp_step(codec,
502 handsfree->left_step,
503 handsfree->right_step);
504
505 /* ramp finished ? */
506 if (handsfree_complete)
507 break;
508
509 /*
510 * TODO: tune: delay is longer over 0dB
511 * as increases are larger.
512 */
513 if (i >= 16)
514 schedule_timeout_interruptible(msecs_to_jiffies(delay +
515 (delay >> 1)));
516 else
517 schedule_timeout_interruptible(msecs_to_jiffies(delay));
518 }
519
520
521 if (handsfree->ramp == TWL6040_RAMP_DOWN) {
522 handsfree->active = 0;
523 complete(&handsfree->ramp_done);
524 } else
525 handsfree->active = 1;
526 handsfree->ramp = TWL6040_RAMP_NONE;
527 }
528
529 static int pga_event(struct snd_soc_dapm_widget *w,
530 struct snd_kcontrol *kcontrol, int event)
531 {
532 struct snd_soc_codec *codec = w->codec;
533 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
534 struct twl6040_output *out;
535 struct delayed_work *work;
536 struct workqueue_struct *queue;
537
538 switch (w->shift) {
539 case 2:
540 case 3:
541 out = &priv->headset;
542 work = &priv->hs_delayed_work;
543 queue = priv->hs_workqueue;
544 out->step_delay = 5; /* 5 ms between volume ramp steps */
545 break;
546 case 4:
547 out = &priv->handsfree;
548 work = &priv->hf_delayed_work;
549 queue = priv->hf_workqueue;
550 out->step_delay = 5; /* 5 ms between volume ramp steps */
551 if (SND_SOC_DAPM_EVENT_ON(event))
552 priv->non_lp++;
553 else
554 priv->non_lp--;
555 break;
556 default:
557 return -1;
558 }
559
560 switch (event) {
561 case SND_SOC_DAPM_POST_PMU:
562 if (out->active)
563 break;
564
565 /* don't use volume ramp for power-up */
566 out->left_step = out->left_vol;
567 out->right_step = out->right_vol;
568
569 if (!delayed_work_pending(work)) {
570 out->ramp = TWL6040_RAMP_UP;
571 queue_delayed_work(queue, work,
572 msecs_to_jiffies(1));
573 }
574 break;
575
576 case SND_SOC_DAPM_PRE_PMD:
577 if (!out->active)
578 break;
579
580 if (!delayed_work_pending(work)) {
581 /* use volume ramp for power-down */
582 out->left_step = 1;
583 out->right_step = 1;
584 out->ramp = TWL6040_RAMP_DOWN;
585 INIT_COMPLETION(out->ramp_done);
586
587 queue_delayed_work(queue, work,
588 msecs_to_jiffies(1));
589
590 wait_for_completion_timeout(&out->ramp_done,
591 msecs_to_jiffies(2000));
592 }
593 break;
594 }
595
596 return 0;
597 }
598
257 /* twl6040 codec manual power-up sequence */ 599 /* twl6040 codec manual power-up sequence */
258 static void twl6040_power_up(struct snd_soc_codec *codec) 600 static void twl6040_power_up(struct snd_soc_codec *codec)
259 { 601 {
260 u8 ncpctl, ldoctl, lppllctl, accctl; 602 u8 ncpctl, ldoctl, lppllctl, accctl;
261 603
262 ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL); 604 ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
263 ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL); 605 ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
264 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL); 606 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
265 accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL); 607 accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
266 608
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 if (SND_SOC_DAPM_EVENT_ON(event)) 717 if (SND_SOC_DAPM_EVENT_ON(event))
376 priv->non_lp++; 718 priv->non_lp++;
377 else 719 else
378 priv->non_lp--; 720 priv->non_lp--;
379 721
380 msleep(1); 722 msleep(1);
381 723
382 return 0; 724 return 0;
383 } 725 }
384 726
727 static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
728 struct snd_soc_jack *jack, int report)
729 {
730 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
731 int status;
732
733 mutex_lock(&priv->mutex);
734
735 /* Sync status */
736 status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS);
737 if (status & TWL6040_PLUGCOMP)
738 snd_soc_jack_report(jack, report, report);
739 else
740 snd_soc_jack_report(jack, 0, report);
741
742 mutex_unlock(&priv->mutex);
743 }
744
745 void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
746 struct snd_soc_jack *jack, int report)
747 {
748 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
749 struct twl6040_jack_data *hs_jack = &priv->hs_jack;
750
751 hs_jack->jack = jack;
752 hs_jack->report = report;
753
754 twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
755 }
756 EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);
757
758 static void twl6040_accessory_work(struct work_struct *work)
759 {
760 struct twl6040_data *priv = container_of(work,
761 struct twl6040_data, delayed_work.work);
762 struct snd_soc_codec *codec = priv->codec;
763 struct twl6040_jack_data *hs_jack = &priv->hs_jack;
764
765 twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
766 }
767
385 /* audio interrupt handler */ 768 /* audio interrupt handler */
386 static irqreturn_t twl6040_naudint_handler(int irq, void *data) 769 static irqreturn_t twl6040_naudint_handler(int irq, void *data)
387 { 770 {
388 struct snd_soc_codec *codec = data; 771 struct snd_soc_codec *codec = data;
389 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 772 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
390 u8 intid; 773 u8 intid;
391 774
392 » twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID); 775 » twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
393 776
394 » switch (intid) { 777 » if (intid & TWL6040_THINT)
395 » case TWL6040_THINT:
396 dev_alert(codec->dev, "die temp over-limit detection\n"); 778 dev_alert(codec->dev, "die temp over-limit detection\n");
397 » » break; 779
398 » case TWL6040_PLUGINT: 780 » if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
399 » case TWL6040_UNPLUGINT: 781 » » queue_delayed_work(priv->workqueue, &priv->delayed_work,
400 » case TWL6040_HOOKINT: 782 » » » » » » » msecs_to_jiffies(200));
401 » » break; 783
402 » case TWL6040_HFINT: 784 » if (intid & TWL6040_HOOKINT)
785 » » dev_info(codec->dev, "hook detection\n");
786
787 » if (intid & TWL6040_HFINT)
403 dev_alert(codec->dev, "hf drivers over current detection\n"); 788 dev_alert(codec->dev, "hf drivers over current detection\n");
404 » » break; 789
405 » case TWL6040_VIBINT: 790 » if (intid & TWL6040_VIBINT)
406 dev_alert(codec->dev, "vib drivers over current detection\n"); 791 dev_alert(codec->dev, "vib drivers over current detection\n");
407 » » break; 792
408 » case TWL6040_READYINT: 793 » if (intid & TWL6040_READYINT)
409 complete(&priv->ready); 794 complete(&priv->ready);
410 break;
411 default:
412 dev_err(codec->dev, "unknown audio interrupt %d\n", intid);
413 break;
414 }
415 795
416 return IRQ_HANDLED; 796 return IRQ_HANDLED;
417 } 797 }
418 798
799 static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
800 struct snd_ctl_elem_value *ucontrol)
801 {
802 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
803 struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
804 struct twl6040_output *out = NULL;
805 struct soc_mixer_control *mc =
806 (struct soc_mixer_control *)kcontrol->private_value;
807 int ret;
808 unsigned int reg = mc->reg;
809
810 /* For HS and HF we shadow the values and only actually write
811 * them out when active in order to ensure the amplifier comes on
812 * as quietly as possible. */
813 switch (reg) {
814 case TWL6040_REG_HSGAIN:
815 out = &twl6040_priv->headset;
816 break;
817 default:
818 break;
819 }
820
821 if (out) {
822 out->left_vol = ucontrol->value.integer.value[0];
823 out->right_vol = ucontrol->value.integer.value[1];
824 if (!out->active)
825 return 1;
826 }
827
828 ret = snd_soc_put_volsw(kcontrol, ucontrol);
829 if (ret < 0)
830 return ret;
831
832 return 1;
833 }
834
835 static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
836 struct snd_ctl_elem_value *ucontrol)
837 {
838 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
839 struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
840 struct twl6040_output *out = &twl6040_priv->headset;
841 struct soc_mixer_control *mc =
842 (struct soc_mixer_control *)kcontrol->private_value;
843 unsigned int reg = mc->reg;
844
845 switch (reg) {
846 case TWL6040_REG_HSGAIN:
847 out = &twl6040_priv->headset;
848 ucontrol->value.integer.value[0] = out->left_vol;
849 ucontrol->value.integer.value[1] = out->right_vol;
850 return 0;
851
852 default:
853 break;
854 }
855
856 return snd_soc_get_volsw(kcontrol, ucontrol);
857 }
858
859 static int twl6040_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
860 struct snd_ctl_elem_value *ucontrol)
861 {
862 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
863 struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
864 struct twl6040_output *out = NULL;
865 struct soc_mixer_control *mc =
866 (struct soc_mixer_control *)kcontrol->private_value;
867 int ret;
868 unsigned int reg = mc->reg;
869
870 /* For HS and HF we shadow the values and only actually write
871 * them out when active in order to ensure the amplifier comes on
872 * as quietly as possible. */
873 switch (reg) {
874 case TWL6040_REG_HFLGAIN:
875 case TWL6040_REG_HFRGAIN:
876 out = &twl6040_priv->handsfree;
877 break;
878 default:
879 break;
880 }
881
882 if (out) {
883 out->left_vol = ucontrol->value.integer.value[0];
884 out->right_vol = ucontrol->value.integer.value[1];
885 if (!out->active)
886 return 1;
887 }
888
889 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
890 if (ret < 0)
891 return ret;
892
893 return 1;
894 }
895
896 static int twl6040_get_volsw_2r(struct snd_kcontrol *kcontrol,
897 struct snd_ctl_elem_value *ucontrol)
898 {
899 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
900 struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
901 struct twl6040_output *out = &twl6040_priv->handsfree;
902 struct soc_mixer_control *mc =
903 (struct soc_mixer_control *)kcontrol->private_value;
904 unsigned int reg = mc->reg;
905
906 /* If these are cached registers use the cache */
907 switch (reg) {
908 case TWL6040_REG_HFLGAIN:
909 case TWL6040_REG_HFRGAIN:
910 out = &twl6040_priv->handsfree;
911 ucontrol->value.integer.value[0] = out->left_vol;
912 ucontrol->value.integer.value[1] = out->right_vol;
913 return 0;
914
915 default:
916 break;
917 }
918
919 return snd_soc_get_volsw_2r(kcontrol, ucontrol);
920 }
921
922 /* double control with volume update */
923 #define SOC_TWL6040_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax,\
924 xinvert, tlv_array)\
925 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
926 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
927 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
928 .tlv.p = (tlv_array), \
929 .info = snd_soc_info_volsw, .get = twl6040_get_volsw, \
930 .put = twl6040_put_volsw, \
931 .private_value = (unsigned long)&(struct soc_mixer_control) \
932 {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
933 .max = xmax, .platform_max = xmax, .invert = xinvert} }
934
935 /* double control with volume update */
936 #define SOC_TWL6040_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax,\
937 xinvert, tlv_array)\
938 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
939 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
940 SNDRV_CTL_ELEM_ACCESS_READWRITE | \
941 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
942 .tlv.p = (tlv_array), \
943 .info = snd_soc_info_volsw_2r, \
944 .get = twl6040_get_volsw_2r, .put = twl6040_put_volsw_2r_vu, \
945 .private_value = (unsigned long)&(struct soc_mixer_control) \
946 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
947 .rshift = xshift, .max = xmax, .invert = xinvert}, }
948
419 /* 949 /*
420 * MICATT volume control: 950 * MICATT volume control:
421 * from -6 to 0 dB in 6 dB steps 951 * from -6 to 0 dB in 6 dB steps
422 */ 952 */
423 static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0); 953 static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
424 954
425 /* 955 /*
426 * MICGAIN volume control: 956 * MICGAIN volume control:
427 * from 6 to 30 dB in 6 dB steps 957 * from -6 to 30 dB in 6 dB steps
428 */ 958 */
429 static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0); 959 static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -600, 600, 0);
960
961 /*
962 * AFMGAIN volume control:
963 * from 18 to 24 dB in 6 dB steps
964 */
965 static DECLARE_TLV_DB_SCALE(afm_amp_tlv, 1800, 600, 0);
430 966
431 /* 967 /*
432 * HSGAIN volume control: 968 * HSGAIN volume control:
433 * from -30 to 0 dB in 2 dB steps 969 * from -30 to 0 dB in 2 dB steps
434 */ 970 */
435 static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0); 971 static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0);
436 972
437 /* 973 /*
438 * HFGAIN volume control: 974 * HFGAIN volume control:
439 * from -52 to 6 dB in 2 dB steps 975 * from -52 to 6 dB in 2 dB steps
440 */ 976 */
441 static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0); 977 static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0);
442 978
443 /* 979 /*
444 * EPGAIN volume control: 980 * EPGAIN volume control:
445 * from -24 to 6 dB in 2 dB steps 981 * from -24 to 6 dB in 2 dB steps
446 */ 982 */
447 static DECLARE_TLV_DB_SCALE(ep_tlv, -2400, 200, 0); 983 static DECLARE_TLV_DB_SCALE(ep_tlv, -2400, 200, 0);
448 984
449 /* Left analog microphone selection */ 985 /* Left analog microphone selection */
450 static const char *twl6040_amicl_texts[] = 986 static const char *twl6040_amicl_texts[] =
451 {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"}; 987 {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"};
452 988
453 /* Right analog microphone selection */ 989 /* Right analog microphone selection */
454 static const char *twl6040_amicr_texts[] = 990 static const char *twl6040_amicr_texts[] =
455 {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"}; 991 {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
456 992
457 static const struct soc_enum twl6040_enum[] = { 993 static const struct soc_enum twl6040_enum[] = {
458 » SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 3, twl6040_amicl_texts), 994 » SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 4, twl6040_amicl_texts),
459 » SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 3, twl6040_amicr_texts), 995 » SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 4, twl6040_amicr_texts),
996 };
997
998 static const char *twl6040_hs_texts[] = {
999 » "Off", "HS DAC", "Line-In amp"
1000 };
1001
1002 static const struct soc_enum twl6040_hs_enum[] = {
1003 » SOC_ENUM_SINGLE(TWL6040_REG_HSLCTL, 5, ARRAY_SIZE(twl6040_hs_texts),
1004 » » » twl6040_hs_texts),
1005 » SOC_ENUM_SINGLE(TWL6040_REG_HSRCTL, 5, ARRAY_SIZE(twl6040_hs_texts),
1006 » » » twl6040_hs_texts),
1007 };
1008
1009 static const char *twl6040_hf_texts[] = {
1010 » "Off", "HF DAC", "Line-In amp"
1011 };
1012
1013 static const struct soc_enum twl6040_hf_enum[] = {
1014 » SOC_ENUM_SINGLE(TWL6040_REG_HFLCTL, 2, ARRAY_SIZE(twl6040_hf_texts),
1015 » » » twl6040_hf_texts),
1016 » SOC_ENUM_SINGLE(TWL6040_REG_HFRCTL, 2, ARRAY_SIZE(twl6040_hf_texts),
1017 » » » twl6040_hf_texts),
460 }; 1018 };
461 1019
462 static const struct snd_kcontrol_new amicl_control = 1020 static const struct snd_kcontrol_new amicl_control =
463 SOC_DAPM_ENUM("Route", twl6040_enum[0]); 1021 SOC_DAPM_ENUM("Route", twl6040_enum[0]);
464 1022
465 static const struct snd_kcontrol_new amicr_control = 1023 static const struct snd_kcontrol_new amicr_control =
466 SOC_DAPM_ENUM("Route", twl6040_enum[1]); 1024 SOC_DAPM_ENUM("Route", twl6040_enum[1]);
467 1025
468 /* Headset DAC playback switches */ 1026 /* Headset DAC playback switches */
469 static const struct snd_kcontrol_new hsdacl_switch_controls = 1027 static const struct snd_kcontrol_new hsl_mux_controls =
470 » SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 5, 1, 0); 1028 » SOC_DAPM_ENUM("Route", twl6040_hs_enum[0]);
471 1029
472 static const struct snd_kcontrol_new hsdacr_switch_controls = 1030 static const struct snd_kcontrol_new hsr_mux_controls =
473 » SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 5, 1, 0); 1031 » SOC_DAPM_ENUM("Route", twl6040_hs_enum[1]);
474 1032
475 /* Handsfree DAC playback switches */ 1033 /* Handsfree DAC playback switches */
476 static const struct snd_kcontrol_new hfdacl_switch_controls = 1034 static const struct snd_kcontrol_new hfl_mux_controls =
477 » SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 2, 1, 0); 1035 » SOC_DAPM_ENUM("Route", twl6040_hf_enum[0]);
478 1036
479 static const struct snd_kcontrol_new hfdacr_switch_controls = 1037 static const struct snd_kcontrol_new hfr_mux_controls =
480 » SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 2, 1, 0); 1038 » SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
481 1039
482 static const struct snd_kcontrol_new ep_driver_switch_controls = 1040 static const struct snd_kcontrol_new ep_driver_switch_controls =
483 SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0); 1041 SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
484 1042
485 static const struct snd_kcontrol_new twl6040_snd_controls[] = { 1043 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
486 /* Capture gains */ 1044 /* Capture gains */
487 SOC_DOUBLE_TLV("Capture Preamplifier Volume", 1045 SOC_DOUBLE_TLV("Capture Preamplifier Volume",
488 TWL6040_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv), 1046 TWL6040_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv),
489 SOC_DOUBLE_TLV("Capture Volume", 1047 SOC_DOUBLE_TLV("Capture Volume",
490 TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv), 1048 TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv),
491 1049
1050 /* AFM gains */
1051 SOC_DOUBLE_TLV("Aux FM Volume",
1052 TWL6040_REG_LINEGAIN, 0, 4, 0xF, 0, afm_amp_tlv),
1053
492 /* Playback gains */ 1054 /* Playback gains */
493 » SOC_DOUBLE_TLV("Headset Playback Volume", 1055 » SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume",
494 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv), 1056 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
495 » SOC_DOUBLE_R_TLV("Handsfree Playback Volume", 1057 » SOC_TWL6040_DOUBLE_R_TLV("Handsfree Playback Volume",
496 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv), 1058 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
497 SOC_SINGLE_TLV("Earphone Playback Volume", 1059 SOC_SINGLE_TLV("Earphone Playback Volume",
498 TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv), 1060 TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
499 }; 1061 };
500 1062
501 static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { 1063 static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
502 /* Inputs */ 1064 /* Inputs */
503 SND_SOC_DAPM_INPUT("MAINMIC"), 1065 SND_SOC_DAPM_INPUT("MAINMIC"),
504 SND_SOC_DAPM_INPUT("HSMIC"), 1066 SND_SOC_DAPM_INPUT("HSMIC"),
505 SND_SOC_DAPM_INPUT("SUBMIC"), 1067 SND_SOC_DAPM_INPUT("SUBMIC"),
(...skipping 12 matching lines...) Expand all
518 SND_SOC_NOPM, 0, 0, &amicl_control), 1080 SND_SOC_NOPM, 0, 0, &amicl_control),
519 SND_SOC_DAPM_MUX("Analog Right Capture Route", 1081 SND_SOC_DAPM_MUX("Analog Right Capture Route",
520 SND_SOC_NOPM, 0, 0, &amicr_control), 1082 SND_SOC_NOPM, 0, 0, &amicr_control),
521 1083
522 /* Analog capture PGAs */ 1084 /* Analog capture PGAs */
523 SND_SOC_DAPM_PGA("MicAmpL", 1085 SND_SOC_DAPM_PGA("MicAmpL",
524 TWL6040_REG_MICLCTL, 0, 0, NULL, 0), 1086 TWL6040_REG_MICLCTL, 0, 0, NULL, 0),
525 SND_SOC_DAPM_PGA("MicAmpR", 1087 SND_SOC_DAPM_PGA("MicAmpR",
526 TWL6040_REG_MICRCTL, 0, 0, NULL, 0), 1088 TWL6040_REG_MICRCTL, 0, 0, NULL, 0),
527 1089
1090 /* Auxiliary FM PGAs */
1091 SND_SOC_DAPM_PGA("AFMAmpL",
1092 TWL6040_REG_MICLCTL, 1, 0, NULL, 0),
1093 SND_SOC_DAPM_PGA("AFMAmpR",
1094 TWL6040_REG_MICRCTL, 1, 0, NULL, 0),
1095
528 /* ADCs */ 1096 /* ADCs */
529 SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture", 1097 SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture",
530 TWL6040_REG_MICLCTL, 2, 0), 1098 TWL6040_REG_MICLCTL, 2, 0),
531 SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture", 1099 SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture",
532 TWL6040_REG_MICRCTL, 2, 0), 1100 TWL6040_REG_MICRCTL, 2, 0),
533 1101
534 /* Microphone bias */ 1102 /* Microphone bias */
535 SND_SOC_DAPM_MICBIAS("Headset Mic Bias", 1103 SND_SOC_DAPM_MICBIAS("Headset Mic Bias",
536 TWL6040_REG_AMICBCTL, 0, 0), 1104 TWL6040_REG_AMICBCTL, 0, 0),
537 SND_SOC_DAPM_MICBIAS("Main Mic Bias", 1105 SND_SOC_DAPM_MICBIAS("Main Mic Bias",
(...skipping 14 matching lines...) Expand all
552 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1120 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
553 SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback", 1121 SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
554 TWL6040_REG_HFLCTL, 0, 0, 1122 TWL6040_REG_HFLCTL, 0, 0,
555 twl6040_power_mode_event, 1123 twl6040_power_mode_event,
556 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1124 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
557 SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback", 1125 SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
558 TWL6040_REG_HFRCTL, 0, 0, 1126 TWL6040_REG_HFRCTL, 0, 0,
559 twl6040_power_mode_event, 1127 twl6040_power_mode_event,
560 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1128 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
561 1129
562 » /* Analog playback switches */ 1130 » SND_SOC_DAPM_MUX("HF Left Playback",
563 » SND_SOC_DAPM_SWITCH("HSDAC Left Playback", 1131 » » » SND_SOC_NOPM, 0, 0, &hfl_mux_controls),
564 » » » SND_SOC_NOPM, 0, 0, &hsdacl_switch_controls), 1132 » SND_SOC_DAPM_MUX("HF Right Playback",
565 » SND_SOC_DAPM_SWITCH("HSDAC Right Playback", 1133 » » » SND_SOC_NOPM, 0, 0, &hfr_mux_controls),
566 » » » SND_SOC_NOPM, 0, 0, &hsdacr_switch_controls), 1134 » /* Analog playback Muxes */
567 » SND_SOC_DAPM_SWITCH("HFDAC Left Playback", 1135 » SND_SOC_DAPM_MUX("HS Left Playback",
568 » » » SND_SOC_NOPM, 0, 0, &hfdacl_switch_controls), 1136 » » » SND_SOC_NOPM, 0, 0, &hsl_mux_controls),
569 » SND_SOC_DAPM_SWITCH("HFDAC Right Playback", 1137 » SND_SOC_DAPM_MUX("HS Right Playback",
570 » » » SND_SOC_NOPM, 0, 0, &hfdacr_switch_controls), 1138 » » » SND_SOC_NOPM, 0, 0, &hsr_mux_controls),
571 1139
572 /* Analog playback drivers */ 1140 /* Analog playback drivers */
573 » SND_SOC_DAPM_PGA_E("Handsfree Left Driver", 1141 » SND_SOC_DAPM_OUT_DRV_E("Handsfree Left Driver",
574 TWL6040_REG_HFLCTL, 4, 0, NULL, 0, 1142 TWL6040_REG_HFLCTL, 4, 0, NULL, 0,
575 » » » twl6040_power_mode_event, 1143 » » » pga_event,
576 » » » SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1144 » » » SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
577 » SND_SOC_DAPM_PGA_E("Handsfree Right Driver", 1145 » SND_SOC_DAPM_OUT_DRV_E("Handsfree Right Driver",
578 TWL6040_REG_HFRCTL, 4, 0, NULL, 0, 1146 TWL6040_REG_HFRCTL, 4, 0, NULL, 0,
579 » » » twl6040_power_mode_event, 1147 » » » pga_event,
580 » » » SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1148 » » » SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
581 » SND_SOC_DAPM_PGA("Headset Left Driver", 1149 » SND_SOC_DAPM_OUT_DRV_E("Headset Left Driver",
582 » » » TWL6040_REG_HSLCTL, 2, 0, NULL, 0), 1150 » » » TWL6040_REG_HSLCTL, 2, 0, NULL, 0,
583 » SND_SOC_DAPM_PGA("Headset Right Driver", 1151 » » » pga_event,
584 » » » TWL6040_REG_HSRCTL, 2, 0, NULL, 0), 1152 » » » SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
1153 » SND_SOC_DAPM_OUT_DRV_E("Headset Right Driver",
1154 » » » TWL6040_REG_HSRCTL, 2, 0, NULL, 0,
1155 » » » pga_event,
1156 » » » SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
585 SND_SOC_DAPM_SWITCH_E("Earphone Driver", 1157 SND_SOC_DAPM_SWITCH_E("Earphone Driver",
586 SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls, 1158 SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls,
587 twl6040_power_mode_event, 1159 twl6040_power_mode_event,
588 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1160 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
589 1161
590 /* Analog playback PGAs */ 1162 /* Analog playback PGAs */
591 SND_SOC_DAPM_PGA("HFDAC Left PGA", 1163 SND_SOC_DAPM_PGA("HFDAC Left PGA",
592 TWL6040_REG_HFLCTL, 1, 0, NULL, 0), 1164 TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
593 SND_SOC_DAPM_PGA("HFDAC Right PGA", 1165 SND_SOC_DAPM_PGA("HFDAC Right PGA",
594 TWL6040_REG_HFRCTL, 1, 0, NULL, 0), 1166 TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
595 1167
596 }; 1168 };
597 1169
598 static const struct snd_soc_dapm_route intercon[] = { 1170 static const struct snd_soc_dapm_route intercon[] = {
599 /* Capture path */ 1171 /* Capture path */
600 {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, 1172 {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
601 {"Analog Left Capture Route", "Main Mic", "MAINMIC"}, 1173 {"Analog Left Capture Route", "Main Mic", "MAINMIC"},
602 {"Analog Left Capture Route", "Aux/FM Left", "AFML"}, 1174 {"Analog Left Capture Route", "Aux/FM Left", "AFML"},
603 1175
604 {"Analog Right Capture Route", "Headset Mic", "HSMIC"}, 1176 {"Analog Right Capture Route", "Headset Mic", "HSMIC"},
605 {"Analog Right Capture Route", "Sub Mic", "SUBMIC"}, 1177 {"Analog Right Capture Route", "Sub Mic", "SUBMIC"},
606 {"Analog Right Capture Route", "Aux/FM Right", "AFMR"}, 1178 {"Analog Right Capture Route", "Aux/FM Right", "AFMR"},
607 1179
608 {"MicAmpL", NULL, "Analog Left Capture Route"}, 1180 {"MicAmpL", NULL, "Analog Left Capture Route"},
609 {"MicAmpR", NULL, "Analog Right Capture Route"}, 1181 {"MicAmpR", NULL, "Analog Right Capture Route"},
610 1182
611 {"ADC Left", NULL, "MicAmpL"}, 1183 {"ADC Left", NULL, "MicAmpL"},
612 {"ADC Right", NULL, "MicAmpR"}, 1184 {"ADC Right", NULL, "MicAmpR"},
613 1185
614 » /* Headset playback path */ 1186 » /* AFM path */
615 » {"HSDAC Left Playback", "Switch", "HSDAC Left"}, 1187 » {"AFMAmpL", "NULL", "AFML"},
616 » {"HSDAC Right Playback", "Switch", "HSDAC Right"}, 1188 » {"AFMAmpR", "NULL", "AFMR"},
617 1189
618 » {"Headset Left Driver", NULL, "HSDAC Left Playback"}, 1190 » {"HS Left Playback", "HS DAC", "HSDAC Left"},
619 » {"Headset Right Driver", NULL, "HSDAC Right Playback"}, 1191 » {"HS Left Playback", "Line-In amp", "AFMAmpL"},
1192
1193 » {"HS Right Playback", "HS DAC", "HSDAC Right"},
1194 » {"HS Right Playback", "Line-In amp", "AFMAmpR"},
1195
1196 » {"Headset Left Driver", "NULL", "HS Left Playback"},
1197 » {"Headset Right Driver", "NULL", "HS Right Playback"},
620 1198
621 {"HSOL", NULL, "Headset Left Driver"}, 1199 {"HSOL", NULL, "Headset Left Driver"},
622 {"HSOR", NULL, "Headset Right Driver"}, 1200 {"HSOR", NULL, "Headset Right Driver"},
623 1201
624 /* Earphone playback path */ 1202 /* Earphone playback path */
625 {"Earphone Driver", "Switch", "HSDAC Left"}, 1203 {"Earphone Driver", "Switch", "HSDAC Left"},
626 {"EP", NULL, "Earphone Driver"}, 1204 {"EP", NULL, "Earphone Driver"},
627 1205
628 » /* Handsfree playback path */ 1206 » {"HF Left Playback", "HF DAC", "HFDAC Left"},
629 » {"HFDAC Left Playback", "Switch", "HFDAC Left"}, 1207 » {"HF Left Playback", "Line-In amp", "AFMAmpL"},
630 » {"HFDAC Right Playback", "Switch", "HFDAC Right"},
631 1208
632 » {"HFDAC Left PGA", NULL, "HFDAC Left Playback"}, 1209 » {"HF Right Playback", "HF DAC", "HFDAC Right"},
633 » {"HFDAC Right PGA", NULL, "HFDAC Right Playback"}, 1210 » {"HF Right Playback", "Line-In amp", "AFMAmpR"},
1211
1212 » {"HFDAC Left PGA", NULL, "HF Left Playback"},
1213 » {"HFDAC Right PGA", NULL, "HF Right Playback"},
634 1214
635 {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"}, 1215 {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
636 {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"}, 1216 {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
637 1217
638 {"HFL", NULL, "Handsfree Left Driver"}, 1218 {"HFL", NULL, "Handsfree Left Driver"},
639 {"HFR", NULL, "Handsfree Right Driver"}, 1219 {"HFR", NULL, "Handsfree Right Driver"},
640 }; 1220 };
641 1221
642 static int twl6040_add_widgets(struct snd_soc_codec *codec) 1222 static int twl6040_add_widgets(struct snd_soc_codec *codec)
643 { 1223 {
644 » snd_soc_dapm_new_controls(codec, twl6040_dapm_widgets, 1224 » struct snd_soc_dapm_context *dapm = &codec->dapm;
1225
1226 » snd_soc_dapm_new_controls(dapm, twl6040_dapm_widgets,
645 ARRAY_SIZE(twl6040_dapm_widgets)); 1227 ARRAY_SIZE(twl6040_dapm_widgets));
646 1228 » snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
647 » snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 1229 » snd_soc_dapm_new_widgets(dapm);
648
649 » snd_soc_dapm_new_widgets(codec);
650 1230
651 return 0; 1231 return 0;
652 } 1232 }
653 1233
654 static int twl6040_power_up_completion(struct snd_soc_codec *codec, 1234 static int twl6040_power_up_completion(struct snd_soc_codec *codec,
655 int naudint) 1235 int naudint)
656 { 1236 {
657 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1237 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
658 int time_left; 1238 int time_left;
659 u8 intid; 1239 u8 intid;
660 1240
661 time_left = wait_for_completion_timeout(&priv->ready, 1241 time_left = wait_for_completion_timeout(&priv->ready,
662 » » » » msecs_to_jiffies(48)); 1242 » » » » msecs_to_jiffies(144));
663 1243
664 if (!time_left) { 1244 if (!time_left) {
665 » » twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid, 1245 » » twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid,
666 TWL6040_REG_INTID); 1246 TWL6040_REG_INTID);
667 if (!(intid & TWL6040_READYINT)) { 1247 if (!(intid & TWL6040_READYINT)) {
668 dev_err(codec->dev, "timeout waiting for READYINT\n"); 1248 dev_err(codec->dev, "timeout waiting for READYINT\n");
669 return -ETIMEDOUT; 1249 return -ETIMEDOUT;
670 } 1250 }
671 } 1251 }
672 1252
673 priv->codec_powered = 1; 1253 priv->codec_powered = 1;
674 1254
675 return 0; 1255 return 0;
(...skipping 30 matching lines...) Expand all
706 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL); 1286 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
707 twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL); 1287 twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL);
708 } else { 1288 } else {
709 /* use manual power-up sequence */ 1289 /* use manual power-up sequence */
710 twl6040_power_up(codec); 1290 twl6040_power_up(codec);
711 priv->codec_powered = 1; 1291 priv->codec_powered = 1;
712 } 1292 }
713 1293
714 /* initialize vdd/vss registers with reg_cache */ 1294 /* initialize vdd/vss registers with reg_cache */
715 twl6040_init_vdd_regs(codec); 1295 twl6040_init_vdd_regs(codec);
1296
1297 /* Set external boost GPO */
1298 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);
716 break; 1305 break;
717 case SND_SOC_BIAS_OFF: 1306 case SND_SOC_BIAS_OFF:
718 if (!priv->codec_powered) 1307 if (!priv->codec_powered)
719 break; 1308 break;
720 1309
721 if (gpio_is_valid(audpwron)) { 1310 if (gpio_is_valid(audpwron)) {
722 /* use AUDPWRON line */ 1311 /* use AUDPWRON line */
723 gpio_set_value(audpwron, 0); 1312 gpio_set_value(audpwron, 0);
724 1313
725 /* power-down sequence latency */ 1314 /* power-down sequence latency */
726 udelay(500); 1315 udelay(500);
727 1316
728 /* sync registers updated during power-down sequence */ 1317 /* sync registers updated during power-down sequence */
729 twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL); 1318 twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
730 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL); 1319 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
731 twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL, 1320 twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL,
732 0x00); 1321 0x00);
733 } else { 1322 } else {
734 /* use manual power-down sequence */ 1323 /* use manual power-down sequence */
735 twl6040_power_down(codec); 1324 twl6040_power_down(codec);
736 } 1325 }
737 1326
738 priv->codec_powered = 0; 1327 priv->codec_powered = 0;
739 break; 1328 break;
740 } 1329 }
741 1330
742 » codec->bias_level = level; 1331 » codec->dapm.bias_level = level;
743 1332
744 return 0; 1333 return 0;
745 } 1334 }
746 1335
747 /* set of rates for each pll: low-power and high-performance */ 1336 /* set of rates for each pll: low-power and high-performance */
748 1337
749 static unsigned int lp_rates[] = { 1338 static unsigned int lp_rates[] = {
750 88200, 1339 88200,
751 96000, 1340 96000,
752 }; 1341 };
(...skipping 12 matching lines...) Expand all
765 .list = hp_rates, 1354 .list = hp_rates,
766 }; 1355 };
767 1356
768 static int twl6040_startup(struct snd_pcm_substream *substream, 1357 static int twl6040_startup(struct snd_pcm_substream *substream,
769 struct snd_soc_dai *dai) 1358 struct snd_soc_dai *dai)
770 { 1359 {
771 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1360 struct snd_soc_pcm_runtime *rtd = substream->private_data;
772 struct snd_soc_codec *codec = rtd->codec; 1361 struct snd_soc_codec *codec = rtd->codec;
773 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1362 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
774 1363
775 if (!priv->sysclk) {
776 dev_err(codec->dev,
777 "no mclk configured, call set_sysclk() on init\n");
778 return -EINVAL;
779 }
780
781 /*
782 * capture is not supported at 17.64 MHz,
783 * it's reserved for headset low-power playback scenario
784 */
785 if ((priv->sysclk == 17640000) && substream->stream) {
786 dev_err(codec->dev,
787 "capture mode is not supported at %dHz\n",
788 priv->sysclk);
789 return -EINVAL;
790 }
791
792 snd_pcm_hw_constraint_list(substream->runtime, 0, 1364 snd_pcm_hw_constraint_list(substream->runtime, 0,
793 SNDRV_PCM_HW_PARAM_RATE, 1365 SNDRV_PCM_HW_PARAM_RATE,
794 priv->sysclk_constraints); 1366 priv->sysclk_constraints);
795 1367
796 return 0; 1368 return 0;
797 } 1369 }
798 1370
799 static int twl6040_hw_params(struct snd_pcm_substream *substream, 1371 static int twl6040_hw_params(struct snd_pcm_substream *substream,
800 struct snd_pcm_hw_params *params, 1372 struct snd_pcm_hw_params *params,
801 struct snd_soc_dai *dai) 1373 struct snd_soc_dai *dai)
802 { 1374 {
803 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1375 struct snd_soc_pcm_runtime *rtd = substream->private_data;
804 struct snd_soc_codec *codec = rtd->codec; 1376 struct snd_soc_codec *codec = rtd->codec;
805 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1377 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
806 u8 lppllctl; 1378 u8 lppllctl;
807 int rate; 1379 int rate;
808 1380
809 /* nothing to do for high-perf pll, it supports only 48 kHz */ 1381 /* nothing to do for high-perf pll, it supports only 48 kHz */
810 if (priv->pll == TWL6040_HPPLL_ID) 1382 if (priv->pll == TWL6040_HPPLL_ID)
811 return 0; 1383 return 0;
812 1384
813 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL); 1385 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
814 1386
815 rate = params_rate(params); 1387 rate = params_rate(params);
816 switch (rate) { 1388 switch (rate) {
1389 case 11250:
1390 case 22500:
1391 case 44100:
817 case 88200: 1392 case 88200:
818 lppllctl |= TWL6040_LPLLFIN; 1393 lppllctl |= TWL6040_LPLLFIN;
819 priv->sysclk = 17640000; 1394 priv->sysclk = 17640000;
820 break; 1395 break;
1396 case 8000:
1397 case 16000:
1398 case 32000:
1399 case 48000:
821 case 96000: 1400 case 96000:
822 lppllctl &= ~TWL6040_LPLLFIN; 1401 lppllctl &= ~TWL6040_LPLLFIN;
823 priv->sysclk = 19200000; 1402 priv->sysclk = 19200000;
824 break; 1403 break;
825 default: 1404 default:
826 dev_err(codec->dev, "unsupported rate %d\n", rate); 1405 dev_err(codec->dev, "unsupported rate %d\n", rate);
827 return -EINVAL; 1406 return -EINVAL;
828 } 1407 }
829 1408
830 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); 1409 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
831 1410
832 return 0; 1411 return 0;
833 } 1412 }
834 1413
835 static int twl6040_trigger(struct snd_pcm_substream *substream, 1414 static int twl6040_prepare(struct snd_pcm_substream *substream,
836 » » » int cmd, struct snd_soc_dai *dai) 1415 » » » struct snd_soc_dai *dai)
837 { 1416 {
838 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1417 struct snd_soc_pcm_runtime *rtd = substream->private_data;
839 struct snd_soc_codec *codec = rtd->codec; 1418 struct snd_soc_codec *codec = rtd->codec;
840 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1419 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
841 1420
842 » switch (cmd) { 1421 » if (!priv->sysclk) {
843 » case SNDRV_PCM_TRIGGER_START: 1422 » » dev_err(codec->dev,
844 » case SNDRV_PCM_TRIGGER_RESUME: 1423 » » » "no mclk configured, call set_sysclk() on init\n");
845 » » /* 1424 » » return -EINVAL;
846 » » * low-power playback mode is restricted 1425 » }
847 » » * for headset path only 1426
848 » » */ 1427 » /*
849 » » if ((priv->sysclk == 17640000) && priv->non_lp) { 1428 » * capture is not supported at 17.64 MHz,
1429 » * it's reserved for headset low-power playback scenario
1430 » */
1431 » if ((priv->sysclk == 17640000) &&
1432 » » » substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1433 » » dev_err(codec->dev,
1434 » » » "capture mode is not supported at %dHz\n",
1435 » » » priv->sysclk);
1436 » » return -EINVAL;
1437 » }
1438
1439 » if ((priv->sysclk == 17640000) && priv->non_lp) {
850 dev_err(codec->dev, 1440 dev_err(codec->dev,
851 "some enabled paths aren't supported at %dHz\n", 1441 "some enabled paths aren't supported at %dHz\n",
852 priv->sysclk); 1442 priv->sysclk);
853 return -EPERM; 1443 return -EPERM;
854 }
855 break;
856 default:
857 break;
858 } 1444 }
859
860 return 0; 1445 return 0;
861 } 1446 }
862 1447
863 static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, 1448 static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
864 int clk_id, unsigned int freq, int dir) 1449 int clk_id, unsigned int freq, int dir)
865 { 1450 {
866 struct snd_soc_codec *codec = codec_dai->codec; 1451 struct snd_soc_codec *codec = codec_dai->codec;
867 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1452 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
868 u8 hppllctl, lppllctl; 1453 u8 hppllctl, lppllctl;
869 1454
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 dev_err(codec->dev, "unknown clk_id %d\n", clk_id); 1548 dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
964 return -EINVAL; 1549 return -EINVAL;
965 } 1550 }
966 1551
967 return 0; 1552 return 0;
968 } 1553 }
969 1554
970 static struct snd_soc_dai_ops twl6040_dai_ops = { 1555 static struct snd_soc_dai_ops twl6040_dai_ops = {
971 .startup = twl6040_startup, 1556 .startup = twl6040_startup,
972 .hw_params = twl6040_hw_params, 1557 .hw_params = twl6040_hw_params,
973 » .trigger» = twl6040_trigger, 1558 » .prepare» = twl6040_prepare,
974 .set_sysclk = twl6040_set_dai_sysclk, 1559 .set_sysclk = twl6040_set_dai_sysclk,
975 }; 1560 };
976 1561
977 static struct snd_soc_dai_driver twl6040_dai = { 1562 static struct snd_soc_dai_driver twl6040_dai = {
978 .name = "twl6040-hifi", 1563 .name = "twl6040-hifi",
979 .playback = { 1564 .playback = {
980 .stream_name = "Playback", 1565 .stream_name = "Playback",
981 .channels_min = 1, 1566 .channels_min = 1,
982 .channels_max = 4, 1567 .channels_max = 4,
983 .rates = TWL6040_RATES, 1568 .rates = TWL6040_RATES,
(...skipping 13 matching lines...) Expand all
997 static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state) 1582 static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
998 { 1583 {
999 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); 1584 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1000 1585
1001 return 0; 1586 return 0;
1002 } 1587 }
1003 1588
1004 static int twl6040_resume(struct snd_soc_codec *codec) 1589 static int twl6040_resume(struct snd_soc_codec *codec)
1005 { 1590 {
1006 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1591 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1592 twl6040_set_bias_level(codec, codec->dapm.suspend_bias_level);
1007 1593
1008 return 0; 1594 return 0;
1009 } 1595 }
1010 #else 1596 #else
1011 #define twl6040_suspend NULL 1597 #define twl6040_suspend NULL
1012 #define twl6040_resume NULL 1598 #define twl6040_resume NULL
1013 #endif 1599 #endif
1014 1600
1015 static int twl6040_probe(struct snd_soc_codec *codec) 1601 static int twl6040_probe(struct snd_soc_codec *codec)
1016 { 1602 {
1017 struct twl4030_codec_data *twl_codec = codec->dev->platform_data; 1603 struct twl4030_codec_data *twl_codec = codec->dev->platform_data;
1018 struct twl6040_data *priv; 1604 struct twl6040_data *priv;
1019 int audpwron, naudint; 1605 int audpwron, naudint;
1020 int ret = 0; 1606 int ret = 0;
1607 u8 icrev, intmr = TWL6040_ALLINT_MSK;
1021 1608
1022 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); 1609 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
1023 if (priv == NULL) 1610 if (priv == NULL)
1024 return -ENOMEM; 1611 return -ENOMEM;
1025 snd_soc_codec_set_drvdata(codec, priv); 1612 snd_soc_codec_set_drvdata(codec, priv);
1026 1613
1027 » if (twl_codec) { 1614 » priv->codec = codec;
1615
1616 » twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &icrev, TWL6040_REG_ASICREV);
1617
1618 » if (twl_codec && (icrev > 0))
1028 audpwron = twl_codec->audpwron_gpio; 1619 audpwron = twl_codec->audpwron_gpio;
1620 else
1621 audpwron = -EINVAL;
1622
1623 if (twl_codec)
1029 naudint = twl_codec->naudint_irq; 1624 naudint = twl_codec->naudint_irq;
1030 » } else { 1625 » else
1031 » » audpwron = -EINVAL;
1032 naudint = 0; 1626 naudint = 0;
1033 }
1034 1627
1035 priv->audpwron = audpwron; 1628 priv->audpwron = audpwron;
1036 priv->naudint = naudint; 1629 priv->naudint = naudint;
1630 priv->workqueue = create_singlethread_workqueue("twl6040-codec");
1631
1632 if (!priv->workqueue)
1633 goto work_err;
1634
1635 INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);
1636
1637 mutex_init(&priv->mutex);
1037 1638
1038 init_completion(&priv->ready); 1639 init_completion(&priv->ready);
1640 init_completion(&priv->headset.ramp_done);
1641 init_completion(&priv->handsfree.ramp_done);
1039 1642
1040 if (gpio_is_valid(audpwron)) { 1643 if (gpio_is_valid(audpwron)) {
1041 ret = gpio_request(audpwron, "audpwron"); 1644 ret = gpio_request(audpwron, "audpwron");
1042 if (ret) 1645 if (ret)
1043 goto gpio1_err; 1646 goto gpio1_err;
1044 1647
1045 ret = gpio_direction_output(audpwron, 0); 1648 ret = gpio_direction_output(audpwron, 0);
1046 if (ret) 1649 if (ret)
1047 goto gpio2_err; 1650 goto gpio2_err;
1048 1651
1049 priv->codec_powered = 0; 1652 priv->codec_powered = 0;
1653
1654 /* enable only codec ready interrupt */
1655 intmr &= ~(TWL6040_READYMSK | TWL6040_PLUGMSK);
1656
1657 /* reset interrupt status to allow correct power up sequence */
1658 twl6040_read_reg_volatile(codec, TWL6040_REG_INTID);
1050 } 1659 }
1660 twl6040_write(codec, TWL6040_REG_INTMR, intmr);
1051 1661
1052 if (naudint) { 1662 if (naudint) {
1053 /* audio interrupt */ 1663 /* audio interrupt */
1054 ret = request_threaded_irq(naudint, NULL, 1664 ret = request_threaded_irq(naudint, NULL,
1055 twl6040_naudint_handler, 1665 twl6040_naudint_handler,
1056 IRQF_TRIGGER_LOW | IRQF_ONESHOT, 1666 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
1057 "twl6040_codec", codec); 1667 "twl6040_codec", codec);
1058 if (ret) 1668 if (ret)
1059 goto gpio2_err; 1669 goto gpio2_err;
1060 } else {
1061 if (gpio_is_valid(audpwron)) {
1062 /* enable only codec ready interrupt */
1063 twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1064 ~TWL6040_READYMSK & TWL6040_ALLINT_MSK);
1065 } else {
1066 /* no interrupts at all */
1067 twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1068 TWL6040_ALLINT_MSK);
1069 }
1070 } 1670 }
1071 1671
1072 /* init vio registers */ 1672 /* init vio registers */
1073 twl6040_init_vio_regs(codec); 1673 twl6040_init_vio_regs(codec);
1074 1674
1675 priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
1676 if (priv->hf_workqueue == NULL) {
1677 ret = -ENOMEM;
1678 goto irq_err;
1679 }
1680 priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
1681 if (priv->hs_workqueue == NULL) {
1682 ret = -ENOMEM;
1683 goto wq_err;
1684 }
1685
1686 INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
1687 INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
1688
1075 /* power on device */ 1689 /* power on device */
1076 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1690 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1077 if (ret) 1691 if (ret)
1078 » » goto irq_err; 1692 » » goto bias_err;
1079 1693
1080 snd_soc_add_controls(codec, twl6040_snd_controls, 1694 snd_soc_add_controls(codec, twl6040_snd_controls,
1081 ARRAY_SIZE(twl6040_snd_controls)); 1695 ARRAY_SIZE(twl6040_snd_controls));
1082 twl6040_add_widgets(codec); 1696 twl6040_add_widgets(codec);
1083 1697
1084 return 0; 1698 return 0;
1085 1699
1700 bias_err:
1701 destroy_workqueue(priv->hs_workqueue);
1702 wq_err:
1703 destroy_workqueue(priv->hf_workqueue);
1086 irq_err: 1704 irq_err:
1087 if (naudint) 1705 if (naudint)
1088 free_irq(naudint, codec); 1706 free_irq(naudint, codec);
1089 gpio2_err: 1707 gpio2_err:
1090 if (gpio_is_valid(audpwron)) 1708 if (gpio_is_valid(audpwron))
1091 gpio_free(audpwron); 1709 gpio_free(audpwron);
1092 gpio1_err: 1710 gpio1_err:
1711 destroy_workqueue(priv->workqueue);
1712 work_err:
1093 kfree(priv); 1713 kfree(priv);
1094 return ret; 1714 return ret;
1095 } 1715 }
1096 1716
1097 static int twl6040_remove(struct snd_soc_codec *codec) 1717 static int twl6040_remove(struct snd_soc_codec *codec)
1098 { 1718 {
1099 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1719 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1100 int audpwron = priv->audpwron; 1720 int audpwron = priv->audpwron;
1101 int naudint = priv->naudint; 1721 int naudint = priv->naudint;
1102 1722
1103 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); 1723 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1104 1724
1105 if (gpio_is_valid(audpwron)) 1725 if (gpio_is_valid(audpwron))
1106 gpio_free(audpwron); 1726 gpio_free(audpwron);
1107 1727
1108 if (naudint) 1728 if (naudint)
1109 free_irq(naudint, codec); 1729 free_irq(naudint, codec);
1110 1730
1731 destroy_workqueue(priv->workqueue);
1732 destroy_workqueue(priv->hf_workqueue);
1733 destroy_workqueue(priv->hs_workqueue);
1111 kfree(priv); 1734 kfree(priv);
1112 1735
1113 return 0; 1736 return 0;
1114 } 1737 }
1115 1738
1116 static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { 1739 static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
1117 .probe = twl6040_probe, 1740 .probe = twl6040_probe,
1118 .remove = twl6040_remove, 1741 .remove = twl6040_remove,
1119 .suspend = twl6040_suspend, 1742 .suspend = twl6040_suspend,
1120 .resume = twl6040_resume, 1743 .resume = twl6040_resume,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 1778
1156 static void __exit twl6040_codec_exit(void) 1779 static void __exit twl6040_codec_exit(void)
1157 { 1780 {
1158 platform_driver_unregister(&twl6040_codec_driver); 1781 platform_driver_unregister(&twl6040_codec_driver);
1159 } 1782 }
1160 module_exit(twl6040_codec_exit); 1783 module_exit(twl6040_codec_exit);
1161 1784
1162 MODULE_DESCRIPTION("ASoC TWL6040 codec driver"); 1785 MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
1163 MODULE_AUTHOR("Misael Lopez Cruz"); 1786 MODULE_AUTHOR("Misael Lopez Cruz");
1164 MODULE_LICENSE("GPL"); 1787 MODULE_LICENSE("GPL");
OLDNEW
« no previous file with comments | « sound/soc/codecs/twl6040.h ('k') | sound/soc/codecs/uda134x.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698