* [PATCH 00/38] Renesas R-Car DU atomic updates support
@ 2015-02-25 21:54 Laurent Pinchart
2015-02-25 21:54 ` [PATCH 01/38] drm/atomic: Rename drm_atomic_helper_commit_pre_planes() state argument Laurent Pinchart
` (38 more replies)
0 siblings, 39 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Hello,
This patch series implements atomic updates support for the rcar-du driver.
The series starts with four core atomic helpers fixes/cleanups (two from
Daniel that I have included here for completeness). It then follows with two
fixes for the adv7511 driver and height fixes for the rcar-du driver. It
finally gets to work by slowly reworking rcar-du until atomic updates are
fully implemented and the transitional helpers gone.
The patches are based on Dave's 'next' branch and available at
git://linuxtv.org/pinchartl/fbdev.git drm/next/atomic
The last patch contains a hardware plane allocator based solely on state
objects, which could be useful as a base implementation should other drivers
experience similar needs.
Daniel Vetter (2):
drm/atomic-helper: Rename commmit_post/pre_planes
drm/atomic-helpers: make mode_set hooks optional
Laurent Pinchart (36):
drm/atomic: Rename drm_atomic_helper_commit_pre_planes() state
argument
drm/atomic-helpers: Fix documentation typos and wrong copy&paste
drm: adv7511: Fix DDC error interrupt handling
drm: adv7511: Fix nested sleep when reading EDID
drm: rcar-du: Don't disable unused functions at init time
drm: rcar-du: Remove drm_fbdev_cma_restore_mode() call at init time
drm: rcar-du: Don't set connector->encoder at init time
drm: rcar-du: Reorder CRTC functions
drm: rcar-du: Wait for page flip completion when turning the CRTC off
drm: rcar-du: Turn vblank on/off when enabling/disabling CRTC
drm: rcar-du: Disable fbdev emulation when no connector is present
drm: rcar-du: Define macros for the max number of groups, CRTCs and
LVDS
drm: rcar-du: Implement universal plane support
drm: rcar-du: Fix hardware plane allocation
drm: rcar-du: Implement planes atomic operations
drm: rcar-du: Handle primary plane config through atomic plane ops
drm: rcar-du: Wire up atomic state object scaffolding
drm: rcar-du: Remove private copy of plane size and position
drm: rcar-du: Replace LVDS encoder DPMS by enable/disable
drm: rcar-du: Rework encoder enable/disable for atomic updates
drm: rcar-du: Rework HDMI encoder enable/disable for atomic updates
drm: rcar-du: Rework CRTC enable/disable for atomic updates
drm: rcar-du: Switch plane update to atomic helpers
drm: rcar-du: Switch mode config to atomic helpers
drm: rcar-du: Switch connector DPMS to atomic helpers
drm: rcar-du: Replace encoder mode_fixup with atomic_check
drm: rcar-du: Implement asynchronous commit support
drm: rcar-du: Switch page flip to atomic helpers
drm: rcar-du: Switch plane set_property to atomic helpers
drm: rcar-du: Rework plane setup code
drm: rcar-du: Replace plane crtc and enabled fields by plane state
drm: rcar-du: Remove unneeded rcar_du_crtc plane field
drm: rcar-du: Move plane format to plane state
drm: rcar-du: Move plane commit code from CRTC start to CRTC resume
drm: rcar-du: Move group locking inside rcar_du_crtc_update_planes()
drm: rcar-du: Fix race condition in hardware plane allocator
drivers/gpu/drm/drm_atomic_helper.c | 68 +++--
drivers/gpu/drm/i2c/adv7511.c | 102 ++++----
drivers/gpu/drm/i915/intel_atomic.c | 4 +-
drivers/gpu/drm/msm/msm_atomic.c | 4 +-
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 400 +++++++++++++---------------
drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 8 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.c | 17 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 16 +-
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 71 ++---
drivers/gpu/drm/rcar-du/rcar_du_group.h | 5 +
drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 9 +-
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 65 +++--
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 333 ++++++++++++++++++++++--
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 9 +-
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 18 +-
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h | 8 +-
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 419 ++++++++++++------------------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 69 +++--
drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 9 +-
include/drm/drm_atomic_helper.h | 6 +-
include/drm/drm_crtc_helper.h | 3 +-
21 files changed, 924 insertions(+), 719 deletions(-)
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 01/38] drm/atomic: Rename drm_atomic_helper_commit_pre_planes() state argument
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 02/38] drm/atomic-helper: Rename commmit_post/pre_planes Laurent Pinchart
` (37 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The argument contains a pointer to the old state, rename it to old_state
like in all other commit helper functions.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 7e3a52b97c7d..6c5bfa2bd18a 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -770,18 +770,18 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
/**
* drm_atomic_helper_commit_pre_planes - modeset commit before plane updates
* @dev: DRM device
- * @state: atomic state
+ * @old_state: atomic state object with old state structures
*
* This function commits the modeset changes that need to be committed before
* updating planes. It shuts down all the outputs that need to be shut down and
* prepares them (if required) with the new mode.
*/
void drm_atomic_helper_commit_pre_planes(struct drm_device *dev,
- struct drm_atomic_state *state)
+ struct drm_atomic_state *old_state)
{
- disable_outputs(dev, state);
- set_routing_links(dev, state);
- crtc_set_mode(dev, state);
+ disable_outputs(dev, old_state);
+ set_routing_links(dev, old_state);
+ crtc_set_mode(dev, old_state);
}
EXPORT_SYMBOL(drm_atomic_helper_commit_pre_planes);
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 02/38] drm/atomic-helper: Rename commmit_post/pre_planes
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
2015-02-25 21:54 ` [PATCH 01/38] drm/atomic: Rename drm_atomic_helper_commit_pre_planes() state argument Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 03/38] drm/atomic-helpers: make mode_set hooks optional Laurent Pinchart
` (36 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
From: Daniel Vetter <daniel.vetter@ffwll.ch>
These names only make sense because of backwards compatability with
the order used by the crtc helper library. There's not really any real
requirement in the ordering here.
So rename them to something more descriptive and update the kerneldoc
a bit. Motivated in a discussion with Laurent about how to restore
plane state for dpms for drivers with runtime pm.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Acked-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 40 +++++++++++++++++++++++--------------
drivers/gpu/drm/i915/intel_atomic.c | 4 ++--
drivers/gpu/drm/msm/msm_atomic.c | 4 ++--
include/drm/drm_atomic_helper.h | 6 +++---
4 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 6c5bfa2bd18a..0a203a7a9a17 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -768,34 +768,44 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
}
/**
- * drm_atomic_helper_commit_pre_planes - modeset commit before plane updates
+ * drm_atomic_helper_commit_modeset_disables - modeset commit to disable outputs
* @dev: DRM device
* @old_state: atomic state object with old state structures
*
- * This function commits the modeset changes that need to be committed before
- * updating planes. It shuts down all the outputs that need to be shut down and
+ * This function shuts down all the outputs that need to be shut down and
* prepares them (if required) with the new mode.
+ *
+ * For compatability with legacy crtc helpers this should be called before
+ * drm_atomic_helper_commit_planes(), which is what the default commit function
+ * does. But drivers with different needs can group the modeset commits together
+ * and do the plane commits at the end. This is useful for drivers doing runtime
+ * PM since planes updates then only happen when the CRTC is actually enabled.
*/
-void drm_atomic_helper_commit_pre_planes(struct drm_device *dev,
- struct drm_atomic_state *old_state)
+void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
+ struct drm_atomic_state *old_state)
{
disable_outputs(dev, old_state);
set_routing_links(dev, old_state);
crtc_set_mode(dev, old_state);
}
-EXPORT_SYMBOL(drm_atomic_helper_commit_pre_planes);
+EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables);
/**
- * drm_atomic_helper_commit_post_planes - modeset commit after plane updates
+ * drm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs
* @dev: DRM device
* @old_state: atomic state object with old state structures
*
- * This function commits the modeset changes that need to be committed after
- * updating planes: It enables all the outputs with the new configuration which
- * had to be turned off for the update.
+ * This function enables all the outputs with the new configuration which had to
+ * be turned off for the update.
+ *
+ * For compatability with legacy crtc helpers this should be called after
+ * drm_atomic_helper_commit_planes(), which is what the default commit function
+ * does. But drivers with different needs can group the modeset commits together
+ * and do the plane commits at the end. This is useful for drivers doing runtime
+ * PM since planes updates then only happen when the CRTC is actually enabled.
*/
-void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
- struct drm_atomic_state *old_state)
+void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
+ struct drm_atomic_state *old_state)
{
int ncrtcs = old_state->dev->mode_config.num_crtc;
int i;
@@ -861,7 +871,7 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
encoder->bridge->funcs->enable(encoder->bridge);
}
}
-EXPORT_SYMBOL(drm_atomic_helper_commit_post_planes);
+EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
static void wait_for_fences(struct drm_device *dev,
struct drm_atomic_state *state)
@@ -1030,11 +1040,11 @@ int drm_atomic_helper_commit(struct drm_device *dev,
wait_for_fences(dev, state);
- drm_atomic_helper_commit_pre_planes(dev, state);
+ drm_atomic_helper_commit_modeset_disables(dev, state);
drm_atomic_helper_commit_planes(dev, state);
- drm_atomic_helper_commit_post_planes(dev, state);
+ drm_atomic_helper_commit_modeset_enables(dev, state);
drm_atomic_helper_wait_for_vblanks(dev, state);
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 19a9dd5408f3..011b8960fd75 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -134,9 +134,9 @@ int intel_atomic_commit(struct drm_device *dev,
* FIXME: The proper sequence here will eventually be:
*
* drm_atomic_helper_swap_state(dev, state)
- * drm_atomic_helper_commit_pre_planes(dev, state);
+ * drm_atomic_helper_commit_modeset_disables(dev, state);
* drm_atomic_helper_commit_planes(dev, state);
- * drm_atomic_helper_commit_post_planes(dev, state);
+ * drm_atomic_helper_commit_modeset_enables(dev, state);
* drm_atomic_helper_wait_for_vblanks(dev, state);
* drm_atomic_helper_cleanup_planes(dev, state);
* drm_atomic_state_free(state);
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 871aa2108dc6..7c412292a0ff 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -96,11 +96,11 @@ static void complete_commit(struct msm_commit *c)
kms->funcs->prepare_commit(kms, state);
- drm_atomic_helper_commit_pre_planes(dev, state);
+ drm_atomic_helper_commit_modeset_disables(dev, state);
drm_atomic_helper_commit_planes(dev, state);
- drm_atomic_helper_commit_post_planes(dev, state);
+ drm_atomic_helper_commit_modeset_enables(dev, state);
/* NOTE: _wait_for_vblanks() only waits for vblank on
* enabled CRTCs. So we end up faulting when disabling
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 8039d54a7441..829280b56874 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -43,9 +43,9 @@ int drm_atomic_helper_commit(struct drm_device *dev,
void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
struct drm_atomic_state *old_state);
-void drm_atomic_helper_commit_pre_planes(struct drm_device *dev,
- struct drm_atomic_state *state);
-void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
+void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
+ struct drm_atomic_state *state);
+void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
struct drm_atomic_state *old_state);
int drm_atomic_helper_prepare_planes(struct drm_device *dev,
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 03/38] drm/atomic-helpers: make mode_set hooks optional
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
2015-02-25 21:54 ` [PATCH 01/38] drm/atomic: Rename drm_atomic_helper_commit_pre_planes() state argument Laurent Pinchart
2015-02-25 21:54 ` [PATCH 02/38] drm/atomic-helper: Rename commmit_post/pre_planes Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 04/38] drm/atomic-helpers: Fix documentation typos and wrong copy&paste Laurent Pinchart
` (35 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
From: Daniel Vetter <daniel.vetter@ffwll.ch>
With runtime PM the hw might still be off while doing the ->mode_set
callbacks - runtime PM get/put should only happen in the
enable/disable hooks to properly support DPMS. Which essentially makes
these callbacks useless for drivers support runtime PM, so make them
optional. Again motivated by discussions with Laurent.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Acked-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 5 +++--
include/drm/drm_crtc_helper.h | 3 ++-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 0a203a7a9a17..caafc237c28b 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -723,7 +723,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
funcs = crtc->helper_private;
- if (crtc->state->enable) {
+ if (crtc->state->enable && funcs->mode_set_nofb) {
DRM_DEBUG_KMS("modeset on [CRTC:%d]\n",
crtc->base.id);
@@ -759,7 +759,8 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
* Each encoder has at most one connector (since we always steal
* it away), so we won't call call mode_set hooks twice.
*/
- funcs->mode_set(encoder, mode, adjusted_mode);
+ if (funcs->mode_set)
+ funcs->mode_set(encoder, mode, adjusted_mode);
if (encoder->bridge && encoder->bridge->funcs->mode_set)
encoder->bridge->funcs->mode_set(encoder->bridge,
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index c250a22b39ab..92d5135b55d2 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -89,6 +89,7 @@ struct drm_crtc_helper_funcs {
int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb);
+ /* Actually set the mode for atomic helpers, optional */
void (*mode_set_nofb)(struct drm_crtc *crtc);
/* Move the crtc on the current fb to the given position *optional* */
@@ -119,7 +120,7 @@ struct drm_crtc_helper_funcs {
* @mode_fixup: try to fixup proposed mode for this connector
* @prepare: part of the disable sequence, called before the CRTC modeset
* @commit: called after the CRTC modeset
- * @mode_set: set this mode
+ * @mode_set: set this mode, optional for atomic helpers
* @get_crtc: return CRTC that the encoder is currently attached to
* @detect: connection status detection
* @disable: disable encoder when not in use (overrides DPMS off)
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 04/38] drm/atomic-helpers: Fix documentation typos and wrong copy&paste
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (2 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 03/38] drm/atomic-helpers: make mode_set hooks optional Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 05/38] drm: adv7511: Fix DDC error interrupt handling Laurent Pinchart
` (34 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The kerneldoc blocks for the drm_atomic_helper_*_set_property()
functions seem to have been copied from the plane disable handler
without being properly updated. Fix them.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index caafc237c28b..df13c70d7899 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1689,12 +1689,13 @@ backoff:
EXPORT_SYMBOL(drm_atomic_helper_set_config);
/**
- * drm_atomic_helper_crtc_set_property - helper for crtc prorties
+ * drm_atomic_helper_crtc_set_property - helper for crtc properties
* @crtc: DRM crtc
* @property: DRM property
* @val: value of property
*
- * Provides a default plane disablle handler using the atomic driver interface.
+ * Provides a default crtc set_property handler using the atomic driver
+ * interface.
*
* RETURNS:
* Zero on success, error code on failure
@@ -1748,12 +1749,13 @@ backoff:
EXPORT_SYMBOL(drm_atomic_helper_crtc_set_property);
/**
- * drm_atomic_helper_plane_set_property - helper for plane prorties
+ * drm_atomic_helper_plane_set_property - helper for plane properties
* @plane: DRM plane
* @property: DRM property
* @val: value of property
*
- * Provides a default plane disable handler using the atomic driver interface.
+ * Provides a default plane set_property handler using the atomic driver
+ * interface.
*
* RETURNS:
* Zero on success, error code on failure
@@ -1807,12 +1809,13 @@ backoff:
EXPORT_SYMBOL(drm_atomic_helper_plane_set_property);
/**
- * drm_atomic_helper_connector_set_property - helper for connector prorties
+ * drm_atomic_helper_connector_set_property - helper for connector properties
* @connector: DRM connector
* @property: DRM property
* @val: value of property
*
- * Provides a default plane disablle handler using the atomic driver interface.
+ * Provides a default connector set_property handler using the atomic driver
+ * interface.
*
* RETURNS:
* Zero on success, error code on failure
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 05/38] drm: adv7511: Fix DDC error interrupt handling
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (3 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 04/38] drm/atomic-helpers: Fix documentation typos and wrong copy&paste Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 06/38] drm: adv7511: Fix nested sleep when reading EDID Laurent Pinchart
` (33 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The DDC error interrupt bit is located in REG_INT1, not REG_INT0. Update
both the interrupt wait code and the interrupt sources reset code
accordingly.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/i2c/adv7511.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c
index fa140e04d5fa..5109c215018e 100644
--- a/drivers/gpu/drm/i2c/adv7511.c
+++ b/drivers/gpu/drm/i2c/adv7511.c
@@ -467,14 +467,16 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
block);
ret = adv7511_wait_for_interrupt(adv7511,
ADV7511_INT0_EDID_READY |
- ADV7511_INT1_DDC_ERROR, 200);
+ (ADV7511_INT1_DDC_ERROR << 8), 200);
if (!(ret & ADV7511_INT0_EDID_READY))
return -EIO;
}
regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
- ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR);
+ ADV7511_INT0_EDID_READY);
+ regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
+ ADV7511_INT1_DDC_ERROR);
/* Break this apart, hopefully more I2C controllers will
* support 64 byte transfers than 256 byte transfers
@@ -528,7 +530,9 @@ static int adv7511_get_modes(struct drm_encoder *encoder,
/* Reading the EDID only works if the device is powered */
if (adv7511->dpms_mode != DRM_MODE_DPMS_ON) {
regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
- ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR);
+ ADV7511_INT0_EDID_READY);
+ regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
+ ADV7511_INT1_DDC_ERROR);
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
ADV7511_POWER_POWER_DOWN, 0);
adv7511->current_edid_segment = -1;
@@ -563,7 +567,9 @@ static void adv7511_encoder_dpms(struct drm_encoder *encoder, int mode)
adv7511->current_edid_segment = -1;
regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
- ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR);
+ ADV7511_INT0_EDID_READY);
+ regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
+ ADV7511_INT1_DDC_ERROR);
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
ADV7511_POWER_POWER_DOWN, 0);
/*
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 06/38] drm: adv7511: Fix nested sleep when reading EDID
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (4 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 05/38] drm: adv7511: Fix DDC error interrupt handling Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 07/38] drm: rcar-du: Don't disable unused functions at init time Laurent Pinchart
` (32 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The EDID read code waits for the read completion interrupt to occur
using wait_event_interruptible(). The condition passed to the macro
reads I2C registers. This results in sleeping with the task state set
to TASK_INTERRUPTIBLE, triggering a WARN_ON() introduced in commit
8eb23b9f35aae ("sched: Debug nested sleeps").
Fix this by reworking the EDID read code. Instead of checking whether
the read is complete through I2C reads, handle the interrupt registers
in the interrupt handler and update a new edid_read flag accordingly. As
a side effect both the IRQ and polling code paths now process the
interrupt sources through the same code path, simplifying the code.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/i2c/adv7511.c | 96 +++++++++++++++++++++----------------------
1 file changed, 46 insertions(+), 50 deletions(-)
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c
index 5109c215018e..60ab1f75d58e 100644
--- a/drivers/gpu/drm/i2c/adv7511.c
+++ b/drivers/gpu/drm/i2c/adv7511.c
@@ -33,6 +33,7 @@ struct adv7511 {
unsigned int current_edid_segment;
uint8_t edid_buf[256];
+ bool edid_read;
wait_queue_head_t wq;
struct drm_encoder *encoder;
@@ -379,69 +380,71 @@ static bool adv7511_hpd(struct adv7511 *adv7511)
return false;
}
-static irqreturn_t adv7511_irq_handler(int irq, void *devid)
-{
- struct adv7511 *adv7511 = devid;
-
- if (adv7511_hpd(adv7511))
- drm_helper_hpd_irq_event(adv7511->encoder->dev);
-
- wake_up_all(&adv7511->wq);
-
- return IRQ_HANDLED;
-}
-
-static unsigned int adv7511_is_interrupt_pending(struct adv7511 *adv7511,
- unsigned int irq)
+static int adv7511_irq_process(struct adv7511 *adv7511)
{
unsigned int irq0, irq1;
- unsigned int pending;
int ret;
ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
if (ret < 0)
- return 0;
+ return ret;
+
ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1);
if (ret < 0)
- return 0;
+ return ret;
+
+ regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
+ regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
+
+ if (irq0 & ADV7511_INT0_HDP)
+ drm_helper_hpd_irq_event(adv7511->encoder->dev);
+
+ if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
+ adv7511->edid_read = true;
- pending = (irq1 << 8) | irq0;
+ if (adv7511->i2c_main->irq)
+ wake_up_all(&adv7511->wq);
+ }
- return pending & irq;
+ return 0;
}
-static int adv7511_wait_for_interrupt(struct adv7511 *adv7511, int irq,
- int timeout)
+static irqreturn_t adv7511_irq_handler(int irq, void *devid)
+{
+ struct adv7511 *adv7511 = devid;
+ int ret;
+
+ ret = adv7511_irq_process(adv7511);
+ return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * EDID retrieval
+ */
+
+static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout)
{
- unsigned int pending;
int ret;
if (adv7511->i2c_main->irq) {
ret = wait_event_interruptible_timeout(adv7511->wq,
- adv7511_is_interrupt_pending(adv7511, irq),
- msecs_to_jiffies(timeout));
- if (ret <= 0)
- return 0;
- pending = adv7511_is_interrupt_pending(adv7511, irq);
+ adv7511->edid_read, msecs_to_jiffies(timeout));
} else {
- if (timeout < 25)
- timeout = 25;
- do {
- pending = adv7511_is_interrupt_pending(adv7511, irq);
- if (pending)
+ for (; timeout > 0; timeout -= 25) {
+ ret = adv7511_irq_process(adv7511);
+ if (ret < 0)
+ break;
+
+ if (adv7511->edid_read)
break;
+
msleep(25);
- timeout -= 25;
- } while (timeout >= 25);
+ }
}
- return pending;
+ return adv7511->edid_read ? 0 : -EIO;
}
-/* -----------------------------------------------------------------------------
- * EDID retrieval
- */
-
static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
size_t len)
{
@@ -463,21 +466,14 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
return ret;
if (status != 2) {
+ adv7511->edid_read = false;
regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT,
block);
- ret = adv7511_wait_for_interrupt(adv7511,
- ADV7511_INT0_EDID_READY |
- (ADV7511_INT1_DDC_ERROR << 8), 200);
-
- if (!(ret & ADV7511_INT0_EDID_READY))
- return -EIO;
+ ret = adv7511_wait_for_edid(adv7511, 200);
+ if (ret < 0)
+ return ret;
}
- regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
- ADV7511_INT0_EDID_READY);
- regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
- ADV7511_INT1_DDC_ERROR);
-
/* Break this apart, hopefully more I2C controllers will
* support 64 byte transfers than 256 byte transfers
*/
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 07/38] drm: rcar-du: Don't disable unused functions at init time
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (5 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 06/38] drm: adv7511: Fix nested sleep when reading EDID Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 08/38] drm: rcar-du: Remove drm_fbdev_cma_restore_mode() call " Laurent Pinchart
` (31 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
All encoders and CRTCs start disabled, re-disabling them is a no-op.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index cc9136e8ee9c..1ea2c1e9cb79 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -448,8 +448,6 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
drm_kms_helper_poll_init(dev);
- drm_helper_disable_unused_functions(dev);
-
fbdev = drm_fbdev_cma_init(dev, 32, dev->mode_config.num_crtc,
dev->mode_config.num_connector);
if (IS_ERR(fbdev))
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 08/38] drm: rcar-du: Remove drm_fbdev_cma_restore_mode() call at init time
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (6 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 07/38] drm: rcar-du: Don't disable unused functions at init time Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 09/38] drm: rcar-du: Don't set connector->encoder " Laurent Pinchart
` (30 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The function is meant to restore the fbdev mode in the lastclose
handler, not to be called at init time. Remove the call.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 1ea2c1e9cb79..aebbcde82ddf 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -453,10 +453,6 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
if (IS_ERR(fbdev))
return PTR_ERR(fbdev);
-#ifndef CONFIG_FRAMEBUFFER_CONSOLE
- drm_fbdev_cma_restore_mode(fbdev);
-#endif
-
rcdu->fbdev = fbdev;
return 0;
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 09/38] drm: rcar-du: Don't set connector->encoder at init time
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (7 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 08/38] drm: rcar-du: Remove drm_fbdev_cma_restore_mode() call " Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 10/38] drm: rcar-du: Reorder CRTC functions Laurent Pinchart
` (29 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The drm_connector encoder field points to the encoder driving the
connector. No such association exists at init time, as all pipelines are
disabled. Don't set the field.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 1 -
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 1 -
drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 1 -
3 files changed, 3 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
index ca94b029ac80..3896cb20ad51 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
@@ -116,7 +116,6 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
if (ret < 0)
return ret;
- connector->encoder = encoder;
rcon->encoder = renc;
return 0;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
index 6d9811c052c4..7c0b08fe0774 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
@@ -125,7 +125,6 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
if (ret < 0)
return ret;
- connector->encoder = encoder;
lvdscon->connector.encoder = renc;
return 0;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
index 9d4879921cc7..ae8b304e6fea 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
@@ -84,7 +84,6 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
if (ret < 0)
return ret;
- connector->encoder = encoder;
rcon->encoder = renc;
return 0;
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 10/38] drm: rcar-du: Reorder CRTC functions
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (8 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 09/38] drm: rcar-du: Don't set connector->encoder " Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 11/38] drm: rcar-du: Wait for page flip completion when turning the CRTC off Laurent Pinchart
` (28 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The next commit will need functions to be reordered to avoid forward
declarations. Do it separately to help review.
This only moves functions without any change to the code.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 142 +++++++++++++++++++--------------
1 file changed, 83 insertions(+), 59 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 25c7a998fc2c..e0562f2b3261 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -99,6 +99,10 @@ static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
clk_disable_unprepare(rcrtc->clock);
}
+/* -----------------------------------------------------------------------------
+ * Hardware Setup
+ */
+
static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
{
const struct drm_display_mode *mode = &rcrtc->crtc.mode;
@@ -256,6 +260,55 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
dspr);
}
+/* -----------------------------------------------------------------------------
+ * Page Flip
+ */
+
+void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
+ struct drm_file *file)
+{
+ struct drm_pending_vblank_event *event;
+ struct drm_device *dev = rcrtc->crtc.dev;
+ unsigned long flags;
+
+ /* Destroy the pending vertical blanking event associated with the
+ * pending page flip, if any, and disable vertical blanking interrupts.
+ */
+ spin_lock_irqsave(&dev->event_lock, flags);
+ event = rcrtc->event;
+ if (event && event->base.file_priv = file) {
+ rcrtc->event = NULL;
+ event->base.destroy(&event->base);
+ drm_vblank_put(dev, rcrtc->index);
+ }
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
+{
+ struct drm_pending_vblank_event *event;
+ struct drm_device *dev = rcrtc->crtc.dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ event = rcrtc->event;
+ rcrtc->event = NULL;
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+
+ if (event = NULL)
+ return;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ drm_send_vblank_event(dev, rcrtc->index, event);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+
+ drm_vblank_put(dev, rcrtc->index);
+}
+
+/* -----------------------------------------------------------------------------
+ * Start/Stop and Suspend/Resume
+ */
+
static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
{
struct drm_crtc *crtc = &rcrtc->crtc;
@@ -350,6 +403,10 @@ static void rcar_du_crtc_update_base(struct rcar_du_crtc *rcrtc)
rcar_du_plane_update_base(rcrtc->plane);
}
+/* -----------------------------------------------------------------------------
+ * CRTC Functions
+ */
+
static void rcar_du_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
@@ -485,65 +542,6 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.disable = rcar_du_crtc_disable,
};
-void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
- struct drm_file *file)
-{
- struct drm_pending_vblank_event *event;
- struct drm_device *dev = rcrtc->crtc.dev;
- unsigned long flags;
-
- /* Destroy the pending vertical blanking event associated with the
- * pending page flip, if any, and disable vertical blanking interrupts.
- */
- spin_lock_irqsave(&dev->event_lock, flags);
- event = rcrtc->event;
- if (event && event->base.file_priv = file) {
- rcrtc->event = NULL;
- event->base.destroy(&event->base);
- drm_vblank_put(dev, rcrtc->index);
- }
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
-{
- struct drm_pending_vblank_event *event;
- struct drm_device *dev = rcrtc->crtc.dev;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->event_lock, flags);
- event = rcrtc->event;
- rcrtc->event = NULL;
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- if (event = NULL)
- return;
-
- spin_lock_irqsave(&dev->event_lock, flags);
- drm_send_vblank_event(dev, rcrtc->index, event);
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- drm_vblank_put(dev, rcrtc->index);
-}
-
-static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
-{
- struct rcar_du_crtc *rcrtc = arg;
- irqreturn_t ret = IRQ_NONE;
- u32 status;
-
- status = rcar_du_crtc_read(rcrtc, DSSR);
- rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK);
-
- if (status & DSSR_FRM) {
- drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index);
- rcar_du_crtc_finish_page_flip(rcrtc);
- ret = IRQ_HANDLED;
- }
-
- return ret;
-}
-
static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
@@ -580,6 +578,32 @@ static const struct drm_crtc_funcs crtc_funcs = {
.page_flip = rcar_du_crtc_page_flip,
};
+/* -----------------------------------------------------------------------------
+ * Interrupt Handling
+ */
+
+static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
+{
+ struct rcar_du_crtc *rcrtc = arg;
+ irqreturn_t ret = IRQ_NONE;
+ u32 status;
+
+ status = rcar_du_crtc_read(rcrtc, DSSR);
+ rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK);
+
+ if (status & DSSR_FRM) {
+ drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index);
+ rcar_du_crtc_finish_page_flip(rcrtc);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Initialization
+ */
+
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
{
static const unsigned int mmio_offsets[] = {
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 11/38] drm: rcar-du: Wait for page flip completion when turning the CRTC off
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (9 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 10/38] drm: rcar-du: Reorder CRTC functions Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 12/38] drm: rcar-du: Turn vblank on/off when enabling/disabling CRTC Laurent Pinchart
` (27 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Turning a CRTC off will prevent a queued page flip from ever completing,
potentially confusing userspace. Wait for queued page flips to complete
before turning the CRTC off to avoid this.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 35 ++++++++++++++++++++++++++++++++++
drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 3 +++
2 files changed, 38 insertions(+)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index e0562f2b3261..7f5ae0269a61 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -300,11 +300,39 @@ static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
spin_lock_irqsave(&dev->event_lock, flags);
drm_send_vblank_event(dev, rcrtc->index, event);
+ wake_up(&rcrtc->flip_wait);
spin_unlock_irqrestore(&dev->event_lock, flags);
drm_vblank_put(dev, rcrtc->index);
}
+static bool rcar_du_crtc_page_flip_pending(struct rcar_du_crtc *rcrtc)
+{
+ struct drm_device *dev = rcrtc->crtc.dev;
+ unsigned long flags;
+ bool pending;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ pending = rcrtc->event != NULL;
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+
+ return pending;
+}
+
+static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *rcrtc)
+{
+ struct rcar_du_device *rcdu = rcrtc->group->dev;
+
+ if (wait_event_timeout(rcrtc->flip_wait,
+ !rcar_du_crtc_page_flip_pending(rcrtc),
+ msecs_to_jiffies(50)))
+ return;
+
+ dev_warn(rcdu->dev, "page flip timeout\n");
+
+ rcar_du_crtc_finish_page_flip(rcrtc);
+}
+
/* -----------------------------------------------------------------------------
* Start/Stop and Suspend/Resume
*/
@@ -365,6 +393,11 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
if (!rcrtc->started)
return;
+ /* Wait for page flip completion before stopping the CRTC as userspace
+ * excepts page flips to eventually complete.
+ */
+ rcar_du_crtc_wait_page_flip(rcrtc);
+
mutex_lock(&rcrtc->group->planes.lock);
rcrtc->plane->enabled = false;
rcar_du_crtc_update_planes(crtc);
@@ -644,6 +677,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
return -EPROBE_DEFER;
}
+ init_waitqueue_head(&rcrtc->flip_wait);
+
rcrtc->group = rgrp;
rcrtc->mmio_offset = mmio_offsets[index];
rcrtc->index = index;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index d2f89f7d2e5e..fb39e040f17b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -15,6 +15,7 @@
#define __RCAR_DU_CRTC_H__
#include <linux/mutex.h>
+#include <linux/wait.h>
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
@@ -32,6 +33,8 @@ struct rcar_du_crtc {
bool started;
struct drm_pending_vblank_event *event;
+ wait_queue_head_t flip_wait;
+
unsigned int outputs;
int dpms;
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 12/38] drm: rcar-du: Turn vblank on/off when enabling/disabling CRTC
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (10 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 11/38] drm: rcar-du: Wait for page flip completion when turning the CRTC off Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 13/38] drm: rcar-du: Disable fbdev emulation when no connector is present Laurent Pinchart
` (26 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The DRM core vblank handling mechanism requires drivers to forcefully
turn vblank reporting off when disabling the CRTC, and to restore the
vblank reporting status when enabling the CRTC.
Implement this using the drm_crtc_vblank_on/off helpers. When disabling
vblank we must first wait for page flips to complete, so implement page
flip completion wait as well.
Finally, drm_crtc_vblank_off() must be called at startup to synchronize
the state of the vblank core code with the hardware, which is initially
disabled. This is performed at CRTC creation time, requiring vertical
blanking to be initialized before creating CRTCs.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 18 +++++++++++++-----
drivers/gpu/drm/rcar-du/rcar_du_drv.c | 14 ++++++++------
2 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 7f5ae0269a61..5cf2cac75146 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -279,7 +279,7 @@ void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
if (event && event->base.file_priv = file) {
rcrtc->event = NULL;
event->base.destroy(&event->base);
- drm_vblank_put(dev, rcrtc->index);
+ drm_crtc_vblank_put(&rcrtc->crtc);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
@@ -303,7 +303,7 @@ static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
wake_up(&rcrtc->flip_wait);
spin_unlock_irqrestore(&dev->event_lock, flags);
- drm_vblank_put(dev, rcrtc->index);
+ drm_crtc_vblank_put(&rcrtc->crtc);
}
static bool rcar_du_crtc_page_flip_pending(struct rcar_du_crtc *rcrtc)
@@ -383,6 +383,9 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
rcar_du_group_start_stop(rcrtc->group, true);
+ /* Turn vertical blanking interrupt reporting back on. */
+ drm_crtc_vblank_on(crtc);
+
rcrtc->started = true;
}
@@ -393,10 +396,12 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
if (!rcrtc->started)
return;
- /* Wait for page flip completion before stopping the CRTC as userspace
- * excepts page flips to eventually complete.
+ /* Disable vertical blanking interrupt reporting. We first need to wait
+ * for page flip completion before stopping the CRTC as userspace
+ * expects page flips to eventually complete.
*/
rcar_du_crtc_wait_page_flip(rcrtc);
+ drm_crtc_vblank_off(crtc);
mutex_lock(&rcrtc->group->planes.lock);
rcrtc->plane->enabled = false;
@@ -596,7 +601,7 @@ static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
if (event) {
event->pipe = rcrtc->index;
- drm_vblank_get(dev, rcrtc->index);
+ drm_crtc_vblank_get(crtc);
spin_lock_irqsave(&dev->event_lock, flags);
rcrtc->event = event;
spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -693,6 +698,9 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
drm_crtc_helper_add(crtc, &crtc_helper_funcs);
+ /* Start with vertical blanking interrupt reporting disabled. */
+ drm_crtc_vblank_off(crtc);
+
/* Register the interrupt handler. */
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
irq = platform_get_irq(pdev, index);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index e0d74f821416..8ab4c69c599b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -175,17 +175,19 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
if (IS_ERR(rcdu->mmio))
return PTR_ERR(rcdu->mmio);
- /* DRM/KMS objects */
- ret = rcar_du_modeset_init(rcdu);
+ /* Initialize vertical blanking interrupts handling. Start with vblank
+ * disabled for all CRTCs.
+ */
+ ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
if (ret < 0) {
- dev_err(&pdev->dev, "failed to initialize DRM/KMS\n");
+ dev_err(&pdev->dev, "failed to initialize vblank\n");
goto done;
}
- /* vblank handling */
- ret = drm_vblank_init(dev, (1 << rcdu->num_crtcs) - 1);
+ /* DRM/KMS objects */
+ ret = rcar_du_modeset_init(rcdu);
if (ret < 0) {
- dev_err(&pdev->dev, "failed to initialize vblank\n");
+ dev_err(&pdev->dev, "failed to initialize DRM/KMS\n");
goto done;
}
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 13/38] drm: rcar-du: Disable fbdev emulation when no connector is present
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (11 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 12/38] drm: rcar-du: Turn vblank on/off when enabling/disabling CRTC Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 14/38] drm: rcar-du: Define macros for the max number of groups, CRTCs and LVDS Laurent Pinchart
` (25 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
fbdev emulation requires at least one connector, and will fail to
initialize if no connector has been successfully instantiated. Disable
it in that case and print an informational message instead of failing
probe with a confusing fbdev emulation error message.
It could be argued that probe should fail when no connector is present,
but the DU could still be useful in that case with the to-be-implemented
memory write-back support.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index aebbcde82ddf..888df404932e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -448,12 +448,17 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
drm_kms_helper_poll_init(dev);
- fbdev = drm_fbdev_cma_init(dev, 32, dev->mode_config.num_crtc,
- dev->mode_config.num_connector);
- if (IS_ERR(fbdev))
- return PTR_ERR(fbdev);
+ if (dev->mode_config.num_connector) {
+ fbdev = drm_fbdev_cma_init(dev, 32, dev->mode_config.num_crtc,
+ dev->mode_config.num_connector);
+ if (IS_ERR(fbdev))
+ return PTR_ERR(fbdev);
- rcdu->fbdev = fbdev;
+ rcdu->fbdev = fbdev;
+ } else {
+ dev_info(rcdu->dev,
+ "no connector found, disabling fbdev emulation\n");
+ }
return 0;
}
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 14/38] drm: rcar-du: Define macros for the max number of groups, CRTCs and LVDS
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (12 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 13/38] drm: rcar-du: Disable fbdev emulation when no connector is present Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 15/38] drm: rcar-du: Implement universal plane support Laurent Pinchart
` (24 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Let's avoid magic constants. Beside increasing code readability, it will
also ensure that no location will be forgotten when raising the maximum
number of groups, CRTCs or LVDS encoders
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index c5b9ea6a7eaa..d1ede13cb1d5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -64,6 +64,10 @@ struct rcar_du_device_info {
unsigned int num_lvds;
};
+#define RCAR_DU_MAX_CRTCS 3
+#define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
+#define RCAR_DU_MAX_LVDS 2
+
struct rcar_du_device {
struct device *dev;
const struct rcar_du_device_info *info;
@@ -73,13 +77,13 @@ struct rcar_du_device {
struct drm_device *ddev;
struct drm_fbdev_cma *fbdev;
- struct rcar_du_crtc crtcs[3];
+ struct rcar_du_crtc crtcs[RCAR_DU_MAX_CRTCS];
unsigned int num_crtcs;
- struct rcar_du_group groups[2];
+ struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
unsigned int dpad0_source;
- struct rcar_du_lvdsenc *lvds[2];
+ struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];
};
static inline bool rcar_du_has(struct rcar_du_device *rcdu,
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 15/38] drm: rcar-du: Implement universal plane support
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (13 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 14/38] drm: rcar-du: Define macros for the max number of groups, CRTCs and LVDS Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 16/38] drm: rcar-du: Fix hardware plane allocation Laurent Pinchart
` (23 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Explicitly create the CRTC primary plane instead of relying on the core
helpers to do so. This simplifies the plane logic by merging the KMS and
software planes.
Reject plane API operations on the primary planes for now, as that code
will anyway be refactored when implementing support for atomic updates.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 3 +-
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 7 ----
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 65 +++++++++++++++------------------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 17 ++++-----
4 files changed, 40 insertions(+), 52 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 5cf2cac75146..c2ca2a302f44 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -692,7 +692,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->plane->crtc = crtc;
- ret = drm_crtc_init(rcdu->ddev, crtc, &crtc_funcs);
+ ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, &rcrtc->plane->plane,
+ NULL, &crtc_funcs);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 888df404932e..413145de3db3 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -439,13 +439,6 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
encoder->possible_clones = (1 << num_encoders) - 1;
}
- /* Now that the CRTCs have been initialized register the planes. */
- for (i = 0; i < num_groups; ++i) {
- ret = rcar_du_planes_register(&rcdu->groups[i]);
- if (ret < 0)
- return ret;
- }
-
drm_kms_helper_poll_init(dev);
if (dev->mode_config.num_connector) {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 50f2f2b20d39..242db1e1a1e4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -26,14 +26,9 @@
#define RCAR_DU_COLORKEY_SOURCE (1 << 24)
#define RCAR_DU_COLORKEY_MASK (1 << 24)
-struct rcar_du_kms_plane {
- struct drm_plane plane;
- struct rcar_du_plane *hwplane;
-};
-
static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane)
{
- return container_of(plane, struct rcar_du_kms_plane, plane)->hwplane;
+ return container_of(plane, struct rcar_du_plane, plane);
}
static u32 rcar_du_plane_read(struct rcar_du_group *rgrp,
@@ -299,6 +294,9 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
unsigned int nplanes;
int ret;
+ if (plane->type != DRM_PLANE_TYPE_OVERLAY)
+ return -EINVAL;
+
format = rcar_du_format_info(fb->pixel_format);
if (format = NULL) {
dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
@@ -348,6 +346,9 @@ static int rcar_du_plane_disable(struct drm_plane *plane)
{
struct rcar_du_plane *rplane = to_rcar_plane(plane);
+ if (plane->type != DRM_PLANE_TYPE_OVERLAY)
+ return -EINVAL;
+
if (!rplane->enabled)
return 0;
@@ -453,7 +454,11 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
{
struct rcar_du_planes *planes = &rgrp->planes;
struct rcar_du_device *rcdu = rgrp->dev;
+ unsigned int num_planes;
+ unsigned int num_crtcs;
+ unsigned int crtcs;
unsigned int i;
+ int ret;
mutex_init(&planes->lock);
planes->free = 0xff;
@@ -478,45 +483,35 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
if (planes->zpos = NULL)
return -ENOMEM;
- for (i = 0; i < ARRAY_SIZE(planes->planes); ++i) {
+ /* Create one primary plane per in this group CRTC and seven overlay
+ * planes.
+ */
+ num_crtcs = min(rcdu->num_crtcs - 2 * rgrp->index, 2U);
+ num_planes = num_crtcs + 7;
+
+ crtcs = ((1 << rcdu->num_crtcs) - 1) & (3 << (2 * rgrp->index));
+
+ for (i = 0; i < num_planes; ++i) {
+ enum drm_plane_type type = i < num_crtcs
+ ? DRM_PLANE_TYPE_PRIMARY
+ : DRM_PLANE_TYPE_OVERLAY;
struct rcar_du_plane *plane = &planes->planes[i];
plane->group = rgrp;
plane->hwindex = -1;
plane->alpha = 255;
plane->colorkey = RCAR_DU_COLORKEY_NONE;
- plane->zpos = 0;
- }
-
- return 0;
-}
+ plane->zpos = type = DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
-int rcar_du_planes_register(struct rcar_du_group *rgrp)
-{
- struct rcar_du_planes *planes = &rgrp->planes;
- struct rcar_du_device *rcdu = rgrp->dev;
- unsigned int crtcs;
- unsigned int i;
- int ret;
-
- crtcs = ((1 << rcdu->num_crtcs) - 1) & (3 << (2 * rgrp->index));
-
- for (i = 0; i < RCAR_DU_NUM_KMS_PLANES; ++i) {
- struct rcar_du_kms_plane *plane;
-
- plane = devm_kzalloc(rcdu->dev, sizeof(*plane), GFP_KERNEL);
- if (plane = NULL)
- return -ENOMEM;
-
- plane->hwplane = &planes->planes[i + 2];
- plane->hwplane->zpos = 1;
-
- ret = drm_plane_init(rcdu->ddev, &plane->plane, crtcs,
- &rcar_du_plane_funcs, formats,
- ARRAY_SIZE(formats), false);
+ ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
+ &rcar_du_plane_funcs, formats,
+ ARRAY_SIZE(formats), type);
if (ret < 0)
return ret;
+ if (type = DRM_PLANE_TYPE_PRIMARY)
+ continue;
+
drm_object_attach_property(&plane->plane.base,
planes->alpha, 255);
drm_object_attach_property(&plane->plane.base,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 3021288b1a89..813b3212392a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -22,17 +22,17 @@
struct rcar_du_format_info;
struct rcar_du_group;
-/* The RCAR DU has 8 hardware planes, shared between KMS planes and CRTCs. As
- * using KMS planes requires at least one of the CRTCs being enabled, no more
- * than 7 KMS planes can be available. We thus create 7 KMS planes and
- * 9 software planes (one for each KMS planes and one for each CRTC).
+/* The RCAR DU has 8 hardware planes, shared between primary and overlay planes.
+ * As using overlay planes requires at least one of the CRTCs being enabled, no
+ * more than 7 overlay planes can be available. We thus create 1 primary plane
+ * per CRTC and 7 overlay planes, for a total of up to 9 KMS planes.
*/
-
-#define RCAR_DU_NUM_KMS_PLANES 7
+#define RCAR_DU_NUM_KMS_PLANES 9
#define RCAR_DU_NUM_HW_PLANES 8
-#define RCAR_DU_NUM_SW_PLANES 9
struct rcar_du_plane {
+ struct drm_plane plane;
+
struct rcar_du_group *group;
struct drm_crtc *crtc;
@@ -58,7 +58,7 @@ struct rcar_du_plane {
};
struct rcar_du_planes {
- struct rcar_du_plane planes[RCAR_DU_NUM_SW_PLANES];
+ struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
unsigned int free;
struct mutex lock;
@@ -68,7 +68,6 @@ struct rcar_du_planes {
};
int rcar_du_planes_init(struct rcar_du_group *rgrp);
-int rcar_du_planes_register(struct rcar_du_group *rgrp);
void rcar_du_plane_setup(struct rcar_du_plane *plane);
void rcar_du_plane_update_base(struct rcar_du_plane *plane);
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 16/38] drm: rcar-du: Fix hardware plane allocation
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (14 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 15/38] drm: rcar-du: Implement universal plane support Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 17/38] drm: rcar-du: Implement planes atomic operations Laurent Pinchart
` (22 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The hardware plane allocator loops over all planes to find free
candidates. However, instead of looping over the number of hardware
planes, it loops over the number of software planes, which happens to be
larger by one unit. This has no effect in practise as the extra plane is
always cleared in the mask of free planes, but it should still be fixed
for correctness.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 242db1e1a1e4..4a0669fd8176 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -54,7 +54,7 @@ int rcar_du_plane_reserve(struct rcar_du_plane *plane,
mutex_lock(&rgrp->planes.lock);
- for (i = 0; i < ARRAY_SIZE(rgrp->planes.planes); ++i) {
+ for (i = 0; i < RCAR_DU_NUM_HW_PLANES; ++i) {
if (!(rgrp->planes.free & (1 << i)))
continue;
@@ -63,7 +63,7 @@ int rcar_du_plane_reserve(struct rcar_du_plane *plane,
break;
}
- if (i = ARRAY_SIZE(rgrp->planes.planes))
+ if (i = RCAR_DU_NUM_HW_PLANES)
goto done;
rgrp->planes.free &= ~(1 << i);
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 17/38] drm: rcar-du: Implement planes atomic operations
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (15 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 16/38] drm: rcar-du: Fix hardware plane allocation Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 18/38] drm: rcar-du: Handle primary plane config through atomic plane ops Laurent Pinchart
` (21 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Implement the CRTC .atomic_begin() and .atomic_flush() operations, the
plane .atomic_check(), .atomic_update() and operations, and use the
transitional atomic helpers to implement the plane update and disable
operations on top of the new atomic operations.
The plane setup code can't be moved out of the CRTC start function
completely yet, as the atomic code paths are not taken every time the
CRTC needs to be started. This results in some code duplication that
will be fixed after switching to atomic updates completely.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 37 +++++++-
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 152 ++++++++++++++++++++++----------
2 files changed, 141 insertions(+), 48 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index c2ca2a302f44..3d862a894b17 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -357,12 +357,21 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
rcar_du_crtc_set_display_timing(rcrtc);
rcar_du_group_set_routing(rcrtc->group);
+ /* FIXME: Commit the planes state. This is required here as the CRTC can
+ * be started from the DPMS and system resume handler, which don't go
+ * through .atomic_plane_update() and .atomic_flush() to commit plane
+ * state. Similarly a mode set operation without any update to planes
+ * will not go through atomic plane configuration either. Additionally,
+ * given that the plane state atomic commit occurs between CRTC disable
+ * and enable, the hardware state could also be lost due to runtime PM,
+ * requiring a full commit here. This will be fixed later after
+ * switching to atomic updates completely.
+ */
mutex_lock(&rcrtc->group->planes.lock);
rcrtc->plane->enabled = true;
rcar_du_crtc_update_planes(crtc);
mutex_unlock(&rcrtc->group->planes.lock);
- /* Setup planes. */
for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
@@ -570,6 +579,30 @@ static void rcar_du_crtc_disable(struct drm_crtc *crtc)
rcar_du_plane_release(rcrtc->plane);
}
+static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc)
+{
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+
+ /* We need to access the hardware during atomic update, acquire a
+ * reference to the CRTC.
+ */
+ rcar_du_crtc_get(rcrtc);
+}
+
+static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc)
+{
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+
+ /* We're done, apply the configuration and drop the reference acquired
+ * in .atomic_begin().
+ */
+ mutex_lock(&rcrtc->group->planes.lock);
+ rcar_du_crtc_update_planes(crtc);
+ mutex_unlock(&rcrtc->group->planes.lock);
+
+ rcar_du_crtc_put(rcrtc);
+}
+
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.dpms = rcar_du_crtc_dpms,
.mode_fixup = rcar_du_crtc_mode_fixup,
@@ -578,6 +611,8 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.mode_set = rcar_du_crtc_mode_set,
.mode_set_base = rcar_du_crtc_mode_set_base,
.disable = rcar_du_crtc_disable,
+ .atomic_begin = rcar_du_crtc_atomic_begin,
+ .atomic_flush = rcar_du_crtc_atomic_flush,
};
static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 4a0669fd8176..03995c15bbe3 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -16,6 +16,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
#include "rcar_du_drv.h"
#include "rcar_du_kms.h"
@@ -45,6 +46,38 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
data);
}
+static int rcar_du_plane_reserve_check(struct rcar_du_plane *plane,
+ const struct rcar_du_format_info *format)
+{
+ struct rcar_du_group *rgrp = plane->group;
+ unsigned int free;
+ unsigned int i;
+ int ret;
+
+ mutex_lock(&rgrp->planes.lock);
+
+ free = rgrp->planes.free;
+
+ if (plane->hwindex != -1) {
+ free |= 1 << plane->hwindex;
+ if (plane->format->planes = 2)
+ free |= 1 << ((plane->hwindex + 1) % 8);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rgrp->planes.planes); ++i) {
+ if (!(free & (1 << i)))
+ continue;
+
+ if (format->planes = 1 || free & (1 << ((i + 1) % 8)))
+ break;
+ }
+
+ ret = i = ARRAY_SIZE(rgrp->planes.planes) ? -EBUSY : 0;
+
+ mutex_unlock(&rgrp->planes.lock);
+ return ret;
+}
+
int rcar_du_plane_reserve(struct rcar_du_plane *plane,
const struct rcar_du_format_info *format)
{
@@ -281,12 +314,8 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
rcar_du_plane_update_base(plane);
}
-static int
-rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+static int rcar_du_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
{
struct rcar_du_plane *rplane = to_rcar_plane(plane);
struct rcar_du_device *rcdu = rplane->group->dev;
@@ -294,63 +323,43 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
unsigned int nplanes;
int ret;
- if (plane->type != DRM_PLANE_TYPE_OVERLAY)
- return -EINVAL;
+ if (!state->fb || !state->crtc)
+ return 0;
- format = rcar_du_format_info(fb->pixel_format);
- if (format = NULL) {
- dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
- fb->pixel_format);
+ if (state->src_w >> 16 != state->crtc_w ||
+ state->src_h >> 16 != state->crtc_h) {
+ dev_dbg(rcdu->dev, "%s: scaling not supported\n", __func__);
return -EINVAL;
}
- if (src_w >> 16 != crtc_w || src_h >> 16 != crtc_h) {
- dev_dbg(rcdu->dev, "%s: scaling not supported\n", __func__);
+ format = rcar_du_format_info(state->fb->pixel_format);
+ if (format = NULL) {
+ dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
+ state->fb->pixel_format);
return -EINVAL;
}
nplanes = rplane->format ? rplane->format->planes : 0;
- /* Reallocate hardware planes if the number of required planes has
- * changed.
+ /* If the number of required planes has changed we will need to
+ * reallocate hardware planes. Ensure free planes are available.
*/
if (format->planes != nplanes) {
- rcar_du_plane_release(rplane);
- ret = rcar_du_plane_reserve(rplane, format);
- if (ret < 0)
+ ret = rcar_du_plane_reserve_check(rplane, format);
+ if (ret < 0) {
+ dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
+ __func__);
return ret;
+ }
}
- rplane->crtc = crtc;
- rplane->format = format;
-
- rplane->src_x = src_x >> 16;
- rplane->src_y = src_y >> 16;
- rplane->dst_x = crtc_x;
- rplane->dst_y = crtc_y;
- rplane->width = crtc_w;
- rplane->height = crtc_h;
-
- rcar_du_plane_compute_base(rplane, fb);
- rcar_du_plane_setup(rplane);
-
- mutex_lock(&rplane->group->planes.lock);
- rplane->enabled = true;
- rcar_du_crtc_update_planes(rplane->crtc);
- mutex_unlock(&rplane->group->planes.lock);
-
return 0;
}
-static int rcar_du_plane_disable(struct drm_plane *plane)
+static void rcar_du_plane_disable(struct rcar_du_plane *rplane)
{
- struct rcar_du_plane *rplane = to_rcar_plane(plane);
-
- if (plane->type != DRM_PLANE_TYPE_OVERLAY)
- return -EINVAL;
-
if (!rplane->enabled)
- return 0;
+ return;
mutex_lock(&rplane->group->planes.lock);
rplane->enabled = false;
@@ -361,10 +370,56 @@ static int rcar_du_plane_disable(struct drm_plane *plane)
rplane->crtc = NULL;
rplane->format = NULL;
+}
- return 0;
+static void rcar_du_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct rcar_du_plane *rplane = to_rcar_plane(plane);
+ struct drm_plane_state *state = plane->state;
+ const struct rcar_du_format_info *format;
+ unsigned int nplanes;
+
+ if (!state->crtc) {
+ rcar_du_plane_disable(rplane);
+ return;
+ }
+
+ format = rcar_du_format_info(state->fb->pixel_format);
+ nplanes = rplane->format ? rplane->format->planes : 0;
+
+ /* Reallocate hardware planes if the number of required planes has
+ * changed.
+ */
+ if (format->planes != nplanes) {
+ rcar_du_plane_release(rplane);
+ rcar_du_plane_reserve(rplane, format);
+ }
+
+ rplane->crtc = state->crtc;
+ rplane->format = format;
+
+ rplane->src_x = state->src_x >> 16;
+ rplane->src_y = state->src_y >> 16;
+ rplane->dst_x = state->crtc_x;
+ rplane->dst_y = state->crtc_y;
+ rplane->width = state->crtc_w;
+ rplane->height = state->crtc_h;
+
+ rcar_du_plane_compute_base(rplane, state->fb);
+ rcar_du_plane_setup(rplane);
+
+ mutex_lock(&rplane->group->planes.lock);
+ rplane->enabled = true;
+ rcar_du_crtc_update_planes(rplane->crtc);
+ mutex_unlock(&rplane->group->planes.lock);
}
+static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
+ .atomic_check = rcar_du_plane_atomic_check,
+ .atomic_update = rcar_du_plane_atomic_update,
+};
+
/* Both the .set_property and the .update_plane operations are called with the
* mode_config lock held. There is this no need to explicitly protect access to
* the alpha and colorkey fields and the mode register.
@@ -431,8 +486,8 @@ static int rcar_du_plane_set_property(struct drm_plane *plane,
}
static const struct drm_plane_funcs rcar_du_plane_funcs = {
- .update_plane = rcar_du_plane_update,
- .disable_plane = rcar_du_plane_disable,
+ .update_plane = drm_plane_helper_update,
+ .disable_plane = drm_plane_helper_disable,
.set_property = rcar_du_plane_set_property,
.destroy = drm_plane_cleanup,
};
@@ -509,6 +564,9 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
if (ret < 0)
return ret;
+ drm_plane_helper_add(&plane->plane,
+ &rcar_du_plane_helper_funcs);
+
if (type = DRM_PLANE_TYPE_PRIMARY)
continue;
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 18/38] drm: rcar-du: Handle primary plane config through atomic plane ops
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (16 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 17/38] drm: rcar-du: Implement planes atomic operations Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 19/38] drm: rcar-du: Wire up atomic state object scaffolding Laurent Pinchart
` (20 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Use the new CRTC atomic transitional helpers drm_helper_crtc_mode_set()
and drm_helper_crtc_mode_set_base() to implement the CRTC .mode_set and
.mode_set_base operations. This delegates primary plane configuration to
the plane .atomic_update and .atomic_disable operations, removing
duplicate code from the CRTC implementation.
There is now no code path available to the driver in which to drop the
reference to the CRTC acquired in the .prepare() operation if an error
then occurs. The driver thus now leaks a reference if an error occurs
during mode set. So be it, this will be fixed in a further step of the
atomic update transition.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 81 +++++----------------------------
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 8 ++--
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 3 --
3 files changed, 14 insertions(+), 78 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 3d862a894b17..169558a3ab40 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -105,7 +105,7 @@ static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
{
- const struct drm_display_mode *mode = &rcrtc->crtc.mode;
+ const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
unsigned long mode_clock = mode->clock * 1000;
unsigned long clk;
u32 value;
@@ -368,7 +368,6 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
* switching to atomic updates completely.
*/
mutex_lock(&rcrtc->group->planes.lock);
- rcrtc->plane->enabled = true;
rcar_du_crtc_update_planes(crtc);
mutex_unlock(&rcrtc->group->planes.lock);
@@ -412,11 +411,6 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
rcar_du_crtc_wait_page_flip(rcrtc);
drm_crtc_vblank_off(crtc);
- mutex_lock(&rcrtc->group->planes.lock);
- rcrtc->plane->enabled = false;
- rcar_du_crtc_update_planes(crtc);
- mutex_unlock(&rcrtc->group->planes.lock);
-
/* Select switch sync mode. This stops display operation and configures
* the HSYNC and VSYNC signals as inputs.
*/
@@ -492,58 +486,20 @@ static void rcar_du_crtc_mode_prepare(struct drm_crtc *crtc)
*/
rcar_du_crtc_get(rcrtc);
- /* Stop the CRTC and release the plane. Force the DPMS mode to off as a
- * result.
- */
+ /* Stop the CRTC, force the DPMS mode to off as a result. */
rcar_du_crtc_stop(rcrtc);
- rcar_du_plane_release(rcrtc->plane);
rcrtc->dpms = DRM_MODE_DPMS_OFF;
+ rcrtc->outputs = 0;
}
-static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y,
- struct drm_framebuffer *old_fb)
+static void rcar_du_crtc_mode_set_nofb(struct drm_crtc *crtc)
{
- struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- struct rcar_du_device *rcdu = rcrtc->group->dev;
- const struct rcar_du_format_info *format;
- int ret;
-
- format = rcar_du_format_info(crtc->primary->fb->pixel_format);
- if (format = NULL) {
- dev_dbg(rcdu->dev, "mode_set: unsupported format %08x\n",
- crtc->primary->fb->pixel_format);
- ret = -EINVAL;
- goto error;
- }
-
- ret = rcar_du_plane_reserve(rcrtc->plane, format);
- if (ret < 0)
- goto error;
-
- rcrtc->plane->format = format;
-
- rcrtc->plane->src_x = x;
- rcrtc->plane->src_y = y;
- rcrtc->plane->width = mode->hdisplay;
- rcrtc->plane->height = mode->vdisplay;
-
- rcar_du_plane_compute_base(rcrtc->plane, crtc->primary->fb);
-
- rcrtc->outputs = 0;
-
- return 0;
-
-error:
- /* There's no rollback/abort operation to clean up in case of error. We
- * thus need to release the reference to the CRTC acquired in prepare()
- * here.
+ /* No-op. We should configure the display timings here, but as we're
+ * called with the CRTC disabled clocks might be off, and we thus can't
+ * access the hardware. Let's just configure everything when enabling
+ * the CRTC.
*/
- rcar_du_crtc_put(rcrtc);
- return ret;
}
static void rcar_du_crtc_mode_commit(struct drm_crtc *crtc)
@@ -558,25 +514,9 @@ static void rcar_du_crtc_mode_commit(struct drm_crtc *crtc)
rcrtc->dpms = DRM_MODE_DPMS_ON;
}
-static int rcar_du_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
-
- rcrtc->plane->src_x = x;
- rcrtc->plane->src_y = y;
-
- rcar_du_crtc_update_base(rcrtc);
-
- return 0;
-}
-
static void rcar_du_crtc_disable(struct drm_crtc *crtc)
{
- struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
-
rcar_du_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
- rcar_du_plane_release(rcrtc->plane);
}
static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc)
@@ -608,8 +548,9 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.mode_fixup = rcar_du_crtc_mode_fixup,
.prepare = rcar_du_crtc_mode_prepare,
.commit = rcar_du_crtc_mode_commit,
- .mode_set = rcar_du_crtc_mode_set,
- .mode_set_base = rcar_du_crtc_mode_set_base,
+ .mode_set = drm_helper_crtc_mode_set,
+ .mode_set_nofb = rcar_du_crtc_mode_set_nofb,
+ .mode_set_base = drm_helper_crtc_mode_set_base,
.disable = rcar_du_crtc_disable,
.atomic_begin = rcar_du_crtc_atomic_begin,
.atomic_flush = rcar_du_crtc_atomic_flush,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 03995c15bbe3..d4682ac7db03 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -78,8 +78,8 @@ static int rcar_du_plane_reserve_check(struct rcar_du_plane *plane,
return ret;
}
-int rcar_du_plane_reserve(struct rcar_du_plane *plane,
- const struct rcar_du_format_info *format)
+static int rcar_du_plane_reserve(struct rcar_du_plane *plane,
+ const struct rcar_du_format_info *format)
{
struct rcar_du_group *rgrp = plane->group;
unsigned int i;
@@ -112,7 +112,7 @@ done:
return ret;
}
-void rcar_du_plane_release(struct rcar_du_plane *plane)
+static void rcar_du_plane_release(struct rcar_du_plane *plane)
{
struct rcar_du_group *rgrp = plane->group;
@@ -363,7 +363,6 @@ static void rcar_du_plane_disable(struct rcar_du_plane *rplane)
mutex_lock(&rplane->group->planes.lock);
rplane->enabled = false;
- rcar_du_crtc_update_planes(rplane->crtc);
mutex_unlock(&rplane->group->planes.lock);
rcar_du_plane_release(rplane);
@@ -411,7 +410,6 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
mutex_lock(&rplane->group->planes.lock);
rplane->enabled = true;
- rcar_du_crtc_update_planes(rplane->crtc);
mutex_unlock(&rplane->group->planes.lock);
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 813b3212392a..55d2f55faece 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -73,8 +73,5 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane);
void rcar_du_plane_update_base(struct rcar_du_plane *plane);
void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
struct drm_framebuffer *fb);
-int rcar_du_plane_reserve(struct rcar_du_plane *plane,
- const struct rcar_du_format_info *format);
-void rcar_du_plane_release(struct rcar_du_plane *plane);
#endif /* __RCAR_DU_PLANE_H__ */
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 19/38] drm: rcar-du: Wire up atomic state object scaffolding
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (17 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 18/38] drm: rcar-du: Handle primary plane config through atomic plane ops Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 20/38] drm: rcar-du: Remove private copy of plane size and position Laurent Pinchart
` (19 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Hook up the default .reset(), .atomic_duplicate_state() and
.atomic_free_state() helpers to ensure that state objects are properly
created and destroyed, and call drm_mode_config_reset() at init time to
create the initial state objects.
Framebuffer reference count also gets maintained automatically by the
transitional helpers except for the legacy page flip operation. Maintain
it explicitly there.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 7 +++++++
drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 4 ++++
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 2 ++
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 4 ++++
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 ++++
drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 4 ++++
6 files changed, 25 insertions(+)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 169558a3ab40..6e7266c1a47b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -15,6 +15,8 @@
#include <linux/mutex.h>
#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h>
@@ -572,6 +574,8 @@ static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
}
spin_unlock_irqrestore(&dev->event_lock, flags);
+ drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
+
crtc->primary->fb = fb;
rcar_du_crtc_update_base(rcrtc);
@@ -587,9 +591,12 @@ static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
}
static const struct drm_crtc_funcs crtc_funcs = {
+ .reset = drm_atomic_helper_crtc_reset,
.destroy = drm_crtc_cleanup,
.set_config = drm_crtc_helper_set_config,
.page_flip = rcar_du_crtc_page_flip,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
};
/* -----------------------------------------------------------------------------
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
index 3896cb20ad51..9378c283cb58 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
@@ -12,6 +12,7 @@
*/
#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_encoder_slave.h>
@@ -75,9 +76,12 @@ rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force)
static const struct drm_connector_funcs connector_funcs = {
.dpms = drm_helper_connector_dpms,
+ .reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_hdmi_connector_destroy,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 413145de3db3..94ff8fcc7268 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -439,6 +439,8 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
encoder->possible_clones = (1 << num_encoders) - 1;
}
+ drm_mode_config_reset(dev);
+
drm_kms_helper_poll_init(dev);
if (dev->mode_config.num_connector) {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
index 7c0b08fe0774..4bfa3ce34ab3 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
@@ -12,6 +12,7 @@
*/
#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
@@ -75,9 +76,12 @@ rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
static const struct drm_connector_funcs connector_funcs = {
.dpms = drm_helper_connector_dpms,
+ .reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_lvds_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_lvds_connector_destroy,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index d4682ac7db03..c4e4fd293eee 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -12,6 +12,7 @@
*/
#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h>
@@ -486,8 +487,11 @@ static int rcar_du_plane_set_property(struct drm_plane *plane,
static const struct drm_plane_funcs rcar_du_plane_funcs = {
.update_plane = drm_plane_helper_update,
.disable_plane = drm_plane_helper_disable,
+ .reset = drm_atomic_helper_plane_reset,
.set_property = rcar_du_plane_set_property,
.destroy = drm_plane_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
};
static const uint32_t formats[] = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
index ae8b304e6fea..a110cf22f3b0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
@@ -12,6 +12,7 @@
*/
#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
@@ -44,9 +45,12 @@ rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
static const struct drm_connector_funcs connector_funcs = {
.dpms = drm_helper_connector_dpms,
+ .reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_vga_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_vga_connector_destroy,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 20/38] drm: rcar-du: Remove private copy of plane size and position
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (18 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 19/38] drm: rcar-du: Wire up atomic state object scaffolding Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 21/38] drm: rcar-du: Replace LVDS encoder DPMS by enable/disable Laurent Pinchart
` (18 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The plane source and destination size and positions are stored in the
plane state, and a private copy is kept in the rcar_du_plane objects.
Remove the private copy as it just duplicates the state.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 25 ++++++++++---------------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 8 --------
2 files changed, 10 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index c4e4fd293eee..f247b1fcf791 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -132,6 +132,8 @@ static void rcar_du_plane_release(struct rcar_du_plane *plane)
void rcar_du_plane_update_base(struct rcar_du_plane *plane)
{
struct rcar_du_group *rgrp = plane->group;
+ unsigned int src_x = plane->plane.state->src_x >> 16;
+ unsigned int src_y = plane->plane.state->src_y >> 16;
unsigned int index = plane->hwindex;
bool interlaced;
u32 mwr;
@@ -163,8 +165,8 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
* require a halved Y position value, in both progressive and interlaced
* modes.
*/
- rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x);
- rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y *
+ rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
+ rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
(!interlaced && plane->format->bpp = 32 ? 2 : 1));
rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[0]);
@@ -173,8 +175,8 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
rcar_du_plane_write(rgrp, index, PnMWR, plane->pitch);
- rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x);
- rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y *
+ rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
+ rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
(plane->format->bpp = 16 ? 2 : 1) / 2);
rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[1]);
}
@@ -294,10 +296,10 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
/* Destination position and size */
- rcar_du_plane_write(rgrp, index, PnDSXR, plane->width);
- rcar_du_plane_write(rgrp, index, PnDSYR, plane->height);
- rcar_du_plane_write(rgrp, index, PnDPXR, plane->dst_x);
- rcar_du_plane_write(rgrp, index, PnDPYR, plane->dst_y);
+ rcar_du_plane_write(rgrp, index, PnDSXR, plane->plane.state->crtc_w);
+ rcar_du_plane_write(rgrp, index, PnDSYR, plane->plane.state->crtc_h);
+ rcar_du_plane_write(rgrp, index, PnDPXR, plane->plane.state->crtc_x);
+ rcar_du_plane_write(rgrp, index, PnDPYR, plane->plane.state->crtc_y);
/* Wrap-around and blinking, disabled */
rcar_du_plane_write(rgrp, index, PnWASPR, 0);
@@ -399,13 +401,6 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
rplane->crtc = state->crtc;
rplane->format = format;
- rplane->src_x = state->src_x >> 16;
- rplane->src_y = state->src_y >> 16;
- rplane->dst_x = state->crtc_x;
- rplane->dst_y = state->crtc_y;
- rplane->width = state->crtc_w;
- rplane->height = state->crtc_h;
-
rcar_du_plane_compute_base(rplane, state->fb);
rcar_du_plane_setup(rplane);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 55d2f55faece..3420ff07f2c6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -47,14 +47,6 @@ struct rcar_du_plane {
unsigned long dma[2];
unsigned int pitch;
-
- unsigned int width;
- unsigned int height;
-
- unsigned int src_x;
- unsigned int src_y;
- unsigned int dst_x;
- unsigned int dst_y;
};
struct rcar_du_planes {
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 21/38] drm: rcar-du: Replace LVDS encoder DPMS by enable/disable
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (19 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 20/38] drm: rcar-du: Remove private copy of plane size and position Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 22/38] drm: rcar-du: Rework encoder enable/disable for atomic updates Laurent Pinchart
` (17 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The LVDS encoder doesn't support DPMS states, replace the DPMS operation
by enable/disable to avoid propagating DPMS states down to the encoder
code.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 12 ++++--------
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 6 ++++--
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 18 +++++++++---------
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h | 8 ++++----
4 files changed, 21 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 279167f783f6..6243af310368 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -46,11 +46,9 @@ static void rcar_du_encoder_dpms(struct drm_encoder *encoder, int mode)
{
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
- if (mode != DRM_MODE_DPMS_ON)
- mode = DRM_MODE_DPMS_OFF;
-
if (renc->lvds)
- rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc, mode);
+ rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc,
+ mode = DRM_MODE_DPMS_ON);
}
static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -110,8 +108,7 @@ static void rcar_du_encoder_mode_prepare(struct drm_encoder *encoder)
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
if (renc->lvds)
- rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc,
- DRM_MODE_DPMS_OFF);
+ rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false);
}
static void rcar_du_encoder_mode_commit(struct drm_encoder *encoder)
@@ -119,8 +116,7 @@ static void rcar_du_encoder_mode_commit(struct drm_encoder *encoder)
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
if (renc->lvds)
- rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc,
- DRM_MODE_DPMS_ON);
+ rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);
}
static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index 221f0a17fd6a..89a7c0ecc935 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -44,13 +44,15 @@ static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode)
return;
if (mode = DRM_MODE_DPMS_ON && hdmienc->renc->lvds)
- rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode);
+ rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
+ true);
if (sfuncs->dpms)
sfuncs->dpms(encoder, mode);
if (mode != DRM_MODE_DPMS_ON && hdmienc->renc->lvds)
- rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode);
+ rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
+ false);
hdmienc->dpms = mode;
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index 7cfb48ce1791..85043c5bad03 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -28,7 +28,7 @@ struct rcar_du_lvdsenc {
unsigned int index;
void __iomem *mmio;
struct clk *clock;
- int dpms;
+ bool enabled;
enum rcar_lvds_input input;
};
@@ -48,7 +48,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
u32 pllcr;
int ret;
- if (lvds->dpms = DRM_MODE_DPMS_ON)
+ if (lvds->enabled)
return 0;
ret = clk_prepare_enable(lvds->clock);
@@ -110,13 +110,13 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
lvdcr0 |= LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
- lvds->dpms = DRM_MODE_DPMS_ON;
+ lvds->enabled = true;
return 0;
}
static void rcar_du_lvdsenc_stop(struct rcar_du_lvdsenc *lvds)
{
- if (lvds->dpms = DRM_MODE_DPMS_OFF)
+ if (!lvds->enabled)
return;
rcar_lvds_write(lvds, LVDCR0, 0);
@@ -124,13 +124,13 @@ static void rcar_du_lvdsenc_stop(struct rcar_du_lvdsenc *lvds)
clk_disable_unprepare(lvds->clock);
- lvds->dpms = DRM_MODE_DPMS_OFF;
+ lvds->enabled = false;
}
-int rcar_du_lvdsenc_dpms(struct rcar_du_lvdsenc *lvds,
- struct drm_crtc *crtc, int mode)
+int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
+ bool enable)
{
- if (mode = DRM_MODE_DPMS_OFF) {
+ if (!enable) {
rcar_du_lvdsenc_stop(lvds);
return 0;
} else if (crtc) {
@@ -179,7 +179,7 @@ int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
lvds->dev = rcdu;
lvds->index = i;
lvds->input = i ? RCAR_LVDS_INPUT_DU1 : RCAR_LVDS_INPUT_DU0;
- lvds->dpms = DRM_MODE_DPMS_OFF;
+ lvds->enabled = false;
ret = rcar_du_lvdsenc_get_resources(lvds, pdev);
if (ret < 0)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
index f65aabda0796..9a6001c07303 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
@@ -28,15 +28,15 @@ enum rcar_lvds_input {
#if IS_ENABLED(CONFIG_DRM_RCAR_LVDS)
int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu);
-int rcar_du_lvdsenc_dpms(struct rcar_du_lvdsenc *lvds,
- struct drm_crtc *crtc, int mode);
+int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
+ struct drm_crtc *crtc, bool enable);
#else
static inline int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
{
return 0;
}
-static inline int rcar_du_lvdsenc_dpms(struct rcar_du_lvdsenc *lvds,
- struct drm_crtc *crtc, int mode)
+static inline int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
+ struct drm_crtc *crtc, bool enable)
{
return 0;
}
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 22/38] drm: rcar-du: Rework encoder enable/disable for atomic updates
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (20 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 21/38] drm: rcar-du: Replace LVDS encoder DPMS by enable/disable Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 23/38] drm: rcar-du: Rework HDMI " Laurent Pinchart
` (16 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
When using atomic updates the encoder .enable() and .disable() helper
operations are preferred over the (then legacy) .prepare() and .commit()
operations. Implement .enable() and .disable() and rework .prepare(),
.commit() and .dpms() as wrappers around .enable() and .disable(),
easing their future removal.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 33 ++++++++++++++++++++-----------
1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 6243af310368..74a744f5dfdb 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -42,13 +42,28 @@ rcar_du_connector_best_encoder(struct drm_connector *connector)
* Encoder
*/
-static void rcar_du_encoder_dpms(struct drm_encoder *encoder, int mode)
+static void rcar_du_encoder_disable(struct drm_encoder *encoder)
{
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
if (renc->lvds)
- rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc,
- mode = DRM_MODE_DPMS_ON);
+ rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false);
+}
+
+static void rcar_du_encoder_enable(struct drm_encoder *encoder)
+{
+ struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+
+ if (renc->lvds)
+ rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);
+}
+
+static void rcar_du_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+ if (mode = DRM_MODE_DPMS_ON)
+ rcar_du_encoder_enable(encoder);
+ else
+ rcar_du_encoder_disable(encoder);
}
static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -105,18 +120,12 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
static void rcar_du_encoder_mode_prepare(struct drm_encoder *encoder)
{
- struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
-
- if (renc->lvds)
- rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false);
+ rcar_du_encoder_disable(encoder);
}
static void rcar_du_encoder_mode_commit(struct drm_encoder *encoder)
{
- struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
-
- if (renc->lvds)
- rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);
+ rcar_du_encoder_enable(encoder);
}
static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
@@ -134,6 +143,8 @@ static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
.prepare = rcar_du_encoder_mode_prepare,
.commit = rcar_du_encoder_mode_commit,
.mode_set = rcar_du_encoder_mode_set,
+ .disable = rcar_du_encoder_disable,
+ .enable = rcar_du_encoder_enable,
};
static const struct drm_encoder_funcs encoder_funcs = {
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 23/38] drm: rcar-du: Rework HDMI encoder enable/disable for atomic updates
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (21 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 22/38] drm: rcar-du: Rework encoder enable/disable for atomic updates Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 24/38] drm: rcar-du: Rework CRTC " Laurent Pinchart
` (15 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
When using atomic updates the encoder .enable() and .disable() helper
operations are preferred over the (then legacy) .prepare() and .commit()
operations. Implement .enable() and .disable() and rework .prepare(),
.commit() and .dpms() as wrappers around .enable() and .disable(),
easing their future removal.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 48 ++++++++++++++++++++++---------
1 file changed, 35 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index 89a7c0ecc935..04e21b5f96d4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -26,35 +26,54 @@
struct rcar_du_hdmienc {
struct rcar_du_encoder *renc;
struct device *dev;
- int dpms;
+ bool enabled;
};
#define to_rcar_hdmienc(e) (to_rcar_encoder(e)->hdmi)
#define to_slave_funcs(e) (to_rcar_encoder(e)->slave.slave_funcs)
-static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode)
+static void rcar_du_hdmienc_disable(struct drm_encoder *encoder)
{
struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
- if (mode != DRM_MODE_DPMS_ON)
- mode = DRM_MODE_DPMS_OFF;
+ if (sfuncs->dpms)
+ sfuncs->dpms(encoder, DRM_MODE_DPMS_OFF);
- if (hdmienc->dpms = mode)
- return;
+ if (hdmienc->renc->lvds)
+ rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
+ false);
+
+ hdmienc->enabled = false;
+}
+
+static void rcar_du_hdmienc_enable(struct drm_encoder *encoder)
+{
+ struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
+ struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
- if (mode = DRM_MODE_DPMS_ON && hdmienc->renc->lvds)
+ if (hdmienc->renc->lvds)
rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
true);
if (sfuncs->dpms)
- sfuncs->dpms(encoder, mode);
+ sfuncs->dpms(encoder, DRM_MODE_DPMS_ON);
- if (mode != DRM_MODE_DPMS_ON && hdmienc->renc->lvds)
- rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
- false);
+ hdmienc->enabled = true;
+}
- hdmienc->dpms = mode;
+static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
+ bool enable = mode = DRM_MODE_DPMS_ON;
+
+ if (hdmienc->enabled = enable)
+ return;
+
+ if (enable)
+ rcar_du_hdmienc_enable(encoder);
+ else
+ rcar_du_hdmienc_disable(encoder);
}
static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder,
@@ -106,13 +125,16 @@ static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
.prepare = rcar_du_hdmienc_mode_prepare,
.commit = rcar_du_hdmienc_mode_commit,
.mode_set = rcar_du_hdmienc_mode_set,
+ .disable = rcar_du_hdmienc_disable,
+ .enable = rcar_du_hdmienc_enable,
};
static void rcar_du_hdmienc_cleanup(struct drm_encoder *encoder)
{
struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
- rcar_du_hdmienc_dpms(encoder, DRM_MODE_DPMS_OFF);
+ if (hdmienc->enabled)
+ rcar_du_hdmienc_disable(encoder);
drm_encoder_cleanup(encoder);
put_device(hdmienc->dev);
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 24/38] drm: rcar-du: Rework CRTC enable/disable for atomic updates
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (22 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 23/38] drm: rcar-du: Rework HDMI " Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 25/38] drm: rcar-du: Switch plane update to atomic helpers Laurent Pinchart
` (14 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
When using atomic updates the CRTC .enable() and .disable() helper
operations are preferred over the (then legacy) .prepare() and .commit()
operations. Implement .enable() and rework .disable() to not depend on
DPMS, easing DPMS removal later on.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 59 ++++++++++++++++++++--------------
drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 2 +-
2 files changed, 35 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 6e7266c1a47b..7fdb968756ba 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -431,7 +431,7 @@ void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc)
void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
{
- if (rcrtc->dpms != DRM_MODE_DPMS_ON)
+ if (!rcrtc->enabled)
return;
rcar_du_crtc_get(rcrtc);
@@ -450,25 +450,38 @@ static void rcar_du_crtc_update_base(struct rcar_du_crtc *rcrtc)
* CRTC Functions
*/
-static void rcar_du_crtc_dpms(struct drm_crtc *crtc, int mode)
+static void rcar_du_crtc_enable(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- if (mode != DRM_MODE_DPMS_ON)
- mode = DRM_MODE_DPMS_OFF;
+ if (rcrtc->enabled)
+ return;
+
+ rcar_du_crtc_get(rcrtc);
+ rcar_du_crtc_start(rcrtc);
+
+ rcrtc->enabled = true;
+}
+
+static void rcar_du_crtc_disable(struct drm_crtc *crtc)
+{
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- if (rcrtc->dpms = mode)
+ if (!rcrtc->enabled)
return;
- if (mode = DRM_MODE_DPMS_ON) {
- rcar_du_crtc_get(rcrtc);
- rcar_du_crtc_start(rcrtc);
- } else {
- rcar_du_crtc_stop(rcrtc);
- rcar_du_crtc_put(rcrtc);
- }
+ rcar_du_crtc_stop(rcrtc);
+ rcar_du_crtc_put(rcrtc);
- rcrtc->dpms = mode;
+ rcrtc->enabled = false;
+}
+
+static void rcar_du_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+ if (mode = DRM_MODE_DPMS_ON)
+ rcar_du_crtc_enable(crtc);
+ else
+ rcar_du_crtc_disable(crtc);
}
static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -488,10 +501,10 @@ static void rcar_du_crtc_mode_prepare(struct drm_crtc *crtc)
*/
rcar_du_crtc_get(rcrtc);
- /* Stop the CRTC, force the DPMS mode to off as a result. */
+ /* Stop the CRTC, force enabled to false as a result. */
rcar_du_crtc_stop(rcrtc);
- rcrtc->dpms = DRM_MODE_DPMS_OFF;
+ rcrtc->enabled = false;
rcrtc->outputs = 0;
}
@@ -508,17 +521,12 @@ static void rcar_du_crtc_mode_commit(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- /* We're done, restart the CRTC and set the DPMS mode to on. The
- * reference to the DU acquired at prepare() time will thus be released
- * by the DPMS handler (possibly called by the disable() handler).
+ /* We're done, restart the CRTC and set enabled to true. The reference
+ * to the DU acquired at prepare() time will thus be released by the
+ * disable() handler.
*/
rcar_du_crtc_start(rcrtc);
- rcrtc->dpms = DRM_MODE_DPMS_ON;
-}
-
-static void rcar_du_crtc_disable(struct drm_crtc *crtc)
-{
- rcar_du_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+ rcrtc->enabled = true;
}
static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc)
@@ -554,6 +562,7 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.mode_set_nofb = rcar_du_crtc_mode_set_nofb,
.mode_set_base = drm_helper_crtc_mode_set_base,
.disable = rcar_du_crtc_disable,
+ .enable = rcar_du_crtc_enable,
.atomic_begin = rcar_du_crtc_atomic_begin,
.atomic_flush = rcar_du_crtc_atomic_flush,
};
@@ -670,7 +679,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->group = rgrp;
rcrtc->mmio_offset = mmio_offsets[index];
rcrtc->index = index;
- rcrtc->dpms = DRM_MODE_DPMS_OFF;
+ rcrtc->enabled = false;
rcrtc->plane = &rgrp->planes.planes[index % 2];
rcrtc->plane->crtc = crtc;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index fb39e040f17b..f50fbafd609f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -36,7 +36,7 @@ struct rcar_du_crtc {
wait_queue_head_t flip_wait;
unsigned int outputs;
- int dpms;
+ bool enabled;
struct rcar_du_group *group;
struct rcar_du_plane *plane;
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 25/38] drm: rcar-du: Switch plane update to atomic helpers
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (23 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 24/38] drm: rcar-du: Rework CRTC " Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 26/38] drm: rcar-du: Switch mode config " Laurent Pinchart
` (13 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
This removes the legacy plane update code. Wire up the default atomic
check and atomic commit mode config helpers as needed by the plane
update atomic helpers.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 3 +++
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 ++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 94ff8fcc7268..2b36f4f2980f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -12,6 +12,7 @@
*/
#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h>
@@ -188,6 +189,8 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {
.fb_create = rcar_du_fb_create,
.output_poll_changed = rcar_du_output_poll_changed,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
};
static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index f247b1fcf791..ff087f7de88e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -480,8 +480,8 @@ static int rcar_du_plane_set_property(struct drm_plane *plane,
}
static const struct drm_plane_funcs rcar_du_plane_funcs = {
- .update_plane = drm_plane_helper_update,
- .disable_plane = drm_plane_helper_disable,
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
.reset = drm_atomic_helper_plane_reset,
.set_property = rcar_du_plane_set_property,
.destroy = drm_plane_cleanup,
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 26/38] drm: rcar-du: Switch mode config to atomic helpers
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (24 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 25/38] drm: rcar-du: Switch plane update to atomic helpers Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 27/38] drm: rcar-du: Switch connector DPMS " Laurent Pinchart
` (12 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
This removes the legacy mode config code. The CRTC and encoder prepare
and commit operations are not used anymore, remove them.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 55 ++++---------------------------
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 12 -------
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 12 -------
3 files changed, 6 insertions(+), 73 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 7fdb968756ba..f82893884a8a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -362,12 +362,10 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
/* FIXME: Commit the planes state. This is required here as the CRTC can
* be started from the DPMS and system resume handler, which don't go
* through .atomic_plane_update() and .atomic_flush() to commit plane
- * state. Similarly a mode set operation without any update to planes
- * will not go through atomic plane configuration either. Additionally,
- * given that the plane state atomic commit occurs between CRTC disable
- * and enable, the hardware state could also be lost due to runtime PM,
- * requiring a full commit here. This will be fixed later after
- * switching to atomic updates completely.
+ * state. Additionally, given that the plane state atomic commit occurs
+ * between CRTC disable and enable, the hardware state could also be
+ * lost due to runtime PM, requiring a full commit here. This will be
+ * fixed later after switching to atomic updates completely.
*/
mutex_lock(&rcrtc->group->planes.lock);
rcar_du_crtc_update_planes(crtc);
@@ -474,6 +472,7 @@ static void rcar_du_crtc_disable(struct drm_crtc *crtc)
rcar_du_crtc_put(rcrtc);
rcrtc->enabled = false;
+ rcrtc->outputs = 0;
}
static void rcar_du_crtc_dpms(struct drm_crtc *crtc, int mode)
@@ -492,43 +491,6 @@ static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc,
return true;
}
-static void rcar_du_crtc_mode_prepare(struct drm_crtc *crtc)
-{
- struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
-
- /* We need to access the hardware during mode set, acquire a reference
- * to the CRTC.
- */
- rcar_du_crtc_get(rcrtc);
-
- /* Stop the CRTC, force enabled to false as a result. */
- rcar_du_crtc_stop(rcrtc);
-
- rcrtc->enabled = false;
- rcrtc->outputs = 0;
-}
-
-static void rcar_du_crtc_mode_set_nofb(struct drm_crtc *crtc)
-{
- /* No-op. We should configure the display timings here, but as we're
- * called with the CRTC disabled clocks might be off, and we thus can't
- * access the hardware. Let's just configure everything when enabling
- * the CRTC.
- */
-}
-
-static void rcar_du_crtc_mode_commit(struct drm_crtc *crtc)
-{
- struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
-
- /* We're done, restart the CRTC and set enabled to true. The reference
- * to the DU acquired at prepare() time will thus be released by the
- * disable() handler.
- */
- rcar_du_crtc_start(rcrtc);
- rcrtc->enabled = true;
-}
-
static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
@@ -556,11 +518,6 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc)
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.dpms = rcar_du_crtc_dpms,
.mode_fixup = rcar_du_crtc_mode_fixup,
- .prepare = rcar_du_crtc_mode_prepare,
- .commit = rcar_du_crtc_mode_commit,
- .mode_set = drm_helper_crtc_mode_set,
- .mode_set_nofb = rcar_du_crtc_mode_set_nofb,
- .mode_set_base = drm_helper_crtc_mode_set_base,
.disable = rcar_du_crtc_disable,
.enable = rcar_du_crtc_enable,
.atomic_begin = rcar_du_crtc_atomic_begin,
@@ -602,7 +559,7 @@ static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
static const struct drm_crtc_funcs crtc_funcs = {
.reset = drm_atomic_helper_crtc_reset,
.destroy = drm_crtc_cleanup,
- .set_config = drm_crtc_helper_set_config,
+ .set_config = drm_atomic_helper_set_config,
.page_flip = rcar_du_crtc_page_flip,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 74a744f5dfdb..76b201f2f75e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -118,16 +118,6 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
return true;
}
-static void rcar_du_encoder_mode_prepare(struct drm_encoder *encoder)
-{
- rcar_du_encoder_disable(encoder);
-}
-
-static void rcar_du_encoder_mode_commit(struct drm_encoder *encoder)
-{
- rcar_du_encoder_enable(encoder);
-}
-
static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -140,8 +130,6 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
.dpms = rcar_du_encoder_dpms,
.mode_fixup = rcar_du_encoder_mode_fixup,
- .prepare = rcar_du_encoder_mode_prepare,
- .commit = rcar_du_encoder_mode_commit,
.mode_set = rcar_du_encoder_mode_set,
.disable = rcar_du_encoder_disable,
.enable = rcar_du_encoder_enable,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index 04e21b5f96d4..a88ef2d6800e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -96,16 +96,6 @@ static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder,
return sfuncs->mode_fixup(encoder, mode, adjusted_mode);
}
-static void rcar_du_hdmienc_mode_prepare(struct drm_encoder *encoder)
-{
- rcar_du_hdmienc_dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-
-static void rcar_du_hdmienc_mode_commit(struct drm_encoder *encoder)
-{
- rcar_du_hdmienc_dpms(encoder, DRM_MODE_DPMS_ON);
-}
-
static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -122,8 +112,6 @@ static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
.dpms = rcar_du_hdmienc_dpms,
.mode_fixup = rcar_du_hdmienc_mode_fixup,
- .prepare = rcar_du_hdmienc_mode_prepare,
- .commit = rcar_du_hdmienc_mode_commit,
.mode_set = rcar_du_hdmienc_mode_set,
.disable = rcar_du_hdmienc_disable,
.enable = rcar_du_hdmienc_enable,
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 27/38] drm: rcar-du: Switch connector DPMS to atomic helpers
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (25 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 26/38] drm: rcar-du: Switch mode config " Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 28/38] drm: rcar-du: Replace encoder mode_fixup with atomic_check Laurent Pinchart
` (11 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The atomic connector DPMS helper implements the connector DPMS operation
using atomic commit, removing the need for DPMS helper operations on
CRTCs and encoders.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 11 +----------
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 9 ---------
drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 4 ++--
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 15 ---------------
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 4 ++--
drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 4 ++--
6 files changed, 7 insertions(+), 40 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index f82893884a8a..8a44d37f1716 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -360,7 +360,7 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
rcar_du_group_set_routing(rcrtc->group);
/* FIXME: Commit the planes state. This is required here as the CRTC can
- * be started from the DPMS and system resume handler, which don't go
+ * be started from the system resume handler, which don't go
* through .atomic_plane_update() and .atomic_flush() to commit plane
* state. Additionally, given that the plane state atomic commit occurs
* between CRTC disable and enable, the hardware state could also be
@@ -475,14 +475,6 @@ static void rcar_du_crtc_disable(struct drm_crtc *crtc)
rcrtc->outputs = 0;
}
-static void rcar_du_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- if (mode = DRM_MODE_DPMS_ON)
- rcar_du_crtc_enable(crtc);
- else
- rcar_du_crtc_disable(crtc);
-}
-
static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -516,7 +508,6 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc)
}
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
- .dpms = rcar_du_crtc_dpms,
.mode_fixup = rcar_du_crtc_mode_fixup,
.disable = rcar_du_crtc_disable,
.enable = rcar_du_crtc_enable,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 76b201f2f75e..d4a70228ce50 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -58,14 +58,6 @@ static void rcar_du_encoder_enable(struct drm_encoder *encoder)
rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);
}
-static void rcar_du_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
- if (mode = DRM_MODE_DPMS_ON)
- rcar_du_encoder_enable(encoder);
- else
- rcar_du_encoder_disable(encoder);
-}
-
static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -128,7 +120,6 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
}
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
- .dpms = rcar_du_encoder_dpms,
.mode_fixup = rcar_du_encoder_mode_fixup,
.mode_set = rcar_du_encoder_mode_set,
.disable = rcar_du_encoder_disable,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
index 9378c283cb58..96f2eb43713c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
@@ -75,7 +75,7 @@ rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force)
}
static const struct drm_connector_funcs connector_funcs = {
- .dpms = drm_helper_connector_dpms,
+ .dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -112,7 +112,7 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
if (ret < 0)
return ret;
- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+ connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,
rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index a88ef2d6800e..3c29250c8abd 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -62,20 +62,6 @@ static void rcar_du_hdmienc_enable(struct drm_encoder *encoder)
hdmienc->enabled = true;
}
-static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode)
-{
- struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
- bool enable = mode = DRM_MODE_DPMS_ON;
-
- if (hdmienc->enabled = enable)
- return;
-
- if (enable)
- rcar_du_hdmienc_enable(encoder);
- else
- rcar_du_hdmienc_disable(encoder);
-}
-
static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -110,7 +96,6 @@ static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
}
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
- .dpms = rcar_du_hdmienc_dpms,
.mode_fixup = rcar_du_hdmienc_mode_fixup,
.mode_set = rcar_du_hdmienc_mode_set,
.disable = rcar_du_hdmienc_disable,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
index 4bfa3ce34ab3..0c43032fc693 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
@@ -75,7 +75,7 @@ rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
}
static const struct drm_connector_funcs connector_funcs = {
- .dpms = drm_helper_connector_dpms,
+ .dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_lvds_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -121,7 +121,7 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
if (ret < 0)
return ret;
- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+ connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,
rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
index a110cf22f3b0..e0a5d8f93963 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
@@ -44,7 +44,7 @@ rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
}
static const struct drm_connector_funcs connector_funcs = {
- .dpms = drm_helper_connector_dpms,
+ .dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_vga_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -80,7 +80,7 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
if (ret < 0)
return ret;
- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+ connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,
rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 28/38] drm: rcar-du: Replace encoder mode_fixup with atomic_check
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (26 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 27/38] drm: rcar-du: Switch connector DPMS " Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 29/38] drm: rcar-du: Implement asynchronous commit support Laurent Pinchart
` (10 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The encoder .mode_fixup() operation is legacy, atomic updates uses the
new .atomic_check() operation. Convert the encoders drivers.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 35 +++++++++++--------------------
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 14 +++++++------
2 files changed, 20 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index d4a70228ce50..d0ae1e8009c6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -58,35 +58,24 @@ static void rcar_du_encoder_enable(struct drm_encoder *encoder)
rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);
}
-static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+ struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+ const struct drm_display_mode *mode = &crtc_state->mode;
const struct drm_display_mode *panel_mode;
+ struct drm_connector *connector = conn_state->connector;
struct drm_device *dev = encoder->dev;
- struct drm_connector *connector;
- bool found = false;
/* DAC encoders have currently no restriction on the mode. */
if (encoder->encoder_type = DRM_MODE_ENCODER_DAC)
- return true;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->encoder = encoder) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- dev_dbg(dev->dev, "mode_fixup: no connector found\n");
- return false;
- }
+ return 0;
if (list_empty(&connector->modes)) {
- dev_dbg(dev->dev, "mode_fixup: empty modes list\n");
- return false;
+ dev_dbg(dev->dev, "encoder: empty modes list\n");
+ return -EINVAL;
}
panel_mode = list_first_entry(&connector->modes,
@@ -95,7 +84,7 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
/* We're not allowed to modify the resolution. */
if (mode->hdisplay != panel_mode->hdisplay ||
mode->vdisplay != panel_mode->vdisplay)
- return false;
+ return -EINVAL;
/* The flat panel mode is fixed, just copy it to the adjusted mode. */
drm_mode_copy(adjusted_mode, panel_mode);
@@ -107,7 +96,7 @@ static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
adjusted_mode->clock = clamp(adjusted_mode->clock,
30000, 150000);
- return true;
+ return 0;
}
static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
@@ -120,10 +109,10 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
}
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
- .mode_fixup = rcar_du_encoder_mode_fixup,
.mode_set = rcar_du_encoder_mode_set,
.disable = rcar_du_encoder_disable,
.enable = rcar_du_encoder_enable,
+ .atomic_check = rcar_du_encoder_atomic_check,
};
static const struct drm_encoder_funcs encoder_funcs = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index 3c29250c8abd..81da8419282b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -62,12 +62,14 @@ static void rcar_du_hdmienc_enable(struct drm_encoder *encoder)
hdmienc->enabled = true;
}
-static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
+ struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+ const struct drm_display_mode *mode = &crtc_state->mode;
/* The internal LVDS encoder has a clock frequency operating range of
* 30MHz to 150MHz. Clamp the clock accordingly.
@@ -77,9 +79,9 @@ static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder,
30000, 150000);
if (sfuncs->mode_fixup = NULL)
- return true;
+ return 0;
- return sfuncs->mode_fixup(encoder, mode, adjusted_mode);
+ return sfuncs->mode_fixup(encoder, mode, adjusted_mode) ? 0 : -EINVAL;
}
static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
@@ -96,10 +98,10 @@ static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
}
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
- .mode_fixup = rcar_du_hdmienc_mode_fixup,
.mode_set = rcar_du_hdmienc_mode_set,
.disable = rcar_du_hdmienc_disable,
.enable = rcar_du_hdmienc_enable,
+ .atomic_check = rcar_du_hdmienc_atomic_check,
};
static void rcar_du_hdmienc_cleanup(struct drm_encoder *encoder)
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 29/38] drm: rcar-du: Implement asynchronous commit support
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (27 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 28/38] drm: rcar-du: Replace encoder mode_fixup with atomic_check Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 30/38] drm: rcar-du: Switch page flip to atomic helpers Laurent Pinchart
` (9 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Implement a custom .atomic_commit() handler that supports asynchronous
commits using a work queue. This can be used for userspace-driven
asynchronous commits, as well as for an atomic page flip implementation.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_drv.c | 3 +
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 ++
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 105 +++++++++++++++++++++++++++++++++-
3 files changed, 113 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 8ab4c69c599b..1d9e4f8568ae 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/slab.h>
+#include <linux/wait.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
@@ -163,6 +164,8 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
return -ENOMEM;
}
+ init_waitqueue_head(&rcdu->commit.wait);
+
rcdu->dev = &pdev->dev;
rcdu->info = np ? of_match_device(rcar_du_of_table, rcdu->dev)->data
: (void *)platform_get_device_id(pdev)->driver_data;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index d1ede13cb1d5..c7c538dd2e68 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -15,6 +15,7 @@
#define __RCAR_DU_DRV_H__
#include <linux/kernel.h>
+#include <linux/wait.h>
#include "rcar_du_crtc.h"
#include "rcar_du_group.h"
@@ -84,6 +85,11 @@ struct rcar_du_device {
unsigned int dpad0_source;
struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];
+
+ struct {
+ wait_queue_head_t wait;
+ u32 pending;
+ } commit;
};
static inline bool rcar_du_has(struct rcar_du_device *rcdu,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 2b36f4f2980f..cec35e405248 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -12,6 +12,7 @@
*/
#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
@@ -19,6 +20,7 @@
#include <drm/drm_gem_cma_helper.h>
#include <linux/of_graph.h>
+#include <linux/wait.h>
#include "rcar_du_crtc.h"
#include "rcar_du_drv.h"
@@ -186,11 +188,112 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
drm_fbdev_cma_hotplug_event(rcdu->fbdev);
}
+/* -----------------------------------------------------------------------------
+ * Atomic Updates
+ */
+
+struct rcar_du_commit {
+ struct work_struct work;
+ struct drm_device *dev;
+ struct drm_atomic_state *state;
+ u32 crtcs;
+};
+
+static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
+{
+ struct drm_device *dev = commit->dev;
+ struct rcar_du_device *rcdu = dev->dev_private;
+ struct drm_atomic_state *old_state = commit->state;
+
+ /* Apply the atomic update. */
+ drm_atomic_helper_commit_modeset_disables(dev, old_state);
+ drm_atomic_helper_commit_planes(dev, old_state);
+ drm_atomic_helper_commit_modeset_enables(dev, old_state);
+
+ drm_atomic_helper_wait_for_vblanks(dev, old_state);
+
+ drm_atomic_helper_cleanup_planes(dev, old_state);
+
+ drm_atomic_state_free(old_state);
+
+ /* Complete the commit, wake up any waiter. */
+ spin_lock(&rcdu->commit.wait.lock);
+ rcdu->commit.pending &= ~commit->crtcs;
+ wake_up_all_locked(&rcdu->commit.wait);
+ spin_unlock(&rcdu->commit.wait.lock);
+
+ kfree(commit);
+}
+
+static void rcar_du_atomic_work(struct work_struct *work)
+{
+ struct rcar_du_commit *commit + container_of(work, struct rcar_du_commit, work);
+
+ rcar_du_atomic_complete(commit);
+}
+
+static int rcar_du_atomic_commit(struct drm_device *dev,
+ struct drm_atomic_state *state, bool async)
+{
+ struct rcar_du_device *rcdu = dev->dev_private;
+ struct rcar_du_commit *commit;
+ unsigned int i;
+ int ret;
+
+ ret = drm_atomic_helper_prepare_planes(dev, state);
+ if (ret)
+ return ret;
+
+ /* Allocate the commit object. */
+ commit = kzalloc(sizeof(*commit), GFP_KERNEL);
+ if (commit = NULL)
+ return -ENOMEM;
+
+ INIT_WORK(&commit->work, rcar_du_atomic_work);
+ commit->dev = dev;
+ commit->state = state;
+
+ /* Wait until all affected CRTCs have completed previous commits and
+ * mark them as pending.
+ */
+ for (i = 0; i < dev->mode_config.num_crtc; ++i) {
+ if (state->crtcs[i])
+ commit->crtcs |= 1 << drm_crtc_index(state->crtcs[i]);
+ }
+
+ spin_lock(&rcdu->commit.wait.lock);
+ ret = wait_event_interruptible_locked(rcdu->commit.wait,
+ !(rcdu->commit.pending & commit->crtcs));
+ if (ret = 0)
+ rcdu->commit.pending |= commit->crtcs;
+ spin_unlock(&rcdu->commit.wait.lock);
+
+ if (ret) {
+ kfree(commit);
+ return ret;
+ }
+
+ /* Swap the state, this is the point of no return. */
+ drm_atomic_helper_swap_state(dev, state);
+
+ if (async)
+ schedule_work(&commit->work);
+ else
+ rcar_du_atomic_complete(commit);
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Initialization
+ */
+
static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {
.fb_create = rcar_du_fb_create,
.output_poll_changed = rcar_du_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
- .atomic_commit = drm_atomic_helper_commit,
+ .atomic_commit = rcar_du_atomic_commit,
};
static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 30/38] drm: rcar-du: Switch page flip to atomic helpers
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (28 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 29/38] drm: rcar-du: Implement asynchronous commit support Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 31/38] drm: rcar-du: Switch plane set_property " Laurent Pinchart
` (8 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The atomic page flip helper implements the page flip operation using
asynchronous commits.
As the legacy page flip was the last CRTC operation that needed direct
access to plane setup, the plane setup functions can now become private
to the plane implementation.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 55 +++++++++------------------------
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 6 ++--
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 3 --
3 files changed, 17 insertions(+), 47 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 8a44d37f1716..2a1119b52c2a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -436,14 +436,6 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
rcar_du_crtc_start(rcrtc);
}
-static void rcar_du_crtc_update_base(struct rcar_du_crtc *rcrtc)
-{
- struct drm_crtc *crtc = &rcrtc->crtc;
-
- rcar_du_plane_compute_base(rcrtc->plane, crtc->primary->fb);
- rcar_du_plane_update_base(rcrtc->plane);
-}
-
/* -----------------------------------------------------------------------------
* CRTC Functions
*/
@@ -485,12 +477,25 @@ static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc,
static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc)
{
+ struct drm_pending_vblank_event *event = crtc->state->event;
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+ struct drm_device *dev = rcrtc->crtc.dev;
+ unsigned long flags;
/* We need to access the hardware during atomic update, acquire a
* reference to the CRTC.
*/
rcar_du_crtc_get(rcrtc);
+
+ if (event) {
+ event->pipe = rcrtc->index;
+
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ rcrtc->event = event;
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
}
static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc)
@@ -515,43 +520,11 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.atomic_flush = rcar_du_crtc_atomic_flush,
};
-static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event,
- uint32_t page_flip_flags)
-{
- struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- struct drm_device *dev = rcrtc->crtc.dev;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->event_lock, flags);
- if (rcrtc->event != NULL) {
- spin_unlock_irqrestore(&dev->event_lock, flags);
- return -EBUSY;
- }
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
-
- crtc->primary->fb = fb;
- rcar_du_crtc_update_base(rcrtc);
-
- if (event) {
- event->pipe = rcrtc->index;
- drm_crtc_vblank_get(crtc);
- spin_lock_irqsave(&dev->event_lock, flags);
- rcrtc->event = event;
- spin_unlock_irqrestore(&dev->event_lock, flags);
- }
-
- return 0;
-}
-
static const struct drm_crtc_funcs crtc_funcs = {
.reset = drm_atomic_helper_crtc_reset,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
- .page_flip = rcar_du_crtc_page_flip,
+ .page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index ff087f7de88e..9176ac451438 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -129,7 +129,7 @@ static void rcar_du_plane_release(struct rcar_du_plane *plane)
plane->hwindex = -1;
}
-void rcar_du_plane_update_base(struct rcar_du_plane *plane)
+static void rcar_du_plane_update_base(struct rcar_du_plane *plane)
{
struct rcar_du_group *rgrp = plane->group;
unsigned int src_x = plane->plane.state->src_x >> 16;
@@ -182,8 +182,8 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
}
}
-void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
- struct drm_framebuffer *fb)
+static void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
+ struct drm_framebuffer *fb)
{
struct drm_gem_cma_object *gem;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 3420ff07f2c6..9b77a638863f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -62,8 +62,5 @@ struct rcar_du_planes {
int rcar_du_planes_init(struct rcar_du_group *rgrp);
void rcar_du_plane_setup(struct rcar_du_plane *plane);
-void rcar_du_plane_update_base(struct rcar_du_plane *plane);
-void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
- struct drm_framebuffer *fb);
#endif /* __RCAR_DU_PLANE_H__ */
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 31/38] drm: rcar-du: Switch plane set_property to atomic helpers
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (29 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 30/38] drm: rcar-du: Switch page flip to atomic helpers Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 32/38] drm: rcar-du: Rework plane setup code Laurent Pinchart
` (7 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Allow setting up plane properties atomically using the plane
set_property atomic helper. The properties are now stored in the plane
state (requiring subclassing it) and applied when updating the planes.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 9 ++-
drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 1 -
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 125 +++++++++++++++++++-------------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 17 ++++-
4 files changed, 95 insertions(+), 57 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 2a1119b52c2a..faa46ed23a62 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -193,7 +193,12 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc,
rcdu->dpad0_source = rcrtc->index;
}
-void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
+static unsigned int plane_zpos(struct rcar_du_plane *plane)
+{
+ return to_rcar_du_plane_state(plane->plane.state)->zpos;
+}
+
+static void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
@@ -212,7 +217,7 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
/* Insert the plane in the sorted planes array. */
for (j = num_planes++; j > 0; --j) {
- if (planes[j-1]->zpos <= plane->zpos)
+ if (plane_zpos(planes[j-1]) <= plane_zpos(plane))
break;
planes[j] = planes[j-1];
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index f50fbafd609f..0a3dcca58fd7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -62,6 +62,5 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
void rcar_du_crtc_route_output(struct drm_crtc *crtc,
enum rcar_du_output output);
-void rcar_du_crtc_update_planes(struct drm_crtc *crtc);
#endif /* __RCAR_DU_CRTC_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 9176ac451438..7e0e2731ea27 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -201,6 +201,8 @@ static void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
unsigned int index)
{
+ struct rcar_du_plane_state *state + to_rcar_du_plane_state(plane->plane.state);
struct rcar_du_group *rgrp = plane->group;
u32 colorkey;
u32 pnmr;
@@ -218,7 +220,7 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
rcar_du_plane_write(rgrp, index, PnALPHAR, PnALPHAR_ABIT_0);
else
rcar_du_plane_write(rgrp, index, PnALPHAR,
- PnALPHAR_ABIT_X | plane->alpha);
+ PnALPHAR_ABIT_X | state->alpha);
pnmr = PnMR_BM_MD | plane->format->pnmr;
@@ -226,7 +228,7 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
* PnMR_SPIM_TP_OFF bit set in their pnmr field, disabling color keying
* automatically.
*/
- if ((plane->colorkey & RCAR_DU_COLORKEY_MASK) = RCAR_DU_COLORKEY_NONE)
+ if ((state->colorkey & RCAR_DU_COLORKEY_MASK) = RCAR_DU_COLORKEY_NONE)
pnmr |= PnMR_SPIM_TP_OFF;
/* For packed YUV formats we need to select the U/V order. */
@@ -237,24 +239,24 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
switch (plane->format->fourcc) {
case DRM_FORMAT_RGB565:
- colorkey = ((plane->colorkey & 0xf80000) >> 8)
- | ((plane->colorkey & 0x00fc00) >> 5)
- | ((plane->colorkey & 0x0000f8) >> 3);
+ colorkey = ((state->colorkey & 0xf80000) >> 8)
+ | ((state->colorkey & 0x00fc00) >> 5)
+ | ((state->colorkey & 0x0000f8) >> 3);
rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
break;
case DRM_FORMAT_ARGB1555:
case DRM_FORMAT_XRGB1555:
- colorkey = ((plane->colorkey & 0xf80000) >> 9)
- | ((plane->colorkey & 0x00f800) >> 6)
- | ((plane->colorkey & 0x0000f8) >> 3);
+ colorkey = ((state->colorkey & 0xf80000) >> 9)
+ | ((state->colorkey & 0x00f800) >> 6)
+ | ((state->colorkey & 0x0000f8) >> 3);
rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
break;
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
rcar_du_plane_write(rgrp, index, PnTC3R,
- PnTC3R_CODE | (plane->colorkey & 0xffffff));
+ PnTC3R_CODE | (state->colorkey & 0xffffff));
break;
}
}
@@ -414,65 +416,87 @@ static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
.atomic_update = rcar_du_plane_atomic_update,
};
-/* Both the .set_property and the .update_plane operations are called with the
- * mode_config lock held. There is this no need to explicitly protect access to
- * the alpha and colorkey fields and the mode register.
- */
-static void rcar_du_plane_set_alpha(struct rcar_du_plane *plane, u32 alpha)
+static void rcar_du_plane_reset(struct drm_plane *plane)
{
- if (plane->alpha = alpha)
- return;
+ struct rcar_du_plane_state *state;
+
+ if (plane->state && plane->state->fb)
+ drm_framebuffer_unreference(plane->state->fb);
- plane->alpha = alpha;
- if (!plane->enabled || plane->format->fourcc != DRM_FORMAT_XRGB1555)
+ kfree(plane->state);
+ plane->state = NULL;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (state = NULL)
return;
- rcar_du_plane_setup_mode(plane, plane->hwindex);
+ state->alpha = 255;
+ state->colorkey = RCAR_DU_COLORKEY_NONE;
+ state->zpos = plane->type = DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
+
+ plane->state = &state->state;
+ plane->state->plane = plane;
}
-static void rcar_du_plane_set_colorkey(struct rcar_du_plane *plane,
- u32 colorkey)
+static struct drm_plane_state *
+rcar_du_plane_atomic_duplicate_state(struct drm_plane *plane)
{
- if (plane->colorkey = colorkey)
- return;
+ struct rcar_du_plane_state *state;
+ struct rcar_du_plane_state *copy;
- plane->colorkey = colorkey;
- if (!plane->enabled)
- return;
+ state = to_rcar_du_plane_state(plane->state);
+ copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
+ if (copy = NULL)
+ return NULL;
+
+ if (copy->state.fb)
+ drm_framebuffer_reference(copy->state.fb);
- rcar_du_plane_setup_mode(plane, plane->hwindex);
+ return ©->state;
}
-static void rcar_du_plane_set_zpos(struct rcar_du_plane *plane,
- unsigned int zpos)
+static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
{
- mutex_lock(&plane->group->planes.lock);
- if (plane->zpos = zpos)
- goto done;
+ kfree(to_rcar_du_plane_state(state));
+}
- plane->zpos = zpos;
- if (!plane->enabled)
- goto done;
+static int rcar_du_plane_atomic_set_property(struct drm_plane *plane,
+ struct drm_plane_state *state,
+ struct drm_property *property,
+ uint64_t val)
+{
+ struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state);
+ struct rcar_du_plane *rplane = to_rcar_plane(plane);
+ struct rcar_du_group *rgrp = rplane->group;
- rcar_du_crtc_update_planes(plane->crtc);
+ if (property = rgrp->planes.alpha)
+ rstate->alpha = val;
+ else if (property = rgrp->planes.colorkey)
+ rstate->colorkey = val;
+ else if (property = rgrp->planes.zpos)
+ rstate->zpos = val;
+ else
+ return -EINVAL;
-done:
- mutex_unlock(&plane->group->planes.lock);
+ return 0;
}
-static int rcar_du_plane_set_property(struct drm_plane *plane,
- struct drm_property *property,
- uint64_t value)
+static int rcar_du_plane_atomic_get_property(struct drm_plane *plane,
+ const struct drm_plane_state *state, struct drm_property *property,
+ uint64_t *val)
{
+ const struct rcar_du_plane_state *rstate + container_of(state, const struct rcar_du_plane_state, state);
struct rcar_du_plane *rplane = to_rcar_plane(plane);
struct rcar_du_group *rgrp = rplane->group;
if (property = rgrp->planes.alpha)
- rcar_du_plane_set_alpha(rplane, value);
+ *val = rstate->alpha;
else if (property = rgrp->planes.colorkey)
- rcar_du_plane_set_colorkey(rplane, value);
+ *val = rstate->colorkey;
else if (property = rgrp->planes.zpos)
- rcar_du_plane_set_zpos(rplane, value);
+ *val = rstate->zpos;
else
return -EINVAL;
@@ -482,11 +506,13 @@ static int rcar_du_plane_set_property(struct drm_plane *plane,
static const struct drm_plane_funcs rcar_du_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
- .reset = drm_atomic_helper_plane_reset,
- .set_property = rcar_du_plane_set_property,
+ .reset = rcar_du_plane_reset,
+ .set_property = drm_atomic_helper_plane_set_property,
.destroy = drm_plane_cleanup,
- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+ .atomic_duplicate_state = rcar_du_plane_atomic_duplicate_state,
+ .atomic_destroy_state = rcar_du_plane_atomic_destroy_state,
+ .atomic_set_property = rcar_du_plane_atomic_set_property,
+ .atomic_get_property = rcar_du_plane_atomic_get_property,
};
static const uint32_t formats[] = {
@@ -551,9 +577,6 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
plane->group = rgrp;
plane->hwindex = -1;
- plane->alpha = 255;
- plane->colorkey = RCAR_DU_COLORKEY_NONE;
- plane->zpos = type = DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
&rcar_du_plane_funcs, formats,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 9b77a638863f..d291e85896ef 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -39,9 +39,6 @@ struct rcar_du_plane {
bool enabled;
int hwindex; /* 0-based, -1 means unused */
- unsigned int alpha;
- unsigned int colorkey;
- unsigned int zpos;
const struct rcar_du_format_info *format;
@@ -59,6 +56,20 @@ struct rcar_du_planes {
struct drm_property *zpos;
};
+struct rcar_du_plane_state {
+ struct drm_plane_state state;
+
+ unsigned int alpha;
+ unsigned int colorkey;
+ unsigned int zpos;
+};
+
+static inline struct rcar_du_plane_state *
+to_rcar_du_plane_state(struct drm_plane_state *state)
+{
+ return container_of(state, struct rcar_du_plane_state, state);
+}
+
int rcar_du_planes_init(struct rcar_du_group *rgrp);
void rcar_du_plane_setup(struct rcar_du_plane *plane);
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 32/38] drm: rcar-du: Rework plane setup code
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (30 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 31/38] drm: rcar-du: Switch plane set_property " Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 33/38] drm: rcar-du: Replace plane crtc and enabled fields by plane state Laurent Pinchart
` (6 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Now that the plane setup code isn't called outside of the plane
implementation, it can be simplified by merging the
rcar_du_plane_compute_base() and rcar_du_plane_update_base() functions.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 34 ++++++++++++---------------------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 3 ---
2 files changed, 12 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 7e0e2731ea27..f28d13dc6fc9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -129,12 +129,14 @@ static void rcar_du_plane_release(struct rcar_du_plane *plane)
plane->hwindex = -1;
}
-static void rcar_du_plane_update_base(struct rcar_du_plane *plane)
+static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
{
+ struct drm_framebuffer *fb = plane->plane.state->fb;
struct rcar_du_group *rgrp = plane->group;
unsigned int src_x = plane->plane.state->src_x >> 16;
unsigned int src_y = plane->plane.state->src_y >> 16;
unsigned int index = plane->hwindex;
+ struct drm_gem_cma_object *gem;
bool interlaced;
u32 mwr;
@@ -144,9 +146,9 @@ static void rcar_du_plane_update_base(struct rcar_du_plane *plane)
* operation with 32bpp formats.
*/
if (plane->format->planes = 2)
- mwr = plane->pitch;
+ mwr = fb->pitches[0];
else
- mwr = plane->pitch * 8 / plane->format->bpp;
+ mwr = fb->pitches[0] * 8 / plane->format->bpp;
if (interlaced && plane->format->bpp = 32)
mwr *= 2;
@@ -168,33 +170,22 @@ static void rcar_du_plane_update_base(struct rcar_du_plane *plane)
rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
(!interlaced && plane->format->bpp = 32 ? 2 : 1));
- rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[0]);
+
+ gem = drm_fb_cma_get_gem_obj(fb, 0);
+ rcar_du_plane_write(rgrp, index, PnDSA0R, gem->paddr + fb->offsets[0]);
if (plane->format->planes = 2) {
index = (index + 1) % 8;
- rcar_du_plane_write(rgrp, index, PnMWR, plane->pitch);
+ rcar_du_plane_write(rgrp, index, PnMWR, fb->pitches[0]);
rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
(plane->format->bpp = 16 ? 2 : 1) / 2);
- rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[1]);
- }
-}
-
-static void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
- struct drm_framebuffer *fb)
-{
- struct drm_gem_cma_object *gem;
-
- plane->pitch = fb->pitches[0];
- gem = drm_fb_cma_get_gem_obj(fb, 0);
- plane->dma[0] = gem->paddr + fb->offsets[0];
-
- if (plane->format->planes = 2) {
gem = drm_fb_cma_get_gem_obj(fb, 1);
- plane->dma[1] = gem->paddr + fb->offsets[1];
+ rcar_du_plane_write(rgrp, index, PnDSA0R,
+ gem->paddr + fb->offsets[1]);
}
}
@@ -316,7 +307,7 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
if (plane->format->planes = 2)
__rcar_du_plane_setup(plane, (plane->hwindex + 1) % 8);
- rcar_du_plane_update_base(plane);
+ rcar_du_plane_setup_fb(plane);
}
static int rcar_du_plane_atomic_check(struct drm_plane *plane,
@@ -403,7 +394,6 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
rplane->crtc = state->crtc;
rplane->format = format;
- rcar_du_plane_compute_base(rplane, state->fb);
rcar_du_plane_setup(rplane);
mutex_lock(&rplane->group->planes.lock);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index d291e85896ef..012f2185ca1f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -41,9 +41,6 @@ struct rcar_du_plane {
int hwindex; /* 0-based, -1 means unused */
const struct rcar_du_format_info *format;
-
- unsigned long dma[2];
- unsigned int pitch;
};
struct rcar_du_planes {
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 33/38] drm: rcar-du: Replace plane crtc and enabled fields by plane state
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (31 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 32/38] drm: rcar-du: Rework plane setup code Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 34/38] drm: rcar-du: Remove unneeded rcar_du_crtc plane field Laurent Pinchart
` (5 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The crtc and enabled fields duplicates information stored in the plane
state. Use the plane state instead and remove the fields.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 6 ++----
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 15 +++------------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 3 ---
3 files changed, 5 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index faa46ed23a62..3f64707412e6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -212,7 +212,7 @@ static void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
unsigned int j;
- if (plane->crtc != &rcrtc->crtc || !plane->enabled)
+ if (plane->plane.state->crtc != &rcrtc->crtc)
continue;
/* Insert the plane in the sorted planes array. */
@@ -379,7 +379,7 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
- if (plane->crtc != crtc || !plane->enabled)
+ if (plane->plane.state->crtc != crtc)
continue;
rcar_du_plane_setup(plane);
@@ -608,8 +608,6 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->enabled = false;
rcrtc->plane = &rgrp->planes.planes[index % 2];
- rcrtc->plane->crtc = crtc;
-
ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, &rcrtc->plane->plane,
NULL, &crtc_funcs);
if (ret < 0)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index f28d13dc6fc9..c5cb2ade2722 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -140,7 +140,8 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
bool interlaced;
u32 mwr;
- interlaced = plane->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE;
+ interlaced = plane->plane.state->crtc->state->adjusted_mode.flags
+ & DRM_MODE_FLAG_INTERLACE;
/* Memory pitch (expressed in pixels). Must be doubled for interlaced
* operation with 32bpp formats.
@@ -354,16 +355,11 @@ static int rcar_du_plane_atomic_check(struct drm_plane *plane,
static void rcar_du_plane_disable(struct rcar_du_plane *rplane)
{
- if (!rplane->enabled)
+ if (!rplane->plane.state->crtc)
return;
- mutex_lock(&rplane->group->planes.lock);
- rplane->enabled = false;
- mutex_unlock(&rplane->group->planes.lock);
-
rcar_du_plane_release(rplane);
- rplane->crtc = NULL;
rplane->format = NULL;
}
@@ -391,14 +387,9 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
rcar_du_plane_reserve(rplane, format);
}
- rplane->crtc = state->crtc;
rplane->format = format;
rcar_du_plane_setup(rplane);
-
- mutex_lock(&rplane->group->planes.lock);
- rplane->enabled = true;
- mutex_unlock(&rplane->group->planes.lock);
}
static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 012f2185ca1f..7050fc1e11ec 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -34,9 +34,6 @@ struct rcar_du_plane {
struct drm_plane plane;
struct rcar_du_group *group;
- struct drm_crtc *crtc;
-
- bool enabled;
int hwindex; /* 0-based, -1 means unused */
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 34/38] drm: rcar-du: Remove unneeded rcar_du_crtc plane field
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (32 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 33/38] drm: rcar-du: Replace plane crtc and enabled fields by plane state Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 35/38] drm: rcar-du: Move plane format to plane state Laurent Pinchart
` (4 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The rcar_du_crtc plane field is only used to check for an error that
can't occur. Remove it.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 7 ++-----
drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 2 --
2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 3f64707412e6..c70f73036056 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -353,9 +353,6 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
if (rcrtc->started)
return;
- if (WARN_ON(rcrtc->plane->format = NULL))
- return;
-
/* Set display off and background to black */
rcar_du_crtc_write(rcrtc, DOOR, DOOR_RGB(0, 0, 0));
rcar_du_crtc_write(rcrtc, BPOR, BPOR_RGB(0, 0, 0));
@@ -606,9 +603,9 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->mmio_offset = mmio_offsets[index];
rcrtc->index = index;
rcrtc->enabled = false;
- rcrtc->plane = &rgrp->planes.planes[index % 2];
- ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, &rcrtc->plane->plane,
+ ret = drm_crtc_init_with_planes(rcdu->ddev, crtc,
+ &rgrp->planes.planes[index % 2].plane,
NULL, &crtc_funcs);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 0a3dcca58fd7..5d9aa9b33769 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -21,7 +21,6 @@
#include <drm/drm_crtc.h>
struct rcar_du_group;
-struct rcar_du_plane;
struct rcar_du_crtc {
struct drm_crtc crtc;
@@ -39,7 +38,6 @@ struct rcar_du_crtc {
bool enabled;
struct rcar_du_group *group;
- struct rcar_du_plane *plane;
};
#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 35/38] drm: rcar-du: Move plane format to plane state
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (33 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 34/38] drm: rcar-du: Remove unneeded rcar_du_crtc plane field Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 36/38] drm: rcar-du: Move plane commit code from CRTC start to CRTC resume Laurent Pinchart
` (3 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The format stored in the rcar_du_plane structure is part of the plane
state. Move it to the rcar_du_plane_state structure and precompute it in
the .atomic_check() handler.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 ++-
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 107 ++++++++++++++++++--------------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 6 +-
3 files changed, 71 insertions(+), 52 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index c70f73036056..98f770622b2d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -198,6 +198,12 @@ static unsigned int plane_zpos(struct rcar_du_plane *plane)
return to_rcar_du_plane_state(plane->plane.state)->zpos;
}
+static const struct rcar_du_format_info *
+plane_format(struct rcar_du_plane *plane)
+{
+ return to_rcar_du_plane_state(plane->plane.state)->format;
+}
+
static void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
@@ -223,7 +229,7 @@ static void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
}
planes[j] = plane;
- prio += plane->format->planes * 4;
+ prio += plane_format(plane)->planes * 4;
}
for (i = 0; i < num_planes; ++i) {
@@ -234,7 +240,7 @@ static void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
dspr |= (index + 1) << prio;
dptsr |= DPTSR_PnDK(index) | DPTSR_PnTS(index);
- if (plane->format->planes = 2) {
+ if (plane_format(plane)->planes = 2) {
index = (index + 1) % 8;
prio -= 4;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index c5cb2ade2722..58b9e02e6910 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -48,7 +48,8 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
}
static int rcar_du_plane_reserve_check(struct rcar_du_plane *plane,
- const struct rcar_du_format_info *format)
+ const struct rcar_du_format_info *cur_format,
+ const struct rcar_du_format_info *new_format)
{
struct rcar_du_group *rgrp = plane->group;
unsigned int free;
@@ -61,7 +62,7 @@ static int rcar_du_plane_reserve_check(struct rcar_du_plane *plane,
if (plane->hwindex != -1) {
free |= 1 << plane->hwindex;
- if (plane->format->planes = 2)
+ if (cur_format->planes = 2)
free |= 1 << ((plane->hwindex + 1) % 8);
}
@@ -69,7 +70,7 @@ static int rcar_du_plane_reserve_check(struct rcar_du_plane *plane,
if (!(free & (1 << i)))
continue;
- if (format->planes = 1 || free & (1 << ((i + 1) % 8)))
+ if (new_format->planes = 1 || free & (1 << ((i + 1) % 8)))
break;
}
@@ -113,7 +114,8 @@ done:
return ret;
}
-static void rcar_du_plane_release(struct rcar_du_plane *plane)
+static void rcar_du_plane_release(struct rcar_du_plane *plane,
+ const struct rcar_du_format_info *format)
{
struct rcar_du_group *rgrp = plane->group;
@@ -122,7 +124,7 @@ static void rcar_du_plane_release(struct rcar_du_plane *plane)
mutex_lock(&rgrp->planes.lock);
rgrp->planes.free |= 1 << plane->hwindex;
- if (plane->format->planes = 2)
+ if (format->planes = 2)
rgrp->planes.free |= 1 << ((plane->hwindex + 1) % 8);
mutex_unlock(&rgrp->planes.lock);
@@ -131,27 +133,29 @@ static void rcar_du_plane_release(struct rcar_du_plane *plane)
static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
{
+ struct rcar_du_plane_state *state + to_rcar_du_plane_state(plane->plane.state);
struct drm_framebuffer *fb = plane->plane.state->fb;
struct rcar_du_group *rgrp = plane->group;
- unsigned int src_x = plane->plane.state->src_x >> 16;
- unsigned int src_y = plane->plane.state->src_y >> 16;
+ unsigned int src_x = state->state.src_x >> 16;
+ unsigned int src_y = state->state.src_y >> 16;
unsigned int index = plane->hwindex;
struct drm_gem_cma_object *gem;
bool interlaced;
u32 mwr;
- interlaced = plane->plane.state->crtc->state->adjusted_mode.flags
+ interlaced = state->state.crtc->state->adjusted_mode.flags
& DRM_MODE_FLAG_INTERLACE;
/* Memory pitch (expressed in pixels). Must be doubled for interlaced
* operation with 32bpp formats.
*/
- if (plane->format->planes = 2)
+ if (state->format->planes = 2)
mwr = fb->pitches[0];
else
- mwr = fb->pitches[0] * 8 / plane->format->bpp;
+ mwr = fb->pitches[0] * 8 / state->format->bpp;
- if (interlaced && plane->format->bpp = 32)
+ if (interlaced && state->format->bpp = 32)
mwr *= 2;
rcar_du_plane_write(rgrp, index, PnMWR, mwr);
@@ -170,19 +174,19 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
*/
rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
- (!interlaced && plane->format->bpp = 32 ? 2 : 1));
+ (!interlaced && state->format->bpp = 32 ? 2 : 1));
gem = drm_fb_cma_get_gem_obj(fb, 0);
rcar_du_plane_write(rgrp, index, PnDSA0R, gem->paddr + fb->offsets[0]);
- if (plane->format->planes = 2) {
+ if (state->format->planes = 2) {
index = (index + 1) % 8;
rcar_du_plane_write(rgrp, index, PnMWR, fb->pitches[0]);
rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
- (plane->format->bpp = 16 ? 2 : 1) / 2);
+ (state->format->bpp = 16 ? 2 : 1) / 2);
gem = drm_fb_cma_get_gem_obj(fb, 1);
rcar_du_plane_write(rgrp, index, PnDSA0R,
@@ -208,13 +212,13 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
* For XRGB, set the alpha value to the plane-wide alpha value and
* enable alpha-blending regardless of the X bit value.
*/
- if (plane->format->fourcc != DRM_FORMAT_XRGB1555)
+ if (state->format->fourcc != DRM_FORMAT_XRGB1555)
rcar_du_plane_write(rgrp, index, PnALPHAR, PnALPHAR_ABIT_0);
else
rcar_du_plane_write(rgrp, index, PnALPHAR,
PnALPHAR_ABIT_X | state->alpha);
- pnmr = PnMR_BM_MD | plane->format->pnmr;
+ pnmr = PnMR_BM_MD | state->format->pnmr;
/* Disable color keying when requested. YUV formats have the
* PnMR_SPIM_TP_OFF bit set in their pnmr field, disabling color keying
@@ -224,12 +228,12 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
pnmr |= PnMR_SPIM_TP_OFF;
/* For packed YUV formats we need to select the U/V order. */
- if (plane->format->fourcc = DRM_FORMAT_YUYV)
+ if (state->format->fourcc = DRM_FORMAT_YUYV)
pnmr |= PnMR_YCDF_YUYV;
rcar_du_plane_write(rgrp, index, PnMR, pnmr);
- switch (plane->format->fourcc) {
+ switch (state->format->fourcc) {
case DRM_FORMAT_RGB565:
colorkey = ((state->colorkey & 0xf80000) >> 8)
| ((state->colorkey & 0x00fc00) >> 5)
@@ -256,6 +260,8 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
unsigned int index)
{
+ struct rcar_du_plane_state *state + to_rcar_du_plane_state(plane->plane.state);
struct rcar_du_group *rgrp = plane->group;
u32 ddcr2 = PnDDCR2_CODE;
u32 ddcr4;
@@ -267,17 +273,17 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
*/
ddcr4 = rcar_du_plane_read(rgrp, index, PnDDCR4);
ddcr4 &= ~PnDDCR4_EDF_MASK;
- ddcr4 |= plane->format->edf | PnDDCR4_CODE;
+ ddcr4 |= state->format->edf | PnDDCR4_CODE;
rcar_du_plane_setup_mode(plane, index);
- if (plane->format->planes = 2) {
+ if (state->format->planes = 2) {
if (plane->hwindex != index) {
- if (plane->format->fourcc = DRM_FORMAT_NV12 ||
- plane->format->fourcc = DRM_FORMAT_NV21)
+ if (state->format->fourcc = DRM_FORMAT_NV12 ||
+ state->format->fourcc = DRM_FORMAT_NV21)
ddcr2 |= PnDDCR2_Y420;
- if (plane->format->fourcc = DRM_FORMAT_NV21)
+ if (state->format->fourcc = DRM_FORMAT_NV21)
ddcr2 |= PnDDCR2_NV21;
ddcr2 |= PnDDCR2_DIVU;
@@ -304,8 +310,11 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
void rcar_du_plane_setup(struct rcar_du_plane *plane)
{
+ struct rcar_du_plane_state *state + to_rcar_du_plane_state(plane->plane.state);
+
__rcar_du_plane_setup(plane, plane->hwindex);
- if (plane->format->planes = 2)
+ if (state->format->planes = 2)
__rcar_du_plane_setup(plane, (plane->hwindex + 1) % 8);
rcar_du_plane_setup_fb(plane);
@@ -314,10 +323,11 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
static int rcar_du_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
+ struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state);
struct rcar_du_plane *rplane = to_rcar_plane(plane);
struct rcar_du_device *rcdu = rplane->group->dev;
- const struct rcar_du_format_info *format;
- unsigned int nplanes;
+ const struct rcar_du_format_info *cur_format;
+ const struct rcar_du_format_info *new_format;
int ret;
if (!state->fb || !state->crtc)
@@ -329,20 +339,20 @@ static int rcar_du_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
- format = rcar_du_format_info(state->fb->pixel_format);
- if (format = NULL) {
+ cur_format = to_rcar_du_plane_state(plane->state)->format;
+ new_format = rcar_du_format_info(state->fb->pixel_format);
+ if (new_format = NULL) {
dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
state->fb->pixel_format);
return -EINVAL;
}
- nplanes = rplane->format ? rplane->format->planes : 0;
-
/* If the number of required planes has changed we will need to
* reallocate hardware planes. Ensure free planes are available.
*/
- if (format->planes != nplanes) {
- ret = rcar_du_plane_reserve_check(rplane, format);
+ if (!cur_format || new_format->planes != cur_format->planes) {
+ ret = rcar_du_plane_reserve_check(rplane, cur_format,
+ new_format);
if (ret < 0) {
dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
__func__);
@@ -350,17 +360,23 @@ static int rcar_du_plane_atomic_check(struct drm_plane *plane,
}
}
+ rstate->format = new_format;
+
return 0;
}
-static void rcar_du_plane_disable(struct rcar_du_plane *rplane)
+static void rcar_du_plane_disable(struct rcar_du_plane *rplane,
+ const struct rcar_du_format_info *cur_format)
{
+ struct rcar_du_plane_state *rstate + to_rcar_du_plane_state(rplane->plane.state);
+
if (!rplane->plane.state->crtc)
return;
- rcar_du_plane_release(rplane);
+ rcar_du_plane_release(rplane, cur_format);
- rplane->format = NULL;
+ rstate->format = NULL;
}
static void rcar_du_plane_atomic_update(struct drm_plane *plane,
@@ -368,27 +384,26 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
{
struct rcar_du_plane *rplane = to_rcar_plane(plane);
struct drm_plane_state *state = plane->state;
- const struct rcar_du_format_info *format;
- unsigned int nplanes;
+ struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state);
+ const struct rcar_du_format_info *cur_format;
+ const struct rcar_du_format_info *new_format;
+
+ cur_format = to_rcar_du_plane_state(old_state)->format;
+ new_format = rstate->format;
if (!state->crtc) {
- rcar_du_plane_disable(rplane);
+ rcar_du_plane_disable(rplane, cur_format);
return;
}
- format = rcar_du_format_info(state->fb->pixel_format);
- nplanes = rplane->format ? rplane->format->planes : 0;
-
/* Reallocate hardware planes if the number of required planes has
* changed.
*/
- if (format->planes != nplanes) {
- rcar_du_plane_release(rplane);
- rcar_du_plane_reserve(rplane, format);
+ if (!cur_format || new_format->planes != cur_format->planes) {
+ rcar_du_plane_release(rplane, cur_format);
+ rcar_du_plane_reserve(rplane, new_format);
}
- rplane->format = format;
-
rcar_du_plane_setup(rplane);
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 7050fc1e11ec..0941c4830edd 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -32,12 +32,8 @@ struct rcar_du_group;
struct rcar_du_plane {
struct drm_plane plane;
-
struct rcar_du_group *group;
-
int hwindex; /* 0-based, -1 means unused */
-
- const struct rcar_du_format_info *format;
};
struct rcar_du_planes {
@@ -53,6 +49,8 @@ struct rcar_du_planes {
struct rcar_du_plane_state {
struct drm_plane_state state;
+ const struct rcar_du_format_info *format;
+
unsigned int alpha;
unsigned int colorkey;
unsigned int zpos;
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 36/38] drm: rcar-du: Move plane commit code from CRTC start to CRTC resume
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (34 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 35/38] drm: rcar-du: Move plane format to plane state Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 37/38] drm: rcar-du: Move group locking inside rcar_du_crtc_update_planes() Laurent Pinchart
` (2 subsequent siblings)
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
As the DRM core will commit plane states when performing atomic updates,
those don't need to be committed manually when the CRTC is started except
in the system resume code path.
However, the atomic plane commit step is currently performed between
mode set disable and mode set enable to mimick the legacy mode setting
operations order. This causes the device clocks to be disabled after
applying plane settings and reenabled when enabling the CRTC,
potentially losing hardware in between.
Reorder the operations to enable the CRTC first and only then apply
plane settings, removing the need to manage clocks in the atomic begin
and flush handlers. We can then move the plane state commit code out of
the CRTC start handler to the system resume handler.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 54 +++++++++++++---------------------
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 2 +-
2 files changed, 21 insertions(+), 35 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 98f770622b2d..29bbb44eecc9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -204,9 +204,8 @@ plane_format(struct rcar_du_plane *plane)
return to_rcar_du_plane_state(plane->plane.state)->format;
}
-static void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
+static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
{
- struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
unsigned int num_planes = 0;
unsigned int prio = 0;
@@ -354,7 +353,6 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
{
struct drm_crtc *crtc = &rcrtc->crtc;
bool interlaced;
- unsigned int i;
if (rcrtc->started)
return;
@@ -367,26 +365,8 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
rcar_du_crtc_set_display_timing(rcrtc);
rcar_du_group_set_routing(rcrtc->group);
- /* FIXME: Commit the planes state. This is required here as the CRTC can
- * be started from the system resume handler, which don't go
- * through .atomic_plane_update() and .atomic_flush() to commit plane
- * state. Additionally, given that the plane state atomic commit occurs
- * between CRTC disable and enable, the hardware state could also be
- * lost due to runtime PM, requiring a full commit here. This will be
- * fixed later after switching to atomic updates completely.
- */
- mutex_lock(&rcrtc->group->planes.lock);
- rcar_du_crtc_update_planes(crtc);
- mutex_unlock(&rcrtc->group->planes.lock);
-
- for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
- struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
-
- if (plane->plane.state->crtc != crtc)
- continue;
-
- rcar_du_plane_setup(plane);
- }
+ /* Start with all planes disabled. */
+ rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0);
/* Select master sync mode. This enables display operation in master
* sync mode (with the HSYNC and VSYNC signals configured as outputs and
@@ -437,11 +417,27 @@ void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc)
void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
{
+ unsigned int i;
+
if (!rcrtc->enabled)
return;
rcar_du_crtc_get(rcrtc);
rcar_du_crtc_start(rcrtc);
+
+ /* Commit the planes state. */
+ for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
+ struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
+
+ if (plane->plane.state->crtc != &rcrtc->crtc)
+ continue;
+
+ rcar_du_plane_setup(plane);
+ }
+
+ mutex_lock(&rcrtc->group->planes.lock);
+ rcar_du_crtc_update_planes(rcrtc);
+ mutex_unlock(&rcrtc->group->planes.lock);
}
/* -----------------------------------------------------------------------------
@@ -490,11 +486,6 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc)
struct drm_device *dev = rcrtc->crtc.dev;
unsigned long flags;
- /* We need to access the hardware during atomic update, acquire a
- * reference to the CRTC.
- */
- rcar_du_crtc_get(rcrtc);
-
if (event) {
event->pipe = rcrtc->index;
@@ -510,14 +501,9 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- /* We're done, apply the configuration and drop the reference acquired
- * in .atomic_begin().
- */
mutex_lock(&rcrtc->group->planes.lock);
- rcar_du_crtc_update_planes(crtc);
+ rcar_du_crtc_update_planes(rcrtc);
mutex_unlock(&rcrtc->group->planes.lock);
-
- rcar_du_crtc_put(rcrtc);
}
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index cec35e405248..8bc7242ba979 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -207,8 +207,8 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
/* Apply the atomic update. */
drm_atomic_helper_commit_modeset_disables(dev, old_state);
- drm_atomic_helper_commit_planes(dev, old_state);
drm_atomic_helper_commit_modeset_enables(dev, old_state);
+ drm_atomic_helper_commit_planes(dev, old_state);
drm_atomic_helper_wait_for_vblanks(dev, old_state);
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 37/38] drm: rcar-du: Move group locking inside rcar_du_crtc_update_planes()
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (35 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 36/38] drm: rcar-du: Move plane commit code from CRTC start to CRTC resume Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-25 21:54 ` [PATCH 38/38] drm: rcar-du: Fix race condition in hardware plane allocator Laurent Pinchart
2015-02-26 0:43 ` [PATCH 00/38] Renesas R-Car DU atomic updates support Magnus Damm
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
Only the planes to CRTCs association control register DPTSR needs to be
protected by custom locking, don't hold the mutex around the whole code.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 29bbb44eecc9..8459aaee8add 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -252,8 +252,6 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
* with superposition controller 2.
*/
if (rcrtc->index % 2) {
- u32 value = rcar_du_group_read(rcrtc->group, DPTSR);
-
/* The DPTSR register is updated when the display controller is
* stopped. We thus need to restart the DU. Once again, sorry
* for the flicker. One way to mitigate the issue would be to
@@ -261,11 +259,13 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
* split, or through a module parameter). Flicker would then
* occur only if we need to break the pre-association.
*/
- if (value != dptsr) {
+ mutex_lock(&rcrtc->group->planes.lock);
+ if (rcar_du_group_read(rcrtc->group, DPTSR) != dptsr) {
rcar_du_group_write(rcrtc->group, DPTSR, dptsr);
if (rcrtc->group->used_crtcs)
rcar_du_group_restart(rcrtc->group);
}
+ mutex_unlock(&rcrtc->group->planes.lock);
}
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
@@ -435,9 +435,7 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
rcar_du_plane_setup(plane);
}
- mutex_lock(&rcrtc->group->planes.lock);
rcar_du_crtc_update_planes(rcrtc);
- mutex_unlock(&rcrtc->group->planes.lock);
}
/* -----------------------------------------------------------------------------
@@ -501,9 +499,7 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- mutex_lock(&rcrtc->group->planes.lock);
rcar_du_crtc_update_planes(rcrtc);
- mutex_unlock(&rcrtc->group->planes.lock);
}
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 38/38] drm: rcar-du: Fix race condition in hardware plane allocator
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (36 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 37/38] drm: rcar-du: Move group locking inside rcar_du_crtc_update_planes() Laurent Pinchart
@ 2015-02-25 21:54 ` Laurent Pinchart
2015-02-26 0:43 ` [PATCH 00/38] Renesas R-Car DU atomic updates support Magnus Damm
38 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-25 21:54 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh
The plane allocator has been inherently racy since the beginning of the
transition to atomic updates, as the allocator lock is released between
free plane check (at .atomic_check() time) and the reservation (at
.atomic_update() time).
To fix it, create a new allocator solely based on the atomic plane
states without keeping any external state and perform allocation in the
.atomic_check() handler. The core idea is to replace the free planes
bitmask with a collective knowledge based on the allocated hardware
plane(s) for each KMS plane. The allocator then loops over all plane
states to compute the free planes bitmask, allocates hardware planes
based on that bitmask, and stores the result back in the plane states.
For this to work we need to access the current state of planes not
touched by the atomic update. To ensure that it won't be modified, we
need to lock all planes using drm_atomic_get_plane_state(). This
effectively serializes atomic updates from .atomic_check() up to
completion, either when swapping the states if the check step has
succeeded, or when freeing the states if the check step has failed.
Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 7 +-
drivers/gpu/drm/rcar-du/rcar_du_group.h | 5 +
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 203 +++++++++++++++++++++++++++++++-
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 166 ++------------------------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 11 +-
5 files changed, 228 insertions(+), 164 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 8459aaee8add..9e72133bb64b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -233,7 +233,8 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
for (i = 0; i < num_planes; ++i) {
struct rcar_du_plane *plane = planes[i];
- unsigned int index = plane->hwindex;
+ struct drm_plane_state *state = plane->plane.state;
+ unsigned int index = to_rcar_du_plane_state(state)->hwindex;
prio -= 4;
dspr |= (index + 1) << prio;
@@ -259,13 +260,13 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
* split, or through a module parameter). Flicker would then
* occur only if we need to break the pre-association.
*/
- mutex_lock(&rcrtc->group->planes.lock);
+ mutex_lock(&rcrtc->group->lock);
if (rcar_du_group_read(rcrtc->group, DPTSR) != dptsr) {
rcar_du_group_write(rcrtc->group, DPTSR, dptsr);
if (rcrtc->group->used_crtcs)
rcar_du_group_restart(rcrtc->group);
}
- mutex_unlock(&rcrtc->group->planes.lock);
+ mutex_unlock(&rcrtc->group->lock);
}
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index 0c38cdcda4ca..ed36433fbe84 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -14,6 +14,8 @@
#ifndef __RCAR_DU_GROUP_H__
#define __RCAR_DU_GROUP_H__
+#include <linux/mutex.h>
+
#include "rcar_du_plane.h"
struct rcar_du_device;
@@ -25,6 +27,7 @@ struct rcar_du_device;
* @index: group index
* @use_count: number of users of the group (rcar_du_group_(get|put))
* @used_crtcs: number of CRTCs currently in use
+ * @lock: protects the DPTSR register
* @planes: planes handled by the group
*/
struct rcar_du_group {
@@ -35,6 +38,8 @@ struct rcar_du_group {
unsigned int use_count;
unsigned int used_crtcs;
+ struct mutex lock;
+
struct rcar_du_planes planes;
};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 8bc7242ba979..fb052bca574f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -189,9 +189,206 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
}
/* -----------------------------------------------------------------------------
- * Atomic Updates
+ * Atomic Check and Update
*/
+/*
+ * Atomic hardware plane allocator
+ *
+ * The hardware plane allocator is solely based on the atomic plane states
+ * without keeping any external state to avoid races between .atomic_check()
+ * and .atomic_commit().
+ *
+ * The core idea is to avoid using a free planes bitmask that would need to be
+ * shared between check and commit handlers with a collective knowledge based on
+ * the allocated hardware plane(s) for each KMS plane. The allocator then loops
+ * over all plane states to compute the free planes bitmask, allocates hardware
+ * planes based on that bitmask, and stores the result back in the plane states.
+ *
+ * For this to work we need to access the current state of planes not touched by
+ * the atomic update. To ensure that it won't be modified, we need to lock all
+ * planes using drm_atomic_get_plane_state(). This effectively serializes atomic
+ * updates from .atomic_check() up to completion (when swapping the states if
+ * the check step has succeeded) or rollback (when freeing the states if the
+ * check step has failed).
+ *
+ * Allocation is performed in the .atomic_check() handler and applied
+ * automatically when the core swaps the old and new states.
+ */
+
+static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
+ struct rcar_du_plane_state *state)
+{
+ const struct rcar_du_format_info *cur_format;
+
+ cur_format = to_rcar_du_plane_state(plane->plane.state)->format;
+
+ /* Lowering the number of planes doesn't strictly require reallocation
+ * as the extra hardware plane will be freed when committing, but doing
+ * so could lead to more fragmentation.
+ */
+ return !cur_format || cur_format->planes != state->format->planes;
+}
+
+static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
+{
+ unsigned int mask;
+
+ if (state->hwindex = -1)
+ return 0;
+
+ mask = 1 << state->hwindex;
+ if (state->format->planes = 2)
+ mask |= 1 << ((state->hwindex + 1) % 8);
+
+ return mask;
+}
+
+static int rcar_du_plane_hwalloc(unsigned int num_planes, unsigned int free)
+{
+ unsigned int i;
+
+ for (i = 0; i < RCAR_DU_NUM_HW_PLANES; ++i) {
+ if (!(free & (1 << i)))
+ continue;
+
+ if (num_planes = 1 || free & (1 << ((i + 1) % 8)))
+ break;
+ }
+
+ return i = RCAR_DU_NUM_HW_PLANES ? -EBUSY : i;
+}
+
+static int rcar_du_atomic_check(struct drm_device *dev,
+ struct drm_atomic_state *state)
+{
+ struct rcar_du_device *rcdu = dev->dev_private;
+ unsigned int group_freed_planes[RCAR_DU_MAX_GROUPS] = { 0, };
+ unsigned int group_free_planes[RCAR_DU_MAX_GROUPS] = { 0, };
+ bool needs_realloc = false;
+ unsigned int groups = 0;
+ unsigned int i;
+ int ret;
+
+ ret = drm_atomic_helper_check(dev, state);
+ if (ret < 0)
+ return ret;
+
+ /* Check if hardware planes need to be reallocated. */
+ for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
+ struct rcar_du_plane_state *plane_state;
+ struct rcar_du_plane *plane;
+ unsigned int index;
+
+ if (!state->planes[i])
+ continue;
+
+ plane = to_rcar_plane(state->planes[i]);
+ plane_state = to_rcar_du_plane_state(state->plane_states[i]);
+
+ /* If the plane is being disabled we don't need to go through
+ * the full reallocation procedure. Just mark the hardware
+ * plane(s) as freed.
+ */
+ if (!plane_state->format) {
+ index = plane - plane->group->planes.planes;
+ group_freed_planes[plane->group->index] |= 1 << index;
+ plane_state->hwindex = -1;
+ continue;
+ }
+
+ /* If the plane needs to be reallocated mark it as such, and
+ * mark the hardware plane(s) as free.
+ */
+ if (rcar_du_plane_needs_realloc(plane, plane_state)) {
+ groups |= 1 << plane->group->index;
+ needs_realloc = true;
+
+ index = plane - plane->group->planes.planes;
+ group_freed_planes[plane->group->index] |= 1 << index;
+ plane_state->hwindex = -1;
+ }
+ }
+
+ if (!needs_realloc)
+ return 0;
+
+ /* Grab all plane states for the groups that need reallocation to ensure
+ * locking and avoid racy updates. This serializes the update operation,
+ * but there's not much we can do about it as that's the hardware
+ * design.
+ *
+ * Compute the used planes mask for each group at the same time to avoid
+ * looping over the planes separately later.
+ */
+ while (groups) {
+ unsigned int index = ffs(groups) - 1;
+ struct rcar_du_group *group = &rcdu->groups[index];
+ unsigned int used_planes = 0;
+
+ for (i = 0; i < RCAR_DU_NUM_KMS_PLANES; ++i) {
+ struct rcar_du_plane *plane = &group->planes.planes[i];
+ struct rcar_du_plane_state *plane_state;
+ struct drm_plane_state *s;
+
+ s = drm_atomic_get_plane_state(state, &plane->plane);
+ if (IS_ERR(s))
+ return PTR_ERR(s);
+
+ /* If the plane has been freed in the above loop its
+ * hardware planes must not be added to the used planes
+ * bitmask. However, the current state doesn't reflect
+ * the free state yet, as we've modified the new state
+ * above. Use the local freed planes list to check for
+ * that condition instead.
+ */
+ if (group_freed_planes[index] & (1 << i))
+ continue;
+
+ plane_state = to_rcar_du_plane_state(plane->plane.state);
+ used_planes |= rcar_du_plane_hwmask(plane_state);
+ }
+
+ group_free_planes[index] = 0xff & ~used_planes;
+ groups &= ~(1 << index);
+ }
+
+ /* Reallocate hardware planes for each plane that needs it. */
+ for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
+ struct rcar_du_plane_state *plane_state;
+ struct rcar_du_plane *plane;
+ int idx;
+
+ if (!state->planes[i])
+ continue;
+
+ plane = to_rcar_plane(state->planes[i]);
+ plane_state = to_rcar_du_plane_state(state->plane_states[i]);
+
+ /* Skip planes that are being disabled or don't need to be
+ * reallocated.
+ */
+ if (!plane_state->format ||
+ !rcar_du_plane_needs_realloc(plane, plane_state))
+ continue;
+
+ idx = rcar_du_plane_hwalloc(plane_state->format->planes,
+ group_free_planes[plane->group->index]);
+ if (idx < 0) {
+ dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
+ __func__);
+ return idx;
+ }
+
+ plane_state->hwindex = idx;
+
+ group_free_planes[plane->group->index] &+ ~rcar_du_plane_hwmask(plane_state);
+ }
+
+ return 0;
+}
+
struct rcar_du_commit {
struct work_struct work;
struct drm_device *dev;
@@ -292,7 +489,7 @@ static int rcar_du_atomic_commit(struct drm_device *dev,
static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {
.fb_create = rcar_du_fb_create,
.output_poll_changed = rcar_du_output_poll_changed,
- .atomic_check = drm_atomic_helper_check,
+ .atomic_check = rcar_du_atomic_check,
.atomic_commit = rcar_du_atomic_commit,
};
@@ -498,6 +695,8 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
for (i = 0; i < num_groups; ++i) {
struct rcar_du_group *rgrp = &rcdu->groups[i];
+ mutex_init(&rgrp->lock);
+
rgrp->dev = rcdu;
rgrp->mmio_offset = mmio_offsets[i];
rgrp->index = i;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 58b9e02e6910..35a2f04ab799 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -28,11 +28,6 @@
#define RCAR_DU_COLORKEY_SOURCE (1 << 24)
#define RCAR_DU_COLORKEY_MASK (1 << 24)
-static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane)
-{
- return container_of(plane, struct rcar_du_plane, plane);
-}
-
static u32 rcar_du_plane_read(struct rcar_du_group *rgrp,
unsigned int index, u32 reg)
{
@@ -47,90 +42,6 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
data);
}
-static int rcar_du_plane_reserve_check(struct rcar_du_plane *plane,
- const struct rcar_du_format_info *cur_format,
- const struct rcar_du_format_info *new_format)
-{
- struct rcar_du_group *rgrp = plane->group;
- unsigned int free;
- unsigned int i;
- int ret;
-
- mutex_lock(&rgrp->planes.lock);
-
- free = rgrp->planes.free;
-
- if (plane->hwindex != -1) {
- free |= 1 << plane->hwindex;
- if (cur_format->planes = 2)
- free |= 1 << ((plane->hwindex + 1) % 8);
- }
-
- for (i = 0; i < ARRAY_SIZE(rgrp->planes.planes); ++i) {
- if (!(free & (1 << i)))
- continue;
-
- if (new_format->planes = 1 || free & (1 << ((i + 1) % 8)))
- break;
- }
-
- ret = i = ARRAY_SIZE(rgrp->planes.planes) ? -EBUSY : 0;
-
- mutex_unlock(&rgrp->planes.lock);
- return ret;
-}
-
-static int rcar_du_plane_reserve(struct rcar_du_plane *plane,
- const struct rcar_du_format_info *format)
-{
- struct rcar_du_group *rgrp = plane->group;
- unsigned int i;
- int ret = -EBUSY;
-
- mutex_lock(&rgrp->planes.lock);
-
- for (i = 0; i < RCAR_DU_NUM_HW_PLANES; ++i) {
- if (!(rgrp->planes.free & (1 << i)))
- continue;
-
- if (format->planes = 1 ||
- rgrp->planes.free & (1 << ((i + 1) % 8)))
- break;
- }
-
- if (i = RCAR_DU_NUM_HW_PLANES)
- goto done;
-
- rgrp->planes.free &= ~(1 << i);
- if (format->planes = 2)
- rgrp->planes.free &= ~(1 << ((i + 1) % 8));
-
- plane->hwindex = i;
-
- ret = 0;
-
-done:
- mutex_unlock(&rgrp->planes.lock);
- return ret;
-}
-
-static void rcar_du_plane_release(struct rcar_du_plane *plane,
- const struct rcar_du_format_info *format)
-{
- struct rcar_du_group *rgrp = plane->group;
-
- if (plane->hwindex = -1)
- return;
-
- mutex_lock(&rgrp->planes.lock);
- rgrp->planes.free |= 1 << plane->hwindex;
- if (format->planes = 2)
- rgrp->planes.free |= 1 << ((plane->hwindex + 1) % 8);
- mutex_unlock(&rgrp->planes.lock);
-
- plane->hwindex = -1;
-}
-
static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
{
struct rcar_du_plane_state *state @@ -139,7 +50,7 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
struct rcar_du_group *rgrp = plane->group;
unsigned int src_x = state->state.src_x >> 16;
unsigned int src_y = state->state.src_y >> 16;
- unsigned int index = plane->hwindex;
+ unsigned int index = state->hwindex;
struct drm_gem_cma_object *gem;
bool interlaced;
u32 mwr;
@@ -278,7 +189,7 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
rcar_du_plane_setup_mode(plane, index);
if (state->format->planes = 2) {
- if (plane->hwindex != index) {
+ if (state->hwindex != index) {
if (state->format->fourcc = DRM_FORMAT_NV12 ||
state->format->fourcc = DRM_FORMAT_NV21)
ddcr2 |= PnDDCR2_Y420;
@@ -313,9 +224,9 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
struct rcar_du_plane_state *state to_rcar_du_plane_state(plane->plane.state);
- __rcar_du_plane_setup(plane, plane->hwindex);
+ __rcar_du_plane_setup(plane, state->hwindex);
if (state->format->planes = 2)
- __rcar_du_plane_setup(plane, (plane->hwindex + 1) % 8);
+ __rcar_du_plane_setup(plane, (state->hwindex + 1) % 8);
rcar_du_plane_setup_fb(plane);
}
@@ -326,12 +237,11 @@ static int rcar_du_plane_atomic_check(struct drm_plane *plane,
struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state);
struct rcar_du_plane *rplane = to_rcar_plane(plane);
struct rcar_du_device *rcdu = rplane->group->dev;
- const struct rcar_du_format_info *cur_format;
- const struct rcar_du_format_info *new_format;
- int ret;
- if (!state->fb || !state->crtc)
+ if (!state->fb || !state->crtc) {
+ rstate->format = NULL;
return 0;
+ }
if (state->src_w >> 16 != state->crtc_w ||
state->src_h >> 16 != state->crtc_h) {
@@ -339,72 +249,23 @@ static int rcar_du_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
- cur_format = to_rcar_du_plane_state(plane->state)->format;
- new_format = rcar_du_format_info(state->fb->pixel_format);
- if (new_format = NULL) {
+ rstate->format = rcar_du_format_info(state->fb->pixel_format);
+ if (rstate->format = NULL) {
dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
state->fb->pixel_format);
return -EINVAL;
}
- /* If the number of required planes has changed we will need to
- * reallocate hardware planes. Ensure free planes are available.
- */
- if (!cur_format || new_format->planes != cur_format->planes) {
- ret = rcar_du_plane_reserve_check(rplane, cur_format,
- new_format);
- if (ret < 0) {
- dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
- __func__);
- return ret;
- }
- }
-
- rstate->format = new_format;
-
return 0;
}
-static void rcar_du_plane_disable(struct rcar_du_plane *rplane,
- const struct rcar_du_format_info *cur_format)
-{
- struct rcar_du_plane_state *rstate - to_rcar_du_plane_state(rplane->plane.state);
-
- if (!rplane->plane.state->crtc)
- return;
-
- rcar_du_plane_release(rplane, cur_format);
-
- rstate->format = NULL;
-}
-
static void rcar_du_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct rcar_du_plane *rplane = to_rcar_plane(plane);
- struct drm_plane_state *state = plane->state;
- struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state);
- const struct rcar_du_format_info *cur_format;
- const struct rcar_du_format_info *new_format;
- cur_format = to_rcar_du_plane_state(old_state)->format;
- new_format = rstate->format;
-
- if (!state->crtc) {
- rcar_du_plane_disable(rplane, cur_format);
- return;
- }
-
- /* Reallocate hardware planes if the number of required planes has
- * changed.
- */
- if (!cur_format || new_format->planes != cur_format->planes) {
- rcar_du_plane_release(rplane, cur_format);
- rcar_du_plane_reserve(rplane, new_format);
- }
-
- rcar_du_plane_setup(rplane);
+ if (plane->state->crtc)
+ rcar_du_plane_setup(rplane);
}
static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
@@ -426,6 +287,7 @@ static void rcar_du_plane_reset(struct drm_plane *plane)
if (state = NULL)
return;
+ state->hwindex = -1;
state->alpha = 255;
state->colorkey = RCAR_DU_COLORKEY_NONE;
state->zpos = plane->type = DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
@@ -534,9 +396,6 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
unsigned int i;
int ret;
- mutex_init(&planes->lock);
- planes->free = 0xff;
-
planes->alpha drm_property_create_range(rcdu->ddev, 0, "alpha", 0, 255);
if (planes->alpha = NULL)
@@ -572,7 +431,6 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
struct rcar_du_plane *plane = &planes->planes[i];
plane->group = rgrp;
- plane->hwindex = -1;
ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
&rcar_du_plane_funcs, formats,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 0941c4830edd..abff0ebeb195 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -14,8 +14,6 @@
#ifndef __RCAR_DU_PLANE_H__
#define __RCAR_DU_PLANE_H__
-#include <linux/mutex.h>
-
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
@@ -33,13 +31,15 @@ struct rcar_du_group;
struct rcar_du_plane {
struct drm_plane plane;
struct rcar_du_group *group;
- int hwindex; /* 0-based, -1 means unused */
};
+static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane)
+{
+ return container_of(plane, struct rcar_du_plane, plane);
+}
+
struct rcar_du_planes {
struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
- unsigned int free;
- struct mutex lock;
struct drm_property *alpha;
struct drm_property *colorkey;
@@ -50,6 +50,7 @@ struct rcar_du_plane_state {
struct drm_plane_state state;
const struct rcar_du_format_info *format;
+ int hwindex; /* 0-based, -1 means unused */
unsigned int alpha;
unsigned int colorkey;
--
2.0.5
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 00/38] Renesas R-Car DU atomic updates support
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
` (37 preceding siblings ...)
2015-02-25 21:54 ` [PATCH 38/38] drm: rcar-du: Fix race condition in hardware plane allocator Laurent Pinchart
@ 2015-02-26 0:43 ` Magnus Damm
2015-02-26 9:23 ` Laurent Pinchart
38 siblings, 1 reply; 43+ messages in thread
From: Magnus Damm @ 2015-02-26 0:43 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: dri-devel, SH-Linux
Hi Laurent,
On Wed, Feb 25, 2015 at 1:54 PM, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> Hello,
>
> This patch series implements atomic updates support for the rcar-du driver.
>
> The series starts with four core atomic helpers fixes/cleanups (two from
> Daniel that I have included here for completeness). It then follows with two
> fixes for the adv7511 driver and height fixes for the rcar-du driver. It
> finally gets to work by slowly reworking rcar-du until atomic updates are
> fully implemented and the transitional helpers gone.
>
> The patches are based on Dave's 'next' branch and available at
>
> git://linuxtv.org/pinchartl/fbdev.git drm/next/atomic
>
> The last patch contains a hardware plane allocator based solely on state
> objects, which could be useful as a base implementation should other drivers
> experience similar needs.
Many thanks for your efforts on this!
It looks to me like the adv7511 fixes would be useful as-is
independently of the atomic update changes.
[PATCH 05/38] drm: adv7511: Fix DDC error interrupt handling
[PATCH 06/38] drm: adv7511: Fix nested sleep when reading EDID
Is it possible to fast track just the fixes somehow? I believe that
several hardware platforms with adv7511 chips would benefit from these
fixes.
Best,
/ magnus
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/38] Renesas R-Car DU atomic updates support
2015-02-26 0:43 ` [PATCH 00/38] Renesas R-Car DU atomic updates support Magnus Damm
@ 2015-02-26 9:23 ` Laurent Pinchart
2015-02-27 0:14 ` Magnus Damm
0 siblings, 1 reply; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-26 9:23 UTC (permalink / raw)
To: Magnus Damm, dri-devel; +Cc: SH-Linux
Hi Magnus,
On Wednesday 25 February 2015 16:43:53 Magnus Damm wrote:
> On Wed, Feb 25, 2015 at 1:54 PM, Laurent Pinchart wrote:
> > Hello,
> >
> > This patch series implements atomic updates support for the rcar-du
> > driver.
> >
> > The series starts with four core atomic helpers fixes/cleanups (two from
> > Daniel that I have included here for completeness). It then follows with
> > two fixes for the adv7511 driver and height fixes for the rcar-du driver.
> > It finally gets to work by slowly reworking rcar-du until atomic updates
> > are fully implemented and the transitional helpers gone.
> >
> > The patches are based on Dave's 'next' branch and available at
> >
> > git://linuxtv.org/pinchartl/fbdev.git drm/next/atomic
> >
> > The last patch contains a hardware plane allocator based solely on state
> > objects, which could be useful as a base implementation should other
> > drivers experience similar needs.
>
> Many thanks for your efforts on this!
>
> It looks to me like the adv7511 fixes would be useful as-is
> independently of the atomic update changes.
>
> [PATCH 05/38] drm: adv7511: Fix DDC error interrupt handling
> [PATCH 06/38] drm: adv7511: Fix nested sleep when reading EDID
>
> Is it possible to fast track just the fixes somehow? I believe that
> several hardware platforms with adv7511 chips would benefit from these
> fixes.
Do you mean fast track them to v4.0 or v4.1 ? I certainly want to see them in
v4.1 (hopefully with the rest of the series as well) and I can mark them as
stable candidates.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/38] Renesas R-Car DU atomic updates support
2015-02-26 9:23 ` Laurent Pinchart
@ 2015-02-27 0:14 ` Magnus Damm
2015-02-27 10:43 ` Laurent Pinchart
0 siblings, 1 reply; 43+ messages in thread
From: Magnus Damm @ 2015-02-27 0:14 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: dri-devel, SH-Linux
Hi Laurent,
On Thu, Feb 26, 2015 at 1:23 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi Magnus,
>
> On Wednesday 25 February 2015 16:43:53 Magnus Damm wrote:
>> On Wed, Feb 25, 2015 at 1:54 PM, Laurent Pinchart wrote:
>> > Hello,
>> >
>> > This patch series implements atomic updates support for the rcar-du
>> > driver.
>> >
>> > The series starts with four core atomic helpers fixes/cleanups (two from
>> > Daniel that I have included here for completeness). It then follows with
>> > two fixes for the adv7511 driver and height fixes for the rcar-du driver.
>> > It finally gets to work by slowly reworking rcar-du until atomic updates
>> > are fully implemented and the transitional helpers gone.
>> >
>> > The patches are based on Dave's 'next' branch and available at
>> >
>> > git://linuxtv.org/pinchartl/fbdev.git drm/next/atomic
>> >
>> > The last patch contains a hardware plane allocator based solely on state
>> > objects, which could be useful as a base implementation should other
>> > drivers experience similar needs.
>>
>> Many thanks for your efforts on this!
>>
>> It looks to me like the adv7511 fixes would be useful as-is
>> independently of the atomic update changes.
>>
>> [PATCH 05/38] drm: adv7511: Fix DDC error interrupt handling
>> [PATCH 06/38] drm: adv7511: Fix nested sleep when reading EDID
>>
>> Is it possible to fast track just the fixes somehow? I believe that
>> several hardware platforms with adv7511 chips would benefit from these
>> fixes.
>
> Do you mean fast track them to v4.0 or v4.1 ? I certainly want to see them in
> v4.1 (hopefully with the rest of the series as well) and I can mark them as
> stable candidates.
The earlier the better IMO, so v4.0 is of course very nice if possible
however v4.1 is also just fine.
Cheers,
/ magnus
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/38] Renesas R-Car DU atomic updates support
2015-02-27 0:14 ` Magnus Damm
@ 2015-02-27 10:43 ` Laurent Pinchart
0 siblings, 0 replies; 43+ messages in thread
From: Laurent Pinchart @ 2015-02-27 10:43 UTC (permalink / raw)
To: Magnus Damm; +Cc: dri-devel, SH-Linux, Dave Airlie
Hi Magnus,
(CC'ing Dave)
On Thursday 26 February 2015 16:14:09 Magnus Damm wrote:
> On Thu, Feb 26, 2015 at 1:23 AM, Laurent Pinchart wrote:
> > On Wednesday 25 February 2015 16:43:53 Magnus Damm wrote:
> >> On Wed, Feb 25, 2015 at 1:54 PM, Laurent Pinchart wrote:
> >>> Hello,
> >>>
> >>> This patch series implements atomic updates support for the rcar-du
> >>> driver.
> >>>
> >>> The series starts with four core atomic helpers fixes/cleanups (two
> >>> from Daniel that I have included here for completeness). It then
> >>> follows with two fixes for the adv7511 driver and height fixes for the
> >>> rcar-du driver. It finally gets to work by slowly reworking rcar-du
> >>> until atomic updates are fully implemented and the transitional helpers
> >>> gone.
> >>>
> >>> The patches are based on Dave's 'next' branch and available at
> >>>
> >>> git://linuxtv.org/pinchartl/fbdev.git drm/next/atomic
> >>>
> >>> The last patch contains a hardware plane allocator based solely on
> >>> state objects, which could be useful as a base implementation should
> >>> other drivers experience similar needs.
> >>
> >> Many thanks for your efforts on this!
> >>
> >> It looks to me like the adv7511 fixes would be useful as-is
> >> independently of the atomic update changes.
> >>
> >> [PATCH 05/38] drm: adv7511: Fix DDC error interrupt handling
> >> [PATCH 06/38] drm: adv7511: Fix nested sleep when reading EDID
> >>
> >> Is it possible to fast track just the fixes somehow? I believe that
> >> several hardware platforms with adv7511 chips would benefit from these
> >> fixes.
> >
> > Do you mean fast track them to v4.0 or v4.1 ? I certainly want to see them
> > in v4.1 (hopefully with the rest of the series as well) and I can mark
> > them as stable candidates.
>
> The earlier the better IMO, so v4.0 is of course very nice if possible
> however v4.1 is also just fine.
The above two patches are not regression fixes, so I doubt getting them merged
in v4.0-rc would be possible. I'll let Dave decide.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2015-02-27 10:43 UTC | newest]
Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-25 21:54 [PATCH 00/38] Renesas R-Car DU atomic updates support Laurent Pinchart
2015-02-25 21:54 ` [PATCH 01/38] drm/atomic: Rename drm_atomic_helper_commit_pre_planes() state argument Laurent Pinchart
2015-02-25 21:54 ` [PATCH 02/38] drm/atomic-helper: Rename commmit_post/pre_planes Laurent Pinchart
2015-02-25 21:54 ` [PATCH 03/38] drm/atomic-helpers: make mode_set hooks optional Laurent Pinchart
2015-02-25 21:54 ` [PATCH 04/38] drm/atomic-helpers: Fix documentation typos and wrong copy&paste Laurent Pinchart
2015-02-25 21:54 ` [PATCH 05/38] drm: adv7511: Fix DDC error interrupt handling Laurent Pinchart
2015-02-25 21:54 ` [PATCH 06/38] drm: adv7511: Fix nested sleep when reading EDID Laurent Pinchart
2015-02-25 21:54 ` [PATCH 07/38] drm: rcar-du: Don't disable unused functions at init time Laurent Pinchart
2015-02-25 21:54 ` [PATCH 08/38] drm: rcar-du: Remove drm_fbdev_cma_restore_mode() call " Laurent Pinchart
2015-02-25 21:54 ` [PATCH 09/38] drm: rcar-du: Don't set connector->encoder " Laurent Pinchart
2015-02-25 21:54 ` [PATCH 10/38] drm: rcar-du: Reorder CRTC functions Laurent Pinchart
2015-02-25 21:54 ` [PATCH 11/38] drm: rcar-du: Wait for page flip completion when turning the CRTC off Laurent Pinchart
2015-02-25 21:54 ` [PATCH 12/38] drm: rcar-du: Turn vblank on/off when enabling/disabling CRTC Laurent Pinchart
2015-02-25 21:54 ` [PATCH 13/38] drm: rcar-du: Disable fbdev emulation when no connector is present Laurent Pinchart
2015-02-25 21:54 ` [PATCH 14/38] drm: rcar-du: Define macros for the max number of groups, CRTCs and LVDS Laurent Pinchart
2015-02-25 21:54 ` [PATCH 15/38] drm: rcar-du: Implement universal plane support Laurent Pinchart
2015-02-25 21:54 ` [PATCH 16/38] drm: rcar-du: Fix hardware plane allocation Laurent Pinchart
2015-02-25 21:54 ` [PATCH 17/38] drm: rcar-du: Implement planes atomic operations Laurent Pinchart
2015-02-25 21:54 ` [PATCH 18/38] drm: rcar-du: Handle primary plane config through atomic plane ops Laurent Pinchart
2015-02-25 21:54 ` [PATCH 19/38] drm: rcar-du: Wire up atomic state object scaffolding Laurent Pinchart
2015-02-25 21:54 ` [PATCH 20/38] drm: rcar-du: Remove private copy of plane size and position Laurent Pinchart
2015-02-25 21:54 ` [PATCH 21/38] drm: rcar-du: Replace LVDS encoder DPMS by enable/disable Laurent Pinchart
2015-02-25 21:54 ` [PATCH 22/38] drm: rcar-du: Rework encoder enable/disable for atomic updates Laurent Pinchart
2015-02-25 21:54 ` [PATCH 23/38] drm: rcar-du: Rework HDMI " Laurent Pinchart
2015-02-25 21:54 ` [PATCH 24/38] drm: rcar-du: Rework CRTC " Laurent Pinchart
2015-02-25 21:54 ` [PATCH 25/38] drm: rcar-du: Switch plane update to atomic helpers Laurent Pinchart
2015-02-25 21:54 ` [PATCH 26/38] drm: rcar-du: Switch mode config " Laurent Pinchart
2015-02-25 21:54 ` [PATCH 27/38] drm: rcar-du: Switch connector DPMS " Laurent Pinchart
2015-02-25 21:54 ` [PATCH 28/38] drm: rcar-du: Replace encoder mode_fixup with atomic_check Laurent Pinchart
2015-02-25 21:54 ` [PATCH 29/38] drm: rcar-du: Implement asynchronous commit support Laurent Pinchart
2015-02-25 21:54 ` [PATCH 30/38] drm: rcar-du: Switch page flip to atomic helpers Laurent Pinchart
2015-02-25 21:54 ` [PATCH 31/38] drm: rcar-du: Switch plane set_property " Laurent Pinchart
2015-02-25 21:54 ` [PATCH 32/38] drm: rcar-du: Rework plane setup code Laurent Pinchart
2015-02-25 21:54 ` [PATCH 33/38] drm: rcar-du: Replace plane crtc and enabled fields by plane state Laurent Pinchart
2015-02-25 21:54 ` [PATCH 34/38] drm: rcar-du: Remove unneeded rcar_du_crtc plane field Laurent Pinchart
2015-02-25 21:54 ` [PATCH 35/38] drm: rcar-du: Move plane format to plane state Laurent Pinchart
2015-02-25 21:54 ` [PATCH 36/38] drm: rcar-du: Move plane commit code from CRTC start to CRTC resume Laurent Pinchart
2015-02-25 21:54 ` [PATCH 37/38] drm: rcar-du: Move group locking inside rcar_du_crtc_update_planes() Laurent Pinchart
2015-02-25 21:54 ` [PATCH 38/38] drm: rcar-du: Fix race condition in hardware plane allocator Laurent Pinchart
2015-02-26 0:43 ` [PATCH 00/38] Renesas R-Car DU atomic updates support Magnus Damm
2015-02-26 9:23 ` Laurent Pinchart
2015-02-27 0:14 ` Magnus Damm
2015-02-27 10:43 ` Laurent Pinchart
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox