diff options
author | Sebastian Reichel <sebastian.reichel@collabora.com> | 2020-12-15 12:46:01 +0200 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2020-12-15 16:08:23 +0200 |
commit | 66c6bf3af6e6838ae4ba76b6258fe4a382f00c55 (patch) | |
tree | eb59d6354c62ada2f1fa5b38d40a3ade1fcf5467 /drivers/gpu/drm/omapdrm/dss | |
parent | 9f0eb51e3c658a767c3fa89b3894f45f5319c208 (diff) | |
download | linux-66c6bf3af6e6838ae4ba76b6258fe4a382f00c55.tar.gz |
drm/omap: dsi: do ULPS in host driver
Move ULPS handling into the DSI host controller, so that we
no longer need a custom API for the DSI client.
Note that for now ULPS is always disabled.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201215104657.802264-29-tomi.valkeinen@ti.com
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss')
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dsi.c | 71 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 |
2 files changed, 53 insertions, 20 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 5853f89aebbe..c7f366ae4764 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -207,6 +207,8 @@ struct dsi_reg { u16 module; u16 idx; }; typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); struct dsi_data; +static void dsi_set_ulps_auto(struct dsi_data *dsi, bool enable); + static int dsi_display_init_dispc(struct dsi_data *dsi); static void dsi_display_uninit_dispc(struct dsi_data *dsi); @@ -378,6 +380,9 @@ struct dsi_data { bool te_enabled; bool ulps_enabled; + bool ulps_auto_idle; + + struct delayed_work ulps_work; void (*framedone_callback)(int, void *); void *framedone_data; @@ -3796,6 +3801,7 @@ static void dsi_handle_framedone(struct dsi_data *dsi, int error) REG_FLD_MOD(dsi, DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ } + dsi_set_ulps_auto(dsi, true); dsi_bus_unlock(dsi); dsi->framedone_callback(error, dsi->framedone_data); @@ -3853,6 +3859,7 @@ static int dsi_update(struct omap_dss_device *dssdev, int channel, struct dsi_data *dsi = to_dsi_data(dssdev); dsi_bus_lock(dsi); + dsi_set_ulps_auto(dsi, false); dsi->update_channel = channel; dsi->framedone_callback = callback; @@ -4121,22 +4128,6 @@ static void dsi_display_disable(struct omap_dss_device *dssdev) dsi_bus_unlock(dsi); } -static void dsi_ulps(struct omap_dss_device *dssdev, bool enable) -{ - struct dsi_data *dsi = to_dsi_data(dssdev); - - DSSDBG("dsi_ulps %d\n", enable); - - dsi_bus_lock(dsi); - - if (enable) - _dsi_display_disable(dsi, false, true); - else - _dsi_display_enable(dsi); - - dsi_bus_unlock(dsi); -} - static int dsi_enable_te(struct dsi_data *dsi, bool enable) { dsi->te_enabled = enable; @@ -4151,6 +4142,42 @@ static int dsi_enable_te(struct dsi_data *dsi, bool enable) return 0; } +static void omap_dsi_ulps_work_callback(struct work_struct *work) +{ + struct dsi_data *dsi = container_of(work, struct dsi_data, + ulps_work.work); + + dsi_bus_lock(dsi); + + dsi_enable_te(dsi, false); + + _dsi_display_disable(dsi, false, true); + + dsi_bus_unlock(dsi); +} + +static void dsi_set_ulps_auto(struct dsi_data *dsi, bool enable) +{ + WARN_ON(!dsi_bus_is_locked(dsi)); + + if (!dsi->ulps_auto_idle) + return; + + if (enable) { + schedule_delayed_work(&dsi->ulps_work, msecs_to_jiffies(250)); + } else { + cancel_delayed_work_sync(&dsi->ulps_work); + + if (!dsi->ulps_enabled) + return; + + dsi_bus_lock(dsi); + _dsi_display_enable(dsi); + dsi_enable_te(dsi, true); + dsi_bus_unlock(dsi); + } +} + #ifdef PRINT_VERBOSE_VM_TIMINGS static void print_dsi_vm(const char *str, const struct omap_dss_dsi_videomode_timings *t) @@ -4801,7 +4828,9 @@ static ssize_t omap_dsi_host_transfer(struct mipi_dsi_host *host, int r; dsi_bus_lock(dsi); + dsi_set_ulps_auto(dsi, false); r = _omap_dsi_host_transfer(dsi, msg); + dsi_set_ulps_auto(dsi, true); dsi_bus_unlock(dsi); return r; @@ -4841,8 +4870,6 @@ static const struct omap_dss_device_ops dsi_ops = { .disable = dsi_display_disable, .dsi = { - .ulps = dsi_ulps, - .set_config = dsi_set_config, .enable_video_output = dsi_enable_video_output, @@ -4971,6 +4998,14 @@ static int omap_dsi_host_attach(struct mipi_dsi_host *host, dsi->vc[channel].dest = client; dsi->pix_fmt = client->format; + INIT_DEFERRABLE_WORK(&dsi->ulps_work, + omap_dsi_ulps_work_callback); + + dsi_bus_lock(dsi); + dsi->ulps_auto_idle = false; + dsi_set_ulps_auto(dsi, true); + dsi_bus_unlock(dsi); + return 0; } diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 1c5421fe0ee8..1e24b4c04762 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -285,8 +285,6 @@ struct omap_dss_writeback_info { struct omapdss_dsi_ops { /* bus configuration */ - void (*ulps)(struct omap_dss_device *dssdev, bool enable); - int (*set_config)(struct omap_dss_device *dssdev, const struct omap_dss_dsi_config *cfg); |