/*
- * linux/arch/arm/mach-omap/omap2/board-n800-audio.c
+ * linux/arch/arm/mach-omap2/board-n800-audio.c
*
* Copyright (C) 2006 Nokia Corporation
- * Contact: Juha Yrj?l?
+ * Contact: Juha Yrjola
* Jarkko Nikula <jarkko.nikula@nokia.com>
*
* This program is free software; you can redistribute it and/or
#include <linux/err.h>
#include <linux/clk.h>
-#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/spi/tsc2301.h>
#include <asm/io.h>
#include <asm/arch/eac.h>
-#include "../plat-omap/dsp/dsp_common.h"
+#include <asm/arch/dsp_common.h>
#if defined(CONFIG_SPI_TSC2301_AUDIO) && defined(CONFIG_SND_OMAP24XX_EAC)
#define AUDIO_ENABLED
static struct clk *sys_clkout2;
+static struct clk *sys_clkout2_src;
static struct clk *func96m_clk;
static struct device *eac_device;
static struct device *tsc2301_device;
static int audio_ok;
static spinlock_t audio_lock;
-
/*
- * Leaving EAC pins multiplexed to EAC functionality results
- * in about 2 mA extra current leaked. The workaround is to
- * multiplex the EAC pins to protected mode (with pull-ups enabled)
+ * Leaving EAC and sys_clkout2 pins multiplexed to those subsystems results
+ * in about 2 mA extra current leak when audios are powered down. The
+ * workaround is to multiplex them to protected mode (with pull-ups enabled)
* whenever audio is not being used.
*/
-static int mux_disabled;
+static int eac_mux_disabled = 0;
+static int clkout2_mux_disabled = 0;
static u32 saved_mux[2];
+#define MUX_EAC_IOP2V(x) (__force void __iomem *)io_p2v(x)
+
static void n800_enable_eac_mux(void)
{
- if (!mux_disabled)
+ if (!eac_mux_disabled)
return;
- __raw_writel(saved_mux[0], IO_ADDRESS(0x480000e8));
- __raw_writel(saved_mux[1], IO_ADDRESS(0x48000124));
- mux_disabled = 0;
+ __raw_writel(saved_mux[1], MUX_EAC_IOP2V(0x48000124));
+ eac_mux_disabled = 0;
}
static void n800_disable_eac_mux(void)
+{
+ if (eac_mux_disabled) {
+ WARN_ON(eac_mux_disabled);
+ return;
+ }
+ saved_mux[1] = __raw_readl(MUX_EAC_IOP2V(0x48000124));
+ __raw_writel(0x1f1f1f1f, MUX_EAC_IOP2V(0x48000124));
+ eac_mux_disabled = 1;
+}
+
+static void n800_enable_clkout2_mux(void)
+{
+ if (!clkout2_mux_disabled)
+ return;
+ __raw_writel(saved_mux[0], MUX_EAC_IOP2V(0x480000e8));
+ clkout2_mux_disabled = 0;
+}
+
+static void n800_disable_clkout2_mux(void)
{
u32 l;
- if (mux_disabled) {
- WARN_ON(mux_disabled);
+ if (clkout2_mux_disabled) {
+ WARN_ON(clkout2_mux_disabled);
return;
}
- saved_mux[0] = __raw_readl(IO_ADDRESS(0x480000e8));
- saved_mux[1] = __raw_readl(IO_ADDRESS(0x48000124));
+ saved_mux[0] = __raw_readl(MUX_EAC_IOP2V(0x480000e8));
l = saved_mux[0] & ~0xff;
l |= 0x1f;
- __raw_writel(l, IO_ADDRESS(0x480000e8));
- __raw_writel(0x1f1f1f1f, IO_ADDRESS(0x48000124));
- mux_disabled = 1;
+ __raw_writel(l, MUX_EAC_IOP2V(0x480000e8));
+ clkout2_mux_disabled = 1;
}
static int n800_eac_enable_ext_clocks(struct device *dev)
{
BUG_ON(tsc2301_device == NULL);
n800_enable_eac_mux();
- tsc2301_enable_mclk(tsc2301_device);
+ tsc2301_mixer_enable_mclk(tsc2301_device);
return 0;
}
static void n800_eac_disable_ext_clocks(struct device *dev)
{
BUG_ON(tsc2301_device == NULL);
+ tsc2301_mixer_disable_mclk(tsc2301_device);
n800_disable_eac_mux();
- tsc2301_disable_mclk(tsc2301_device);
}
static int n800_audio_set_power(void *pdata, int dac, int adc)
static struct eac_codec n800_eac_codec = {
.mclk_src = EAC_MCLK_EXT_2x12288000,
- .codec_mode = EAC_CODEC_I2S,
+ .codec_mode = EAC_CODEC_I2S_MASTER,
.codec_conf.i2s.polarity_changed_mode = 0,
.codec_conf.i2s.sync_delay_enable = 0,
.default_rate = 48000,
static int n800_codec_get_clocks(struct device *dev)
{
+ sys_clkout2_src = clk_get(dev, "sys_clkout2_src");
+ if (IS_ERR(sys_clkout2_src)) {
+ dev_err(dev, "Could not get sys_clkout2_src clock\n");
+ return -ENODEV;
+ }
sys_clkout2 = clk_get(dev, "sys_clkout2");
if (IS_ERR(sys_clkout2)) {
- printk(KERN_ERR "Could not get sys_clkout2\n");
+ dev_err(dev, "Could not get sys_clkout2 clock\n");
+ clk_put(sys_clkout2_src);
return -ENODEV;
}
/* configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
* 96 MHz as its parent in order to get 12 MHz */
func96m_clk = clk_get(dev, "func_96m_ck");
if (IS_ERR(func96m_clk)) {
- printk(KERN_ERR "could not get func 96M clock\n");
+ dev_err(dev, "Could not get func 96M clock\n");
clk_put(sys_clkout2);
+ clk_put(sys_clkout2_src);
return -ENODEV;
}
- clk_set_parent(sys_clkout2, func96m_clk);
+ clk_set_parent(sys_clkout2_src, func96m_clk);
clk_set_rate(sys_clkout2, 12000000);
return 0;
{
clk_put(func96m_clk);
clk_put(sys_clkout2);
+ clk_put(sys_clkout2_src);
}
static int n800_codec_enable_clock(struct device *dev)
{
- int err;
-
- err = clk_enable(sys_clkout2);
- if (err)
- return err;
- /* TODO: 'educated' guess for audio codec's PLL startup delay */
- mdelay(1);
-
- return 0;
+ n800_enable_clkout2_mux();
+ return clk_enable(sys_clkout2);
}
static void n800_codec_disable_clock(struct device *dev)
{
clk_disable(sys_clkout2);
+ n800_disable_clkout2_mux();
}
static int n800_codec_init(struct device *dev)
#else
-void __init n800_audio_init(void)
+void __init n800_audio_init(struct tsc2301_platform_data *tc)
{
}