arm-sdk

os build toolkit for various embedded devices
git clone https://git.parazyd.org/arm-sdk
Log | Files | Refs | Submodules | README | LICENSE

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