Hello all,
This patch series is a continuation of rework of blending support in Exynos DRM driver. Some background can be found here: http://www.spinics.net/lists/dri-devel/msg96969.html
Daniel Vetter suggested that zpos property should be made generic, with well-defined semantics. This patchset is my proposal for such generic zpos property: - added zpos properties to drm core and plane state structures, - added helpers for normalizing zpos properties of given set of planes, - well defined semantics: planes are sorted by zpos values and then plane id value if zpos equals.
Patches are based on top of latest exynos-drm-next branch.
Best regards Marek Szyprowski Samsung R&D Institute Poland
Changelog:
v2: - dropped 2 fixes for Exynos DRM, which got merged in meantime - added more comments and kernel docs for core functions as suggested by Daniel Vetter - reworked initialization of zpos properties (moved assiging property class to common code), now the code in the driver is even simpler - while reworking of intialization of zpos property code, did the same change to generic rotation property
v1: http://www.spinics.net/lists/dri-devel/msg97709.html - initial version
Patch summary:
Marek Szyprowski (3): drm: add generic zpos property drm/exynos: use generic code for managing zpos plane property drm: simplify initialization of rotation property
Documentation/DocBook/gpu.tmpl | 14 ++++- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 10 ++-- drivers/gpu/drm/drm_atomic.c | 4 ++ drivers/gpu/drm/drm_atomic_helper.c | 45 +++++++++++++++ drivers/gpu/drm/drm_crtc.c | 73 +++++++++++++++++++++++-- drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 - drivers/gpu/drm/exynos/exynos_drm_plane.c | 66 +++++----------------- drivers/gpu/drm/exynos/exynos_mixer.c | 19 ++++++- drivers/gpu/drm/i915/intel_display.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 3 +- drivers/gpu/drm/omapdrm/omap_drv.c | 3 +- include/drm/drm_atomic_helper.h | 2 + include/drm/drm_crtc.h | 16 +++++- 13 files changed, 182 insertions(+), 80 deletions(-)
This patch adds support for generic plane's zpos property property with well-defined semantics: - added zpos properties to drm core and plane state structures - added helpers for normalizing zpos properties of given set of planes - well defined semantics: planes are sorted by zpos values and then plane id value if zpos equals
Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com --- Documentation/DocBook/gpu.tmpl | 14 +++++++++-- drivers/gpu/drm/drm_atomic.c | 4 ++++ drivers/gpu/drm/drm_atomic_helper.c | 45 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc.c | 47 +++++++++++++++++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 2 ++ include/drm/drm_crtc.h | 12 ++++++++++ 6 files changed, 122 insertions(+), 2 deletions(-)
diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index 6c6e81a9eaf4..e81acd999891 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -2004,7 +2004,7 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >Description/Restrictions</td> </tr> <tr> - <td rowspan="37" valign="top" >DRM</td> + <td rowspan="38" valign="top" >DRM</td> <td valign="top" >Generic</td> <td valign="top" >“rotation”</td> <td valign="top" >BITMASK</td> @@ -2256,7 +2256,7 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >property to suggest an Y offset for a connector</td> </tr> <tr> - <td rowspan="3" valign="top" >Optional</td> + <td rowspan="4" valign="top" >Optional</td> <td valign="top" >“scaling mode”</td> <td valign="top" >ENUM</td> <td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td> @@ -2280,6 +2280,16 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >TBD</td> </tr> <tr> + <td valign="top" > "zpos" </td> + <td valign="top" >RANGE</td> + <td valign="top" >Min=0, Max=255</td> + <td valign="top" >Plane</td> + <td valign="top" >Plane's 'z' position during blending (0 for background, 255 for frontmost). + If two planes assigned to same CRTC have equal zpos values, the plane with higher plane + id is treated as closer to front. Can be IMMUTABLE if driver doesn't support changing + planes' order.</td> + </tr> + <tr> <td rowspan="20" valign="top" >i915</td> <td rowspan="2" valign="top" >Generic</td> <td valign="top" >"Broadcast RGB"</td> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 6a21e5c378c1..97bb069cb6a3 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -614,6 +614,8 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, state->src_h = val; } else if (property == config->rotation_property) { state->rotation = val; + } else if (property == config->zpos_property) { + state->zpos = val; } else if (plane->funcs->atomic_set_property) { return plane->funcs->atomic_set_property(plane, state, property, val); @@ -670,6 +672,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = state->src_h; } else if (property == config->rotation_property) { *val = state->rotation; + } else if (property == config->zpos_property) { + *val = state->zpos; } else if (plane->funcs->atomic_get_property) { return plane->funcs->atomic_get_property(plane, state, property, val); } else { diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 268d37f26960..167d32346e2f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -31,6 +31,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_atomic_helper.h> #include <linux/fence.h> +#include <linux/sort.h>
/** * DOC: overview @@ -2781,3 +2782,47 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, kfree(state); } EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); + +static int __drm_atomic_helper_plane_zpos_cmp(const void *a, const void *b) +{ + const struct drm_plane *pa = *(struct drm_plane **)a; + const struct drm_plane *pb = *(struct drm_plane **)b; + int zpos_a = 0, zpos_b = 0; + + if (pa->state) + zpos_a = pa->state->zpos << 16; + if (pb->state) + zpos_b = pb->state->zpos << 16; + + zpos_a += pa->base.id; + zpos_b += pb->base.id; + + return zpos_a - zpos_b; +} + +/** + * drm_atomic_helper_normalize_zpos - calculate normalized zpos values + * @planes: arrays of pointer to planes to consider for normalization + * @count: number of planes in the above array + * + * This function takes arrays of pointers to planes and calculates normalized + * zpos value for them taking into account each planes[i]->state->zpos value + * and plane's id. Planes are compared first by their zpos values, then in case + * they equal, by plane id. Plane with lowest zpos value is at the bottom. + * The plane[i]->state->normalized_zpos is then filled with uniqe values from 0 + * to count-1. + * Note: a side effect of this function is the fact that the planes array will + * be modified (sorted). It is up to the caller to construct planes array with + * all planes that have been assigned to given crtc. + */ +void drm_atomic_helper_normalize_zpos(struct drm_plane *planes[], int count) +{ + int i; + + sort(planes, count, sizeof(struct drm_plane *), + __drm_atomic_helper_plane_zpos_cmp, NULL); + for (i = 0; i < count; i++) + if (planes[i]->state) + planes[i]->state->normalized_zpos = i; +} +EXPORT_SYMBOL(drm_atomic_helper_normalize_zpos); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 62fa95fa5471..e33866084b70 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -5880,6 +5880,53 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, EXPORT_SYMBOL(drm_mode_create_rotation_property);
/** + * drm_mode_create_zpos_property - create muttable zpos property + * @dev: DRM device + * + * This function initializes generic muttable zpos property and enables support + * for it in drm core. Drivers can then attach this property to planes to enable + * support for configurable planes arrangement during blending operation. + * Drivers can also use drm_atomic_helper_normalize_zpos() function to calculate + * drm_plane_state->normalized_zpos values. + */ +int drm_mode_create_zpos_property(struct drm_device *dev) +{ + struct drm_property *prop; + + prop = drm_property_create_range(dev, 0, "zpos", 0, 255); + if (!prop) + return -ENOMEM; + + dev->mode_config.zpos_property = prop; + return 0; +} +EXPORT_SYMBOL(drm_mode_create_zpos_property); + +/** + * drm_plane_create_zpos_property - create immuttable zpos property + * @dev: DRM device + * + * This function initializes generic immuttable zpos property and enables + * support for it in drm core. Using this property driver lets userspace + * to get the arrangement of the planes for blending operation and notifies + * it that the hardware (or driver) doesn't support changing of the planes' + * order. + */ +int drm_mode_create_zpos_immutable_property(struct drm_device *dev) +{ + struct drm_property *prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "zpos", + 0, 255); + if (!prop) + return -ENOMEM; + + dev->mode_config.zpos_immutable_property = prop; + return 0; +} +EXPORT_SYMBOL(drm_mode_create_zpos_immutable_property); + +/** * DOC: Tile group * * Tile groups are used to represent tiled monitors with a unique diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index a286cce98720..2a7ade5ad8bd 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -141,6 +141,8 @@ __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state);
+void drm_atomic_helper_normalize_zpos(struct drm_plane *planes[], int count); + /** * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC * @plane: the loop cursor diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 3b040b355472..13035e2c5e51 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1243,6 +1243,9 @@ struct drm_connector { * plane (in 16.16) * @src_w: width of visible portion of plane (in 16.16) * @src_h: height of visible portion of plane (in 16.16) + * @zpos: priority of the given plane on crtc (optional) + * @normalized_zpos: normalized value of zpos: uniqe, range from 0 to + * (number of planes - 1) for given crtc * @state: backpointer to global drm_atomic_state */ struct drm_plane_state { @@ -1263,6 +1266,10 @@ struct drm_plane_state { /* Plane rotation */ unsigned int rotation;
+ /* Plane zpos */ + unsigned int zpos; + unsigned int normalized_zpos; + struct drm_atomic_state *state; };
@@ -2083,6 +2090,8 @@ struct drm_mode_config { struct drm_property *tile_property; struct drm_property *plane_type_property; struct drm_property *rotation_property; + struct drm_property *zpos_property; + struct drm_property *zpos_immutable_property; struct drm_property *prop_src_x; struct drm_property *prop_src_y; struct drm_property *prop_src_w; @@ -2484,6 +2493,9 @@ extern struct drm_property *drm_mode_create_rotation_property(struct drm_device extern unsigned int drm_rotation_simplify(unsigned int rotation, unsigned int supported_rotations);
+extern int drm_mode_create_zpos_property(struct drm_device *dev); +extern int drm_mode_create_zpos_immutable_property(struct drm_device *dev); + /* Helpers */
static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
On Mon, Jan 11, 2016 at 12:03:03PM +0100, Marek Szyprowski wrote:
This patch adds support for generic plane's zpos property property with well-defined semantics:
- added zpos properties to drm core and plane state structures
- added helpers for normalizing zpos properties of given set of planes
- well defined semantics: planes are sorted by zpos values and then plane id value if zpos equals
Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com
Documentation/DocBook/gpu.tmpl | 14 +++++++++-- drivers/gpu/drm/drm_atomic.c | 4 ++++ drivers/gpu/drm/drm_atomic_helper.c | 45 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc.c | 47 +++++++++++++++++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 2 ++ include/drm/drm_crtc.h | 12 ++++++++++ 6 files changed, 122 insertions(+), 2 deletions(-)
diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index 6c6e81a9eaf4..e81acd999891 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -2004,7 +2004,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >Description/Restrictions</td> </tr> <tr> - <td rowspan="37" valign="top" >DRM</td> + <td rowspan="38" valign="top" >DRM</td> <td valign="top" >Generic</td> <td valign="top" >“rotation”</td> <td valign="top" >BITMASK</td> @@ -2256,7 +2256,7 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >property to suggest an Y offset for a connector</td> </tr> <tr> - <td rowspan="3" valign="top" >Optional</td> + <td rowspan="4" valign="top" >Optional</td> <td valign="top" >“scaling mode”</td> <td valign="top" >ENUM</td> <td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td> @@ -2280,6 +2280,16 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >TBD</td> </tr> <tr> + <td valign="top" > "zpos" </td> + <td valign="top" >RANGE</td> + <td valign="top" >Min=0, Max=255</td> + <td valign="top" >Plane</td> + <td valign="top" >Plane's 'z' position during blending (0 for background, 255 for frontmost). + If two planes assigned to same CRTC have equal zpos values, the plane with higher plane + id is treated as closer to front. Can be IMMUTABLE if driver doesn't support changing + planes' order.</td> + </tr> + <tr> <td rowspan="20" valign="top" >i915</td> <td rowspan="2" valign="top" >Generic</td> <td valign="top" >"Broadcast RGB"</td> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 6a21e5c378c1..97bb069cb6a3 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -614,6 +614,8 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, state->src_h = val; } else if (property == config->rotation_property) { state->rotation = val; + } else if (property == config->zpos_property) { + state->zpos = val; } else if (plane->funcs->atomic_set_property) { return plane->funcs->atomic_set_property(plane, state, property, val); @@ -670,6 +672,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = state->src_h; } else if (property == config->rotation_property) { *val = state->rotation; + } else if (property == config->zpos_property) { + *val = state->zpos; } else if (plane->funcs->atomic_get_property) { return plane->funcs->atomic_get_property(plane, state, property, val); } else { diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 268d37f26960..167d32346e2f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -31,6 +31,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_atomic_helper.h> #include <linux/fence.h> +#include <linux/sort.h>
/**
- DOC: overview
@@ -2781,3 +2782,47 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, kfree(state); } EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
+static int __drm_atomic_helper_plane_zpos_cmp(const void *a, const void *b) +{
- const struct drm_plane *pa = *(struct drm_plane **)a;
- const struct drm_plane *pb = *(struct drm_plane **)b;
- int zpos_a = 0, zpos_b = 0;
- if (pa->state)
zpos_a = pa->state->zpos << 16;
- if (pb->state)
zpos_b = pb->state->zpos << 16;
- zpos_a += pa->base.id;
- zpos_b += pb->base.id;
- return zpos_a - zpos_b;
+}
+/**
- drm_atomic_helper_normalize_zpos - calculate normalized zpos values
- @planes: arrays of pointer to planes to consider for normalization
- @count: number of planes in the above array
- This function takes arrays of pointers to planes and calculates normalized
- zpos value for them taking into account each planes[i]->state->zpos value
- and plane's id. Planes are compared first by their zpos values, then in case
- they equal, by plane id. Plane with lowest zpos value is at the bottom.
- The plane[i]->state->normalized_zpos is then filled with uniqe values from 0
- to count-1.
- Note: a side effect of this function is the fact that the planes array will
- be modified (sorted). It is up to the caller to construct planes array with
- all planes that have been assigned to given crtc.
- */
+void drm_atomic_helper_normalize_zpos(struct drm_plane *planes[], int count) +{
- int i;
- sort(planes, count, sizeof(struct drm_plane *),
__drm_atomic_helper_plane_zpos_cmp, NULL);
- for (i = 0; i < count; i++)
if (planes[i]->state)
planes[i]->state->normalized_zpos = i;
+} +EXPORT_SYMBOL(drm_atomic_helper_normalize_zpos); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 62fa95fa5471..e33866084b70 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -5880,6 +5880,53 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, EXPORT_SYMBOL(drm_mode_create_rotation_property);
/**
- drm_mode_create_zpos_property - create muttable zpos property
- @dev: DRM device
- This function initializes generic muttable zpos property and enables support
- for it in drm core. Drivers can then attach this property to planes to enable
- support for configurable planes arrangement during blending operation.
- Drivers can also use drm_atomic_helper_normalize_zpos() function to calculate
- drm_plane_state->normalized_zpos values.
Should also document return value semantics. Same for all the others with non-void return value. But I have some more thoughts about the helper interface itself (in reply to patch 2) so maybe that should wait a bit until that's settled. -Daniel
- */
+int drm_mode_create_zpos_property(struct drm_device *dev) +{
- struct drm_property *prop;
- prop = drm_property_create_range(dev, 0, "zpos", 0, 255);
- if (!prop)
return -ENOMEM;
- dev->mode_config.zpos_property = prop;
- return 0;
+} +EXPORT_SYMBOL(drm_mode_create_zpos_property);
+/**
- drm_plane_create_zpos_property - create immuttable zpos property
- @dev: DRM device
- This function initializes generic immuttable zpos property and enables
- support for it in drm core. Using this property driver lets userspace
- to get the arrangement of the planes for blending operation and notifies
- it that the hardware (or driver) doesn't support changing of the planes'
- order.
- */
+int drm_mode_create_zpos_immutable_property(struct drm_device *dev) +{
- struct drm_property *prop;
- prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "zpos",
0, 255);
- if (!prop)
return -ENOMEM;
- dev->mode_config.zpos_immutable_property = prop;
- return 0;
+} +EXPORT_SYMBOL(drm_mode_create_zpos_immutable_property);
+/**
- DOC: Tile group
- Tile groups are used to represent tiled monitors with a unique
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index a286cce98720..2a7ade5ad8bd 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -141,6 +141,8 @@ __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state);
+void drm_atomic_helper_normalize_zpos(struct drm_plane *planes[], int count);
/**
- drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
- @plane: the loop cursor
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 3b040b355472..13035e2c5e51 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1243,6 +1243,9 @@ struct drm_connector {
- plane (in 16.16)
- @src_w: width of visible portion of plane (in 16.16)
- @src_h: height of visible portion of plane (in 16.16)
- @zpos: priority of the given plane on crtc (optional)
- @normalized_zpos: normalized value of zpos: uniqe, range from 0 to
*/
- (number of planes - 1) for given crtc
- @state: backpointer to global drm_atomic_state
struct drm_plane_state { @@ -1263,6 +1266,10 @@ struct drm_plane_state { /* Plane rotation */ unsigned int rotation;
- /* Plane zpos */
- unsigned int zpos;
- unsigned int normalized_zpos;
- struct drm_atomic_state *state;
};
@@ -2083,6 +2090,8 @@ struct drm_mode_config { struct drm_property *tile_property; struct drm_property *plane_type_property; struct drm_property *rotation_property;
- struct drm_property *zpos_property;
- struct drm_property *zpos_immutable_property; struct drm_property *prop_src_x; struct drm_property *prop_src_y; struct drm_property *prop_src_w;
@@ -2484,6 +2493,9 @@ extern struct drm_property *drm_mode_create_rotation_property(struct drm_device extern unsigned int drm_rotation_simplify(unsigned int rotation, unsigned int supported_rotations);
+extern int drm_mode_create_zpos_property(struct drm_device *dev); +extern int drm_mode_create_zpos_immutable_property(struct drm_device *dev);
/* Helpers */
static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
1.9.2
This patch replaces zpos property handling custom code in Exynos DRM driver with calls to generic DRM code.
Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com --- drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 - drivers/gpu/drm/exynos/exynos_drm_plane.c | 66 +++++++------------------------ drivers/gpu/drm/exynos/exynos_mixer.c | 19 +++++++-- 3 files changed, 30 insertions(+), 56 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 17b5ded72ff1..244ae6c4482c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -217,7 +217,6 @@ struct exynos_drm_private { * this array is used to be aware of which crtc did it request vblank. */ struct drm_crtc *crtc[MAX_CRTC]; - struct drm_property *plane_zpos_property;
unsigned long da_start; unsigned long da_space_size; diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index d86227236f55..ba46bc3de796 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -137,9 +137,9 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL); if (exynos_state) { - exynos_state->zpos = exynos_plane->config->zpos; plane->state = &exynos_state->base; plane->state->plane = plane; + plane->state->zpos = exynos_plane->config->zpos; } }
@@ -155,7 +155,6 @@ exynos_drm_plane_duplicate_state(struct drm_plane *plane) return NULL;
__drm_atomic_helper_plane_duplicate_state(plane, ©->base); - copy->zpos = exynos_state->zpos; return ©->base; }
@@ -168,43 +167,6 @@ static void exynos_drm_plane_destroy_state(struct drm_plane *plane, kfree(old_exynos_state); }
-static int exynos_drm_plane_atomic_set_property(struct drm_plane *plane, - struct drm_plane_state *state, - struct drm_property *property, - uint64_t val) -{ - struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_plane_state *exynos_state = - to_exynos_plane_state(state); - struct exynos_drm_private *dev_priv = plane->dev->dev_private; - const struct exynos_drm_plane_config *config = exynos_plane->config; - - if (property == dev_priv->plane_zpos_property && - (config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS)) - exynos_state->zpos = val; - else - return -EINVAL; - - return 0; -} - -static int exynos_drm_plane_atomic_get_property(struct drm_plane *plane, - const struct drm_plane_state *state, - struct drm_property *property, - uint64_t *val) -{ - const struct exynos_drm_plane_state *exynos_state = - container_of(state, const struct exynos_drm_plane_state, base); - struct exynos_drm_private *dev_priv = plane->dev->dev_private; - - if (property == dev_priv->plane_zpos_property) - *val = exynos_state->zpos; - else - return -EINVAL; - - return 0; -} - static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -213,8 +175,6 @@ static struct drm_plane_funcs exynos_plane_funcs = { .reset = exynos_drm_plane_reset, .atomic_duplicate_state = exynos_drm_plane_duplicate_state, .atomic_destroy_state = exynos_drm_plane_destroy_state, - .atomic_set_property = exynos_drm_plane_atomic_set_property, - .atomic_get_property = exynos_drm_plane_atomic_get_property, };
static int @@ -302,20 +262,21 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = { };
static void exynos_plane_attach_zpos_property(struct drm_plane *plane, - unsigned int zpos) + unsigned int zpos, bool immutable) { struct drm_device *dev = plane->dev; - struct exynos_drm_private *dev_priv = dev->dev_private; struct drm_property *prop;
- prop = dev_priv->plane_zpos_property; - if (!prop) { - prop = drm_property_create_range(dev, 0, "zpos", - 0, MAX_PLANE - 1); - if (!prop) - return; - - dev_priv->plane_zpos_property = prop; + if (immutable) { + if (!dev->mode_config.zpos_immutable_property) + if (!drm_mode_create_zpos_immutable_property(dev)) + return; + prop = dev->mode_config.zpos_immutable_property; + } else { + if (!dev->mode_config.zpos_property) + if (!drm_mode_create_zpos_property(dev)) + return; + prop = dev->mode_config.zpos_property; }
drm_object_attach_property(&plane->base, prop, zpos); @@ -344,7 +305,8 @@ int exynos_plane_init(struct drm_device *dev, exynos_plane->index = index; exynos_plane->config = config;
- exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos); + exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos, + !(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS));
return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index b5fbc1cbf024..6ab68eca0004 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -34,6 +34,7 @@ #include <linux/component.h>
#include <drm/exynos_drm.h> +#include <drm/drm_atomic_helper.h>
#include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" @@ -95,6 +96,8 @@ struct mixer_context { struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR]; + struct drm_plane *zpos_planes[MIXER_WIN_NR]; + int num_planes; int pipe; unsigned long flags; bool interlace; @@ -478,6 +481,7 @@ static void vp_video_buffer(struct mixer_context *ctx, struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb; + unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; dma_addr_t luma_addr[2], chroma_addr[2]; bool tiled_mode = false; @@ -562,7 +566,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
mixer_cfg_scan(ctx, mode->vdisplay); mixer_cfg_rgb_fmt(ctx, mode->vdisplay); - mixer_cfg_layer(ctx, plane->index, state->zpos + 1, true); + mixer_cfg_layer(ctx, plane->index, priority, true); mixer_cfg_vp_blend(ctx); mixer_run(ctx);
@@ -587,6 +591,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb; + unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; unsigned int win = plane->index; unsigned int x_ratio = 0, y_ratio = 0; @@ -678,7 +683,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
mixer_cfg_scan(ctx, mode->vdisplay); mixer_cfg_rgb_fmt(ctx, mode->vdisplay); - mixer_cfg_layer(ctx, win, state->zpos + 1, true); + mixer_cfg_layer(ctx, win, priority, true); mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format));
/* layer update mandatory for mixer 16.0.33.0 */ @@ -981,6 +986,12 @@ static void mixer_atomic_begin(struct exynos_drm_crtc *crtc) if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) return;
+ /* + * Normalizing up to 3 planes is cheap, no need for checking + * if zpos has been really changed. + */ + drm_atomic_helper_normalize_zpos(mixer_ctx->zpos_planes, + mixer_ctx->num_planes); mixer_vsync_set_update(mixer_ctx, false); }
@@ -1203,13 +1214,15 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
for (i = 0; i < MIXER_WIN_NR; i++) { if (i == VP_DEFAULT_WIN && !ctx->vp_enabled) - continue; + break;
ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, 1 << ctx->pipe, &plane_configs[i]); if (ret) return ret; + ctx->zpos_planes[i] = &ctx->planes[i].base; } + ctx->num_planes = i;
exynos_plane = &ctx->planes[DEFAULT_WIN]; ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
On Mon, Jan 11, 2016 at 12:03:04PM +0100, Marek Szyprowski wrote:
This patch replaces zpos property handling custom code in Exynos DRM driver with calls to generic DRM code.
Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com
drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 - drivers/gpu/drm/exynos/exynos_drm_plane.c | 66 +++++++------------------------ drivers/gpu/drm/exynos/exynos_mixer.c | 19 +++++++-- 3 files changed, 30 insertions(+), 56 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 17b5ded72ff1..244ae6c4482c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -217,7 +217,6 @@ struct exynos_drm_private { * this array is used to be aware of which crtc did it request vblank. */ struct drm_crtc *crtc[MAX_CRTC];
struct drm_property *plane_zpos_property;
unsigned long da_start; unsigned long da_space_size;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index d86227236f55..ba46bc3de796 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -137,9 +137,9 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL); if (exynos_state) {
plane->state = &exynos_state->base; plane->state->plane = plane;exynos_state->zpos = exynos_plane->config->zpos;
}plane->state->zpos = exynos_plane->config->zpos;
}
@@ -155,7 +155,6 @@ exynos_drm_plane_duplicate_state(struct drm_plane *plane) return NULL;
__drm_atomic_helper_plane_duplicate_state(plane, ©->base);
- copy->zpos = exynos_state->zpos; return ©->base;
}
@@ -168,43 +167,6 @@ static void exynos_drm_plane_destroy_state(struct drm_plane *plane, kfree(old_exynos_state); }
-static int exynos_drm_plane_atomic_set_property(struct drm_plane *plane,
struct drm_plane_state *state,
struct drm_property *property,
uint64_t val)
-{
- struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
- struct exynos_drm_plane_state *exynos_state =
to_exynos_plane_state(state);
- struct exynos_drm_private *dev_priv = plane->dev->dev_private;
- const struct exynos_drm_plane_config *config = exynos_plane->config;
- if (property == dev_priv->plane_zpos_property &&
(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS))
exynos_state->zpos = val;
- else
return -EINVAL;
- return 0;
-}
-static int exynos_drm_plane_atomic_get_property(struct drm_plane *plane,
const struct drm_plane_state *state,
struct drm_property *property,
uint64_t *val)
-{
- const struct exynos_drm_plane_state *exynos_state =
container_of(state, const struct exynos_drm_plane_state, base);
- struct exynos_drm_private *dev_priv = plane->dev->dev_private;
- if (property == dev_priv->plane_zpos_property)
*val = exynos_state->zpos;
- else
return -EINVAL;
- return 0;
-}
static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -213,8 +175,6 @@ static struct drm_plane_funcs exynos_plane_funcs = { .reset = exynos_drm_plane_reset, .atomic_duplicate_state = exynos_drm_plane_duplicate_state, .atomic_destroy_state = exynos_drm_plane_destroy_state,
- .atomic_set_property = exynos_drm_plane_atomic_set_property,
- .atomic_get_property = exynos_drm_plane_atomic_get_property,
};
static int @@ -302,20 +262,21 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = { };
static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
unsigned int zpos)
unsigned int zpos, bool immutable)
{ struct drm_device *dev = plane->dev;
struct exynos_drm_private *dev_priv = dev->dev_private; struct drm_property *prop;
prop = dev_priv->plane_zpos_property;
if (!prop) {
prop = drm_property_create_range(dev, 0, "zpos",
0, MAX_PLANE - 1);
if (!prop)
return;
dev_priv->plane_zpos_property = prop;
if (immutable) {
if (!dev->mode_config.zpos_immutable_property)
if (!drm_mode_create_zpos_immutable_property(dev))
return;
prop = dev->mode_config.zpos_immutable_property;
} else {
if (!dev->mode_config.zpos_property)
if (!drm_mode_create_zpos_property(dev))
return;
prop = dev->mode_config.zpos_property;
}
drm_object_attach_property(&plane->base, prop, zpos);
@@ -344,7 +305,8 @@ int exynos_plane_init(struct drm_device *dev, exynos_plane->index = index; exynos_plane->config = config;
- exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos);
exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos,
!(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS));
return 0;
} diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index b5fbc1cbf024..6ab68eca0004 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -34,6 +34,7 @@ #include <linux/component.h>
#include <drm/exynos_drm.h> +#include <drm/drm_atomic_helper.h>
#include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" @@ -95,6 +96,8 @@ struct mixer_context { struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR];
- struct drm_plane *zpos_planes[MIXER_WIN_NR];
- int num_planes; int pipe; unsigned long flags; bool interlace;
@@ -478,6 +481,7 @@ static void vp_video_buffer(struct mixer_context *ctx, struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb;
- unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; dma_addr_t luma_addr[2], chroma_addr[2]; bool tiled_mode = false;
@@ -562,7 +566,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
mixer_cfg_scan(ctx, mode->vdisplay); mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
- mixer_cfg_layer(ctx, plane->index, state->zpos + 1, true);
- mixer_cfg_layer(ctx, plane->index, priority, true); mixer_cfg_vp_blend(ctx); mixer_run(ctx);
@@ -587,6 +591,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb;
- unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; unsigned int win = plane->index; unsigned int x_ratio = 0, y_ratio = 0;
@@ -678,7 +683,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
mixer_cfg_scan(ctx, mode->vdisplay); mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
- mixer_cfg_layer(ctx, win, state->zpos + 1, true);
mixer_cfg_layer(ctx, win, priority, true); mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format));
/* layer update mandatory for mixer 16.0.33.0 */
@@ -981,6 +986,12 @@ static void mixer_atomic_begin(struct exynos_drm_crtc *crtc) if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) return;
- /*
* Normalizing up to 3 planes is cheap, no need for checking
* if zpos has been really changed.
*/
- drm_atomic_helper_normalize_zpos(mixer_ctx->zpos_planes,
mixer_ctx->num_planes);
Hm, this is a bit a cumbersome interface for drivers and will make converting over to the normalized zpos more work. Can't we handle this in the atomic helpers directly? I'm thinking of the following flow:
- if new_plane_state->zpos != old_plane_state->zpos then set new_crtc_state->zpos_changed - if new_crtc_state->plane_mask != old_crtc_state->plane_mask || new_crtc_state->zpos_changed then recompute normilized zpos.
Imo that would fit well in drm_atomic_helper_check_planes().
With that bit of additional logic drivers can just use normlized_zpos and don't need to care about anything really.
Thoughts? -Daniel
mixer_vsync_set_update(mixer_ctx, false); }
@@ -1203,13 +1214,15 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
for (i = 0; i < MIXER_WIN_NR; i++) { if (i == VP_DEFAULT_WIN && !ctx->vp_enabled)
continue;
break;
ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, 1 << ctx->pipe, &plane_configs[i]); if (ret) return ret;
ctx->zpos_planes[i] = &ctx->planes[i].base;
}
ctx->num_planes = i;
exynos_plane = &ctx->planes[DEFAULT_WIN]; ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
-- 1.9.2
Hello,
On 2016-01-11 16:13, Daniel Vetter wrote:
On Mon, Jan 11, 2016 at 12:03:04PM +0100, Marek Szyprowski wrote:
This patch replaces zpos property handling custom code in Exynos DRM driver with calls to generic DRM code.
Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com
drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 - drivers/gpu/drm/exynos/exynos_drm_plane.c | 66 +++++++------------------------ drivers/gpu/drm/exynos/exynos_mixer.c | 19 +++++++-- 3 files changed, 30 insertions(+), 56 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 17b5ded72ff1..244ae6c4482c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -217,7 +217,6 @@ struct exynos_drm_private { * this array is used to be aware of which crtc did it request vblank. */ struct drm_crtc *crtc[MAX_CRTC];
struct drm_property *plane_zpos_property;
unsigned long da_start; unsigned long da_space_size;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index d86227236f55..ba46bc3de796 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -137,9 +137,9 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL); if (exynos_state) {
plane->state = &exynos_state->base; plane->state->plane = plane;exynos_state->zpos = exynos_plane->config->zpos;
} }plane->state->zpos = exynos_plane->config->zpos;
@@ -155,7 +155,6 @@ exynos_drm_plane_duplicate_state(struct drm_plane *plane) return NULL;
__drm_atomic_helper_plane_duplicate_state(plane, ©->base);
- copy->zpos = exynos_state->zpos; return ©->base; }
@@ -168,43 +167,6 @@ static void exynos_drm_plane_destroy_state(struct drm_plane *plane, kfree(old_exynos_state); }
-static int exynos_drm_plane_atomic_set_property(struct drm_plane *plane,
struct drm_plane_state *state,
struct drm_property *property,
uint64_t val)
-{
- struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
- struct exynos_drm_plane_state *exynos_state =
to_exynos_plane_state(state);
- struct exynos_drm_private *dev_priv = plane->dev->dev_private;
- const struct exynos_drm_plane_config *config = exynos_plane->config;
- if (property == dev_priv->plane_zpos_property &&
(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS))
exynos_state->zpos = val;
- else
return -EINVAL;
- return 0;
-}
-static int exynos_drm_plane_atomic_get_property(struct drm_plane *plane,
const struct drm_plane_state *state,
struct drm_property *property,
uint64_t *val)
-{
- const struct exynos_drm_plane_state *exynos_state =
container_of(state, const struct exynos_drm_plane_state, base);
- struct exynos_drm_private *dev_priv = plane->dev->dev_private;
- if (property == dev_priv->plane_zpos_property)
*val = exynos_state->zpos;
- else
return -EINVAL;
- return 0;
-}
- static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane,
@@ -213,8 +175,6 @@ static struct drm_plane_funcs exynos_plane_funcs = { .reset = exynos_drm_plane_reset, .atomic_duplicate_state = exynos_drm_plane_duplicate_state, .atomic_destroy_state = exynos_drm_plane_destroy_state,
.atomic_set_property = exynos_drm_plane_atomic_set_property,
.atomic_get_property = exynos_drm_plane_atomic_get_property, };
static int
@@ -302,20 +262,21 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = { };
static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
unsigned int zpos)
{ struct drm_device *dev = plane->dev;unsigned int zpos, bool immutable)
struct exynos_drm_private *dev_priv = dev->dev_private; struct drm_property *prop;
prop = dev_priv->plane_zpos_property;
if (!prop) {
prop = drm_property_create_range(dev, 0, "zpos",
0, MAX_PLANE - 1);
if (!prop)
return;
dev_priv->plane_zpos_property = prop;
if (immutable) {
if (!dev->mode_config.zpos_immutable_property)
if (!drm_mode_create_zpos_immutable_property(dev))
return;
prop = dev->mode_config.zpos_immutable_property;
} else {
if (!dev->mode_config.zpos_property)
if (!drm_mode_create_zpos_property(dev))
return;
prop = dev->mode_config.zpos_property;
}
drm_object_attach_property(&plane->base, prop, zpos);
@@ -344,7 +305,8 @@ int exynos_plane_init(struct drm_device *dev, exynos_plane->index = index; exynos_plane->config = config;
- exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos);
exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos,
!(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS));
return 0; }
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index b5fbc1cbf024..6ab68eca0004 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -34,6 +34,7 @@ #include <linux/component.h>
#include <drm/exynos_drm.h> +#include <drm/drm_atomic_helper.h>
#include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" @@ -95,6 +96,8 @@ struct mixer_context { struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR];
- struct drm_plane *zpos_planes[MIXER_WIN_NR];
- int num_planes; int pipe; unsigned long flags; bool interlace;
@@ -478,6 +481,7 @@ static void vp_video_buffer(struct mixer_context *ctx, struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb;
- unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; dma_addr_t luma_addr[2], chroma_addr[2]; bool tiled_mode = false;
@@ -562,7 +566,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
mixer_cfg_scan(ctx, mode->vdisplay); mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
- mixer_cfg_layer(ctx, plane->index, state->zpos + 1, true);
- mixer_cfg_layer(ctx, plane->index, priority, true); mixer_cfg_vp_blend(ctx); mixer_run(ctx);
@@ -587,6 +591,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb;
- unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; unsigned int win = plane->index; unsigned int x_ratio = 0, y_ratio = 0;
@@ -678,7 +683,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
mixer_cfg_scan(ctx, mode->vdisplay); mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
- mixer_cfg_layer(ctx, win, state->zpos + 1, true);
mixer_cfg_layer(ctx, win, priority, true); mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format));
/* layer update mandatory for mixer 16.0.33.0 */
@@ -981,6 +986,12 @@ static void mixer_atomic_begin(struct exynos_drm_crtc *crtc) if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) return;
- /*
* Normalizing up to 3 planes is cheap, no need for checking
* if zpos has been really changed.
*/
- drm_atomic_helper_normalize_zpos(mixer_ctx->zpos_planes,
mixer_ctx->num_planes);
Hm, this is a bit a cumbersome interface for drivers and will make converting over to the normalized zpos more work. Can't we handle this in the atomic helpers directly? I'm thinking of the following flow:
- if new_plane_state->zpos != old_plane_state->zpos then set new_crtc_state->zpos_changed
- if new_crtc_state->plane_mask != old_crtc_state->plane_mask || new_crtc_state->zpos_changed then recompute normilized zpos.
Imo that would fit well in drm_atomic_helper_check_planes().
With that bit of additional logic drivers can just use normlized_zpos and don't need to care about anything really.
Okay, I will try to implement this logic.
Best regards
On Tue, Jan 12, 2016 at 10:34:27AM +0100, Marek Szyprowski wrote:
Hello,
On 2016-01-11 16:13, Daniel Vetter wrote:
On Mon, Jan 11, 2016 at 12:03:04PM +0100, Marek Szyprowski wrote:
This patch replaces zpos property handling custom code in Exynos DRM driver with calls to generic DRM code.
Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com
drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 - drivers/gpu/drm/exynos/exynos_drm_plane.c | 66 +++++++------------------------ drivers/gpu/drm/exynos/exynos_mixer.c | 19 +++++++-- 3 files changed, 30 insertions(+), 56 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 17b5ded72ff1..244ae6c4482c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -217,7 +217,6 @@ struct exynos_drm_private { * this array is used to be aware of which crtc did it request vblank. */ struct drm_crtc *crtc[MAX_CRTC];
- struct drm_property *plane_zpos_property; unsigned long da_start; unsigned long da_space_size;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index d86227236f55..ba46bc3de796 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -137,9 +137,9 @@ static void exynos_drm_plane_reset(struct drm_plane *plane) exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL); if (exynos_state) {
plane->state = &exynos_state->base; plane->state->plane = plane;exynos_state->zpos = exynos_plane->config->zpos;
}plane->state->zpos = exynos_plane->config->zpos;
} @@ -155,7 +155,6 @@ exynos_drm_plane_duplicate_state(struct drm_plane *plane) return NULL; __drm_atomic_helper_plane_duplicate_state(plane, ©->base);
- copy->zpos = exynos_state->zpos; return ©->base;
} @@ -168,43 +167,6 @@ static void exynos_drm_plane_destroy_state(struct drm_plane *plane, kfree(old_exynos_state); } -static int exynos_drm_plane_atomic_set_property(struct drm_plane *plane,
struct drm_plane_state *state,
struct drm_property *property,
uint64_t val)
-{
- struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
- struct exynos_drm_plane_state *exynos_state =
to_exynos_plane_state(state);
- struct exynos_drm_private *dev_priv = plane->dev->dev_private;
- const struct exynos_drm_plane_config *config = exynos_plane->config;
- if (property == dev_priv->plane_zpos_property &&
(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS))
exynos_state->zpos = val;
- else
return -EINVAL;
- return 0;
-}
-static int exynos_drm_plane_atomic_get_property(struct drm_plane *plane,
const struct drm_plane_state *state,
struct drm_property *property,
uint64_t *val)
-{
- const struct exynos_drm_plane_state *exynos_state =
container_of(state, const struct exynos_drm_plane_state, base);
- struct exynos_drm_private *dev_priv = plane->dev->dev_private;
- if (property == dev_priv->plane_zpos_property)
*val = exynos_state->zpos;
- else
return -EINVAL;
- return 0;
-}
static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -213,8 +175,6 @@ static struct drm_plane_funcs exynos_plane_funcs = { .reset = exynos_drm_plane_reset, .atomic_duplicate_state = exynos_drm_plane_duplicate_state, .atomic_destroy_state = exynos_drm_plane_destroy_state,
- .atomic_set_property = exynos_drm_plane_atomic_set_property,
- .atomic_get_property = exynos_drm_plane_atomic_get_property,
}; static int @@ -302,20 +262,21 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = { }; static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
unsigned int zpos)
unsigned int zpos, bool immutable)
{ struct drm_device *dev = plane->dev;
- struct exynos_drm_private *dev_priv = dev->dev_private; struct drm_property *prop;
- prop = dev_priv->plane_zpos_property;
- if (!prop) {
prop = drm_property_create_range(dev, 0, "zpos",
0, MAX_PLANE - 1);
if (!prop)
return;
dev_priv->plane_zpos_property = prop;
- if (immutable) {
if (!dev->mode_config.zpos_immutable_property)
if (!drm_mode_create_zpos_immutable_property(dev))
return;
prop = dev->mode_config.zpos_immutable_property;
- } else {
if (!dev->mode_config.zpos_property)
if (!drm_mode_create_zpos_property(dev))
return;
} drm_object_attach_property(&plane->base, prop, zpos);prop = dev->mode_config.zpos_property;
@@ -344,7 +305,8 @@ int exynos_plane_init(struct drm_device *dev, exynos_plane->index = index; exynos_plane->config = config;
- exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos);
- exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos,
return 0;!(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS));
} diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index b5fbc1cbf024..6ab68eca0004 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -34,6 +34,7 @@ #include <linux/component.h> #include <drm/exynos_drm.h> +#include <drm/drm_atomic_helper.h> #include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" @@ -95,6 +96,8 @@ struct mixer_context { struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR];
- struct drm_plane *zpos_planes[MIXER_WIN_NR];
- int num_planes; int pipe; unsigned long flags; bool interlace;
@@ -478,6 +481,7 @@ static void vp_video_buffer(struct mixer_context *ctx, struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb;
- unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; dma_addr_t luma_addr[2], chroma_addr[2]; bool tiled_mode = false;
@@ -562,7 +566,7 @@ static void vp_video_buffer(struct mixer_context *ctx, mixer_cfg_scan(ctx, mode->vdisplay); mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
- mixer_cfg_layer(ctx, plane->index, state->zpos + 1, true);
- mixer_cfg_layer(ctx, plane->index, priority, true); mixer_cfg_vp_blend(ctx); mixer_run(ctx);
@@ -587,6 +591,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb;
- unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; unsigned int win = plane->index; unsigned int x_ratio = 0, y_ratio = 0;
@@ -678,7 +683,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, mixer_cfg_scan(ctx, mode->vdisplay); mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
- mixer_cfg_layer(ctx, win, state->zpos + 1, true);
- mixer_cfg_layer(ctx, win, priority, true); mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format)); /* layer update mandatory for mixer 16.0.33.0 */
@@ -981,6 +986,12 @@ static void mixer_atomic_begin(struct exynos_drm_crtc *crtc) if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) return;
- /*
* Normalizing up to 3 planes is cheap, no need for checking
* if zpos has been really changed.
*/
- drm_atomic_helper_normalize_zpos(mixer_ctx->zpos_planes,
mixer_ctx->num_planes);
Hm, this is a bit a cumbersome interface for drivers and will make converting over to the normalized zpos more work. Can't we handle this in the atomic helpers directly? I'm thinking of the following flow:
- if new_plane_state->zpos != old_plane_state->zpos then set new_crtc_state->zpos_changed
- if new_crtc_state->plane_mask != old_crtc_state->plane_mask || new_crtc_state->zpos_changed then recompute normilized zpos.
Imo that would fit well in drm_atomic_helper_check_planes().
With that bit of additional logic drivers can just use normlized_zpos and don't need to care about anything really.
Okay, I will try to implement this logic.
Just to avoid another respin: If you do so I think it still makes sense to export the current set of functions, for drivers which don't use helpers or need to figure out the normalized zpos earlier or whatever. -Daniel
This patch simplifies initialization of generic rotation property and aligns the code to match recently introduced function for intializing generic zpos property. It also adds missing documentation.
Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 10 ++++------ drivers/gpu/drm/drm_crtc.c | 26 +++++++++++++++++++------ drivers/gpu/drm/i915/intel_display.c | 6 ++---- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 3 +-- drivers/gpu/drm/omapdrm/omap_drv.c | 3 +-- include/drm/drm_crtc.h | 4 ++-- 6 files changed, 30 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 1ffe9c329c46..4f9606cdf0f2 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -967,12 +967,10 @@ atmel_hlcdc_plane_create_properties(struct drm_device *dev) if (!props->alpha) return ERR_PTR(-ENOMEM);
- dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, - BIT(DRM_ROTATE_0) | - BIT(DRM_ROTATE_90) | - BIT(DRM_ROTATE_180) | - BIT(DRM_ROTATE_270)); + drm_mode_create_rotation_property(dev, BIT(DRM_ROTATE_0) | + BIT(DRM_ROTATE_90) | + BIT(DRM_ROTATE_180) | + BIT(DRM_ROTATE_270)); if (!dev->mode_config.rotation_property) return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e33866084b70..890c5925e6db 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -5861,10 +5861,20 @@ void drm_mode_config_cleanup(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_config_cleanup);
-struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, - unsigned int supported_rotations) +/** + * drm_mode_create_rotation_property - create generic rotation property + * @dev: DRM device + * @supported_rotations: bitmask of supported rotation modes + * + * This function initializes generic rotation property and enables support + * for it in drm core. Drivers can then attach this property to planes to enable + * support for different rotation modes. + */ +int drm_mode_create_rotation_property(struct drm_device *dev, + unsigned int supported_rotations) { - static const struct drm_prop_enum_list props[] = { + struct drm_property *prop; + static const struct drm_prop_enum_list values[] = { { DRM_ROTATE_0, "rotate-0" }, { DRM_ROTATE_90, "rotate-90" }, { DRM_ROTATE_180, "rotate-180" }, @@ -5873,9 +5883,13 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, { DRM_REFLECT_Y, "reflect-y" }, };
- return drm_property_create_bitmask(dev, 0, "rotation", - props, ARRAY_SIZE(props), - supported_rotations); + prop = drm_property_create_bitmask(dev, 0, "rotation", values, + ARRAY_SIZE(values), supported_rotations); + if (!prop) + return -ENOMEM; + + dev->mode_config.rotation_property = prop; + return 0; } EXPORT_SYMBOL(drm_mode_create_rotation_property);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 02f6ccb848a9..5b7ba46491a0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14042,8 +14042,7 @@ void intel_create_rotation_property(struct drm_device *dev, struct intel_plane * if (INTEL_INFO(dev)->gen >= 9) flags |= BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270);
- dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, flags); + drm_mode_create_rotation_property(dev, flags); } if (dev->mode_config.rotation_property) drm_object_attach_property(&plane->base.base, @@ -14179,8 +14178,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
if (INTEL_INFO(dev)->gen >= 4) { if (!dev->mode_config.rotation_property) - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, + drm_mode_create_rotation_property(dev, BIT(DRM_ROTATE_0) | BIT(DRM_ROTATE_180)); if (dev->mode_config.rotation_property) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 432c09836b0e..8defeec0d453 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -76,8 +76,7 @@ static void mdp5_plane_install_rotation_property(struct drm_device *dev, return;
if (!dev->mode_config.rotation_property) - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, + drm_mode_create_rotation_property(dev, BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y));
if (dev->mode_config.rotation_property) diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index dfafdb602ad2..c6ce2b31f1c5 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -304,8 +304,7 @@ static int omap_modeset_init_properties(struct drm_device *dev) struct omap_drm_private *priv = dev->dev_private;
if (priv->has_dmm) { - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, + drm_mode_create_rotation_property(dev, BIT(DRM_ROTATE_0) | BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_180) | BIT(DRM_ROTATE_270) | BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y)); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 13035e2c5e51..7fe38dc8244a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -2488,8 +2488,8 @@ extern int drm_format_plane_cpp(uint32_t format, int plane); extern int drm_format_horz_chroma_subsampling(uint32_t format); extern int drm_format_vert_chroma_subsampling(uint32_t format); extern const char *drm_get_format_name(uint32_t format); -extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, - unsigned int supported_rotations); +extern int drm_mode_create_rotation_property(struct drm_device *dev, + unsigned int supported_rotations); extern unsigned int drm_rotation_simplify(unsigned int rotation, unsigned int supported_rotations);
dri-devel@lists.freedesktop.org