1
0
mirror of https://git.yoctoproject.org/meta-ti synced 2026-01-12 01:20:20 +00:00

linux-omap: update to 2.6.37-final

Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
This commit is contained in:
Koen Kooi
2011-01-12 22:15:29 +01:00
parent 5e33c64e08
commit c931af0807
122 changed files with 8025 additions and 114 deletions

View File

@@ -1,7 +1,7 @@
From c818eb868fd5621ad373e508fbb71b69739a56c1 Mon Sep 17 00:00:00 2001
From 5bae403e0f66a67c222ce124422d43b8b9307041 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Thu, 7 Oct 2010 09:25:45 +0200
Subject: [PATCH 01/29] ARM: OMAP: Power on EHCI, serial, camera and DVI on beagleboard-xM
Subject: [PATCH 01/26] ARM: OMAP: Power on EHCI, serial, camera and DVI on beagleboard-xM
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---

View File

@@ -1,7 +1,7 @@
From 3adfccd800f37f6d4eac565366b86cafe96b487a Mon Sep 17 00:00:00 2001
From 3258ce5493fd9e603a31cc4156892f08ee1500e9 Mon Sep 17 00:00:00 2001
From: Robert Nelson <robertcnelson@gmail.com>
Date: Tue, 9 Nov 2010 08:34:55 -0600
Subject: [PATCH 02/29] omap: Beagle: detect new xM revision B
Subject: [PATCH 02/26] omap: Beagle: detect new xM revision B
The xM B uses a DM3730 ES1.1 over the ES1.0 on xM A's, no other board changes.

View File

@@ -1,7 +1,7 @@
From c857174c0394df227696d145fb1f15a33d870600 Mon Sep 17 00:00:00 2001
From 116a1ffd21e520b0a6c7a91576605bc6151138cb Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Wed, 6 Oct 2010 10:19:34 +0200
Subject: [PATCH 03/29] ARM: OMAP: beagleboard: Add infrastructure to do fixups based on expansionboard name passed by u-boot
Subject: [PATCH 03/26] ARM: OMAP: beagleboard: Add infrastructure to do fixups based on expansionboard name passed by u-boot
Add support for Tincantools Zippy and Zippy2 expansionboards as well

View File

@@ -1,7 +1,7 @@
From 35b474d13b609841faa420a763c7a6d9cb13ce66 Mon Sep 17 00:00:00 2001
From 64215e5d75084b49c490d2aad78c8d3702e6c419 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Sun, 5 Dec 2010 13:25:00 +0100
Subject: [PATCH 04/29] ARM: OMAP: beagleboard: pre-export GPIOs to userspace when using a Tincantools trainerboard
Subject: [PATCH 04/26] ARM: OMAP: beagleboard: pre-export GPIOs to userspace when using a Tincantools trainerboard
This really needs a for loop, patches welcome

View File

@@ -1,7 +1,7 @@
From 1db89a463f04db7c5f6b027910c41f438739e14f Mon Sep 17 00:00:00 2001
From 84b16387417976abbba2dd1608147ab0c7692093 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Mon, 8 Mar 2010 14:38:31 +0100
Subject: [PATCH 05/29] modedb.c: add proper 720p60 mode
Subject: [PATCH 05/26] modedb.c: add proper 720p60 mode
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---

View File

@@ -1,7 +1,7 @@
From db401a606f8bb40accbb5a560e445edc29ab995e Mon Sep 17 00:00:00 2001
From 11aba6aa87fc0d7c452324d002578aa54d3c9a6b Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Mon, 4 Jan 2010 19:20:25 -0800
Subject: [PATCH 06/29] mmc: don't display single block read console messages
Subject: [PATCH 06/26] mmc: don't display single block read console messages
mmc: don't display single block read console messages
---

View File

@@ -1,7 +1,7 @@
From 461835a249017f6e96902f509c78e03ef26ef2a9 Mon Sep 17 00:00:00 2001
From 7f3e88e66f1dd872ed087372d6cd81fce5d96d24 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Mon, 26 Apr 2010 11:17:26 -0700
Subject: [PATCH 07/29] MTD: silence ecc errors on mtdblock0
Subject: [PATCH 07/26] MTD: silence ecc errors on mtdblock0
mtdblock0 is the x-load partition, which uses hw ecc
this confuses linux, which uses sw ecc

View File

@@ -1,7 +1,7 @@
From 8aa41351f7c9e1f846a3d6e1e4bbd3a85a87d10c Mon Sep 17 00:00:00 2001
From d7dbe93075a4e7b5c0fa2a2b745440a53ad26a72 Mon Sep 17 00:00:00 2001
From: Mike Galbraith <efault@gmx.de>
Date: Fri, 19 Nov 2010 12:52:42 +0100
Subject: [PATCH 08/29] Miracle patch
Subject: [PATCH 08/26] Miracle patch
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@@ -113,7 +113,7 @@ Signed-off-by: Mike Galbraith <efault@gmx.de>
create mode 100644 kernel/sched_autogroup.h
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 8b61c93..9408728 100644
index 01ece1b..1031923 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1622,6 +1622,8 @@ and is between 256 and 4096 characters. It is defined in the file

View File

@@ -1,7 +1,7 @@
From b86550d1c9423b9609cc7260fe723881879989af Mon Sep 17 00:00:00 2001
From d378376ed64b5506c352b33085baeb21013e55f2 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Tue, 23 Nov 2010 11:40:20 +0100
Subject: [PATCH 09/29] ARM: OMAP: add omap_rev_* macros
Subject: [PATCH 09/26] ARM: OMAP: add omap_rev_* macros
This is just to make the SGX modules build that depend on omap_rev_lt_3_0

View File

@@ -1,7 +1,7 @@
From de23d5117cbd6bb7accd92a9a6628e688d9f5fa2 Mon Sep 17 00:00:00 2001
From b5e34d9e5b20b412686f84ea8f4e56245f7d5f7f Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Mon, 10 May 2010 20:44:09 -0700
Subject: [PATCH 10/29] OMAP: DSS2: enable hsclk in dsi_pll_init for OMAP36XX
Subject: [PATCH 10/26] OMAP: DSS2: enable hsclk in dsi_pll_init for OMAP36XX
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---

View File

@@ -1,7 +1,7 @@
From 8d0ecb38ebb0b50364f94e72eaee2f4945020cff Mon Sep 17 00:00:00 2001
From 7bd039c94c36e206ffeb521e2facab7dc9737eaf Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@beagleboard.org>
Date: Mon, 20 Dec 2010 11:57:56 +0100
Subject: [PATCH 11/29] omap3: beagleboard: add WIP support for beagleboardtoys WL12xx board
Subject: [PATCH 11/26] omap3: beagleboard: add WIP support for beagleboardtoys WL12xx board
Based on a patch by Luciano Coelho <luciano.coelho@nokia.com>

View File

@@ -1,7 +1,7 @@
From 84148dd7b2824a008561b4aabe483d16cf093951 Mon Sep 17 00:00:00 2001
From 9eb52cc853ca5aae2cf2b8c4df8ecfd3b666d560 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <sakoman@gmail.com>
Date: Tue, 15 Dec 2009 15:17:44 -0800
Subject: [PATCH 12/29] drivers: net: smsc911x: return ENODEV if device is not found
Subject: [PATCH 12/26] drivers: net: smsc911x: return ENODEV if device is not found
Signed-off-by: Steve Sakoman <sakoman@gmail.com>
---

View File

@@ -1,7 +1,7 @@
From 5167902964ed42113dbc2302cd64a12df4cd6a8e Mon Sep 17 00:00:00 2001
From 090cbb4e522ea0a7e31508435fa1852eecef2fea Mon Sep 17 00:00:00 2001
From: Steve Sakoman <sakoman@gmail.com>
Date: Tue, 15 Dec 2009 15:24:10 -0800
Subject: [PATCH 13/29] drivers: input: touchscreen: ads7846: return ENODEV if device is not found
Subject: [PATCH 13/26] drivers: input: touchscreen: ads7846: return ENODEV if device is not found
Signed-off-by: Steve Sakoman <sakoman@gmail.com>
---

View File

@@ -1,7 +1,7 @@
From 6377ecd5556f5329ddd5f5e9b9b5cd019cd76e67 Mon Sep 17 00:00:00 2001
From 3afe141cc65d54db2bfc82683d7ac5e142d48dad Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 12:45:20 -0800
Subject: [PATCH 14/29] ASoC: enable audio capture by default for twl4030
Subject: [PATCH 14/26] ASoC: enable audio capture by default for twl4030
---
sound/soc/codecs/twl4030.c | 4 ++--

View File

@@ -1,7 +1,7 @@
From 0e659f27fa00c4a6263e2b2ff96e09759f09b053 Mon Sep 17 00:00:00 2001
From f749aa37992fe966db530bd1d3ff00ea0eb8e13f Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Sat, 23 Jan 2010 06:26:54 -0800
Subject: [PATCH 15/29] MFD: enable madc clock
Subject: [PATCH 15/26] MFD: enable madc clock
---
drivers/mfd/twl-core.c | 8 ++++++++

View File

@@ -1,7 +1,7 @@
From a68c5e1548041d308fa46f834ff00e3a1ccd0acf Mon Sep 17 00:00:00 2001
From bd8ef0fcbab561b010735e12e18946da7a2d81f4 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 14:19:34 -0800
Subject: [PATCH 16/29] MFD: add twl4030 madc driver
Subject: [PATCH 16/26] MFD: add twl4030 madc driver
---
drivers/mfd/Kconfig | 21 ++

View File

@@ -1,7 +1,7 @@
From 7a9db8dd7562102e3c71eb079dc4e21792a650dc Mon Sep 17 00:00:00 2001
From e8f9b322f40b10dbd947281203411c9b0c9cb458 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 14:27:15 -0800
Subject: [PATCH 17/29] ARM: OMAP: Add twl4030 madc support to Overo
Subject: [PATCH 17/26] ARM: OMAP: Add twl4030 madc support to Overo
---
arch/arm/mach-omap2/board-overo.c | 5 +++++

View File

@@ -1,7 +1,7 @@
From 11bcde4707cf385ba61ccd0e00c9ab71db76ba6c Mon Sep 17 00:00:00 2001
From d37c0152c00ea15b488b2274544dcb30758fb8ca Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 14:32:36 -0800
Subject: [PATCH 18/29] ARM: OMAP: Add twl4030 madc support to Beagle
Subject: [PATCH 18/26] ARM: OMAP: Add twl4030 madc support to Beagle
---
arch/arm/mach-omap2/board-omap3beagle.c | 5 +++++

View File

@@ -1,7 +1,7 @@
From 92f8c713af962a538532279ce29ce5936f7736f7 Mon Sep 17 00:00:00 2001
From b8983a303fe84ba5a2ff5075edee0071c0b982ae Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Tue, 23 Feb 2010 14:40:27 -0800
Subject: [PATCH 19/29] OMAP: DSS2: Add support for Samsung LTE430WQ-F0C panel
Subject: [PATCH 19/26] OMAP: DSS2: Add support for Samsung LTE430WQ-F0C panel
---
.../omap2/displays/panel-samsung-lte430wq-f0c.c | 154 ++++++++++++++++++++

View File

@@ -1,7 +1,7 @@
From 36be685c580ace452461045b9278631330f18c89 Mon Sep 17 00:00:00 2001
From 571cdd24aee8cd6091bcc4dac0d8a0affc3500bf Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 15:05:30 -0800
Subject: [PATCH 20/29] OMAP: DSS2: Add support for LG Philips LB035Q02 panel
Subject: [PATCH 20/26] OMAP: DSS2: Add support for LG Philips LB035Q02 panel
---
drivers/video/omap2/displays/Kconfig | 12 +

View File

@@ -1,7 +1,7 @@
From a8f054b88944b7e1bd9b017eee1db76e90db0039 Mon Sep 17 00:00:00 2001
From d4ae1b11c94e268467ff6cb6143b934733ed762a Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Tue, 19 Jan 2010 21:19:15 -0800
Subject: [PATCH 21/29] OMAP: DSS2: add bootarg for selecting svideo or composite for tv output
Subject: [PATCH 21/26] OMAP: DSS2: add bootarg for selecting svideo or composite for tv output
also add pal-16 and ntsc-16 omapfb.mode settings for 16bpp
---

View File

@@ -1,7 +1,7 @@
From 036a15634116c64217d424dc1677fed9480cf381 Mon Sep 17 00:00:00 2001
From d0f67e031cd9eb514bbcff3147bf6644b92c5ee4 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Sun, 24 Jan 2010 09:33:56 -0800
Subject: [PATCH 22/29] ARM: OMAP2: mmc-twl4030: move clock input selection prior to vcc test
Subject: [PATCH 22/26] ARM: OMAP2: mmc-twl4030: move clock input selection prior to vcc test
otherwise it is not executed on systems that use non-twl regulators
---

View File

@@ -1,7 +1,7 @@
From db329c64c7c6abf08929860512964fc00d13f075 Mon Sep 17 00:00:00 2001
From 27f251ad46eeda205c220f89b4f9fbeaf930ae54 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 4 Feb 2010 12:26:22 -0800
Subject: [PATCH 23/29] RTC: add support for backup battery recharge
Subject: [PATCH 23/26] RTC: add support for backup battery recharge
---
drivers/rtc/rtc-twl.c | 25 +++++++++++++++++++++++++

View File

@@ -1,7 +1,7 @@
From 12fd29b006ffd5b8b14837088db8949a53d04f04 Mon Sep 17 00:00:00 2001
From 4eedcb7fb5101a042102355463a213fa51e52e4f Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Wed, 24 Feb 2010 10:37:22 -0800
Subject: [PATCH 24/29] ARM: OMAP: automatically set musb mode in platform data based on CONFIG options
Subject: [PATCH 24/26] ARM: OMAP: automatically set musb mode in platform data based on CONFIG options
---
arch/arm/mach-omap2/board-omap3beagle.c | 6 ++++++

View File

@@ -1,7 +1,7 @@
From 6d36c6f600becef7ee3f9d139c065b733a732a54 Mon Sep 17 00:00:00 2001
From 3e9463eb0f8c54286c086f259a598415ba28c28f Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Mon, 10 May 2010 13:59:14 -0700
Subject: [PATCH 25/29] OMAP: DSS2: check for both cpu type and revision, rather than just revision
Subject: [PATCH 25/26] OMAP: DSS2: check for both cpu type and revision, rather than just revision
---
drivers/video/omap2/dss/dispc.c | 4 ++--

View File

@@ -1,7 +1,7 @@
From 21da1a248b7a19136bb53a32061989473bc79551 Mon Sep 17 00:00:00 2001
From 5ac69358c0af66eadb86561fb99a661280f61f78 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Fri, 18 Dec 2009 06:39:24 -0800
Subject: [PATCH 26/29] OMAP: DSS2: Add DSS2 support for Overo
Subject: [PATCH 26/26] OMAP: DSS2: Add DSS2 support for Overo
---
arch/arm/mach-omap2/board-overo.c | 238 +++++++++++++++++++++++++++++++------

View File

@@ -0,0 +1,60 @@
From 405be95c4b7c397815b20052dbaa43ce36c1a724 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 31 Dec 2010 13:35:02 +0530
Subject: [PATCH 01/19] OMAP3: PM: Adding T2 enabling of smartreflex
The smartreflex bit on twl4030 needs to be enabled by default irrespective
of whether smartreflex module is enabled on the OMAP side or not.
This is because without this bit enabled the voltage scaling through
vp forceupdate does not function properly on OMAP3.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/mach-omap2/omap_twl.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index 15f8c6c..a59f36b 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -58,7 +58,9 @@
static bool is_offset_valid;
static u8 smps_offset;
+#define TWL4030_DCDC_GLOBAL_CFG 0x06
#define REG_SMPS_OFFSET 0xE0
+#define SMARTREFLEX_ENABLE BIT(3)
unsigned long twl4030_vsel_to_uv(const u8 vsel)
{
@@ -256,6 +258,7 @@ int __init omap4_twl_init(void)
int __init omap3_twl_init(void)
{
struct voltagedomain *voltdm;
+ u8 temp;
if (!cpu_is_omap34xx())
return -ENODEV;
@@ -267,6 +270,19 @@ int __init omap3_twl_init(void)
omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
}
+ /*
+ * The smartreflex bit on twl4030 needs to be enabled by
+ * default irrespective of whether smartreflex module is
+ * enabled on the OMAP side or not. This is because without
+ * this bit enabled the voltage scaling through
+ * vp forceupdate does not function properly on OMAP3.
+ */
+ twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp,
+ TWL4030_DCDC_GLOBAL_CFG);
+ temp |= SMARTREFLEX_ENABLE;
+ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp,
+ TWL4030_DCDC_GLOBAL_CFG);
+
voltdm = omap_voltage_domain_lookup("mpu");
omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info);
--
1.6.6.1

View File

@@ -0,0 +1,38 @@
From fe693a9d05c58aa7e5157f695b9af00688a2b91d Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Thu, 6 Jan 2011 13:05:55 +0100
Subject: [PATCH 1/4] omap3: add support for 720MHz MPU OPP
The 720MHz capability can be probed run-time by reading the
PRODID.SKUID[3:0] at 0x4830A20C.
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/opp3xxx_data.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
index fd3a1af..a861f5e 100644
--- a/arch/arm/mach-omap2/opp3xxx_data.c
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
@@ -34,6 +34,8 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
OPP_INITIALIZER("mpu", true, 550000000, 1270000),
/* MPU OPP5 */
OPP_INITIALIZER("mpu", true, 600000000, 1350000),
+ /* MPU OPP6 */
+ OPP_INITIALIZER("mpu", false, 720000000, 1350000),
/*
* L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
@@ -59,6 +61,8 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
OPP_INITIALIZER("iva", true, 400000000, 1270000),
/* DSP OPP5 */
OPP_INITIALIZER("iva", true, 430000000, 1350000),
+ /* DSP OPP6 */
+ OPP_INITIALIZER("iva", false, 520000000, 1350000),
};
static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
--
1.6.6.1

View File

@@ -0,0 +1,27 @@
From a1df976c51e22bed9d95fcb07832571ef3520f2a Mon Sep 17 00:00:00 2001
From: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
Date: Wed, 11 Aug 2010 17:02:43 -0700
Subject: [PATCH 02/19] OMAP: CPUfreq: ensure driver initializes after cpufreq framework and governors
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/plat-omap/cpu-omap.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 11c54ec..79d2155 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -160,7 +160,7 @@ static int __init omap_cpufreq_init(void)
return cpufreq_register_driver(&omap_driver);
}
-arch_initcall(omap_cpufreq_init);
+late_initcall(omap_cpufreq_init);
/*
* if ever we want to remove this, upon cleanup call:
--
1.6.6.1

View File

@@ -0,0 +1,90 @@
From 154571d1620731a3207da126eb4f139a1534f293 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Thu, 6 Jan 2011 13:13:18 +0100
Subject: [PATCH 2/4] OMAP35x: Add support for 720MHz part
This patch adds support for ARM running at 720MHz part.
The 720MHz capability can be probed run-time by reading the
PRODID.SKUID[3:0] at 0x4830A20C.
[1] http://focus.ti.com/lit/ug/spruff1d/spruff1d.pdf
This is a forward port of https://patchwork.kernel.org/patch/53125/
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/control.h | 7 +++++++
arch/arm/mach-omap2/id.c | 10 ++++++++++
arch/arm/plat-omap/include/plat/cpu.h | 2 ++
3 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index f0629ae..b9671d3 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -365,7 +365,14 @@
#define FEAT_NEON 0
#define FEAT_NEON_NONE 1
+/*
+ * Product ID register
+ */
+#define OMAP3_PRODID 0x020C
+#define OMAP3_SKUID_MASK 0x0f
+#define OMAP3_SKUID_720MHZ 0x08
+
#ifndef __ASSEMBLY__
#ifdef CONFIG_ARCH_OMAP2PLUS
extern void __iomem *omap_ctrl_base_get(void);
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 5f9086c..53fbe01 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -195,6 +195,15 @@ static void __init omap3_check_features(void)
* TODO: Get additional info (where applicable)
* e.g. Size of L2 cache.
*/
+
+ /*
+ * Does it support 720MHz?
+ */
+ status = (OMAP3_SKUID_MASK & read_tap_reg(OMAP3_PRODID));
+
+ if (status & OMAP3_SKUID_720MHZ) {
+ omap3_features |= OMAP3_HAS_720MHZ;
+ }
}
static void __init omap3_check_revision(void)
@@ -445,6 +454,7 @@ static void __init omap3_cpuinfo(void)
OMAP3_SHOW_FEATURE(neon);
OMAP3_SHOW_FEATURE(isp);
OMAP3_SHOW_FEATURE(192mhz_clk);
+ OMAP3_SHOW_FEATURE(720mhz);
printk(")\n");
}
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 1a8c347..7d24faa 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -510,6 +510,7 @@ extern u32 omap3_features;
#define OMAP3_HAS_ISP BIT(4)
#define OMAP3_HAS_192MHZ_CLK BIT(5)
#define OMAP3_HAS_IO_WAKEUP BIT(6)
+#define OMAP3_HAS_720MHZ BIT(7)
#define OMAP3_HAS_FEATURE(feat,flag) \
static inline unsigned int omap3_has_ ##feat(void) \
@@ -524,5 +525,6 @@ OMAP3_HAS_FEATURE(neon, NEON)
OMAP3_HAS_FEATURE(isp, ISP)
OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
+OMAP3_HAS_FEATURE(720mhz, 720MHZ)
#endif
--
1.6.6.1

View File

@@ -0,0 +1,31 @@
From fe6bc036ebf31ca377051ff0ea99da3cdc66854f Mon Sep 17 00:00:00 2001
From: Kevin Hilman <khilman@deeprootsystems.com>
Date: Wed, 11 Aug 2010 17:05:38 -0700
Subject: [PATCH 03/19] OMAP: CPUfreq: ensure policy is fully initialized
Ensure policy min/max/cur values are initialized when OMAP
CPUfreq driver starts.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/plat-omap/cpu-omap.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 79d2155..bfa063b 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -126,6 +126,10 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy)
VERY_HI_RATE) / 1000;
}
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+ policy->cur = omap_getspeed(0);
+
/* FIXME: what's the actual transition time? */
policy->cpuinfo.transition_latency = 300 * 1000;
--
1.6.6.1

View File

@@ -0,0 +1,62 @@
From 1a97a3600227fd0b52ee3bfd67bac6dde034af0d Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Thu, 6 Jan 2011 13:23:45 +0100
Subject: [PATCH 3/4] OMAP3: beagle C4: enable upto 720MHz OPP
Beagle C4 uses a recent 3530 and the board design allows enabling 720MHz
OPP. tweak the default table to allow for higher OPP tables
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/board-omap3beagle.c | 35 +++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 9393e75..a0462b9 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -829,6 +829,41 @@ static void __init beagle_opp_init(void)
pr_err("%s: turbo OPPs enabled!\n", __func__);
}
}
+ /* Custom OPP enabled for C4 */
+ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4) {
+ struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
+ struct omap_hwmod *dh = omap_hwmod_lookup("iva");
+ struct device *dev;
+
+ if (!mh || !dh) {
+ pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
+ __func__, mh, dh);
+ r = -EINVAL;
+ } else {
+ /* Enable MPU 720MHz */
+ dev = &mh->od->pdev.dev;
+ r = opp_enable(dev, 720000000);
+
+ /* Enable IVA 520MHz and lower opps */
+ dev = &dh->od->pdev.dev;
+ r |= opp_enable(dev, 520000000);
+ }
+ if (r) {
+ pr_err("%s: failed to enable higher opp %d\n",
+ __func__, r);
+ /*
+ * Cleanup - disable the higher freqs - we dont care
+ * about the results
+ */
+ dev = &mh->od->pdev.dev;
+ opp_disable(dev, 720000000);
+ dev = &dh->od->pdev.dev;
+ opp_disable(dev, 520000000);
+ } else {
+ pr_err("%s: 720MHz MPU OPPs enabled!\n", __func__);
+ }
+ }
+
}
static void __init omap3_beagle_init(void)
--
1.6.6.1

View File

@@ -0,0 +1,103 @@
From ba484e6276ba5089a0397aad845ae5be80850bac Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Wed, 12 Jan 2011 17:04:04 +0100
Subject: [PATCH 4/4] OMAP3: Overo Tide: enable upto 720MHz OPP
Overo Tide uses a recent 3530 and the board design allows enabling 720MHz
OPP. tweak the default table to allow for higher OPP tables
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/board-overo.c | 51 +++++++++++++++++++++++++++++++++++++
1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 8a44c17..d6d8619 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -29,6 +29,7 @@
#include <linux/i2c/twl.h>
#include <linux/regulator/machine.h>
#include <linux/spi/spi.h>
+#include <linux/opp.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -50,10 +51,12 @@
#include <plat/mcspi.h>
#include <plat/mux.h>
#include <plat/usb.h>
+#include <plat/omap_device.h>
#include "mux.h"
#include "sdram-micron-mt46h32m32lf-6.h"
#include "hsmmc.h"
+#include "pm.h"
#define OVERO_GPIO_BT_XGATE 15
#define OVERO_GPIO_W2W_NRESET 16
@@ -626,6 +629,53 @@ static struct omap_musb_board_data musb_board_data = {
.power = 100,
};
+static void __init overo_opp_init(void)
+{
+ int r = 0;
+
+ /* Initialize the omap3 opp table */
+ if (omap3_opp_init()) {
+ pr_err("%s: opp default init failed\n", __func__);
+ return;
+ }
+
+ /* Custom OPP enabled for Tide */
+ if (omap3_has_720mhz()) {
+ struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
+ struct omap_hwmod *dh = omap_hwmod_lookup("iva");
+ struct device *dev;
+
+ if (!mh || !dh) {
+ pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
+ __func__, mh, dh);
+ r = -EINVAL;
+ } else {
+ /* Enable MPU 720MHz */
+ dev = &mh->od->pdev.dev;
+ r = opp_enable(dev, 720000000);
+
+ /* Enable IVA 520MHz and lower opps */
+ dev = &dh->od->pdev.dev;
+ r |= opp_enable(dev, 520000000);
+ }
+ if (r) {
+ pr_err("%s: failed to enable higher opp %d\n",
+ __func__, r);
+ /*
+ * Cleanup - disable the higher freqs - we dont care
+ * about the results
+ */
+ dev = &mh->od->pdev.dev;
+ opp_disable(dev, 720000000);
+ dev = &dh->od->pdev.dev;
+ opp_disable(dev, 520000000);
+ } else {
+ pr_err("%s: 720MHz MPU OPPs enabled!\n", __func__);
+ }
+ }
+
+}
+
static void __init overo_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -678,6 +728,7 @@ static void __init overo_init(void)
else
printk(KERN_ERR "could not obtain gpio for "
"OVERO_GPIO_USBH_CPEN\n");
+ overo_opp_init();
}
MACHINE_START(OVERO, "Gumstsix Overo")
--
1.6.6.1

View File

