2 * ALSA SoC TWL6040 codec driver
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/init.h>
25 #include <linux/delay.h>
27 #include <linux/i2c.h>
28 #include <linux/gpio.h>
29 #include <linux/platform_device.h>
30 #include <linux/slab.h>
31 #include <linux/i2c/twl.h>
33 #include <sound/core.h>
34 #include <sound/pcm.h>
35 #include <sound/pcm_params.h>
36 #include <sound/soc.h>
37 #include <sound/initval.h>
38 #include <sound/tlv.h>
42 #define TWL6040_RATES SNDRV_PCM_RATE_8000_96000
43 #define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
45 #define TWL6040_OUTHS_0dB 0x00
46 #define TWL6040_OUTHS_M30dB 0x0F
47 #define TWL6040_OUTHF_0dB 0x03
48 #define TWL6040_OUTHF_M52dB 0x1D
50 #define TWL6040_RAMP_NONE 0
51 #define TWL6040_RAMP_UP 1
52 #define TWL6040_RAMP_DOWN 2
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
61 struct twl6040_output
{
67 unsigned int step_delay
;
70 struct completion ramp_done
;
73 struct twl6040_jack_data
{
74 struct snd_soc_jack
*jack
;
78 /* codec private data */
86 struct snd_pcm_hw_constraint_list
*sysclk_constraints
;
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
;
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
;
102 * twl6040 register cache & default register settings
104 static const u8 twl6040_reg
[TWL6040_CACHEREGNUM
] = {
105 0x00, /* not used 0x00 */
106 0x4B, /* TWL6040_ASICID (ro) 0x01 */
107 0x00, /* TWL6040_ASICREV (ro) 0x02 */
108 0x00, /* TWL6040_INTID 0x03 */
109 0x00, /* TWL6040_INTMR 0x04 */
110 0x00, /* TWL6040_NCPCTRL 0x05 */
111 0x00, /* TWL6040_LDOCTL 0x06 */
112 0x60, /* TWL6040_HPPLLCTL 0x07 */
113 0x00, /* TWL6040_LPPLLCTL 0x08 */
114 0x4A, /* TWL6040_LPPLLDIV 0x09 */
115 0x00, /* TWL6040_AMICBCTL 0x0A */
116 0x00, /* TWL6040_DMICBCTL 0x0B */
117 0x18, /* TWL6040_MICLCTL 0x0C - No input selected on Left Mic */
118 0x18, /* TWL6040_MICRCTL 0x0D - No input selected on Right Mic */
119 0x00, /* TWL6040_MICGAIN 0x0E */
120 0x1B, /* TWL6040_LINEGAIN 0x0F */
121 0x00, /* TWL6040_HSLCTL 0x10 */
122 0x00, /* TWL6040_HSRCTL 0x11 */
123 0x00, /* TWL6040_HSGAIN 0x12 */
124 0x00, /* TWL6040_EARCTL 0x13 */
125 0x00, /* TWL6040_HFLCTL 0x14 */
126 0x00, /* TWL6040_HFLGAIN 0x15 */
127 0x00, /* TWL6040_HFRCTL 0x16 */
128 0x00, /* TWL6040_HFRGAIN 0x17 */
129 0x00, /* TWL6040_VIBCTLL 0x18 */
130 0x00, /* TWL6040_VIBDATL 0x19 */
131 0x00, /* TWL6040_VIBCTLR 0x1A */
132 0x00, /* TWL6040_VIBDATR 0x1B */
133 0x00, /* TWL6040_HKCTL1 0x1C */
134 0x00, /* TWL6040_HKCTL2 0x1D */
135 0x00, /* TWL6040_GPOCTL 0x1E */
136 0x00, /* TWL6040_ALB 0x1F */
137 0x00, /* TWL6040_DLB 0x20 */
138 0x00, /* not used 0x21 */
139 0x00, /* not used 0x22 */
140 0x00, /* not used 0x23 */
141 0x00, /* not used 0x24 */
142 0x00, /* not used 0x25 */
143 0x00, /* not used 0x26 */
144 0x00, /* not used 0x27 */
145 0x00, /* TWL6040_TRIM1 0x28 */
146 0x00, /* TWL6040_TRIM2 0x29 */
147 0x00, /* TWL6040_TRIM3 0x2A */
148 0x00, /* TWL6040_HSOTRIM 0x2B */
149 0x00, /* TWL6040_HFOTRIM 0x2C */
150 0x09, /* TWL6040_ACCCTL 0x2D */
151 0x00, /* TWL6040_STATUS (ro) 0x2E */
155 * twl6040 vio/gnd registers:
156 * registers under vio/gnd supply can be accessed
157 * before the power-up sequence, after NRESPWRON goes high
159 static const int twl6040_vio_reg
[TWL6040_VIOREGNUM
] = {
166 TWL6040_REG_AMICBCTL
,
167 TWL6040_REG_DMICBCTL
,
181 * twl6040 vdd/vss registers:
182 * registers under vdd/vss supplies can only be accessed
183 * after the power-up sequence
185 static const int twl6040_vdd_reg
[TWL6040_VDDREGNUM
] = {
186 TWL6040_REG_HPPLLCTL
,
187 TWL6040_REG_LPPLLCTL
,
188 TWL6040_REG_LPPLLDIV
,
192 TWL6040_REG_LINEGAIN
,
210 * read twl6040 register cache
212 static inline unsigned int twl6040_read_reg_cache(struct snd_soc_codec
*codec
,
215 u8
*cache
= codec
->reg_cache
;
217 if (reg
>= TWL6040_CACHEREGNUM
)
224 * write twl6040 register cache
226 static inline void twl6040_write_reg_cache(struct snd_soc_codec
*codec
,
229 u8
*cache
= codec
->reg_cache
;
231 if (reg
>= TWL6040_CACHEREGNUM
)
237 * read from twl6040 hardware register
239 static int twl6040_read_reg_volatile(struct snd_soc_codec
*codec
,
244 if (reg
>= TWL6040_CACHEREGNUM
)
247 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE
, &value
, reg
);
248 twl6040_write_reg_cache(codec
, reg
, value
);
254 * write to the twl6040 register space
256 static int twl6040_write(struct snd_soc_codec
*codec
,
257 unsigned int reg
, unsigned int value
)
259 if (reg
>= TWL6040_CACHEREGNUM
)
262 twl6040_write_reg_cache(codec
, reg
, value
);
263 return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE
, value
, reg
);
266 static void twl6040_init_vio_regs(struct snd_soc_codec
*codec
)
268 u8
*cache
= codec
->reg_cache
;
271 /* allow registers to be accessed by i2c */
272 twl6040_write(codec
, TWL6040_REG_ACCCTL
, cache
[TWL6040_REG_ACCCTL
]);
274 for (i
= 0; i
< TWL6040_VIOREGNUM
; i
++) {
275 reg
= twl6040_vio_reg
[i
];
276 /* skip read-only registers (ASICID, ASICREV, STATUS) */
278 case TWL6040_REG_ASICID
:
279 case TWL6040_REG_ASICREV
:
280 case TWL6040_REG_STATUS
:
285 twl6040_write(codec
, reg
, cache
[reg
]);
289 static void twl6040_init_vdd_regs(struct snd_soc_codec
*codec
)
291 u8
*cache
= codec
->reg_cache
;
294 for (i
= 0; i
< TWL6040_VDDREGNUM
; i
++) {
295 reg
= twl6040_vdd_reg
[i
];
296 twl6040_write(codec
, reg
, cache
[reg
]);
301 * Ramp HS PGA volume to minimise pops at stream startup and shutdown.
303 static inline int twl6040_hs_ramp_step(struct snd_soc_codec
*codec
,
304 unsigned int left_step
, unsigned int right_step
)
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;
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
);
317 if (headset
->ramp
== TWL6040_RAMP_UP
) {
319 if (val
< headset
->left_vol
) {
321 reg
&= ~TWL6040_HSL_VOL_MASK
;
322 twl6040_write(codec
, TWL6040_REG_HSGAIN
,
323 (reg
| (~val
& TWL6040_HSL_VOL_MASK
)));
327 } else if (headset
->ramp
== TWL6040_RAMP_DOWN
) {
331 reg
&= ~TWL6040_HSL_VOL_MASK
;
332 twl6040_write(codec
, TWL6040_REG_HSGAIN
, reg
|
333 (~val
& TWL6040_HSL_VOL_MASK
));
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
;
344 if (headset
->ramp
== TWL6040_RAMP_UP
) {
346 if (val
< headset
->right_vol
) {
348 reg
&= ~TWL6040_HSR_VOL_MASK
;
349 twl6040_write(codec
, TWL6040_REG_HSGAIN
,
350 (reg
| (~val
<< TWL6040_HSR_VOL_SHIFT
)));
354 } else if (headset
->ramp
== TWL6040_RAMP_DOWN
) {
358 reg
&= ~TWL6040_HSR_VOL_MASK
;
359 twl6040_write(codec
, TWL6040_REG_HSGAIN
,
360 reg
| (~val
<< TWL6040_HSR_VOL_SHIFT
));
366 return left_complete
& right_complete
;
370 * Ramp HF PGA volume to minimise pops at stream startup and shutdown.
372 static inline int twl6040_hf_ramp_step(struct snd_soc_codec
*codec
,
373 unsigned int left_step
, unsigned int right_step
)
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;
381 left_step
= (left_step
> 0x1D) ? 0x1D : left_step
;
382 reg
= twl6040_read_reg_cache(codec
, TWL6040_REG_HFLGAIN
);
384 val
= (reg
& TWL6040_HF_VOL_MASK
);
385 if (handsfree
->ramp
== TWL6040_RAMP_UP
) {
387 if (val
< handsfree
->left_vol
) {
389 reg
&= ~TWL6040_HF_VOL_MASK
;
390 twl6040_write(codec
, TWL6040_REG_HFLGAIN
,
395 } else if (handsfree
->ramp
== TWL6040_RAMP_DOWN
) {
399 reg
&= ~TWL6040_HF_VOL_MASK
;
400 twl6040_write(codec
, TWL6040_REG_HFLGAIN
,
408 right_step
= (right_step
> 0x1D) ? 0x1D : right_step
;
409 reg
= twl6040_read_reg_cache(codec
, TWL6040_REG_HFRGAIN
);
411 val
= (reg
& TWL6040_HF_VOL_MASK
);
412 if (handsfree
->ramp
== TWL6040_RAMP_UP
) {
414 if (val
< handsfree
->right_vol
) {
416 reg
&= ~TWL6040_HF_VOL_MASK
;
417 twl6040_write(codec
, TWL6040_REG_HFRGAIN
,
422 } else if (handsfree
->ramp
== TWL6040_RAMP_DOWN
) {
426 reg
&= ~TWL6040_HF_VOL_MASK
;
427 twl6040_write(codec
, TWL6040_REG_HFRGAIN
,
432 return left_complete
& right_complete
;
436 * This work ramps both output PGAs at stream start/stop time to
437 * minimise pop associated with DAPM power switching.
439 static void twl6040_pga_hs_work(struct work_struct
*work
)
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
;
448 /* do we need to ramp at all ? */
449 if (headset
->ramp
== TWL6040_RAMP_NONE
)
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
,
458 headset
->right_step
);
460 /* ramp finished ? */
461 if (headset_complete
)
465 * TODO: tune: delay is longer over 0dB
466 * as increases are larger.
469 schedule_timeout_interruptible(msecs_to_jiffies(delay
+
472 schedule_timeout_interruptible(msecs_to_jiffies(delay
));
475 if (headset
->ramp
== TWL6040_RAMP_DOWN
) {
477 complete(&headset
->ramp_done
);
481 headset
->ramp
= TWL6040_RAMP_NONE
;
484 static void twl6040_pga_hf_work(struct work_struct
*work
)
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
;
493 /* do we need to ramp at all ? */
494 if (handsfree
->ramp
== TWL6040_RAMP_NONE
)
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
);
505 /* ramp finished ? */
506 if (handsfree_complete
)
510 * TODO: tune: delay is longer over 0dB
511 * as increases are larger.
514 schedule_timeout_interruptible(msecs_to_jiffies(delay
+
517 schedule_timeout_interruptible(msecs_to_jiffies(delay
));
521 if (handsfree
->ramp
== TWL6040_RAMP_DOWN
) {
522 handsfree
->active
= 0;
523 complete(&handsfree
->ramp_done
);
525 handsfree
->active
= 1;
526 handsfree
->ramp
= TWL6040_RAMP_NONE
;
529 static int pga_event(struct snd_soc_dapm_widget
*w
,
530 struct snd_kcontrol
*kcontrol
, int event
)
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
;
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 */
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
))
561 case SND_SOC_DAPM_POST_PMU
:
565 /* don't use volume ramp for power-up */
566 out
->left_step
= out
->left_vol
;
567 out
->right_step
= out
->right_vol
;
569 if (!delayed_work_pending(work
)) {
570 out
->ramp
= TWL6040_RAMP_UP
;
571 queue_delayed_work(queue
, work
,
572 msecs_to_jiffies(1));
576 case SND_SOC_DAPM_PRE_PMD
:
580 if (!delayed_work_pending(work
)) {
581 /* use volume ramp for power-down */
584 out
->ramp
= TWL6040_RAMP_DOWN
;
585 INIT_COMPLETION(out
->ramp_done
);
587 queue_delayed_work(queue
, work
,
588 msecs_to_jiffies(1));
590 wait_for_completion_timeout(&out
->ramp_done
,
591 msecs_to_jiffies(2000));
599 /* twl6040 codec manual power-up sequence */
600 static void twl6040_power_up(struct snd_soc_codec
*codec
)
602 u8 ncpctl
, ldoctl
, lppllctl
, accctl
;
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
);
609 /* enable reference system */
610 ldoctl
|= TWL6040_REFENA
;
611 twl6040_write(codec
, TWL6040_REG_LDOCTL
, ldoctl
);
613 /* enable internal oscillator */
614 ldoctl
|= TWL6040_OSCENA
;
615 twl6040_write(codec
, TWL6040_REG_LDOCTL
, ldoctl
);
617 /* enable high-side ldo */
618 ldoctl
|= TWL6040_HSLDOENA
;
619 twl6040_write(codec
, TWL6040_REG_LDOCTL
, ldoctl
);
621 /* enable negative charge pump */
622 ncpctl
|= TWL6040_NCPENA
| TWL6040_NCPOPEN
;
623 twl6040_write(codec
, TWL6040_REG_NCPCTL
, ncpctl
);
625 /* enable low-side ldo */
626 ldoctl
|= TWL6040_LSLDOENA
;
627 twl6040_write(codec
, TWL6040_REG_LDOCTL
, ldoctl
);
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
);
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
);
643 /* twl6040 codec manual power-down sequence */
644 static void twl6040_power_down(struct snd_soc_codec
*codec
)
646 u8 ncpctl
, ldoctl
, lppllctl
, accctl
;
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
);
653 /* enable internal oscillator */
654 ldoctl
|= TWL6040_OSCENA
;
655 twl6040_write(codec
, TWL6040_REG_LDOCTL
, ldoctl
);
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
);
664 /* disable negative charge pump */
665 ncpctl
&= ~(TWL6040_NCPENA
| TWL6040_NCPOPEN
);
666 twl6040_write(codec
, TWL6040_REG_NCPCTL
, ncpctl
);
668 /* disable high-side ldo */
669 ldoctl
&= ~TWL6040_HSLDOENA
;
670 twl6040_write(codec
, TWL6040_REG_LDOCTL
, ldoctl
);
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
);
681 /* set headset dac and driver power mode */
682 static int headset_power_mode(struct snd_soc_codec
*codec
, int high_perf
)
685 int mask
= TWL6040_HSDRVMODEL
| TWL6040_HSDACMODEL
;
687 hslctl
= twl6040_read_reg_cache(codec
, TWL6040_REG_HSLCTL
);
688 hsrctl
= twl6040_read_reg_cache(codec
, TWL6040_REG_HSRCTL
);
698 twl6040_write(codec
, TWL6040_REG_HSLCTL
, hslctl
);
699 twl6040_write(codec
, TWL6040_REG_HSRCTL
, hsrctl
);
704 static int twl6040_hs_dac_event(struct snd_soc_dapm_widget
*w
,
705 struct snd_kcontrol
*kcontrol
, int event
)
711 static int twl6040_power_mode_event(struct snd_soc_dapm_widget
*w
,
712 struct snd_kcontrol
*kcontrol
, int event
)
714 struct snd_soc_codec
*codec
= w
->codec
;
715 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
717 if (SND_SOC_DAPM_EVENT_ON(event
))
727 static void twl6040_hs_jack_report(struct snd_soc_codec
*codec
,
728 struct snd_soc_jack
*jack
, int report
)
730 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
733 mutex_lock(&priv
->mutex
);
736 status
= twl6040_read_reg_volatile(codec
, TWL6040_REG_STATUS
);
737 if (status
& TWL6040_PLUGCOMP
)
738 snd_soc_jack_report(jack
, report
, report
);
740 snd_soc_jack_report(jack
, 0, report
);
742 mutex_unlock(&priv
->mutex
);
745 void twl6040_hs_jack_detect(struct snd_soc_codec
*codec
,
746 struct snd_soc_jack
*jack
, int report
)
748 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
749 struct twl6040_jack_data
*hs_jack
= &priv
->hs_jack
;
751 hs_jack
->jack
= jack
;
752 hs_jack
->report
= report
;
754 twl6040_hs_jack_report(codec
, hs_jack
->jack
, hs_jack
->report
);
756 EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect
);
758 static void twl6040_accessory_work(struct work_struct
*work
)
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
;
765 twl6040_hs_jack_report(codec
, hs_jack
->jack
, hs_jack
->report
);
768 /* audio interrupt handler */
769 static irqreturn_t
twl6040_naudint_handler(int irq
, void *data
)
771 struct snd_soc_codec
*codec
= data
;
772 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
775 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE
, &intid
, TWL6040_REG_INTID
);
777 if (intid
& TWL6040_THINT
)
778 dev_alert(codec
->dev
, "die temp over-limit detection\n");
780 if ((intid
& TWL6040_PLUGINT
) || (intid
& TWL6040_UNPLUGINT
))
781 queue_delayed_work(priv
->workqueue
, &priv
->delayed_work
,
782 msecs_to_jiffies(200));
784 if (intid
& TWL6040_HOOKINT
)
785 dev_info(codec
->dev
, "hook detection\n");
787 if (intid
& TWL6040_HFINT
)
788 dev_alert(codec
->dev
, "hf drivers over current detection\n");
790 if (intid
& TWL6040_VIBINT
)
791 dev_alert(codec
->dev
, "vib drivers over current detection\n");
793 if (intid
& TWL6040_READYINT
)
794 complete(&priv
->ready
);
799 static int twl6040_put_volsw(struct snd_kcontrol
*kcontrol
,
800 struct snd_ctl_elem_value
*ucontrol
)
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
;
808 unsigned int reg
= mc
->reg
;
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. */
814 case TWL6040_REG_HSGAIN
:
815 out
= &twl6040_priv
->headset
;
822 out
->left_vol
= ucontrol
->value
.integer
.value
[0];
823 out
->right_vol
= ucontrol
->value
.integer
.value
[1];
828 ret
= snd_soc_put_volsw(kcontrol
, ucontrol
);
835 static int twl6040_get_volsw(struct snd_kcontrol
*kcontrol
,
836 struct snd_ctl_elem_value
*ucontrol
)
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
;
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
;
856 return snd_soc_get_volsw(kcontrol
, ucontrol
);
859 static int twl6040_put_volsw_2r_vu(struct snd_kcontrol
*kcontrol
,
860 struct snd_ctl_elem_value
*ucontrol
)
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
;
868 unsigned int reg
= mc
->reg
;
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. */
874 case TWL6040_REG_HFLGAIN
:
875 case TWL6040_REG_HFRGAIN
:
876 out
= &twl6040_priv
->handsfree
;
883 out
->left_vol
= ucontrol
->value
.integer
.value
[0];
884 out
->right_vol
= ucontrol
->value
.integer
.value
[1];
889 ret
= snd_soc_put_volsw_2r(kcontrol
, ucontrol
);
896 static int twl6040_get_volsw_2r(struct snd_kcontrol
*kcontrol
,
897 struct snd_ctl_elem_value
*ucontrol
)
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
;
906 /* If these are cached registers use the cache */
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
;
919 return snd_soc_get_volsw_2r(kcontrol
, ucontrol
);
922 /* double control with volume update */
923 #define SOC_TWL6040_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax,\
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} }
935 /* double control with volume update */
936 #define SOC_TWL6040_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax,\
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}, }
950 * MICATT volume control:
951 * from -6 to 0 dB in 6 dB steps
953 static DECLARE_TLV_DB_SCALE(mic_preamp_tlv
, -600, 600, 0);
956 * MICGAIN volume control:
957 * from -6 to 30 dB in 6 dB steps
959 static DECLARE_TLV_DB_SCALE(mic_amp_tlv
, -600, 600, 0);
962 * AFMGAIN volume control:
963 * from -18 to 24 dB in 6 dB steps
965 static DECLARE_TLV_DB_SCALE(afm_amp_tlv
, -1800, 600, 0);
968 * HSGAIN volume control:
969 * from -30 to 0 dB in 2 dB steps
971 static DECLARE_TLV_DB_SCALE(hs_tlv
, -3000, 200, 0);
974 * HFGAIN volume control:
975 * from -52 to 6 dB in 2 dB steps
977 static DECLARE_TLV_DB_SCALE(hf_tlv
, -5200, 200, 0);
980 * EPGAIN volume control:
981 * from -24 to 6 dB in 2 dB steps
983 static DECLARE_TLV_DB_SCALE(ep_tlv
, -2400, 200, 0);
985 /* Left analog microphone selection */
986 static const char *twl6040_amicl_texts
[] =
987 {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"};
989 /* Right analog microphone selection */
990 static const char *twl6040_amicr_texts
[] =
991 {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
993 static const struct soc_enum twl6040_enum
[] = {
994 SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL
, 3, 4, twl6040_amicl_texts
),
995 SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL
, 3, 4, twl6040_amicr_texts
),
998 static const char *twl6040_hs_texts
[] = {
999 "Off", "HS DAC", "Line-In amp"
1002 static const struct soc_enum twl6040_hs_enum
[] = {
1003 SOC_ENUM_SINGLE(TWL6040_REG_HSLCTL
, 5, ARRAY_SIZE(twl6040_hs_texts
),
1005 SOC_ENUM_SINGLE(TWL6040_REG_HSRCTL
, 5, ARRAY_SIZE(twl6040_hs_texts
),
1009 static const char *twl6040_hf_texts
[] = {
1010 "Off", "HF DAC", "Line-In amp"
1013 static const struct soc_enum twl6040_hf_enum
[] = {
1014 SOC_ENUM_SINGLE(TWL6040_REG_HFLCTL
, 2, ARRAY_SIZE(twl6040_hf_texts
),
1016 SOC_ENUM_SINGLE(TWL6040_REG_HFRCTL
, 2, ARRAY_SIZE(twl6040_hf_texts
),
1020 static const struct snd_kcontrol_new amicl_control
=
1021 SOC_DAPM_ENUM("Route", twl6040_enum
[0]);
1023 static const struct snd_kcontrol_new amicr_control
=
1024 SOC_DAPM_ENUM("Route", twl6040_enum
[1]);
1026 /* Headset DAC playback switches */
1027 static const struct snd_kcontrol_new hsl_mux_controls
=
1028 SOC_DAPM_ENUM("Route", twl6040_hs_enum
[0]);
1030 static const struct snd_kcontrol_new hsr_mux_controls
=
1031 SOC_DAPM_ENUM("Route", twl6040_hs_enum
[1]);
1033 /* Handsfree DAC playback switches */
1034 static const struct snd_kcontrol_new hfl_mux_controls
=
1035 SOC_DAPM_ENUM("Route", twl6040_hf_enum
[0]);
1037 static const struct snd_kcontrol_new hfr_mux_controls
=
1038 SOC_DAPM_ENUM("Route", twl6040_hf_enum
[1]);
1040 static const struct snd_kcontrol_new ep_driver_switch_controls
=
1041 SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL
, 0, 1, 0);
1043 static const struct snd_kcontrol_new twl6040_snd_controls
[] = {
1045 SOC_DOUBLE_TLV("Capture Preamplifier Volume",
1046 TWL6040_REG_MICGAIN
, 6, 7, 1, 1, mic_preamp_tlv
),
1047 SOC_DOUBLE_TLV("Capture Volume",
1048 TWL6040_REG_MICGAIN
, 0, 3, 4, 0, mic_amp_tlv
),
1051 SOC_DOUBLE_TLV("Aux FM Volume",
1052 TWL6040_REG_LINEGAIN
, 0, 3, 7, 0, afm_amp_tlv
),
1054 /* Playback gains */
1055 SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume",
1056 TWL6040_REG_HSGAIN
, 0, 4, 0xF, 1, hs_tlv
),
1057 SOC_TWL6040_DOUBLE_R_TLV("Handsfree Playback Volume",
1058 TWL6040_REG_HFLGAIN
, TWL6040_REG_HFRGAIN
, 0, 0x1D, 1, hf_tlv
),
1059 SOC_SINGLE_TLV("Earphone Playback Volume",
1060 TWL6040_REG_EARCTL
, 1, 0xF, 1, ep_tlv
),
1063 static const struct snd_soc_dapm_widget twl6040_dapm_widgets
[] = {
1065 SND_SOC_DAPM_INPUT("MAINMIC"),
1066 SND_SOC_DAPM_INPUT("HSMIC"),
1067 SND_SOC_DAPM_INPUT("SUBMIC"),
1068 SND_SOC_DAPM_INPUT("AFML"),
1069 SND_SOC_DAPM_INPUT("AFMR"),
1072 SND_SOC_DAPM_OUTPUT("HSOL"),
1073 SND_SOC_DAPM_OUTPUT("HSOR"),
1074 SND_SOC_DAPM_OUTPUT("HFL"),
1075 SND_SOC_DAPM_OUTPUT("HFR"),
1076 SND_SOC_DAPM_OUTPUT("EP"),
1078 /* Analog input muxes for the capture amplifiers */
1079 SND_SOC_DAPM_MUX("Analog Left Capture Route",
1080 SND_SOC_NOPM
, 0, 0, &amicl_control
),
1081 SND_SOC_DAPM_MUX("Analog Right Capture Route",
1082 SND_SOC_NOPM
, 0, 0, &amicr_control
),
1084 /* Analog capture PGAs */
1085 SND_SOC_DAPM_PGA("MicAmpL",
1086 TWL6040_REG_MICLCTL
, 0, 0, NULL
, 0),
1087 SND_SOC_DAPM_PGA("MicAmpR",
1088 TWL6040_REG_MICRCTL
, 0, 0, NULL
, 0),
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),
1097 SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture",
1098 TWL6040_REG_MICLCTL
, 2, 0),
1099 SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture",
1100 TWL6040_REG_MICRCTL
, 2, 0),
1102 /* Microphone bias */
1103 SND_SOC_DAPM_MICBIAS("Headset Mic Bias",
1104 TWL6040_REG_AMICBCTL
, 0, 0),
1105 SND_SOC_DAPM_MICBIAS("Main Mic Bias",
1106 TWL6040_REG_AMICBCTL
, 4, 0),
1107 SND_SOC_DAPM_MICBIAS("Digital Mic1 Bias",
1108 TWL6040_REG_DMICBCTL
, 0, 0),
1109 SND_SOC_DAPM_MICBIAS("Digital Mic2 Bias",
1110 TWL6040_REG_DMICBCTL
, 4, 0),
1113 SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback",
1114 TWL6040_REG_HSLCTL
, 0, 0,
1115 twl6040_hs_dac_event
,
1116 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_POST_PMD
),
1117 SND_SOC_DAPM_DAC_E("HSDAC Right", "Headset Playback",
1118 TWL6040_REG_HSRCTL
, 0, 0,
1119 twl6040_hs_dac_event
,
1120 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_POST_PMD
),
1121 SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
1122 TWL6040_REG_HFLCTL
, 0, 0,
1123 twl6040_power_mode_event
,
1124 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_POST_PMD
),
1125 SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
1126 TWL6040_REG_HFRCTL
, 0, 0,
1127 twl6040_power_mode_event
,
1128 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_POST_PMD
),
1130 SND_SOC_DAPM_MUX("HF Left Playback",
1131 SND_SOC_NOPM
, 0, 0, &hfl_mux_controls
),
1132 SND_SOC_DAPM_MUX("HF Right Playback",
1133 SND_SOC_NOPM
, 0, 0, &hfr_mux_controls
),
1134 /* Analog playback Muxes */
1135 SND_SOC_DAPM_MUX("HS Left Playback",
1136 SND_SOC_NOPM
, 0, 0, &hsl_mux_controls
),
1137 SND_SOC_DAPM_MUX("HS Right Playback",
1138 SND_SOC_NOPM
, 0, 0, &hsr_mux_controls
),
1140 /* Analog playback drivers */
1141 SND_SOC_DAPM_OUT_DRV_E("Handsfree Left Driver",
1142 TWL6040_REG_HFLCTL
, 4, 0, NULL
, 0,
1144 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_PRE_PMD
),
1145 SND_SOC_DAPM_OUT_DRV_E("Handsfree Right Driver",
1146 TWL6040_REG_HFRCTL
, 4, 0, NULL
, 0,
1148 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_PRE_PMD
),
1149 SND_SOC_DAPM_OUT_DRV_E("Headset Left Driver",
1150 TWL6040_REG_HSLCTL
, 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,
1156 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_PRE_PMD
),
1157 SND_SOC_DAPM_SWITCH_E("Earphone Driver",
1158 SND_SOC_NOPM
, 0, 0, &ep_driver_switch_controls
,
1159 twl6040_power_mode_event
,
1160 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_POST_PMD
),
1162 /* Analog playback PGAs */
1163 SND_SOC_DAPM_PGA("HFDAC Left PGA",
1164 TWL6040_REG_HFLCTL
, 1, 0, NULL
, 0),
1165 SND_SOC_DAPM_PGA("HFDAC Right PGA",
1166 TWL6040_REG_HFRCTL
, 1, 0, NULL
, 0),
1170 static const struct snd_soc_dapm_route intercon
[] = {
1172 {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
1173 {"Analog Left Capture Route", "Main Mic", "MAINMIC"},
1174 {"Analog Left Capture Route", "Aux/FM Left", "AFML"},
1176 {"Analog Right Capture Route", "Headset Mic", "HSMIC"},
1177 {"Analog Right Capture Route", "Sub Mic", "SUBMIC"},
1178 {"Analog Right Capture Route", "Aux/FM Right", "AFMR"},
1180 {"MicAmpL", NULL
, "Analog Left Capture Route"},
1181 {"MicAmpR", NULL
, "Analog Right Capture Route"},
1183 {"ADC Left", NULL
, "MicAmpL"},
1184 {"ADC Right", NULL
, "MicAmpR"},
1187 {"AFMAmpL", "NULL", "AFML"},
1188 {"AFMAmpR", "NULL", "AFMR"},
1190 {"HS Left Playback", "HS DAC", "HSDAC Left"},
1191 {"HS Left Playback", "Line-In amp", "AFMAmpL"},
1193 {"HS Right Playback", "HS DAC", "HSDAC Right"},
1194 {"HS Right Playback", "Line-In amp", "AFMAmpR"},
1196 {"Headset Left Driver", "NULL", "HS Left Playback"},
1197 {"Headset Right Driver", "NULL", "HS Right Playback"},
1199 {"HSOL", NULL
, "Headset Left Driver"},
1200 {"HSOR", NULL
, "Headset Right Driver"},
1202 /* Earphone playback path */
1203 {"Earphone Driver", "Switch", "HSDAC Left"},
1204 {"EP", NULL
, "Earphone Driver"},
1206 {"HF Left Playback", "HF DAC", "HFDAC Left"},
1207 {"HF Left Playback", "Line-In amp", "AFMAmpL"},
1209 {"HF Right Playback", "HF DAC", "HFDAC Right"},
1210 {"HF Right Playback", "Line-In amp", "AFMAmpR"},
1212 {"HFDAC Left PGA", NULL
, "HF Left Playback"},
1213 {"HFDAC Right PGA", NULL
, "HF Right Playback"},
1215 {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
1216 {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
1218 {"HFL", NULL
, "Handsfree Left Driver"},
1219 {"HFR", NULL
, "Handsfree Right Driver"},
1222 static int twl6040_add_widgets(struct snd_soc_codec
*codec
)
1224 struct snd_soc_dapm_context
*dapm
= &codec
->dapm
;
1226 snd_soc_dapm_new_controls(dapm
, twl6040_dapm_widgets
,
1227 ARRAY_SIZE(twl6040_dapm_widgets
));
1228 snd_soc_dapm_add_routes(dapm
, intercon
, ARRAY_SIZE(intercon
));
1229 snd_soc_dapm_new_widgets(dapm
);
1234 static int twl6040_power_up_completion(struct snd_soc_codec
*codec
,
1237 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
1241 time_left
= wait_for_completion_timeout(&priv
->ready
,
1242 msecs_to_jiffies(144));
1245 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE
, &intid
,
1247 if (!(intid
& TWL6040_READYINT
)) {
1248 dev_err(codec
->dev
, "timeout waiting for READYINT\n");
1253 priv
->codec_powered
= 1;
1258 static int twl6040_set_bias_level(struct snd_soc_codec
*codec
,
1259 enum snd_soc_bias_level level
)
1261 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
1262 int audpwron
= priv
->audpwron
;
1263 int naudint
= priv
->naudint
;
1267 case SND_SOC_BIAS_ON
:
1269 case SND_SOC_BIAS_PREPARE
:
1271 case SND_SOC_BIAS_STANDBY
:
1272 if (priv
->codec_powered
)
1275 if (gpio_is_valid(audpwron
)) {
1276 /* use AUDPWRON line */
1277 gpio_set_value(audpwron
, 1);
1279 /* wait for power-up completion */
1280 ret
= twl6040_power_up_completion(codec
, naudint
);
1284 /* sync registers updated during power-up sequence */
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
);
1289 /* use manual power-up sequence */
1290 twl6040_power_up(codec
);
1291 priv
->codec_powered
= 1;
1294 /* initialize vdd/vss registers with reg_cache */
1295 twl6040_init_vdd_regs(codec
);
1297 /* Set external boost GPO */
1298 twl6040_write(codec
, TWL6040_REG_GPOCTL
, 0x02);
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);
1306 case SND_SOC_BIAS_OFF
:
1307 if (!priv
->codec_powered
)
1310 if (gpio_is_valid(audpwron
)) {
1311 /* use AUDPWRON line */
1312 gpio_set_value(audpwron
, 0);
1314 /* power-down sequence latency */
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
,
1323 /* use manual power-down sequence */
1324 twl6040_power_down(codec
);
1327 priv
->codec_powered
= 0;
1331 codec
->dapm
.bias_level
= level
;
1336 /* set of rates for each pll: low-power and high-performance */
1338 static unsigned int lp_rates
[] = {
1343 static struct snd_pcm_hw_constraint_list lp_constraints
= {
1344 .count
= ARRAY_SIZE(lp_rates
),
1348 static unsigned int hp_rates
[] = {
1352 static struct snd_pcm_hw_constraint_list hp_constraints
= {
1353 .count
= ARRAY_SIZE(hp_rates
),
1357 static int twl6040_startup(struct snd_pcm_substream
*substream
,
1358 struct snd_soc_dai
*dai
)
1360 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
1361 struct snd_soc_codec
*codec
= rtd
->codec
;
1362 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
1364 snd_pcm_hw_constraint_list(substream
->runtime
, 0,
1365 SNDRV_PCM_HW_PARAM_RATE
,
1366 priv
->sysclk_constraints
);
1371 static int twl6040_hw_params(struct snd_pcm_substream
*substream
,
1372 struct snd_pcm_hw_params
*params
,
1373 struct snd_soc_dai
*dai
)
1375 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
1376 struct snd_soc_codec
*codec
= rtd
->codec
;
1377 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
1381 /* nothing to do for high-perf pll, it supports only 48 kHz */
1382 if (priv
->pll
== TWL6040_HPPLL_ID
)
1385 lppllctl
= twl6040_read_reg_cache(codec
, TWL6040_REG_LPPLLCTL
);
1387 rate
= params_rate(params
);
1393 lppllctl
|= TWL6040_LPLLFIN
;
1394 priv
->sysclk
= 17640000;
1401 lppllctl
&= ~TWL6040_LPLLFIN
;
1402 priv
->sysclk
= 19200000;
1405 dev_err(codec
->dev
, "unsupported rate %d\n", rate
);
1409 twl6040_write(codec
, TWL6040_REG_LPPLLCTL
, lppllctl
);
1414 static int twl6040_prepare(struct snd_pcm_substream
*substream
,
1415 struct snd_soc_dai
*dai
)
1417 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
1418 struct snd_soc_codec
*codec
= rtd
->codec
;
1419 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
1421 if (!priv
->sysclk
) {
1423 "no mclk configured, call set_sysclk() on init\n");
1428 * capture is not supported at 17.64 MHz,
1429 * it's reserved for headset low-power playback scenario
1431 if ((priv
->sysclk
== 17640000) &&
1432 substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
1434 "capture mode is not supported at %dHz\n",
1439 if ((priv
->sysclk
== 17640000) && priv
->non_lp
) {
1441 "some enabled paths aren't supported at %dHz\n",
1448 static int twl6040_set_dai_sysclk(struct snd_soc_dai
*codec_dai
,
1449 int clk_id
, unsigned int freq
, int dir
)
1451 struct snd_soc_codec
*codec
= codec_dai
->codec
;
1452 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
1453 u8 hppllctl
, lppllctl
;
1455 hppllctl
= twl6040_read_reg_cache(codec
, TWL6040_REG_HPPLLCTL
);
1456 lppllctl
= twl6040_read_reg_cache(codec
, TWL6040_REG_LPPLLCTL
);
1459 case TWL6040_SYSCLK_SEL_LPPLL
:
1462 /* headset dac and driver must be in low-power mode */
1463 headset_power_mode(codec
, 0);
1465 /* clk32k input requires low-power pll */
1466 lppllctl
|= TWL6040_LPLLENA
;
1467 twl6040_write(codec
, TWL6040_REG_LPPLLCTL
, lppllctl
);
1469 lppllctl
&= ~TWL6040_HPLLSEL
;
1470 twl6040_write(codec
, TWL6040_REG_LPPLLCTL
, lppllctl
);
1471 hppllctl
&= ~TWL6040_HPLLENA
;
1472 twl6040_write(codec
, TWL6040_REG_HPPLLCTL
, hppllctl
);
1475 dev_err(codec
->dev
, "unknown mclk freq %d\n", freq
);
1480 switch (priv
->sysclk
) {
1482 lppllctl
|= TWL6040_LPLLFIN
;
1485 lppllctl
&= ~TWL6040_LPLLFIN
;
1488 /* sysclk not yet configured */
1489 lppllctl
&= ~TWL6040_LPLLFIN
;
1490 priv
->sysclk
= 19200000;
1494 twl6040_write(codec
, TWL6040_REG_LPPLLCTL
, lppllctl
);
1496 priv
->pll
= TWL6040_LPPLL_ID
;
1497 priv
->sysclk_constraints
= &lp_constraints
;
1499 case TWL6040_SYSCLK_SEL_HPPLL
:
1500 hppllctl
&= ~TWL6040_MCLK_MSK
;
1504 /* mclk input, pll enabled */
1505 hppllctl
|= TWL6040_MCLK_12000KHZ
|
1510 /* mclk input, pll disabled */
1511 hppllctl
|= TWL6040_MCLK_19200KHZ
|
1512 TWL6040_HPLLSQRENA
|
1516 /* mclk input, pll enabled */
1517 hppllctl
|= TWL6040_MCLK_26000KHZ
|
1522 /* clk slicer, pll disabled */
1523 hppllctl
|= TWL6040_MCLK_38400KHZ
|
1524 TWL6040_HPLLSQRENA
|
1528 dev_err(codec
->dev
, "unknown mclk freq %d\n", freq
);
1532 /* headset dac and driver must be in high-performance mode */
1533 headset_power_mode(codec
, 1);
1535 twl6040_write(codec
, TWL6040_REG_HPPLLCTL
, hppllctl
);
1537 lppllctl
|= TWL6040_HPLLSEL
;
1538 twl6040_write(codec
, TWL6040_REG_LPPLLCTL
, lppllctl
);
1539 lppllctl
&= ~TWL6040_LPLLENA
;
1540 twl6040_write(codec
, TWL6040_REG_LPPLLCTL
, lppllctl
);
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
;
1548 dev_err(codec
->dev
, "unknown clk_id %d\n", clk_id
);
1555 static struct snd_soc_dai_ops twl6040_dai_ops
= {
1556 .startup
= twl6040_startup
,
1557 .hw_params
= twl6040_hw_params
,
1558 .prepare
= twl6040_prepare
,
1559 .set_sysclk
= twl6040_set_dai_sysclk
,
1562 static struct snd_soc_dai_driver twl6040_dai
= {
1563 .name
= "twl6040-hifi",
1565 .stream_name
= "Playback",
1568 .rates
= TWL6040_RATES
,
1569 .formats
= TWL6040_FORMATS
,
1572 .stream_name
= "Capture",
1575 .rates
= TWL6040_RATES
,
1576 .formats
= TWL6040_FORMATS
,
1578 .ops
= &twl6040_dai_ops
,
1582 static int twl6040_suspend(struct snd_soc_codec
*codec
, pm_message_t state
)
1584 twl6040_set_bias_level(codec
, SND_SOC_BIAS_OFF
);
1589 static int twl6040_resume(struct snd_soc_codec
*codec
)
1591 twl6040_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
1592 twl6040_set_bias_level(codec
, codec
->dapm
.suspend_bias_level
);
1597 #define twl6040_suspend NULL
1598 #define twl6040_resume NULL
1601 static int twl6040_probe(struct snd_soc_codec
*codec
)
1603 struct twl4030_codec_data
*twl_codec
= codec
->dev
->platform_data
;
1604 struct twl6040_data
*priv
;
1605 int audpwron
, naudint
;
1607 u8 icrev
, intmr
= TWL6040_ALLINT_MSK
;
1609 priv
= kzalloc(sizeof(struct twl6040_data
), GFP_KERNEL
);
1612 snd_soc_codec_set_drvdata(codec
, priv
);
1614 priv
->codec
= codec
;
1616 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE
, &icrev
, TWL6040_REG_ASICREV
);
1618 if (twl_codec
&& (icrev
> 0))
1619 audpwron
= twl_codec
->audpwron_gpio
;
1624 naudint
= twl_codec
->naudint_irq
;
1628 priv
->audpwron
= audpwron
;
1629 priv
->naudint
= naudint
;
1630 priv
->workqueue
= create_singlethread_workqueue("twl6040-codec");
1632 if (!priv
->workqueue
) {
1637 INIT_DELAYED_WORK(&priv
->delayed_work
, twl6040_accessory_work
);
1639 mutex_init(&priv
->mutex
);
1641 init_completion(&priv
->ready
);
1642 init_completion(&priv
->headset
.ramp_done
);
1643 init_completion(&priv
->handsfree
.ramp_done
);
1645 if (gpio_is_valid(audpwron
)) {
1646 ret
= gpio_request(audpwron
, "audpwron");
1650 ret
= gpio_direction_output(audpwron
, 0);
1654 priv
->codec_powered
= 0;
1656 /* enable only codec ready interrupt */
1657 intmr
&= ~(TWL6040_READYMSK
| TWL6040_PLUGMSK
);
1659 /* reset interrupt status to allow correct power up sequence */
1660 twl6040_read_reg_volatile(codec
, TWL6040_REG_INTID
);
1662 twl6040_write(codec
, TWL6040_REG_INTMR
, intmr
);
1665 /* audio interrupt */
1666 ret
= request_threaded_irq(naudint
, NULL
,
1667 twl6040_naudint_handler
,
1668 IRQF_TRIGGER_LOW
| IRQF_ONESHOT
,
1669 "twl6040_codec", codec
);
1674 /* init vio registers */
1675 twl6040_init_vio_regs(codec
);
1677 priv
->hf_workqueue
= create_singlethread_workqueue("twl6040-hf");
1678 if (priv
->hf_workqueue
== NULL
) {
1682 priv
->hs_workqueue
= create_singlethread_workqueue("twl6040-hs");
1683 if (priv
->hs_workqueue
== NULL
) {
1688 INIT_DELAYED_WORK(&priv
->hs_delayed_work
, twl6040_pga_hs_work
);
1689 INIT_DELAYED_WORK(&priv
->hf_delayed_work
, twl6040_pga_hf_work
);
1691 /* power on device */
1692 ret
= twl6040_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
1696 snd_soc_add_controls(codec
, twl6040_snd_controls
,
1697 ARRAY_SIZE(twl6040_snd_controls
));
1698 twl6040_add_widgets(codec
);
1703 destroy_workqueue(priv
->hs_workqueue
);
1705 destroy_workqueue(priv
->hf_workqueue
);
1708 free_irq(naudint
, codec
);
1710 if (gpio_is_valid(audpwron
))
1711 gpio_free(audpwron
);
1713 destroy_workqueue(priv
->workqueue
);
1719 static int twl6040_remove(struct snd_soc_codec
*codec
)
1721 struct twl6040_data
*priv
= snd_soc_codec_get_drvdata(codec
);
1722 int audpwron
= priv
->audpwron
;
1723 int naudint
= priv
->naudint
;
1725 twl6040_set_bias_level(codec
, SND_SOC_BIAS_OFF
);
1727 if (gpio_is_valid(audpwron
))
1728 gpio_free(audpwron
);
1731 free_irq(naudint
, codec
);
1733 destroy_workqueue(priv
->workqueue
);
1734 destroy_workqueue(priv
->hf_workqueue
);
1735 destroy_workqueue(priv
->hs_workqueue
);
1741 static struct snd_soc_codec_driver soc_codec_dev_twl6040
= {
1742 .probe
= twl6040_probe
,
1743 .remove
= twl6040_remove
,
1744 .suspend
= twl6040_suspend
,
1745 .resume
= twl6040_resume
,
1746 .read
= twl6040_read_reg_cache
,
1747 .write
= twl6040_write
,
1748 .set_bias_level
= twl6040_set_bias_level
,
1749 .reg_cache_size
= ARRAY_SIZE(twl6040_reg
),
1750 .reg_word_size
= sizeof(u8
),
1751 .reg_cache_default
= twl6040_reg
,
1754 static int __devinit
twl6040_codec_probe(struct platform_device
*pdev
)
1756 return snd_soc_register_codec(&pdev
->dev
,
1757 &soc_codec_dev_twl6040
, &twl6040_dai
, 1);
1760 static int __devexit
twl6040_codec_remove(struct platform_device
*pdev
)
1762 snd_soc_unregister_codec(&pdev
->dev
);
1766 static struct platform_driver twl6040_codec_driver
= {
1768 .name
= "twl6040-codec",
1769 .owner
= THIS_MODULE
,
1771 .probe
= twl6040_codec_probe
,
1772 .remove
= __devexit_p(twl6040_codec_remove
),
1775 static int __init
twl6040_codec_init(void)
1777 return platform_driver_register(&twl6040_codec_driver
);
1779 module_init(twl6040_codec_init
);
1781 static void __exit
twl6040_codec_exit(void)
1783 platform_driver_unregister(&twl6040_codec_driver
);
1785 module_exit(twl6040_codec_exit
);
1787 MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
1788 MODULE_AUTHOR("Misael Lopez Cruz");
1789 MODULE_LICENSE("GPL");