summaryrefslogtreecommitdiff
path: root/recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch')
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch209
1 files changed, 209 insertions, 0 deletions
diff --git a/recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch b/recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch
new file mode 100644
index 0000000000..5a45e433a0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch
@@ -0,0 +1,209 @@
+From 964c2a99d0b9db59bc716022c7f9f6da580f44d6 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 12 Jun 2009 11:17:15 +0300
+Subject: [PATCH 110/146] DSS2: isolate the SDI pads when SDI is disabled
+
+When SDI is disabled there is still ~1.6mA drain through the VSDI_CSI
+regulator. This seems to be internal to the SDI module, since even
+disconnecting the LCD panel doesn't get rid of the drain. Also
+disabling/resetting the SDI or the DSS module doesn't help. The only
+solution is to configure the SDI pads to safe mode with pull up
+resistors enabled on them when SDI gets disabled.
+
+Bootloader / platform code is still responsible for setting up the
+muxing, so in the driver check if all required pads are in SDI mode
+or all of them are in non-configured state.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+
+Conflicts:
+
+ arch/arm/plat-omap/include/mach/display.h
+---
+ arch/arm/plat-omap/include/mach/display.h | 2 +
+ drivers/video/omap2/dss/sdi.c | 110 ++++++++++++++++++++++++++++-
+ 2 files changed, 111 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 3d8ed69..0695497 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -344,6 +344,8 @@ struct omap_dss_device {
+
+ struct {
+ u8 datapairs;
++ unsigned pad_off_pe : 1; /* pull pads if disabled */
++ unsigned pad_off_pu : 1; /* pull up */
+ } sdi;
+
+ struct {
+diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
+index 86b9a56..c484e0c 100644
+--- a/drivers/video/omap2/dss/sdi.c
++++ b/drivers/video/omap2/dss/sdi.c
+@@ -23,17 +23,120 @@
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/err.h>
++#include <linux/io.h>
+
+ #include <mach/board.h>
+ #include <mach/display.h>
+ #include "dss.h"
+
++#define CONTROL_PADCONF_BASE 0x48002000
++
++#define OMAP_SDI_PAD_DIS(pe,pu) ((7 << 0) | /* MODE 7 = safe */ \
++ (((pe) ? 1 : 0) << 3) | /* PULL_ENA */ \
++ (((pu) ? 1 : 0) << 4) | /* PULL_UP */ \
++ (1 << 8)) /* INPUT_EN */
++
++#define OMAP_SDI_PAD_EN (1 << 0) /* MODE 1 = SDI_xx */
++
++#define OMAP_SDI_PAD_MASK OMAP_SDI_PAD_DIS(1, 1)
+
+ static struct {
+ bool skip_init;
+ bool update_enabled;
+ } sdi;
+
++/* CONTROL_PADCONF_DSS_DATAXX */
++const u16 sdi_pads[] =
++{
++ 0x0f0, /* 10[ 7..0]:SDI_DAT1N */
++ 0x0f2, /* 10[15..0]:SDI_DAT1P */
++ 0x0f4, /* 12[ 7..0]:SDI_DAT2N */
++ 0x0f6, /* 12[15..0]:SDI_DAT2P */
++ 0x0f8, /* 14[ 7..0]:SDI_DAT3N */
++ 0x0fa, /* 14[15..0]:SDI_DAT3P */
++ 0x108, /* 22[ 7..0]:SDI_CLKN */
++ 0x10a, /* 22[15..0]:SDI_CLKP */
++};
++
++/*
++ * Check if bootloader / platform code has configured the SDI pads properly.
++ * This means it either configured all required pads for SDI mode, or that it
++ * left all the required pads unconfigured.
++ */
++static int sdi_pad_init(struct omap_dss_device *dssdev)
++{
++ unsigned req_map;
++ bool configured = false;
++ bool unconfigured = false;
++ int data_pairs;
++ int i;
++
++ data_pairs = dssdev->phy.sdi.datapairs;
++ req_map = (1 << (data_pairs * 2)) - 1; /* data lanes */
++ req_map |= 3 << 6; /* clk lane */
++ for (i = 0; i < ARRAY_SIZE(sdi_pads); i++) {
++ u32 reg;
++ u32 val;
++
++ if (!((1 << i) & req_map))
++ /* Ignore unneded pads. */
++ continue;
++ reg = CONTROL_PADCONF_BASE + sdi_pads[i];
++ val = omap_readw(reg);
++ switch (val & 0x07) { /* pad mode */
++ case 1:
++ if (unconfigured)
++ break;
++ /* Is the pull configuration ok for SDI mode? */
++ if ((val & OMAP_SDI_PAD_MASK) != OMAP_SDI_PAD_EN)
++ break;
++ configured = true;
++ break;
++ case 0:
++ case 7:
++ if (configured)
++ break;
++ unconfigured = true;
++ break;
++ default:
++ break;
++ }
++ }
++ if (i != ARRAY_SIZE(sdi_pads)) {
++ DSSERR("SDI: invalid pad configuration\n");
++ return -1;
++ }
++
++ return 0;
++}
++
++static void sdi_pad_config(struct omap_dss_device *dssdev, bool enable)
++{
++ int data_pairs;
++ bool pad_off_pe, pad_off_pu;
++ unsigned req_map;
++ int i;
++
++ data_pairs = dssdev->phy.sdi.datapairs;
++ pad_off_pe = dssdev->phy.sdi.pad_off_pe;
++ pad_off_pu = dssdev->phy.sdi.pad_off_pu;
++ req_map = (1 << (data_pairs * 2)) - 1; /* data lanes */
++ req_map |= 3 << 6; /* clk lane */
++ for (i = 0; i < ARRAY_SIZE(sdi_pads); i++) {
++ u32 reg;
++ u16 val;
++
++ if (!((1 << i) & req_map))
++ continue;
++ if (enable)
++ val = OMAP_SDI_PAD_EN;
++ else
++ val = OMAP_SDI_PAD_DIS(pad_off_pe, pad_off_pu);
++ reg = CONTROL_PADCONF_BASE + sdi_pads[i];
++ omap_writew(val, reg);
++ }
++}
++
+ static void sdi_basic_init(void)
+ {
+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
+@@ -64,6 +167,8 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
+ goto err1;
+ }
+
++ sdi_pad_config(dssdev, 1);
++
+ /* In case of skip_init sdi_init has already enabled the clocks */
+ if (!sdi.skip_init)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+@@ -153,6 +258,7 @@ static void sdi_display_disable(struct omap_dss_device *dssdev)
+ dss_sdi_disable();
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ sdi_pad_config(dssdev, 0);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+@@ -172,6 +278,7 @@ static int sdi_display_suspend(struct omap_dss_device *dssdev)
+ dss_sdi_disable();
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ sdi_pad_config(dssdev, 0);
+
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+@@ -183,6 +290,7 @@ static int sdi_display_resume(struct omap_dss_device *dssdev)
+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ return -EINVAL;
+
++ sdi_pad_config(dssdev, 1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ dss_sdi_enable();
+@@ -240,7 +348,7 @@ int sdi_init_display(struct omap_dss_device *dssdev)
+ dssdev->get_update_mode = sdi_display_get_update_mode;
+ dssdev->get_timings = sdi_get_timings;
+
+- return 0;
++ return sdi_pad_init(dssdev);
+ }
+
+ int sdi_init(bool skip_init)
+--
+1.6.2.4
+