@@ -0,0 +1,269 @@
From f7580811a6d3ac015a8401388124e746651ab64c Mon Sep 17 00:00:00 2001
From: Rajendra Nayak <rnayak@ti.com>
Date: Mon, 10 Nov 2008 17:00:25 +0530
Subject: [PATCH 04/19] OMAP3 PM: CPUFreq driver for OMAP3
CPUFreq driver for OMAP3
With additional fixes and cleanups from Tero Kristo:
- Fix rate calculation bug in omap3_select_table_rate
- Refreshed DVFS VDD1 control against latest clock fw
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
OMAP3: PM: CPUFreq: Fix omap_getspeed.
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
Make sure omap cpufreq driver initializes after cpufreq framework and governors
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
merge: CPUFreq: remove obsolete funcs
OMAP3 clock: Update cpufreq driver
This patch removes all refrences to virtual clock
nodes in CPUFreq driver.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
Signed-off-by: Jean Pihet <jpihet@mvista.com>
PM: Prevent direct cpufreq scaling during initialization
It is seen that the OMAP specific cpufreq initialization code tries to
scale the MPU frequency to the highest possible without taking care of
the voltage level. On power on reset the power IC does not provide the
necessary voltage for the highest available MPU frequency (that would
satisfy all Si families). This potentially is an window of opportunity
for things to go wrong.
Signed-off-by: Romit Dasgupta <romit@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
OMAP3: PM: enable 600MHz (overdrive) OPP
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
omap3: introduce cpufreq
OMAP OPP layer functions now have dependencies of CONFIG_CPU_FREQ only.
With this patch, omap opp layer now has its compilation flags
bound to CONFIG_CPU_FREQ. Also its code has been removed from pm34xx.c.
A new file has been created to contain cpu freq code related to
OMAP3: cpufreq34xx.c
OMAP34xx and OMAP36xx family OPPs are made available
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Romit Dasgupta <romit@ti.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
omap3: cpufreq: allow default opp table init
For board files which choose to override the defaults, the existing
mechanism will work, for boards that would like to work with defaults,
allow init_common_hw to call init_opp_table to initialize if not
already initialized. this will allow all omap boards which have opp
tables predefined for a silicon to use the same.
Originally reported for overo:
http://marc.info/?t=127265269400004&r=1&w=2
Signed-off-by: Nishanth Menon <nm@ti.com>
Reported-by: Peter Tseng <tsenpet09@gmail.com>
Cc: Cliff Brake <cliff.brake@gmail.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
OMAP2: update OPP data to be device based
Cc: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
OMAP3: CPUfreq: update to device-based OPP API
Update usage of OPP API to use new device-based API. This requires
getting the 'struct device' for the MPU and using that with the OPP
API.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
omap3: opp: make independent of cpufreq
Make opp3xx data which is registered with the opp layer
dependent purely on CONFIG_PM as opp layer and pm.c users
are CONFIG_PM dependent not cpufreq dependent.
so we rename the data definition to opp3xxx_data.c (inline with what
we have for omap2), also move the build definition to be under
the existing CONFIG_PM build instead of CPUFREQ.
Cc: Eduardo Valentin <eduardo.valentin@nokia.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Rajendra Nayak <rnayak@ti.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/clock.h | 14 +++++++++++++-
arch/arm/mach-omap2/clock34xx.c | 2 ++
arch/arm/plat-omap/cpu-omap.c | 35 ++++++++++++++++++++++++++++++++---
3 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 896584e..29b5cf0 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -137,7 +137,9 @@ extern const struct clksel_rate gpt_32k_rates[];
extern const struct clksel_rate gpt_sys_rates[];
extern const struct clksel_rate gfx_l3_rates[];
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
+#ifdef CONFIG_CPU_FREQ
+
+#ifdef CONFIG_ARCH_OMAP2
extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
#else
@@ -145,6 +147,16 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
#define omap2_clk_exit_cpufreq_table 0
#endif
+#ifdef CONFIG_ARCH_OMAP3
+extern void omap3_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
+extern void omap3_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
+#else
+#define omap3_clk_init_cpufreq_table 0
+#define omap3_clk_exit_cpufreq_table 0
+#endif
+
+#endif /* CONFIG_CPU_FREQ */
+
extern const struct clkops clkops_omap3_noncore_dpll_ops;
#endif
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 287abc4..85d3877 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -20,6 +20,8 @@
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/cpufreq.h>
#include <plat/clock.h>
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index bfa063b..608216b 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -8,6 +8,10 @@
*
* Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
*
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Updated to support OMAP3
+ * Rajendra Nayak <rnayak@ti.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -21,17 +25,25 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/opp.h>
#include <mach/hardware.h>
#include <plat/clock.h>
+#include <plat/common.h>
#include <asm/system.h>
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
+#include <plat/omap-pm.h>
+#endif
+
#define VERY_HI_RATE 900000000
static struct cpufreq_frequency_table *freq_table;
#ifdef CONFIG_ARCH_OMAP1
#define MPU_CLK "mpu"
+#elif CONFIG_ARCH_OMAP3
+#define MPU_CLK "arm_fck"
#else
#define MPU_CLK "virt_prcm_set"
#endif
@@ -73,7 +85,13 @@ static int omap_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
+#ifdef CONFIG_ARCH_OMAP1
struct cpufreq_freqs freqs;
+#endif
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
+ unsigned long freq;
+ struct device *mpu_dev = omap2_get_mpuss_device();
+#endif
int ret = 0;
/* Ensure desired rate is within allowed range. Some govenors
@@ -83,13 +101,13 @@ static int omap_target(struct cpufreq_policy *policy,
if (target_freq > policy->max)
target_freq = policy->max;
+#ifdef CONFIG_ARCH_OMAP1
freqs.old = omap_getspeed(0);
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
freqs.cpu = 0;
if (freqs.old == freqs.new)
return ret;
-
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
#ifdef CONFIG_CPU_FREQ_DEBUG
printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
@@ -97,7 +115,11 @@ static int omap_target(struct cpufreq_policy *policy,
#endif
ret = clk_set_rate(mpu_clk, freqs.new * 1000);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
+#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
+ freq = target_freq * 1000;
+ if (opp_find_freq_ceil(mpu_dev, &freq))
+ omap_pm_cpu_set_freq(freq);
+#endif
return ret;
}
@@ -114,7 +136,14 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy)
policy->cur = policy->min = policy->max = omap_getspeed(0);
- clk_init_cpufreq_table(&freq_table);
+ if (!cpu_is_omap34xx()) {
+ clk_init_cpufreq_table(&freq_table);
+ } else {
+ struct device *mpu_dev = omap2_get_mpuss_device();
+
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
+ }
+
if (freq_table) {
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
if (!result)
--
1.6.6.1

View File

@@ -0,0 +1,32 @@
From 3a51f3ffe8299bcc28a6be1bdcd0e0ea39af2042 Mon Sep 17 00:00:00 2001
From: Silesh C V <silesh@ti.com>
Date: Wed, 29 Sep 2010 14:52:54 +0530
Subject: [PATCH 05/19] OMAP: PM: CPUFREQ: Fix conditional compilation
Fix conditional compilation. A conditional expresiion
should follow "#elif", in this case #elif clause should
check whether CONFIG_ARCH_OMAP3 is defined or not
(ie. defined(CONFIG_ARCH_OMAP3)) rather than checking for
the value of the macro.
Signed-off-by: Silesh C V <silesh@ti.com>
---
arch/arm/plat-omap/cpu-omap.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 608216b..671e4b9 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -42,7 +42,7 @@ static struct cpufreq_frequency_table *freq_table;
#ifdef CONFIG_ARCH_OMAP1
#define MPU_CLK "mpu"
-#elif CONFIG_ARCH_OMAP3
+#elif defined(CONFIG_ARCH_OMAP3)
#define MPU_CLK "arm_fck"
#else
#define MPU_CLK "virt_prcm_set"
--
1.6.6.1

View File

@@ -0,0 +1,199 @@
From c37bb21e4f82e5d88af21f7dbcef407e7a9d5306 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 29 Oct 2010 20:43:07 +0530
Subject: [PATCH 06/19] OMAP: Introduce a user list for each voltage domain instance in the voltage driver.
This patch introduces a user list of devices associated with each
voltage domain instance. The user list is implemented using plist
structure with priority node populated with the voltage values.
This patch also adds an API which will take in a device and
requested voltage as parameters, adds the info to the user list
and returns back the maximum voltage requested by all the user
devices. This can be used anytime to get the voltage that the
voltage domain instance can be transitioned into.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/mach-omap2/voltage.c | 97 +++++++++++++++++++++++++++++
arch/arm/plat-omap/include/plat/voltage.h | 8 +++
2 files changed, 105 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index ed6079c..76c98c6 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -24,6 +24,9 @@
#include <linux/err.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/plist.h>
+#include <linux/slab.h>
#include <plat/common.h>
#include <plat/voltage.h>
@@ -118,6 +121,20 @@ struct vc_reg_info {
};
/**
+ * struct omap_vdd_user_list - The per vdd user list
+ *
+ * @dev: The device asking for the vdd to be set at a particular
+ * voltage
+ * @node: The list head entry
+ * @volt: The voltage requested by the device <dev>
+ */
+struct omap_vdd_user_list {
+ struct device *dev;
+ struct plist_node node;
+ u32 volt;
+};
+
+/**
* omap_vdd_info - Per Voltage Domain info
*
* @volt_data : voltage table having the distinct voltages supported
@@ -132,6 +149,10 @@ struct vc_reg_info {
* shifts, masks etc.
* @voltdm : pointer to the voltage domain structure
* @debug_dir : debug directory for this voltage domain.
+ * @user_lock : the lock to be used by the plist user_list
+ * @user_list : the list head maintaining the various users.
+ * @scaling_mutex : the dvfs muutex.
+ * of this vdd with the voltage requested by each user.
* @curr_volt : current voltage for this vdd.
* @ocp_mod : The prm module for accessing the prm irqstatus reg.
* @prm_irqst_reg : prm irqstatus register.
@@ -146,6 +167,9 @@ struct omap_vdd_info {
struct vc_reg_info vc_reg;
struct voltagedomain voltdm;
struct dentry *debug_dir;
+ spinlock_t user_lock;
+ struct plist_head user_list;
+ struct mutex scaling_mutex;
u32 curr_volt;
u16 ocp_mod;
u8 prm_irqst_reg;
@@ -869,6 +893,11 @@ static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
vdd->write_reg = omap3_voltage_write_reg;
vdd->volt_scale = vp_forceupdate_scale_voltage;
vdd->vp_enabled = false;
+ /* Init the plist */
+ spin_lock_init(&vdd->user_lock);
+ plist_head_init(&vdd->user_list, &vdd->user_lock);
+ /* Init the DVFS mutex */
+ mutex_init(&vdd->scaling_mutex);
/* VC parameters */
vdd->vc_reg.prm_mod = OMAP3430_GR_MOD;
@@ -1059,6 +1088,11 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
vdd->write_reg = omap4_voltage_write_reg;
vdd->volt_scale = vp_forceupdate_scale_voltage;
vdd->vp_enabled = false;
+ /* Init the plist */
+ spin_lock_init(&vdd->user_lock);
+ plist_head_init(&vdd->user_list, &vdd->user_lock);
+ /* Init the DVFS mutex */
+ mutex_init(&vdd->scaling_mutex);
/* VC parameters */
vdd->vc_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
@@ -1171,6 +1205,69 @@ unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
return vdd->pmic_info->vsel_to_uv(curr_vsel);
}
+/**
+ * omap_voltage_add_request() - API to keep track of various requests to
+ * scale the VDD and returns the best possible
+ * voltage the VDD can be put to.
+ * @volt_domain: pointer to the voltage domain.
+ * @dev: the device pointer.
+ * @volt: the voltage which is requested by the device.
+ *
+ * This API is to be called before the actual voltage scaling is
+ * done to determine what is the best possible voltage the VDD can
+ * be put to. This API adds the device <dev> in the user list of the
+ * vdd <volt_domain> with <volt> as the requested voltage. The user list
+ * is a plist with the priority element absolute voltage values.
+ * The API then finds the maximum of all the requested voltages for
+ * the VDD and returns it back through <volt> pointer itself.
+ * Returns error value in case of any errors.
+ */
+int omap_voltage_add_request(struct voltagedomain *voltdm, struct device *dev,
+ unsigned long *volt)
+{
+ struct omap_vdd_info *vdd;
+ struct omap_vdd_user_list *user;
+ struct plist_node *node;
+ int found = 0;
+
+ if (!voltdm || IS_ERR(voltdm)) {
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
+ return -EINVAL;
+ }
+
+ vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
+
+ mutex_lock(&vdd->scaling_mutex);
+
+ plist_for_each_entry(user, &vdd->user_list, node) {
+ if (user->dev == dev) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ user = kzalloc(sizeof(struct omap_vdd_user_list), GFP_KERNEL);
+ if (!user) {
+ pr_err("%s: Unable to creat a new user for vdd_%s\n",
+ __func__, voltdm->name);
+ mutex_unlock(&vdd->scaling_mutex);
+ return -ENOMEM;
+ }
+ user->dev = dev;
+ } else {
+ plist_del(&user->node, &vdd->user_list);
+ }
+
+ plist_node_init(&user->node, *volt);
+ plist_add(&user->node, &vdd->user_list);
+ node = plist_last(&vdd->user_list);
+ *volt = user->volt = node->prio;
+
+ mutex_unlock(&vdd->scaling_mutex);
+
+ return 0;
+}
/**
* omap_vp_enable() - API to enable a particular VP
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
index 0ff1233..bd07eca 100644
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -132,6 +132,9 @@ int omap_voltage_register_pmic(struct voltagedomain *voltdm,
void omap_change_voltscale_method(struct voltagedomain *voltdm,
int voltscale_method);
int omap_voltage_late_init(void);
+int omap_voltage_add_request(struct voltagedomain *voltdm, struct device *dev,
+ unsigned long *volt);
+
#else
static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
struct omap_volt_pmic_info *pmic_info) {}
@@ -141,6 +144,11 @@ static inline int omap_voltage_late_init(void)
{
return -EINVAL;
}
+static inline int omap_voltage_add_request(struct voltagedomain *voltdm,
+ struct device *dev, unsigned long *volt)
+{
+ return -EINVAL;
+}
#endif
#endif
--
1.6.6.1

View File

@@ -0,0 +1,82 @@
From 717bd73868e57fde49a25104af9bb8b9c6400b67 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 29 Oct 2010 20:43:10 +0530
Subject: [PATCH 07/19] OMAP: Introduce API in the OPP layer to find the opp entry corresponding to a voltage.
This patch adds an API in the opp layer to get the opp table entry
corresponding to the voltage passed as the parameter.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
drivers/base/power/opp.c | 28 ++++++++++++++++++++++++++++
include/linux/opp.h | 8 ++++++++
2 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 2bb9b4c..60b4478 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -354,6 +354,34 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
}
/**
+ * opp_find_voltage() - search for an exact voltage
+ * @dev: device pointer associated with the opp type
+ * @volt: voltage to search for
+ *
+ * Searches for exact match in the opp list and returns handle to the matching
+ * opp if found, else returns ERR_PTR in case of error and should be handled
+ * using IS_ERR.
+ */
+struct opp *opp_find_voltage(struct device *dev, unsigned long volt)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available && temp_opp->u_volt == volt) {
+ opp = temp_opp;
+ break;
+ }
+ }
+
+ return opp;
+}
+
+/**
* opp_add() - Add an OPP table from a table definitions
* @dev: device for which we do this operation
* @freq: Frequency in Hz for this OPP
diff --git a/include/linux/opp.h b/include/linux/opp.h
index 5449945..4977d5c 100644
--- a/include/linux/opp.h
+++ b/include/linux/opp.h
@@ -34,6 +34,8 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq);
struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
+struct opp *opp_find_voltage(struct device *dev, unsigned long volt);
+
int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
int opp_enable(struct device *dev, unsigned long freq);
@@ -74,6 +76,12 @@ static inline struct opp *opp_find_freq_ceil(struct device *dev,
return ERR_PTR(-EINVAL);
}
+static inline struct opp *opp_find_voltage(struct device *dev,
+ unsigned long volt)
+{
+ return ERR_PTR(-EINVAL);
+}
+
static inline int opp_add(struct device *dev, unsigned long freq,
unsigned long u_volt)
{
--
1.6.6.1

View File

@@ -0,0 +1,182 @@
From be5bdabb6206f106f0dcf91b0e90474d23773416 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 29 Oct 2010 20:43:24 +0530
Subject: [PATCH 08/19] OMAP: Introduce API to register a device with a voltagedomain
This patch adds an API in the voltage layer that
can be used during omap_device_build to register the built
device with the voltage domain. This API is to be typically called
only once per device during the device registeration. This approach
makes it easy during dvfs to scale all the devices associated with
a voltage domain and then scale the voltage domain.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/mach-omap2/voltage.c | 50 +++++++++++++++++++++++++++++
arch/arm/plat-omap/include/plat/voltage.h | 7 +++-
arch/arm/plat-omap/omap_device.c | 12 +++++++
3 files changed, 68 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 76c98c6..7381fa6 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -134,6 +134,11 @@ struct omap_vdd_user_list {
u32 volt;
};
+struct omap_vdd_dev_list {
+ struct device *dev;
+ struct list_head node;
+};
+
/**
* omap_vdd_info - Per Voltage Domain info
*
@@ -153,6 +158,7 @@ struct omap_vdd_user_list {
* @user_list : the list head maintaining the various users.
* @scaling_mutex : the dvfs muutex.
* of this vdd with the voltage requested by each user.
+ * @dev_list : list of devices bwlonging to this voltage domain.
* @curr_volt : current voltage for this vdd.
* @ocp_mod : The prm module for accessing the prm irqstatus reg.
* @prm_irqst_reg : prm irqstatus register.
@@ -170,6 +176,7 @@ struct omap_vdd_info {
spinlock_t user_lock;
struct plist_head user_list;
struct mutex scaling_mutex;
+ struct list_head dev_list;
u32 curr_volt;
u16 ocp_mod;
u8 prm_irqst_reg;
@@ -1093,6 +1100,8 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
plist_head_init(&vdd->user_list, &vdd->user_lock);
/* Init the DVFS mutex */
mutex_init(&vdd->scaling_mutex);
+ /* Init the device list */
+ INIT_LIST_HEAD(&vdd->dev_list);
/* VC parameters */
vdd->vc_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
@@ -1269,6 +1278,40 @@ int omap_voltage_add_request(struct voltagedomain *voltdm, struct device *dev,
return 0;
}
+int omap_voltage_add_dev(struct voltagedomain *voltdm, struct device *dev)
+{
+ struct omap_vdd_info *vdd;
+ struct omap_vdd_dev_list *temp_dev;
+
+ if (!voltdm || IS_ERR(voltdm)) {
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
+ return -EINVAL;
+ }
+
+ vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
+
+ list_for_each_entry(temp_dev, &vdd->dev_list, node) {
+ if (temp_dev->dev == dev) {
+ dev_warn(dev, "%s: Device already added to vdee_%s\n",
+ __func__, voltdm->name);
+ return -EINVAL;
+ }
+ }
+
+ temp_dev = kzalloc(sizeof(struct omap_vdd_dev_list), GFP_KERNEL);
+ if (!temp_dev) {
+ dev_err(dev, "%s: Unable to creat a new device for vdd_%s\n",
+ __func__, voltdm->name);
+ return -ENOMEM;
+ }
+
+ temp_dev->dev = dev;
+
+ list_add(&temp_dev->node, &vdd->dev_list);
+
+ return 0;
+}
+
/**
* omap_vp_enable() - API to enable a particular VP
* @voltdm: pointer to the VDD whose VP is to be enabled.
@@ -1649,6 +1692,8 @@ int __init omap_voltage_late_init(void)
*/
static int __init omap_voltage_early_init(void)
{
+ int i;
+
if (cpu_is_omap34xx()) {
vdd_info = omap3_vdd_info;
nr_scalable_vdd = OMAP3_NR_SCALABLE_VDD;
@@ -1661,8 +1706,13 @@ static int __init omap_voltage_early_init(void)
vdd_data_configure = omap4_vdd_data_configure;
} else {
pr_warning("%s: voltage driver support not added\n", __func__);
+ return -EINVAL;
}
+ /* Init the device list */
+ for (i = 0; i < nr_scalable_vdd; i++)
+ INIT_LIST_HEAD(&(vdd_info[i].dev_list));
+
return 0;
}
core_initcall(omap_voltage_early_init);
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
index bd07eca..adbc6af 100644
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -134,7 +134,7 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm,
int omap_voltage_late_init(void);
int omap_voltage_add_request(struct voltagedomain *voltdm, struct device *dev,
unsigned long *volt);
-
+int omap_voltage_add_dev(struct voltagedomain *voltdm, struct device *dev);
#else
static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
struct omap_volt_pmic_info *pmic_info) {}
@@ -149,6 +149,11 @@ static inline int omap_voltage_add_request(struct voltagedomain *voltdm,
{
return -EINVAL;
}
+static inline int omap_voltage_add_dev(struct voltagedomain *voltdm,
+ struct device *dev)
+{
+ return -EINVAL;
+}
#endif
#endif
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 57adb27..2c95e61 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -86,6 +86,7 @@
#include <plat/omap_device.h>
#include <plat/omap_hwmod.h>
+#include <plat/voltage.h>
/* These parameters are passed to _omap_device_{de,}activate() */
#define USE_WAKEUP_LAT 0
@@ -481,6 +482,17 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
for (i = 0; i < oh_cnt; i++) {
hwmods[i]->od = od;
_add_optional_clock_alias(od, hwmods[i]);
+ if (hwmods[i]->vdd_name) {
+ struct omap_hwmod *oh = hwmods[i];
+ struct voltagedomain *voltdm;
+
+ if (is_early_device)
+ continue;
+
+ voltdm = omap_voltage_domain_lookup(oh->vdd_name);
+ if (!omap_voltage_add_dev(voltdm, &od->pdev.dev))
+ oh->voltdm = voltdm;
+ }
}
if (ret)
--
1.6.6.1

View File

@@ -0,0 +1,120 @@
From 50f4db415d1ee9ee5100214cc89cf5df1ee1c1e2 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 29 Oct 2010 20:43:29 +0530
Subject: [PATCH 09/19] OMAP: Introduce device specific set rate and get rate in omap_device structure
This patch extends the omap_device structure to contain
pointers to scale the operating rate of the
device and to retrieve the operating rate of the device.
This patch also adds the three new APIs in the omap device layer
namely omap_device_set_rate that can be called to set a new operating
rate for a device, omap_device_get_rate that can be called to retrieve
the operating frequency for a device and omap_device_populate_rate_fns
to populte the device specific set_rate and get_rate API's.
The omap_device_set_rate and omap_device_get_rate does some routine error
checks and finally calls into the device specific set_rate
and get_rate APIs populated through omap_device_populate_rate_fns.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/plat-omap/include/plat/omap_device.h | 9 +++++
arch/arm/plat-omap/omap_device.c | 49 +++++++++++++++++++++++++
2 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index e4c349f..1178b86 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -50,6 +50,8 @@ extern struct device omap_device_parent;
* @hwmods: (one .. many per omap_device)
* @hwmods_cnt: ARRAY_SIZE() of @hwmods
* @pm_lats: ptr to an omap_device_pm_latency table
+ * @set_rate: fn ptr to change the operating rate.
+ * @get_rate: fn ptr to retrieve the current operating rate.
* @pm_lats_cnt: ARRAY_SIZE() of what is passed to @pm_lats
* @pm_lat_level: array index of the last odpl entry executed - -1 if never
* @dev_wakeup_lat: dev wakeup latency in nanoseconds
@@ -67,6 +69,8 @@ struct omap_device {
struct platform_device pdev;
struct omap_hwmod **hwmods;
struct omap_device_pm_latency *pm_lats;
+ int (*set_rate)(struct device *dev, unsigned long rate);
+ unsigned long (*get_rate) (struct device *dev);
u32 dev_wakeup_lat;
u32 _dev_wakeup_lat_limit;
u8 pm_lats_cnt;
@@ -108,6 +112,11 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
u32 new_wakeup_lat_limit);
struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
u32 omap_device_get_context_loss_count(struct platform_device *pdev);
+int omap_device_set_rate(struct device *dev, unsigned long freq);
+unsigned long omap_device_get_rate(struct device *dev);
+void omap_device_populate_rate_fns(struct device *dev,
+ int (*set_rate)(struct device *dev, unsigned long rate),
+ unsigned long (*get_rate) (struct device *dev));
/* Other */
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 2c95e61..0d67af6 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -813,6 +813,55 @@ int omap_device_enable_clocks(struct omap_device *od)
return 0;
}
+int omap_device_set_rate(struct device *dev, unsigned long freq)
+{
+ struct platform_device *pdev;
+ struct omap_device *od;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ od = _find_by_pdev(pdev);
+
+ if (!od->set_rate) {
+ dev_err(dev, "%s: No set_rate API for scaling device\n",
+ __func__);
+ return -ENODATA;
+ }
+
+ return od->set_rate(dev, freq);
+}
+
+unsigned long omap_device_get_rate(struct device *dev)
+{
+ struct platform_device *pdev;
+ struct omap_device *od;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ od = _find_by_pdev(pdev);
+
+
+ if (!od->get_rate) {
+ dev_err(dev, "%s: No get rate API for the device\n",
+ __func__);
+ return 0;
+ }
+
+ return od->get_rate(dev);
+}
+
+void omap_device_populate_rate_fns(struct device *dev,
+ int (*set_rate)(struct device *dev, unsigned long rate),
+ unsigned long (*get_rate) (struct device *dev))
+{
+ struct platform_device *pdev;
+ struct omap_device *od;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ od = _find_by_pdev(pdev);
+
+ od->set_rate = set_rate;
+ od->get_rate = get_rate;
+}
+
struct device omap_device_parent = {
.init_name = "omap",
.parent = &platform_bus,
--
1.6.6.1

View File

@@ -0,0 +1,134 @@
From 3a9b78f58772645a9e1337454faed4e313e55368 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 29 Oct 2010 20:43:34 +0530
Subject: [PATCH 10/19] OMAP: Voltage layer changes to support DVFS.
This patch introduces an API to take in the voltage domain and the
new voltage as parameter and to scale all the scalable devices
associated with the the voltage domain to the rate corresponding to the
new voltage and scale the voltage domain to the new voltage.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/mach-omap2/voltage.c | 69 +++++++++++++++++++++++++++++
arch/arm/plat-omap/include/plat/voltage.h | 7 +++
2 files changed, 76 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 7381fa6..9adf9d1 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -27,9 +27,11 @@
#include <linux/spinlock.h>
#include <linux/plist.h>
#include <linux/slab.h>
+#include <linux/opp.h>
#include <plat/common.h>
#include <plat/voltage.h>
+#include <plat/omap_device.h>
#include "prm-regbits-34xx.h"
#include "prm-regbits-44xx.h"
@@ -1656,6 +1658,73 @@ struct voltagedomain *omap_voltage_domain_lookup(char *name)
}
/**
+ * omap_voltage_scale : API to scale the devices associated with a
+ * voltage domain vdd voltage.
+ * @volt_domain : the voltage domain to be scaled
+ * @volt : the new voltage for the voltage domain
+ *
+ * This API runs through the list of devices associated with the
+ * voltage domain and scales the device rates to those corresponding
+ * to the new voltage of the voltage domain. This API also scales
+ * the voltage domain voltage to the new value. Returns 0 on success
+ * else the error value.
+ */
+int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
+{
+ unsigned long curr_volt;
+ int is_volt_scaled = 0;
+ struct omap_vdd_info *vdd;
+ struct omap_vdd_dev_list *temp_dev;
+
+ if (!voltdm || IS_ERR(voltdm)) {
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
+ return -EINVAL;
+ }
+
+ vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
+
+ mutex_lock(&vdd->scaling_mutex);
+
+ curr_volt = omap_voltage_get_nom_volt(voltdm);
+
+ if (curr_volt == volt) {
+ is_volt_scaled = 1;
+ } else if (curr_volt < volt) {
+ omap_voltage_scale_vdd(voltdm, volt);
+ is_volt_scaled = 1;
+ }
+
+ list_for_each_entry(temp_dev, &vdd->dev_list, node) {
+ struct device *dev;
+ struct opp *opp;
+ unsigned long freq;
+
+ dev = temp_dev->dev;
+
+ opp = opp_find_voltage(dev, volt);
+ if (IS_ERR(opp))
+ continue;
+
+ freq = opp_get_freq(opp);
+
+ if (freq == omap_device_get_rate(dev)) {
+ dev_warn(dev, "%s: Already at the requested"
+ "rate %ld\n", __func__, freq);
+ continue;
+ }
+
+ omap_device_set_rate(dev, freq);
+ }
+
+ if (!is_volt_scaled)
+ omap_voltage_scale_vdd(voltdm, volt);
+
+ mutex_unlock(&vdd->scaling_mutex);
+
+ return 0;
+}
+
+/**
* omap_voltage_late_init() - Init the various voltage parameters
*
* This API is to be called in the later stages of the
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
index adbc6af..6782c5e 100644
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -135,6 +135,7 @@ int omap_voltage_late_init(void);
int omap_voltage_add_request(struct voltagedomain *voltdm, struct device *dev,
unsigned long *volt);
int omap_voltage_add_dev(struct voltagedomain *voltdm, struct device *dev);
+int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt);
#else
static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
struct omap_volt_pmic_info *pmic_info) {}
@@ -154,6 +155,12 @@ static inline int omap_voltage_add_dev(struct voltagedomain *voltdm,
{
return -EINVAL;
}
+
+static inline int omap_voltage_scale(struct voltagedomain *voltdm,
+ unsigned long volt)
+{
+ return -EINVAL;
+}
#endif
#endif
--
1.6.6.1

View File

@@ -0,0 +1,195 @@
From 444b19e90ae45ccd68c84285fe8339d797a08911 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 2 Jul 2010 13:06:57 +0530
Subject: [PATCH 11/19] OMAP: Introduce dependent voltage domain support.
There could be dependencies between various voltage domains for
maintaining system performance or hardware limitation reasons
like VDD<X> should be at voltage v1 when VDD<Y> is at voltage v2.
This patch introduce dependent vdd information structures in the
voltage layer which can be used to populate these dependencies
for a voltage domain. This patch also adds support to scale
the dependent vdd and the scalable devices belonging to it
during the scaling of a main vdd through omap_voltage_scale.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/mach-omap2/voltage.c | 122 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 122 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 9adf9d1..c83d968 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -123,6 +123,36 @@ struct vc_reg_info {
};
/**
+ * omap_vdd_dep_volt - Table containing the parent vdd voltage and the
+ * dependent vdd voltage corresponding to it.
+ *
+ * @main_vdd_volt : The main vdd voltage
+ * @dep_vdd_volt : The voltage at which the dependent vdd should be
+ * when the main vdd is at <main_vdd_volt> voltage
+ */
+struct omap_vdd_dep_volt {
+ u32 main_vdd_volt;
+ u32 dep_vdd_volt;
+};
+
+/**
+ * omap_vdd_dep_info - Dependent vdd info
+ *
+ * @name : Dependent vdd name
+ * @voltdm : Dependent vdd pointer
+ * @dep_table : Table containing the dependent vdd voltage
+ * corresponding to every main vdd voltage.
+ * @cur_dep_volt : The voltage to which dependent vdd should be put
+ * to for the current main vdd voltage.
+ */
+struct omap_vdd_dep_info {
+ char *name;
+ struct voltagedomain *voltdm;
+ struct omap_vdd_dep_volt *dep_table;
+ unsigned long cur_dep_volt;
+};
+
+/**
* struct omap_vdd_user_list - The per vdd user list
*
* @dev: The device asking for the vdd to be set at a particular
@@ -174,11 +204,13 @@ struct omap_vdd_info {
struct vp_reg_val vp_reg;
struct vc_reg_info vc_reg;
struct voltagedomain voltdm;
+ struct omap_vdd_dep_info *dep_vdd_info;
struct dentry *debug_dir;
spinlock_t user_lock;
struct plist_head user_list;
struct mutex scaling_mutex;
struct list_head dev_list;
+ int nr_dep_vdd;
u32 curr_volt;
u16 ocp_mod;
u8 prm_irqst_reg;
@@ -1160,6 +1192,80 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
return 0;
}
+static int calc_dep_vdd_volt(struct device *dev,
+ struct omap_vdd_info *main_vdd, unsigned long main_volt)
+{
+ struct omap_vdd_dep_info *dep_vdds;
+ int i, ret = 0;
+
+ if (!main_vdd->dep_vdd_info) {
+ pr_debug("%s: No dependent VDD's for vdd_%s\n",
+ __func__, main_vdd->voltdm.name);
+ return 0;
+ }
+
+ dep_vdds = main_vdd->dep_vdd_info;
+
+ for (i = 0; i < main_vdd->nr_dep_vdd; i++) {
+ struct omap_vdd_dep_volt *volt_table = dep_vdds[i].dep_table;
+ int nr_volt = 0;
+ unsigned long dep_volt = 0, act_volt = 0;
+
+ while (volt_table[nr_volt].main_vdd_volt != 0) {
+ if (volt_table[nr_volt].main_vdd_volt == main_volt) {
+ dep_volt = volt_table[nr_volt].dep_vdd_volt;
+ break;
+ }
+ nr_volt++;
+ }
+ if (!dep_volt) {
+ pr_warning("%s: Not able to find a matching volt for"
+ "vdd_%s corresponding to vdd_%s %ld volt\n",
+ __func__, dep_vdds[i].name,
+ main_vdd->voltdm.name, main_volt);
+ ret = -EINVAL;
+ continue;
+ }
+
+ if (!dep_vdds[i].voltdm)
+ dep_vdds[i].voltdm =
+ omap_voltage_domain_lookup(dep_vdds[i].name);
+
+ act_volt = dep_volt;
+
+ /* See if dep_volt is possible for the vdd*/
+ ret = omap_voltage_add_request(dep_vdds[i].voltdm, dev,
+ &act_volt);
+
+ /*
+ * Currently we do not bother if the dep volt and act volt are
+ * different. We could add a check if needed.
+ */
+ dep_vdds[i].cur_dep_volt = act_volt;
+ }
+
+ return ret;
+}
+
+static int scale_dep_vdd(struct omap_vdd_info *main_vdd)
+{
+ struct omap_vdd_dep_info *dep_vdds;
+ int i;
+
+ if (!main_vdd->dep_vdd_info) {
+ pr_debug("%s: No dependent VDD's for vdd_%s\n",
+ __func__, main_vdd->voltdm.name);
+ return 0;
+ }
+
+ dep_vdds = main_vdd->dep_vdd_info;
+
+ for (i = 0; i < main_vdd->nr_dep_vdd; i++)
+ omap_voltage_scale(dep_vdds[i].voltdm,
+ dep_vdds[i].cur_dep_volt);
+ return 0;
+}
+
/* Public functions */
/**
* omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
@@ -1675,6 +1781,8 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
int is_volt_scaled = 0;
struct omap_vdd_info *vdd;
struct omap_vdd_dev_list *temp_dev;
+ struct plist_node *node;
+ struct omap_vdd_user_list *user;
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
@@ -1687,6 +1795,17 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
curr_volt = omap_voltage_get_nom_volt(voltdm);
+ /* Find the device requesting the voltage scaling */
+ node = plist_first(&vdd->user_list);
+ user = container_of(node, struct omap_vdd_user_list, node);
+
+ /* calculate the voltages for dependent vdd's */
+ if (calc_dep_vdd_volt(user->dev, vdd, volt)) {
+ pr_warning("%s: Error in calculating dependent vdd voltages"
+ "for vdd_%s\n", __func__, voltdm->name);
+ return -EINVAL;
+ }
+
if (curr_volt == volt) {
is_volt_scaled = 1;
} else if (curr_volt < volt) {
@@ -1721,6 +1840,9 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
mutex_unlock(&vdd->scaling_mutex);
+ /* Scale dependent vdds */
+ scale_dep_vdd(vdd);
+
return 0;
}
--
1.6.6.1

