From 6ba6d03e69125ef42a63e90d45e49c659ea3c34f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 10 Jun 2013 11:15:10 +0300 Subject: drm: Print pretty names for pixel formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than just printing the pixel format as a hex number, decode the fourcc into human readable form, and also decode the LE vs. BE flag. Keep printing the raw hex number too in case it contains non-printable characters. Some examples what the new drm_get_format_name() produces: DRM_FORMAT_XRGB8888: "XR24 little-endian (0x34325258)" DRM_FORMAT_YUYV: "YUYV little-endian (0x56595559)" DRM_FORMAT_RGB565|DRM_FORMAT_BIG_ENDIAN: "RG16 big-endian (0xb6314752)" Unprintable characters: "D??? big-endian (0xff7f0244)" v2: Fix patch author Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e7e92429d10f..079996ad02a7 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -29,6 +29,7 @@ * Dave Airlie * Jesse Barnes */ +#include #include #include #include @@ -252,6 +253,28 @@ char *drm_get_connector_status_name(enum drm_connector_status status) } EXPORT_SYMBOL(drm_get_connector_status_name); +static char printable_char(int c) +{ + return isascii(c) && isprint(c) ? c : '?'; +} + +char *drm_get_format_name(uint32_t format) +{ + static char buf[32]; + + snprintf(buf, sizeof(buf), + "%c%c%c%c %s-endian (0x%08x)", + printable_char(format & 0xff), + printable_char((format >> 8) & 0xff), + printable_char((format >> 16) & 0xff), + printable_char((format >> 24) & 0x7f), + format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little", + format); + + return buf; +} +EXPORT_SYMBOL(drm_get_format_name); + /** * drm_mode_object_get - allocate a new modeset identifier * @dev: DRM device @@ -1834,7 +1857,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data, if (fb->pixel_format == plane->format_types[i]) break; if (i == plane->format_count) { - DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format); + DRM_DEBUG_KMS("Invalid pixel format %s\n", + drm_get_format_name(fb->pixel_format)); ret = -EINVAL; goto out; } @@ -2312,7 +2336,8 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) ret = format_check(r); if (ret) { - DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format); + DRM_DEBUG_KMS("bad framebuffer format %s\n", + drm_get_format_name(r->pixel_format)); return ret; } -- cgit v1.2.3 From d20d3174806ef6589cb912a488657d21fcd7ece2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 7 Jun 2013 15:43:07 +0000 Subject: drm: Constify the pretty-print functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structures and strings involved with various pretty-print functions aren't meant to be modified, so make them all const. The exception is drm_connector_enum_list which does get modified in drm_connector_init(). While at it move the drm_get_connector_status_name() prototype from drmP.h to drm_crtc.h where it belongs. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 079996ad02a7..44c3421899bb 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -92,7 +92,7 @@ EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked); /* Avoid boilerplate. I'm tired of typing. */ #define DRM_ENUM_NAME_FN(fnname, list) \ - char *fnname(int val) \ + const char *fnname(int val) \ { \ int i; \ for (i = 0; i < ARRAY_SIZE(list); i++) { \ @@ -105,7 +105,7 @@ EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked); /* * Global properties */ -static struct drm_prop_enum_list drm_dpms_enum_list[] = +static const struct drm_prop_enum_list drm_dpms_enum_list[] = { { DRM_MODE_DPMS_ON, "On" }, { DRM_MODE_DPMS_STANDBY, "Standby" }, { DRM_MODE_DPMS_SUSPEND, "Suspend" }, @@ -117,7 +117,7 @@ DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) /* * Optional properties */ -static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = +static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { { DRM_MODE_SCALE_NONE, "None" }, { DRM_MODE_SCALE_FULLSCREEN, "Full" }, @@ -125,7 +125,7 @@ static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { DRM_MODE_SCALE_ASPECT, "Full aspect" }, }; -static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = +static const struct drm_prop_enum_list drm_dithering_mode_enum_list[] = { { DRM_MODE_DITHERING_OFF, "Off" }, { DRM_MODE_DITHERING_ON, "On" }, @@ -135,7 +135,7 @@ static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = /* * Non-global properties, but "required" for certain connectors. */ -static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = +static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ @@ -144,7 +144,7 @@ static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) -static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = +static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ @@ -154,7 +154,7 @@ static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, drm_dvi_i_subconnector_enum_list) -static struct drm_prop_enum_list drm_tv_select_enum_list[] = +static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ @@ -165,7 +165,7 @@ static struct drm_prop_enum_list drm_tv_select_enum_list[] = DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) -static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = +static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ @@ -177,7 +177,7 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, drm_tv_subconnector_enum_list) -static struct drm_prop_enum_list drm_dirty_info_enum_list[] = { +static const struct drm_prop_enum_list drm_dirty_info_enum_list[] = { { DRM_MODE_DIRTY_OFF, "Off" }, { DRM_MODE_DIRTY_ON, "On" }, { DRM_MODE_DIRTY_ANNOTATE, "Annotate" }, @@ -185,7 +185,7 @@ static struct drm_prop_enum_list drm_dirty_info_enum_list[] = { struct drm_conn_prop_enum_list { int type; - char *name; + const char *name; int count; }; @@ -211,7 +211,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0}, }; -static struct drm_prop_enum_list drm_encoder_enum_list[] = +static const struct drm_prop_enum_list drm_encoder_enum_list[] = { { DRM_MODE_ENCODER_NONE, "None" }, { DRM_MODE_ENCODER_DAC, "DAC" }, { DRM_MODE_ENCODER_TMDS, "TMDS" }, @@ -220,7 +220,7 @@ static struct drm_prop_enum_list drm_encoder_enum_list[] = { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, }; -char *drm_get_encoder_name(struct drm_encoder *encoder) +const char *drm_get_encoder_name(const struct drm_encoder *encoder) { static char buf[32]; @@ -231,7 +231,7 @@ char *drm_get_encoder_name(struct drm_encoder *encoder) } EXPORT_SYMBOL(drm_get_encoder_name); -char *drm_get_connector_name(struct drm_connector *connector) +const char *drm_get_connector_name(const struct drm_connector *connector) { static char buf[32]; @@ -242,7 +242,7 @@ char *drm_get_connector_name(struct drm_connector *connector) } EXPORT_SYMBOL(drm_get_connector_name); -char *drm_get_connector_status_name(enum drm_connector_status status) +const char *drm_get_connector_status_name(enum drm_connector_status status) { if (status == connector_status_connected) return "connected"; @@ -258,7 +258,7 @@ static char printable_char(int c) return isascii(c) && isprint(c) ? c : '?'; } -char *drm_get_format_name(uint32_t format) +const char *drm_get_format_name(uint32_t format) { static char buf[32]; -- cgit v1.2.3 From 990256aec2f10800595dddf4d1c3441fcd6b2616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 31 May 2013 12:17:07 +0000 Subject: drm: Add probed modes in probe order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keeping the modes in the same order as we probe them makes it a bit easier to track what's happening. Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 44c3421899bb..3385b5cb084f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -680,7 +680,7 @@ EXPORT_SYMBOL(drm_crtc_cleanup); void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode) { - list_add(&mode->head, &connector->probed_modes); + list_add_tail(&mode->head, &connector->probed_modes); } EXPORT_SYMBOL(drm_mode_probed_add); -- cgit v1.2.3 From ad6f5c343364e52a49b6a0a9153bda7f0e101416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 5 Jun 2013 12:39:55 +0000 Subject: drm: Improve drm_crtc documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3385b5cb084f..baee5752ca6b 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -616,7 +616,7 @@ EXPORT_SYMBOL(drm_framebuffer_remove); * @crtc: CRTC object to init * @funcs: callbacks for the new CRTC * - * Inits a new object created as base part of an driver crtc object. + * Inits a new object created as base part of a driver crtc object. * * RETURNS: * Zero on success, error code on failure. @@ -651,11 +651,12 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, EXPORT_SYMBOL(drm_crtc_init); /** - * drm_crtc_cleanup - Cleans up the core crtc usage. + * drm_crtc_cleanup - Clean up the core crtc usage * @crtc: CRTC to cleanup * - * Cleanup @crtc. Removes from drm modesetting space - * does NOT free object, caller does that. + * This function cleans up @crtc and removes it from the DRM mode setting + * core. Note that the function does *not* free the crtc structure itself, + * this is the responsibility of the caller. */ void drm_crtc_cleanup(struct drm_crtc *crtc) { -- cgit v1.2.3 From 9125e6186822b2698da17690416cd1b55c030115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 3 Jun 2013 16:10:40 +0300 Subject: drm: Add drm_plane_force_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_plane_force_disable() will forcibly disable the plane even if user had previously requested the plane to be enabled. This can be used to force planes to be off when restoring the fbdev mode. The code was simply pulled from drm_framebuffer_remove(), which now calls the new function as well. v2: Check plane->fb in drm_plane_force_disable(), drop bogus comment about disabling crtc Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index baee5752ca6b..c8042a1c83b8 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -592,16 +592,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) } list_for_each_entry(plane, &dev->mode_config.plane_list, head) { - if (plane->fb == fb) { - /* should turn off the crtc */ - ret = plane->funcs->disable_plane(plane); - if (ret) - DRM_ERROR("failed to disable plane with busy fb\n"); - /* disconnect the plane from the fb and crtc: */ - __drm_framebuffer_unreference(plane->fb); - plane->fb = NULL; - plane->crtc = NULL; - } + if (plane->fb == fb) + drm_plane_force_disable(plane); } drm_modeset_unlock_all(dev); } @@ -891,6 +883,23 @@ void drm_plane_cleanup(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_cleanup); +void drm_plane_force_disable(struct drm_plane *plane) +{ + int ret; + + if (!plane->fb) + return; + + ret = plane->funcs->disable_plane(plane); + if (ret) + DRM_ERROR("failed to disable plane with busy fb\n"); + /* disconnect the plane from the fb and crtc: */ + __drm_framebuffer_unreference(plane->fb); + plane->fb = NULL; + plane->crtc = NULL; +} +EXPORT_SYMBOL(drm_plane_force_disable); + /** * drm_mode_create - create a new display mode * @dev: DRM device -- cgit v1.2.3 From 35f2c3ae764ec8d458d6b9c78826d23c112abc7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 5 Jun 2013 15:39:56 +0300 Subject: drm: Add kernel-doc for plane functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: Follow the drm_crtc documentation fixes Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c8042a1c83b8..755d9bb0b4e2 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -819,6 +819,21 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) } EXPORT_SYMBOL(drm_encoder_cleanup); +/** + * drm_plane_init - Initialise a new plane object + * @dev: DRM device + * @plane: plane object to init + * @possible_crtcs: bitmask of possible CRTCs + * @funcs: callbacks for the new plane + * @formats: array of supported formats (%DRM_FORMAT_*) + * @format_count: number of elements in @formats + * @priv: plane is private (hidden from userspace)? + * + * Inits a new object created as base part of a driver plane object. + * + * RETURNS: + * Zero on success, error code on failure. + */ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, @@ -867,6 +882,14 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, } EXPORT_SYMBOL(drm_plane_init); +/** + * drm_plane_cleanup - Clean up the core plane usage + * @plane: plane to cleanup + * + * This function cleans up @plane and removes it from the DRM mode setting + * core. Note that the function does *not* free the plane structure itself, + * this is the responsibility of the caller. + */ void drm_plane_cleanup(struct drm_plane *plane) { struct drm_device *dev = plane->dev; @@ -883,6 +906,15 @@ void drm_plane_cleanup(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_cleanup); +/** + * drm_plane_force_disable - Forcibly disable a plane + * @plane: plane to disable + * + * Forces the plane to be disabled. + * + * Used when the plane's current framebuffer is destroyed, + * and when restoring fbdev mode. + */ void drm_plane_force_disable(struct drm_plane *plane) { int ret; -- cgit v1.2.3 From 778ad903f951a45a309a5a70dbdcf38eccabeaf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 3 Jun 2013 16:11:42 +0300 Subject: drm: Remove some unused stuff from drm_plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a bunch of unused members inside drm_plane, bloating the size of the structure needlessly. Eliminate them. v2: Remove all of it from kernel-doc too Reviewed-by: Laurent Pinchart Reviewed-by: Daniel Vetter Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 755d9bb0b4e2..c9f9f3ded9e1 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1805,7 +1805,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data, plane_resp->plane_id = plane->base.id; plane_resp->possible_crtcs = plane->possible_crtcs; - plane_resp->gamma_size = plane->gamma_size; + plane_resp->gamma_size = 0; /* * This ioctl is called twice, once to determine how much space is -- cgit v1.2.3 From cc85e1217f598f342b69dc44710d7a7355513a1b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 15 Jun 2013 00:13:15 +0200 Subject: drm: check that ->set_config properly updates the fb Historically drm lacked fb refcounting, so the updating of crtc->fb was done by the lower levels at a point convenient to get their own refcounting (e.g. refcounts for the underlying gem bo, pinning refcounts) right. With the introduction of refcounted fbs the drm core handled the fb refcounts, but still relied on drivers to update the crtc->fb pointer (this approach required the least invasive changes in drivers). Enforce this contract with a WARN_ON. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c9f9f3ded9e1..a7dc1e266c98 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1980,6 +1980,9 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) ret = crtc->funcs->set_config(set); if (ret == 0) { + /* crtc->fb must be updated by ->set_config, enforces this. */ + WARN_ON(fb != crtc->fb); + if (old_fb) drm_framebuffer_unreference(old_fb); if (fb) -- cgit v1.2.3 From 5cef29aa5227e6347145940a7bccde92fd9a1afa Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 15 Jun 2013 00:13:16 +0200 Subject: drm: fix fb leak in setcrtc Drivers are allowed (actually have to) disable unrelated crtcs in their ->set_config callback (when we steal all the connectors from that crtc). If they do that they'll clear crtc->fb to NULL. Which results in a refcount leak, since the drm core is keeping track of that reference. To fix this track the old fb of all crtcs and adjust references for all of them. Of course, since we only hold an additional reference for the fb for the current crtc we need to increase refcounts before we drop the old one. This approach has the benefit that it inches us a bit closer to an atomic modeset world, where we want to update the config of all crtcs in one step. This regression has been introduce in the framebuffer refcount conversion, specifically in commit b0d1232589df5575c5971224ac4cb30e7e525884 Author: Daniel Vetter Date: Tue Dec 11 01:07:12 2012 +0100 drm: refcounting for crtc framebuffers Reported-by: Russell King Cc: Russell King Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index a7dc1e266c98..02838e66af76 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1972,21 +1972,31 @@ out: int drm_mode_set_config_internal(struct drm_mode_set *set) { struct drm_crtc *crtc = set->crtc; - struct drm_framebuffer *fb, *old_fb; + struct drm_framebuffer *fb; + struct drm_crtc *tmp; int ret; - old_fb = crtc->fb; + /* + * NOTE: ->set_config can also disable other crtcs (if we steal all + * connectors from it), hence we need to refcount the fbs across all + * crtcs. Atomic modeset will have saner semantics ... + */ + list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) + tmp->old_fb = tmp->fb; + fb = set->fb; ret = crtc->funcs->set_config(set); if (ret == 0) { /* crtc->fb must be updated by ->set_config, enforces this. */ WARN_ON(fb != crtc->fb); + } - if (old_fb) - drm_framebuffer_unreference(old_fb); - if (fb) - drm_framebuffer_reference(fb); + list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { + if (tmp->fb) + drm_framebuffer_reference(tmp->fb); + if (tmp->old_fb) + drm_framebuffer_unreference(tmp->old_fb); } return ret; -- cgit v1.2.3 From 4c813d4d759c0e6b83bfd73795e9526493556dc2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 20 Jun 2013 11:48:52 +1000 Subject: drm: add hotspot support for cursors. So it looks like for virtual hw cursors on QXL we need to inform the "hw" device what the cursor hotspot parameters are. This makes sense if you think the host has to draw the cursor and interpret clicks from it. However the current modesetting interface doesn't support passing the hotspot information from userspace. This implements a new cursor ioctl, that takes the hotspot info as well, userspace can try calling the new interface and if it gets -ENOSYS it means its on an older kernel and can just fallback. Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 02838e66af76..fc83bb9eb514 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2178,10 +2178,10 @@ out: return ret; } -int drm_mode_cursor_ioctl(struct drm_device *dev, - void *data, struct drm_file *file_priv) +static int drm_mode_cursor_common(struct drm_device *dev, + struct drm_mode_cursor2 *req, + struct drm_file *file_priv) { - struct drm_mode_cursor *req = data; struct drm_mode_object *obj; struct drm_crtc *crtc; int ret = 0; @@ -2201,13 +2201,17 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, mutex_lock(&crtc->mutex); if (req->flags & DRM_MODE_CURSOR_BO) { - if (!crtc->funcs->cursor_set) { + if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { ret = -ENXIO; goto out; } /* Turns off the cursor if handle is 0 */ - ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, - req->width, req->height); + if (crtc->funcs->cursor_set2) + ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle, + req->width, req->height, req->hot_x, req->hot_y); + else + ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, + req->width, req->height); } if (req->flags & DRM_MODE_CURSOR_MOVE) { @@ -2222,6 +2226,25 @@ out: mutex_unlock(&crtc->mutex); return ret; + +} +int drm_mode_cursor_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_cursor *req = data; + struct drm_mode_cursor2 new_req; + + memcpy(&new_req, req, sizeof(struct drm_mode_cursor)); + new_req.hot_x = new_req.hot_y = 0; + + return drm_mode_cursor_common(dev, &new_req, file_priv); +} + +int drm_mode_cursor2_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_cursor2 *req = data; + return drm_mode_cursor_common(dev, req, file_priv); } /* Original addfb only supported RGB formats, so figure out which one */ -- cgit v1.2.3