]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
ARM: OMAP: Add audio power control interface for DSP Gateway
authorToshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
Wed, 1 Mar 2006 11:13:36 +0000 (13:13 +0200)
committerJuha Yrjola <juha.yrjola@nokia.com>
Wed, 1 Mar 2006 11:13:36 +0000 (13:13 +0200)
Signed-off-by: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
Signed-off-by: Juha Yrjölä <juha.yrjola@nokia.com>
arch/arm/mach-omap1/board-nokia770.c
arch/arm/plat-omap/dsp/dsp_common.c
arch/arm/plat-omap/dsp/dsp_core.c
arch/arm/plat-omap/dsp/mblog.c
include/asm-arm/arch-omap/aic23.h
include/asm-arm/arch-omap/dsp.h
include/asm-arm/arch-omap/dsp_common.h

index 3298864ab633965b918e90926fc12e1fa1c2e38b..8133b5944abebc92eb9581ada47175835124c8aa 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
+#include <linux/clk.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -27,6 +28,9 @@
 #include <asm/arch/board.h>
 #include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/aic23.h>
+#include <asm/arch/gpio.h>
 
 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)
index 22c931c29c421f399c22d59b14f64b2d0368a2be..9c701567f1f09a2b83ecbc54174779dcf9fad1b1 100644 (file)
@@ -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);
index a77216a454dc132fd2f9eb1f8d6da9a3a4cff6ad..42565774988cde43b5aa5f346a47adb8f2a0f766 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/signal.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
+#include <asm/arch/dsp_common.h>
 #include <asm/arch/dsp.h>
 #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);
index 0edf07079edffc28c40101a54554b06c0370c392..3298976602028ee7cc779d5145510783464c3487 100644 (file)
@@ -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):
index b46885f3a92e8d7cdc667be629e40ef9a428a994..6513065941d0872753ba5ded51dec517f82393de 100644 (file)
 #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 */
index ec834b381586997759035db2940a19ed9b9f97b0..06dad83dd41f1c7116409a64e6ad12803d9c5ff5 100644 (file)
@@ -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
 
index ca2374380809742d245af3b3fd5d30c6e00d514f..16a459dfa714ab770da53bff8680d90a36a70d6c 100644 (file)
 #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 */