View File

@@ -0,0 +1,134 @@
From 40c41b250b9430b9d9998751fdf7e03201d1784e Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 2 Jul 2010 13:07:35 +0530
Subject: [PATCH 12/19] OMAP: Introduce device scale
This patch adds omap_device_scale API which can be used to generic
device rate scaling.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/plat-omap/include/plat/omap_device.h | 3 +-
arch/arm/plat-omap/omap_device.c | 78 +++++++++++++++++++++++++
2 files changed, 80 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index 1178b86..e44a0f7 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -117,6 +117,8 @@ unsigned long omap_device_get_rate(struct device *dev);
void omap_device_populate_rate_fns(struct device *dev,
int (*set_rate)(struct device *dev, unsigned long rate),
unsigned long (*get_rate) (struct device *dev));
+int omap_device_scale(struct device *req_dev, struct device *dev,
+ unsigned long rate);
/* Other */
@@ -126,7 +128,6 @@ int omap_device_enable_hwmods(struct omap_device *od);
int omap_device_disable_clocks(struct omap_device *od);
int omap_device_enable_clocks(struct omap_device *od);
-
/*
* Entries should be kept in latency order ascending
*
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 0d67af6..458d648 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -83,6 +83,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk.h>
+#include <linux/opp.h>
#include <plat/omap_device.h>
#include <plat/omap_hwmod.h>
@@ -862,6 +863,83 @@ void omap_device_populate_rate_fns(struct device *dev,
od->get_rate = get_rate;
}
+/**
+ * omap_device_scale() - Set a new rate at which the device is to operate
+ * @req_dev: pointer to the device requesting the scaling.
+ * @dev: pointer to the device that is to be scaled
+ * @rate: the rnew rate for the device.
+ *
+ * This API gets the device opp table associated with this device and
+ * tries putting the device to the requested rate and the voltage domain
+ * associated with the device to the voltage corresponding to the
+ * requested rate. Since multiple devices can be assocciated with a
+ * voltage domain this API finds out the possible voltage the
+ * voltage domain can enter and then decides on the final device
+ * rate. Return 0 on success else the error value
+ */
+int omap_device_scale(struct device *req_dev, struct device *dev,
+ unsigned long rate)
+{
+ struct opp *opp;
+ unsigned long volt, freq, min_freq, max_freq;
+ struct voltagedomain *voltdm;
+ struct platform_device *pdev;
+ struct omap_device *od;
+ int ret;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ od = _find_by_pdev(pdev);
+
+ /*
+ * Figure out if the desired frquency lies between the
+ * maximum and minimum possible for the particular device
+ */
+ min_freq = 0;
+ if (IS_ERR(opp_find_freq_ceil(dev, &min_freq))) {
+ dev_err(dev, "%s: Unable to find lowest opp\n", __func__);
+ return -ENODEV;
+ }
+
+ max_freq = ULONG_MAX;
+ if (IS_ERR(opp_find_freq_floor(dev, &max_freq))) {
+ dev_err(dev, "%s: Unable to find highest opp\n", __func__);
+ return -ENODEV;
+ }
+
+ if (rate < min_freq)
+ freq = min_freq;
+ else if (rate > max_freq)
+ freq = max_freq;
+ else
+ freq = rate;
+
+ opp = opp_find_freq_ceil(dev, &freq);
+ if (IS_ERR(opp)) {
+ dev_err(dev, "%s: Unable to find OPP for freq%ld\n",
+ __func__, rate);
+ return -ENODEV;
+ }
+
+ /* Get the voltage corresponding to the requested frequency */
+ volt = opp_get_voltage(opp);
+
+ /*
+ * Call into the voltage layer to get the final voltage possible
+ * for the voltage domain associated with the device.
+ */
+ voltdm = od->hwmods[0]->voltdm;
+ ret = omap_voltage_add_request(voltdm, req_dev, &volt);
+ if (ret) {
+ dev_err(dev, "%s: Unable to get the final volt for scaling\n",
+ __func__);
+ return ret;
+ }
+
+ /* Do the actual scaling */
+ return omap_voltage_scale(voltdm, volt);
+}
+EXPORT_SYMBOL(omap_device_scale);
+
struct device omap_device_parent = {
.init_name = "omap",
.parent = &platform_bus,
--
1.6.6.1

View File

@@ -0,0 +1,50 @@
From 72eb0b4978e15f56c99900ec8da10b91864eda98 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 2 Jul 2010 13:06:57 +0530
Subject: [PATCH 13/19] OMAP: Disable smartreflex across DVFS
This patch disables smartreflex for a particular voltage
domain when the the voltage domain and the devices belonging
to it is being scaled and re-enables it back once the scaling
is done.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/mach-omap2/voltage.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index c83d968..2f331de 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -32,6 +32,7 @@
#include <plat/common.h>
#include <plat/voltage.h>
#include <plat/omap_device.h>
+#include <plat/smartreflex.h>
#include "prm-regbits-34xx.h"
#include "prm-regbits-44xx.h"
@@ -1806,6 +1807,9 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
return -EINVAL;
}
+ /* Disable smartreflex module across voltage and frequency scaling */
+ omap_sr_disable(voltdm);
+
if (curr_volt == volt) {
is_volt_scaled = 1;
} else if (curr_volt < volt) {
@@ -1840,6 +1844,9 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
mutex_unlock(&vdd->scaling_mutex);
+ /* Enable Smartreflex module */
+ omap_sr_enable(voltdm);
+
/* Scale dependent vdds */
scale_dep_vdd(vdd);
--
1.6.6.1

View File

@@ -0,0 +1,176 @@
From 42e395f0dcc618300267f440f613572635eb2e55 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Wed, 18 Aug 2010 16:22:32 +0530
Subject: [PATCH 14/19] OMAP3: Introduce custom set rate and get rate APIs for scalable devices
This patch also introduces omap3_mpu_set_rate, omap3_iva_set_rate,
omap3_l3_set_rate, omap3_mpu_get_rate, omap3_iva_get_rate,
omap3_l3_get_rate as device specific set rate and get rate
APIs for OMAP3 mpu, iva and l3_main devices. This patch also
calls into omap_device_populate_rate_fns during system init to register
various set_rate and get_rate APIs with the omap device layer
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/mach-omap2/pm.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index d5a102c..94ab0dd 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -14,6 +14,7 @@
#include <linux/io.h>
#include <linux/err.h>
#include <linux/opp.h>
+#include <linux/delay.h>
#include <plat/omap-pm.h>
#include <plat/omap_device.h>
@@ -22,6 +23,8 @@
#include "powerdomain.h"
#include "clockdomain.h"
+#include "cm-regbits-34xx.h"
+#include "cm2xxx_3xxx.h"
#include "pm.h"
static struct omap_device_pm_latency *pm_lats;
@@ -31,6 +34,8 @@ static struct device *iva_dev;
static struct device *l3_dev;
static struct device *dsp_dev;
+static struct clk *dpll1_clk, *dpll2_clk, *dpll3_clk;
+
struct device *omap2_get_mpuss_device(void)
{
WARN_ON_ONCE(!mpu_dev);
@@ -56,6 +61,26 @@ struct device *omap4_get_dsp_device(void)
}
EXPORT_SYMBOL(omap4_get_dsp_device);
+static unsigned long compute_lpj(unsigned long ref, u_int div, u_int mult)
+{
+ unsigned long new_jiffy_l, new_jiffy_h;
+
+ /*
+ * Recalculate loops_per_jiffy. We do it this way to
+ * avoid math overflow on 32-bit machines. Maybe we
+ * should make this architecture dependent? If you have
+ * a better way of doing this, please replace!
+ *
+ * new = old * mult / div
+ */
+ new_jiffy_h = ref / div;
+ new_jiffy_l = (ref % div) / 100;
+ new_jiffy_h *= mult;
+ new_jiffy_l = new_jiffy_l * mult / div;
+
+ return new_jiffy_h + new_jiffy_l * 100;
+}
+
/* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
static int _init_omap_device(char *name, struct device **new_dev)
{
@@ -77,6 +102,74 @@ static int _init_omap_device(char *name, struct device **new_dev)
return 0;
}
+static unsigned long omap3_mpu_get_rate(struct device *dev)
+{
+ return dpll1_clk->rate;
+}
+
+static int omap3_mpu_set_rate(struct device *dev, unsigned long rate)
+{
+ unsigned long cur_rate = omap3_mpu_get_rate(dev);
+ int ret;
+
+#ifdef CONFIG_CPU_FREQ
+ struct cpufreq_freqs freqs_notify;
+
+ freqs_notify.old = cur_rate / 1000;
+ freqs_notify.new = rate / 1000;
+ freqs_notify.cpu = 0;
+ /* Send pre notification to CPUFreq */
+ cpufreq_notify_transition(&freqs_notify, CPUFREQ_PRECHANGE);
+#endif
+ ret = clk_set_rate(dpll1_clk, rate);
+ if (ret) {
+ dev_warn(dev, "%s: Unable to set rate to %ld\n",
+ __func__, rate);
+ return ret;
+ }
+
+#ifdef CONFIG_CPU_FREQ
+ /* Send a post notification to CPUFreq */
+ cpufreq_notify_transition(&freqs_notify, CPUFREQ_POSTCHANGE);
+#endif
+
+#ifndef CONFIG_CPU_FREQ
+ /*Update loops_per_jiffy if processor speed is being changed*/
+ loops_per_jiffy = compute_lpj(loops_per_jiffy,
+ cur_rate / 1000, rate / 1000);
+#endif
+ return 0;
+}
+
+static int omap3_iva_set_rate(struct device *dev, unsigned long rate)
+{
+ return clk_set_rate(dpll2_clk, rate);
+}
+
+static unsigned long omap3_iva_get_rate(struct device *dev)
+{
+ return dpll2_clk->rate;
+}
+
+static int omap3_l3_set_rate(struct device *dev, unsigned long rate)
+{
+ int l3_div;
+
+ l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
+ OMAP3430_CLKSEL_L3_MASK;
+
+ return clk_set_rate(dpll3_clk, rate * l3_div);
+}
+
+static unsigned long omap3_l3_get_rate(struct device *dev)
+{
+ int l3_div;
+
+ l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
+ OMAP3430_CLKSEL_L3_MASK;
+ return dpll3_clk->rate / l3_div;
+}
+
/*
* Build omap_devices for processors and bus.
*/
@@ -90,6 +183,23 @@ static void omap2_init_processor_devices(void)
} else {
_init_omap_device("l3_main", &l3_dev);
}
+
+ if (cpu_is_omap34xx()) {
+ dpll1_clk = clk_get(NULL, "dpll1_ck");
+ dpll2_clk = clk_get(NULL, "dpll2_ck");
+ dpll3_clk = clk_get(NULL, "dpll3_m2_ck");
+
+ if (mpu_dev)
+ omap_device_populate_rate_fns(mpu_dev,
+ omap3_mpu_set_rate, omap3_mpu_get_rate);
+ if (iva_dev)
+ omap_device_populate_rate_fns(iva_dev,
+ omap3_iva_set_rate, omap3_iva_get_rate);
+ if (l3_dev)
+ omap_device_populate_rate_fns(l3_dev,
+ omap3_l3_set_rate, omap3_l3_get_rate);
+
+ }
}
/* Types of sleep_switch used in omap_set_pwrdm_state */
--
1.6.6.1

View File

@@ -0,0 +1,54 @@
From 0c5c41f6bcf77b388f49615ac28ccde294e7a5bd Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Fri, 2 Jul 2010 13:07:49 +0530
Subject: [PATCH 15/19] OMAP3: Update cpufreq driver to use the new set_rate API
This patch updates the cpufreq driver to use the device
set rate API to scale the mpu frequency for OMAP3.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/plat-omap/cpu-omap.c | 11 ++++-------
1 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 671e4b9..71777db 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -31,10 +31,7 @@
#include <plat/clock.h>
#include <plat/common.h>
#include <asm/system.h>
-
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
-#include <plat/omap-pm.h>
-#endif
+#include <plat/omap_device.h>
#define VERY_HI_RATE 900000000
@@ -88,7 +85,7 @@ static int omap_target(struct cpufreq_policy *policy,
#ifdef CONFIG_ARCH_OMAP1
struct cpufreq_freqs freqs;
#endif
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
+#if defined(CONFIG_ARCH_OMAP3)
unsigned long freq;
struct device *mpu_dev = omap2_get_mpuss_device();
#endif
@@ -115,10 +112,10 @@ static int omap_target(struct cpufreq_policy *policy,
#endif
ret = clk_set_rate(mpu_clk, freqs.new * 1000);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
+#elif defined(CONFIG_ARCH_OMAP3)
freq = target_freq * 1000;
if (opp_find_freq_ceil(mpu_dev, &freq))
- omap_pm_cpu_set_freq(freq);
+ omap_device_scale(mpu_dev, mpu_dev, freq);
#endif
return ret;
}
--
1.6.6.1

View File

@@ -0,0 +1,45 @@
From a66e4a5a5ee1d98fafab60935bddd28bbd440628 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Wed, 18 Aug 2010 16:22:43 +0530
Subject: [PATCH 16/19] OMAP3: Introduce voltage domain info in the hwmod structures.
This patch adds voltage domain info in the relevant
device hwmod structures so as to enable OMAP3 DVFS
support.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 8d81813..c57f34d 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -94,6 +94,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = {
static struct omap_hwmod omap3xxx_l3_main_hwmod = {
.name = "l3_main",
.class = &l3_hwmod_class,
+ .vdd_name = "core",
.masters = omap3xxx_l3_main_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_l3_main_masters),
.slaves = omap3xxx_l3_main_slaves,
@@ -384,6 +385,7 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = {
.name = "mpu",
.class = &mpu_hwmod_class,
.main_clk = "arm_fck",
+ .vdd_name = "mpu",
.masters = omap3xxx_mpu_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_mpu_masters),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -412,6 +414,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_iva_masters[] = {
static struct omap_hwmod omap3xxx_iva_hwmod = {
.name = "iva",
.class = &iva_hwmod_class,
+ .vdd_name = "mpu",
.masters = omap3xxx_iva_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_iva_masters),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
--
1.6.6.1

View File

@@ -0,0 +1,61 @@
From 6e99ca0e5780932988471f106099c98595cb0aa3 Mon Sep 17 00:00:00 2001
From: Thara Gopinath <thara@ti.com>
Date: Wed, 18 Aug 2010 16:22:49 +0530
Subject: [PATCH 17/19] OMAP3: Add voltage dependency table for VDD1.
In OMAP3, for perfomrance reasons when VDD1 is at voltage above
1.075V, VDD2 should be at 1.15V for perfomrance reasons. This
patch introduce this cross VDD dependency for OMAP3 VDD1.
Signed-off-by: Thara Gopinath <thara@ti.com>
---
arch/arm/mach-omap2/voltage.c | 24 ++++++++++++++++++++++--
1 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 2f331de..d10cb1b 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -374,6 +374,23 @@ static struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
VOLT_DATA_DEFINE(0, 0, 0, 0),
};
+/* OMAP 3430 MPU Core VDD dependency table */
+static struct omap_vdd_dep_volt omap34xx_vdd1_vdd2_data[] = {
+ {.main_vdd_volt = 975000, .dep_vdd_volt = 1050000},
+ {.main_vdd_volt = 1075000, .dep_vdd_volt = 1050000},
+ {.main_vdd_volt = 1200000, .dep_vdd_volt = 1150000},
+ {.main_vdd_volt = 1270000, .dep_vdd_volt = 1150000},
+ {.main_vdd_volt = 1350000, .dep_vdd_volt = 1150000},
+ {.main_vdd_volt = 0, .dep_vdd_volt = 0},
+};
+
+static struct omap_vdd_dep_info omap34xx_vdd1_dep_info[] = {
+ {
+ .name = "core",
+ .dep_table = omap34xx_vdd1_vdd2_data,
+ },
+};
+
static struct dentry *voltage_dir;
/* Init function pointers */
@@ -879,10 +896,13 @@ static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
}
if (!strcmp(vdd->voltdm.name, "mpu")) {
- if (cpu_is_omap3630())
+ if (cpu_is_omap3630()) {
vdd->volt_data = omap36xx_vddmpu_volt_data;
- else
+ } else {
vdd->volt_data = omap34xx_vddmpu_volt_data;
+ vdd->dep_vdd_info = omap34xx_vdd1_dep_info;
+ vdd->nr_dep_vdd = ARRAY_SIZE(omap34xx_vdd1_dep_info);
+ }
vdd->vp_reg.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK;
vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET;
--
1.6.6.1

View File

@@ -0,0 +1,62 @@
From 53d08ca85f9b623e25ba9a976bc3315f3784a3a7 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Wed, 5 Jan 2011 14:14:55 -0600
Subject: [PATCH 18/19] omap3|4: opp: make omapx_opp_init non-static
omap3 and omap4 opp_init should be made non-static to allow
for platform specific opp table tweaking. making these static
conflicts with the definition in pm.h(global) as well.
we include pm.h as well to ensure that there are no such prototype
conflicts with actual implementation in the future.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/opp3xxx_data.c | 3 ++-
arch/arm/mach-omap2/opp4xxx_data.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
index 0486fce..fd3a1af 100644
--- a/arch/arm/mach-omap2/opp3xxx_data.c
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
@@ -21,6 +21,7 @@
#include <plat/cpu.h>
#include "omap_opp_data.h"
+#include "pm.h"
static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
/* MPU OPP1 */
@@ -88,7 +89,7 @@ static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
/**
* omap3_opp_init() - initialize omap3 opp table
*/
-static int __init omap3_opp_init(void)
+int __init omap3_opp_init(void)
{
int r = -ENODEV;
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index a11fa56..f0e9939 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -22,6 +22,7 @@
#include <plat/cpu.h>
#include "omap_opp_data.h"
+#include "pm.h"
static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
/* MPU OPP1 - OPP50 */
@@ -42,7 +43,7 @@ static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
/**
* omap4_opp_init() - initialize omap4 opp table
*/
-static int __init omap4_opp_init(void)
+int __init omap4_opp_init(void)
{
int r = -ENODEV;
--
1.6.6.1

View File

@@ -0,0 +1,107 @@
From 1f77cf1150d5e0205ab3f588ab25cbdf65acdc40 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Wed, 5 Jan 2011 14:16:59 -0600
Subject: [PATCH 19/19] OMAP3: beagle xm: enable upto 1GHz OPP
Beagle XM uses 3730 and the board design allows enabling 800MHz and 1GHz
OPPs. tweak the default table to allow for higher OPP tables
Reported-by: Koen Kooi <koen@beagleboard.org>
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/board-omap3beagle.c | 54 +++++++++++++++++++++++++++++++
1 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 006dc26..9393e75 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -24,6 +24,7 @@
#include <linux/irq.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
+#include <linux/opp.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
@@ -45,10 +46,12 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
#include <plat/usb.h>
+#include <plat/omap_device.h>
#include "mux.h"
#include "hsmmc.h"
#include "timer-gp.h"
+#include "pm.h"
#define NAND_BLOCK_SIZE SZ_128K
@@ -778,6 +781,56 @@ static int __init expansionboard_setup(char *str)
return 0;
}
+static void __init beagle_opp_init(void)
+{
+ int r = 0;
+
+ /* Initialize the omap3 opp table */
+ if (omap3_opp_init()) {
+ pr_err("%s: opp default init failed\n", __func__);
+ return;
+ }
+
+ /* Custom OPP enabled for XM */
+ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+ struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
+ struct omap_hwmod *dh = omap_hwmod_lookup("iva");
+ struct device *dev;
+
+ if (!mh || !dh) {
+ pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
+ __func__, mh, dh);
+ r = -EINVAL;
+ } else {
+ /* Enable MPU 1GHz and lower opps */
+ dev = &mh->od->pdev.dev;
+ r = opp_enable(dev, 800000000);
+ r |= opp_enable(dev, 1000000000);
+
+ /* Enable IVA 800MHz and lower opps */
+ dev = &dh->od->pdev.dev;
+ r |= opp_enable(dev, 660000000);
+ r |= opp_enable(dev, 800000000);
+ }
+ if (r) {
+ pr_err("%s: failed to enable higher opp %d\n",
+ __func__, r);
+ /*
+ * Cleanup - disable the higher freqs - we dont care
+ * about the results
+ */
+ dev = &mh->od->pdev.dev;
+ opp_disable(dev, 800000000);
+ opp_disable(dev, 1000000000);
+ dev = &dh->od->pdev.dev;
+ opp_disable(dev, 660000000);
+ opp_disable(dev, 800000000);
+ } else {
+ pr_err("%s: turbo OPPs enabled!\n", __func__);
+ }
+ }
+}
+
static void __init omap3_beagle_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -850,6 +903,7 @@ static void __init omap3_beagle_init(void)
omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
beagle_display_init();
+ beagle_opp_init();
}
early_param("buddy", expansionboard_setup);
--
1.6.6.1

View File

@@ -0,0 +1,29 @@
From a74b74a5555c741ed3df896096e33b853995631e Mon Sep 17 00:00:00 2001
From: Lennert Buytenhek <buytenh@wantstofly.org>
Date: Wed, 15 Dec 2010 07:20:16 +0800
Subject: [PATCH 01/66] ARM: pxa: PXA_ESERIES depends on FB_W100.
As arch/arm/mach-pxa/eseries.c references w100fb_gpio_{read,write}()
directly.
Signed-off-by: Lennert Buytenhek <buytenh@secretlab.ca>
Signed-off-by: Eric Miao <eric.y.miao@gmail.com>
---
arch/arm/mach-pxa/Kconfig | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index dd235ec..c93e73d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -540,6 +540,7 @@ config MACH_ICONTROL
config ARCH_PXA_ESERIES
bool "PXA based Toshiba e-series PDAs"
select PXA25x
+ select FB_W100
config MACH_E330
bool "Toshiba e330"
--
1.6.6.1

View File

@@ -0,0 +1,32 @@
From 1ae1b5f053cf36bd0f913e83f3b136fec8152d4d Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@arm.linux.org.uk>
Date: Sat, 18 Dec 2010 13:57:00 +0000
Subject: [PATCH 02/66] ARM: smp: avoid incrementing mm_users on CPU startup
We should not be incrementing mm_users when we startup a secondary
CPU - doing so results in mm_users incrementing by one each time we
hotplug a CPU, which will eventually wrap, and will cause problems.
Other architectures such as x86 do not increment mm_users, but only
mm_count, so we follow that pattern.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/kernel/smp.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 8c19595..9066473 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -310,7 +310,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
* All kernel threads share the same mm context; grab a
* reference and switch to it.
*/
- atomic_inc(&mm->mm_users);
atomic_inc(&mm->mm_count);
current->active_mm = mm;
cpumask_set_cpu(cpu, mm_cpumask(mm));
--
1.6.6.1

View File

@@ -0,0 +1,186 @@
From 39af22a79232373764904576f31572f1db76af10 Mon Sep 17 00:00:00 2001
From: Nicolas Pitre <nicolas.pitre@linaro.org>
Date: Wed, 15 Dec 2010 15:14:45 -0500
Subject: [PATCH 03/66] ARM: get rid of kmap_high_l1_vipt()
Since commit 3e4d3af501 "mm: stack based kmap_atomic()", it is no longer
necessary to carry an ad hoc version of kmap_atomic() added in commit
7e5a69e83b "ARM: 6007/1: fix highmem with VIPT cache and DMA" to cope
with reentrancy.
In fact, it is now actively wrong to rely on fixed kmap type indices
(namely KM_L1_CACHE) as kmap_atomic() totally ignores them now and a
concurrent instance of it may reuse any slot for any purpose.
Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
---
arch/arm/include/asm/highmem.h | 3 -
arch/arm/mm/dma-mapping.c | 7 ++-
arch/arm/mm/flush.c | 7 ++-
arch/arm/mm/highmem.c | 87 ----------------------------------------
4 files changed, 8 insertions(+), 96 deletions(-)
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h
index 1fc684e..7080e2c 100644
--- a/arch/arm/include/asm/highmem.h
+++ b/arch/arm/include/asm/highmem.h
@@ -25,9 +25,6 @@ extern void *kmap_high(struct page *page);
extern void *kmap_high_get(struct page *page);
extern void kunmap_high(struct page *page);
-extern void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte);
-extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte);
-
/*
* The following functions are already defined by <linux/highmem.h>
* when CONFIG_HIGHMEM is not set.
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ac6a361..809f1bf 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
#include <asm/memory.h>
#include <asm/highmem.h>
@@ -480,10 +481,10 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
op(vaddr, len, dir);
kunmap_high(page);
} else if (cache_is_vipt()) {
- pte_t saved_pte;
- vaddr = kmap_high_l1_vipt(page, &saved_pte);
+ /* unmapped pages might still be cached */
+ vaddr = kmap_atomic(page);
op(vaddr + offset, len, dir);
- kunmap_high_l1_vipt(page, saved_pte);
+ kunmap_atomic(vaddr);
}
} else {
vaddr = page_address(page) + offset;
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 391ffae..c29f283 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
+#include <linux/highmem.h>
#include <asm/cacheflush.h>
#include <asm/cachetype.h>
@@ -180,10 +181,10 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
kunmap_high(page);
} else if (cache_is_vipt()) {
- pte_t saved_pte;
- addr = kmap_high_l1_vipt(page, &saved_pte);
+ /* unmapped pages might still be cached */
+ addr = kmap_atomic(page);
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
- kunmap_high_l1_vipt(page, saved_pte);
+ kunmap_atomic(addr);
}
}
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index c435fd9..807c057 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -140,90 +140,3 @@ struct page *kmap_atomic_to_page(const void *ptr)
pte = TOP_PTE(vaddr);
return pte_page(*pte);
}
-
-#ifdef CONFIG_CPU_CACHE_VIPT
-
-#include <linux/percpu.h>
-
-/*
- * The VIVT cache of a highmem page is always flushed before the page
- * is unmapped. Hence unmapped highmem pages need no cache maintenance
- * in that case.
- *
- * However unmapped pages may still be cached with a VIPT cache, and
- * it is not possible to perform cache maintenance on them using physical
- * addresses unfortunately. So we have no choice but to set up a temporary
- * virtual mapping for that purpose.
- *
- * Yet this VIPT cache maintenance may be triggered from DMA support
- * functions which are possibly called from interrupt context. As we don't
- * want to keep interrupt disabled all the time when such maintenance is
- * taking place, we therefore allow for some reentrancy by preserving and
- * restoring the previous fixmap entry before the interrupted context is
- * resumed. If the reentrancy depth is 0 then there is no need to restore
- * the previous fixmap, and leaving the current one in place allow it to
- * be reused the next time without a TLB flush (common with DMA).
- */
-
-static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);
-
-void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte)
-{
- unsigned int idx, cpu;
- int *depth;
- unsigned long vaddr, flags;
- pte_t pte, *ptep;
-
- if (!in_interrupt())
- preempt_disable();
-
- cpu = smp_processor_id();
- depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
-
- idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- ptep = TOP_PTE(vaddr);
- pte = mk_pte(page, kmap_prot);
-
- raw_local_irq_save(flags);
- (*depth)++;
- if (pte_val(*ptep) == pte_val(pte)) {
- *saved_pte = pte;
- } else {
- *saved_pte = *ptep;
- set_pte_ext(ptep, pte, 0);
- local_flush_tlb_kernel_page(vaddr);
- }
- raw_local_irq_restore(flags);
-
- return (void *)vaddr;
-}
-
-void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte)
-{
- unsigned int idx, cpu = smp_processor_id();
- int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
- unsigned long vaddr, flags;
- pte_t pte, *ptep;
-
- idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- ptep = TOP_PTE(vaddr);
- pte = mk_pte(page, kmap_prot);
-
- BUG_ON(pte_val(*ptep) != pte_val(pte));
- BUG_ON(*depth <= 0);
-
- raw_local_irq_save(flags);
- (*depth)--;
- if (*depth != 0 && pte_val(pte) != pte_val(saved_pte)) {
- set_pte_ext(ptep, saved_pte, 0);
- local_flush_tlb_kernel_page(vaddr);
- }
- raw_local_irq_restore(flags);
-
- if (!in_interrupt())
- preempt_enable();
-}
-
-#endif /* CONFIG_CPU_CACHE_VIPT */
--
1.6.6.1

View File

@@ -0,0 +1,189 @@
From 25cbe45440ea89a3b0f6f7ed326d3d476d53068b Mon Sep 17 00:00:00 2001
From: Nicolas Pitre <nicolas.pitre@linaro.org>
Date: Wed, 15 Dec 2010 23:29:04 -0500
Subject: [PATCH 04/66] ARM: fix cache-xsc3l2 after stack based kmap_atomic()
Since commit 3e4d3af501 "mm: stack based kmap_atomic()", it is actively
wrong to rely on fixed kmap type indices (namely KM_L2_CACHE) as
kmap_atomic() totally ignores them and a concurrent instance of it may
happily reuse any slot for any purpose. Because kmap_atomic() is now
able to deal with reentrancy, we can get rid of the ad hoc mapping here,
and we even don't have to disable IRQs anymore (highmem case).
While the code is made much simpler, there is a needless cache flush
introduced by the usage of __kunmap_atomic(). It is not clear if the
performance difference to remove that is worth the cost in code
maintenance (I don't think there are that many highmem users on that
platform if at all anyway).
Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
---
arch/arm/mm/cache-xsc3l2.c | 57 ++++++++++++++++---------------------------
1 files changed, 21 insertions(+), 36 deletions(-)
diff --git a/arch/arm/mm/cache-xsc3l2.c b/arch/arm/mm/cache-xsc3l2.c
index c315492..5a32020 100644
--- a/arch/arm/mm/cache-xsc3l2.c
+++ b/arch/arm/mm/cache-xsc3l2.c
@@ -17,14 +17,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
+#include <linux/highmem.h>
#include <asm/system.h>
#include <asm/cputype.h>
#include <asm/cacheflush.h>
-#include <asm/kmap_types.h>
-#include <asm/fixmap.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-#include "mm.h"
#define CR_L2 (1 << 26)
@@ -71,16 +67,15 @@ static inline void xsc3_l2_inv_all(void)
dsb();
}
+static inline void l2_unmap_va(unsigned long va)
+{
#ifdef CONFIG_HIGHMEM
-#define l2_map_save_flags(x) raw_local_save_flags(x)
-#define l2_map_restore_flags(x) raw_local_irq_restore(x)
-#else
-#define l2_map_save_flags(x) ((x) = 0)
-#define l2_map_restore_flags(x) ((void)(x))
+ if (va != -1)
+ kunmap_atomic((void *)va);
#endif
+}
-static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
- unsigned long flags)
+static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va)
{
#ifdef CONFIG_HIGHMEM
unsigned long va = prev_va & PAGE_MASK;
@@ -89,17 +84,10 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
/*
* Switching to a new page. Because cache ops are
* using virtual addresses only, we must put a mapping
- * in place for it. We also enable interrupts for a
- * short while and disable them again to protect this
- * mapping.
+ * in place for it.
*/
- unsigned long idx;
- raw_local_irq_restore(flags);
- idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
- va = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- raw_local_irq_restore(flags | PSR_I_BIT);
- set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0);
- local_flush_tlb_kernel_page(va);
+ l2_unmap_va(prev_va);
+ va = (unsigned long)kmap_atomic_pfn(pa >> PAGE_SHIFT);
}
return va + (pa_offset >> (32 - PAGE_SHIFT));
#else
@@ -109,7 +97,7 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
{
- unsigned long vaddr, flags;
+ unsigned long vaddr;
if (start == 0 && end == -1ul) {
xsc3_l2_inv_all();
@@ -117,13 +105,12 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
}
vaddr = -1; /* to force the first mapping */
- l2_map_save_flags(flags);
/*
* Clean and invalidate partial first cache line.
*/
if (start & (CACHE_LINE_SIZE - 1)) {
- vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags);
+ vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr);
xsc3_l2_clean_mva(vaddr);
xsc3_l2_inv_mva(vaddr);
start = (start | (CACHE_LINE_SIZE - 1)) + 1;
@@ -133,7 +120,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
* Invalidate all full cache lines between 'start' and 'end'.
*/
while (start < (end & ~(CACHE_LINE_SIZE - 1))) {
- vaddr = l2_map_va(start, vaddr, flags);
+ vaddr = l2_map_va(start, vaddr);
xsc3_l2_inv_mva(vaddr);
start += CACHE_LINE_SIZE;
}
@@ -142,31 +129,30 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
* Clean and invalidate partial last cache line.
*/
if (start < end) {
- vaddr = l2_map_va(start, vaddr, flags);
+ vaddr = l2_map_va(start, vaddr);
xsc3_l2_clean_mva(vaddr);
xsc3_l2_inv_mva(vaddr);
}
- l2_map_restore_flags(flags);
+ l2_unmap_va(vaddr);
dsb();
}
static void xsc3_l2_clean_range(unsigned long start, unsigned long end)
{
- unsigned long vaddr, flags;
+ unsigned long vaddr;
vaddr = -1; /* to force the first mapping */
- l2_map_save_flags(flags);
start &= ~(CACHE_LINE_SIZE - 1);
while (start < end) {
- vaddr = l2_map_va(start, vaddr, flags);
+ vaddr = l2_map_va(start, vaddr);
xsc3_l2_clean_mva(vaddr);
start += CACHE_LINE_SIZE;
}
- l2_map_restore_flags(flags);
+ l2_unmap_va(vaddr);
dsb();
}
@@ -193,7 +179,7 @@ static inline void xsc3_l2_flush_all(void)
static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
{
- unsigned long vaddr, flags;
+ unsigned long vaddr;
if (start == 0 && end == -1ul) {
xsc3_l2_flush_all();
@@ -201,17 +187,16 @@ static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
}
vaddr = -1; /* to force the first mapping */
- l2_map_save_flags(flags);
start &= ~(CACHE_LINE_SIZE - 1);
while (start < end) {
- vaddr = l2_map_va(start, vaddr, flags);
+ vaddr = l2_map_va(start, vaddr);
xsc3_l2_clean_mva(vaddr);
xsc3_l2_inv_mva(vaddr);
start += CACHE_LINE_SIZE;
}
- l2_map_restore_flags(flags);
+ l2_unmap_va(vaddr);
dsb();
}
--
1.6.6.1

View File

@@ -0,0 +1,119 @@
From 6d3e6d3640052cac958d61c44597cc216f6ee09f Mon Sep 17 00:00:00 2001
From: Nicolas Pitre <nicolas.pitre@linaro.org>
Date: Thu, 16 Dec 2010 14:56:34 -0500
Subject: [PATCH 05/66] ARM: fix cache-feroceon-l2 after stack based kmap_atomic()
Since commit 3e4d3af501 "mm: stack based kmap_atomic()", it is actively
wrong to rely on fixed kmap type indices (namely KM_L2_CACHE) as
kmap_atomic() totally ignores them and a concurrent instance of it may
happily reuse any slot for any purpose. Because kmap_atomic() is now
able to deal with reentrancy, we can get rid of the ad hoc mapping here.
While the code is made much simpler, there is a needless cache flush
introduced by the usage of __kunmap_atomic(). It is not clear if the
performance difference to remove that is worth the cost in code
maintenance (I don't think there are that many highmem users on that
platform anyway) but that should be reconsidered when/if someone cares
enough to do some measurements.
Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
---
arch/arm/mm/cache-feroceon-l2.c | 37 +++++++++++++++++++------------------
1 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c
index 6e77c04..e0b0e7a 100644
--- a/arch/arm/mm/cache-feroceon-l2.c
+++ b/arch/arm/mm/cache-feroceon-l2.c
@@ -13,13 +13,9 @@
*/
#include <linux/init.h>
+#include <linux/highmem.h>
#include <asm/cacheflush.h>
-#include <asm/kmap_types.h>
-#include <asm/fixmap.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
#include <plat/cache-feroceon-l2.h>
-#include "mm.h"
/*
* Low-level cache maintenance operations.
@@ -39,27 +35,30 @@
* between which we don't want to be preempted.
*/
-static inline unsigned long l2_start_va(unsigned long paddr)
+static inline unsigned long l2_get_va(unsigned long paddr)
{
#ifdef CONFIG_HIGHMEM
/*
- * Let's do our own fixmap stuff in a minimal way here.
* Because range ops can't be done on physical addresses,
* we simply install a virtual mapping for it only for the
* TLB lookup to occur, hence no need to flush the untouched
- * memory mapping. This is protected with the disabling of
- * interrupts by the caller.
+ * memory mapping afterwards (note: a cache flush may happen
+ * in some circumstances depending on the path taken in kunmap_atomic).
*/
- unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
- unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0);
- local_flush_tlb_kernel_page(vaddr);
- return vaddr + (paddr & ~PAGE_MASK);
+ void *vaddr = kmap_atomic_pfn(paddr >> PAGE_SHIFT);
+ return (unsigned long)vaddr + (paddr & ~PAGE_MASK);
#else
return __phys_to_virt(paddr);
#endif
}
+static inline void l2_put_va(unsigned long vaddr)
+{
+#ifdef CONFIG_HIGHMEM
+ kunmap_atomic((void *)vaddr);
+#endif
+}
+
static inline void l2_clean_pa(unsigned long addr)
{
__asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr));
@@ -76,13 +75,14 @@ static inline void l2_clean_pa_range(unsigned long start, unsigned long end)
*/
BUG_ON((start ^ end) >> PAGE_SHIFT);
- raw_local_irq_save(flags);
- va_start = l2_start_va(start);
+ va_start = l2_get_va(start);
va_end = va_start + (end - start);
+ raw_local_irq_save(flags);
__asm__("mcr p15, 1, %0, c15, c9, 4\n\t"
"mcr p15, 1, %1, c15, c9, 5"
: : "r" (va_start), "r" (va_end));
raw_local_irq_restore(flags);
+ l2_put_va(va_start);
}
static inline void l2_clean_inv_pa(unsigned long addr)
@@ -106,13 +106,14 @@ static inline void l2_inv_pa_range(unsigned long start, unsigned long end)
*/
BUG_ON((start ^ end) >> PAGE_SHIFT);
- raw_local_irq_save(flags);
- va_start = l2_start_va(start);
+ va_start = l2_get_va(start);
va_end = va_start + (end - start);
+ raw_local_irq_save(flags);
__asm__("mcr p15, 1, %0, c15, c11, 4\n\t"
"mcr p15, 1, %1, c15, c11, 5"
: : "r" (va_start), "r" (va_end));
raw_local_irq_restore(flags);
+ l2_put_va(va_start);
}
static inline void l2_inv_all(void)
--
1.6.6.1

View File

@@ -0,0 +1,45 @@
From 06f37751af77192b424b2b0ff17dc08de65faba0 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Tue, 14 Dec 2010 10:06:46 -0800
Subject: [PATCH 06/66] drm/i915: Set the required VFMUNIT clock gating disable on Ironlake.
It's required by the specs, but we don't know why. Let's not find out
why.
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_reg.h | 3 +++
drivers/gpu/drm/i915/intel_display.c | 2 ++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 878fc76..8470a97 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2471,6 +2471,9 @@
# define MARIUNIT_CLOCK_GATE_DISABLE (1 << 18)
# define SVSMUNIT_CLOCK_GATE_DISABLE (1 << 1)
+#define PCH_3DCGDIS1 0x46024
+# define VFMUNIT_CLOCK_GATE_DISABLE (1 << 11)
+
#define FDI_PLL_FREQ_CTL 0x46030
#define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24)
#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d9b7092..97e374e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5825,6 +5825,8 @@ void intel_init_clock_gating(struct drm_device *dev)
I915_WRITE(PCH_3DCGDIS0,
MARIUNIT_CLOCK_GATE_DISABLE |
SVSMUNIT_CLOCK_GATE_DISABLE);
+ I915_WRITE(PCH_3DCGDIS1,
+ VFMUNIT_CLOCK_GATE_DISABLE);
}
I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
--
1.6.6.1

View File

@@ -0,0 +1,38 @@
From f797d22121404eac7b63f1291409f96bcab51c11 Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris@chris-wilson.co.uk>
Date: Thu, 23 Dec 2010 09:43:48 +0000
Subject: [PATCH 07/66] drm/i915/sdvo: Add hdmi connector properties after initing the connector
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25012
Reported-by: Tõnu Raitviir <jussuf@linux.ee>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/intel_sdvo.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 27e63ab..6bc42fa 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2040,13 +2040,14 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
SDVO_COLORIMETRY_RGB256);
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
- intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
intel_sdvo->is_hdmi = true;
}
intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
(1 << INTEL_ANALOG_CLONE_BIT));
intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
+ if (intel_sdvo->is_hdmi)
+ intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
return true;
}
--
1.6.6.1

View File

@@ -0,0 +1,190 @@
From 63ee41d794d9c555f84205517a68509848988760 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Mon, 20 Dec 2010 18:40:06 -0800
Subject: [PATCH 08/66] drm/i915, intel_ips: When i915 loads after IPS, make IPS relink to i915.
The IPS driver is designed to be able to run detached from i915 and
just not enable GPU turbo in that case, in order to avoid module
dependencies between the two drivers. This means that we don't know
what the load order between the two is going to be, and we had
previously only supported IPS after (optionally) i915, but not i915
after IPS. If the wrong order was chosen, you'd get no GPU turbo, and
something like half the possible graphics performance.
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: stable@kernel.org
---
drivers/gpu/drm/i915/i915_dma.c | 23 +++++++++++++++++++++++
drivers/platform/x86/intel_ips.c | 36 +++++++++++++++++++++++++++++++++---
drivers/platform/x86/intel_ips.h | 21 +++++++++++++++++++++
3 files changed, 77 insertions(+), 3 deletions(-)
create mode 100644 drivers/platform/x86/intel_ips.h
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index e680081..cb900dc 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -34,6 +34,7 @@
#include "i915_drm.h"
#include "i915_drv.h"
#include "i915_trace.h"
+#include "../../../platform/x86/intel_ips.h"
#include <linux/pci.h>
#include <linux/vgaarb.h>
#include <linux/acpi.h>
@@ -1871,6 +1872,26 @@ out_unlock:
EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
/**
+ * Tells the intel_ips driver that the i915 driver is now loaded, if
+ * IPS got loaded first.
+ *
+ * This awkward dance is so that neither module has to depend on the
+ * other in order for IPS to do the appropriate communication of
+ * GPU turbo limits to i915.
+ */
+static void
+ips_ping_for_i915_load(void)
+{
+ void (*link)(void);
+
+ link = symbol_get(ips_link_to_i915_driver);
+ if (link) {
+ link();
+ symbol_put(ips_link_to_i915_driver);
+ }
+}
+
+/**
* i915_driver_load - setup chip and create an initial config
* @dev: DRM device
* @flags: startup flags
@@ -2075,6 +2096,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev_priv->mchdev_lock = &mchdev_lock;
spin_unlock(&mchdev_lock);
+ ips_ping_for_i915_load();
+
return 0;
out_workqueue_free:
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index c44a5e8..f0b3ad1 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -75,6 +75,7 @@
#include <drm/i915_drm.h>
#include <asm/msr.h>
#include <asm/processor.h>
+#include "intel_ips.h"
#define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32
@@ -245,6 +246,7 @@
#define thm_writel(off, val) writel((val), ips->regmap + (off))
static const int IPS_ADJUST_PERIOD = 5000; /* ms */
+static bool late_i915_load = false;
/* For initial average collection */
static const int IPS_SAMPLE_PERIOD = 200; /* ms */
@@ -339,6 +341,9 @@ struct ips_driver {
u64 orig_turbo_ratios;
};
+static bool
+ips_gpu_turbo_enabled(struct ips_driver *ips);
+
/**
* ips_cpu_busy - is CPU busy?
* @ips: IPS driver struct
@@ -517,7 +522,7 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips)
*/
static bool ips_gpu_busy(struct ips_driver *ips)
{
- if (!ips->gpu_turbo_enabled)
+ if (!ips_gpu_turbo_enabled(ips))
return false;
return ips->gpu_busy();
@@ -532,7 +537,7 @@ static bool ips_gpu_busy(struct ips_driver *ips)
*/
static void ips_gpu_raise(struct ips_driver *ips)
{
- if (!ips->gpu_turbo_enabled)
+ if (!ips_gpu_turbo_enabled(ips))
return;
if (!ips->gpu_raise())
@@ -549,7 +554,7 @@ static void ips_gpu_raise(struct ips_driver *ips)
*/
static void ips_gpu_lower(struct ips_driver *ips)
{
- if (!ips->gpu_turbo_enabled)
+ if (!ips_gpu_turbo_enabled(ips))
return;
if (!ips->gpu_lower())
@@ -1454,6 +1459,31 @@ out_err:
return false;
}
+static bool
+ips_gpu_turbo_enabled(struct ips_driver *ips)
+{
+ if (!ips->gpu_busy && late_i915_load) {
+ if (ips_get_i915_syms(ips)) {
+ dev_info(&ips->dev->dev,
+ "i915 driver attached, reenabling gpu turbo\n");
+ ips->gpu_turbo_enabled = !(thm_readl(THM_HTS) & HTS_GTD_DIS);
+ }
+ }
+
+ return ips->gpu_turbo_enabled;
+}
+
+void
+ips_link_to_i915_driver()
+{
+ /* We can't cleanly get at the various ips_driver structs from
+ * this caller (the i915 driver), so just set a flag saying
+ * that it's time to try getting the symbols again.
+ */
+ late_i915_load = true;
+}
+EXPORT_SYMBOL_GPL(ips_link_to_i915_driver);
+
static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), },
diff --git a/drivers/platform/x86/intel_ips.h b/drivers/platform/x86/intel_ips.h
new file mode 100644
index 0000000..73299be
--- /dev/null
+++ b/drivers/platform/x86/intel_ips.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+void ips_link_to_i915_driver(void);
--
1.6.6.1

View File

@@ -0,0 +1,69 @@
From 4d3024428f5c3ef5295e6f6fb257ae118b3f93a1 Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue, 14 Dec 2010 19:21:29 +0000
Subject: [PATCH 09/66] drm/i915: Verify Ironlake eDP presence on DP_A using the capability fuse
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_reg.h | 7 +++++++
drivers/gpu/drm/i915/intel_display.c | 19 ++++++++++++++++++-
2 files changed, 25 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8470a97..cb8f434 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2591,6 +2591,13 @@
#define ILK_DISPLAY_CHICKEN2 0x42004
#define ILK_DPARB_GATE (1<<22)
#define ILK_VSDPFD_FULL (1<<21)
+#define ILK_DISPLAY_CHICKEN_FUSES 0x42014
+#define ILK_INTERNAL_GRAPHICS_DISABLE (1<<31)
+#define ILK_INTERNAL_DISPLAY_DISABLE (1<<30)
+#define ILK_DISPLAY_DEBUG_DISABLE (1<<29)
+#define ILK_HDCP_DISABLE (1<<25)
+#define ILK_eDP_A_DISABLE (1<<24)
+#define ILK_DESKTOP (1<<23)
#define ILK_DSPCLK_GATE 0x42020
#define ILK_DPARB_CLK_GATE (1<<5)
/* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 97e374e..fca5232 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5379,6 +5379,23 @@ static int intel_encoder_clones(struct drm_device *dev, int type_mask)
return index_mask;
}
+static bool has_edp_a(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (!IS_MOBILE(dev))
+ return false;
+
+ if ((I915_READ(DP_A) & DP_DETECTED) == 0)
+ return false;
+
+ if (IS_GEN5(dev) &&
+ (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
+ return false;
+
+ return true;
+}
+
static void intel_setup_outputs(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5396,7 +5413,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev)) {
dpd_is_edp = intel_dpd_is_edp(dev);
- if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
+ if (has_edp_a(dev))
intel_dp_init(dev, DP_A);
if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
--
1.6.6.1

View File

@@ -0,0 +1,42 @@
From 537de3a67c0c86586eacffde40673b727242dc3a Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Wed, 22 Dec 2010 04:52:05 +0100
Subject: [PATCH 10/66] ARM: 6536/1: Add missing SZ_{32,64,128}
... and also remove misleading comment stating that this header is
auto-generated.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Uwe Kleine-Knig <u.kleine-koenig@pengutronix.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/include/asm/sizes.h | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h
index 4fc1565..316bb2b 100644
--- a/arch/arm/include/asm/sizes.h
+++ b/arch/arm/include/asm/sizes.h
@@ -13,9 +13,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* DO NOT EDIT!! - this file automatically generated
- * from .s file by awk -f s2h.awk
- */
/* Size definitions
* Copyright (C) ARM Limited 1998. All rights reserved.
*/
@@ -25,6 +22,9 @@
/* handy sizes */
#define SZ_16 0x00000010
+#define SZ_32 0x00000020
+#define SZ_64 0x00000040
+#define SZ_128 0x00000080
#define SZ_256 0x00000100
#define SZ_512 0x00000200
--
1.6.6.1

View File

@@ -0,0 +1,65 @@
From 875728807ff001b67a1e0535de5ad2cd3c41d47c Mon Sep 17 00:00:00 2001
From: Linus Walleij <linus.walleij@stericsson.com>
Date: Wed, 22 Dec 2010 09:18:29 +0100
Subject: [PATCH 11/66] ARM: 6537/1: update Nomadik, U300 and Ux500 maintainers
Adding in self as maintainer for Nomadik and Ux500, I'm running
an active -next tree for that stuff now. Extend file matchers to
cover a few more relevant drivers and add git references.
Cc: Alessandro Rubini <rubini@unipv.it>
Acked-by: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
MAINTAINERS | 17 ++++++++++++++++-
1 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6a58887..4323f8f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -792,11 +792,14 @@ S: Maintained
ARM/NOMADIK ARCHITECTURE
M: Alessandro Rubini <rubini@unipv.it>
+M: Linus Walleij <linus.walleij@stericsson.com>
M: STEricsson <STEricsson_nomadik_linux@list.st.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-nomadik/
F: arch/arm/plat-nomadik/
+F: drivers/i2c/busses/i2c-nomadik.c
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
M: Nelson Castillo <arhuaco@freaks-unidos.net>
@@ -998,12 +1001,24 @@ F: drivers/i2c/busses/i2c-stu300.c
F: drivers/rtc/rtc-coh901331.c
F: drivers/watchdog/coh901327_wdt.c
F: drivers/dma/coh901318*
+F: drivers/mfd/ab3100*
+F: drivers/rtc/rtc-ab3100.c
+F: drivers/rtc/rtc-coh901331.c
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
-ARM/U8500 ARM ARCHITECTURE
+ARM/Ux500 ARM ARCHITECTURE
M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
+M: Linus Walleij <linus.walleij@stericsson.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-ux500/
+F: drivers/dma/ste_dma40*
+F: drivers/mfd/ab3550*
+F: drivers/mfd/abx500*
+F: drivers/mfd/ab8500*
+F: drivers/mfd/stmpe*
+F: drivers/rtc/rtc-ab8500.c
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
ARM/VFP SUPPORT
M: Russell King <linux@arm.linux.org.uk>
--
1.6.6.1

View File

@@ -0,0 +1,44 @@
From d13e5edd7284bedcf5952e1b6490e39ad843cb91 Mon Sep 17 00:00:00 2001
From: Todd Android Poynor <toddpoynor@google.com>
Date: Thu, 23 Dec 2010 01:52:44 +0100
Subject: [PATCH 12/66] ARM: 6540/1: Stop irqsoff trace on return to user
If the irqsoff tracer is in use, stop tracing the interrupt disable
interval when returning to userspace. Tracing userspace execution time
as interrupts disabled time is not helpful for kernel performance
analysis purposes. Only do so if the irqsoff tracer is enabled, to
avoid overhead for lockdep, which doesn't care.
Signed-off-by: Todd Poynor <toddpoynor@google.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/kernel/entry-common.S | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 8bfa987..80bf8cd 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -29,6 +29,9 @@ ret_fast_syscall:
ldr r1, [tsk, #TI_FLAGS]
tst r1, #_TIF_WORK_MASK
bne fast_work_pending
+#if defined(CONFIG_IRQSOFF_TRACER)
+ asm_trace_hardirqs_on
+#endif
/* perform architecture specific actions before user return */
arch_ret_to_user r1, lr
@@ -65,6 +68,9 @@ ret_slow_syscall:
tst r1, #_TIF_WORK_MASK
bne work_pending
no_work_pending:
+#if defined(CONFIG_IRQSOFF_TRACER)
+ asm_trace_hardirqs_on
+#endif
/* perform architecture specific actions before user return */
arch_ret_to_user r1, lr
--
1.6.6.1

View File

@@ -0,0 +1,100 @@
From 12f188f2e59394ec1f1c8c0a4439f48ec16bc336 Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Sun, 19 Dec 2010 08:17:50 +0000
Subject: [PATCH 13/66] ueagle-atm: fix PHY signal initialization race
A race exists when initializing ueagle-atm devices where the generic atm
device may not yet be created before the driver attempts to initialize
it's PHY signal state, which checks whether the atm device has been
created or not. This often causes the sysfs 'carrier' attribute to be
'1' even though no signal has actually been found.
uea_probe
usbatm_usb_probe
driver->bind (uea_bind)
uea_boot
kthread_run(uea_kthread) uea_kthread
usbatm_atm_init uea_start_reset
atm_dev_register UPDATE_ATM_SIGNAL
UPDATE_ATM_SIGNAL checks whether the ATM device has been created and if
not, will not update the PHY signal state. Because of the race that
does not always happen in time, and the PHY signal state remains
ATM_PHY_SIG_FOUND even though no signal exists.
To fix the race, just create the kthread during initialization, and only
after initialization is complete, start the thread that reboots the
device and initializes PHY state.
[ 3030.490931] uea_probe: calling usbatm_usb_probe
[ 3030.490946] ueagle-atm 8-2:1.0: usbatm_usb_probe: trying driver ueagle-atm with vendor=1110, product=9031, ifnum 0
[ 3030.493691] uea_bind: setting usbatm
[ 3030.496932] usb 8-2: [ueagle-atm] using iso mode
[ 3030.497283] ueagle-atm 8-2:1.0: usbatm_usb_probe: using 3021 byte buffer for rx channel 0xffff880125953508
<kthread already started before usbatm_usb_probe() has returned>
[ 3030.497292] usb 8-2: [ueagle-atm] (re)booting started
<UPDATE_ATM_SIGNAL checks whether ATM device has been created yet before setting PHY state>
[ 3030.497298] uea_start_reset: atm dev (null)
<and since it hasn't been created yet PHY state is not set>
[ 3030.497306] ueagle-atm 8-2:1.0: usbatm_usb_probe: using 3392 byte buffer for tx channel 0xffff8801259535b8
[ 3030.497374] usbatm_usb_probe: about to init
[ 3030.497379] usbatm_usb_probe: calling usbatm_atm_init
<atm device finally gets created>
[ 3030.497384] usbatm_atm_init: creating atm device!
Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/usb/atm/ueagle-atm.c | 22 +++++++++++++++++++---
1 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 44447f5..99ac70e 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -2206,8 +2206,11 @@ static int uea_boot(struct uea_softc *sc)
goto err1;
}
- sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
- if (sc->kthread == ERR_PTR(-ENOMEM)) {
+ /* Create worker thread, but don't start it here. Start it after
+ * all usbatm generic initialization is done.
+ */
+ sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm");
+ if (IS_ERR(sc->kthread)) {
uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
goto err2;
}
@@ -2624,6 +2627,7 @@ static struct usbatm_driver uea_usbatm_driver = {
static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *usb = interface_to_usbdev(intf);
+ int ret;
uea_enters(usb);
uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n",
@@ -2637,7 +2641,19 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (UEA_IS_PREFIRM(id))
return uea_load_firmware(usb, UEA_CHIP_VERSION(id));
- return usbatm_usb_probe(intf, id, &uea_usbatm_driver);
+ ret = usbatm_usb_probe(intf, id, &uea_usbatm_driver);
+ if (ret == 0) {
+ struct usbatm_data *usbatm = usb_get_intfdata(intf);
+ struct uea_softc *sc = usbatm->driver_data;
+
+ /* Ensure carrier is initialized to off as early as possible */
+ UPDATE_ATM_SIGNAL(ATM_PHY_SIG_LOST);
+
+ /* Only start the worker thread when all init is done */
+ wake_up_process(sc->kthread);
+ }
+
+ return ret;
}
static void uea_disconnect(struct usb_interface *intf)
--
1.6.6.1

View File

@@ -0,0 +1,34 @@
From c4711786986af0cce654f493426ee0a1055e4b17 Mon Sep 17 00:00:00 2001
From: Breno Leitao <leitao@linux.vnet.ibm.com>
Date: Mon, 20 Dec 2010 09:02:37 +0000
Subject: [PATCH 14/66] ehea: Avoid changing vlan flags
This patch avoids disabling the vlan flags using ethtool.
Signed-off-by: Breno Leitao <leitao@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ehea/ehea_ethtool.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c
index 1f37ee6..d6cf502 100644
--- a/drivers/net/ehea/ehea_ethtool.c
+++ b/drivers/net/ehea/ehea_ethtool.c
@@ -263,6 +263,13 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
static int ehea_set_flags(struct net_device *dev, u32 data)
{
+ /* Avoid changing the VLAN flags */
+ if ((data & (ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN)) !=
+ (ethtool_op_get_flags(dev) & (ETH_FLAG_RXVLAN |
+ ETH_FLAG_TXVLAN))){
+ return -EINVAL;
+ }
+
return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO
| ETH_FLAG_TXVLAN
| ETH_FLAG_RXVLAN);
--
1.6.6.1

View File

@@ -0,0 +1,64 @@
From d39cd5e99a0ad88aba6793fb5e5f34e29cda6e6f Mon Sep 17 00:00:00 2001
From: stephen hemminger <shemminger@vyatta.com>
Date: Mon, 20 Dec 2010 17:58:33 +0000
Subject: [PATCH 15/66] ppp: allow disabling multilink protocol ID compression
Linux would not connect to other router running old version Cisco IOS (12.0).
This is most likely a bug in that version of IOS, since it is fixed
in later versions. As a workaround this patch allows a module parameter
to be set to disable compressing the protocol ID.
See: https://bugzilla.vyatta.com/show_bug.cgi?id=3979
RFC 1990 allows an implementation to formulate MP fragments as if protocol
compression had been negotiated. This allows us to always send compressed
protocol IDs. But some implementations don't accept MP fragments with
compressed protocol IDs. This parameter allows us to interoperate with
them. The default value of the configurable parameter is the same as the
current behavior: protocol compression is enabled. If protocol compression
is disabled we will not send compressed protocol IDs.
This is based on an earlier patch by Bob Gilligan (using a sysctl).
Module parameter is writable to allow for enabling even if ppp
is already loaded for other uses.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ppp_generic.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 3965997..89294b4 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1285,6 +1285,11 @@ ppp_push(struct ppp *ppp)
}
#ifdef CONFIG_PPP_MULTILINK
+static bool mp_protocol_compress __read_mostly = true;
+module_param(mp_protocol_compress, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(mp_protocol_compress,
+ "compress protocol id in multilink fragments");
+
/*
* Divide a packet to be transmitted into fragments and
* send them out the individual links.
@@ -1347,10 +1352,10 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
if (nfree == 0 || nfree < navail / 2)
return 0; /* can't take now, leave it in xmit_pending */
- /* Do protocol field compression (XXX this should be optional) */
+ /* Do protocol field compression */
p = skb->data;
len = skb->len;
- if (*p == 0) {
+ if (*p == 0 && mp_protocol_compress) {
++p;
--len;
}
--
1.6.6.1

View File

@@ -0,0 +1,31 @@
From 4a5fc4e179d79c79ad87bfc12a2d7e9b2371e40c Mon Sep 17 00:00:00 2001
From: Dan Carpenter <error27@gmail.com>
Date: Thu, 23 Dec 2010 19:17:34 +0000
Subject: [PATCH 16/66] skfp: testing the wrong variable in skfp_driver_init()
The intent here was to test if the allocation failed but we tested
"SharedMemSize" instead of "SharedMemAddr" by mistake.
Signed-off-by: Dan Carpenter <error27@gmail.com>
Reviewed-by: Jiri Pirko <jpirko@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/skfp/skfddi.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 0a66fed..16c6265 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -412,7 +412,7 @@ static int skfp_driver_init(struct net_device *dev)
bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
bp->SharedMemSize,
&bp->SharedMemDMA);
- if (!bp->SharedMemSize) {
+ if (!bp->SharedMemAddr) {
printk("could not allocate mem for ");
printk("hardware module: %ld byte\n",
bp->SharedMemSize);
--
1.6.6.1

View File

@@ -0,0 +1,84 @@
From 7f984b55acb6530bf854bfcac13104228f3336c1 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 28 Dec 2010 21:08:57 +0100
Subject: [PATCH 17/66] ASoC: codecs: Add missing control_type initialization
Some codec drivers do not initialize the control_type field in their private
device struct, but still use it when calling snd_soc_codec_set_cache_io.
This patch fixes the issue by properly initializing it in the drivers probe
functions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: stable@kernel.org (for 2.6.37 only)
---
sound/soc/codecs/wm8940.c | 1 +
sound/soc/codecs/wm8955.c | 1 +
sound/soc/codecs/wm8960.c | 1 +
sound/soc/codecs/wm8971.c | 1 +
sound/soc/codecs/wm9081.c | 1 +
5 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 2cb16f8..23086e2 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -768,6 +768,7 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8940);
wm8940->control_data = i2c;
+ wm8940->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8940, &wm8940_dai, 1);
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 9cbab8e..a2ad91d 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -1003,6 +1003,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, wm8955);
+ wm8955->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8955, &wm8955_dai, 1);
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 21986c4..ff6ff2f 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1013,6 +1013,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, wm8960);
+ wm8960->control_type = SND_SOC_I2C;
wm8960->control_data = i2c;
ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 63f6dbf..9f18db6 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -718,6 +718,7 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
if (wm8971 == NULL)
return -ENOMEM;
+ wm8971->control_type = SND_SOC_I2C;
i2c_set_clientdata(i2c, wm8971);
ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index ecc7c37..a486670 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1335,6 +1335,7 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, wm9081);
+ wm9081->control_type = SND_SOC_I2C;
wm9081->control_data = i2c;
ret = snd_soc_register_codec(&i2c->dev,
--
1.6.6.1

View File

@@ -0,0 +1,72 @@
From d24eb0db9c8a7ceecae860bdc636ed1e8a86943a Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 28 Dec 2010 21:37:56 +0100
Subject: [PATCH 18/66] ASoC: codecs: max98088: Fix register cache incoherency
The multi-component patch(commit f0fba2ad1) moved the allocation of the
register cache from the driver to the ASoC core. Most drivers where adjusted to
this, but the max98088 driver still uses its own register cache for its
private functions, while functions from the ASoC core use the generic cache.
Thus we end up with two from each other incoherent caches, which can lead to
undefined behaviour.
This patch fixes the issue by changing the max98088 driver to use the
generic register cache in its private functions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Peter Hsiang <Peter.Hsiang@maxim-ic.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: stable@kernel.org (for 2.6.37 only)
---
sound/soc/codecs/max98088.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index d63e287..6447dbb 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -40,7 +40,6 @@ struct max98088_cdata {
};
struct max98088_priv {
- u8 reg_cache[M98088_REG_CNT];
enum max98088_type devtype;
void *control_data;
struct max98088_pdata *pdata;
@@ -1588,7 +1587,7 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai,
static void max98088_sync_cache(struct snd_soc_codec *codec)
{
- struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = codec->reg_cache;
int i;
if (!codec->cache_sync)
@@ -1599,14 +1598,14 @@ static void max98088_sync_cache(struct snd_soc_codec *codec)
/* write back cached values if they're writeable and
* different from the hardware default.
*/
- for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) {
+ for (i = 1; i < codec->driver->reg_cache_size; i++) {
if (!max98088_access[i].writable)
continue;
- if (max98088->reg_cache[i] == max98088_reg[i])
+ if (reg_cache[i] == max98088_reg[i])
continue;
- snd_soc_write(codec, i, max98088->reg_cache[i]);
+ snd_soc_write(codec, i, reg_cache[i]);
}
codec->cache_sync = 0;
@@ -1951,7 +1950,6 @@ static int max98088_probe(struct snd_soc_codec *codec)
int ret = 0;
codec->cache_sync = 1;
- memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg));
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
if (ret != 0) {
--
1.6.6.1

View File

@@ -0,0 +1,74 @@
From beebca312009e9567d5e0229ea6b82bdf9a864cf Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 28 Dec 2010 21:37:57 +0100
Subject: [PATCH 19/66] ASoC: codecs: wm8523: Fix register cache incoherency
The multi-component patch(commit f0fba2ad1) moved the allocation of the
register cache from the driver to the ASoC core. Most drivers where adjusted to
this, but the wm8523 driver still uses its own register cache for its
private functions, while functions from the ASoC core use the generic cache.
Thus we end up with two from each other incoherent caches, which can lead to
undefined behaviour.
This patch fixes the issue by changing the wm8523 driver to use the
generic register cache in its private functions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Ian Lartey <ian@opensource.wolfsonmicro.com>
Cc: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: stable@kernel.org (for 2.6.37 only)
---
sound/soc/codecs/wm8523.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 9a433a5..deca79e 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -41,7 +41,6 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
/* codec private data */
struct wm8523_priv {
enum snd_soc_control_type control_type;
- u16 reg_cache[WM8523_REGISTER_COUNT];
struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
unsigned int sysclk;
unsigned int rate_constraint_list[WM8523_NUM_RATES];
@@ -314,6 +313,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = codec->reg_cache;
int ret, i;
switch (level) {
@@ -344,7 +344,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
/* Sync back default/cached values */
for (i = WM8523_AIF_CTRL1;
i < WM8523_MAX_REGISTER; i++)
- snd_soc_write(codec, i, wm8523->reg_cache[i]);
+ snd_soc_write(codec, i, reg_cache[i]);
msleep(100);
@@ -414,6 +414,7 @@ static int wm8523_resume(struct snd_soc_codec *codec)
static int wm8523_probe(struct snd_soc_codec *codec)
{
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = codec->reg_cache;
int ret, i;
codec->hw_write = (hw_write_t)i2c_master_send;
@@ -470,8 +471,8 @@ static int wm8523_probe(struct snd_soc_codec *codec)
}
/* Change some default settings - latch VU and enable ZC */
- wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
- wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
+ reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
+ reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
--
1.6.6.1

View File

@@ -0,0 +1,61 @@
From 52ca353bc8597dcc1d6d7abc03eecc1b452d79c9 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 28 Dec 2010 21:37:58 +0100
Subject: [PATCH 20/66] ASoC: codecs: wm8741: Fix register cache incoherency
The multi-component patch(commit f0fba2ad1) moved the allocation of the
register cache from the driver to the ASoC core. Most drivers where adjusted to
this, but the wm8741 driver still uses its own register cache for its
private functions, while functions from the ASoC core use the generic cache.
Thus we end up with two from each other incoherent caches, which can lead to
undefined behaviour.
This patch fixes the issue by changing the wm8741 driver to use the
generic register cache in its private functions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Ian Lartey <ian@opensource.wolfsonmicro.com>
Cc: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: stable@kernel.org (for 2.6.37 only)
---
sound/soc/codecs/wm8741.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 90e31e9..aea60ef 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -41,7 +41,6 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {
/* codec private data */
struct wm8741_priv {
enum snd_soc_control_type control_type;
- u16 reg_cache[WM8741_REGISTER_COUNT];
struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
unsigned int sysclk;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
@@ -422,6 +421,7 @@ static int wm8741_resume(struct snd_soc_codec *codec)
static int wm8741_probe(struct snd_soc_codec *codec)
{
struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = codec->reg_cache;
int ret = 0;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
@@ -437,10 +437,10 @@ static int wm8741_probe(struct snd_soc_codec *codec)
}
/* Change some default settings - latch VU */
- wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
- wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
- wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
- wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
+ reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
+ reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
+ reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
+ reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
snd_soc_add_controls(codec, wm8741_snd_controls,
ARRAY_SIZE(wm8741_snd_controls));
--
1.6.6.1

View File

@@ -0,0 +1,131 @@
From f578a188e8b21be623b48bb0eb3a92174c2e5b82 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 28 Dec 2010 21:37:59 +0100
Subject: [PATCH 21/66] ASoC: codecs: wm8904: Fix register cache incoherency
The multi-component patch(commit f0fba2ad1) moved the allocation of the
register cache from the driver to the ASoC core. Most drivers where adjusted to
this, but the wm8904 driver still uses its own register cache for its
private functions, while functions from the ASoC core use the generic cache.
Thus we end up with two from each other incoherent caches, which can lead to
undefined behaviour.
This patch fixes the issue by changing the wm8904 driver to use the
generic register cache in its private functions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Ian Lartey <ian@opensource.wolfsonmicro.com>
Cc: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: stable@kernel.org (for 2.6.37 only)
---
sound/soc/codecs/wm8904.c | 37 ++++++++++++++++++-------------------
1 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 9001cc4..1ec12ef 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -50,8 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
/* codec private data */
struct wm8904_priv {
- u16 reg_cache[WM8904_MAX_REGISTER + 1];
-
enum wm8904_type devtype;
void *control_data;
@@ -2094,7 +2092,7 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
static void wm8904_sync_cache(struct snd_soc_codec *codec)
{
- struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = codec->reg_cache;
int i;
if (!codec->cache_sync)
@@ -2105,14 +2103,14 @@ static void wm8904_sync_cache(struct snd_soc_codec *codec)
/* Sync back cached values if they're different from the
* hardware default.
*/
- for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) {
+ for (i = 1; i < codec->driver->reg_cache_size; i++) {
if (!wm8904_access[i].writable)
continue;
- if (wm8904->reg_cache[i] == wm8904_reg[i])
+ if (reg_cache[i] == wm8904_reg[i])
continue;
- snd_soc_write(codec, i, wm8904->reg_cache[i]);
+ snd_soc_write(codec, i, reg_cache[i]);
}
codec->cache_sync = 0;
@@ -2371,6 +2369,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
{
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
struct wm8904_pdata *pdata = wm8904->pdata;
+ u16 *reg_cache = codec->reg_cache;
int ret, i;
codec->cache_sync = 1;
@@ -2437,19 +2436,19 @@ static int wm8904_probe(struct snd_soc_codec *codec)
}
/* Change some default settings - latch VU and enable ZC */
- wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
- wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
- wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
- wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
- wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
+ reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
+ reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
+ reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
+ reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
+ reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
WM8904_HPOUTLZC;
- wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
+ reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
WM8904_HPOUTRZC;
- wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
+ reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
WM8904_LINEOUTLZC;
- wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
+ reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
WM8904_LINEOUTRZC;
- wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
+ reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
/* Apply configuration from the platform data. */
if (wm8904->pdata) {
@@ -2457,23 +2456,23 @@ static int wm8904_probe(struct snd_soc_codec *codec)
if (!pdata->gpio_cfg[i])
continue;
- wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i]
+ reg_cache[WM8904_GPIO_CONTROL_1 + i]
= pdata->gpio_cfg[i] & 0xffff;
}
/* Zero is the default value for these anyway */
for (i = 0; i < WM8904_MIC_REGS; i++)
- wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
+ reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
= pdata->mic_cfg[i];
}
/* Set Class W by default - this will be managed by the Class
* G widget at runtime where bypass paths are available.
*/
- wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
+ reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
/* Use normal bias source */
- wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
+ reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
--
1.6.6.1

View File

@@ -0,0 +1,107 @@
From 715920d04c787ed718327da53cf51689e51ef3ce Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 28 Dec 2010 21:38:00 +0100
Subject: [PATCH 22/66] ASoC: codecs: wm8955: Fix register cache incoherency
The multi-component patch(commit f0fba2ad1) moved the allocation of the
register cache from the driver to the ASoC core. Most drivers where adjusted to
this, but the wm8955 driver still uses its own register cache for its
private functions, while functions from the ASoC core use the generic cache.
Thus we end up with two from each other incoherent caches, which can lead to
undefined behaviour.
This patch fixes the issue by changing the wm8955 driver to use the
generic register cache in its private functions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: stable@kernel.org (for 2.6.37 only)
---
sound/soc/codecs/wm8955.c | 30 +++++++++++++++---------------
1 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index a2ad91d..2ac35b0 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -42,8 +42,6 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
struct wm8955_priv {
enum snd_soc_control_type control_type;
- u16 reg_cache[WM8955_MAX_REGISTER + 1];
-
unsigned int mclk_rate;
int deemph;
@@ -768,6 +766,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = codec->reg_cache;
int ret, i;
switch (level) {
@@ -800,14 +799,14 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
/* Sync back cached values if they're
* different from the hardware default.
*/
- for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) {
+ for (i = 0; i < codec->driver->reg_cache_size; i++) {
if (i == WM8955_RESET)
continue;
- if (wm8955->reg_cache[i] == wm8955_reg[i])
+ if (reg_cache[i] == wm8955_reg[i])
continue;
- snd_soc_write(codec, i, wm8955->reg_cache[i]);
+ snd_soc_write(codec, i, reg_cache[i]);
}
/* Enable VREF and VMID */
@@ -902,6 +901,7 @@ static int wm8955_probe(struct snd_soc_codec *codec)
{
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
+ u16 *reg_cache = codec->reg_cache;
int ret, i;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
@@ -934,25 +934,25 @@ static int wm8955_probe(struct snd_soc_codec *codec)
}
/* Change some default settings - latch VU and enable ZC */
- wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
- wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
- wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
- wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
- wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
- wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
- wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
+ reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
+ reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
+ reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
+ reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
+ reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
+ reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
+ reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
/* Also enable adaptive bass boost by default */
- wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
+ reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
/* Set platform data values */
if (pdata) {
if (pdata->out2_speaker)
- wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2]
+ reg_cache[WM8955_ADDITIONAL_CONTROL_2]
|= WM8955_ROUT2INV;
if (pdata->monoin_diff)
- wm8955->reg_cache[WM8955_MONO_OUT_MIX_1]
+ reg_cache[WM8955_MONO_OUT_MIX_1]
|= WM8955_DMEN;
}
--
1.6.6.1

View File

@@ -0,0 +1,151 @@
From 7f87e30ef29951f4509a7f86acf00e1ba48af54a Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 28 Dec 2010 21:38:01 +0100
Subject: [PATCH 23/66] ASoC: codecs: wm8962: Fix register cache incoherency
The multi-component patch(commit f0fba2ad1) moved the allocation of the
register cache from the driver to the ASoC core. Most drivers where adjusted to
this, but the wm8962 driver still uses its own register cache for its
private functions, while functions from the ASoC core use the generic cache.
Thus we end up with two from each other incoherent caches, which can lead to
undefined behaviour.
This patch fixes the issue by changing the wm8962 driver to use the
generic register cache in its private functions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: stable@kernel.org (for 2.6.37 only)
---
sound/soc/codecs/wm8962.c | 45 ++++++++++++++++++++-------------------------
1 files changed, 20 insertions(+), 25 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 1304ca9..7c421cc 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -52,8 +52,6 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {
struct wm8962_priv {
struct snd_soc_codec *codec;
- u16 reg_cache[WM8962_MAX_REGISTER + 1];
-
int sysclk;
int sysclk_rate;
@@ -1991,8 +1989,7 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- u16 *reg_cache = wm8962->reg_cache;
+ u16 *reg_cache = codec->reg_cache;
int ret;
/* Apply the update (if any) */
@@ -2020,8 +2017,7 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- u16 *reg_cache = wm8962->reg_cache;
+ u16 *reg_cache = codec->reg_cache;
int ret;
/* Apply the update (if any) */
@@ -2329,8 +2325,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- u16 *reg_cache = wm8962->reg_cache;
+ u16 *reg_cache = codec->reg_cache;
int reg;
switch (w->shift) {
@@ -2719,7 +2714,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
static void wm8962_sync_cache(struct snd_soc_codec *codec)
{
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = codec->reg_cache;
int i;
if (!codec->cache_sync)
@@ -2732,13 +2727,13 @@ static void wm8962_sync_cache(struct snd_soc_codec *codec)
/* Sync back cached values if they're different from the
* hardware default.
*/
- for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+ for (i = 1; i < codec->driver->reg_cache_size; i++) {
if (i == WM8962_SOFTWARE_RESET)
continue;
- if (wm8962->reg_cache[i] == wm8962_reg[i])
+ if (reg_cache[i] == wm8962_reg[i])
continue;
- snd_soc_write(codec, i, wm8962->reg_cache[i]);
+ snd_soc_write(codec, i, reg_cache[i]);
}
codec->cache_sync = 0;
@@ -3406,12 +3401,11 @@ EXPORT_SYMBOL_GPL(wm8962_mic_detect);
#ifdef CONFIG_PM
static int wm8962_resume(struct snd_soc_codec *codec)
{
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int i;
/* Restore the registers */
- for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+ for (i = 1; i < codec->driver->reg_cache_size; i++) {
switch (i) {
case WM8962_SOFTWARE_RESET:
continue;
@@ -3705,6 +3699,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
dev);
+ u16 *reg_cache = codec->reg_cache;
int i, trigger, irq_pol;
wm8962->codec = codec;
@@ -3804,7 +3799,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
/* Put the speakers into mono mode? */
if (pdata->spk_mono)
- wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2]
+ reg_cache[WM8962_CLASS_D_CONTROL_2]
|= WM8962_SPK_MONO;
/* Micbias setup, detection enable and detection
@@ -3819,16 +3814,16 @@ static int wm8962_probe(struct snd_soc_codec *codec)
}
/* Latch volume update bits */
- wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
- wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
- wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
- wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;
- wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
- wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
- wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
- wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
- wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
- wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
+ reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
+ reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
+ reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
+ reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;
+ reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
+ reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
+ reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
+ reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
+ reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
+ reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
wm8962_add_widgets(codec);
--
1.6.6.1

View File

@@ -0,0 +1,75 @@
From da280f51d0b341282b4181eb3235f774b0446584 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 28 Dec 2010 21:38:02 +0100
Subject: [PATCH 24/66] ASoC: codecs: wm9090: Fix register cache incoherency
The multi-component patch(commit f0fba2ad1) moved the allocation of the
register cache from the driver to the ASoC core. Most drivers where adjusted to
this, but the wm9090 driver still uses its own register cache for its
private functions, while functions from the ASoC core use the generic cache.
Thus we end up with two from each other incoherent caches, which can lead to
undefined behaviour.
This patch fixes the issue by changing the wm9090 driver to use the
generic register cache in its private functions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: stable@kernel.org (for 2.6.37 only)
---
sound/soc/codecs/wm9090.c | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 99c046b..6e5f64f 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -141,7 +141,6 @@ static const u16 wm9090_reg_defaults[] = {
/* This struct is used to save the context */
struct wm9090_priv {
struct mutex mutex;
- u16 reg_cache[WM9090_MAX_REGISTER + 1];
struct wm9090_platform_data pdata;
void *control_data;
};
@@ -552,6 +551,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
static int wm9090_probe(struct snd_soc_codec *codec)
{
struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = codec->reg_cache;
int ret;
codec->control_data = wm9090->control_data;
@@ -576,22 +576,22 @@ static int wm9090_probe(struct snd_soc_codec *codec)
/* Configure some defaults; they will be written out when we
* bring the bias up.
*/
- wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
+ reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
| WM9090_IN1A_ZC;
- wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
+ reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
| WM9090_IN1B_ZC;
- wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
+ reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
| WM9090_IN2A_ZC;
- wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
+ reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
| WM9090_IN2B_ZC;
- wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
+ reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
- wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
+ reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
- wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
+ reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
- wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
+ reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
--
1.6.6.1

View File

@@ -0,0 +1,514 @@
From 776065e36de1d5eb9e33ff908352fef4050ab38d Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Tue, 28 Dec 2010 21:38:03 +0100
Subject: [PATCH 25/66] ASoC: codecs: wm8753: Fix register cache incoherency
The multi-component patch(commit f0fba2ad1) moved the allocation of the
register cache from the driver to the ASoC core. Most drivers where adjusted to
this, but the wm8753 driver still uses its own register cache for its
private functions, while functions from the ASoC core use the generic cache.
Furthermore the generic cache uses zero-based numbering while the wm8753 cache
uses one-based numbering.
Thus we end up with two from each other incoherent caches, which leads to undefined
behaviour and crashes.
This patch fixes the issue by changing the wm8753 driver to use the generic
register cache in its private functions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
sound/soc/codecs/wm8753.c | 226 +++++++++++++++++----------------------------
1 files changed, 83 insertions(+), 143 deletions(-)
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 8f679a1..87caae5 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -65,22 +65,22 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
* are using 2 wire for device control, so we cache them instead.
*/
static const u16 wm8753_reg[] = {
- 0x0008, 0x0000, 0x000a, 0x000a,
- 0x0033, 0x0000, 0x0007, 0x00ff,
- 0x00ff, 0x000f, 0x000f, 0x007b,
- 0x0000, 0x0032, 0x0000, 0x00c3,
- 0x00c3, 0x00c0, 0x0000, 0x0000,
+ 0x0000, 0x0008, 0x0000, 0x000a,
+ 0x000a, 0x0033, 0x0000, 0x0007,
+ 0x00ff, 0x00ff, 0x000f, 0x000f,
+ 0x007b, 0x0000, 0x0032, 0x0000,
+ 0x00c3, 0x00c3, 0x00c0, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0055,
- 0x0005, 0x0050, 0x0055, 0x0050,
- 0x0055, 0x0050, 0x0055, 0x0079,
- 0x0079, 0x0079, 0x0079, 0x0079,
0x0000, 0x0000, 0x0000, 0x0000,
- 0x0097, 0x0097, 0x0000, 0x0004,
- 0x0000, 0x0083, 0x0024, 0x01ba,
- 0x0000, 0x0083, 0x0024, 0x01ba,
- 0x0000, 0x0000, 0x0000
+ 0x0055, 0x0005, 0x0050, 0x0055,
+ 0x0050, 0x0055, 0x0050, 0x0055,
+ 0x0079, 0x0079, 0x0079, 0x0079,
+ 0x0079, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0097, 0x0097, 0x0000,
+ 0x0004, 0x0000, 0x0083, 0x0024,
+ 0x01ba, 0x0000, 0x0083, 0x0024,
+ 0x01ba, 0x0000, 0x0000, 0x0000
};
/* codec private data */
@@ -88,57 +88,10 @@ struct wm8753_priv {
enum snd_soc_control_type control_type;
unsigned int sysclk;
unsigned int pcmclk;
- u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
int dai_func;
};
-/*
- * read wm8753 register cache
- */
-static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u16 *cache = codec->reg_cache;
- if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
- return -1;
- return cache[reg - 1];
-}
-
-/*
- * write wm8753 register cache
- */
-static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
-{
- u16 *cache = codec->reg_cache;
- if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
- return;
- cache[reg - 1] = value;
-}
-
-/*
- * write to the WM8753 register space
- */
-static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 data[2];
-
- /* data is
- * D15..D9 WM8753 register offset
- * D8...D0 register data
- */
- data[0] = (reg << 1) | ((value >> 8) & 0x0001);
- data[1] = value & 0x00ff;
-
- wm8753_write_reg_cache(codec, reg, value);
- if (codec->hw_write(codec->control_data, data, 2) == 2)
- return 0;
- else
- return -EIO;
-}
-
-#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0)
+#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)
/*
* WM8753 Controls
@@ -218,7 +171,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+ int mode = snd_soc_read(codec, WM8753_IOCTL);
ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;
return 0;
@@ -228,7 +181,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+ int mode = snd_soc_read(codec, WM8753_IOCTL);
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
@@ -738,17 +691,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
if (pll_id == WM8753_PLL1) {
offset = 0;
enable = 0x10;
- reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef;
+ reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef;
} else {
offset = 4;
enable = 0x8;
- reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7;
+ reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7;
}
if (!freq_in || !freq_out) {
/* disable PLL */
- wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
- wm8753_write(codec, WM8753_CLOCK, reg);
+ snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
+ snd_soc_write(codec, WM8753_CLOCK, reg);
return 0;
} else {
u16 value = 0;
@@ -759,20 +712,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
/* set up N and K PLL divisor ratios */
/* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18);
- wm8753_write(codec, WM8753_PLL1CTL2 + offset, value);
+ snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value);
/* bits 8:0 = PLL_K[17:9] */
value = (pll_div.k & 0x03fe00) >> 9;
- wm8753_write(codec, WM8753_PLL1CTL3 + offset, value);
+ snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value);
/* bits 8:0 = PLL_K[8:0] */
value = pll_div.k & 0x0001ff;
- wm8753_write(codec, WM8753_PLL1CTL4 + offset, value);
+ snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value);
/* set PLL as input and enable */
- wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
+ snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
(pll_div.div2 << 3));
- wm8753_write(codec, WM8753_CLOCK, reg | enable);
+ snd_soc_write(codec, WM8753_CLOCK, reg | enable);
}
return 0;
}
@@ -879,7 +832,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec;
+ u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec;
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -901,7 +854,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
- wm8753_write(codec, WM8753_PCM, voice);
+ snd_soc_write(codec, WM8753_PCM, voice);
return 0;
}
@@ -922,8 +875,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
- u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;
- u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
+ u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3;
+ u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f;
/* bit size */
switch (params_format(params)) {
@@ -943,9 +896,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
/* sample rate */
if (params_rate(params) * 384 == wm8753->pcmclk)
srate |= 0x80;
- wm8753_write(codec, WM8753_SRATE1, srate);
+ snd_soc_write(codec, WM8753_SRATE1, srate);
- wm8753_write(codec, WM8753_PCM, voice);
+ snd_soc_write(codec, WM8753_PCM, voice);
return 0;
}
@@ -958,8 +911,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct snd_soc_codec *codec = codec_dai->codec;
u16 voice, ioctl;
- voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f;
- ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d;
+ voice = snd_soc_read(codec, WM8753_PCM) & 0x011f;
+ ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d;
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1013,8 +966,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
- wm8753_write(codec, WM8753_PCM, voice);
- wm8753_write(codec, WM8753_IOCTL, ioctl);
+ snd_soc_write(codec, WM8753_PCM, voice);
+ snd_soc_write(codec, WM8753_IOCTL, ioctl);
return 0;
}
@@ -1026,16 +979,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) {
case WM8753_PCMDIV:
- reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f;
- wm8753_write(codec, WM8753_CLOCK, reg | div);
+ reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f;
+ snd_soc_write(codec, WM8753_CLOCK, reg | div);
break;
case WM8753_BCLKDIV:
- reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7;
- wm8753_write(codec, WM8753_SRATE2, reg | div);
+ reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7;
+ snd_soc_write(codec, WM8753_SRATE2, reg | div);
break;
case WM8753_VXCLKDIV:
- reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f;
- wm8753_write(codec, WM8753_SRATE2, reg | div);
+ reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f;
+ snd_soc_write(codec, WM8753_SRATE2, reg | div);
break;
default:
return -EINVAL;
@@ -1050,7 +1003,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0;
+ u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0;
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -1072,7 +1025,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
- wm8753_write(codec, WM8753_HIFI, hifi);
+ snd_soc_write(codec, WM8753_HIFI, hifi);
return 0;
}
@@ -1085,8 +1038,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct snd_soc_codec *codec = codec_dai->codec;
u16 ioctl, hifi;
- hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f;
- ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae;
+ hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f;
+ ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae;
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1140,8 +1093,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
- wm8753_write(codec, WM8753_HIFI, hifi);
- wm8753_write(codec, WM8753_IOCTL, ioctl);
+ snd_soc_write(codec, WM8753_HIFI, hifi);
+ snd_soc_write(codec, WM8753_IOCTL, ioctl);
return 0;
}
@@ -1162,8 +1115,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
- u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
- u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3;
+ u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0;
+ u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3;
int coeff;
/* is digital filter coefficient valid ? */
@@ -1172,7 +1125,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
printk(KERN_ERR "wm8753 invalid MCLK or rate\n");
return coeff;
}
- wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
+ snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
coeff_div[coeff].usb);
/* bit size */
@@ -1190,7 +1143,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
break;
}
- wm8753_write(codec, WM8753_HIFI, hifi);
+ snd_soc_write(codec, WM8753_HIFI, hifi);
return 0;
}
@@ -1201,8 +1154,8 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 clock;
/* set clk source as pcmclk */
- clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
- wm8753_write(codec, WM8753_CLOCK, clock);
+ clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
+ snd_soc_write(codec, WM8753_CLOCK, clock);
if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
return -EINVAL;
@@ -1224,8 +1177,8 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 clock;
/* set clk source as pcmclk */
- clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
- wm8753_write(codec, WM8753_CLOCK, clock);
+ clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
+ snd_soc_write(codec, WM8753_CLOCK, clock);
if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
return -EINVAL;
@@ -1239,8 +1192,8 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 clock;
/* set clk source as mclk */
- clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
- wm8753_write(codec, WM8753_CLOCK, clock | 0x4);
+ clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
+ snd_soc_write(codec, WM8753_CLOCK, clock | 0x4);
if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
return -EINVAL;
@@ -1252,19 +1205,19 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int wm8753_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
+ u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
/* the digital mute covers the HiFi and Voice DAC's on the WM8753.
* make sure we check if they are not both active when we mute */
if (mute && wm8753->dai_func == 1) {
if (!codec->active)
- wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
+ snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
} else {
if (mute)
- wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
+ snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
else
- wm8753_write(codec, WM8753_DAC, mute_reg);
+ snd_soc_write(codec, WM8753_DAC, mute_reg);
}
return 0;
@@ -1273,23 +1226,23 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
static int wm8753_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e;
+ u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e;
switch (level) {
case SND_SOC_BIAS_ON:
/* set vmid to 50k and unmute dac */
- wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
+ snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
break;
case SND_SOC_BIAS_PREPARE:
/* set vmid to 5k for quick power up */
- wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
+ snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
break;
case SND_SOC_BIAS_STANDBY:
/* mute dac and set vmid to 500k, enable VREF */
- wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
+ snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
break;
case SND_SOC_BIAS_OFF:
- wm8753_write(codec, WM8753_PWR1, 0x0001);
+ snd_soc_write(codec, WM8753_PWR1, 0x0001);
break;
}
codec->bias_level = level;
@@ -1477,7 +1430,7 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
else
dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];
}
- wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func);
+ snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func);
}
static void wm8753_work(struct work_struct *work)
@@ -1495,22 +1448,19 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8753_resume(struct snd_soc_codec *codec)
{
+ u16 *reg_cache = codec->reg_cache;
int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
/* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) {
- if (i + 1 == WM8753_RESET)
+ for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
+ if (i == WM8753_RESET)
continue;
/* No point in writing hardware default values back */
- if (cache[i] == wm8753_reg[i])
+ if (reg_cache[i] == wm8753_reg[i])
continue;
- data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
+ snd_soc_write(codec, i, reg_cache[i]);
}
wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1548,7 +1498,7 @@ static int run_delayed_work(struct delayed_work *dwork)
static int wm8753_probe(struct snd_soc_codec *codec)
{
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
- int ret = 0, reg;
+ int ret;
INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
@@ -1573,26 +1523,16 @@ static int wm8753_probe(struct snd_soc_codec *codec)
msecs_to_jiffies(caps_charge));
/* set the update bits */
- reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
- wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
- reg = wm8753_read_reg_cache(codec, WM8753_RDAC);
- wm8753_write(codec, WM8753_RDAC, reg | 0x0100);
- reg = wm8753_read_reg_cache(codec, WM8753_LADC);
- wm8753_write(codec, WM8753_LADC, reg | 0x0100);
- reg = wm8753_read_reg_cache(codec, WM8753_RADC);
- wm8753_write(codec, WM8753_RADC, reg | 0x0100);
- reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V);
- wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100);
- reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
- wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
- reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
- wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
- reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
- wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
- reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
- wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
- reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
- wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
+ snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);
snd_soc_add_controls(codec, wm8753_snd_controls,
ARRAY_SIZE(wm8753_snd_controls));
--
1.6.6.1

