From 8cf5c9177151537e73ff1816540e4ba24b174391 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 14 Nov 2011 14:51:27 -0800 Subject: drm: add plane support v3 Planes are a bit like half-CRTCs. They have a location and fb, but don't drive outputs directly. Add support for handling them to the core KMS code. v2: fix ABI of get_plane - move format_type_ptr to the end v3: add 'flags' field for interlaced support (from Ville) Acked-by: Alan Cox Reviewed-by: Rob Clark Reviewed-by: Daniel Vetter Signed-off-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 257 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 255 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 9a2e2a14b3bb..5e1df76c8f72 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -324,6 +324,7 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) { struct drm_device *dev = fb->dev; struct drm_crtc *crtc; + struct drm_plane *plane; struct drm_mode_set set; int ret; @@ -340,6 +341,15 @@ void drm_framebuffer_cleanup(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"); + } + } + drm_mode_object_put(dev, &fb->base); list_del(&fb->head); dev->mode_config.num_fb--; @@ -540,6 +550,50 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) } EXPORT_SYMBOL(drm_encoder_cleanup); +int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, + unsigned long possible_crtcs, + const struct drm_plane_funcs *funcs, + uint32_t *formats, uint32_t format_count) +{ + mutex_lock(&dev->mode_config.mutex); + + plane->dev = dev; + drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); + plane->funcs = funcs; + plane->format_types = kmalloc(sizeof(uint32_t) * format_count, + GFP_KERNEL); + if (!plane->format_types) { + DRM_DEBUG_KMS("out of memory when allocating plane\n"); + drm_mode_object_put(dev, &plane->base); + return -ENOMEM; + } + + memcpy(plane->format_types, formats, format_count); + plane->format_count = format_count; + plane->possible_crtcs = possible_crtcs; + + list_add_tail(&plane->head, &dev->mode_config.plane_list); + dev->mode_config.num_plane++; + + mutex_unlock(&dev->mode_config.mutex); + + return 0; +} +EXPORT_SYMBOL(drm_plane_init); + +void drm_plane_cleanup(struct drm_plane *plane) +{ + struct drm_device *dev = plane->dev; + + mutex_lock(&dev->mode_config.mutex); + kfree(plane->format_types); + drm_mode_object_put(dev, &plane->base); + list_del(&plane->head); + dev->mode_config.num_plane--; + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(drm_plane_cleanup); + /** * drm_mode_create - create a new display mode * @dev: DRM device @@ -871,6 +925,7 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.encoder_list); INIT_LIST_HEAD(&dev->mode_config.property_list); INIT_LIST_HEAD(&dev->mode_config.property_blob_list); + INIT_LIST_HEAD(&dev->mode_config.plane_list); idr_init(&dev->mode_config.crtc_idr); mutex_lock(&dev->mode_config.mutex); @@ -947,6 +1002,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) struct drm_encoder *encoder, *enct; struct drm_framebuffer *fb, *fbt; struct drm_property *property, *pt; + struct drm_plane *plane, *plt; list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, head) { @@ -971,6 +1027,10 @@ void drm_mode_config_cleanup(struct drm_device *dev) crtc->funcs->destroy(crtc); } + list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, + head) { + plane->funcs->destroy(plane); + } } EXPORT_SYMBOL(drm_mode_config_cleanup); @@ -1470,6 +1530,197 @@ out: return ret; } +/** + * drm_mode_getplane_res - get plane info + * @dev: DRM device + * @data: ioctl data + * @file_priv: DRM file info + * + * Return an plane count and set of IDs. + */ +int drm_mode_getplane_res(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_get_plane_res *plane_resp = data; + struct drm_mode_config *config; + struct drm_plane *plane; + uint32_t __user *plane_ptr; + int copied = 0, ret = 0; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + mutex_lock(&dev->mode_config.mutex); + config = &dev->mode_config; + + /* + * This ioctl is called twice, once to determine how much space is + * needed, and the 2nd time to fill it. + */ + if (config->num_plane && + (plane_resp->count_planes >= config->num_plane)) { + plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr; + + list_for_each_entry(plane, &config->plane_list, head) { + if (put_user(plane->base.id, plane_ptr + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + plane_resp->count_planes = config->num_plane; + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_mode_getplane - get plane info + * @dev: DRM device + * @data: ioctl data + * @file_priv: DRM file info + * + * Return plane info, including formats supported, gamma size, any + * current fb, etc. + */ +int drm_mode_getplane(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_get_plane *plane_resp = data; + struct drm_mode_object *obj; + struct drm_plane *plane; + uint32_t __user *format_ptr; + int ret = 0; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, plane_resp->plane_id, + DRM_MODE_OBJECT_PLANE); + if (!obj) { + ret = -ENOENT; + goto out; + } + plane = obj_to_plane(obj); + + if (plane->crtc) + plane_resp->crtc_id = plane->crtc->base.id; + else + plane_resp->crtc_id = 0; + + if (plane->fb) + plane_resp->fb_id = plane->fb->base.id; + else + plane_resp->fb_id = 0; + + plane_resp->plane_id = plane->base.id; + plane_resp->possible_crtcs = plane->possible_crtcs; + plane_resp->gamma_size = plane->gamma_size; + + /* + * This ioctl is called twice, once to determine how much space is + * needed, and the 2nd time to fill it. + */ + if (plane->format_count && + (plane_resp->count_format_types >= plane->format_count)) { + format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr; + if (copy_to_user(format_ptr, + plane->format_types, + sizeof(uint32_t) * plane->format_count)) { + ret = -EFAULT; + goto out; + } + } + plane_resp->count_format_types = plane->format_count; + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_mode_setplane - set up or tear down an plane + * @dev: DRM device + * @data: ioctl data* + * @file_prive: DRM file info + * + * Set plane info, including placement, fb, scaling, and other factors. + * Or pass a NULL fb to disable. + */ +int drm_mode_setplane(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_set_plane *plane_req = data; + struct drm_mode_object *obj; + struct drm_plane *plane; + struct drm_crtc *crtc; + struct drm_framebuffer *fb; + int ret = 0; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + mutex_lock(&dev->mode_config.mutex); + + /* + * First, find the plane, crtc, and fb objects. If not available, + * we don't bother to call the driver. + */ + obj = drm_mode_object_find(dev, plane_req->plane_id, + DRM_MODE_OBJECT_PLANE); + if (!obj) { + DRM_DEBUG_KMS("Unknown plane ID %d\n", + plane_req->plane_id); + ret = -ENOENT; + goto out; + } + plane = obj_to_plane(obj); + + /* No fb means shut it down */ + if (!plane_req->fb_id) { + plane->funcs->disable_plane(plane); + goto out; + } + + obj = drm_mode_object_find(dev, plane_req->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!obj) { + DRM_DEBUG_KMS("Unknown crtc ID %d\n", + plane_req->crtc_id); + ret = -ENOENT; + goto out; + } + crtc = obj_to_crtc(obj); + + obj = drm_mode_object_find(dev, plane_req->fb_id, + DRM_MODE_OBJECT_FB); + if (!obj) { + DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", + plane_req->fb_id); + ret = -ENOENT; + goto out; + } + fb = obj_to_fb(obj); + + ret = plane->funcs->update_plane(plane, crtc, fb, + plane_req->crtc_x, plane_req->crtc_y, + plane_req->crtc_w, plane_req->crtc_h, + plane_req->src_x, plane_req->src_y, + plane_req->src_w, plane_req->src_h); + if (!ret) { + plane->crtc = crtc; + plane->fb = fb; + } + +out: + mutex_unlock(&dev->mode_config.mutex); + + return ret; +} + /** * drm_mode_setcrtc - set CRTC configuration * @inode: inode from the ioctl @@ -1693,11 +1944,13 @@ int drm_mode_addfb(struct drm_device *dev, return -EINVAL; if ((config->min_width > r->width) || (r->width > config->max_width)) { - DRM_ERROR("mode new framebuffer width not within limits\n"); + DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n", + r->width, config->min_width, config->max_width); return -EINVAL; } if ((config->min_height > r->height) || (r->height > config->max_height)) { - DRM_ERROR("mode new framebuffer height not within limits\n"); + DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n", + r->height, config->min_height, config->max_height); return -EINVAL; } -- cgit v1.2.3 From 308e5bcbdb10452e8aba31aa21432fb67ee46d72 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 14 Nov 2011 14:51:28 -0800 Subject: drm: add an fb creation ioctl that takes a pixel format v5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To properly support the various plane formats supported by different hardware, the kernel must know the pixel format of a framebuffer object. So add a new ioctl taking a format argument corresponding to a fourcc name from the new drm_fourcc.h header file. Implement the fb creation hooks in terms of the new mode_fb_cmd2 using helpers where the old bpp/depth values are needed. v2: create DRM specific fourcc header file for sharing with libdrm etc v3: fix rebase failure and use DRM fourcc codes in intel_display.c and update commit message v4: make fb_cmd2 handle field into an array for multi-object formats pull in Ville's fix for the memcpy in drm_plane_init apply Ville's cleanup to zero out fb_cmd2 arg in drm_mode_addfb v5: add 'flags' field for interlaced support (from Ville) Signed-off-by: Ville Syrjälä Acked-by: Alan Cox Reviewed-by: Rob Clark Signed-off-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 111 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 5 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 5e1df76c8f72..e54c0a6a3072 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -36,6 +36,7 @@ #include "drmP.h" #include "drm_crtc.h" #include "drm_edid.h" +#include "drm_fourcc.h" struct drm_prop_enum_list { int type; @@ -568,7 +569,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, return -ENOMEM; } - memcpy(plane->format_types, formats, format_count); + memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); plane->format_count = format_count; plane->possible_crtcs = possible_crtcs; @@ -1915,6 +1916,42 @@ out: return ret; } +/* Original addfb only supported RGB formats, so figure out which one */ +uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) +{ + uint32_t fmt; + + switch (bpp) { + case 8: + fmt = DRM_FOURCC_RGB332; + break; + case 16: + if (depth == 15) + fmt = DRM_FOURCC_RGB555; + else + fmt = DRM_FOURCC_RGB565; + break; + case 24: + fmt = DRM_FOURCC_RGB24; + break; + case 32: + if (depth == 24) + fmt = DRM_FOURCC_RGB24; + else if (depth == 30) + fmt = DRM_INTEL_RGB30; + else + fmt = DRM_FOURCC_RGB32; + break; + default: + DRM_ERROR("bad bpp, assuming RGB24 pixel format\n"); + fmt = DRM_FOURCC_RGB24; + break; + } + + return fmt; +} +EXPORT_SYMBOL(drm_mode_legacy_fb_format); + /** * drm_mode_addfb - add an FB to the graphics configuration * @inode: inode from the ioctl @@ -1935,7 +1972,74 @@ out: int drm_mode_addfb(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_fb_cmd *r = data; + struct drm_mode_fb_cmd *or = data; + struct drm_mode_fb_cmd2 r = {}; + struct drm_mode_config *config = &dev->mode_config; + struct drm_framebuffer *fb; + int ret = 0; + + /* Use new struct with format internally */ + r.fb_id = or->fb_id; + r.width = or->width; + r.height = or->height; + r.pitches[0] = or->pitch; + r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); + r.handles[0] = or->handle; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + if ((config->min_width > r.width) || (r.width > config->max_width)) { + DRM_ERROR("mode new framebuffer width not within limits\n"); + return -EINVAL; + } + if ((config->min_height > r.height) || (r.height > config->max_height)) { + DRM_ERROR("mode new framebuffer height not within limits\n"); + return -EINVAL; + } + + mutex_lock(&dev->mode_config.mutex); + + /* TODO check buffer is sufficiently large */ + /* TODO setup destructor callback */ + + fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); + if (IS_ERR(fb)) { + DRM_ERROR("could not create framebuffer\n"); + ret = PTR_ERR(fb); + goto out; + } + + or->fb_id = fb->base.id; + list_add(&fb->filp_head, &file_priv->fbs); + DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +/** + * drm_mode_addfb2 - add an FB to the graphics configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Takes mode config lock. + * + * Add a new FB to the specified CRTC, given a user request with format. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_addfb2(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_fb_cmd2 *r = data; struct drm_mode_config *config = &dev->mode_config; struct drm_framebuffer *fb; int ret = 0; @@ -1956,9 +2060,6 @@ int drm_mode_addfb(struct drm_device *dev, mutex_lock(&dev->mode_config.mutex); - /* TODO check buffer is sufficiently large */ - /* TODO setup destructor callback */ - fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); if (IS_ERR(fb)) { DRM_ERROR("could not create framebuffer\n"); -- cgit v1.2.3 From 248dbc2350501e2c7b9f5ceb60c75515d82f4134 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 29 Nov 2011 20:02:54 +0000 Subject: drm: move the fb bpp/depth helper into the core. This is used by nearly everyone including vmwgfx which doesn't generally use the fb helper. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 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 e54c0a6a3072..07c80fd7a98d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3136,3 +3136,44 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, return dev->driver->dumb_destroy(file_priv, dev, args->handle); } + +/* + * Just need to support RGB formats here for compat with code that doesn't + * use pixel formats directly yet. + */ +void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, + int *bpp) +{ + switch (format) { + case DRM_FOURCC_RGB332: + *depth = 8; + *bpp = 8; + break; + case DRM_FOURCC_RGB555: + *depth = 15; + *bpp = 16; + break; + case DRM_FOURCC_RGB565: + *depth = 16; + *bpp = 16; + break; + case DRM_FOURCC_RGB24: + *depth = 24; + *bpp = 32; + break; + case DRM_INTEL_RGB30: + *depth = 30; + *bpp = 32; + break; + case DRM_FOURCC_RGB32: + *depth = 32; + *bpp = 32; + break; + default: + DRM_DEBUG_KMS("unsupported pixel format\n"); + *depth = 0; + *bpp = 0; + break; + } +} +EXPORT_SYMBOL(drm_fb_get_bpp_depth); -- cgit v1.2.3 From 04b3924db60f974d2b4af0b2e19a0ae7ca202dc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 17 Nov 2011 18:05:13 +0200 Subject: drm: Redefine pixel formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Name the formats as DRM_FORMAT_X instead of DRM_FOURCC_X. Use consistent names, especially for the RGB formats. Component order and byte order are now strictly specified for each format. The RGB format naming follows a convention where the components names and sizes are listed from left to right, matching the order within a single pixel from most significant bit to least significant bit. The YUV format names vary more. For the 4:2:2 packed formats and 2 plane formats use the fourcc. For the three plane formats the name includes the plane order and subsampling information using the standard subsampling notation. Some of those also happen to match the official fourcc definition. The fourccs for for all the RGB formats and some of the YUV formats I invented myself. The idea was that looking at just the fourcc you get some idea what the format is about without having to decode it using some external reference. Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 57 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 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 07c80fd7a98d..1dfc28600751 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1923,28 +1923,28 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) switch (bpp) { case 8: - fmt = DRM_FOURCC_RGB332; + fmt = DRM_FORMAT_RGB332; break; case 16: if (depth == 15) - fmt = DRM_FOURCC_RGB555; + fmt = DRM_FORMAT_XRGB1555; else - fmt = DRM_FOURCC_RGB565; + fmt = DRM_FORMAT_RGB565; break; case 24: - fmt = DRM_FOURCC_RGB24; + fmt = DRM_FORMAT_RGB888; break; case 32: if (depth == 24) - fmt = DRM_FOURCC_RGB24; + fmt = DRM_FORMAT_XRGB8888; else if (depth == 30) - fmt = DRM_INTEL_RGB30; + fmt = DRM_FORMAT_XRGB2101010; else - fmt = DRM_FOURCC_RGB32; + fmt = DRM_FORMAT_ARGB8888; break; default: - DRM_ERROR("bad bpp, assuming RGB24 pixel format\n"); - fmt = DRM_FOURCC_RGB24; + DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n"); + fmt = DRM_FORMAT_XRGB8888; break; } @@ -3145,27 +3145,54 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp) { switch (format) { - case DRM_FOURCC_RGB332: + case DRM_FORMAT_RGB332: + case DRM_FORMAT_BGR233: *depth = 8; *bpp = 8; break; - case DRM_FOURCC_RGB555: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRX5551: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_BGRA5551: *depth = 15; *bpp = 16; break; - case DRM_FOURCC_RGB565: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: *depth = 16; *bpp = 16; break; - case DRM_FOURCC_RGB24: + case DRM_FORMAT_RGB888: + case DRM_FORMAT_BGR888: + *depth = 24; + *bpp = 24; + break; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: *depth = 24; *bpp = 32; break; - case DRM_INTEL_RGB30: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRX1010102: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_BGRA1010102: *depth = 30; *bpp = 32; break; - case DRM_FOURCC_RGB32: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: *depth = 32; *bpp = 32; break; -- cgit v1.2.3 From acb4b992d8a13728044f430b47b9199aa45993e9 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 7 Nov 2011 12:03:23 -0800 Subject: drm: remove some potentially dangerous DRM_ERRORs Each of these error messages can be caused by a broken or malicious userspace wanting to spam the dmesg with useless info. They're really not worthy of DRM_DEBUG statements either; those are generally only useful during bringup of new hardware or versions, and ought to be removed before going upstream anyway. Signed-off-by: Jesse Barnes Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 19 ++++--------------- 1 file changed, 4 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 1dfc28600751..255658906fcf 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1877,10 +1877,8 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - if (!req->flags) { - DRM_ERROR("no operation set\n"); + if (!req->flags) return -EINVAL; - } mutex_lock(&dev->mode_config.mutex); obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); @@ -1893,7 +1891,6 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (req->flags & DRM_MODE_CURSOR_BO) { if (!crtc->funcs->cursor_set) { - DRM_ERROR("crtc does not support cursor\n"); ret = -ENXIO; goto out; } @@ -1906,7 +1903,6 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (crtc->funcs->cursor_move) { ret = crtc->funcs->cursor_move(crtc, req->x, req->y); } else { - DRM_ERROR("crtc does not support cursor\n"); ret = -EFAULT; goto out; } @@ -1989,14 +1985,11 @@ int drm_mode_addfb(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - if ((config->min_width > r.width) || (r.width > config->max_width)) { - DRM_ERROR("mode new framebuffer width not within limits\n"); + if ((config->min_width > r.width) || (r.width > config->max_width)) return -EINVAL; - } - if ((config->min_height > r.height) || (r.height > config->max_height)) { - DRM_ERROR("mode new framebuffer height not within limits\n"); + + if ((config->min_height > r.height) || (r.height > config->max_height)) return -EINVAL; - } mutex_lock(&dev->mode_config.mutex); @@ -2110,7 +2103,6 @@ int drm_mode_rmfb(struct drm_device *dev, obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); /* TODO check that we really get a framebuffer back. */ if (!obj) { - DRM_ERROR("mode invalid framebuffer id\n"); ret = -EINVAL; goto out; } @@ -2121,7 +2113,6 @@ int drm_mode_rmfb(struct drm_device *dev, found = 1; if (!found) { - DRM_ERROR("tried to remove a fb that we didn't own\n"); ret = -EINVAL; goto out; } @@ -2168,7 +2159,6 @@ int drm_mode_getfb(struct drm_device *dev, mutex_lock(&dev->mode_config.mutex); obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); if (!obj) { - DRM_ERROR("invalid framebuffer id\n"); ret = -EINVAL; goto out; } @@ -2204,7 +2194,6 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, mutex_lock(&dev->mode_config.mutex); obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); if (!obj) { - DRM_ERROR("invalid framebuffer id\n"); ret = -EINVAL; goto out_err1; } -- cgit v1.2.3 From 10bf573bc10f50f316764418c704309b02cd1246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 20 Dec 2011 00:06:41 +0200 Subject: drm: plane: mutex_unlock() was missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlock the mode_config mutex if drm_plane_init() fails. Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 1 + 1 file changed, 1 insertion(+) (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 255658906fcf..7cb02f63b8e3 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -566,6 +566,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, if (!plane->format_types) { DRM_DEBUG_KMS("out of memory when allocating plane\n"); drm_mode_object_put(dev, &plane->base); + mutex_unlock(&dev->mode_config.mutex); return -ENOMEM; } -- cgit v1.2.3 From 81f6c7f873a69346762c9cd6347b908ba7035532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 20 Dec 2011 00:06:42 +0200 Subject: drm: Fix __user sparse warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several pointers and casts were missing __user annotations. Signed-off-by: Ville Syrjälä 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 7cb02f63b8e3..e05d99791544 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1441,7 +1441,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, */ if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; - mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr; + mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; list_for_each_entry(mode, &connector->modes, head) { drm_crtc_convert_to_umode(&u_mode, mode); if (copy_to_user(mode_ptr + copied, @@ -1456,8 +1456,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, if ((out_resp->count_props >= props_count) && props_count) { copied = 0; - prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr); - prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr); + prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr); + prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { if (connector->property_ids[i] != 0) { if (put_user(connector->property_ids[i], @@ -1479,7 +1479,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, if ((out_resp->count_encoders >= encoders_count) && encoders_count) { copied = 0; - encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr); + encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr); for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { if (connector->encoder_ids[i] != 0) { if (put_user(connector->encoder_ids[i], @@ -1561,7 +1561,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, */ if (config->num_plane && (plane_resp->count_planes >= config->num_plane)) { - plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr; + plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; list_for_each_entry(plane, &config->plane_list, head) { if (put_user(plane->base.id, plane_ptr + copied)) { @@ -1628,7 +1628,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data, */ if (plane->format_count && (plane_resp->count_format_types >= plane->format_count)) { - format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr; + format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr; if (copy_to_user(format_ptr, plane->format_types, sizeof(uint32_t) * plane->format_count)) { @@ -1829,7 +1829,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, } for (i = 0; i < crtc_req->count_connectors; i++) { - set_connectors_ptr = (uint32_t *)(unsigned long)crtc_req->set_connectors_ptr; + set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr; if (get_user(out_id, &set_connectors_ptr[i])) { ret = -EFAULT; goto out; @@ -2201,7 +2201,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, fb = obj_to_fb(obj); num_clips = r->num_clips; - clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr; + clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; if (!num_clips != !clips_ptr) { ret = -EINVAL; @@ -2591,7 +2591,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, struct drm_property_enum *prop_enum; struct drm_mode_property_enum __user *enum_ptr; struct drm_property_blob *prop_blob; - uint32_t *blob_id_ptr; + uint32_t __user *blob_id_ptr; uint64_t __user *values_ptr; uint32_t __user *blob_length_ptr; @@ -2621,7 +2621,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, out_resp->flags = property->flags; if ((out_resp->count_values >= value_count) && value_count) { - values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr; + values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr; for (i = 0; i < value_count; i++) { if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) { ret = -EFAULT; @@ -2634,7 +2634,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, if (property->flags & DRM_MODE_PROP_ENUM) { if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { copied = 0; - enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr; + enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; list_for_each_entry(prop_enum, &property->enum_blob_list, head) { if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { @@ -2656,8 +2656,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, if (property->flags & DRM_MODE_PROP_BLOB) { if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { copied = 0; - blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr; - blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr; + blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr; + blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr; list_for_each_entry(prop_blob, &property->enum_blob_list, head) { if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { @@ -2718,7 +2718,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, struct drm_mode_get_blob *out_resp = data; struct drm_property_blob *blob; int ret = 0; - void *blob_ptr; + void __user *blob_ptr; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; @@ -2732,7 +2732,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, blob = obj_to_blob(obj); if (out_resp->length == blob->length) { - blob_ptr = (void *)(unsigned long)out_resp->data; + blob_ptr = (void __user *)(unsigned long)out_resp->data; if (copy_to_user(blob_ptr, blob->data, blob->length)){ ret = -EFAULT; goto done; -- cgit v1.2.3 From e5e3b44c676be2dac97efd94e581e14a073e4ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 20 Dec 2011 00:06:43 +0200 Subject: drm: plane: Clear plane.crtc and plane.fb after disable_plane() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are the only indication to user space that the plane was disabled. Signed-off-by: Ville Syrjälä Acked-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 2 ++ 1 file changed, 2 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 e05d99791544..d9bf9d88ff43 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1684,6 +1684,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data, /* No fb means shut it down */ if (!plane_req->fb_id) { plane->funcs->disable_plane(plane); + plane->crtc = NULL; + plane->fb = NULL; goto out; } -- cgit v1.2.3 From 42ef87896adeb3116835a1e88abab84dafc1912d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 20 Dec 2011 00:06:44 +0200 Subject: drm: plane: Check source coordinates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure the source coordinates stay within the buffer. Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 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 d9bf9d88ff43..1242e121e4ad 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1661,6 +1661,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, struct drm_crtc *crtc; struct drm_framebuffer *fb; int ret = 0; + unsigned int fb_width, fb_height; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; @@ -1709,6 +1710,28 @@ int drm_mode_setplane(struct drm_device *dev, void *data, } fb = obj_to_fb(obj); + fb_width = fb->width << 16; + fb_height = fb->height << 16; + + /* Make sure source coordinates are inside the fb. */ + if (plane_req->src_w > fb_width || + plane_req->src_x > fb_width - plane_req->src_w || + plane_req->src_h > fb_height || + plane_req->src_y > fb_height - plane_req->src_h) { + DRM_DEBUG_KMS("Invalid source coordinates " + "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", + plane_req->src_w >> 16, + ((plane_req->src_w & 0xffff) * 15625) >> 10, + plane_req->src_h >> 16, + ((plane_req->src_h & 0xffff) * 15625) >> 10, + plane_req->src_x >> 16, + ((plane_req->src_x & 0xffff) * 15625) >> 10, + plane_req->src_y >> 16, + ((plane_req->src_y & 0xffff) * 15625) >> 10); + ret = -ENOSPC; + goto out; + } + ret = plane->funcs->update_plane(plane, crtc, fb, plane_req->crtc_x, plane_req->crtc_y, plane_req->crtc_w, plane_req->crtc_h, -- cgit v1.2.3 From 687a040038fb92c764adbb349ca132226677b417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 20 Dec 2011 00:06:45 +0200 Subject: drm: plane: Check crtc coordinates against integer overflows in setplane ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Help drivers a little by guaranteeing that crtc_x+crtc_w and crtc_y+crtc_h don't overflow. Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 12 ++++++++++++ 1 file changed, 12 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 1242e121e4ad..b98e49112081 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1732,6 +1732,18 @@ int drm_mode_setplane(struct drm_device *dev, void *data, goto out; } + /* Give drivers some help against integer overflows */ + if (plane_req->crtc_w > INT_MAX || + plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || + plane_req->crtc_h > INT_MAX || + plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { + DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", + plane_req->crtc_w, plane_req->crtc_h, + plane_req->crtc_x, plane_req->crtc_y); + ret = -ERANGE; + goto out; + } + ret = plane->funcs->update_plane(plane, crtc, fb, plane_req->crtc_x, plane_req->crtc_y, plane_req->crtc_w, plane_req->crtc_h, -- cgit v1.2.3 From 22cd7c625837e520c94ffda7bc926396bbc4ba67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 20 Dec 2011 00:06:46 +0200 Subject: drm: plane: Make 'formats' parameter to drm_plane_init() const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 b98e49112081..80cfe1cbeb99 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -554,7 +554,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup); int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, - uint32_t *formats, uint32_t format_count) + const uint32_t *formats, uint32_t format_count) { mutex_lock(&dev->mode_config.mutex); -- cgit v1.2.3 From 62443be626a3a753e6c650abd87e8a39fd569d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 20 Dec 2011 00:06:47 +0200 Subject: drm: plane: Check that the fb pixel format is supported by the plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 11 +++++++++++ 1 file changed, 11 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 80cfe1cbeb99..66a165dac5c4 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1662,6 +1662,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, struct drm_framebuffer *fb; int ret = 0; unsigned int fb_width, fb_height; + int i; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; @@ -1710,6 +1711,16 @@ int drm_mode_setplane(struct drm_device *dev, void *data, } fb = obj_to_fb(obj); + /* Check whether this plane supports the fb pixel format. */ + for (i = 0; i < plane->format_count; i++) + 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); + ret = -EINVAL; + goto out; + } + fb_width = fb->width << 16; fb_height = fb->height << 16; -- cgit v1.2.3 From 935b59774012d11e3012c909cdd0c3cba0adf219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 20 Dec 2011 00:06:48 +0200 Subject: drm: Check that the requested pixel format is valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 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 66a165dac5c4..07d78e27ec3d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2061,6 +2061,75 @@ out: return ret; } +static int format_check(struct drm_mode_fb_cmd2 *r) +{ + uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; + + switch (format) { + case DRM_FORMAT_C8: + case DRM_FORMAT_RGB332: + case DRM_FORMAT_BGR233: + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_XBGR4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_BGRX4444: + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_BGRA4444: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRX5551: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_BGRA5551: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + case DRM_FORMAT_RGB888: + case DRM_FORMAT_BGR888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRX1010102: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_AYUV: + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + case DRM_FORMAT_YUV410: + case DRM_FORMAT_YVU410: + case DRM_FORMAT_YUV411: + case DRM_FORMAT_YVU411: + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: + return 0; + default: + return -EINVAL; + } +} + /** * drm_mode_addfb2 - add an FB to the graphics configuration * @inode: inode from the ioctl @@ -2100,6 +2169,12 @@ int drm_mode_addfb2(struct drm_device *dev, return -EINVAL; } + ret = format_check(r); + if (ret) { + DRM_ERROR("bad framebuffer format 0x%08x\n", r->pixel_format); + return ret; + } + mutex_lock(&dev->mode_config.mutex); fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); -- cgit v1.2.3 From 01f2c7730e188077026c5f766f85f329c7000c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 20 Dec 2011 00:06:49 +0200 Subject: drm: Replace pitch with pitches[] in drm_framebuffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise each driver would need to keep the information inside their own framebuffer object structure. Also add offsets[]. BOs on the other hand are driver specific, so those can be kept in driver specific structures. 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 07d78e27ec3d..0d1faa72e1ff 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2292,7 +2292,7 @@ int drm_mode_getfb(struct drm_device *dev, r->width = fb->width; r->depth = fb->depth; r->bpp = fb->bits_per_pixel; - r->pitch = fb->pitch; + r->pitch = fb->pitches[0]; fb->funcs->create_handle(fb, file_priv, &r->handle); out: -- cgit v1.2.3 From a9971157b6c550644fe19551c21f4b05f7e9475a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 13 Dec 2011 20:19:35 -0600 Subject: drm: disconnect plane from fb/crtc when disabled Since plane->fb and plane->crtc are set in drm_mode_setplane() after update_plane(), They should be cleared after disable(). Signed-off-by: Rob Clark 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 f259a2563204..7710bcb4bd8d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -348,6 +348,9 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) 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: */ + plane->fb = NULL; + plane->crtc = NULL; } } -- cgit v1.2.3 From 0a7eb243db7864640134f8c57e6856f8eb3ed7c6 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 13 Dec 2011 20:19:36 -0600 Subject: drm: add support for private planes In cases where the scanout hw is sufficiently similar between "overlay" and traditional crtc layers, it might be convenient to allow the driver to create internal drm_plane helper objects used by the drm_crtc implementation, rather than duplicate code between the plane and crtc. A private plane is not exposed to userspace. Signed-off-by: Rob Clark Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 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 7710bcb4bd8d..5e818a808ace 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -557,7 +557,8 @@ EXPORT_SYMBOL(drm_encoder_cleanup); int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, - const uint32_t *formats, uint32_t format_count) + const uint32_t *formats, uint32_t format_count, + bool priv) { mutex_lock(&dev->mode_config.mutex); @@ -577,8 +578,16 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, plane->format_count = format_count; plane->possible_crtcs = possible_crtcs; - list_add_tail(&plane->head, &dev->mode_config.plane_list); - dev->mode_config.num_plane++; + /* private planes are not exposed to userspace, but depending on + * display hardware, might be convenient to allow sharing programming + * for the scanout engine with the crtc implementation. + */ + if (!priv) { + list_add_tail(&plane->head, &dev->mode_config.plane_list); + dev->mode_config.num_plane++; + } else { + INIT_LIST_HEAD(&plane->head); + } mutex_unlock(&dev->mode_config.mutex); @@ -593,8 +602,11 @@ void drm_plane_cleanup(struct drm_plane *plane) mutex_lock(&dev->mode_config.mutex); kfree(plane->format_types); drm_mode_object_put(dev, &plane->base); - list_del(&plane->head); - dev->mode_config.num_plane--; + /* if not added to a list, it must be a private plane */ + if (!list_empty(&plane->head)) { + list_del(&plane->head); + dev->mode_config.num_plane--; + } mutex_unlock(&dev->mode_config.mutex); } EXPORT_SYMBOL(drm_plane_cleanup); -- cgit v1.2.3