diff options
Diffstat (limited to 'drivers/video/omap2/displays/panel-minnow.c')
| -rw-r--r-- | drivers/video/omap2/displays/panel-minnow.c | 187 |
1 files changed, 86 insertions, 101 deletions
diff --git a/drivers/video/omap2/displays/panel-minnow.c b/drivers/video/omap2/displays/panel-minnow.c index ed9b9c7eea8..31c90f7faeb 100644 --- a/drivers/video/omap2/displays/panel-minnow.c +++ b/drivers/video/omap2/displays/panel-minnow.c @@ -408,6 +408,7 @@ struct minnow_panel_data { /* runtime variables */ bool enabled; + bool interactive; enum minnow_panel_dummy_type dummy_panel; bool te_enabled; @@ -494,22 +495,6 @@ exit1: static void minnow_panel_esd_work(struct work_struct *work); static void minnow_panel_ulps_work(struct work_struct *work); -static void hw_guard_start(struct minnow_panel_data *mpd, int guard_msec) -{ - mpd->hw_guard_wait = msecs_to_jiffies(guard_msec); - mpd->hw_guard_end = jiffies + mpd->hw_guard_wait; -} - -static void hw_guard_wait(struct minnow_panel_data *mpd) -{ - unsigned long wait = mpd->hw_guard_end - jiffies; - - if ((long)wait > 0 && wait <= mpd->hw_guard_wait) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(wait); - } -} - static int set_bridge_retrans(struct minnow_panel_data *mpd, int enable) { u8 data[2] = {0xFF, enable ? 0x01 : 0x00}; @@ -545,33 +530,6 @@ static int minnow_panel_dcs_write_1(struct minnow_panel_data *mpd, u8 dcs_cmd, u return dsi_vc_dcs_write(mpd->dssdev, mpd->channel, buf, 2); } -static int minnow_panel_sleep_out(struct minnow_panel_data *mpd) -{ - int r; - - hw_guard_wait(mpd); - - r = minnow_panel_dcs_write_0(mpd, MIPI_DCS_EXIT_SLEEP_MODE); - if (r) - return r; - if (mpd->id_panel == MINNOW_PANEL_CM_BRIDGE_320X320) { - r = set_bridge_retrans(mpd, true); - if (!r) { - r = minnow_panel_dcs_write_0(mpd, - MIPI_DCS_EXIT_SLEEP_MODE); - set_bridge_retrans(mpd, false); - } - if (r) - return r; - } - - hw_guard_start(mpd, 120); - - msleep(10); - - return 0; -} - static int minnow_panel_get_bridge_rev(struct minnow_panel_data *mpd, u8 *id1, u8 *id2, u8 *id3) { @@ -976,11 +934,12 @@ static int minnow_panel_enter_ulps(struct omap_dss_device *dssdev) omapdss_dsi_display_disable(dssdev, false, true); mpd->ulps_enabled = true; + dev_info(&dssdev->dev, "entered ULPS mode\n"); return 0; err: - dev_err(&dssdev->dev, "enter ULPS failed"); + dev_err(&dssdev->dev, "enter ULPS failed\n"); minnow_panel_reset(dssdev); mpd->ulps_enabled = false; @@ -1019,10 +978,12 @@ static int minnow_panel_exit_ulps(struct omap_dss_device *dssdev) mpd->ulps_enabled = false; + dev_info(&dssdev->dev, "exited ULPS mode\n"); + return 0; err2: - dev_err(&dssdev->dev, "failed to exit ULPS"); + dev_err(&dssdev->dev, "failed to exit ULPS\n"); r = minnow_panel_reset(dssdev); if (!r) { @@ -1384,6 +1345,7 @@ static ssize_t minnow_panel_show_ulps_timeout(struct device *dev, return snprintf(buf, PAGE_SIZE, "%u\n", t); } +#ifdef DEBUG static ssize_t minnow_panel_store_init_data(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1440,6 +1402,56 @@ static ssize_t minnow_panel_show_init_data(struct device *dev, return i < PAGE_SIZE ? i : PAGE_SIZE; } +#endif + +static ssize_t minnow_panel_show_interactivemode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct minnow_panel_data *mpd = dev_get_drvdata(&dssdev->dev); + unsigned t; + + mutex_lock(&mpd->lock); + t = mpd->interactive; + mutex_unlock(&mpd->lock); + + return snprintf(buf, PAGE_SIZE, "%u\n", t); +} + +static ssize_t minnow_panel_store_interactivemode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct minnow_panel_data *mpd = dev_get_drvdata(&dssdev->dev); + unsigned long t; + int r; + + r = strict_strtoul(buf, 10, &t); + if (!r) { + bool enable = !!t; + /* Temporary force DSI goto ULPS mode when interactive mode + * turns OFF, it will add support to switch bridge/panel to + * low refresh mode later + */ + mutex_lock(&mpd->lock); + if (mpd->enabled && (mpd->interactive != enable)) { + mpd->interactive = enable; + dsi_bus_lock(dssdev); + if (enable) + r = minnow_panel_wake_up(dssdev); + else + r = minnow_panel_enter_ulps(dssdev); + dsi_bus_unlock(dssdev); + } + mutex_unlock(&mpd->lock); + dev_info(&dssdev->dev, "%s interactive mode%s\n", + enable ? "enable" : "disable", r ? " failed" : ""); + } + + return r ? r : count; +} static DEVICE_ATTR(num_dsi_errors, S_IRUGO, minnow_panel_num_errors_show, NULL); static DEVICE_ATTR(hw_revision, S_IRUGO, minnow_panel_hw_revision_show, NULL); @@ -1453,8 +1465,12 @@ static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR, minnow_panel_show_ulps, minnow_panel_store_ulps); static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR, minnow_panel_show_ulps_timeout, minnow_panel_store_ulps_timeout); +#ifdef DEBUG static DEVICE_ATTR(init_data, S_IRUGO | S_IWUSR, minnow_panel_show_init_data, minnow_panel_store_init_data); +#endif +static DEVICE_ATTR(interactivemode, S_IRUGO | S_IWUSR, + minnow_panel_show_interactivemode, minnow_panel_store_interactivemode); static struct attribute *minnow_panel_attrs[] = { &dev_attr_num_dsi_errors.attr, @@ -1464,7 +1480,10 @@ static struct attribute *minnow_panel_attrs[] = { &dev_attr_esd_interval.attr, &dev_attr_ulps.attr, &dev_attr_ulps_timeout.attr, +#ifdef DEBUG &dev_attr_init_data.attr, +#endif + &dev_attr_interactivemode.attr, NULL, }; @@ -1645,7 +1664,8 @@ static int minnow_panel_dt_init(struct minnow_panel_data *mpd) mpd->esd_interval = value; DTINFO("esd_interval = %d\n", mpd->esd_interval); } - mpd->ulps_timeout = 0; + /* automatically go to ULPS mode for none-update within 250ms */ + mpd->ulps_timeout = 250; mpd->use_dsi_backlight = false; mpd->pin_config.num_pins = 4; @@ -1989,23 +2009,17 @@ init_start: /* for the first time power on, do not reset h/w to keep logo on */ if (mpd->first_enable && def_skip_first_init) { dsi_vc_send_bta_sync(dssdev, mpd->channel); - retry = 0; - } else + } else { _minnow_panel_hw_reset(dssdev); - while (retry--) { r = minnow_panel_process_cmdbuf(mpd, &mpd->power_on); if (!r) { if (mpd->dummy_panel == DUMMY_DISABLED) r = minnow_panel_check_panel_status(mpd); - if (!r) - break; } - if (!retry) - goto err; - dev_err(&dssdev->dev, "Reset hardware to retry ...\n"); - _minnow_panel_hw_reset(dssdev); - /* for dummy panel, it needs reset DSI */ - if (mpd->dummy_panel == DUMMY_ENABLED) { + if (r) { + if (!retry--) + goto err; + dev_err(&dssdev->dev, "Reset hardware to retry ...\n"); omapdss_dsi_display_disable(dssdev, true, false); goto init_start; } @@ -2033,7 +2047,8 @@ init_start: if (r) goto err; - mpd->enabled = 1; + mpd->enabled = true; + mpd->interactive = true; if (mpd->first_enable) dev_info(&dssdev->dev, "panel revision %02x.%02x.%02x\n", @@ -2064,7 +2079,8 @@ static void minnow_panel_power_off(struct omap_dss_device *dssdev) omapdss_dsi_display_disable(dssdev, true, false); - mpd->enabled = 0; + mpd->enabled = false; + mpd->interactive = false; } static int minnow_panel_reset(struct omap_dss_device *dssdev) @@ -2211,25 +2227,23 @@ static int minnow_panel_update(struct omap_dss_device *dssdev, u16 x, u16 y, u16 w, u16 h) { struct minnow_panel_data *mpd = dev_get_drvdata(&dssdev->dev); - int r; + int r = 0; /* for video mode, do not need manual update */ if (mpd->dsi_config.mode == OMAP_DSS_DSI_VIDEO_MODE) - return 0; + return r; dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); mutex_lock(&mpd->lock); dsi_bus_lock(dssdev); - r = minnow_panel_wake_up(dssdev); - if (r) + if (!mpd->enabled) goto err; - if (!mpd->enabled) { - r = 0; + r = minnow_panel_wake_up(dssdev); + if (r) goto err; - } /* XXX no need to send this every frame, but dsi break if not done */ r = minnow_panel_set_update_window(mpd, 0, 0, @@ -2471,7 +2485,6 @@ static void minnow_panel_esd_work(struct work_struct *work) struct minnow_panel_data *mpd = container_of(work, struct minnow_panel_data, esd_work.work); struct omap_dss_device *dssdev = mpd->dssdev; - u8 state1, state2; int r; mutex_lock(&mpd->lock); @@ -2489,57 +2502,29 @@ static void minnow_panel_esd_work(struct work_struct *work) goto err; } - r = minnow_panel_dcs_read_1(mpd, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1); - if (r) { - dev_err(&dssdev->dev, "failed to read minnow-panel status\n"); - goto err; - } - - /* Run self diagnostics */ - r = minnow_panel_sleep_out(mpd); - if (r) { - dev_err(&dssdev->dev, "failed to run minnow-panel self-diagnostics\n"); - goto err; - } - - r = minnow_panel_dcs_read_1(mpd, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2); + r = minnow_panel_check_panel_status(mpd); if (r) { dev_err(&dssdev->dev, "failed to read minnow-panel status\n"); goto err; } - /* Each sleep out command will trigger a self diagnostic and flip - * Bit6 if the test passes. - */ - if (!((state1 ^ state2) & (1 << 6))) { - dev_err(&dssdev->dev, "LCD self diagnostics failed\n"); - goto err; - } - /* Self-diagnostics result is also shown on TE GPIO line. We need - * to re-enable TE after self diagnostics */ - if (mpd->te_enabled && gpio_is_valid(mpd->ext_te_gpio)) { - r = minnow_panel_dcs_write_1(mpd, MIPI_DCS_SET_TEAR_ON, 0); - if (r) - goto err; - } + if (!mpd->interactive) + minnow_panel_enter_ulps(dssdev); dsi_bus_unlock(dssdev); minnow_panel_queue_esd_work(dssdev); - mutex_unlock(&mpd->lock); return; err: dev_err(&dssdev->dev, "performing LCD reset\n"); - minnow_panel_reset(dssdev); - dsi_bus_unlock(dssdev); - - minnow_panel_queue_esd_work(dssdev); - mutex_unlock(&mpd->lock); + + minnow_panel_disable(dssdev); + minnow_panel_enable(dssdev); } static struct omap_dss_driver minnow_panel_driver = { |