View File

@@ -0,0 +1,35 @@
From 649497d1a3676020802ebba04a3d9bb31253adb5 Mon Sep 17 00:00:00 2001
From: Avi Kivity <avi@redhat.com>
Date: Tue, 28 Dec 2010 12:09:07 +0200
Subject: [PATCH 26/66] KVM: MMU: Fix incorrect direct gfn for unpaged mode shadow
We use the physical address instead of the base gfn for the four
PAE page directories we use in unpaged mode. When the guest accesses
an address above 1GB that is backed by a large host page, a BUG_ON()
in kvm_mmu_set_gfn() triggers.
Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=21962
Reported-and-tested-by: Nicolas Prochazka <prochazka.nicolas@gmail.com>
KVM-Stable-Tag.
Signed-off-by: Avi Kivity <avi@redhat.com>
---
arch/x86/kvm/mmu.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index fb8b376..fbb04ae 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2394,7 +2394,8 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
ASSERT(!VALID_PAGE(root));
spin_lock(&vcpu->kvm->mmu_lock);
kvm_mmu_free_some_pages(vcpu);
- sp = kvm_mmu_get_page(vcpu, i << 30, i << 30,
+ sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT),
+ i << 30,
PT32_ROOT_LEVEL, 1, ACC_ALL,
NULL);
root = __pa(sp->spt);
--
1.6.6.1

View File

@@ -0,0 +1,34 @@
From 4ef9e11d6867f88951e30db910fa015300e31871 Mon Sep 17 00:00:00 2001
From: Hillf Danton <dhillf@gmail.com>
Date: Wed, 29 Dec 2010 21:55:28 +0800
Subject: [PATCH 27/66] fix freeing user_struct in user cache
When racing on adding into user cache, the new allocated from mm slab
is freed without putting user namespace.
Since the user namespace is already operated by getting, putting has
to be issued.
Signed-off-by: Hillf Danton <dhillf@gmail.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
kernel/user.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/kernel/user.c b/kernel/user.c
index 2c7d8d5..5c598ca 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -158,6 +158,7 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)
spin_lock_irq(&uidhash_lock);
up = uid_hash_find(uid, hashent);
if (up) {
+ put_user_ns(ns);
key_put(new->uid_keyring);
key_put(new->session_keyring);
kmem_cache_free(uid_cachep, new);
--
1.6.6.1

View File

@@ -0,0 +1,111 @@
From 42ce7fd6319bed8ecb26d656c476365da46b29e9 Mon Sep 17 00:00:00 2001
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
Date: Wed, 29 Dec 2010 11:52:53 +0100
Subject: [PATCH 28/66] spi/omap2_mcspi.c: Force CS to be in inactive state after off-mode transition
When SPI wake up from OFF mode, CS is in the wrong state: force it to the
inactive state.
During the system life, I monitored the CS behavior using a oscilloscope.
I also activated debug in omap2_mcspi, so I saw when driver disable the clocks
and restore context when device is not used.Each time the CS was in the correct
state. It was only when system was put suspend to ram with off-mode activated
that on resume the CS was in wrong state( ie activated).
Changelog:
* Change from v1 to v2:
- Rebase on linus/master (after 2.6.37-rc1)
- Do some clean-up and fix indentation on both patches
- Add more explanations for patch 2
* Change from v2 to v3:
- Use directly resume function of spi_master instead of using function
- from spi_device as Grant Likely pointed it out.
- Force this transition explicitly for each CS used by a device.
* Change from v3 to v4:
- Patch clean-up according to Kevin Hilman and checkpatch.
- Now force CS to be in inactive state only if it was inactive when it was
suspended.
* Change from v4 to v5:
- Rebase on linus/master (after 2.6.37-rc3)
- Collapse some lines as pointed by Grant Likely
- Fix a spelling
* Change from v5 to v6:
- Rebase on linus/master (after 2.6.37-rc7)
- Use CONFIG_SUSPEND instead of CONFIG_PM
- Didn't use legacy PM methods anymore. Instead, add a struct dev_pm_ops and
add the resume method there.
- Fix multi-line comment style
* Change from v6 to v7:
- Rebase on linus/master (after 2.6.37-rc8)
- Drop an extra line
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Reviewed-by: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
drivers/spi/omap2_mcspi.c | 39 +++++++++++++++++++++++++++++++++++++++
1 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 2a651e6..951a160 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -1305,10 +1305,49 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:omap2_mcspi");
+#ifdef CONFIG_SUSPEND
+/*
+ * When SPI wake up from off-mode, CS is in activate state. If it was in
+ * unactive state when driver was suspend, then force it to unactive state at
+ * wake up.
+ */
+static int omap2_mcspi_resume(struct device *dev)
+{
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+ struct omap2_mcspi_cs *cs;
+
+ omap2_mcspi_enable_clocks(mcspi);
+ list_for_each_entry(cs, &omap2_mcspi_ctx[master->bus_num - 1].cs,
+ node) {
+ if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) {
+
+ /*
+ * We need to toggle CS state for OMAP take this
+ * change in account.
+ */
+ MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1);
+ __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+ MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0);
+ __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+ }
+ }
+ omap2_mcspi_disable_clocks(mcspi);
+ return 0;
+}
+#else
+#define omap2_mcspi_resume NULL
+#endif
+
+static const struct dev_pm_ops omap2_mcspi_pm_ops = {
+ .resume = omap2_mcspi_resume,
+};
+
static struct platform_driver omap2_mcspi_driver = {
.driver = {
.name = "omap2_mcspi",
.owner = THIS_MODULE,
+ .pm = &omap2_mcspi_pm_ops
},
.remove = __exit_p(omap2_mcspi_remove),
};
--
1.6.6.1

View File

@@ -0,0 +1,49 @@
From 7ad1227818f09242cfe9bf1845fd24211f5f99bd Mon Sep 17 00:00:00 2001
From: Jan Beulich <JBeulich@novell.com>
Date: Thu, 9 Dec 2010 08:11:38 +0000
Subject: [PATCH 29/66] kconfig: fix undesirable side effect of adding "visible" menu attribute
This lead to non-selected, non-user-selectable options to be written
out to .config. This is not only pointless, but also preventing the
user to be prompted should any of those options eventually become
visible (e.g. by de-selecting the *_AUTO options the "visible"
attribute was added for.
Furthermore it is quite logical for the "visible" attribute of a menu
to control the visibility of all contained prompts, which is what the
patch does.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Michal Marek <mmarek@suse.cz>
---
scripts/kconfig/menu.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index b9d9aa1..5f77dcb 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -140,6 +140,20 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
}
if (current_entry->prompt && current_entry != &rootmenu)
prop_warn(prop, "prompt redefined");
+
+ /* Apply all upper menus' visibilities to actual prompts. */
+ if(type == P_PROMPT) {
+ struct menu *menu = current_entry;
+
+ while ((menu = menu->parent) != NULL) {
+ if (!menu->visibility)
+ continue;
+ prop->visible.expr
+ = expr_alloc_and(prop->visible.expr,
+ menu->visibility);
+ }
+ }
+
current_entry->prompt = prop;
}
prop->text = prompt;
--
1.6.6.1

View File

@@ -0,0 +1,33 @@
From 0bc463426ab5eb39e76df637b29a4f191d01b8a0 Mon Sep 17 00:00:00 2001
From: Jate Sujjavanich <jsujjavanich@syntech-fuelmaster.com>
Date: Wed, 29 Sep 2010 09:44:32 -0400
Subject: [PATCH 30/66] spi/m68knommu: Coldfire QSPI platform support
After grabbing a msg from the msgq, the mcfqspi_work function calls
list_del_init on the mcfqspi->msgq which unintentionally deletes the rest
of the list before it can be processed. If qspi call was made using
spi_sync, this can result in a process hang.
Signed-off-by: Jate Sujjavanich <jsujjavanich@syntech-fuelmaster.com>
Acked-by: Steven King <sfking@fdwdc.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
drivers/spi/coldfire_qspi.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/spi/coldfire_qspi.c b/drivers/spi/coldfire_qspi.c
index 052b3c7..8856bcc 100644
--- a/drivers/spi/coldfire_qspi.c
+++ b/drivers/spi/coldfire_qspi.c
@@ -317,7 +317,7 @@ static void mcfqspi_work(struct work_struct *work)
msg = container_of(mcfqspi->msgq.next, struct spi_message,
queue);
- list_del_init(&mcfqspi->msgq);
+ list_del_init(&msg->queue);
spin_unlock_irqrestore(&mcfqspi->lock, flags);
spi = msg->spi;
--
1.6.6.1

View File

