summaryrefslogtreecommitdiff
path: root/packages/linux/linux-omap2-git/beagleboard
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-omap2-git/beagleboard')
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/cache-display-fix.patch238
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/i2c-omap-race-fix.diff118
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/serialfix.diff18
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/soc.patch233
4 files changed, 481 insertions, 126 deletions
diff --git a/packages/linux/linux-omap2-git/beagleboard/cache-display-fix.patch b/packages/linux/linux-omap2-git/beagleboard/cache-display-fix.patch
new file mode 100644
index 0000000000..c96b95f2f4
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/cache-display-fix.patch
@@ -0,0 +1,238 @@
+On Tue, 2008-07-01 at 06:23 +0100, Dirk Behme wrote:
+> Catalin Marinas wrote:
+> > But, anyway, if you want a patch, Harry is updating it to a recent
+> > kernel.
+>
+> Any news on this? I think there are some people wanting a patch ;)
+
+See below for a preliminary patch updated to 2.6.26-rc8. Note that I
+don't plan to submit it in its current form but clean it up a bit first.
+
+
+Show the cache type of ARMv7 CPUs
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+---
+
+ arch/arm/kernel/setup.c | 137 +++++++++++++++++++++++++++++++++++++++++++++-
+ include/asm-arm/system.h | 18 ++++++
+ 2 files changed, 153 insertions(+), 2 deletions(-)
+
+
+diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
+index 5ae0eb2..0cd238d 100644
+--- a/arch/arm/kernel/setup.c
++++ b/arch/arm/kernel/setup.c
+@@ -256,6 +256,24 @@ static const char *proc_arch[] = {
+ "?(17)",
+ };
+
++static const char *v7_cache_policy[4] = {
++ "reserved",
++ "AVIVT",
++ "VIPT",
++ "PIPT",
++};
++
++static const char *v7_cache_type[8] = {
++ "none",
++ "instruction only",
++ "data only",
++ "separate instruction and data",
++ "unified",
++ "unknown type",
++ "unknown type",
++ "unknown type",
++};
++
+ #define CACHE_TYPE(x) (((x) >> 25) & 15)
+ #define CACHE_S(x) ((x) & (1 << 24))
+ #define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */
+@@ -266,6 +284,22 @@ static const char *proc_arch[] = {
+ #define CACHE_M(y) ((y) & (1 << 2))
+ #define CACHE_LINE(y) ((y) & 3)
+
++#define CACHE_TYPE_V7(x) (((x) >> 14) & 3)
++#define CACHE_UNIFIED(x) ((((x) >> 27) & 7)+1)
++#define CACHE_COHERENT(x) ((((x) >> 24) & 7)+1)
++
++#define CACHE_ID_LEVEL_MASK 7
++#define CACHE_ID_LEVEL_BITS 3
++
++#define CACHE_LINE_V7(v) ((1 << (((v) & 7)+4)))
++#define CACHE_ASSOC_V7(v) ((((v) >> 3) & ((1<<10)-1))+1)
++#define CACHE_SETS_V7(v) ((((v) >> 13) & ((1<<15)-1))+1)
++#define CACHE_SIZE_V7(v) (CACHE_LINE_V7(v)*CACHE_ASSOC_V7(v)*CACHE_SETS_V7(v))
++#define CACHE_WA_V7(v) (((v) & (1<<28)) != 0)
++#define CACHE_RA_V7(v) (((v) & (1<<29)) != 0)
++#define CACHE_WB_V7(v) (((v) & (1<<30)) != 0)
++#define CACHE_WT_V7(v) (((v) & (1<<31)) != 0)
++
+ static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
+ {
+ unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
+@@ -279,11 +313,57 @@ static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
+ CACHE_LINE(cache)));
+ }
+
++static void dump_v7_cache(const char *type, int cpu, unsigned int level)
++{
++ unsigned int cachesize;
++
++ write_extended_cpuid(2,0,0,0,level); /* Set the cache size selection register */
++ write_extended_cpuid(0,7,5,4,0); /* Prefetch flush to wait for above */
++ cachesize = read_extended_cpuid(1,0,0,0);
++
++ printk("CPU%u: %s cache: %d bytes, associativity %d, %d byte lines, %d sets,\n supports%s%s%s%s\n",
++ cpu, type,
++ CACHE_SIZE_V7(cachesize),CACHE_ASSOC_V7(cachesize),
++ CACHE_LINE_V7(cachesize),CACHE_SETS_V7(cachesize),
++ CACHE_WA_V7(cachesize) ? " WA" : "",
++ CACHE_RA_V7(cachesize) ? " RA" : "",
++ CACHE_WB_V7(cachesize) ? " WB" : "",
++ CACHE_WT_V7(cachesize) ? " WT" : "");
++}
++
+ static void __init dump_cpu_info(int cpu)
+ {
+ unsigned int info = read_cpuid(CPUID_CACHETYPE);
+
+- if (info != processor_id) {
++ if (info != processor_id && (info & (1 << 31))) {
++ /* ARMv7 style of cache info register */
++ unsigned int id = read_extended_cpuid(1,0,0,1);
++ unsigned int level = 0;
++ printk("CPU%u: L1 I %s cache. Caches unified at level %u, coherent at level %u\n",
++ cpu,
++ v7_cache_policy[CACHE_TYPE_V7(info)],
++ CACHE_UNIFIED(id),
++ CACHE_COHERENT(id));
++
++ while (id & CACHE_ID_LEVEL_MASK) {
++ printk("CPU%u: Level %u cache is %s\n",
++ cpu, (level >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]);
++
++ if (id & 1) {
++ /* Dump I at this level */
++ dump_v7_cache("I", cpu, level | 1);
++ }
++
++ if (id & (4 | 2)) {
++ /* Dump D or unified at this level */
++ dump_v7_cache((id & 4) ? "unified" : "D", cpu, level);
++ }
++
++ /* Next level out */
++ level += 2;
++ id >>= CACHE_ID_LEVEL_BITS;
++ }
++ } else if (info != processor_id) {
+ printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT",
+ cache_types[CACHE_TYPE(info)]);
+ if (CACHE_S(info)) {
+@@ -916,6 +996,30 @@ c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
+ CACHE_LINE(cache)));
+ }
+
++static void c_show_v7_cache(struct seq_file *m, const char *type, unsigned int levelselect)
++{
++ unsigned int cachesize;
++ unsigned int level = (levelselect >> 1) + 1;
++
++ write_extended_cpuid(2,0,0,0,levelselect); /* Set the cache size selection register */
++ write_extended_cpuid(0,7,5,4,0); /* Prefetch flush to wait for above */
++ cachesize = read_extended_cpuid(1,0,0,0);
++
++ seq_printf(m, "L%u %s size\t\t: %d bytes\n"
++ "L%u %s assoc\t\t: %d\n"
++ "L%u %s line length\t: %d\n"
++ "L%u %s sets\t\t: %d\n"
++ "L%u %s supports\t\t:%s%s%s%s\n",
++ level, type, CACHE_SIZE_V7(cachesize),
++ level, type, CACHE_ASSOC_V7(cachesize),
++ level, type, CACHE_LINE_V7(cachesize),
++ level, type, CACHE_SETS_V7(cachesize),
++ level, type, CACHE_WA_V7(cachesize) ? " WA" : "",
++ CACHE_RA_V7(cachesize) ? " RA" : "",
++ CACHE_WB_V7(cachesize) ? " WB" : "",
++ CACHE_WT_V7(cachesize) ? " WT" : "");
++}
++
+ static int c_show(struct seq_file *m, void *v)
+ {
+ int i;
+@@ -971,7 +1075,36 @@ static int c_show(struct seq_file *m, void *v)
+
+ {
+ unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
+- if (cache_info != processor_id) {
++ if (cache_info != processor_id && (cache_info & (1<<31))) {
++ /* V7 style of cache info register */
++ unsigned int id = read_extended_cpuid(1,0,0,1);
++ unsigned int levelselect = 0;
++ seq_printf(m, "L1 I cache\t:%s\n"
++ "Cache unification level\t: %u\n"
++ "Cache coherency level\t: %u\n",
++ v7_cache_policy[CACHE_TYPE_V7(cache_info)],
++ CACHE_UNIFIED(id),
++ CACHE_COHERENT(id));
++
++ while (id & CACHE_ID_LEVEL_MASK) {
++ seq_printf(m, "Level %u cache\t\t: %s\n",
++ (levelselect >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]);
++
++ if (id & 1) {
++ /* Dump I at this level */
++ c_show_v7_cache(m, "I", levelselect | 1);
++ }
++
++ if (id & (4 | 2)) {
++ /* Dump D or unified at this level */
++ c_show_v7_cache(m, (id & 4) ? "cache" : "D", levelselect);
++ }
++
++ /* Next level out */
++ levelselect += 2;
++ id >>= CACHE_ID_LEVEL_BITS;
++ }
++ } else if (cache_info != processor_id) {
+ seq_printf(m, "Cache type\t: %s\n"
+ "Cache clean\t: %s\n"
+ "Cache lockdown\t: %s\n"
+diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
+index 514af79..704738e 100644
+--- a/include/asm-arm/system.h
++++ b/include/asm-arm/system.h
+@@ -74,6 +74,24 @@
+ : "cc"); \
+ __val; \
+ })
++#define read_extended_cpuid(op1,op2,op3,op4) \
++ ({ \
++ unsigned int __val; \
++ asm("mrc p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4) \
++ : "=r" (__val) \
++ : \
++ : "cc"); \
++ __val; \
++ })
++
++#define write_extended_cpuid(op1,op2,op3,op4,v) \
++ ({ \
++ unsigned int __val = v; \
++ asm("mcr p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4) \
++ : \
++ : "r" (__val) \
++ : "cc"); \
++ })
+ #else
+ extern unsigned int processor_id;
+ #define read_cpuid(reg) (processor_id)
+
+
+--
+Catalin
+
+
diff --git a/packages/linux/linux-omap2-git/beagleboard/i2c-omap-race-fix.diff b/packages/linux/linux-omap2-git/beagleboard/i2c-omap-race-fix.diff
new file mode 100644
index 0000000000..6eb33f76b7
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/i2c-omap-race-fix.diff
@@ -0,0 +1,118 @@
+From linux-omap-owner@vger.kernel.org Tue Jul 15 21:23:13 2008
+Received: from localhost
+ ([127.0.0.1] helo=dominion ident=koen)
+ by dominion.dominion.void with esmtp (Exim 4.69)
+ (envelope-from <linux-omap-owner@vger.kernel.org>)
+ id 1KIq7E-0004FX-VS
+ for koen@localhost; Tue, 15 Jul 2008 21:23:13 +0200
+Received: from xs.service.utwente.nl [130.89.5.250]
+ by dominion with POP3 (fetchmail-6.3.6)
+ for <koen@localhost> (single-drop); Tue, 15 Jul 2008 21:23:12 +0200 (CEST)
+Received: from mail.service.utwente.nl ([130.89.5.254]) by exchange.service.utwente.nl with Microsoft SMTPSVC(6.0.3790.3959);
+ Tue, 15 Jul 2008 21:01:02 +0200
+Received: from mx.utwente.nl ([130.89.2.12]) by mail.service.utwente.nl with Microsoft SMTPSVC(6.0.3790.3959);
+ Tue, 15 Jul 2008 21:01:01 +0200
+Received: from vger.kernel.org (vger.kernel.org [209.132.176.167])
+ by mx.utwente.nl (8.12.10/SuSE Linux 0.7) with ESMTP id m6FJ0qDf031889
+ for <k.kooi@student.utwente.nl>; Tue, 15 Jul 2008 21:00:52 +0200
+Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
+ id S1756776AbYGOTAV (ORCPT <rfc822;k.kooi@student.utwente.nl>);
+ Tue, 15 Jul 2008 15:00:21 -0400
+Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755065AbYGOTAV
+ (ORCPT <rfc822;linux-omap-outgoing>);
+ Tue, 15 Jul 2008 15:00:21 -0400
+Received: from utopia.booyaka.com ([72.9.107.138]:35569 "EHLO
+ utopia.booyaka.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
+ with ESMTP id S1756776AbYGOTAU (ORCPT
+ <rfc822;linux-omap@vger.kernel.org>); Tue, 15 Jul 2008 15:00:20 -0400
+Received: (qmail 2982 invoked by uid 526); 15 Jul 2008 19:00:18 -0000
+Date: Tue, 15 Jul 2008 13:00:18 -0600 (MDT)
+From: Paul Walmsley <paul@pwsan.com>
+To: linux-omap@vger.kernel.org
+Subject: [PATCH] i2c-omap: close suspected race between omap_i2c_idle() and
+ omap_i2c_isr()
+Message-ID: <alpine.DEB.1.00.0807151259180.467@utopia.booyaka.com>
+User-Agent: Alpine 1.00 (DEB 882 2007-12-20)
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Sender: linux-omap-owner@vger.kernel.org
+Precedence: bulk
+List-ID: <linux-omap.vger.kernel.org>
+X-Mailing-List: linux-omap@vger.kernel.org
+X-UTwente-MailScanner-Information: Scanned by MailScanner. Contact servicedesk@icts.utwente.nl for more information.
+X-UTwente-MailScanner: Found to be clean
+X-UTwente-MailScanner-From: linux-omap-owner@vger.kernel.org
+X-Spam-Status: No
+X-OriginalArrivalTime: 15 Jul 2008 19:01:01.0610 (UTC) FILETIME=[1FBA68A0:01C8E6AD]
+
+
+omap_i2c_idle() sets an internal flag, "dev->idle", instructing its
+ISR to decline interrupts. It sets this flag before it actually masks
+the interrupts on the I2C controller. This is problematic, since an
+I2C interrupt could arrive after dev->idle is set, but before the
+interrupt source is masked. When this happens, Linux disables the I2C
+controller's IRQ, causing all future transactions on the bus to fail.
+
+Symptoms, happening on about 7% of boots:
+
+ irq 56: nobody cared (try booting with the "irqpoll" option)
+ <warning traceback here>
+ Disabling IRQ #56
+ i2c_omap i2c_omap.1: controller timed out
+
+In omap_i2c_idle(), this patch sets dev->idle only after the interrupt
+mask write to the I2C controller has left the ARM write buffer.
+That's probably the major offender. For additional prophylaxis, in
+omap_i2c_unidle(), the patch clears the dev->idle flag before
+interrupts are enabled, rather than afterwards.
+
+The patch has survived twenty-two reboots on the 3430SDP here without
+wedging I2C1. Not absolutely dispositive, but promising!
+
+
+Signed-off-by: Paul Walmsley <paul@pwsan.com>
+---
+
+ drivers/i2c/busses/i2c-omap.c | 10 ++++++++--
+ 1 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
+index 55779f5..ed7e9ad 100644
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -209,22 +209,28 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
+ if (dev->iclk != NULL)
+ clk_enable(dev->iclk);
+ clk_enable(dev->fclk);
++ dev->idle = 0;
+ if (dev->iestate)
+ omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+- dev->idle = 0;
+ }
+
+ static void omap_i2c_idle(struct omap_i2c_dev *dev)
+ {
+ u16 iv;
+
+- dev->idle = 1;
+ dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+ omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
+ if (dev->rev1)
+ iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
+ else
+ omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
++ /*
++ * The wmb() is to ensure that the I2C interrupt mask write
++ * reaches the I2C controller before the dev->idle store
++ * occurs.
++ */
++ wmb();
++ dev->idle = 1;
+ clk_disable(dev->fclk);
+ if (dev->iclk != NULL)
+ clk_disable(dev->iclk);
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
diff --git a/packages/linux/linux-omap2-git/beagleboard/serialfix.diff b/packages/linux/linux-omap2-git/beagleboard/serialfix.diff
new file mode 100644
index 0000000000..74c2ebaa69
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/serialfix.diff
@@ -0,0 +1,18 @@
+--- /tmp/pm34xx.c 2008-07-14 18:09:08.000000000 +0200
++++ git/arch/arm/mach-omap2/pm34xx.c 2008-07-14 18:09:42.453198000 +0200
+@@ -398,13 +398,13 @@
+ INT_34XX_PRCM_MPU_IRQ);
+ goto err1;
+ }
+-
++/*
+ ret = pwrdm_for_each(pwrdms_setup);
+ if (ret) {
+ printk(KERN_ERR "Failed to setup powerdomains\n");
+ goto err2;
+ }
+-
++*/
+ mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
+ if (mpu_pwrdm == NULL) {
+ printk(KERN_ERR "Failed to get mpu_pwrdm\n");
diff --git a/packages/linux/linux-omap2-git/beagleboard/soc.patch b/packages/linux/linux-omap2-git/beagleboard/soc.patch
index bb97403f29..f4cce21ca7 100644
--- a/packages/linux/linux-omap2-git/beagleboard/soc.patch
+++ b/packages/linux/linux-omap2-git/beagleboard/soc.patch
@@ -29,10 +29,10 @@ index 4e1314c..d2c0b12 100644
+obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
new file mode 100644
-index 0000000..c9eee19
+index 0000000..eb8370c
--- /dev/null
+++ b/sound/soc/codecs/twl4030.c
-@@ -0,0 +1,595 @@
+@@ -0,0 +1,625 @@
+/*
+ * ALSA SoC TWL4030 codec driver
+ *
@@ -196,7 +196,7 @@ index 0000000..c9eee19
+ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ twl4030_reg[REG_CODEC_MODE] & 0xfd, REG_CODEC_MODE);
+
-+ udelay(10); /* 10 ms delay for power settling */
++ udelay(10); /* delay for power settling */
+
+ for (i = REG_OPTION; i <= REG_MISC_SET_2; i++) {
+ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, twl4030_reg[i], i);
@@ -205,7 +205,7 @@ index 0000000..c9eee19
+ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ twl4030_reg[REG_CODEC_MODE], REG_CODEC_MODE);
+
-+ udelay(10); /* 10 ms delay for power settling */
++ udelay(10); /* delay for power settling */
+
+ /* initiate offset cancellation */
+ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
@@ -219,7 +219,6 @@ index 0000000..c9eee19
+ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ twl4030_reg[REG_MISC_SET_1] | 0x02, REG_MISC_SET_1);
+
-+ twl4030_dump_registers();
+}
+
+static const struct snd_kcontrol_new twl4030_snd_controls[] = {
@@ -247,8 +246,6 @@ index 0000000..c9eee19
+ return 0;
+}
+
-+#define TWL4030_PWR 0
-+
+static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("INL"),
+ SND_SOC_DAPM_INPUT("INR"),
@@ -314,32 +311,40 @@ index 0000000..c9eee19
+
+static void twl4030_power_up (struct snd_soc_codec *codec, u8 mode)
+{
++ u8 popn, hsgain;
++
+ twl4030_write(codec, REG_CODEC_MODE, mode & ~CODECPDZ);
+ twl4030_write(codec, REG_CODEC_MODE, mode | CODECPDZ);
+ udelay(10);
+
-+ u8 popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET) | (0x40);
++ popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET);
++ popn &= RAMP_DELAY;
++ popn |= VMID_EN | RAMP_DELAY_161MS;
+ twl4030_write(codec, REG_HS_POPN_SET, popn);
+
-+ u8 hsgain = twl4030_read_reg_cache(codec, REG_HS_GAIN_SET) | (0x0a);
++ hsgain = HSR_GAIN_0DB| HSL_GAIN_0DB;
+ twl4030_write(codec, REG_HS_GAIN_SET, hsgain);
+
-+ popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET) | (0x02);
++ popn |= RAMP_EN;
+ twl4030_write(codec, REG_HS_POPN_SET, popn);
+}
+
+static void twl4030_power_down (struct snd_soc_codec *codec)
+{
-+ u8 popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET) & ~(0x02);
++ u8 popn, hsgain, mode;
++
++ popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET);
++ popn &= ~RAMP_EN;
+ twl4030_write(codec, REG_HS_POPN_SET, popn);
+
-+ u8 hsgain = twl4030_read_reg_cache(codec, REG_HS_GAIN_SET) & ~(0x0f);
++ hsgain = HSR_GAIN_PWR_DOWN | HSL_GAIN_PWR_DOWN;
+ twl4030_write(codec, REG_HS_GAIN_SET, hsgain);
+
-+ popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET) & ~(0x40);
++ popn &= ~VMID_EN;
+ twl4030_write(codec, REG_HS_POPN_SET, popn);
+
-+ u8 mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE) & ~CODECPDZ;
++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE);
++ mode &= ~CODECPDZ;
+ twl4030_write(codec, REG_CODEC_MODE, mode);
+ udelay(10);
+}
@@ -352,19 +357,18 @@ index 0000000..c9eee19
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct twl4030_priv *twl4030 = codec->private_data;
++ u8 mode, old_mode, format, old_format;
+
-+ twl4030_power_down(codec);
-+
-+ u8 mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE) & ~CODECPDZ;
+
++ /* bit rate */
++ old_mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE) & ~CODECPDZ;
++ mode = old_mode;
+ mode &= ~APLL_RATE;
+ switch (params_rate(params)) {
+ case 44100:
-+ printk(KERN_INFO "TWL4030 hw params: set rate to 44.1khz\n");
+ mode |= APLL_RATE_44100;
+ break;
+ case 48000:
-+ printk(KERN_INFO "TWL4030 hw params: set rate to 48khz\n");
+ mode |= APLL_RATE_48000;
+ break;
+ default:
@@ -372,22 +376,43 @@ index 0000000..c9eee19
+ return -EINVAL;
+ }
+
-+ /* bit size */
++ if (mode != old_mode) {
++ /* change rate and turn codec back on */
++ twl4030_write(codec, REG_CODEC_MODE, mode);
++ mode |= CODECPDZ;
++ twl4030_write(codec, REG_CODEC_MODE, mode);
++ }
++
++ /* sample size */
++ old_format = twl4030_read_reg_cache(codec, REG_AUDIO_IF);
++ format = old_format;
++ format &= ~DATA_WIDTH;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
-+ printk(KERN_INFO "TWL4030 hw params: set format to S16_LE\n");
++ format |= DATA_WIDTH_16S_16W;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
-+ printk(KERN_INFO "TWL4030 hw params: set format to S24_LE\n");
++ format |= DATA_WIDTH_32S_24W;
+ break;
+ default:
+ printk(KERN_INFO "TWL4030 hw params: unknown format %d\n", params_format(params));
+ return -EINVAL;
+ }
+
-+ /* change rate and turn codec back on */
-+ twl4030_power_up(codec, mode);
++ if (format != old_format) {
++
++ /* turn off codec before changing format */
++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE);
++ mode &= ~CODECPDZ;
++ twl4030_write(codec, REG_CODEC_MODE, mode);
+
++ /* change format */
++ twl4030_write(codec, REG_AUDIO_IF, format);
++
++ /* turn on codec */
++ mode |= CODECPDZ;
++ twl4030_write(codec, REG_CODEC_MODE, mode);
++ }
+ return 0;
+}
+
@@ -399,14 +424,14 @@ index 0000000..c9eee19
+ u8 rdac_reg = twl4030_read_reg_cache(codec, REG_ARXR2PGA);
+
+ if (mute) {
-+ printk(KERN_INFO "TWL4030 Audio Codec mute\n");
++ /* printk(KERN_INFO "TWL4030 Audio Codec mute\n"); */
+ twl4030_write(codec, REG_ARXL2PGA, 0x00);
+ twl4030_write(codec, REG_ARXR2PGA, 0x00);
+ twl4030_write_reg_cache(codec, REG_ARXL2PGA, ldac_reg);
+ twl4030_write_reg_cache(codec, REG_ARXR2PGA, rdac_reg);
+ }
+ else {
-+ printk(KERN_INFO "TWL4030 Audio Codec unmute: %02x/%02x\n", ldac_reg, rdac_reg);
++ /* printk(KERN_INFO "TWL4030 Audio Codec unmute: %02x/%02x\n", ldac_reg, rdac_reg); */
+ twl4030_write(codec, REG_ARXL2PGA, ldac_reg);
+ twl4030_write(codec, REG_ARXR2PGA, rdac_reg);
+ }
@@ -419,19 +444,21 @@ index 0000000..c9eee19
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct twl4030_priv *twl4030 = codec->private_data;
++ u8 mode, old_format, format;
+
-+ /* get current format */
-+ u8 format = twl4030_read_reg_cache(codec, REG_AUDIO_IF);
++ /* get format */
++ old_format = twl4030_read_reg_cache(codec, REG_AUDIO_IF);
++ format = old_format;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
-+ printk(KERN_INFO "TWL4030 set dai fmt: master\n");
++ /* printk(KERN_INFO "TWL4030 set dai fmt: master\n"); */
+ format &= ~(AIF_SLAVE_EN);
+ format |= CLK256FS_EN;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
-+ printk(KERN_INFO "TWL4030 set dai fmt: slave\n");
++ /* printk(KERN_INFO "TWL4030 set dai fmt: slave\n"); */
+ format &= ~(CLK256FS_EN);
+ format |= AIF_SLAVE_EN;
+ break;
@@ -443,21 +470,26 @@ index 0000000..c9eee19
+ format &= ~AIF_FORMAT;
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
-+ printk(KERN_INFO "TWL4030 set dai fmt: i2s\n");
++ /* printk(KERN_INFO "TWL4030 set dai fmt: i2s\n"); */
+ format |= AIF_FORMAT_CODEC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
-+ /* turn off codec before changing format */
-+ twl4030_power_down(codec);
++ if (format != old_format) {
+
-+ /* change format */
-+ twl4030_write(codec, REG_AUDIO_IF, format);
++ /* turn off codec before changing format */
++ mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE);
++ mode &= ~CODECPDZ;
++ twl4030_write(codec, REG_CODEC_MODE, mode);
+
-+ u8 mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE);
-+ twl4030_power_up(codec, mode);
++ /* change format */
++ twl4030_write(codec, REG_AUDIO_IF, format);
++
++ mode |= CODECPDZ;
++ twl4030_write(codec, REG_CODEC_MODE, mode);
++ }
+
+ return 0;
+}
@@ -530,8 +562,6 @@ index 0000000..c9eee19
+
+ printk(KERN_INFO "TWL4030 Audio Codec init \n");
+
-+ twl4030_init_chip();
-+
+ codec->name = "twl4030";
+ codec->owner = THIS_MODULE;
+ codec->read = twl4030_read_reg_cache;
@@ -560,6 +590,9 @@ index 0000000..c9eee19
+ goto card_err;
+ }
+
++ twl4030_init_chip();
++ twl4030_power_up(codec, APLL_RATE_44100 | OPT_MODE);
++
+ return ret;
+
+card_err:
@@ -580,8 +613,6 @@ index 0000000..c9eee19
+ struct snd_soc_codec *codec;
+ struct twl4030_priv *twl4030;
+
-+ printk(KERN_INFO "TWL4030 Audio Codec probe\n");
-+
+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (codec == NULL)
+ return -ENOMEM;
@@ -601,7 +632,6 @@ index 0000000..c9eee19
+ twl4030_socdev = socdev;
+ twl4030_init(socdev);
+
-+ printk(KERN_INFO "TWL4030 Audio Codec probe exit\n");
+ return 0;
+}
+
@@ -630,10 +660,10 @@ index 0000000..c9eee19
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
new file mode 100644
-index 0000000..af8eb43
+index 0000000..e126f96
--- /dev/null
+++ b/sound/soc/codecs/twl4030.h
-@@ -0,0 +1,125 @@
+@@ -0,0 +1,152 @@
+/*
+ * ALSA SoC TWL4030 codec driver
+ *
@@ -722,7 +752,7 @@ index 0000000..af8eb43
+
+/* Bitfield Definitions */
+
-+/* CODEC_MODE Fields */
++/* CODEC_MODE (0x01) Fields */
+
+#define APLL_RATE 0xF0
+#define APLL_RATE_8000 0x00
@@ -738,7 +768,7 @@ index 0000000..af8eb43
+#define CODECPDZ 0x02
+#define OPT_MODE 0x01
+
-+/* AUDIO_IF Fields */
++/* AUDIO_IF (0x0E) Fields */
+
+#define AIF_SLAVE_EN 0x80
+#define DATA_WIDTH 0x60
@@ -754,6 +784,33 @@ index 0000000..af8eb43
+#define CLK256FS_EN 0x02
+#define AIF_EN 0x01
+
++/* HS_GAIN_SET (0x23) Fields */
++
++#define HSR_GAIN 0x0c
++#define HSR_GAIN_PWR_DOWN 0x00
++#define HSR_GAIN_PLUS_6DB 0x04
++#define HSR_GAIN_0DB 0x08
++#define HSR_GAIN_MINUS_6DB 0x0c
++#define HSL_GAIN 0x0c
++#define HSL_GAIN_PWR_DOWN 0x00
++#define HSL_GAIN_PLUS_6DB 0x01
++#define HSL_GAIN_0DB 0x02
++#define HSL_GAIN_MINUS_6DB 0x03
++
++/* HS_POPN_SET (0x24) Fields */
++
++#define VMID_EN 0x40
++#define EXTMUTE 0x20
++#define RAMP_DELAY 0x1C
++#define RAMP_DELAY_20MS 0x00
++#define RAMP_DELAY_40MS 0x04
++#define RAMP_DELAY_81MS 0x08
++#define RAMP_DELAY_161MS 0x0c
++#define RAMP_DELAY_323MS 0x10
++#define RAMP_DELAY_645MS 0x14
++#define RAMP_DELAY_1291MS 0x18
++#define RAMP_DELAY_2581MS 0x1c
++#define RAMP_EN 0x02
+
+extern struct snd_soc_codec_dai twl4030_dai;
+extern struct snd_soc_codec_device soc_codec_dev_twl4030;
@@ -801,10 +858,10 @@ index d8d8d58..638a240 100644
+
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
new file mode 100644
-index 0000000..fb79938
+index 0000000..878f894
--- /dev/null
+++ b/sound/soc/omap/omap3beagle.c
-@@ -0,0 +1,180 @@
+@@ -0,0 +1,142 @@
+/*
+ * omap3beagle.c -- SoC audio for OMAP3 Beagle
+ *
@@ -877,50 +934,12 @@ index 0000000..fb79938
+ .hw_params = omap3beagle_hw_params,
+};
+
-+static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
-+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
-+ SND_SOC_DAPM_LINE("Line In", NULL),
-+};
-+
-+static const char *audio_map[][3] = {
-+ {"Headphone Jack", NULL, "HPLOUT"},
-+ {"Headphone Jack", NULL, "HPROUT"},
-+
-+ {"Line In", NULL, "Line In"},
-+ {"Line In", NULL, "Line In"},
-+};
-+
-+static int omap3beagle_twl4030_init(struct snd_soc_codec *codec)
-+{
-+ int i;
-+
-+ printk(KERN_INFO "OMAP3 Beagle TWL4030 SoC init\n");
-+
-+ /* Add omap3beagle specific widgets */
-+ for (i = 0; i < ARRAY_SIZE(twl4030_dapm_widgets); i++)
-+ snd_soc_dapm_new_control(codec, &twl4030_dapm_widgets[i]);
-+
-+ /* Set up omap3beagle specific audio path audio_map */
-+ for (i = 0; i < ARRAY_SIZE(audio_map); i++)
-+ snd_soc_dapm_connect_input(codec, audio_map[i][0],
-+ audio_map[i][1], audio_map[i][2]);
-+
-+ /* always connected */
-+ snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
-+ snd_soc_dapm_set_endpoint(codec, "Line In", 1);
-+
-+ snd_soc_dapm_sync_endpoints(codec);
-+
-+ return 0;
-+}
-+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap3beagle_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
-+ .init = omap3beagle_twl4030_init,
+ .ops = &omap3beagle_ops,
+};
+
@@ -987,10 +1006,10 @@ index 0000000..fb79938
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
new file mode 100644
-index 0000000..32d4f5d
+index 0000000..a64c788
--- /dev/null
+++ b/sound/soc/omap/omap3evm.c
-@@ -0,0 +1,180 @@
+@@ -0,0 +1,142 @@
+/*
+ * omap3evm.c -- SoC audio for OMAP3 EVM
+ *
@@ -1063,50 +1082,12 @@ index 0000000..32d4f5d
+ .hw_params = omap3evm_hw_params,
+};
+
-+static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
-+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
-+ SND_SOC_DAPM_LINE("Line In", NULL),
-+};
-+
-+static const char *audio_map[][3] = {
-+ {"Headphone Jack", NULL, "HPLOUT"},
-+ {"Headphone Jack", NULL, "HPROUT"},
-+
-+ {"Line In", NULL, "Line In"},
-+ {"Line In", NULL, "Line In"},
-+};
-+
-+static int omap3evm_twl4030_init(struct snd_soc_codec *codec)
-+{
-+ int i;
-+
-+ printk(KERN_INFO "OMAP3 EVM TWL4030 SoC init\n");
-+
-+ /* Add omap3evm specific widgets */
-+ for (i = 0; i < ARRAY_SIZE(twl4030_dapm_widgets); i++)
-+ snd_soc_dapm_new_control(codec, &twl4030_dapm_widgets[i]);
-+
-+ /* Set up omap3evm specific audio path audio_map */
-+ for (i = 0; i < ARRAY_SIZE(audio_map); i++)
-+ snd_soc_dapm_connect_input(codec, audio_map[i][0],
-+ audio_map[i][1], audio_map[i][2]);
-+
-+ /* always connected */
-+ snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
-+ snd_soc_dapm_set_endpoint(codec, "Line In", 1);
-+
-+ snd_soc_dapm_sync_endpoints(codec);
-+
-+ return 0;
-+}
-+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap3evm_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
-+ .init = omap3evm_twl4030_init,
+ .ops = &omap3evm_ops,
+};
+