diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss')
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dsi.c | 91 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/omapdss.h | 13 |
2 files changed, 84 insertions, 20 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index c7f366ae4764..56cff14061ee 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -214,6 +214,9 @@ static void dsi_display_uninit_dispc(struct dsi_data *dsi); static int dsi_vc_send_null(struct dsi_data *dsi, int channel); +static ssize_t _omap_dsi_host_transfer(struct dsi_data *dsi, + const struct mipi_dsi_msg *msg); + /* DSI PLL HSDIV indices */ #define HSDIV_DISPC 0 #define HSDIV_DSI 1 @@ -384,9 +387,6 @@ struct dsi_data { struct delayed_work ulps_work; - void (*framedone_callback)(int, void *); - void *framedone_data; - struct delayed_work framedone_timeout_work; #ifdef DSI_CATCH_MISSING_TE @@ -3804,8 +3804,6 @@ static void dsi_handle_framedone(struct dsi_data *dsi, int error) dsi_set_ulps_auto(dsi, true); dsi_bus_unlock(dsi); - dsi->framedone_callback(error, dsi->framedone_data); - if (!error) dsi_perf_show(dsi, "DISPC"); } @@ -3837,6 +3835,8 @@ static void dsi_framedone_irq_callback(void *data) cancel_delayed_work(&dsi->framedone_timeout_work); + DSSDBG("Framedone received!\n"); + dsi_handle_framedone(dsi, 0); } @@ -3853,17 +3853,69 @@ static int _dsi_update(struct dsi_data *dsi) return 0; } -static int dsi_update(struct omap_dss_device *dssdev, int channel, - void (*callback)(int, void *), void *data) +static int _dsi_update_window(struct dsi_data *dsi, int channel, + int x, int y, int w, int h) +{ + int x1 = x, x2 = (x + w - 1); + int y1 = y, y2 = (y + h - 1); + u8 payloadX[5] = { MIPI_DCS_SET_COLUMN_ADDRESS, + x1 >> 8, x1 & 0xff, x2 >> 8, x2 & 0xff }; + u8 payloadY[5] = { MIPI_DCS_SET_PAGE_ADDRESS, + y1 >> 8, y1 & 0xff, y2 >> 8, y2 & 0xff }; + struct mipi_dsi_msg msgX = { 0 }, msgY = { 0 }; + int ret; + + WARN_ON(!dsi_bus_is_locked(dsi)); + + msgX.type = MIPI_DSI_DCS_LONG_WRITE; + msgX.channel = channel; + msgX.tx_buf = payloadX; + msgX.tx_len = sizeof(payloadX); + + msgY.type = MIPI_DSI_DCS_LONG_WRITE; + msgY.channel = channel; + msgY.tx_buf = payloadY; + msgY.tx_len = sizeof(payloadY); + + ret = _omap_dsi_host_transfer(dsi, &msgX); + if (ret != 0) + return ret; + + return _omap_dsi_host_transfer(dsi, &msgY); +} + +static int dsi_update_channel(struct omap_dss_device *dssdev, int channel) { struct dsi_data *dsi = to_dsi_data(dssdev); + int r; + + if (channel > 3) + return -EINVAL; dsi_bus_lock(dsi); + + if (!dsi->vc[channel].dest) { + r = -ENODEV; + goto err; + } + + if (dsi->vm.hactive == 0 || dsi->vm.vactive == 0) { + r = -EINVAL; + goto err; + } + + DSSDBG("dsi_update_channel: %d", channel); + dsi_set_ulps_auto(dsi, false); + r = _dsi_update_window(dsi, channel, 0, 0, dsi->vm.hactive, + dsi->vm.vactive); + if (r < 0) { + DSSWARN("window update error: %d\n", r); + goto err; + } + dsi->update_channel = channel; - dsi->framedone_callback = callback; - dsi->framedone_data = data; if (dsi->te_enabled && dsi->te_gpio) { schedule_delayed_work(&dsi->te_timeout_work, @@ -3874,6 +3926,25 @@ static int dsi_update(struct omap_dss_device *dssdev, int channel, } return 0; + +err: + dsi_set_ulps_auto(dsi, true); + dsi_bus_unlock(dsi); + return r; +} + +static int dsi_update_all(struct omap_dss_device *dssdev) +{ + unsigned int i; + int r; + + for (i = 0; i < 4; i++) { + r = dsi_update_channel(dssdev, i); + if (r && r != -ENODEV) + return r; + } + + return r; } /* Display funcs */ @@ -4875,7 +4946,7 @@ static const struct omap_dss_device_ops dsi_ops = { .enable_video_output = dsi_enable_video_output, .disable_video_output = dsi_disable_video_output, - .update = dsi_update, + .update = dsi_update_all, }, }; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 1e24b4c04762..592c208d88c2 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -284,13 +284,12 @@ struct omap_dss_writeback_info { }; struct omapdss_dsi_ops { - /* bus configuration */ + int (*update)(struct omap_dss_device *dssdev); + + /* legacy API used by omapdss panels */ int (*set_config)(struct omap_dss_device *dssdev, const struct omap_dss_dsi_config *cfg); - int (*update)(struct omap_dss_device *dssdev, int channel, - void (*callback)(int, void *), void *data); - int (*enable_video_output)(struct omap_dss_device *dssdev, int channel); void (*disable_video_output)(struct omap_dss_device *dssdev, int channel); @@ -354,7 +353,6 @@ struct omap_dss_device { const char *name; - const struct omap_dss_driver *driver; const struct omap_dss_device_ops *ops; unsigned long ops_flags; u32 bus_flags; @@ -375,11 +373,6 @@ struct omap_dss_device { unsigned int of_port; }; -struct omap_dss_driver { - int (*update)(struct omap_dss_device *dssdev, - u16 x, u16 y, u16 w, u16 h); -}; - struct dss_device *omapdss_get_dss(void); void omapdss_set_dss(struct dss_device *dss); static inline bool omapdss_is_initialized(void) |