@@ -0,0 +1,47 @@
From d81a12bc29ae4038770e05dce4ab7f26fd5880fb Mon Sep 17 00:00:00 2001
From: Dan Rosenberg <drosenberg@vsecurity.com>
Date: Sat, 25 Dec 2010 16:23:40 -0500
Subject: [PATCH 31/66] sound: Prevent buffer overflow in OSS load_mixer_volumes
The load_mixer_volumes() function, which can be triggered by
unprivileged users via the SOUND_MIXER_SETLEVELS ioctl, is vulnerable to
a buffer overflow. Because the provided "name" argument isn't
guaranteed to be NULL terminated at the expected 32 bytes, it's possible
to overflow past the end of the last element in the mixer_vols array.
Further exploitation can result in an arbitrary kernel write (via
subsequent calls to load_mixer_volumes()) leading to privilege
escalation, or arbitrary kernel reads via get_mixer_levels(). In
addition, the strcmp() may leak bytes beyond the mixer_vols array.
Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/oss/soundcard.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 46c0d03..fcb14a0 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -87,7 +87,7 @@ int *load_mixer_volumes(char *name, int *levels, int present)
int i, n;
for (i = 0; i < num_mixer_volumes; i++) {
- if (strcmp(name, mixer_vols[i].name) == 0) {
+ if (strncmp(name, mixer_vols[i].name, 32) == 0) {
if (present)
mixer_vols[i].num = i;
return mixer_vols[i].levels;
@@ -99,7 +99,7 @@ int *load_mixer_volumes(char *name, int *levels, int present)
}
n = num_mixer_volumes++;
- strcpy(mixer_vols[n].name, name);
+ strncpy(mixer_vols[n].name, name, 32);
if (present)
mixer_vols[n].num = n;
--
1.6.6.1

View File

@@ -0,0 +1,32 @@
From e03fa055bc126e536c7f65862e08a9b143138ea9 Mon Sep 17 00:00:00 2001
From: Daniel T Chen <crimsun@ubuntu.com>
Date: Tue, 28 Dec 2010 17:20:02 -0500
Subject: [PATCH 32/66] ALSA: hda: Use LPIB quirk for Dell Inspiron m101z/1120
Sjoerd Simons reports that, without using position_fix=1, recording
experiences overruns. Work around that by applying the LPIB quirk
for his hardware.
Reported-and-tested-by: Sjoerd Simons <sjoerd@debian.org>
Cc: <stable@kernel.org>
Signed-off-by: Daniel T Chen <crimsun@ubuntu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/hda_intel.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index b030c8e..a1c4008 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2300,6 +2300,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
--
1.6.6.1

View File

@@ -0,0 +1,33 @@
From bcfbbce822d219eb587acaba8a6e062bbeae4761 Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris@chris-wilson.co.uk>
Date: Thu, 30 Dec 2010 09:07:15 +0000
Subject: [PATCH 33/66] Revert "drm/i915/bios: Reverse order of 100/120 Mhz SSC clocks"
As I feared, whilst this fixed the clocks for the Lenovo U160, it broke
many other machines. So lets reverts commit 448f53a1ede54eb854d036abf
and search for the real bug.
Reported-and-tested-by: Travis Hume <travis@computoring.org> [et al]
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25842
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=32698
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/intel_bios.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 2b20786..b0b1200 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -270,7 +270,7 @@ parse_general_features(struct drm_i915_private *dev_priv,
general->ssc_freq ? 66 : 48;
else if (IS_GEN5(dev) || IS_GEN6(dev))
dev_priv->lvds_ssc_freq =
- general->ssc_freq ? 120 : 100;
+ general->ssc_freq ? 100 : 120;
else
dev_priv->lvds_ssc_freq =
general->ssc_freq ? 100 : 96;
--
1.6.6.1

View File

@@ -0,0 +1,30 @@
From cc6455f82edd3f9da3b03870d41cde3cb22ad40d Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris@chris-wilson.co.uk>
Date: Thu, 30 Dec 2010 12:54:00 +0000
Subject: [PATCH 34/66] drm/i915/dvo: Report LVDS attached to ch701x as connected
As we have already detected something attached to the chip during
initialisation, always report the LVDS connector status as connected
during probing.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/dvo_ch7017.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
index af70337..d3e8c54 100644
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -242,7 +242,7 @@ fail:
static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo)
{
- return connector_status_unknown;
+ return connector_status_connected;
}
static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo,
--
1.6.6.1

View File

@@ -0,0 +1,402 @@
From b83be6f20a0e468f715b14225c9f897538dfe5ad Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch>
Date: Thu, 16 Dec 2010 12:04:54 +0100
Subject: [PATCH 35/66] update Documentation/filesystems/Locking
Mostly inspired by all the recent BKL removal changes, but a lot of older
updates also weren't properly recorded.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
Documentation/filesystems/Locking | 214 ++++++++++++++++++-------------------
1 files changed, 102 insertions(+), 112 deletions(-)
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index b6426f1..7686e76 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -18,7 +18,6 @@ prototypes:
char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
locking rules:
- none have BKL
dcache_lock rename_lock ->d_lock may block
d_revalidate: no no no yes
d_hash no no no yes
@@ -42,18 +41,23 @@ ata *);
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
int (*readlink) (struct dentry *, char __user *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
+ void * (*follow_link) (struct dentry *, struct nameidata *);
+ void (*put_link) (struct dentry *, struct nameidata *, void *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, struct nameidata *);
+ int (*check_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
+ void (*truncate_range)(struct inode *, loff_t, loff_t);
+ long (*fallocate)(struct inode *inode, int mode, loff_t offset, loff_t len);
+ int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
locking rules:
- all may block, none have BKL
+ all may block
i_mutex(inode)
lookup: yes
create: yes
@@ -66,19 +70,24 @@ rmdir: yes (both) (see below)
rename: yes (all) (see below)
readlink: no
follow_link: no
+put_link: no
truncate: yes (see below)
setattr: yes
permission: no
+check_acl: no
getattr: no
setxattr: yes
getxattr: no
listxattr: no
removexattr: yes
+truncate_range: yes
+fallocate: no
+fiemap: no
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim.
cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
->truncate() is never called directly - it's a callback, not a
-method. It's called by vmtruncate() - library function normally used by
+method. It's called by vmtruncate() - deprecated library function used by
->setattr(). Locking information above applies to that call (i.e. is
inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been
passed).
@@ -91,7 +100,7 @@ prototypes:
struct inode *(*alloc_inode)(struct super_block *sb);
void (*destroy_inode)(struct inode *);
void (*dirty_inode) (struct inode *);
- int (*write_inode) (struct inode *, int);
+ int (*write_inode) (struct inode *, struct writeback_control *wbc);
int (*drop_inode) (struct inode *);
void (*evict_inode) (struct inode *);
void (*put_super) (struct super_block *);
@@ -105,10 +114,11 @@ prototypes:
int (*show_options)(struct seq_file *, struct vfsmount *);
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+ int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+ int (*trim_fs) (struct super_block *, struct fstrim_range *);
locking rules:
All may block [not true, see below]
- None have BKL
s_umount
alloc_inode:
destroy_inode:
@@ -127,6 +137,8 @@ umount_begin: no
show_options: no (namespace_sem)
quota_read: no (see below)
quota_write: no (see below)
+bdev_try_to_free_page: no (see below)
+trim_fs: no
->statfs() has s_umount (shared) when called by ustat(2) (native or
compat), but that's an accident of bad API; s_umount is used to pin
@@ -139,19 +151,25 @@ be the only ones operating on the quota file by the quota code (via
dqio_sem) (unless an admin really wants to screw up something and
writes to quota files with quotas on). For other details about locking
see also dquot_operations section.
+->bdev_try_to_free_page is called from the ->releasepage handler of
+the block device inode. See there for more details.
--------------------------- file_system_type ---------------------------
prototypes:
int (*get_sb) (struct file_system_type *, int,
const char *, void *, struct vfsmount *);
+ struct dentry *(*mount) (struct file_system_type *, int,
+ const char *, void *);
void (*kill_sb) (struct super_block *);
locking rules:
- may block BKL
-get_sb yes no
-kill_sb yes no
+ may block
+get_sb yes
+mount yes
+kill_sb yes
->get_sb() returns error or 0 with locked superblock attached to the vfsmount
(exclusive on ->s_umount).
+->mount() returns ERR_PTR or the root dentry.
->kill_sb() takes a write-locked superblock, does all shutdown work on it,
unlocks and drops the reference.
@@ -176,27 +194,35 @@ prototypes:
void (*freepage)(struct page *);
int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
loff_t offset, unsigned long nr_segs);
- int (*launder_page) (struct page *);
+ int (*get_xip_mem)(struct address_space *, pgoff_t, int, void **,
+ unsigned long *);
+ int (*migratepage)(struct address_space *, struct page *, struct page *);
+ int (*launder_page)(struct page *);
+ int (*is_partially_uptodate)(struct page *, read_descriptor_t *, unsigned long);
+ int (*error_remove_page)(struct address_space *, struct page *);
locking rules:
All except set_page_dirty and freepage may block
- BKL PageLocked(page) i_mutex
-writepage: no yes, unlocks (see below)
-readpage: no yes, unlocks
-sync_page: no maybe
-writepages: no
-set_page_dirty no no
-readpages: no
-write_begin: no locks the page yes
-write_end: no yes, unlocks yes
-perform_write: no n/a yes
-bmap: no
-invalidatepage: no yes
-releasepage: no yes
-freepage: no yes
-direct_IO: no
-launder_page: no yes
+ PageLocked(page) i_mutex
+writepage: yes, unlocks (see below)
+readpage: yes, unlocks
+sync_page: maybe
+writepages:
+set_page_dirty no
+readpages:
+write_begin: locks the page yes
+write_end: yes, unlocks yes
+bmap:
+invalidatepage: yes
+releasepage: yes
+freepage: yes
+direct_IO:
+get_xip_mem: maybe
+migratepage: yes (both)
+launder_page: yes
+is_partially_uptodate: yes
+error_remove_page: yes
->write_begin(), ->write_end(), ->sync_page() and ->readpage()
may be called from the request handler (/dev/loop).
@@ -276,9 +302,8 @@ under spinlock (it cannot block) and is sometimes called with the page
not locked.
->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some
-filesystems and by the swapper. The latter will eventually go away. All
-instances do not actually need the BKL. Please, keep it that way and don't
-breed new callers.
+filesystems and by the swapper. The latter will eventually go away. Please,
+keep it that way and don't breed new callers.
->invalidatepage() is called when the filesystem must attempt to drop
some or all of the buffers from the page when it is being truncated. It
@@ -299,47 +324,37 @@ cleaned, or an error value if not. Note that in order to prevent the page
getting mapped back in and redirtied, it needs to be kept locked
across the entire operation.
- Note: currently almost all instances of address_space methods are
-using BKL for internal serialization and that's one of the worst sources
-of contention. Normally they are calling library functions (in fs/buffer.c)
-and pass foo_get_block() as a callback (on local block-based filesystems,
-indeed). BKL is not needed for library stuff and is usually taken by
-foo_get_block(). It's an overkill, since block bitmaps can be protected by
-internal fs locking and real critical areas are much smaller than the areas
-filesystems protect now.
-
----------------------- file_lock_operations ------------------------------
prototypes:
- void (*fl_insert)(struct file_lock *); /* lock insertion callback */
- void (*fl_remove)(struct file_lock *); /* lock removal callback */
void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
void (*fl_release_private)(struct file_lock *);
locking rules:
- BKL may block
-fl_insert: yes no
-fl_remove: yes no
-fl_copy_lock: yes no
-fl_release_private: yes yes
+ file_lock_lock may block
+fl_copy_lock: yes no
+fl_release_private: maybe no
----------------------- lock_manager_operations ---------------------------
prototypes:
int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
void (*fl_notify)(struct file_lock *); /* unblock callback */
+ int (*fl_grant)(struct file_lock *, struct file_lock *, int);
void (*fl_release_private)(struct file_lock *);
void (*fl_break)(struct file_lock *); /* break_lease callback */
+ int (*fl_mylease)(struct file_lock *, struct file_lock *);
+ int (*fl_change)(struct file_lock **, int);
locking rules:
- BKL may block
-fl_compare_owner: yes no
-fl_notify: yes no
-fl_release_private: yes yes
-fl_break: yes no
-
- Currently only NFSD and NLM provide instances of this class. None of the
-them block. If you have out-of-tree instances - please, show up. Locking
-in that area will change.
+ file_lock_lock may block
+fl_compare_owner: yes no
+fl_notify: yes no
+fl_grant: no no
+fl_release_private: maybe no
+fl_break: yes no
+fl_mylease: yes no
+fl_change yes no
+
--------------------------- buffer_head -----------------------------------
prototypes:
void (*b_end_io)(struct buffer_head *bh, int uptodate);
@@ -364,17 +379,17 @@ prototypes:
void (*swap_slot_free_notify) (struct block_device *, unsigned long);
locking rules:
- BKL bd_mutex
-open: no yes
-release: no yes
-ioctl: no no
-compat_ioctl: no no
-direct_access: no no
-media_changed: no no
-unlock_native_capacity: no no
-revalidate_disk: no no
-getgeo: no no
-swap_slot_free_notify: no no (see below)
+ bd_mutex
+open: yes
+release: yes
+ioctl: no
+compat_ioctl: no
+direct_access: no
+media_changed: no
+unlock_native_capacity: no
+revalidate_disk: no
+getgeo: no
+swap_slot_free_notify: no (see below)
media_changed, unlock_native_capacity and revalidate_disk are called only from
check_disk_change().
@@ -413,34 +428,21 @@ prototypes:
unsigned long (*get_unmapped_area)(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
+ int (*flock) (struct file *, int, struct file_lock *);
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *,
+ size_t, unsigned int);
+ ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,
+ size_t, unsigned int);
+ int (*setlease)(struct file *, long, struct file_lock **);
};
locking rules:
- All may block.
- BKL
-llseek: no (see below)
-read: no
-aio_read: no
-write: no
-aio_write: no
-readdir: no
-poll: no
-unlocked_ioctl: no
-compat_ioctl: no
-mmap: no
-open: no
-flush: no
-release: no
-fsync: no (see below)
-aio_fsync: no
-fasync: no
-lock: yes
-readv: no
-writev: no
-sendfile: no
-sendpage: no
-get_unmapped_area: no
-check_flags: no
+ All may block except for ->setlease.
+ No VFS locks held on entry except for ->fsync and ->setlease.
+
+->fsync() has i_mutex on inode.
+
+->setlease has the file_list_lock held and must not sleep.
->llseek() locking has moved from llseek to the individual llseek
implementations. If your fs is not using generic_file_llseek, you
@@ -450,17 +452,10 @@ mutex or just to use i_size_read() instead.
Note: this does not protect the file->f_pos against concurrent modifications
since this is something the userspace has to take care about.
-Note: ext2_release() was *the* source of contention on fs-intensive
-loads and dropping BKL on ->release() helps to get rid of that (we still
-grab BKL for cases when we close a file that had been opened r/w, but that
-can and should be done using the internal locking with smaller critical areas).
-Current worst offender is ext2_get_block()...
-
-->fasync() is called without BKL protection, and is responsible for
-maintaining the FASYNC bit in filp->f_flags. Most instances call
-fasync_helper(), which does that maintenance, so it's not normally
-something one needs to worry about. Return values > 0 will be mapped to
-zero in the VFS layer.
+->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags.
+Most instances call fasync_helper(), which does that maintenance, so it's
+not normally something one needs to worry about. Return values > 0 will be
+mapped to zero in the VFS layer.
->readdir() and ->ioctl() on directories must be changed. Ideally we would
move ->readdir() to inode_operations and use a separate method for directory
@@ -471,8 +466,6 @@ components. And there are other reasons why the current interface is a mess...
->read on directories probably must go away - we should just enforce -EISDIR
in sys_read() and friends.
-->fsync() has i_mutex on inode.
-
--------------------------- dquot_operations -------------------------------
prototypes:
int (*write_dquot) (struct dquot *);
@@ -507,12 +500,12 @@ prototypes:
int (*access)(struct vm_area_struct *, unsigned long, void*, int, int);
locking rules:
- BKL mmap_sem PageLocked(page)
-open: no yes
-close: no yes
-fault: no yes can return with page locked
-page_mkwrite: no yes can return with page locked
-access: no yes
+ mmap_sem PageLocked(page)
+open: yes
+close: yes
+fault: yes can return with page locked
+page_mkwrite: yes can return with page locked
+access: yes
->fault() is called when a previously not present pte is about
to be faulted in. The filesystem must find and return the page associated
@@ -539,6 +532,3 @@ VM_IO | VM_PFNMAP VMAs.
(if you break something or notice that it is broken and do not fix it yourself
- at least put it here)
-
-ipc/shm.c::shm_delete() - may need BKL.
-->read() and ->write() in many drivers are (probably) missing BKL.
--
1.6.6.1

View File

@@ -0,0 +1,63 @@
From ebb76ce16daf6908dc030dec1c00827d37129fe5 Mon Sep 17 00:00:00 2001
From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Date: Wed, 29 Dec 2010 14:07:11 -0800
Subject: [PATCH 36/66] memcg: fix wrong VM_BUG_ON() in try_charge()'s mm->owner check
At __mem_cgroup_try_charge(), VM_BUG_ON(!mm->owner) is checked.
But as commented in mem_cgroup_from_task(), mm->owner can be NULL
in some racy case. This check of VM_BUG_ON() is bad.
A possible story to hit this is at swapoff()->try_to_unuse(). It passes
mm_struct to mem_cgroup_try_charge_swapin() while mm->owner is NULL. If we
can't get proper mem_cgroup from swap_cgroup information, mm->owner is used
as charge target and we see NULL.
Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Reported-by: Hugh Dickins <hughd@google.com>
Reported-by: Thomas Meyer <thomas@m3y3r.de>
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Reviewed-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
mm/memcontrol.c | 19 +++++++++----------
1 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 7a22b41..00bb8a6 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1925,19 +1925,18 @@ again:
rcu_read_lock();
p = rcu_dereference(mm->owner);
- VM_BUG_ON(!p);
/*
- * because we don't have task_lock(), "p" can exit while
- * we're here. In that case, "mem" can point to root
- * cgroup but never be NULL. (and task_struct itself is freed
- * by RCU, cgroup itself is RCU safe.) Then, we have small
- * risk here to get wrong cgroup. But such kind of mis-account
- * by race always happens because we don't have cgroup_mutex().
- * It's overkill and we allow that small race, here.
+ * Because we don't have task_lock(), "p" can exit.
+ * In that case, "mem" can point to root or p can be NULL with
+ * race with swapoff. Then, we have small risk of mis-accouning.
+ * But such kind of mis-account by race always happens because
+ * we don't have cgroup_mutex(). It's overkill and we allo that
+ * small race, here.
+ * (*) swapoff at el will charge against mm-struct not against
+ * task-struct. So, mm->owner can be NULL.
*/
mem = mem_cgroup_from_task(p);
- VM_BUG_ON(!mem);
- if (mem_cgroup_is_root(mem)) {
+ if (!mem || mem_cgroup_is_root(mem)) {
rcu_read_unlock();
goto done;
}
--
1.6.6.1

View File

@@ -0,0 +1,54 @@
From e983dc2428164698571e1dd1b25c4322181adbac Mon Sep 17 00:00:00 2001
From: Nitin Gupta <ngupta@vflare.org>
Date: Thu, 30 Dec 2010 04:07:58 -0500
Subject: [PATCH 37/66] Revert "Staging: zram: work around oops due to startup ordering snafu"
This reverts commit 7e24cce38a99f373450db67bf576fe73e8168d66 because it
was never appropriate for mainline.
Do not check for init flag before starting I/O - zram module is unusable
without this fix.
The oops mentioned in the reverted commit message was actually a problem
only with the zram version as present in project's own repository where
we allocate struct zram_stats_cpu upon device initialization. OTOH, In
mainline/staging version of zram, we allocate struct stats upfront, so
this oops cannot happen in mainline version.
Checking for init_done flag in zram_make_request() results in a *no-op*
for any I/O operation since we simply always return success. This flag
is actually set when the first write occurs on a zram disk which
triggers its initialization.
Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=25722
Reported-by: Dennis Jansen <dennis.jansen@web.de>
Signed-off-by: Nitin Gupta <ngupta@vflare.org>
Cc: Anton Blanchard <anton@samba.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
drivers/staging/zram/zram_drv.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 8c3c057..d0e9e02 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -435,12 +435,6 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio)
int ret = 0;
struct zram *zram = queue->queuedata;
- if (unlikely(!zram->init_done)) {
- set_bit(BIO_UPTODATE, &bio->bi_flags);
- bio_endio(bio, 0);
- return 0;
- }
-
if (!valid_io_request(zram, bio)) {
zram_stat64_inc(zram, &zram->stats.invalid_io);
bio_io_error(bio);
--
1.6.6.1

View File

@@ -0,0 +1,43 @@
From 9f260e0efa4766e56d0ac14f1aeea6ee5eb8fe83 Mon Sep 17 00:00:00 2001
From: Dan Rosenberg <drosenberg@vsecurity.com>
Date: Sun, 26 Dec 2010 06:54:53 +0000
Subject: [PATCH 38/66] CAN: Use inode instead of kernel address for /proc file
Since the socket address is just being used as a unique identifier, its
inode number is an alternative that does not leak potentially sensitive
information.
CC-ing stable because MITRE has assigned CVE-2010-4565 to the issue.
Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/can/bcm.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 6faa825..9d5e8ac 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -125,7 +125,7 @@ struct bcm_sock {
struct list_head tx_ops;
unsigned long dropped_usr_msgs;
struct proc_dir_entry *bcm_proc_read;
- char procname [20]; /* pointer printed in ASCII with \0 */
+ char procname [32]; /* inode number in decimal with \0 */
};
static inline struct bcm_sock *bcm_sk(const struct sock *sk)
@@ -1521,7 +1521,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
if (proc_dir) {
/* unique socket address as filename */
- sprintf(bo->procname, "%p", sock);
+ sprintf(bo->procname, "%lu", sock_i_ino(sk));
bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
proc_dir,
&bcm_proc_fops, sk);
--
1.6.6.1

View File

@@ -0,0 +1,56 @@
From 2393c944d5d60eedaede80273ede8a816b5fa3e0 Mon Sep 17 00:00:00 2001
From: Jesper Juhl <jj@chaosbits.net>
Date: Sun, 26 Dec 2010 09:59:58 +0000
Subject: [PATCH 39/66] ISDN, Gigaset: Fix memory leak in do_disconnect_req()
Hi,
In drivers/isdn/gigaset/capi.c::do_disconnect_req() we will leak the
memory allocated (with kmalloc) to 'b3cmsg' if the call to alloc_skb()
fails.
...
b3cmsg = kmalloc(sizeof(*b3cmsg), GFP_KERNEL);
allocation here ------^
if (!b3cmsg) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
return;
}
capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND,
ap->nextMessageNumber++,
cmsg->adr.adrPLCI | (1 << 16));
b3cmsg->Reason_B3 = CapiProtocolErrorLayer1;
b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL);
if (b3skb == NULL) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
return;
leak here ------^
...
This leak is easily fixed by just kfree()'ing the memory allocated to
'b3cmsg' right before we return. The following patch does that.
Signed-off-by: Jesper Juhl <jj@chaosbits.net>
Acked-by: Tilman Schmidt <tilman@imap.cc>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/isdn/gigaset/capi.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index bcc174e..658e75f 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -1900,6 +1900,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
if (b3skb == NULL) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
+ kfree(b3cmsg);
return;
}
capi_cmsg2message(b3cmsg,
--
1.6.6.1

View File

@@ -0,0 +1,58 @@
From f7e4c9775ea648deed4a8193951e50d0c7706173 Mon Sep 17 00:00:00 2001
From: Jesper Juhl <jj@chaosbits.net>
Date: Fri, 31 Dec 2010 11:18:48 -0800
Subject: [PATCH 40/66] Broadcom CNIC core network driver: fix mem leak on allocation failures in cnic_alloc_uio_rings()
We are leaking memory in drivers/net/cnic.c::cnic_alloc_uio_rings() if
either of the calls to dma_alloc_coherent() fail. This patch fixes it by
freeing both the memory allocated with kzalloc() and memory allocated with
previous calls to dma_alloc_coherent() when there's a failure.
Thanks to Joe Perches <joe@perches.com> for suggesting a better
implementation than my initial version.
Signed-off-by: Jesper Juhl <jj@chaosbits.net>
Acked-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/cnic.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 92bac19..6dff321 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -940,7 +940,7 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
&udev->l2_ring_map,
GFP_KERNEL | __GFP_COMP);
if (!udev->l2_ring)
- return -ENOMEM;
+ goto err_udev;
udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size);
@@ -948,7 +948,7 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
&udev->l2_buf_map,
GFP_KERNEL | __GFP_COMP);
if (!udev->l2_buf)
- return -ENOMEM;
+ goto err_dma;
write_lock(&cnic_dev_lock);
list_add(&udev->list, &cnic_udev_list);
@@ -959,6 +959,12 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
cp->udev = udev;
return 0;
+ err_dma:
+ dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size,
+ udev->l2_ring, udev->l2_ring_map);
+ err_udev:
+ kfree(udev);
+ return -ENOMEM;
}
static int cnic_init_uio(struct cnic_dev *dev)
--
1.6.6.1

View File

@@ -0,0 +1,35 @@
From 824f5f38d3005c346a043dedcfe8b048b699b81a Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Wed, 29 Dec 2010 03:40:31 +0000
Subject: [PATCH 41/66] tg3: fix return value check in tg3_read_vpd()
Besides -ETIMEDOUT and -EINTR, pci_read_vpd may return other error
values like -ENODEV or -EINVAL which are ignored due to the buggy
check, but the data are not read from VPD anyway and this is checked
subsequently with at most 3 needless loop iterations. This does not
show up as a runtime bug.
CC: Matt Carlson <mcarlson@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/tg3.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 30ccbb6..6f97b7b 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -12658,7 +12658,7 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
cnt = pci_read_vpd(tp->pdev, pos,
TG3_NVM_VPD_LEN - pos,
&vpd_data[pos]);
- if (cnt == -ETIMEDOUT || -EINTR)
+ if (cnt == -ETIMEDOUT || cnt == -EINTR)
cnt = 0;
else if (cnt < 0)
goto out_not_found;
--
1.6.6.1

View File

@@ -0,0 +1,37 @@
From f4d5900a99dbc354ef1ba384d445ff80ae4d77b4 Mon Sep 17 00:00:00 2001
From: Ben Hutchings <ben@decadent.org.uk>
Date: Wed, 29 Dec 2010 04:26:17 +0000
Subject: [PATCH 42/66] starfire: Fix dma_addr_t size test for MIPS
Commit 56543af "starfire: use BUILD_BUG_ON for netdrv_addr_t" revealed
that the preprocessor condition used to find the size of dma_addr_t
yielded the wrong result for some architectures and configurations.
This was kluged for 64-bit PowerPC in commit 3e502e6 by adding yet
another case to the condition. However, 64-bit MIPS configurations
are not detected reliably either.
This should be fixed by using CONFIG_ARCH_DMA_ADDR_T_64BIT, but that
isn't yet defined everywhere it should be.
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/starfire.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 4adf124..a4f2bd5 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -148,7 +148,7 @@ static int full_duplex[MAX_UNITS] = {0, };
* This SUCKS.
* We need a much better method to determine if dma_addr_t is 64-bit.
*/
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT))
+#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || (defined(CONFIG_MIPS) && ((defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || defined(CONFIG_64BIT))) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT))
/* 64-bit dma_addr_t */
#define ADDR_64BITS /* This chip uses 64 bit addresses. */
#define netdrv_addr_t __le64
--
1.6.6.1

View File

@@ -0,0 +1,50 @@
From b9556f9a1abdc56a179ac7ba6053469373b6de0f Mon Sep 17 00:00:00 2001
From: Julia Lawall <julia@diku.dk>
Date: Wed, 29 Dec 2010 04:01:03 +0000
Subject: [PATCH 43/66] drivers/atm/atmtcp.c: add missing atm_dev_put
The earlier call to atm_dev_lookup increases the reference count of dev,
so decrease it on the way out.
The semantic match that finds this problem is as follows:
(http://coccinelle.lip6.fr/)
// <smpl>
@@
expression x, E;
constant C;
@@
x = atm_dev_lookup(...);
... when != false x != NULL
when != true x == NULL
when != \(E = x\|x = E\)
when != atm_dev_put(dev);
*return -C;
// </smpl>
Signed-off-by: Julia Lawall <julia@diku.dk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/atm/atmtcp.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
index 2b464b6..0b06250 100644
--- a/drivers/atm/atmtcp.c
+++ b/drivers/atm/atmtcp.c
@@ -392,7 +392,10 @@ static int atmtcp_attach(struct atm_vcc *vcc,int itf)
atm_dev_put(dev);
return -EMEDIUMTYPE;
}
- if (PRIV(dev)->vcc) return -EBUSY;
+ if (PRIV(dev)->vcc) {
+ atm_dev_put(dev);
+ return -EBUSY;
+ }
}
else {
int error;
--
1.6.6.1

View File

@@ -0,0 +1,32 @@
From d0dfc6b74a0c6e9ee46b62713256e2b025244d3c Mon Sep 17 00:00:00 2001
From: Avi Kivity <avi@redhat.com>
Date: Fri, 31 Dec 2010 10:52:15 +0200
Subject: [PATCH 44/66] KVM: i8259: initialize isr_ack
isr_ack is never initialized. So, until the first PIC reset, interrupts
may fail to be injected. This can cause Windows XP to fail to boot, as
reported in the fallout from the fix to
https://bugzilla.kernel.org/show_bug.cgi?id=21962.
Reported-and-tested-by: Nicolas Prochazka <prochazka.nicolas@gmail.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
---
arch/x86/kvm/i8259.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index f628234..3cece05 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -575,6 +575,8 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
s->pics[1].elcr_mask = 0xde;
s->pics[0].pics_state = s;
s->pics[1].pics_state = s;
+ s->pics[0].isr_ack = 0xff;
+ s->pics[1].isr_ack = 0xff;
/*
* Initialize PIO device
--
1.6.6.1

View File

@@ -0,0 +1,37 @@
From b518a64983cbf2ff31aed530898de2d80e4573d5 Mon Sep 17 00:00:00 2001
From: Maurus Cuelenaere <mcuelenaere@gmail.com>
Date: Sun, 2 Jan 2011 14:48:16 -0500
Subject: [PATCH 45/66] hwmon: (s3c-hwmon) Fix compilation
The owner field was removed from struct attribute in
6fd69dc578fa0b1bbc3aad70ae3af9a137211707, so don't assign it anymore.
Signed-off-by: Maurus Cuelenaere <mcuelenaere@gmail.com>
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
---
drivers/hwmon/s3c-hwmon.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
index 05248f2..92b42db 100644
--- a/drivers/hwmon/s3c-hwmon.c
+++ b/drivers/hwmon/s3c-hwmon.c
@@ -234,7 +234,6 @@ static int s3c_hwmon_create_attr(struct device *dev,
attr->index = channel;
attr->dev_attr.attr.name = attrs->in_name;
attr->dev_attr.attr.mode = S_IRUGO;
- attr->dev_attr.attr.owner = THIS_MODULE;
attr->dev_attr.show = s3c_hwmon_ch_show;
ret = device_create_file(dev, &attr->dev_attr);
@@ -252,7 +251,6 @@ static int s3c_hwmon_create_attr(struct device *dev,
attr->index = channel;
attr->dev_attr.attr.name = attrs->label_name;
attr->dev_attr.attr.mode = S_IRUGO;
- attr->dev_attr.attr.owner = THIS_MODULE;
attr->dev_attr.show = s3c_hwmon_label_show;
ret = device_create_file(dev, &attr->dev_attr);
--
1.6.6.1

View File

@@ -0,0 +1,58 @@
From 551423748a4eba55f2eb0fc250d757986471f187 Mon Sep 17 00:00:00 2001
From: Ben Hutchings <ben@decadent.org.uk>
Date: Sun, 2 Jan 2011 23:02:42 +0000
Subject: [PATCH 46/66] watchdog: Improve initialisation error message and documentation
The error message 'NMI watchdog failed to create perf event...'
does not make it clear that this is a fatal error for the
watchdog. It also currently prints the error value as a
pointer, rather than extracting the error code with PTR_ERR().
Fix that.
Add a note to the description of the 'nowatchdog' kernel
parameter to associate it with this message.
Reported-by: Cesare Leonardi <celeonar@gmail.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Cc: 599368@bugs.debian.org
Cc: 608138@bugs.debian.org
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: <stable@kernel.org> # .37.x and later
LKML-Reference: <1294009362.3167.126.camel@localhost>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
Documentation/kernel-parameters.txt | 2 +-
kernel/watchdog.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 8b61c93..01ece1b 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1759,7 +1759,7 @@ and is between 256 and 4096 characters. It is defined in the file
nousb [USB] Disable the USB subsystem
- nowatchdog [KNL] Disable the lockup detector.
+ nowatchdog [KNL] Disable the lockup detector (NMI watchdog).
nowb [ARM]
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 6e3c41a..5b08215 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -364,7 +364,8 @@ static int watchdog_nmi_enable(int cpu)
goto out_save;
}
- printk(KERN_ERR "NMI watchdog failed to create perf event on cpu%i: %p\n", cpu, event);
+ printk(KERN_ERR "NMI watchdog disabled for cpu%i: unable to create perf event: %ld\n",
+ cpu, PTR_ERR(event));
return PTR_ERR(event);
/* success path */
--
1.6.6.1

View File

@@ -0,0 +1,42 @@
From 7c0ab43e6ab09d72dc8dbac2521b2f819ccc4026 Mon Sep 17 00:00:00 2001
From: Axel Lin <axel.lin@gmail.com>
Date: Mon, 3 Jan 2011 02:26:53 +0100
Subject: [PATCH 47/66] ARM: 6605/1: Add missing include "asm/memory.h"
This patch fixes below build error by adding the missing asm/memory.h,
which is needed for arch_is_coherent().
$ make pxa3xx_defconfig; make
CC init/do_mounts_rd.o
In file included from include/linux/list_bl.h:5,
from include/linux/rculist_bl.h:7,
from include/linux/dcache.h:7,
from include/linux/fs.h:381,
from init/do_mounts_rd.c:3:
include/linux/bit_spinlock.h: In function 'bit_spin_unlock':
include/linux/bit_spinlock.h:61: error: implicit declaration of function 'arch_is_coherent'
make[1]: *** [init/do_mounts_rd.o] Error 1
make: *** [init] Error 2
Signed-off-by: Axel Lin <axel.lin@gmail.com>
Acked-by: Peter Huewe <peterhuewe@gmx.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/include/asm/system.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 1120f18..8002594 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -150,6 +150,7 @@ extern unsigned int user_debug;
#define rmb() dmb()
#define wmb() mb()
#else
+#include <asm/memory.h>
#define mb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
#define rmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
#define wmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
--
1.6.6.1

View File

@@ -0,0 +1,31 @@
From 8333f65ef094e47020cd01452b4637e7daf5a77f Mon Sep 17 00:00:00 2001
From: Saeed Bishara <saeed@marvell.com>
Date: Tue, 21 Dec 2010 16:53:39 +0200
Subject: [PATCH 48/66] mv_xor: fix race in tasklet function
use mv_xor_slot_cleanup() instead of __mv_xor_slot_cleanup() as the former function
aquires the spin lock that needed to protect the drivers data.
Cc: <stable@kernel.org>
Signed-off-by: Saeed Bishara <saeed@marvell.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/dma/mv_xor.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 411d5bf..a25f5f6 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -449,7 +449,7 @@ mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
static void mv_xor_tasklet(unsigned long data)
{
struct mv_xor_chan *chan = (struct mv_xor_chan *) data;
- __mv_xor_slot_cleanup(chan);
+ mv_xor_slot_cleanup(chan);
}
static struct mv_xor_desc_slot *
--
1.6.6.1

View File

@@ -0,0 +1,55 @@
From 8f33d5277fada0291ea495f7fd44a3e7b7aa41d3 Mon Sep 17 00:00:00 2001
From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Date: Wed, 22 Dec 2010 14:46:46 +0100
Subject: [PATCH 49/66] dmaengine: provide dummy functions for DMA_ENGINE=n
This lets drivers, optionally using the dmaengine, build with DMA_ENGINE
unselected.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
include/linux/dmaengine.h | 13 ++++++++++---
1 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 9d8688b..8cd00ad 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -824,6 +824,8 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
#ifdef CONFIG_DMA_ENGINE
enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
void dma_issue_pending_all(void);
+struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
+void dma_release_channel(struct dma_chan *chan);
#else
static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
{
@@ -831,7 +833,14 @@ static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descript
}
static inline void dma_issue_pending_all(void)
{
- do { } while (0);
+}
+static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
+ dma_filter_fn fn, void *fn_param)
+{
+ return NULL;
+}
+static inline void dma_release_channel(struct dma_chan *chan)
+{
}
#endif
@@ -842,8 +851,6 @@ void dma_async_device_unregister(struct dma_device *device);
void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
#define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
-struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
-void dma_release_channel(struct dma_chan *chan);
/* --- Helper iov-locking functions --- */
--
1.6.6.1

View File

@@ -0,0 +1,52 @@
From f23b7952d37c69c0caa6c8dfb85dbf2eb9e5fcaa Mon Sep 17 00:00:00 2001
From: Andy Walls <awalls@md.metrocast.net>
Date: Sun, 5 Dec 2010 19:42:30 -0300
Subject: [PATCH 50/66] [media] cx25840: Prevent device probe failure due to volume control ERANGE error
This patch fixes a regression that crept into 2.6.36.
The volume control scale in the cx25840 driver has an unusual mapping
from register values to v4l2 volume control values. Enforce the mapping
limits, so that the default volume control setting does not fall out of
bounds to prevent the cx25840 module device probe from failing.
Signed-off-by: Andy Walls <awalls@md.metrocast.net>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
drivers/media/video/cx25840/cx25840-core.c | 19 +++++++++++++++++--
1 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index dfb198d..f164618 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -1989,8 +1989,23 @@ static int cx25840_probe(struct i2c_client *client,
v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
V4L2_CID_HUE, -128, 127, 1, 0);
if (!is_cx2583x(state)) {
- default_volume = 228 - cx25840_read(client, 0x8d4);
- default_volume = ((default_volume / 2) + 23) << 9;
+ default_volume = cx25840_read(client, 0x8d4);
+ /*
+ * Enforce the legacy PVR-350/MSP3400 to PVR-150/CX25843 volume
+ * scale mapping limits to avoid -ERANGE errors when
+ * initializing the volume control
+ */
+ if (default_volume > 228) {
+ /* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
+ default_volume = 228;
+ cx25840_write(client, 0x8d4, 228);
+ }
+ else if (default_volume < 20) {
+ /* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
+ default_volume = 20;
+ cx25840_write(client, 0x8d4, 20);
+ }
+ default_volume = (((228 - default_volume) >> 1) + 23) << 9;
state->volume = v4l2_ctrl_new_std(&state->hdl,
&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
--
1.6.6.1

View File

@@ -0,0 +1,518 @@
From 46e67acd5d4cacda758e871eebd15cef4e2c2665 Mon Sep 17 00:00:00 2001
From: Mauro Carvalho Chehab <mchehab@redhat.com>
Date: Mon, 3 Jan 2011 09:09:56 -0200
Subject: [PATCH 51/66] [media] wm8775: Revert changeset fcb9757333 to avoid a regression
It seems that cx88 and ivtv use wm8775 on some different modes. The
patch that added support for a board with wm8775 broke ivtv boards with
this device. As we're too close to release 2.6.37, let's just revert
it.
Reported-by: Andy Walls <awalls@md.metrocast.net>
Reported-by: Eric Sharkey <eric@lisaneric.org>
Reported-by: Auric <auric@aanet.com.au>
Reported by: David Gesswein <djg@pdp8online.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
drivers/media/video/cx88/cx88-alsa.c | 99 ++++---------------------------
drivers/media/video/cx88/cx88-cards.c | 7 ++
drivers/media/video/cx88/cx88-video.c | 27 +--------
drivers/media/video/cx88/cx88.h | 6 +-
drivers/media/video/wm8775.c | 104 ++++++++++++--------------------
include/media/wm8775.h | 3 -
6 files changed, 61 insertions(+), 185 deletions(-)
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 4aaa47c..54b7fcd 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -40,7 +40,6 @@
#include <sound/control.h>
#include <sound/initval.h>
#include <sound/tlv.h>
-#include <media/wm8775.h>
#include "cx88.h"
#include "cx88-reg.h"
@@ -587,47 +586,26 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
int left, right, v, b;
int changed = 0;
u32 old;
- struct v4l2_control client_ctl;
-
- /* Pass volume & balance onto any WM8775 */
- if (value->value.integer.value[0] >= value->value.integer.value[1]) {
- v = value->value.integer.value[0] << 10;
- b = value->value.integer.value[0] ?
- (0x8000 * value->value.integer.value[1]) / value->value.integer.value[0] :
- 0x8000;
- } else {
- v = value->value.integer.value[1] << 10;
- b = value->value.integer.value[1] ?
- 0xffff - (0x8000 * value->value.integer.value[0]) / value->value.integer.value[1] :
- 0x8000;
- }
- client_ctl.value = v;
- client_ctl.id = V4L2_CID_AUDIO_VOLUME;
- call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
- client_ctl.value = b;
- client_ctl.id = V4L2_CID_AUDIO_BALANCE;
- call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
left = value->value.integer.value[0] & 0x3f;
right = value->value.integer.value[1] & 0x3f;
b = right - left;
if (b < 0) {
- v = 0x3f - left;
- b = (-b) | 0x40;
+ v = 0x3f - left;
+ b = (-b) | 0x40;
} else {
- v = 0x3f - right;
+ v = 0x3f - right;
}
/* Do we really know this will always be called with IRQs on? */
spin_lock_irq(&chip->reg_lock);
old = cx_read(AUD_VOL_CTL);
if (v != (old & 0x3f)) {
- cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
- changed = 1;
+ cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
+ changed = 1;
}
- if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
- cx_write(AUD_BAL_CTL, b);
- changed = 1;
+ if (cx_read(AUD_BAL_CTL) != b) {
+ cx_write(AUD_BAL_CTL, b);
+ changed = 1;
}
spin_unlock_irq(&chip->reg_lock);
@@ -640,7 +618,7 @@ static const struct snd_kcontrol_new snd_cx88_volume = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ,
- .name = "Analog-TV Volume",
+ .name = "Playback Volume",
.info = snd_cx88_volume_info,
.get = snd_cx88_volume_get,
.put = snd_cx88_volume_put,
@@ -671,14 +649,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
vol = cx_read(AUD_VOL_CTL);
if (value->value.integer.value[0] != !(vol & bit)) {
vol ^= bit;
- cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
- /* Pass mute onto any WM8775 */
- if ((1<<6) == bit) {
- struct v4l2_control client_ctl;
- client_ctl.value = 0 != (vol & bit);
- client_ctl.id = V4L2_CID_AUDIO_MUTE;
- call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
- }
+ cx_write(AUD_VOL_CTL, vol);
ret = 1;
}
spin_unlock_irq(&chip->reg_lock);
@@ -687,7 +658,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
static const struct snd_kcontrol_new snd_cx88_dac_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Audio-Out Switch",
+ .name = "Playback Switch",
.info = snd_ctl_boolean_mono_info,
.get = snd_cx88_switch_get,
.put = snd_cx88_switch_put,
@@ -696,49 +667,13 @@ static const struct snd_kcontrol_new snd_cx88_dac_switch = {
static const struct snd_kcontrol_new snd_cx88_source_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog-TV Switch",
+ .name = "Capture Switch",
.info = snd_ctl_boolean_mono_info,
.get = snd_cx88_switch_get,
.put = snd_cx88_switch_put,
.private_value = (1<<6),
};
-static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *value)
-{
- snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
- struct cx88_core *core = chip->core;
- struct v4l2_control client_ctl;
-
- client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
- call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
- value->value.integer.value[0] = client_ctl.value ? 1 : 0;
-
- return 0;
-}
-
-static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *value)
-{
- snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
- struct cx88_core *core = chip->core;
- struct v4l2_control client_ctl;
-
- client_ctl.value = 0 != value->value.integer.value[0];
- client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
- call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
- return 0;
-}
-
-static struct snd_kcontrol_new snd_cx88_alc_switch = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Line-In ALC Switch",
- .info = snd_ctl_boolean_mono_info,
- .get = snd_cx88_alc_get,
- .put = snd_cx88_alc_put,
-};
-
/****************************************************************************
Basic Flow for Sound Devices
****************************************************************************/
@@ -860,7 +795,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
{
struct snd_card *card;
snd_cx88_card_t *chip;
- struct v4l2_subdev *sd;
int err;
if (devno >= SNDRV_CARDS)
@@ -896,15 +830,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
if (err < 0)
goto error;
- /* If there's a wm8775 then add a Line-In ALC switch */
- list_for_each_entry(sd, &chip->core->v4l2_dev.subdevs, list) {
- if (WM8775_GID == sd->grp_id) {
- snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch,
- chip));
- break;
- }
- }
-
strcpy (card->driver, "CX88x");
sprintf(card->shortname, "Conexant CX%x", pci->device);
sprintf(card->longname, "%s at %#llx",
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 9b9e169..0ccc2af 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1007,15 +1007,22 @@ static const struct cx88_board cx88_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
+ .audio_chip = V4L2_IDENT_WM8775,
.input = {{
.type = CX88_VMUX_DVB,
.vmux = 0,
+ /* 2: Line-In */
+ .audioroute = 2,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
+ /* 2: Line-In */
+ .audioroute = 2,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
+ /* 2: Line-In */
+ .audioroute = 2,
}},
.mpeg = CX88_MPEG_DVB,
},
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 62cea95..d9249e5 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -40,7 +40,6 @@
#include "cx88.h"
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
-#include <media/wm8775.h>
MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -977,7 +976,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
const struct cx88_ctrl *c = NULL;
u32 value,mask;
int i;
- struct v4l2_control client_ctl;
for (i = 0; i < CX8800_CTLS; i++) {
if (cx8800_ctls[i].v.id == ctl->id) {
@@ -991,27 +989,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
ctl->value = c->v.minimum;
if (ctl->value > c->v.maximum)
ctl->value = c->v.maximum;
-
- /* Pass changes onto any WM8775 */
- client_ctl.id = ctl->id;
- switch (ctl->id) {
- case V4L2_CID_AUDIO_MUTE:
- client_ctl.value = ctl->value;
- break;
- case V4L2_CID_AUDIO_VOLUME:
- client_ctl.value = (ctl->value) ?
- (0x90 + ctl->value) << 8 : 0;
- break;
- case V4L2_CID_AUDIO_BALANCE:
- client_ctl.value = ctl->value << 9;
- break;
- default:
- client_ctl.id = 0;
- break;
- }
- if (client_ctl.id)
- call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
mask=c->mask;
switch (ctl->id) {
case V4L2_CID_AUDIO_BALANCE:
@@ -1558,9 +1535,7 @@ static int radio_queryctrl (struct file *file, void *priv,
if (c->id < V4L2_CID_BASE ||
c->id >= V4L2_CID_LASTP1)
return -EINVAL;
- if (c->id == V4L2_CID_AUDIO_MUTE ||
- c->id == V4L2_CID_AUDIO_VOLUME ||
- c->id == V4L2_CID_AUDIO_BALANCE) {
+ if (c->id == V4L2_CID_AUDIO_MUTE) {
for (i = 0; i < CX8800_CTLS; i++) {
if (cx8800_ctls[i].v.id == c->id)
break;
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index e8c732e..c9981e7 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -398,19 +398,17 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
}
-#define call_hw(core, grpid, o, f, args...) \
+#define call_all(core, o, f, args...) \
do { \
if (!core->i2c_rc) { \
if (core->gate_ctrl) \
core->gate_ctrl(core, 1); \
- v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
+ v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \
if (core->gate_ctrl) \
core->gate_ctrl(core, 0); \
} \
} while (0)
-#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
-
struct cx8800_dev;
struct cx8802_dev;
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index 1355256..fe8ef64 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -35,7 +35,6 @@
#include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h>
-#include <media/wm8775.h>
MODULE_DESCRIPTION("wm8775 driver");
MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
@@ -51,16 +50,10 @@ enum {
TOT_REGS
};
-#define ALC_HOLD 0x85 /* R17: use zero cross detection, ALC hold time 42.6 ms */
-#define ALC_EN 0x100 /* R17: ALC enable */
-
struct wm8775_state {
struct v4l2_subdev sd;
struct v4l2_ctrl_handler hdl;
struct v4l2_ctrl *mute;
- struct v4l2_ctrl *vol;
- struct v4l2_ctrl *bal;
- struct v4l2_ctrl *loud;
u8 input; /* Last selected input (0-0xf) */
};
@@ -92,30 +85,6 @@ static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val)
return -1;
}
-static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly)
-{
- struct wm8775_state *state = to_state(sd);
- u8 vol_l, vol_r;
- int muted = 0 != state->mute->val;
- u16 volume = (u16)state->vol->val;
- u16 balance = (u16)state->bal->val;
-
- /* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */
- vol_l = (min(65536 - balance, 32768) * volume) >> 23;
- vol_r = (min(balance, (u16)32768) * volume) >> 23;
-
- /* Mute */
- if (muted || quietly)
- wm8775_write(sd, R21, 0x0c0 | state->input);
-
- wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */
- wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */
-
- /* Un-mute */
- if (!muted)
- wm8775_write(sd, R21, state->input);
-}
-
static int wm8775_s_routing(struct v4l2_subdev *sd,
u32 input, u32 output, u32 config)
{
@@ -133,26 +102,25 @@ static int wm8775_s_routing(struct v4l2_subdev *sd,
state->input = input;
if (!v4l2_ctrl_g_ctrl(state->mute))
return 0;
- if (!v4l2_ctrl_g_ctrl(state->vol))
- return 0;
- if (!v4l2_ctrl_g_ctrl(state->bal))
- return 0;
- wm8775_set_audio(sd, 1);
+ wm8775_write(sd, R21, 0x0c0);
+ wm8775_write(sd, R14, 0x1d4);
+ wm8775_write(sd, R15, 0x1d4);
+ wm8775_write(sd, R21, 0x100 + state->input);
return 0;
}
static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = to_sd(ctrl);
+ struct wm8775_state *state = to_state(sd);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
- case V4L2_CID_AUDIO_VOLUME:
- case V4L2_CID_AUDIO_BALANCE:
- wm8775_set_audio(sd, 0);
- return 0;
- case V4L2_CID_AUDIO_LOUDNESS:
- wm8775_write(sd, R17, (ctrl->val ? ALC_EN : 0) | ALC_HOLD);
+ wm8775_write(sd, R21, 0x0c0);
+ wm8775_write(sd, R14, 0x1d4);
+ wm8775_write(sd, R15, 0x1d4);
+ if (!ctrl->val)
+ wm8775_write(sd, R21, 0x100 + state->input);
return 0;
}
return -EINVAL;
@@ -176,7 +144,16 @@ static int wm8775_log_status(struct v4l2_subdev *sd)
static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
{
- wm8775_set_audio(sd, 0);
+ struct wm8775_state *state = to_state(sd);
+
+ /* If I remove this, then it can happen that I have no
+ sound the first time I tune from static to a valid channel.
+ It's difficult to reproduce and is almost certainly related
+ to the zero cross detect circuit. */
+ wm8775_write(sd, R21, 0x0c0);
+ wm8775_write(sd, R14, 0x1d4);
+ wm8775_write(sd, R15, 0x1d4);
+ wm8775_write(sd, R21, 0x100 + state->input);
return 0;
}
@@ -226,7 +203,6 @@ static int wm8775_probe(struct i2c_client *client,
{
struct wm8775_state *state;
struct v4l2_subdev *sd;
- int err;
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -240,21 +216,15 @@ static int wm8775_probe(struct i2c_client *client,
return -ENOMEM;
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &wm8775_ops);
- sd->grp_id = WM8775_GID; /* subdev group id */
state->input = 2;
- v4l2_ctrl_handler_init(&state->hdl, 4);
+ v4l2_ctrl_handler_init(&state->hdl, 1);
state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
- state->vol = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
- V4L2_CID_AUDIO_VOLUME, 0, 65535, (65535+99)/100, 0xCF00); /* 0dB*/
- state->bal = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
- V4L2_CID_AUDIO_BALANCE, 0, 65535, (65535+99)/100, 32768);
- state->loud = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
- V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 1);
sd->ctrl_handler = &state->hdl;
- err = state->hdl.error;
- if (err) {
+ if (state->hdl.error) {
+ int err = state->hdl.error;
+
v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return err;
@@ -266,25 +236,29 @@ static int wm8775_probe(struct i2c_client *client,
wm8775_write(sd, R23, 0x000);
/* Disable zero cross detect timeout */
wm8775_write(sd, R7, 0x000);
- /* HPF enable, I2S mode, 24-bit */
- wm8775_write(sd, R11, 0x022);
+ /* Left justified, 24-bit mode */
+ wm8775_write(sd, R11, 0x021);
/* Master mode, clock ratio 256fs */
wm8775_write(sd, R12, 0x102);
/* Powered up */
wm8775_write(sd, R13, 0x000);
- /* ALC stereo, ALC target level -5dB FS, ALC max gain +8dB */
- wm8775_write(sd, R16, 0x1bb);
- /* Set ALC mode and hold time */
- wm8775_write(sd, R17, (state->loud->val ? ALC_EN : 0) | ALC_HOLD);
+ /* ADC gain +2.5dB, enable zero cross */
+ wm8775_write(sd, R14, 0x1d4);
+ /* ADC gain +2.5dB, enable zero cross */
+ wm8775_write(sd, R15, 0x1d4);
+ /* ALC Stereo, ALC target level -1dB FS max gain +8dB */
+ wm8775_write(sd, R16, 0x1bf);
+ /* Enable gain control, use zero cross detection,
+ ALC hold time 42.6 ms */
+ wm8775_write(sd, R17, 0x185);
/* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */
wm8775_write(sd, R18, 0x0a2);
/* Enable noise gate, threshold -72dBfs */
wm8775_write(sd, R19, 0x005);
- /* Transient window 4ms, ALC min gain -5dB */
- wm8775_write(sd, R20, 0x0fb);
-
- wm8775_set_audio(sd, 1); /* set volume/mute/mux */
-
+ /* Transient window 4ms, lower PGA gain limit -1dB */
+ wm8775_write(sd, R20, 0x07a);
+ /* LRBOTH = 1, use input 2. */
+ wm8775_write(sd, R21, 0x102);
return 0;
}
diff --git a/include/media/wm8775.h b/include/media/wm8775.h
index a1c4d41..60739c5 100644
--- a/include/media/wm8775.h
+++ b/include/media/wm8775.h
@@ -32,7 +32,4 @@
#define WM8775_AIN3 4
#define WM8775_AIN4 8
-/* subdev group ID */
-#define WM8775_GID (1 << 0)
-
#endif
--
1.6.6.1

Some files were not shown because too many files have changed in this diff Show More