* [PATCH 01/19] OMAP: DSS2: DSI: Add lane override functions
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 02/19] OMAP: DSS2: DSI: Remove CIO LDO status check Tomi Valkeinen
` (18 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
DSI_DSIPHY_CFG10 register can be used to override DSI lane state. Add
functions to configure and enable the override, and to disable the
override.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 58 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 2666b6b..d245c5c 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -90,6 +90,7 @@ struct dsi_reg { u16 idx; };
#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
+#define DSI_DSIPHY_CFG10 DSI_REG(0x200 + 0x0028)
/* DSI_PLL_CTRL_SCP */
@@ -208,6 +209,15 @@ enum dsi_vc_mode {
DSI_VC_MODE_VP,
};
+enum dsi_lane {
+ DSI_CLK_P = 1 << 0,
+ DSI_CLK_N = 1 << 1,
+ DSI_DATA1_P = 1 << 2,
+ DSI_DATA1_N = 1 << 3,
+ DSI_DATA2_P = 1 << 4,
+ DSI_DATA2_N = 1 << 5,
+};
+
struct dsi_update_region {
u16 x, y, w, h;
struct omap_dss_device *device;
@@ -1863,6 +1873,54 @@ static void dsi_complexio_timings(void)
dsi_write_reg(DSI_DSIPHY_CFG2, r);
}
+static void dsi_enable_lane_override(struct omap_dss_device *dssdev,
+ enum dsi_lane lanes)
+{
+ int clk_lane = dssdev->phy.dsi.clk_lane;
+ int data1_lane = dssdev->phy.dsi.data1_lane;
+ int data2_lane = dssdev->phy.dsi.data2_lane;
+ int clk_pol = dssdev->phy.dsi.clk_pol;
+ int data1_pol = dssdev->phy.dsi.data1_pol;
+ int data2_pol = dssdev->phy.dsi.data2_pol;
+
+ u32 l = 0;
+
+ if (lanes & DSI_CLK_P)
+ l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1));
+ if (lanes & DSI_CLK_N)
+ l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0));
+
+ if (lanes & DSI_DATA1_P)
+ l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1));
+ if (lanes & DSI_DATA1_N)
+ l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0));
+
+ if (lanes & DSI_DATA2_P)
+ l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1));
+ if (lanes & DSI_DATA2_N)
+ l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0));
+
+ /*
+ * Bits in REGLPTXSCPDAT4TO0DXDY:
+ * 17: DY0 18: DX0
+ * 19: DY1 20: DX1
+ * 21: DY2 22: DX2
+ */
+
+ /* Set the lane override configuration */
+ REG_FLD_MOD(DSI_DSIPHY_CFG10, l, 22, 17); /* REGLPTXSCPDAT4TO0DXDY */
+
+ /* Enable lane override */
+ REG_FLD_MOD(DSI_DSIPHY_CFG10, 1, 27, 27); /* ENLPTXSCPDAT */
+}
+
+static void dsi_disable_lane_override(void)
+{
+ /* Disable lane override */
+ REG_FLD_MOD(DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */
+ /* Reset the lane override configuration */
+ REG_FLD_MOD(DSI_DSIPHY_CFG10, 0, 22, 17); /* REGLPTXSCPDAT4TO0DXDY */
+}
static int dsi_complexio_init(struct omap_dss_device *dssdev)
{
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 02/19] OMAP: DSS2: DSI: Remove CIO LDO status check
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 01/19] OMAP: DSS2: DSI: Add lane override functions Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 03/19] OMAP: DSS2: DSI: implement ULPS enter and exit Tomi Valkeinen
` (17 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
CIO LDO status check seems to be broken on OMAP3630+ chips, and it's
also quite unclear what LDO status actually tells and when its status
changes.
This patch removes the whole check on the grounds that if there's a
problem with the LDO, we should anyway catch the problem as we check the
CIO power state and CIO reset status.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 8 --------
drivers/video/omap2/dss/dss_features.c | 4 ++--
drivers/video/omap2/dss/dss_features.h | 5 ++---
3 files changed, 4 insertions(+), 13 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index d245c5c..013621e 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1952,14 +1952,6 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
goto err;
}
- if (dss_has_feature(FEAT_DSI_LDO_STATUS)) {
- if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
- DSSERR("ComplexIO LDO power down.\n");
- r = -ENODEV;
- goto err;
- }
- }
-
dsi_complexio_timings();
/*
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 6a1b130..5f3a7c4 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -253,7 +253,7 @@ static struct omap_dss_features omap3430_dss_features = {
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
- FEAT_DSI_PLL_FREQSEL | FEAT_DSI_LDO_STATUS,
+ FEAT_DSI_PLL_FREQSEL,
.num_mgrs = 2,
.num_ovls = 3,
@@ -273,7 +273,7 @@ static struct omap_dss_features omap3630_dss_features = {
FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
- FEAT_DSI_PLL_FREQSEL |FEAT_DSI_LDO_STATUS,
+ FEAT_DSI_PLL_FREQSEL,
.num_mgrs = 2,
.num_ovls = 3,
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index d03f558..1093e8d 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -43,9 +43,8 @@ enum dss_feat_id {
/* DSI-PLL power command 0x3 is not working */
FEAT_DSI_PLL_PWR_BUG = 1 << 13,
FEAT_DSI_PLL_FREQSEL = 1 << 14,
- FEAT_DSI_LDO_STATUS = 1 << 15,
- FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 16,
- FEAT_DSI_VC_OCP_WIDTH = 1 << 17,
+ FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15,
+ FEAT_DSI_VC_OCP_WIDTH = 1 << 16,
};
/* DSS register field id */
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 03/19] OMAP: DSS2: DSI: implement ULPS enter and exit
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 01/19] OMAP: DSS2: DSI: Add lane override functions Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 02/19] OMAP: DSS2: DSI: Remove CIO LDO status check Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 04/19] OMAP: DSS2: DSI: add option to leave DSI lanes powered on Tomi Valkeinen
` (16 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Entering ULPS (Ultra Low Power State) happens by sending ULPS entry
sequence to the DSI peripheral and pulling the DSI lines down.
Exiting ULPS happens by sending ULPS exit sequence.
We can send the ULPS entry sequence by using OMAP DSS HW's ULPS support,
but we cannot use the ULPS exit support from DSS HW. DSS HW refuses to
send the ULPS exit sequence if it thinks that the lanes are not in ULPS.
After being in OFF mode the DSS HW has been reset, and so it does not
know that the lanes are actually in ULPS.
Thus we need to use the lane override support and manually send the ULPS
exit sequence. Luckily the sequence is very simple.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 141 +++++++++++++++++++++++++++++++++++-----
1 files changed, 123 insertions(+), 18 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 013621e..5303548 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -33,6 +33,7 @@
#include <linux/regulator/consumer.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
+#include <linux/sched.h>
#include <plat/display.h>
#include <plat/clock.h>
@@ -268,6 +269,7 @@ static struct
struct dsi_update_region update_region;
bool te_enabled;
+ bool ulps_enabled;
struct workqueue_struct *workqueue;
@@ -1925,9 +1927,13 @@ static void dsi_disable_lane_override(void)
static int dsi_complexio_init(struct omap_dss_device *dssdev)
{
int r = 0;
+ u32 l;
DSSDBG("dsi_complexio_init\n");
+ if (dsi.ulps_enabled)
+ DSSDBG("manual ulps exit\n");
+
/* A dummy read using the SCP interface to any DSIPHY register is
* required after DSIPHY reset to complete the reset of the DSI complex
* I/O. */
@@ -1941,11 +1947,49 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
dsi_complexio_config(dssdev);
- r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
+ dsi_if_enable(true);
+ dsi_if_enable(false);
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
+
+ /* set TX STOP MODE timer to maximum for this operation */
+ l = dsi_read_reg(DSI_TIMING1);
+ l = FLD_MOD(l, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
+ l = FLD_MOD(l, 1, 14, 14); /* STOP_STATE_X16_IO */
+ l = FLD_MOD(l, 1, 13, 13); /* STOP_STATE_X4_IO */
+ l = FLD_MOD(l, 0x1fff, 12, 0); /* STOP_STATE_COUNTER_IO */
+ dsi_write_reg(DSI_TIMING1, l);
+
+ if (dsi.ulps_enabled) {
+ /* ULPS is exited by Mark-1 state for 1ms, followed by
+ * stop state. DSS HW cannot do this via the normal
+ * ULPS exit sequence, as after reset the DSS HW thinks
+ * that we are not in ULPS mode, and refuses to send the
+ * sequence. So we need to send the ULPS exit sequence
+ * manually.
+ */
+
+ dsi_enable_lane_override(dssdev,
+ DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P);
+ }
+ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
if (r)
goto err;
+ if (dsi.ulps_enabled) {
+ /* Keep Mark-1 state for 1ms (as per DSI spec) */
+ ktime_t wait = ns_to_ktime(1000 * 1000);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
+
+ /* Disable the override. The lanes should be set to Mark-11
+ * state by the HW */
+ dsi_disable_lane_override();
+ }
+
+ /* FORCE_TX_STOP_MODE_IO */
+ REG_FLD_MOD(DSI_TIMING1, 0, 15, 15);
+
if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
DSSERR("ComplexIO not coming out of reset.\n");
r = -ENODEV;
@@ -1954,23 +1998,7 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
dsi_complexio_timings();
- /*
- The configuration of the DSI complex I/O (number of data lanes,
- position, differential order) should not be changed while
- DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
- hardware to recognize a new configuration of the complex I/O (done
- in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
- this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
- reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
- LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
- bit to 1. If the sequence is not followed, the DSi complex I/O
- configuration is undetermined.
- */
- dsi_if_enable(1);
- dsi_if_enable(0);
- REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
- dsi_if_enable(1);
- dsi_if_enable(0);
+ dsi.ulps_enabled = false;
DSSDBG("CIO init done\n");
err:
@@ -2793,6 +2821,80 @@ int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
}
EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
+static int dsi_enter_ulps(void)
+{
+ DECLARE_COMPLETION_ONSTACK(completion);
+ int r;
+
+ DSSDBGF();
+
+ WARN_ON(!dsi_bus_is_locked());
+
+ WARN_ON(dsi.ulps_enabled);
+
+ if (dsi.ulps_enabled)
+ return 0;
+
+ if (REG_GET(DSI_CLK_CTRL, 13, 13)) {
+ DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n");
+ return -EIO;
+ }
+
+ dsi_sync_vc(0);
+ dsi_sync_vc(1);
+ dsi_sync_vc(2);
+ dsi_sync_vc(3);
+
+ dsi_force_tx_stop_mode_io();
+
+ dsi_vc_enable(0, false);
+ dsi_vc_enable(1, false);
+ dsi_vc_enable(2, false);
+ dsi_vc_enable(3, false);
+
+ if (REG_GET(DSI_COMPLEXIO_CFG2, 16, 16)) { /* HS_BUSY */
+ DSSERR("HS busy when enabling ULPS\n");
+ return -EIO;
+ }
+
+ if (REG_GET(DSI_COMPLEXIO_CFG2, 17, 17)) { /* LP_BUSY */
+ DSSERR("LP busy when enabling ULPS\n");
+ return -EIO;
+ }
+
+ r = dsi_register_isr_cio(dsi_completion_handler, &completion,
+ DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
+ if (r)
+ return r;
+
+ /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
+ /* LANEx_ULPS_SIG2 */
+ REG_FLD_MOD(DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2), 7, 5);
+
+ if (wait_for_completion_timeout(&completion,
+ msecs_to_jiffies(1000)) = 0) {
+ DSSERR("ULPS enable timeout\n");
+ r = -EIO;
+ goto err;
+ }
+
+ dsi_unregister_isr_cio(dsi_completion_handler, &completion,
+ DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
+
+ dsi_complexio_power(DSI_COMPLEXIO_POWER_ULPS);
+
+ dsi_if_enable(false);
+
+ dsi.ulps_enabled = true;
+
+ return 0;
+
+err:
+ dsi_unregister_isr_cio(dsi_completion_handler, &completion,
+ DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
+ return r;
+}
+
static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16)
{
unsigned long fck;
@@ -3547,6 +3649,9 @@ err0:
static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
{
+ if (!dsi.ulps_enabled)
+ dsi_enter_ulps();
+
/* disable interface */
dsi_if_enable(0);
dsi_vc_enable(0, 0);
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 04/19] OMAP: DSS2: DSI: add option to leave DSI lanes powered on
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (2 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 03/19] OMAP: DSS2: DSI: implement ULPS enter and exit Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 05/19] OMAP: DSS2: DSI: rename complexio related functions Tomi Valkeinen
` (15 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
The DSI pins are powered by VDDS_DSI. If VDDS_DSI is off, the DSI pins
are floating even if they are pinmuxed to, say, safe mode and there's a
pull down/up.
This patch gives the panel drivers an option to leave the VDDS_DSI power
enabled while the DSS itself is turned off. This can be used to keep the
DSI lanes in a valid state while DSS is off, if the DSI pins are muxed
for pull down (not done in this patch).
There will be a slight power consumption increase (~100 uA?) when the
VDDS_DSI is left on, but because this option is used when the panel is
left on, the regulator consumption is negligible compared to panel power
consumption.
When the panel is fully turned off the VDDS_DSI is also turned off.
As an added bonus this will give us faster start up time when starting
up the DSS and the regulator is already enabled.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
arch/arm/plat-omap/include/plat/display.h | 3 +-
drivers/video/omap2/displays/panel-taal.c | 4 +-
drivers/video/omap2/dss/dpi.c | 4 +-
drivers/video/omap2/dss/dsi.c | 35 +++++++++++++++++++---------
drivers/video/omap2/dss/dss.h | 2 +-
5 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h
index 43b887b..205c6de 100644
--- a/arch/arm/plat-omap/include/plat/display.h
+++ b/arch/arm/plat-omap/include/plat/display.h
@@ -591,7 +591,8 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
-void omapdss_dsi_display_disable(struct omap_dss_device *dssdev);
+void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
+ bool disconnect_lanes);
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 490998f..74ce9f8 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -932,7 +932,7 @@ err:
taal_hw_reset(dssdev);
- omapdss_dsi_display_disable(dssdev);
+ omapdss_dsi_display_disable(dssdev, true);
err0:
return r;
}
@@ -955,7 +955,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)
taal_hw_reset(dssdev);
}
- omapdss_dsi_display_disable(dssdev);
+ omapdss_dsi_display_disable(dssdev, true);
td->enabled = 0;
}
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 17d28d7..ba0b8da 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -206,7 +206,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
err4:
if (dpi_use_dsi_pll(dssdev))
- dsi_pll_uninit();
+ dsi_pll_uninit(true);
err3:
if (dpi_use_dsi_pll(dssdev))
dss_clk_disable(DSS_CLK_SYSCK);
@@ -227,7 +227,7 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
if (dpi_use_dsi_pll(dssdev)) {
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
- dsi_pll_uninit();
+ dsi_pll_uninit(true);
dss_clk_disable(DSS_CLK_SYSCK);
}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 5303548..54fc0f6 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -246,6 +246,7 @@ static struct
struct dsi_clock_info current_cinfo;
+ bool vdds_dsi_enabled;
struct regulator *vdds_dsi_reg;
struct {
@@ -1445,9 +1446,12 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
enable_clocks(1);
dsi_enable_pll_clock(1);
- r = regulator_enable(dsi.vdds_dsi_reg);
- if (r)
- goto err0;
+ if (!dsi.vdds_dsi_enabled) {
+ r = regulator_enable(dsi.vdds_dsi_reg);
+ if (r)
+ goto err0;
+ dsi.vdds_dsi_enabled = true;
+ }
/* XXX PLL does not come out of reset without this... */
dispc_pck_free_enable(1);
@@ -1481,21 +1485,28 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
return 0;
err1:
- regulator_disable(dsi.vdds_dsi_reg);
+ if (dsi.vdds_dsi_enabled) {
+ regulator_disable(dsi.vdds_dsi_reg);
+ dsi.vdds_dsi_enabled = false;
+ }
err0:
enable_clocks(0);
dsi_enable_pll_clock(0);
return r;
}
-void dsi_pll_uninit(void)
+void dsi_pll_uninit(bool disconnect_lanes)
{
enable_clocks(0);
dsi_enable_pll_clock(0);
dsi.pll_locked = 0;
dsi_pll_power(DSI_PLL_POWER_OFF);
- regulator_disable(dsi.vdds_dsi_reg);
+ if (disconnect_lanes) {
+ WARN_ON(!dsi.vdds_dsi_enabled);
+ regulator_disable(dsi.vdds_dsi_reg);
+ dsi.vdds_dsi_enabled = false;
+ }
DSSDBG("PLL uninit done\n");
}
@@ -3642,12 +3653,13 @@ err2:
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK);
err1:
- dsi_pll_uninit();
+ dsi_pll_uninit(true);
err0:
return r;
}
-static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
+static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
+ bool disconnect_lanes)
{
if (!dsi.ulps_enabled)
dsi_enter_ulps();
@@ -3662,7 +3674,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK);
dsi_complexio_uninit();
- dsi_pll_uninit();
+ dsi_pll_uninit(disconnect_lanes);
}
static int dsi_core_init(void)
@@ -3731,7 +3743,8 @@ err0:
}
EXPORT_SYMBOL(omapdss_dsi_display_enable);
-void omapdss_dsi_display_disable(struct omap_dss_device *dssdev)
+void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
+ bool disconnect_lanes)
{
DSSDBG("dsi_display_disable\n");
@@ -3741,7 +3754,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev)
dsi_display_uninit_dispc(dssdev);
- dsi_display_uninit_dsi(dssdev);
+ dsi_display_uninit_dsi(dssdev, disconnect_lanes);
enable_clocks(0);
dsi_enable_pll_clock(0);
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index d3b5697..eea5c7d 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -294,7 +294,7 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
struct dispc_clock_info *dispc_cinfo);
int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
bool enable_hsdiv);
-void dsi_pll_uninit(void);
+void dsi_pll_uninit(bool disconnect_lanes);
void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
u32 fifo_size, enum omap_burst_size *burst_size,
u32 *fifo_low, u32 *fifo_high);
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 05/19] OMAP: DSS2: DSI: rename complexio related functions
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (3 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 04/19] OMAP: DSS2: DSI: add option to leave DSI lanes powered on Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 06/19] OMAP: DSS2: Add FEAT_DSI_REVERSE_TXCLKESC Tomi Valkeinen
` (14 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Rename ComplexIO from dsi_complexio_xxx to dsi_cio_xxx for brevity.
Also, add cio prefix for couple of functions that didn't have it, but
are cio related.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 38 +++++++++++++++++++-------------------
1 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 54fc0f6..61d9f3c 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1738,13 +1738,13 @@ void dsi_dump_regs(struct seq_file *s)
#undef DUMPREG
}
-enum dsi_complexio_power_state {
+enum dsi_cio_power_state {
DSI_COMPLEXIO_POWER_OFF = 0x0,
DSI_COMPLEXIO_POWER_ON = 0x1,
DSI_COMPLEXIO_POWER_ULPS = 0x2,
};
-static int dsi_complexio_power(enum dsi_complexio_power_state state)
+static int dsi_cio_power(enum dsi_cio_power_state state)
{
int t = 0;
@@ -1764,7 +1764,7 @@ static int dsi_complexio_power(enum dsi_complexio_power_state state)
return 0;
}
-static void dsi_complexio_config(struct omap_dss_device *dssdev)
+static void dsi_set_lane_config(struct omap_dss_device *dssdev)
{
u32 r;
@@ -1816,7 +1816,7 @@ static inline unsigned ddr2ns(unsigned ddr)
return ddr * 1000 * 1000 / (ddr_clk / 1000);
}
-static void dsi_complexio_timings(void)
+static void dsi_cio_timings(void)
{
u32 r;
u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
@@ -1886,7 +1886,7 @@ static void dsi_complexio_timings(void)
dsi_write_reg(DSI_DSIPHY_CFG2, r);
}
-static void dsi_enable_lane_override(struct omap_dss_device *dssdev,
+static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev,
enum dsi_lane lanes)
{
int clk_lane = dssdev->phy.dsi.clk_lane;
@@ -1927,7 +1927,7 @@ static void dsi_enable_lane_override(struct omap_dss_device *dssdev,
REG_FLD_MOD(DSI_DSIPHY_CFG10, 1, 27, 27); /* ENLPTXSCPDAT */
}
-static void dsi_disable_lane_override(void)
+static void dsi_cio_disable_lane_override(void)
{
/* Disable lane override */
REG_FLD_MOD(DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */
@@ -1935,12 +1935,12 @@ static void dsi_disable_lane_override(void)
REG_FLD_MOD(DSI_DSIPHY_CFG10, 0, 22, 17); /* REGLPTXSCPDAT4TO0DXDY */
}
-static int dsi_complexio_init(struct omap_dss_device *dssdev)
+static int dsi_cio_init(struct omap_dss_device *dssdev)
{
int r = 0;
u32 l;
- DSSDBG("dsi_complexio_init\n");
+ DSSDBGF();
if (dsi.ulps_enabled)
DSSDBG("manual ulps exit\n");
@@ -1956,7 +1956,7 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
goto err;
}
- dsi_complexio_config(dssdev);
+ dsi_set_lane_config(dssdev);
dsi_if_enable(true);
dsi_if_enable(false);
@@ -1979,11 +1979,11 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
* manually.
*/
- dsi_enable_lane_override(dssdev,
+ dsi_cio_enable_lane_override(dssdev,
DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P);
}
- r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
+ r = dsi_cio_power(DSI_COMPLEXIO_POWER_ON);
if (r)
goto err;
@@ -1995,7 +1995,7 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
/* Disable the override. The lanes should be set to Mark-11
* state by the HW */
- dsi_disable_lane_override();
+ dsi_cio_disable_lane_override();
}
/* FORCE_TX_STOP_MODE_IO */
@@ -2007,7 +2007,7 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
goto err;
}
- dsi_complexio_timings();
+ dsi_cio_timings();
dsi.ulps_enabled = false;
@@ -2016,9 +2016,9 @@ err:
return r;
}
-static void dsi_complexio_uninit(void)
+static void dsi_cio_uninit(void)
{
- dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
+ dsi_cio_power(DSI_COMPLEXIO_POWER_OFF);
}
static int _dsi_wait_reset(void)
@@ -2892,7 +2892,7 @@ static int dsi_enter_ulps(void)
dsi_unregister_isr_cio(dsi_completion_handler, &completion,
DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
- dsi_complexio_power(DSI_COMPLEXIO_POWER_ULPS);
+ dsi_cio_power(DSI_COMPLEXIO_POWER_ULPS);
dsi_if_enable(false);
@@ -3622,7 +3622,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
if (r)
goto err2;
- r = dsi_complexio_init(dssdev);
+ r = dsi_cio_init(dssdev);
if (r)
goto err2;
@@ -3648,7 +3648,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
return 0;
err3:
- dsi_complexio_uninit();
+ dsi_cio_uninit();
err2:
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK);
@@ -3673,7 +3673,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK);
- dsi_complexio_uninit();
+ dsi_cio_uninit();
dsi_pll_uninit(disconnect_lanes);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 06/19] OMAP: DSS2: Add FEAT_DSI_REVERSE_TXCLKESC
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (4 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 05/19] OMAP: DSS2: DSI: rename complexio related functions Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 07/19] OMAP: DSS2: DSI: fix _dsi_print_reset_status Tomi Valkeinen
` (13 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
OMAP3430 has RESETDONETXCLKESCx bits in the order following bitnumber
order for lanes 0, 1, 2: 28, 27, 26. OMAP3630 and later have them in
saner order: 24, 25, 26 (and 27, 28 for OMAP4).
This patch adds a dss_feature that can be used to differentiate between
those two orders of RESETDONETXCLKESCx bits.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dss_features.c | 2 +-
drivers/video/omap2/dss/dss_features.h | 1 +
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 5f3a7c4..502a953 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -253,7 +253,7 @@ static struct omap_dss_features omap3430_dss_features = {
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
- FEAT_DSI_PLL_FREQSEL,
+ FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
.num_mgrs = 2,
.num_ovls = 3,
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 1093e8d..5668fec 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -45,6 +45,7 @@ enum dss_feat_id {
FEAT_DSI_PLL_FREQSEL = 1 << 14,
FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15,
FEAT_DSI_VC_OCP_WIDTH = 1 << 16,
+ FEAT_DSI_REVERSE_TXCLKESC = 1 << 17,
};
/* DSS register field id */
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 07/19] OMAP: DSS2: DSI: fix _dsi_print_reset_status
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (5 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 06/19] OMAP: DSS2: Add FEAT_DSI_REVERSE_TXCLKESC Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 08/19] OMAP: DSS2: DSI: implement enable/disable SCP clk Tomi Valkeinen
` (12 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
The bits for TXCLKESCx reset have changed for OMAP3630 and OMAP4.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 17 +++++++++++++++--
1 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 61d9f3c..a6b6ca6 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -960,6 +960,7 @@ static inline void dsi_enable_pll_clock(bool enable)
static void _dsi_print_reset_status(void)
{
u32 l;
+ int b0, b1, b2;
if (!dss_debug)
return;
@@ -977,9 +978,21 @@ static void _dsi_print_reset_status(void)
l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
printk("CIO (%d) ", FLD_GET(l, 29, 29));
+ if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
+ b0 = 28;
+ b1 = 27;
+ b2 = 26;
+ } else {
+ b0 = 24;
+ b1 = 25;
+ b2 = 26;
+ }
+
l = dsi_read_reg(DSI_DSIPHY_CFG5);
- printk("PHY (%x, %d, %d, %d)\n",
- FLD_GET(l, 28, 26),
+ printk("PHY (%x%x%x, %d, %d, %d)\n",
+ FLD_GET(l, b0, b0),
+ FLD_GET(l, b1, b1),
+ FLD_GET(l, b2, b2),
FLD_GET(l, 29, 29),
FLD_GET(l, 30, 30),
FLD_GET(l, 31, 31));
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 08/19] OMAP: DSS2: DSI: implement enable/disable SCP clk
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (6 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 07/19] OMAP: DSS2: DSI: fix _dsi_print_reset_status Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 09/19] OMAP: DSS2: DSI: fix CIO init and uninit Tomi Valkeinen
` (11 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
SCP clock is needed for CIO on OMAP3, and for CIO and PLL on OMAP4.
Current driver enables the CIO clock always when DSI display is
initialized. However, if a DPI display tries to use DSI PLL, the SCP
clock is never enabled.
This patch implements simple ref counting enable/disable functions for
SCP clock.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 33 ++++++++++++++++++++++++++++-----
1 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index a6b6ca6..9a0f9e4 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -305,6 +305,8 @@ static struct
unsigned long regm_dispc_max, regm_dsi_max;
unsigned long fint_min, fint_max;
unsigned long lpdiv_max;
+
+ unsigned scp_clk_refcount;
} dsi;
#ifdef DEBUG
@@ -1073,6 +1075,18 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
return 0;
}
+static void dsi_enable_scp_clk(void)
+{
+ if (dsi.scp_clk_refcount++ = 0)
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); /* CIO_CLK_ICG */
+}
+
+static void dsi_disable_scp_clk(void)
+{
+ WARN_ON(dsi.scp_clk_refcount = 0);
+ if (--dsi.scp_clk_refcount = 0)
+ REG_FLD_MOD(DSI_CLK_CTRL, 0, 14, 14); /* CIO_CLK_ICG */
+}
enum dsi_pll_power_state {
DSI_PLL_POWER_OFF = 0x0,
@@ -1458,6 +1472,10 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
enable_clocks(1);
dsi_enable_pll_clock(1);
+ /*
+ * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
+ */
+ dsi_enable_scp_clk();
if (!dsi.vdds_dsi_enabled) {
r = regulator_enable(dsi.vdds_dsi_reg);
@@ -1503,6 +1521,7 @@ err1:
dsi.vdds_dsi_enabled = false;
}
err0:
+ dsi_disable_scp_clk();
enable_clocks(0);
dsi_enable_pll_clock(0);
return r;
@@ -1510,9 +1529,6 @@ err0:
void dsi_pll_uninit(bool disconnect_lanes)
{
- enable_clocks(0);
- dsi_enable_pll_clock(0);
-
dsi.pll_locked = 0;
dsi_pll_power(DSI_PLL_POWER_OFF);
if (disconnect_lanes) {
@@ -1520,6 +1536,11 @@ void dsi_pll_uninit(bool disconnect_lanes)
regulator_disable(dsi.vdds_dsi_reg);
dsi.vdds_dsi_enabled = false;
}
+
+ dsi_disable_scp_clk();
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+
DSSDBG("PLL uninit done\n");
}
@@ -3611,8 +3632,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
int r;
/* The SCPClk is required for both PLL and CIO registers on OMAP4 */
- /* CIO_CLK_ICG, enable L3 clk to CIO */
- REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
+ dsi_enable_scp_clk();
_dsi_print_reset_status();
@@ -3668,6 +3688,7 @@ err2:
err1:
dsi_pll_uninit(true);
err0:
+ dsi_disable_scp_clk();
return r;
}
@@ -3688,6 +3709,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK);
dsi_cio_uninit();
dsi_pll_uninit(disconnect_lanes);
+ dsi_disable_scp_clk();
}
static int dsi_core_init(void)
@@ -4013,6 +4035,7 @@ err_dsi:
static int omap_dsi1hw_remove(struct platform_device *pdev)
{
dsi_exit();
+ WARN_ON(dsi.scp_clk_refcount > 0);
return 0;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 09/19] OMAP: DSS2: DSI: fix CIO init and uninit
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (7 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 08/19] OMAP: DSS2: DSI: implement enable/disable SCP clk Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 10/19] OMAP: DSS2: DSI: wait for TXCLKESC domain to come out of reset Tomi Valkeinen
` (10 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Use dsi_enable_scp_clk and dsi_disable_scp_clk in CIO init and uninit,
and improve the CIO init by adding a few status checks and error
handling.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 54 ++++++++++++++++++++++-------------------
1 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 9a0f9e4..9f450af 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1971,13 +1971,12 @@ static void dsi_cio_disable_lane_override(void)
static int dsi_cio_init(struct omap_dss_device *dssdev)
{
- int r = 0;
+ int r;
u32 l;
DSSDBGF();
- if (dsi.ulps_enabled)
- DSSDBG("manual ulps exit\n");
+ dsi_enable_scp_clk();
/* A dummy read using the SCP interface to any DSIPHY register is
* required after DSIPHY reset to complete the reset of the DSI complex
@@ -1985,17 +1984,13 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
dsi_read_reg(DSI_DSIPHY_CFG5);
if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
- DSSERR("ComplexIO PHY not coming out of reset.\n");
- r = -ENODEV;
- goto err;
+ DSSERR("CIO SCP Clock domain not coming out of reset.\n");
+ r = -EIO;
+ goto err_scp_clk_dom;
}
dsi_set_lane_config(dssdev);
- dsi_if_enable(true);
- dsi_if_enable(false);
- REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
-
/* set TX STOP MODE timer to maximum for this operation */
l = dsi_read_reg(DSI_TIMING1);
l = FLD_MOD(l, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
@@ -2005,6 +2000,8 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
dsi_write_reg(DSI_TIMING1, l);
if (dsi.ulps_enabled) {
+ DSSDBG("manual ulps exit\n");
+
/* ULPS is exited by Mark-1 state for 1ms, followed by
* stop state. DSS HW cannot do this via the normal
* ULPS exit sequence, as after reset the DSS HW thinks
@@ -2019,7 +2016,17 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
r = dsi_cio_power(DSI_COMPLEXIO_POWER_ON);
if (r)
- goto err;
+ goto err_cio_pwr;
+
+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
+ DSSERR("CIO PWR clock domain not coming out of reset.\n");
+ r = -ENODEV;
+ goto err_cio_pwr_dom;
+ }
+
+ dsi_if_enable(true);
+ dsi_if_enable(false);
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
if (dsi.ulps_enabled) {
/* Keep Mark-1 state for 1ms (as per DSI spec) */
@@ -2035,24 +2042,28 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
/* FORCE_TX_STOP_MODE_IO */
REG_FLD_MOD(DSI_TIMING1, 0, 15, 15);
- if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
- DSSERR("ComplexIO not coming out of reset.\n");
- r = -ENODEV;
- goto err;
- }
-
dsi_cio_timings();
dsi.ulps_enabled = false;
DSSDBG("CIO init done\n");
-err:
+
+ return 0;
+
+err_cio_pwr_dom:
+ dsi_cio_power(DSI_COMPLEXIO_POWER_OFF);
+err_cio_pwr:
+ if (dsi.ulps_enabled)
+ dsi_cio_disable_lane_override();
+err_scp_clk_dom:
+ dsi_disable_scp_clk();
return r;
}
static void dsi_cio_uninit(void)
{
dsi_cio_power(DSI_COMPLEXIO_POWER_OFF);
+ dsi_disable_scp_clk();
}
static int _dsi_wait_reset(void)
@@ -3631,11 +3642,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
{
int r;
- /* The SCPClk is required for both PLL and CIO registers on OMAP4 */
- dsi_enable_scp_clk();
-
- _dsi_print_reset_status();
-
r = dsi_pll_init(dssdev, true, true);
if (r)
goto err0;
@@ -3688,7 +3694,6 @@ err2:
err1:
dsi_pll_uninit(true);
err0:
- dsi_disable_scp_clk();
return r;
}
@@ -3709,7 +3714,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK);
dsi_cio_uninit();
dsi_pll_uninit(disconnect_lanes);
- dsi_disable_scp_clk();
}
static int dsi_core_init(void)
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 10/19] OMAP: DSS2: DSI: wait for TXCLKESC domain to come out of reset
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (8 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 09/19] OMAP: DSS2: DSI: fix CIO init and uninit Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 11/19] OMAP: DSS2: DSI: add parameter to enter ulps on disable Tomi Valkeinen
` (9 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Add dsi_cio_wait_tx_clk_esc_reset() function which waits for the
TXCLKESC domains to come out of reset.
Things have worked fine without this, but better be safe than sorry.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 65 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 9f450af..8d85635 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1969,6 +1969,65 @@ static void dsi_cio_disable_lane_override(void)
REG_FLD_MOD(DSI_DSIPHY_CFG10, 0, 22, 17); /* REGLPTXSCPDAT4TO0DXDY */
}
+static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
+{
+ int t;
+ int bits[3];
+ bool in_use[3];
+
+ if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
+ bits[0] = 28;
+ bits[1] = 27;
+ bits[2] = 26;
+ } else {
+ bits[0] = 24;
+ bits[1] = 25;
+ bits[2] = 26;
+ }
+
+ in_use[0] = false;
+ in_use[1] = false;
+ in_use[2] = false;
+
+ if (dssdev->phy.dsi.clk_lane != 0)
+ in_use[dssdev->phy.dsi.clk_lane - 1] = true;
+ if (dssdev->phy.dsi.data1_lane != 0)
+ in_use[dssdev->phy.dsi.data1_lane - 1] = true;
+ if (dssdev->phy.dsi.data2_lane != 0)
+ in_use[dssdev->phy.dsi.data2_lane - 1] = true;
+
+ t = 100000;
+ while (true) {
+ u32 l;
+ int i;
+ int ok;
+
+ l = dsi_read_reg(DSI_DSIPHY_CFG5);
+
+ ok = 0;
+ for (i = 0; i < 3; ++i) {
+ if (!in_use[i] || (l & (1 << bits[i])))
+ ok++;
+ }
+
+ if (ok = 3)
+ break;
+
+ if (--t = 0) {
+ for (i = 0; i < 3; ++i) {
+ if (!in_use[i] || (l & (1 << bits[i])))
+ continue;
+
+ DSSERR("CIO TXCLKESC%d domain not coming " \
+ "out of reset\n", i);
+ }
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
static int dsi_cio_init(struct omap_dss_device *dssdev)
{
int r;
@@ -2028,6 +2087,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
dsi_if_enable(false);
REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
+ r = dsi_cio_wait_tx_clk_esc_reset(dssdev);
+ if (r)
+ goto err_tx_clk_esc_rst;
+
if (dsi.ulps_enabled) {
/* Keep Mark-1 state for 1ms (as per DSI spec) */
ktime_t wait = ns_to_ktime(1000 * 1000);
@@ -2050,6 +2113,8 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
return 0;
+err_tx_clk_esc_rst:
+ REG_FLD_MOD(DSI_CLK_CTRL, 0, 20, 20); /* LP_CLK_ENABLE */
err_cio_pwr_dom:
dsi_cio_power(DSI_COMPLEXIO_POWER_OFF);
err_cio_pwr:
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 11/19] OMAP: DSS2: DSI: add parameter to enter ulps on disable
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (9 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 10/19] OMAP: DSS2: DSI: wait for TXCLKESC domain to come out of reset Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 12/19] OMAP: DSS2: DSI: Add DSI pad muxing support Tomi Valkeinen
` (8 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Add parameter to omapdss_dsi_display_disable() which the panel driver
can use to tell if the DSI lanes should be put to ULPS before disabling
the interface.
This can be used to skip ULPS entry in cases where the panel doesn't
care about ULPS state, for example when the panel will be reset, or when
the display interface will be enabled again right after the disable.
This will speed up the operation considerably in cases where entering
ULPS would fail with timeout, and the panel driver isn't even interested
in entering ULPS.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
arch/arm/plat-omap/include/plat/display.h | 2 +-
drivers/video/omap2/displays/panel-taal.c | 4 ++--
drivers/video/omap2/dss/dsi.c | 8 ++++----
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h
index 205c6de..a65479c 100644
--- a/arch/arm/plat-omap/include/plat/display.h
+++ b/arch/arm/plat-omap/include/plat/display.h
@@ -592,7 +592,7 @@ void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
- bool disconnect_lanes);
+ bool disconnect_lanes, bool enter_ulps);
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 74ce9f8..d68119e 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -932,7 +932,7 @@ err:
taal_hw_reset(dssdev);
- omapdss_dsi_display_disable(dssdev, true);
+ omapdss_dsi_display_disable(dssdev, true, false);
err0:
return r;
}
@@ -955,7 +955,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)
taal_hw_reset(dssdev);
}
- omapdss_dsi_display_disable(dssdev, true);
+ omapdss_dsi_display_disable(dssdev, true, false);
td->enabled = 0;
}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 8d85635..d15014e 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3763,9 +3763,9 @@ err0:
}
static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
- bool disconnect_lanes)
+ bool disconnect_lanes, bool enter_ulps)
{
- if (!dsi.ulps_enabled)
+ if (enter_ulps && !dsi.ulps_enabled)
dsi_enter_ulps();
/* disable interface */
@@ -3848,7 +3848,7 @@ err0:
EXPORT_SYMBOL(omapdss_dsi_display_enable);
void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
- bool disconnect_lanes)
+ bool disconnect_lanes, bool enter_ulps)
{
DSSDBG("dsi_display_disable\n");
@@ -3858,7 +3858,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
dsi_display_uninit_dispc(dssdev);
- dsi_display_uninit_dsi(dssdev, disconnect_lanes);
+ dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
enable_clocks(0);
dsi_enable_pll_clock(0);
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 12/19] OMAP: DSS2: DSI: Add DSI pad muxing support
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (10 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 11/19] OMAP: DSS2: DSI: add parameter to enter ulps on disable Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 13/19] OMAP: DSS2: DSI: ensure VDDS_DSI is disabled on exit Tomi Valkeinen
` (7 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Add dsi_mux_pads function pointer to omap_dss_board_info, and use the
function pointer in DSI code to configure the DSI pads either to normal
DSI operation, or to pull down when in ULPS.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
arch/arm/plat-omap/include/plat/display.h | 1 +
drivers/video/omap2/dss/dsi.c | 15 +++++++++++++++
2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h
index a65479c..bd0f08e 100644
--- a/arch/arm/plat-omap/include/plat/display.h
+++ b/arch/arm/plat-omap/include/plat/display.h
@@ -235,6 +235,7 @@ struct omap_dss_board_info {
int num_devices;
struct omap_dss_device **devices;
struct omap_dss_device *default_device;
+ void (*dsi_mux_pads)(bool enable);
};
#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index d15014e..f1e14ca 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -244,6 +244,8 @@ static struct
void __iomem *base;
int irq;
+ void (*dsi_mux_pads)(bool enable);
+
struct dsi_clock_info current_cinfo;
bool vdds_dsi_enabled;
@@ -2035,6 +2037,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
DSSDBGF();
+ if (dsi.dsi_mux_pads)
+ dsi.dsi_mux_pads(true);
+
dsi_enable_scp_clk();
/* A dummy read using the SCP interface to any DSIPHY register is
@@ -2122,6 +2127,8 @@ err_cio_pwr:
dsi_cio_disable_lane_override();
err_scp_clk_dom:
dsi_disable_scp_clk();
+ if (dsi.dsi_mux_pads)
+ dsi.dsi_mux_pads(false);
return r;
}
@@ -2129,6 +2136,8 @@ static void dsi_cio_uninit(void)
{
dsi_cio_power(DSI_COMPLEXIO_POWER_OFF);
dsi_disable_scp_clk();
+ if (dsi.dsi_mux_pads)
+ dsi.dsi_mux_pads(false);
}
static int _dsi_wait_reset(void)
@@ -3993,10 +4002,16 @@ static void dsi_calc_clock_param_ranges(void)
static int dsi_init(struct platform_device *pdev)
{
+ struct omap_display_platform_data *dss_plat_data;
+ struct omap_dss_board_info *board_info;
u32 rev;
int r, i;
struct resource *dsi_mem;
+ dss_plat_data = pdev->dev.platform_data;
+ board_info = dss_plat_data->board_data;
+ dsi.dsi_mux_pads = board_info->dsi_mux_pads;
+
spin_lock_init(&dsi.irq_lock);
spin_lock_init(&dsi.errors_lock);
dsi.errors = 0;
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 13/19] OMAP: DSS2: DSI: ensure VDDS_DSI is disabled on exit
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (11 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 12/19] OMAP: DSS2: DSI: Add DSI pad muxing support Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 14/19] OMAP: DSS2: Taal: Implement configurable ESD interval Tomi Valkeinen
` (6 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
The panel drivers can leave the VDDS_DSI regulator enabled, even when
the panel is disabled, to ensure that the DSI pins are powered.
This patch ensures that VDDS_DSI is disabled on DSI module unload.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dsi.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index f1e14ca..9c5715a 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4090,6 +4090,11 @@ err1:
static void dsi_exit(void)
{
if (dsi.vdds_dsi_reg != NULL) {
+ if (dsi.vdds_dsi_enabled) {
+ regulator_disable(dsi.vdds_dsi_reg);
+ dsi.vdds_dsi_enabled = false;
+ }
+
regulator_put(dsi.vdds_dsi_reg);
dsi.vdds_dsi_reg = NULL;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 14/19] OMAP: DSS2: Taal: Implement configurable ESD interval
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (12 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 13/19] OMAP: DSS2: DSI: ensure VDDS_DSI is disabled on exit Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 15/19] OMAP: DSS2: Taal: Clean up ESD queueing Tomi Valkeinen
` (5 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
ESD check in Taal driver is currently on/off feature with hardcoded
interval. This patch changes it to a configurable interval, which can be
set from the board file.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
arch/arm/mach-omap2/board-4430sdp.c | 2 +-
arch/arm/plat-omap/include/plat/nokia-dsi-panel.h | 4 ++--
drivers/video/omap2/displays/panel-taal.c | 20 ++++++++++----------
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 1503f0b..570e83f 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -753,7 +753,7 @@ static struct nokia_dsi_panel_data dsi1_panel = {
.reset_gpio = 102,
.use_ext_te = false,
.ext_te_gpio = 101,
- .use_esd_check = false,
+ .esd_interval = 0,
.set_backlight = dsi1_panel_set_backlight,
};
diff --git a/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h b/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h
index 01ab657..aaa1c14 100644
--- a/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h
+++ b/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h
@@ -8,7 +8,7 @@
* @name: panel name
* @use_ext_te: use external TE
* @ext_te_gpio: external TE GPIO
- * @use_esd_check: perform ESD checks
+ * @esd_interval: interval of ESD checks, 0 = disabled (ms)
* @max_backlight_level: maximum backlight level
* @set_backlight: pointer to backlight set function
* @get_backlight: pointer to backlight get function
@@ -21,7 +21,7 @@ struct nokia_dsi_panel_data {
bool use_ext_te;
int ext_te_gpio;
- bool use_esd_check;
+ unsigned esd_interval;
int max_backlight_level;
int (*set_backlight)(struct omap_dss_device *dssdev, int level);
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index d68119e..cdb28a8 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -63,8 +63,6 @@
#define DCS_GET_ID2 0xdb
#define DCS_GET_ID3 0xdc
-#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
-
static irqreturn_t taal_te_isr(int irq, void *data);
static void taal_te_timeout_work_callback(struct work_struct *work);
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
@@ -231,6 +229,7 @@ struct taal_data {
struct workqueue_struct *esd_wq;
struct delayed_work esd_work;
+ unsigned esd_interval;
struct panel_config *panel_config;
};
@@ -700,6 +699,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
}
td->dssdev = dssdev;
td->panel_config = panel_config;
+ td->esd_interval = panel_data->esd_interval;
mutex_init(&td->lock);
@@ -963,7 +963,6 @@ static void taal_power_off(struct omap_dss_device *dssdev)
static int taal_enable(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
- struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
dev_dbg(&dssdev->dev, "enable\n");
@@ -984,9 +983,9 @@ static int taal_enable(struct omap_dss_device *dssdev)
if (r)
goto err;
- if (panel_data->use_esd_check)
+ if (td->esd_interval > 0)
queue_delayed_work(td->esd_wq, &td->esd_work,
- TAAL_ESD_CHECK_PERIOD);
+ msecs_to_jiffies(td->esd_interval));
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
@@ -1056,7 +1055,6 @@ err:
static int taal_resume(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
- struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
dev_dbg(&dssdev->dev, "resume\n");
@@ -1078,9 +1076,9 @@ static int taal_resume(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
} else {
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
- if (panel_data->use_esd_check)
+ if (td->esd_interval > 0)
queue_delayed_work(td->esd_wq, &td->esd_work,
- TAAL_ESD_CHECK_PERIOD);
+ msecs_to_jiffies(td->esd_interval));
}
mutex_unlock(&td->lock);
@@ -1523,7 +1521,8 @@ static void taal_esd_work(struct work_struct *work)
dsi_bus_unlock();
- queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
+ queue_delayed_work(td->esd_wq, &td->esd_work,
+ msecs_to_jiffies(td->esd_interval));
mutex_unlock(&td->lock);
return;
@@ -1536,7 +1535,8 @@ err:
dsi_bus_unlock();
- queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
+ queue_delayed_work(td->esd_wq, &td->esd_work,
+ msecs_to_jiffies(td->esd_interval));
mutex_unlock(&td->lock);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 15/19] OMAP: DSS2: Taal: Clean up ESD queueing
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (13 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 14/19] OMAP: DSS2: Taal: Implement configurable ESD interval Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 16/19] OMAP: DSS2: Taal: Add sysfs file for ESD interval Tomi Valkeinen
` (4 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Separate the code which queues/cancels ESD work into their own
functions.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/displays/panel-taal.c | 36 ++++++++++++++++++----------
1 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index cdb28a8..2787a51 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -420,6 +420,22 @@ static int taal_set_update_window(struct taal_data *td,
return r;
}
+static void taal_queue_esd_work(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+ if (td->esd_interval > 0)
+ queue_delayed_work(td->esd_wq, &td->esd_work,
+ msecs_to_jiffies(td->esd_interval));
+}
+
+static void taal_cancel_esd_work(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+ cancel_delayed_work(&td->esd_work);
+}
+
static int taal_bl_update_status(struct backlight_device *dev)
{
struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
@@ -841,7 +857,7 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
taal_bl_update_status(bldev);
backlight_device_unregister(bldev);
- cancel_delayed_work(&td->esd_work);
+ taal_cancel_esd_work(dssdev);
destroy_workqueue(td->esd_wq);
/* reset, to be sure that the panel is in a valid state */
@@ -983,9 +999,7 @@ static int taal_enable(struct omap_dss_device *dssdev)
if (r)
goto err;
- if (td->esd_interval > 0)
- queue_delayed_work(td->esd_wq, &td->esd_work,
- msecs_to_jiffies(td->esd_interval));
+ taal_queue_esd_work(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
@@ -1006,7 +1020,7 @@ static void taal_disable(struct omap_dss_device *dssdev)
mutex_lock(&td->lock);
- cancel_delayed_work(&td->esd_work);
+ taal_cancel_esd_work(dssdev);
dsi_bus_lock();
@@ -1034,7 +1048,7 @@ static int taal_suspend(struct omap_dss_device *dssdev)
goto err;
}
- cancel_delayed_work(&td->esd_work);
+ taal_cancel_esd_work(dssdev);
dsi_bus_lock();
@@ -1076,9 +1090,7 @@ static int taal_resume(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
} else {
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
- if (td->esd_interval > 0)
- queue_delayed_work(td->esd_wq, &td->esd_work,
- msecs_to_jiffies(td->esd_interval));
+ taal_queue_esd_work(dssdev);
}
mutex_unlock(&td->lock);
@@ -1521,8 +1533,7 @@ static void taal_esd_work(struct work_struct *work)
dsi_bus_unlock();
- queue_delayed_work(td->esd_wq, &td->esd_work,
- msecs_to_jiffies(td->esd_interval));
+ taal_queue_esd_work(dssdev);
mutex_unlock(&td->lock);
return;
@@ -1535,8 +1546,7 @@ err:
dsi_bus_unlock();
- queue_delayed_work(td->esd_wq, &td->esd_work,
- msecs_to_jiffies(td->esd_interval));
+ taal_queue_esd_work(dssdev);
mutex_unlock(&td->lock);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 16/19] OMAP: DSS2: Taal: Add sysfs file for ESD interval
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (14 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 15/19] OMAP: DSS2: Taal: Clean up ESD queueing Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 17/19] OMAP: DSS2: Taal: Separate panel reset Tomi Valkeinen
` (3 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Implement sysfs support to configure the ESD interval.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/displays/panel-taal.c | 42 +++++++++++++++++++++++++++++
1 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 2787a51..3192dd7 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -635,18 +635,60 @@ static ssize_t show_cabc_available_modes(struct device *dev,
return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
}
+static ssize_t taal_store_esd_interval(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+ unsigned long t;
+ int r;
+
+ r = strict_strtoul(buf, 10, &t);
+ if (r)
+ return r;
+
+ mutex_lock(&td->lock);
+ taal_cancel_esd_work(dssdev);
+ td->esd_interval = t;
+ if (td->enabled)
+ taal_queue_esd_work(dssdev);
+ mutex_unlock(&td->lock);
+
+ return count;
+}
+
+static ssize_t taal_show_esd_interval(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ unsigned t;
+
+ mutex_lock(&td->lock);
+ t = td->esd_interval;
+ mutex_unlock(&td->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", t);
+}
+
static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
show_cabc_mode, store_cabc_mode);
static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
show_cabc_available_modes, NULL);
+static DEVICE_ATTR(esd_interval, S_IRUGO | S_IWUSR,
+ taal_show_esd_interval, taal_store_esd_interval);
static struct attribute *taal_attrs[] = {
&dev_attr_num_dsi_errors.attr,
&dev_attr_hw_revision.attr,
&dev_attr_cabc_mode.attr,
&dev_attr_cabc_available_modes.attr,
+ &dev_attr_esd_interval.attr,
NULL,
};
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 17/19] OMAP: DSS2: Taal: Separate panel reset
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (15 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 16/19] OMAP: DSS2: Taal: Add sysfs file for ESD interval Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 18/19] OMAP: DSS2: Taal: Rename esd_wq to workqueue Tomi Valkeinen
` (2 subsequent siblings)
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Separate panel reset code to a function of its own. This will keep the
code cleaner in the future when panel reset is called from multiple
locations.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/displays/panel-taal.c | 13 ++++++++++---
1 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 3192dd7..2f7a223 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1018,6 +1018,15 @@ static void taal_power_off(struct omap_dss_device *dssdev)
td->enabled = 0;
}
+static int taal_panel_reset(struct omap_dss_device *dssdev)
+{
+ dev_err(&dssdev->dev, "performing LCD reset\n");
+
+ taal_power_off(dssdev);
+ taal_hw_reset(dssdev);
+ return taal_power_on(dssdev);
+}
+
static int taal_enable(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
@@ -1582,9 +1591,7 @@ static void taal_esd_work(struct work_struct *work)
err:
dev_err(&dssdev->dev, "performing LCD reset\n");
- taal_power_off(dssdev);
- taal_hw_reset(dssdev);
- taal_power_on(dssdev);
+ taal_panel_reset(dssdev);
dsi_bus_unlock();
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 18/19] OMAP: DSS2: Taal: Rename esd_wq to workqueue
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (16 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 17/19] OMAP: DSS2: Taal: Separate panel reset Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-19 9:22 ` [PATCH 19/19] OMAP: DSS2: Taal: Implement ULPS functionality Tomi Valkeinen
2011-04-20 5:55 ` [PATCH 00/19] OMAP: DSS2: ULPS support Archit Taneja
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
ESD workqueue will be shared with other functionality also. Rename
"esd_wq" to "workqueue" to better reflect its usage.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/displays/panel-taal.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 2f7a223..9626e49 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -227,7 +227,8 @@ struct taal_data {
bool intro_printed;
- struct workqueue_struct *esd_wq;
+ struct workqueue_struct *workqueue;
+
struct delayed_work esd_work;
unsigned esd_interval;
@@ -425,7 +426,7 @@ static void taal_queue_esd_work(struct omap_dss_device *dssdev)
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
if (td->esd_interval > 0)
- queue_delayed_work(td->esd_wq, &td->esd_work,
+ queue_delayed_work(td->workqueue, &td->esd_work,
msecs_to_jiffies(td->esd_interval));
}
@@ -768,8 +769,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
if (r)
goto err_reg;
- td->esd_wq = create_singlethread_workqueue("taal_esd");
- if (td->esd_wq = NULL) {
+ td->workqueue = create_singlethread_workqueue("taal_esd");
+ if (td->workqueue = NULL) {
dev_err(&dssdev->dev, "can't create ESD workqueue\n");
r = -ENOMEM;
goto err_wq;
@@ -868,7 +869,7 @@ err_irq:
err_gpio:
backlight_device_unregister(bldev);
err_bl:
- destroy_workqueue(td->esd_wq);
+ destroy_workqueue(td->workqueue);
err_wq:
free_regulators(panel_config->regulators, panel_config->num_regulators);
err_reg:
@@ -900,7 +901,7 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
backlight_device_unregister(bldev);
taal_cancel_esd_work(dssdev);
- destroy_workqueue(td->esd_wq);
+ destroy_workqueue(td->workqueue);
/* reset, to be sure that the panel is in a valid state */
taal_hw_reset(dssdev);
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 19/19] OMAP: DSS2: Taal: Implement ULPS functionality
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (17 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 18/19] OMAP: DSS2: Taal: Rename esd_wq to workqueue Tomi Valkeinen
@ 2011-04-19 9:22 ` Tomi Valkeinen
2011-04-20 5:55 ` [PATCH 00/19] OMAP: DSS2: ULPS support Archit Taneja
19 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-19 9:22 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
ULPS is a low power state where the DSI lanes are kept at ground. This
patch implements ULPS by having a DSI bus inactivity timer which
triggers the entry to ULPS. ULPS exit will happen automatically when the
driver needs to do something on the DSI lanes.
The ulps_timeout is configurable from board file or via sysfs.
Additionally another sysfs file, "ulps", can be used to check the
current ULPS state, or to manually enter or exit ULPS.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
arch/arm/plat-omap/include/plat/nokia-dsi-panel.h | 2 +
drivers/video/omap2/displays/panel-taal.c | 310 ++++++++++++++++++++-
2 files changed, 305 insertions(+), 7 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h b/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h
index aaa1c14..36ba7bd 100644
--- a/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h
+++ b/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h
@@ -9,6 +9,7 @@
* @use_ext_te: use external TE
* @ext_te_gpio: external TE GPIO
* @esd_interval: interval of ESD checks, 0 = disabled (ms)
+ * @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms)
* @max_backlight_level: maximum backlight level
* @set_backlight: pointer to backlight set function
* @get_backlight: pointer to backlight get function
@@ -22,6 +23,7 @@ struct nokia_dsi_panel_data {
int ext_te_gpio;
unsigned esd_interval;
+ unsigned ulps_timeout;
int max_backlight_level;
int (*set_backlight)(struct omap_dss_device *dssdev, int level);
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 9626e49..78ad355 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -67,6 +67,8 @@ static irqreturn_t taal_te_isr(int irq, void *data);
static void taal_te_timeout_work_callback(struct work_struct *work);
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
+static int taal_panel_reset(struct omap_dss_device *dssdev);
+
struct panel_regulator {
struct regulator *regulator;
const char *name;
@@ -232,6 +234,10 @@ struct taal_data {
struct delayed_work esd_work;
unsigned esd_interval;
+ bool ulps_enabled;
+ unsigned ulps_timeout;
+ struct delayed_work ulps_work;
+
struct panel_config *panel_config;
};
@@ -242,6 +248,7 @@ static inline struct nokia_dsi_panel_data
}
static void taal_esd_work(struct work_struct *work);
+static void taal_ulps_work(struct work_struct *work);
static void hw_guard_start(struct taal_data *td, int guard_msec)
{
@@ -437,6 +444,107 @@ static void taal_cancel_esd_work(struct omap_dss_device *dssdev)
cancel_delayed_work(&td->esd_work);
}
+static void taal_queue_ulps_work(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+ if (td->ulps_timeout > 0)
+ queue_delayed_work(td->workqueue, &td->ulps_work,
+ msecs_to_jiffies(td->ulps_timeout));
+}
+
+static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+ cancel_delayed_work(&td->ulps_work);
+}
+
+static int taal_enter_ulps(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
+ int r;
+
+ if (td->ulps_enabled)
+ return 0;
+
+ taal_cancel_ulps_work(dssdev);
+
+ r = _taal_enable_te(dssdev, false);
+ if (r)
+ goto err;
+
+ disable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+
+ omapdss_dsi_display_disable(dssdev, false, true);
+
+ td->ulps_enabled = true;
+
+ return 0;
+
+err:
+ dev_err(&dssdev->dev, "enter ULPS failed");
+ taal_panel_reset(dssdev);
+
+ td->ulps_enabled = false;
+
+ taal_queue_ulps_work(dssdev);
+
+ return r;
+}
+
+static int taal_exit_ulps(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
+ int r;
+
+ if (!td->ulps_enabled)
+ return 0;
+
+ r = omapdss_dsi_display_enable(dssdev);
+ if (r)
+ goto err;
+
+ omapdss_dsi_vc_enable_hs(td->channel, true);
+
+ r = _taal_enable_te(dssdev, true);
+ if (r)
+ goto err;
+
+ enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+
+ taal_queue_ulps_work(dssdev);
+
+ td->ulps_enabled = false;
+
+ return 0;
+
+err:
+ dev_err(&dssdev->dev, "exit ULPS failed");
+ r = taal_panel_reset(dssdev);
+
+ enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+ td->ulps_enabled = false;
+
+ taal_queue_ulps_work(dssdev);
+
+ return r;
+}
+
+static int taal_wake_up(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+ if (td->ulps_enabled)
+ return taal_exit_ulps(dssdev);
+
+ taal_cancel_ulps_work(dssdev);
+ taal_queue_ulps_work(dssdev);
+ return 0;
+}
+
static int taal_bl_update_status(struct backlight_device *dev)
{
struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
@@ -458,7 +566,11 @@ static int taal_bl_update_status(struct backlight_device *dev)
if (td->use_dsi_bl) {
if (td->enabled) {
dsi_bus_lock();
- r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
+
+ r = taal_wake_up(dssdev);
+ if (!r)
+ r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
+
dsi_bus_unlock();
} else {
r = 0;
@@ -521,7 +633,11 @@ static ssize_t taal_num_errors_show(struct device *dev,
if (td->enabled) {
dsi_bus_lock();
- r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors);
+
+ r = taal_wake_up(dssdev);
+ if (!r)
+ r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors);
+
dsi_bus_unlock();
} else {
r = -ENODEV;
@@ -547,7 +663,11 @@ static ssize_t taal_hw_revision_show(struct device *dev,
if (td->enabled) {
dsi_bus_lock();
- r = taal_get_id(td, &id1, &id2, &id3);
+
+ r = taal_wake_up(dssdev);
+ if (!r)
+ r = taal_get_id(td, &id1, &id2, &id3);
+
dsi_bus_unlock();
} else {
r = -ENODEV;
@@ -595,6 +715,7 @@ static ssize_t store_cabc_mode(struct device *dev,
struct omap_dss_device *dssdev = to_dss_device(dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
int i;
+ int r;
for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
if (sysfs_streq(cabc_modes[i], buf))
@@ -608,8 +729,17 @@ static ssize_t store_cabc_mode(struct device *dev,
if (td->enabled) {
dsi_bus_lock();
- if (!td->cabc_broken)
- taal_dcs_write_1(td, DCS_WRITE_CABC, i);
+
+ if (!td->cabc_broken) {
+ r = taal_wake_up(dssdev);
+ if (r)
+ goto err;
+
+ r = taal_dcs_write_1(td, DCS_WRITE_CABC, i);
+ if (r)
+ goto err;
+ }
+
dsi_bus_unlock();
}
@@ -618,6 +748,10 @@ static ssize_t store_cabc_mode(struct device *dev,
mutex_unlock(&td->lock);
return count;
+err:
+ dsi_bus_unlock();
+ mutex_unlock(&td->lock);
+ return r;
}
static ssize_t show_cabc_available_modes(struct device *dev,
@@ -675,6 +809,101 @@ static ssize_t taal_show_esd_interval(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%u\n", t);
}
+static ssize_t taal_store_ulps(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ unsigned long t;
+ int r;
+
+ r = strict_strtoul(buf, 10, &t);
+ if (r)
+ return r;
+
+ mutex_lock(&td->lock);
+
+ if (td->enabled) {
+ dsi_bus_lock();
+
+ if (t)
+ r = taal_enter_ulps(dssdev);
+ else
+ r = taal_wake_up(dssdev);
+
+ dsi_bus_unlock();
+ }
+
+ mutex_unlock(&td->lock);
+
+ if (r)
+ return r;
+
+ return count;
+}
+
+static ssize_t taal_show_ulps(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ unsigned t;
+
+ mutex_lock(&td->lock);
+ t = td->ulps_enabled;
+ mutex_unlock(&td->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", t);
+}
+
+static ssize_t taal_store_ulps_timeout(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ unsigned long t;
+ int r;
+
+ r = strict_strtoul(buf, 10, &t);
+ if (r)
+ return r;
+
+ mutex_lock(&td->lock);
+ td->ulps_timeout = t;
+
+ if (td->enabled) {
+ /* taal_wake_up will restart the timer */
+ dsi_bus_lock();
+ r = taal_wake_up(dssdev);
+ dsi_bus_unlock();
+ }
+
+ mutex_unlock(&td->lock);
+
+ if (r)
+ return r;
+
+ return count;
+}
+
+static ssize_t taal_show_ulps_timeout(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ unsigned t;
+
+ mutex_lock(&td->lock);
+ t = td->ulps_timeout;
+ mutex_unlock(&td->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", t);
+}
+
static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
@@ -683,6 +912,10 @@ static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
show_cabc_available_modes, NULL);
static DEVICE_ATTR(esd_interval, S_IRUGO | S_IWUSR,
taal_show_esd_interval, taal_store_esd_interval);
+static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
+ taal_show_ulps, taal_store_ulps);
+static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
+ taal_show_ulps_timeout, taal_store_ulps_timeout);
static struct attribute *taal_attrs[] = {
&dev_attr_num_dsi_errors.attr,
@@ -690,6 +923,8 @@ static struct attribute *taal_attrs[] = {
&dev_attr_cabc_mode.attr,
&dev_attr_cabc_available_modes.attr,
&dev_attr_esd_interval.attr,
+ &dev_attr_ulps.attr,
+ &dev_attr_ulps_timeout.attr,
NULL,
};
@@ -759,6 +994,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
td->dssdev = dssdev;
td->panel_config = panel_config;
td->esd_interval = panel_data->esd_interval;
+ td->ulps_enabled = false;
+ td->ulps_timeout = panel_data->ulps_timeout;
mutex_init(&td->lock);
@@ -776,6 +1013,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
goto err_wq;
}
INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
+ INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
dev_set_drvdata(&dssdev->dev, td);
@@ -900,6 +1138,7 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
taal_bl_update_status(bldev);
backlight_device_unregister(bldev);
+ taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
destroy_workqueue(td->workqueue);
@@ -1072,12 +1311,15 @@ static void taal_disable(struct omap_dss_device *dssdev)
mutex_lock(&td->lock);
+ taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
dsi_bus_lock();
- if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
+ if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
+ taal_wake_up(dssdev);
taal_power_off(dssdev);
+ }
dsi_bus_unlock();
@@ -1100,11 +1342,14 @@ static int taal_suspend(struct omap_dss_device *dssdev)
goto err;
}
+ taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
dsi_bus_lock();
- taal_power_off(dssdev);
+ r = taal_wake_up(dssdev);
+ if (!r)
+ taal_power_off(dssdev);
dsi_bus_unlock();
@@ -1213,6 +1458,10 @@ static int taal_update(struct omap_dss_device *dssdev,
mutex_lock(&td->lock);
dsi_bus_lock();
+ r = taal_wake_up(dssdev);
+ if (r)
+ goto err;
+
if (!td->enabled) {
r = 0;
goto err;
@@ -1300,6 +1549,10 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
dsi_bus_lock();
if (td->enabled) {
+ r = taal_wake_up(dssdev);
+ if (r)
+ goto err;
+
r = _taal_enable_te(dssdev, enable);
if (r)
goto err;
@@ -1346,6 +1599,10 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
dsi_bus_lock();
if (td->enabled) {
+ r = taal_wake_up(dssdev);
+ if (r)
+ goto err;
+
r = taal_set_addr_mode(td, rotate, td->mirror);
if (r)
goto err;
@@ -1389,6 +1646,10 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
dsi_bus_lock();
if (td->enabled) {
+ r = taal_wake_up(dssdev);
+ if (r)
+ goto err;
+
r = taal_set_addr_mode(td, td->rotate, enable);
if (r)
goto err;
@@ -1433,6 +1694,10 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
dsi_bus_lock();
+ r = taal_wake_up(dssdev);
+ if (r)
+ goto err2;
+
r = taal_dcs_read_1(td, DCS_GET_ID1, &id1);
if (r)
goto err2;
@@ -1479,6 +1744,10 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
dsi_bus_lock();
+ r = taal_wake_up(dssdev);
+ if (r)
+ goto err2;
+
/* plen 1 or 2 goes into short packet. until checksum error is fixed,
* use short packets. plen 32 works, but bigger packets seem to cause
* an error. */
@@ -1531,6 +1800,27 @@ err1:
return r;
}
+static void taal_ulps_work(struct work_struct *work)
+{
+ struct taal_data *td = container_of(work, struct taal_data,
+ ulps_work.work);
+ struct omap_dss_device *dssdev = td->dssdev;
+
+ mutex_lock(&td->lock);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !td->enabled) {
+ mutex_unlock(&td->lock);
+ return;
+ }
+
+ dsi_bus_lock();
+
+ taal_enter_ulps(dssdev);
+
+ dsi_bus_unlock();
+ mutex_unlock(&td->lock);
+}
+
static void taal_esd_work(struct work_struct *work)
{
struct taal_data *td = container_of(work, struct taal_data,
@@ -1549,6 +1839,12 @@ static void taal_esd_work(struct work_struct *work)
dsi_bus_lock();
+ r = taal_wake_up(dssdev);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to exit ULPS\n");
+ goto err;
+ }
+
r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
if (r) {
dev_err(&dssdev->dev, "failed to read Taal status\n");
--
1.7.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 00/19] OMAP: DSS2: ULPS support
2011-04-19 9:22 [PATCH 00/19] OMAP: DSS2: ULPS support Tomi Valkeinen
` (18 preceding siblings ...)
2011-04-19 9:22 ` [PATCH 19/19] OMAP: DSS2: Taal: Implement ULPS functionality Tomi Valkeinen
@ 2011-04-20 5:55 ` Archit Taneja
2011-04-20 6:08 ` Tomi Valkeinen
19 siblings, 1 reply; 22+ messages in thread
From: Archit Taneja @ 2011-04-20 5:55 UTC (permalink / raw)
To: Valkeinen, Tomi; +Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org
On Tuesday 19 April 2011 02:52 PM, Valkeinen, Tomi wrote:
> ULPS (Ultra-Low Power State) is a power saving method for DSI bus. When the
> ULPS is entered, the host sends an ULPS entry sequence and pulls the DSI lines
> down. On ULPS exit, the host sends an exit sequence and continues normal
> operation. This allows both the host and the DSI peripheral to save some power
> while in ULPS.
>
> This patch set implements ULPS support for DSS2. ULPS can be used with DSI
> command mode displays, and as command mode displays can refresh the panel
> independently using its own framebuffer, entering ULPS allows OMAP DSS HW to be
> totally turned off while the image on the display stays. This in turn may allow
> OMAP to enter deep sleep.
>
> Taal panel driver implements an inactivity timer which is used to enter ULPS
> after a certain period. The period can configured via sysfs, "ulps_timeout"
> file. A good value for the ulps_timeout depends on the use case and board, but
> is most likely around 100-500ms.
>
> The patch set does not enable the ULPS timeout, but it has to be enabled either
> manually via sysfs or from the board file.
>
> Tested on OMAP 4430 Blaze board. The patches are based on the current DSS2
> master branch.
Tested on 4430sdp and 3430sdp with Taal Panel.
Archit
>
> Tomi
>
> Tomi Valkeinen (19):
> OMAP: DSS2: DSI: Add lane override functions
> OMAP: DSS2: DSI: Remove CIO LDO status check
> OMAP: DSS2: DSI: implement ULPS enter and exit
> OMAP: DSS2: DSI: add option to leave DSI lanes powered on
> OMAP: DSS2: DSI: rename complexio related functions
> OMAP: DSS2: Add FEAT_DSI_REVERSE_TXCLKESC
> OMAP: DSS2: DSI: fix _dsi_print_reset_status
> OMAP: DSS2: DSI: implement enable/disable SCP clk
> OMAP: DSS2: DSI: fix CIO init and uninit
> OMAP: DSS2: DSI: wait for TXCLKESC domain to come out of reset
> OMAP: DSS2: DSI: add parameter to enter ulps on disable
> OMAP: DSS2: DSI: Add DSI pad muxing support
> OMAP: DSS2: DSI: ensure VDDS_DSI is disabled on exit
> OMAP: DSS2: Taal: Implement configurable ESD interval
> OMAP: DSS2: Taal: Clean up ESD queueing
> OMAP: DSS2: Taal: Add sysfs file for ESD interval
> OMAP: DSS2: Taal: Separate panel reset
> OMAP: DSS2: Taal: Rename esd_wq to workqueue
> OMAP: DSS2: Taal: Implement ULPS functionality
>
> arch/arm/mach-omap2/board-4430sdp.c | 2 +-
> arch/arm/plat-omap/include/plat/display.h | 4 +-
> arch/arm/plat-omap/include/plat/nokia-dsi-panel.h | 6 +-
> drivers/video/omap2/displays/panel-taal.c | 420 +++++++++++++++++++--
> drivers/video/omap2/dss/dpi.c | 4 +-
> drivers/video/omap2/dss/dsi.c | 427 +++++++++++++++++----
> drivers/video/omap2/dss/dss.h | 2 +-
> drivers/video/omap2/dss/dss_features.c | 4 +-
> drivers/video/omap2/dss/dss_features.h | 6 +-
> 9 files changed, 764 insertions(+), 111 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 00/19] OMAP: DSS2: ULPS support
2011-04-20 5:55 ` [PATCH 00/19] OMAP: DSS2: ULPS support Archit Taneja
@ 2011-04-20 6:08 ` Tomi Valkeinen
0 siblings, 0 replies; 22+ messages in thread
From: Tomi Valkeinen @ 2011-04-20 6:08 UTC (permalink / raw)
To: Archit Taneja; +Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org
On Wed, 2011-04-20 at 11:13 +0530, Archit Taneja wrote:
> On Tuesday 19 April 2011 02:52 PM, Valkeinen, Tomi wrote:
> > ULPS (Ultra-Low Power State) is a power saving method for DSI bus. When the
> > ULPS is entered, the host sends an ULPS entry sequence and pulls the DSI lines
> > down. On ULPS exit, the host sends an exit sequence and continues normal
> > operation. This allows both the host and the DSI peripheral to save some power
> > while in ULPS.
> >
> > This patch set implements ULPS support for DSS2. ULPS can be used with DSI
> > command mode displays, and as command mode displays can refresh the panel
> > independently using its own framebuffer, entering ULPS allows OMAP DSS HW to be
> > totally turned off while the image on the display stays. This in turn may allow
> > OMAP to enter deep sleep.
> >
> > Taal panel driver implements an inactivity timer which is used to enter ULPS
> > after a certain period. The period can configured via sysfs, "ulps_timeout"
> > file. A good value for the ulps_timeout depends on the use case and board, but
> > is most likely around 100-500ms.
> >
> > The patch set does not enable the ULPS timeout, but it has to be enabled either
> > manually via sysfs or from the board file.
> >
> > Tested on OMAP 4430 Blaze board. The patches are based on the current DSS2
> > master branch.
>
> Tested on 4430sdp and 3430sdp with Taal Panel.
Thanks. I've applied the ULPS patch set to my master branch.
Tomi
^ permalink raw reply [flat|nested] 22+ messages in thread