From: Toshihiro Kobayashi Date: Wed, 1 Mar 2006 11:13:36 +0000 (+0200) Subject: ARM: OMAP: Add audio power control interface for DSP Gateway X-Git-Tag: v2.6.16-omap1~42 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=799d9aa7b0b8a05ba61bb0a93f1c8f8e31bae57f;p=linux-2.6-omap-h63xx.git ARM: OMAP: Add audio power control interface for DSP Gateway Signed-off-by: Toshihiro Kobayashi Signed-off-by: Juha Yrjölä --- diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 3298864ab63..8133b5944ab 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,9 @@ #include #include #include +#include +#include +#include static void __init omap_nokia770_init_irq(void) { @@ -136,6 +140,95 @@ static struct omap_board_config_kernel nokia770_config[] = { { OMAP_TAG_MMC, &nokia770_mmc_config }, }; +/* + * audio power control + */ +#define HEADPHONE_GPIO 14 +#define AMPLIFIER_CTRL_GPIO 58 + +static struct clk *dspxor_ck; +static DECLARE_MUTEX(audio_pwr_sem); +/* + * audio_pwr_state + * +--+-------------------------+---------------------------------------+ + * |-1|down |power-up request -> 0 | + * +--+-------------------------+---------------------------------------+ + * | 0|up |power-down(1) request -> 1 | + * | | |power-down(2) request -> (ignore) | + * +--+-------------------------+---------------------------------------+ + * | 1|up, |power-up request -> 0 | + * | |received down(1) request |power-down(2) request -> -1 | + * +--+-------------------------+---------------------------------------+ + */ +static int audio_pwr_state = -1; + +/* + * audio_pwr_up / down should be called under audio_pwr_sem + */ +static void nokia770_audio_pwr_up(void) +{ + clk_enable(dspxor_ck); + + /* Turn on codec */ + tlv320aic23_power_up(); + + if (omap_get_gpio_datain(HEADPHONE_GPIO)) + /* HP not connected, turn on amplifier */ + omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 1); + else + /* HP connected, do not turn on amplifier */ + printk("HP connected\n"); +} + +static void codec_delayed_power_down(void *arg) +{ + down(&audio_pwr_sem); + if (audio_pwr_state == -1) + tlv320aic23_power_down(); + up(&audio_pwr_sem); +} + +static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL); + +static void nokia770_audio_pwr_down(void) +{ + clk_disable(dspxor_ck); + + /* Turn off amplifier */ + omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 0); + + /* Turn off codec: schedule delayed work */ + schedule_delayed_work(&codec_power_down_work, HZ / 20); /* 50ms */ +} + +void nokia770_audio_pwr_up_request(int stage) +{ + down(&audio_pwr_sem); + if (audio_pwr_state == -1) + nokia770_audio_pwr_up(); + /* force audio_pwr_state = 0, even if it was 1. */ + audio_pwr_state = 0; + up(&audio_pwr_sem); +} + +void nokia770_audio_pwr_down_request(int stage) +{ + down(&audio_pwr_sem); + switch (stage) { + case 1: + if (audio_pwr_state == 0) + audio_pwr_state = 1; + break; + case 2: + if (audio_pwr_state == 1) { + nokia770_audio_pwr_down(); + audio_pwr_state = -1; + } + break; + } + up(&audio_pwr_sem); +} + static void __init omap_nokia770_init(void) { nokia770_config[0].data = &nokia770_usb_config; @@ -146,6 +239,9 @@ static void __init omap_nokia770_init(void) omap_board_config = nokia770_config; omap_board_config_size = ARRAY_SIZE(nokia770_config); omap_serial_init(); + omap_dsp_audio_pwr_up_request = nokia770_audio_pwr_up_request; + omap_dsp_audio_pwr_down_request = nokia770_audio_pwr_down_request; + dspxor_ck = clk_get(0, "dspxor_ck"); } static void __init omap_nokia770_map_io(void) diff --git a/arch/arm/plat-omap/dsp/dsp_common.c b/arch/arm/plat-omap/dsp/dsp_common.c index 22c931c29c4..9c701567f1f 100644 --- a/arch/arm/plat-omap/dsp/dsp_common.c +++ b/arch/arm/plat-omap/dsp/dsp_common.c @@ -496,6 +496,26 @@ void dsp_unregister_mem_cb(void) up(&cpustat.sem); } +/* + * Audio power control function prototypes and defaults + * (To be overridden with board specific functions) + */ +static void generic_audio_pwr_up_request(int stage) +{ + printk(KERN_ERR "audio power-up request function is not defined.\n"); +} + +void (*omap_dsp_audio_pwr_up_request)(int stage) = generic_audio_pwr_up_request; +EXPORT_SYMBOL(omap_dsp_audio_pwr_up_request); + +static void generic_audio_pwr_down_request(int stage) +{ + printk(KERN_ERR "audio power-down request function is not defined.\n"); +} + +void (*omap_dsp_audio_pwr_down_request)(int stage) = generic_audio_pwr_down_request; +EXPORT_SYMBOL(omap_dsp_audio_pwr_down_request); + arch_initcall(omap_dsp_init); EXPORT_SYMBOL(omap_dsp_request_mpui); diff --git a/arch/arm/plat-omap/dsp/dsp_core.c b/arch/arm/plat-omap/dsp/dsp_core.c index a77216a454d..42565774988 100644 --- a/arch/arm/plat-omap/dsp/dsp_core.c +++ b/arch/arm/plat-omap/dsp/dsp_core.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "hardware_dsp.h" #include "dsp.h" @@ -455,13 +456,39 @@ static void mbx1_kfunc_fbctl(unsigned short data) } } +static void mbx1_kfunc_audio_pwr(unsigned short data) +{ + struct mbcmd mb; + + switch (data) { + case OMAP_DSP_MBCMD_AUDIO_PWR_UP: + omap_dsp_audio_pwr_up_request(0); + /* send back ack */ + mbcmd_set(mb, MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR, + OMAP_DSP_MBCMD_AUDIO_PWR_UP); + dsp_mbcmd_send(&mb); + break; + case OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1: + omap_dsp_audio_pwr_down_request(1); + break; + case OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2: + omap_dsp_audio_pwr_down_request(2); + break; + default: + printk(KERN_ERR + "mailbox: Unknown AUDIO_PWR from DSP: 0x%04x\n", data); + } +} + static void mbx1_kfunc(struct mbcmd *mb) { switch (mb->cmd_l) { case OMAP_DSP_MBCMD_KFUNC_FBCTL: mbx1_kfunc_fbctl(mb->data); break; - + case OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR: + mbx1_kfunc_audio_pwr(mb->data); + break; default: printk(KERN_ERR "mailbox: Unknown kfunc from DSP: 0x%02x\n", mb->cmd_l); diff --git a/arch/arm/plat-omap/dsp/mblog.c b/arch/arm/plat-omap/dsp/mblog.c index 0edf07079ed..32989766020 100644 --- a/arch/arm/plat-omap/dsp/mblog.c +++ b/arch/arm/plat-omap/dsp/mblog.c @@ -59,7 +59,8 @@ char *subcmd_name(struct mbcmd *mb) NULL; break; case MBCMD(KFUNC): - s = (cmd_l == KFUNCCMD(FBCTL)) ? "FBCTL": + s = (cmd_l == KFUNCCMD(FBCTL)) ? "FBCTL": + (cmd_l == KFUNCCMD(AUDIO_PWR)) ? "AUDIO_PWR": NULL; break; case MBCMD(DSPCFG): diff --git a/include/asm-arm/arch-omap/aic23.h b/include/asm-arm/arch-omap/aic23.h index b46885f3a92..6513065941d 100644 --- a/include/asm-arm/arch-omap/aic23.h +++ b/include/asm-arm/arch-omap/aic23.h @@ -110,4 +110,7 @@ #define TLV320AIC23ID1 (0x1a) // cs low #define TLV320AIC23ID2 (0x1b) // cs high +void tlv320aic23_power_up(void); +void tlv320aic23_power_down(void); + #endif /* __ASM_ARCH_AIC23_H */ diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h index ec834b38158..06dad83dd41 100644 --- a/include/asm-arm/arch-omap/dsp.h +++ b/include/asm-arm/arch-omap/dsp.h @@ -181,11 +181,16 @@ struct omap_dsp_varinfo { #define OMAP_DSP_MBCMD_PM_ENABLE 0x01 #define OMAP_DSP_MBCMD_KFUNC_FBCTL 0x00 +#define OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR 0x01 #define OMAP_DSP_MBCMD_FBCTL_UPD 0x0000 #define OMAP_DSP_MBCMD_FBCTL_ENABLE 0x0002 #define OMAP_DSP_MBCMD_FBCTL_DISABLE 0x0003 +#define OMAP_DSP_MBCMD_AUDIO_PWR_UP 0x0000 +#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1 0x0001 +#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2 0x0002 + #define OMAP_DSP_MBCMD_TDEL_SAFE 0x0000 #define OMAP_DSP_MBCMD_TDEL_KILL 0x0001 diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h index ca237438080..16a459dfa71 100644 --- a/include/asm-arm/arch-omap/dsp_common.h +++ b/include/asm-arm/arch-omap/dsp_common.h @@ -27,9 +27,12 @@ #ifndef ASM_ARCH_DSP_COMMON_H #define ASM_ARCH_DSP_COMMON_H -void omap_dsp_request_mpui(void); -void omap_dsp_release_mpui(void); -int omap_dsp_request_mem(void); -int omap_dsp_release_mem(void); +extern void omap_dsp_request_mpui(void); +extern void omap_dsp_release_mpui(void); +extern int omap_dsp_request_mem(void); +extern int omap_dsp_release_mem(void); + +extern void (*omap_dsp_audio_pwr_up_request)(int stage); +extern void (*omap_dsp_audio_pwr_down_request)(int stage); #endif /* ASM_ARCH_DSP_COMMON_H */