Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 251034
b: refs/heads/master
c: 40885ab
h: refs/heads/master
v: v3
  • Loading branch information
Tomi Valkeinen committed May 11, 2011
1 parent 1f7ed41 commit 31e607e
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 95861368e3eb2180dc9f00e916a4ba6f5e1fe4ce
refs/heads/master: 40885ab31f754426c2e9a40362e568778baa5e82
141 changes: 123 additions & 18 deletions trunk/drivers/video/omap2/dss/dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/regulator/consumer.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/sched.h>

#include <video/omapdss.h>
#include <plat/clock.h>
Expand Down Expand Up @@ -268,6 +269,7 @@ static struct
struct dsi_update_region update_region;

bool te_enabled;
bool ulps_enabled;

struct workqueue_struct *workqueue;

Expand Down Expand Up @@ -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. */
Expand All @@ -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;
Expand All @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -3547,6 +3649,9 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)

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);
Expand Down

0 comments on commit 31e607e

Please sign in to comment.