0006-drm-omap-add-support-for-manually-updated-displays.patch (8428B)
1 From 2a51a11e2f2705bbf7642e2e08ae6b2f1372d79c Mon Sep 17 00:00:00 2001 2 From: Sebastian Reichel <sebastian.reichel@collabora.co.uk> 3 Date: Mon, 24 Jul 2017 19:33:03 +0200 4 Subject: [PATCH 06/17] drm/omap: add support for manually updated displays 5 6 This adds the required infrastructure for manually 7 updated displays, such as DSI command mode panels. 8 9 While those panels often support partial updates 10 we currently always do a full refresh. Display 11 will be refreshed when something calls the dirty 12 callback, such as libdrm's drmModeDirtyFB(). 13 14 This is currently being implemented for the kernel 15 console and for Xorg. Weston currently does not 16 implement this and is known not to work on manually 17 updated displays. 18 19 Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk> 20 --- 21 drivers/gpu/drm/omapdrm/omap_crtc.c | 110 +++++++++++++++++++++++++++++++++--- 22 drivers/gpu/drm/omapdrm/omap_drv.h | 1 + 23 drivers/gpu/drm/omapdrm/omap_fb.c | 20 +++++++ 24 3 files changed, 123 insertions(+), 8 deletions(-) 25 26 diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c 27 index dee9b6e..8255241 100644 28 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c 29 +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c 30 @@ -52,6 +52,7 @@ struct omap_crtc { 31 bool pending; 32 wait_queue_head_t pending_wait; 33 struct drm_pending_vblank_event *event; 34 + struct delayed_work update_work; 35 36 void (*framedone_handler)(void *); 37 void *framedone_handler_data; 38 @@ -143,6 +144,28 @@ static void omap_crtc_dss_disconnect(enum omap_channel channel, 39 40 static void omap_crtc_dss_start_update(enum omap_channel channel) 41 { 42 + struct omap_crtc *omap_crtc = omap_crtcs[channel]; 43 + struct omap_drm_private *priv = omap_crtc->base.dev->dev_private; 44 + 45 + priv->dispc_ops->mgr_enable(channel, true); 46 +} 47 + 48 +static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc) 49 +{ 50 + struct drm_connector *connector; 51 + struct drm_connector_list_iter conn_iter; 52 + bool result = false; 53 + 54 + drm_connector_list_iter_begin(crtc->dev, &conn_iter); 55 + drm_for_each_connector_iter(connector, &conn_iter) { 56 + if (connector->state->crtc != crtc) 57 + continue; 58 + result = omap_connector_get_manually_updated(connector); 59 + break; 60 + } 61 + drm_connector_list_iter_end(&conn_iter); 62 + 63 + return result; 64 } 65 66 /* Called only from the encoder enable/disable and suspend/resume handlers. */ 67 @@ -154,12 +177,17 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) 68 enum omap_channel channel = omap_crtc->channel; 69 struct omap_irq_wait *wait; 70 u32 framedone_irq, vsync_irq; 71 + bool is_manual = omap_crtc_is_manually_updated(crtc); 72 + enum omap_display_type type = omap_crtc_output[channel]->output_type; 73 int ret; 74 75 if (WARN_ON(omap_crtc->enabled == enable)) 76 return; 77 78 - if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) { 79 + if (is_manual) 80 + omap_irq_enable_framedone(crtc, enable); 81 + 82 + if (is_manual || type == OMAP_DISPLAY_TYPE_HDMI) { 83 priv->dispc_ops->mgr_enable(channel, enable); 84 omap_crtc->enabled = enable; 85 return; 86 @@ -210,7 +238,6 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) 87 } 88 } 89 90 - 91 static int omap_crtc_dss_enable(enum omap_channel channel) 92 { 93 struct omap_crtc *omap_crtc = omap_crtcs[channel]; 94 @@ -370,6 +397,53 @@ void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus) 95 wake_up(&omap_crtc->pending_wait); 96 } 97 98 +void omap_crtc_flush(struct drm_crtc *crtc) 99 +{ 100 + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 101 + 102 + if (!omap_crtc_is_manually_updated(crtc)) 103 + return; 104 + 105 + if (!delayed_work_pending(&omap_crtc->update_work)) 106 + schedule_delayed_work(&omap_crtc->update_work, 0); 107 +} 108 + 109 +static void omap_crtc_manual_display_update(struct work_struct *data) 110 +{ 111 + struct omap_crtc *omap_crtc = 112 + container_of(data, struct omap_crtc, update_work.work); 113 + struct omap_dss_device *dssdev = omap_crtc_output[omap_crtc->channel]; 114 + struct drm_device *dev = omap_crtc->base.dev; 115 + struct omap_dss_driver *dssdrv; 116 + int ret, width, height; 117 + 118 + if (!dssdev || !dssdev->dst) { 119 + dev_err_once(dev->dev, "missing dssdev!"); 120 + return; 121 + } 122 + 123 + dssdev = dssdev->dst; 124 + dssdrv = dssdev->driver; 125 + 126 + if (!dssdrv || !dssdrv->update) { 127 + dev_err_once(dev->dev, "incorrect dssdrv!"); 128 + return; 129 + } 130 + 131 + if (dssdrv->sync) 132 + dssdrv->sync(dssdev); 133 + 134 + width = dssdev->panel.vm.hactive; 135 + height = dssdev->panel.vm.vactive; 136 + ret = dssdrv->update(dssdev, 0, 0, width, height); 137 + if (ret < 0) { 138 + spin_lock_irq(&dev->event_lock); 139 + omap_crtc->pending = false; 140 + spin_unlock_irq(&dev->event_lock); 141 + wake_up(&omap_crtc->pending_wait); 142 + } 143 +} 144 + 145 static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc) 146 { 147 struct omap_drm_private *priv = crtc->dev->dev_private; 148 @@ -422,6 +496,10 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc, 149 150 DBG("%s", omap_crtc->name); 151 152 + /* manual updated display will not trigger vsync irq */ 153 + if (omap_crtc_is_manually_updated(crtc)) 154 + return; 155 + 156 spin_lock_irq(&crtc->dev->event_lock); 157 drm_crtc_vblank_on(crtc); 158 ret = drm_crtc_vblank_get(crtc); 159 @@ -435,6 +513,7 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc, 160 struct drm_crtc_state *old_state) 161 { 162 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 163 + struct drm_device *dev = crtc->dev; 164 165 DBG("%s", omap_crtc->name); 166 167 @@ -445,6 +524,11 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc, 168 } 169 spin_unlock_irq(&crtc->dev->event_lock); 170 171 + cancel_delayed_work(&omap_crtc->update_work); 172 + 173 + if (!omap_crtc_wait_pending(crtc)) 174 + dev_warn(dev->dev, "manual display update did not finish!"); 175 + 176 drm_crtc_vblank_off(crtc); 177 } 178 179 @@ -559,13 +643,20 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, 180 181 DBG("%s: GO", omap_crtc->name); 182 183 - ret = drm_crtc_vblank_get(crtc); 184 - WARN_ON(ret != 0); 185 + if (!omap_crtc_is_manually_updated(crtc)) { 186 + ret = drm_crtc_vblank_get(crtc); 187 + WARN_ON(ret != 0); 188 189 - spin_lock_irq(&crtc->dev->event_lock); 190 - priv->dispc_ops->mgr_go(omap_crtc->channel); 191 - omap_crtc_arm_event(crtc); 192 - spin_unlock_irq(&crtc->dev->event_lock); 193 + spin_lock_irq(&crtc->dev->event_lock); 194 + priv->dispc_ops->mgr_go(omap_crtc->channel); 195 + omap_crtc_arm_event(crtc); 196 + spin_unlock_irq(&crtc->dev->event_lock); 197 + } else { 198 + spin_lock_irq(&crtc->dev->event_lock); 199 + omap_crtc_flush(crtc); 200 + omap_crtc_arm_event(crtc); 201 + spin_unlock_irq(&crtc->dev->event_lock); 202 + } 203 } 204 205 static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, 206 @@ -726,6 +817,9 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, 207 omap_crtc->channel = channel; 208 omap_crtc->name = channel_names[channel]; 209 210 + INIT_DELAYED_WORK(&omap_crtc->update_work, 211 + omap_crtc_manual_display_update); 212 + 213 ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, 214 &omap_crtc_funcs, NULL); 215 if (ret < 0) { 216 diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h 217 index f6c48f2..3cb9f9a 100644 218 --- a/drivers/gpu/drm/omapdrm/omap_drv.h 219 +++ b/drivers/gpu/drm/omapdrm/omap_drv.h 220 @@ -126,6 +126,7 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc); 221 void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus); 222 void omap_crtc_vblank_irq(struct drm_crtc *crtc); 223 void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus); 224 +void omap_crtc_flush(struct drm_crtc *crtc); 225 226 struct drm_plane *omap_plane_init(struct drm_device *dev, 227 int idx, enum drm_plane_type type, 228 diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c 229 index b1a762b..9492be6 100644 230 --- a/drivers/gpu/drm/omapdrm/omap_fb.c 231 +++ b/drivers/gpu/drm/omapdrm/omap_fb.c 232 @@ -97,8 +97,28 @@ static void omap_framebuffer_destroy(struct drm_framebuffer *fb) 233 kfree(omap_fb); 234 } 235 236 +static int omap_framebuffer_dirty(struct drm_framebuffer *fb, 237 + struct drm_file *file_priv, 238 + unsigned flags, unsigned color, 239 + struct drm_clip_rect *clips, 240 + unsigned num_clips) 241 +{ 242 + struct drm_connector *connector = NULL; 243 + 244 + drm_modeset_lock_all(fb->dev); 245 + 246 + while ((connector = omap_framebuffer_get_next_connector(fb, connector))) 247 + if (connector->encoder && connector->encoder->crtc) 248 + omap_crtc_flush(connector->encoder->crtc); 249 + 250 + drm_modeset_unlock_all(fb->dev); 251 + 252 + return 0; 253 +} 254 + 255 static const struct drm_framebuffer_funcs omap_framebuffer_funcs = { 256 .create_handle = omap_framebuffer_create_handle, 257 + .dirty = omap_framebuffer_dirty, 258 .destroy = omap_framebuffer_destroy, 259 }; 260 261 -- 262 2.1.4 263