arm-sdk

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

0001-PATCHv2-3-8-drm-omap-add-support-for-manually-updated-displays.patch (9065B)


      1 From patchwork Thu Feb  8 18:30:30 2018
      2 Content-Type: text/plain; charset="utf-8"
      3 MIME-Version: 1.0
      4 Content-Transfer-Encoding: 7bit
      5 Subject: [PATCHv2,3/8] drm/omap: add support for manually updated displays
      6 From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
      7 X-Patchwork-Id: 10207759
      8 Message-Id: <20180208183035.8461-4-sebastian.reichel@collabora.co.uk>
      9 To: Sebastian Reichel <sre@kernel.org>,
     10  Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
     11 Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
     12  Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
     13  Mark Rutland <mark.rutland@arm.com>,
     14  dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
     15  linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
     16  kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
     17 Date: Thu,  8 Feb 2018 19:30:30 +0100
     18 
     19 This adds the required infrastructure for manually
     20 updated displays, such as DSI command mode panels.
     21 
     22 While those panels often support partial updates
     23 we currently always do a full refresh. Display
     24 will be refreshed when something calls the dirty
     25 callback, such as libdrm's drmModeDirtyFB().
     26 
     27 This is currently being implemented for the kernel
     28 console and for Xorg. Weston currently does not
     29 implement this and is known not to work on manually
     30 updated displays.
     31 
     32 Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
     33 Tested-by: Tony Lindgren <tony@atomide.com>
     34 ---
     35  drivers/gpu/drm/omapdrm/omap_crtc.c | 110 +++++++++++++++++++++++++++++++++---
     36  drivers/gpu/drm/omapdrm/omap_crtc.h |   1 +
     37  drivers/gpu/drm/omapdrm/omap_fb.c   |  20 +++++++
     38  3 files changed, 123 insertions(+), 8 deletions(-)
     39 
     40 diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
     41 index 2278e3433008..c2defb514b9f 100644
     42 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c
     43 +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
     44 @@ -51,6 +51,7 @@ struct omap_crtc {
     45  	bool pending;
     46  	wait_queue_head_t pending_wait;
     47  	struct drm_pending_vblank_event *event;
     48 +	struct delayed_work update_work;
     49  
     50  	void (*framedone_handler)(void *);
     51  	void *framedone_handler_data;
     52 @@ -142,6 +143,28 @@ static void omap_crtc_dss_disconnect(enum omap_channel channel,
     53  
     54  static void omap_crtc_dss_start_update(enum omap_channel channel)
     55  {
     56 +	struct omap_crtc *omap_crtc = omap_crtcs[channel];
     57 +	struct omap_drm_private *priv = omap_crtc->base.dev->dev_private;
     58 +
     59 +	priv->dispc_ops->mgr_enable(channel, true);
     60 +}
     61 +
     62 +static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc)
     63 +{
     64 +	struct drm_connector *connector;
     65 +	struct drm_connector_list_iter conn_iter;
     66 +	bool result = false;
     67 +
     68 +	drm_connector_list_iter_begin(crtc->dev, &conn_iter);
     69 +	drm_for_each_connector_iter(connector, &conn_iter) {
     70 +		if (connector->state->crtc != crtc)
     71 +			continue;
     72 +		result = omap_connector_get_manually_updated(connector);
     73 +		break;
     74 +	}
     75 +	drm_connector_list_iter_end(&conn_iter);
     76 +
     77 +	return result;
     78  }
     79  
     80  /* Called only from the encoder enable/disable and suspend/resume handlers. */
     81 @@ -153,12 +176,17 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
     82  	enum omap_channel channel = omap_crtc->channel;
     83  	struct omap_irq_wait *wait;
     84  	u32 framedone_irq, vsync_irq;
     85 +	bool is_manual = omap_crtc_is_manually_updated(crtc);
     86 +	enum omap_display_type type = omap_crtc_output[channel]->output_type;
     87  	int ret;
     88  
     89  	if (WARN_ON(omap_crtc->enabled == enable))
     90  		return;
     91  
     92 -	if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) {
     93 +	if (is_manual)
     94 +		omap_irq_enable_framedone(crtc, enable);
     95 +
     96 +	if (is_manual || type == OMAP_DISPLAY_TYPE_HDMI) {
     97  		priv->dispc_ops->mgr_enable(channel, enable);
     98  		omap_crtc->enabled = enable;
     99  		return;
    100 @@ -209,7 +237,6 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
    101  	}
    102  }
    103  
    104 -
    105  static int omap_crtc_dss_enable(enum omap_channel channel)
    106  {
    107  	struct omap_crtc *omap_crtc = omap_crtcs[channel];
    108 @@ -369,6 +396,53 @@ void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus)
    109  	wake_up(&omap_crtc->pending_wait);
    110  }
    111  
    112 +void omap_crtc_flush(struct drm_crtc *crtc)
    113 +{
    114 +	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
    115 +
    116 +	if (!omap_crtc_is_manually_updated(crtc))
    117 +		return;
    118 +
    119 +	if (!delayed_work_pending(&omap_crtc->update_work))
    120 +		schedule_delayed_work(&omap_crtc->update_work, 0);
    121 +}
    122 +
    123 +static void omap_crtc_manual_display_update(struct work_struct *data)
    124 +{
    125 +	struct omap_crtc *omap_crtc =
    126 +			container_of(data, struct omap_crtc, update_work.work);
    127 +	struct omap_dss_device *dssdev = omap_crtc_output[omap_crtc->channel];
    128 +	struct drm_device *dev = omap_crtc->base.dev;
    129 +	struct omap_dss_driver *dssdrv;
    130 +	int ret, width, height;
    131 +
    132 +	if (!dssdev || !dssdev->dst) {
    133 +		dev_err_once(dev->dev, "missing dssdev!");
    134 +		return;
    135 +	}
    136 +
    137 +	dssdev = dssdev->dst;
    138 +	dssdrv = dssdev->driver;
    139 +
    140 +	if (!dssdrv || !dssdrv->update) {
    141 +		dev_err_once(dev->dev, "incorrect dssdrv!");
    142 +		return;
    143 +	}
    144 +
    145 +	if (dssdrv->sync)
    146 +		dssdrv->sync(dssdev);
    147 +
    148 +	width = dssdev->panel.vm.hactive;
    149 +	height = dssdev->panel.vm.vactive;
    150 +	ret = dssdrv->update(dssdev, 0, 0, width, height);
    151 +	if (ret < 0) {
    152 +		spin_lock_irq(&dev->event_lock);
    153 +		omap_crtc->pending = false;
    154 +		spin_unlock_irq(&dev->event_lock);
    155 +		wake_up(&omap_crtc->pending_wait);
    156 +	}
    157 +}
    158 +
    159  static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
    160  {
    161  	struct omap_drm_private *priv = crtc->dev->dev_private;
    162 @@ -421,6 +495,10 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
    163  
    164  	DBG("%s", omap_crtc->name);
    165  
    166 +	/* manual updated display will not trigger vsync irq */
    167 +	if (omap_crtc_is_manually_updated(crtc))
    168 +		return;
    169 +
    170  	spin_lock_irq(&crtc->dev->event_lock);
    171  	drm_crtc_vblank_on(crtc);
    172  	ret = drm_crtc_vblank_get(crtc);
    173 @@ -434,6 +512,7 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
    174  				     struct drm_crtc_state *old_state)
    175  {
    176  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
    177 +	struct drm_device *dev = crtc->dev;
    178  
    179  	DBG("%s", omap_crtc->name);
    180  
    181 @@ -444,6 +523,11 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
    182  	}
    183  	spin_unlock_irq(&crtc->dev->event_lock);
    184  
    185 +	cancel_delayed_work(&omap_crtc->update_work);
    186 +
    187 +	if (!omap_crtc_wait_pending(crtc))
    188 +		dev_warn(dev->dev, "manual display update did not finish!");
    189 +
    190  	drm_crtc_vblank_off(crtc);
    191  }
    192  
    193 @@ -593,13 +677,20 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
    194  
    195  	DBG("%s: GO", omap_crtc->name);
    196  
    197 -	ret = drm_crtc_vblank_get(crtc);
    198 -	WARN_ON(ret != 0);
    199 +	if (!omap_crtc_is_manually_updated(crtc)) {
    200 +		ret = drm_crtc_vblank_get(crtc);
    201 +		WARN_ON(ret != 0);
    202  
    203 -	spin_lock_irq(&crtc->dev->event_lock);
    204 -	priv->dispc_ops->mgr_go(omap_crtc->channel);
    205 -	omap_crtc_arm_event(crtc);
    206 -	spin_unlock_irq(&crtc->dev->event_lock);
    207 +		spin_lock_irq(&crtc->dev->event_lock);
    208 +		priv->dispc_ops->mgr_go(omap_crtc->channel);
    209 +		omap_crtc_arm_event(crtc);
    210 +		spin_unlock_irq(&crtc->dev->event_lock);
    211 +	} else {
    212 +		spin_lock_irq(&crtc->dev->event_lock);
    213 +		omap_crtc_flush(crtc);
    214 +		omap_crtc_arm_event(crtc);
    215 +		spin_unlock_irq(&crtc->dev->event_lock);
    216 +	}
    217  }
    218  
    219  static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
    220 @@ -761,6 +852,9 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
    221  	omap_crtc->channel = channel;
    222  	omap_crtc->name = channel_names[channel];
    223  
    224 +	INIT_DELAYED_WORK(&omap_crtc->update_work,
    225 +			  omap_crtc_manual_display_update);
    226 +
    227  	ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
    228  					&omap_crtc_funcs, NULL);
    229  	if (ret < 0) {
    230 diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.h b/drivers/gpu/drm/omapdrm/omap_crtc.h
    231 index bd316bc0b6f4..b61c94b34f04 100644
    232 --- a/drivers/gpu/drm/omapdrm/omap_crtc.h
    233 +++ b/drivers/gpu/drm/omapdrm/omap_crtc.h
    234 @@ -40,5 +40,6 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc);
    235  void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
    236  void omap_crtc_vblank_irq(struct drm_crtc *crtc);
    237  void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus);
    238 +void omap_crtc_flush(struct drm_crtc *crtc);
    239  
    240  #endif /* __OMAPDRM_CRTC_H__ */
    241 diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
    242 index b2539a90e1a4..57b1767bef09 100644
    243 --- a/drivers/gpu/drm/omapdrm/omap_fb.c
    244 +++ b/drivers/gpu/drm/omapdrm/omap_fb.c
    245 @@ -95,8 +95,28 @@ static void omap_framebuffer_destroy(struct drm_framebuffer *fb)
    246  	kfree(omap_fb);
    247  }
    248  
    249 +static int omap_framebuffer_dirty(struct drm_framebuffer *fb,
    250 +				  struct drm_file *file_priv,
    251 +				  unsigned flags, unsigned color,
    252 +				  struct drm_clip_rect *clips,
    253 +				  unsigned num_clips)
    254 +{
    255 +	struct drm_connector *connector = NULL;
    256 +
    257 +	drm_modeset_lock_all(fb->dev);
    258 +
    259 +	while ((connector = omap_framebuffer_get_next_connector(fb, connector)))
    260 +		if (connector->encoder && connector->encoder->crtc)
    261 +			omap_crtc_flush(connector->encoder->crtc);
    262 +
    263 +	drm_modeset_unlock_all(fb->dev);
    264 +
    265 +	return 0;
    266 +}
    267 +
    268  static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
    269  	.create_handle = omap_framebuffer_create_handle,
    270 +	.dirty = omap_framebuffer_dirty,
    271  	.destroy = omap_framebuffer_destroy,
    272  };
    273