2 * MFD driver for twl6040 codec submodule
4 * Authors: Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
5 * Misael Lopez Cruz <misael.lopez@ti.com>
7 * Copyright: (C) 20010 Texas Instruments, Inc.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 #include <linux/module.h>
26 #include <linux/types.h>
27 #include <linux/slab.h>
28 #include <linux/kernel.h>
29 #include <linux/platform_device.h>
30 #include <linux/gpio.h>
31 #include <linux/delay.h>
32 #include <linux/i2c/twl.h>
33 #include <linux/mfd/core.h>
34 #include <linux/mfd/twl6040-codec.h>
36 int twl6040_reg_read(struct twl6040
*twl6040
, unsigned int reg
)
41 mutex_lock(&twl6040
->io_mutex
);
42 ret
= twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE
, &val
, reg
);
44 mutex_unlock(&twl6040
->io_mutex
);
47 mutex_unlock(&twl6040
->io_mutex
);
51 EXPORT_SYMBOL(twl6040_reg_read
);
53 int twl6040_reg_write(struct twl6040
*twl6040
, unsigned int reg
, u8 val
)
57 mutex_lock(&twl6040
->io_mutex
);
58 ret
= twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE
, val
, reg
);
59 mutex_unlock(&twl6040
->io_mutex
);
63 EXPORT_SYMBOL(twl6040_reg_write
);
65 int twl6040_set_bits(struct twl6040
*twl6040
, unsigned int reg
, u8 mask
)
70 mutex_lock(&twl6040
->io_mutex
);
71 ret
= twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE
, &val
, reg
);
76 ret
= twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE
, val
, reg
);
78 mutex_unlock(&twl6040
->io_mutex
);
81 EXPORT_SYMBOL(twl6040_set_bits
);
83 int twl6040_clear_bits(struct twl6040
*twl6040
, unsigned int reg
, u8 mask
)
88 mutex_lock(&twl6040
->io_mutex
);
89 ret
= twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE
, &val
, reg
);
94 ret
= twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE
, val
, reg
);
96 mutex_unlock(&twl6040
->io_mutex
);
99 EXPORT_SYMBOL(twl6040_clear_bits
);
101 /* twl6040 codec manual power-up sequence */
102 static int twl6040_power_up(struct twl6040
*twl6040
)
104 u8 ncpctl
, ldoctl
, lppllctl
, accctl
;
107 ncpctl
= twl6040_reg_read(twl6040
, TWL6040_REG_NCPCTL
);
108 ldoctl
= twl6040_reg_read(twl6040
, TWL6040_REG_LDOCTL
);
109 lppllctl
= twl6040_reg_read(twl6040
, TWL6040_REG_LPPLLCTL
);
110 accctl
= twl6040_reg_read(twl6040
, TWL6040_REG_ACCCTL
);
112 /* enable reference system */
113 ldoctl
|= TWL6040_REFENA
;
114 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
119 /* enable internal oscillator */
120 ldoctl
|= TWL6040_OSCENA
;
121 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
126 /* enable high-side ldo */
127 ldoctl
|= TWL6040_HSLDOENA
;
128 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
133 /* enable negative charge pump */
134 ncpctl
|= TWL6040_NCPENA
| TWL6040_NCPOPEN
;
135 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_NCPCTL
, ncpctl
);
140 /* enable low-side ldo */
141 ldoctl
|= TWL6040_LSLDOENA
;
142 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
147 /* enable low-power pll */
148 lppllctl
|= TWL6040_LPLLENA
;
149 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
, lppllctl
);
153 /* reset state machine */
154 accctl
|= TWL6040_RESETSPLIT
;
155 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_ACCCTL
, accctl
);
159 accctl
&= ~TWL6040_RESETSPLIT
;
160 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_ACCCTL
, accctl
);
164 /* disable internal oscillator */
165 ldoctl
&= ~TWL6040_OSCENA
;
166 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
173 lppllctl
&= ~TWL6040_LPLLENA
;
174 twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
, lppllctl
);
176 ldoctl
&= ~TWL6040_LSLDOENA
;
177 twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
180 ncpctl
&= ~(TWL6040_NCPENA
| TWL6040_NCPOPEN
);
181 twl6040_reg_write(twl6040
, TWL6040_REG_NCPCTL
, ncpctl
);
184 ldoctl
&= ~TWL6040_HSLDOENA
;
185 twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
188 ldoctl
&= ~TWL6040_OSCENA
;
189 twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
191 ldoctl
&= ~TWL6040_REFENA
;
192 twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
198 /* twl6040 codec manual power-down sequence */
199 static int twl6040_power_down(struct twl6040
*twl6040
)
201 u8 ncpctl
, ldoctl
, lppllctl
, accctl
;
204 ncpctl
= twl6040_reg_read(twl6040
, TWL6040_REG_NCPCTL
);
205 ldoctl
= twl6040_reg_read(twl6040
, TWL6040_REG_LDOCTL
);
206 lppllctl
= twl6040_reg_read(twl6040
, TWL6040_REG_LPPLLCTL
);
207 accctl
= twl6040_reg_read(twl6040
, TWL6040_REG_ACCCTL
);
209 /* enable internal oscillator */
210 ldoctl
|= TWL6040_OSCENA
;
211 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
216 /* disable low-power pll */
217 lppllctl
&= ~TWL6040_LPLLENA
;
218 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
, lppllctl
);
222 /* disable low-side ldo */
223 ldoctl
&= ~TWL6040_LSLDOENA
;
224 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
229 /* disable negative charge pump */
230 ncpctl
&= ~(TWL6040_NCPENA
| TWL6040_NCPOPEN
);
231 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_NCPCTL
, ncpctl
);
236 /* disable high-side ldo */
237 ldoctl
&= ~TWL6040_HSLDOENA
;
238 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
243 /* disable internal oscillator */
244 ldoctl
&= ~TWL6040_OSCENA
;
245 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
249 /* disable reference system */
250 ldoctl
&= ~TWL6040_REFENA
;
251 ret
= twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
259 ldoctl
|= TWL6040_OSCENA
;
260 twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
263 ldoctl
|= TWL6040_HSLDOENA
;
264 twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
267 ncpctl
|= TWL6040_NCPENA
| TWL6040_NCPOPEN
;
268 twl6040_reg_write(twl6040
, TWL6040_REG_NCPCTL
, ncpctl
);
271 ldoctl
|= TWL6040_LSLDOENA
;
272 twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
275 lppllctl
|= TWL6040_LPLLENA
;
276 twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
, lppllctl
);
278 lppllctl
|= TWL6040_LPLLENA
;
279 twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
, lppllctl
);
280 accctl
|= TWL6040_RESETSPLIT
;
281 twl6040_reg_write(twl6040
, TWL6040_REG_ACCCTL
, accctl
);
283 accctl
&= ~TWL6040_RESETSPLIT
;
284 twl6040_reg_write(twl6040
, TWL6040_REG_ACCCTL
, accctl
);
285 ldoctl
&= ~TWL6040_OSCENA
;
286 twl6040_reg_write(twl6040
, TWL6040_REG_LDOCTL
, ldoctl
);
292 static irqreturn_t
twl6040_naudint_handler(int irq
, void *data
)
294 struct twl6040
*twl6040
= data
;
297 intid
= twl6040_reg_read(twl6040
, TWL6040_REG_INTID
);
299 if (intid
& TWL6040_READYINT
)
300 complete(&twl6040
->ready
);
305 static int twl6040_power_up_completion(struct twl6040
*twl6040
,
320 /* NCPCTL expected value: NCP enabled */
321 ncpctl_exp
= (TWL6040_TSHUTENA
| TWL6040_NCPENA
);
323 /* LDOCTL expected value: HS/LS LDOs and Reference enabled */
324 ldoctl_exp
= (TWL6040_REFENA
| TWL6040_HSLDOENA
| TWL6040_LSLDOENA
);
326 /* LPPLLCTL expected value: Low-Power PLL enabled */
327 lppllctl_exp
= TWL6040_LPLLENA
;
330 gpio_set_value(twl6040
->audpwron
, 1);
331 time_left
= wait_for_completion_timeout(&twl6040
->ready
,
332 msecs_to_jiffies(700));
334 intid
= twl6040_reg_read(twl6040
, TWL6040_REG_INTID
);
335 if (!(intid
& TWL6040_READYINT
)) {
336 dev_err(twl6040
->dev
,
337 "timeout waiting for READYINT\n");
342 * Power on seemingly completed.
343 * Look for clues that the twl6040 might be still booting.
347 ncpctl
= twl6040_reg_read(twl6040
, TWL6040_REG_NCPCTL
);
348 if (ncpctl
!= ncpctl_exp
)
351 ldoctl
= twl6040_reg_read(twl6040
, TWL6040_REG_LDOCTL
);
352 if (ldoctl
!= ldoctl_exp
)
355 lppllctl
= twl6040_reg_read(twl6040
, TWL6040_REG_LPPLLCTL
);
356 if (lppllctl
!= lppllctl_exp
)
360 dev_err(twl6040
->dev
,
361 "NCPCTL: 0x%02x (should be 0x%02x)\n"
362 "LDOCTL: 0x%02x (should be 0x%02x)\n"
363 "LPLLCTL: 0x%02x (should be 0x%02x)\n",
366 lppllctl
, lppllctl_exp
);
368 gpio_set_value(twl6040
->audpwron
, 0);
369 usleep_range(1000, 1500);
372 } while (round
&& (round
< 3));
375 dev_err(twl6040
->dev
,
376 "Automatic power on failed, reverting to manual\n");
377 twl6040
->audpwron
= -EINVAL
;
378 ret
= twl6040_power_up(twl6040
);
380 dev_err(twl6040
->dev
, "Manual power-up failed\n");
386 static int twl6040_power(struct twl6040
*twl6040
, int enable
)
388 struct twl4030_codec_data
*pdata
= dev_get_platdata(twl6040
->dev
);
389 int audpwron
= twl6040
->audpwron
;
390 int naudint
= twl6040
->irq
;
394 /* enable 32kHz external clock */
395 if (pdata
->set_ext_clk32k
) {
396 ret
= pdata
->set_ext_clk32k(true);
398 dev_err(twl6040
->dev
,
399 "failed to enable CLK32K %d\n", ret
);
404 /* disable internal 32kHz oscillator */
405 twl6040_clear_bits(twl6040
, TWL6040_REG_ACCCTL
,
408 if (gpio_is_valid(audpwron
)) {
409 /* wait for power-up completion */
410 ret
= twl6040_power_up_completion(twl6040
, naudint
);
412 dev_err(twl6040
->dev
,
413 "automatic power-down failed\n");
417 /* use manual power-up sequence */
418 ret
= twl6040_power_up(twl6040
);
420 dev_err(twl6040
->dev
,
421 "manual power-up failed\n");
425 twl6040
->pll
= TWL6040_LPPLL_ID
;
426 twl6040
->sysclk
= 19200000;
428 if (gpio_is_valid(audpwron
)) {
429 /* use AUDPWRON line */
430 gpio_set_value(audpwron
, 0);
432 /* power-down sequence latency */
435 /* use manual power-down sequence */
436 ret
= twl6040_power_down(twl6040
);
438 dev_err(twl6040
->dev
,
439 "manual power-down failed\n");
444 /* enable internal 32kHz oscillator */
445 twl6040_set_bits(twl6040
, TWL6040_REG_ACCCTL
,
448 /* disable 32kHz external clock */
449 if (pdata
->set_ext_clk32k
) {
450 ret
= pdata
->set_ext_clk32k(false);
452 dev_err(twl6040
->dev
,
453 "failed to disable CLK32K %d\n", ret
);
456 twl6040
->pll
= TWL6040_NOPLL_ID
;
460 twl6040
->powered
= enable
;
465 int twl6040_enable(struct twl6040
*twl6040
)
469 mutex_lock(&twl6040
->mutex
);
470 if (!twl6040
->power_count
++)
471 ret
= twl6040_power(twl6040
, 1);
472 mutex_unlock(&twl6040
->mutex
);
476 EXPORT_SYMBOL(twl6040_enable
);
478 int twl6040_disable(struct twl6040
*twl6040
)
482 mutex_lock(&twl6040
->mutex
);
483 WARN(!twl6040
->power_count
, "TWL6040 is already disabled");
484 if (!--twl6040
->power_count
)
485 ret
= twl6040_power(twl6040
, 0);
486 mutex_unlock(&twl6040
->mutex
);
490 EXPORT_SYMBOL(twl6040_disable
);
492 int twl6040_is_enabled(struct twl6040
*twl6040
)
494 return twl6040
->power_count
;
496 EXPORT_SYMBOL(twl6040_is_enabled
);
498 int twl6040_set_pll(struct twl6040
*twl6040
, enum twl6040_pll_id id
,
499 unsigned int freq_in
, unsigned int freq_out
)
501 u8 hppllctl
, lppllctl
;
504 mutex_lock(&twl6040
->mutex
);
506 hppllctl
= twl6040_reg_read(twl6040
, TWL6040_REG_HPPLLCTL
);
507 lppllctl
= twl6040_reg_read(twl6040
, TWL6040_REG_LPPLLCTL
);
510 case TWL6040_LPPLL_ID
:
514 lppllctl
|= TWL6040_LPLLFIN
;
517 lppllctl
&= ~TWL6040_LPLLFIN
;
520 dev_err(twl6040
->dev
,
521 "freq_out %d not supported\n", freq_out
);
525 twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
, lppllctl
);
529 lppllctl
|= TWL6040_LPLLENA
;
530 twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
,
533 lppllctl
&= ~TWL6040_HPLLSEL
;
534 twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
,
536 hppllctl
&= ~TWL6040_HPLLENA
;
537 twl6040_reg_write(twl6040
, TWL6040_REG_HPPLLCTL
,
541 dev_err(twl6040
->dev
,
542 "freq_in %d not supported\n", freq_in
);
547 twl6040
->pll
= TWL6040_LPPLL_ID
;
549 case TWL6040_HPPLL_ID
:
550 /* high-performance pll can provide only 19.2 MHz */
551 if (freq_out
!= 19200000) {
552 dev_err(twl6040
->dev
,
553 "freq_out %d not supported\n", freq_out
);
558 hppllctl
&= ~TWL6040_MCLK_MSK
;
562 /* mclk input, pll enabled */
563 hppllctl
|= TWL6040_MCLK_12000KHZ
|
568 /* mclk input, pll disabled */
569 hppllctl
|= TWL6040_MCLK_19200KHZ
|
574 /* mclk input, pll enabled */
575 hppllctl
|= TWL6040_MCLK_26000KHZ
|
580 /* clk slicer, pll disabled */
581 hppllctl
|= TWL6040_MCLK_38400KHZ
|
586 dev_err(twl6040
->dev
,
587 "freq_in %d not supported\n", freq_in
);
592 twl6040_reg_write(twl6040
, TWL6040_REG_HPPLLCTL
, hppllctl
);
594 lppllctl
|= TWL6040_HPLLSEL
;
595 twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
, lppllctl
);
596 lppllctl
&= ~TWL6040_LPLLENA
;
597 twl6040_reg_write(twl6040
, TWL6040_REG_LPPLLCTL
, lppllctl
);
599 twl6040
->pll
= TWL6040_HPPLL_ID
;
602 dev_err(twl6040
->dev
, "unknown pll id %d\n", id
);
607 twl6040
->sysclk
= freq_out
;
610 mutex_unlock(&twl6040
->mutex
);
613 EXPORT_SYMBOL(twl6040_set_pll
);
615 enum twl6040_pll_id
twl6040_get_pll(struct twl6040
*twl6040
)
619 EXPORT_SYMBOL(twl6040_get_pll
);
621 unsigned int twl6040_get_sysclk(struct twl6040
*twl6040
)
623 return twl6040
->sysclk
;
625 EXPORT_SYMBOL(twl6040_get_sysclk
);
627 int twl6040_get_icrev(struct twl6040
*twl6040
)
629 return twl6040
->icrev
;
631 EXPORT_SYMBOL(twl6040_get_icrev
);
633 static int __devinit
twl6040_probe(struct platform_device
*pdev
)
635 struct twl4030_codec_data
*pdata
= pdev
->dev
.platform_data
;
636 struct twl6040
*twl6040
;
637 struct mfd_cell
*cell
= NULL
;
638 unsigned int naudint
;
640 int ret
, children
= 0;
644 dev_err(&pdev
->dev
, "Platform data is missing\n");
648 twl6040
= kzalloc(sizeof(struct twl6040
), GFP_KERNEL
);
652 platform_set_drvdata(pdev
, twl6040
);
654 twl6040
->dev
= &pdev
->dev
;
655 mutex_init(&twl6040
->mutex
);
656 mutex_init(&twl6040
->io_mutex
);
658 twl6040
->icrev
= twl6040_reg_read(twl6040
, TWL6040_REG_ASICREV
);
659 if (twl6040
->icrev
< 0) {
660 ret
= twl6040
->icrev
;
664 if (pdata
&& (twl6040_get_icrev(twl6040
) > TWL6040_REV_1_0
))
665 audpwron
= pdata
->audpwron_gpio
;
670 naudint
= pdata
->naudint_irq
;
674 twl6040
->audpwron
= audpwron
;
675 twl6040
->powered
= 0;
676 twl6040
->irq
= naudint
;
677 twl6040
->irq_base
= pdata
->irq_base
;
678 init_completion(&twl6040
->ready
);
680 if (gpio_is_valid(audpwron
)) {
681 ret
= gpio_request(audpwron
, "audpwron");
685 ret
= gpio_direction_output(audpwron
, 0);
691 /* codec interrupt */
692 ret
= twl6040_irq_init(twl6040
);
696 ret
= twl6040_request_irq(twl6040
, TWL6040_IRQ_READY
,
697 twl6040_naudint_handler
, "twl6040_irq_ready",
700 dev_err(twl6040
->dev
, "READY IRQ request failed: %d\n",
706 /* dual-access registers controlled by I2C only */
707 accctl
= twl6040_reg_read(twl6040
, TWL6040_REG_ACCCTL
);
708 twl6040_reg_write(twl6040
, TWL6040_REG_ACCCTL
, accctl
| TWL6040_I2CSEL
);
710 if (pdata
->get_ext_clk32k
) {
711 ret
= pdata
->get_ext_clk32k();
713 dev_err(twl6040
->dev
,
714 "failed to get external 32kHz clock %d\n",
721 cell
= &twl6040
->cells
[children
];
722 cell
->name
= "twl6040-codec";
723 cell
->platform_data
= pdata
->audio
;
724 cell
->pdata_size
= sizeof(*pdata
->audio
);
729 cell
= &twl6040
->cells
[children
];
730 cell
->name
= "twl6040-vibra";
731 cell
->platform_data
= pdata
->vibra
;
732 cell
->pdata_size
= sizeof(*pdata
->vibra
);
737 ret
= mfd_add_devices(&pdev
->dev
, pdev
->id
, twl6040
->cells
,
742 dev_err(&pdev
->dev
, "No platform data found for children\n");
750 if (pdata
->put_ext_clk32k
)
751 pdata
->put_ext_clk32k();
754 twl6040_free_irq(twl6040
, TWL6040_IRQ_READY
, twl6040
);
757 twl6040_irq_exit(twl6040
);
759 if (gpio_is_valid(audpwron
))
762 platform_set_drvdata(pdev
, NULL
);
767 static int __devexit
twl6040_remove(struct platform_device
*pdev
)
769 struct twl6040
*twl6040
= platform_get_drvdata(pdev
);
770 struct twl4030_codec_data
*pdata
= dev_get_platdata(twl6040
->dev
);
771 int audpwron
= twl6040
->audpwron
;
772 int naudint
= twl6040
->irq
;
774 twl6040_disable(twl6040
);
776 twl6040_free_irq(twl6040
, TWL6040_IRQ_READY
, twl6040
);
778 if (gpio_is_valid(audpwron
))
782 twl6040_irq_exit(twl6040
);
784 mfd_remove_devices(&pdev
->dev
);
786 if (pdata
->put_ext_clk32k
)
787 pdata
->put_ext_clk32k();
789 platform_set_drvdata(pdev
, NULL
);
795 static struct platform_driver twl6040_driver
= {
796 .probe
= twl6040_probe
,
797 .remove
= __devexit_p(twl6040_remove
),
799 .owner
= THIS_MODULE
,
800 .name
= "twl6040-audio",
804 static int __devinit
twl6040_init(void)
806 return platform_driver_register(&twl6040_driver
);
808 module_init(twl6040_init
);
810 static void __devexit
twl6040_exit(void)
812 platform_driver_unregister(&twl6040_driver
);
815 module_exit(twl6040_exit
);
817 MODULE_DESCRIPTION("TWL6040 MFD");
818 MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
819 MODULE_LICENSE("GPL");
820 MODULE_ALIAS("platform:twl6040-audio");