Loading drivers/gpu/drm/drm_crtc.c +357 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -324,6 +325,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; Loading @@ -340,6 +342,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--; Loading Loading @@ -540,6 +551,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 * sizeof(uint32_t)); 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 Loading Loading @@ -871,6 +926,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); Loading Loading @@ -947,6 +1003,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) { Loading @@ -971,6 +1028,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); Loading Loading @@ -1470,6 +1531,197 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, 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 Loading Loading @@ -1664,6 +1916,42 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, 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 Loading @@ -1684,19 +1972,28 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, 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)) { 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)) { if ((config->min_height > r.height) || (r.height > config->max_height)) { DRM_ERROR("mode new framebuffer height not within limits\n"); return -EINVAL; } Loading @@ -1706,6 +2003,63 @@ int drm_mode_addfb(struct drm_device *dev, /* 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; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; if ((config->min_width > r->width) || (r->width > config->max_width)) { 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("bad framebuffer height %d, should be >= %d && <= %d\n", r->height, config->min_height, config->max_height); return -EINVAL; } mutex_lock(&dev->mode_config.mutex); fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); if (IS_ERR(fb)) { DRM_ERROR("could not create framebuffer\n"); Loading drivers/gpu/drm/drm_crtc_helper.c +47 −4 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "drmP.h" #include "drm_crtc.h" #include "drm_fourcc.h" #include "drm_crtc_helper.h" #include "drm_fb_helper.h" Loading Loading @@ -810,14 +811,56 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) } EXPORT_SYMBOL(drm_helper_connector_dpms); /* * Just need to support RGB formats here for compat with code that doesn't * use pixel formats directly yet. */ void drm_helper_get_fb_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_helper_get_fb_bpp_depth); int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, struct drm_mode_fb_cmd *mode_cmd) struct drm_mode_fb_cmd2 *mode_cmd) { fb->width = mode_cmd->width; fb->height = mode_cmd->height; fb->pitch = mode_cmd->pitch; fb->bits_per_pixel = mode_cmd->bpp; fb->depth = mode_cmd->depth; fb->pitch = mode_cmd->pitches[0]; drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format, &fb->depth, &fb->bits_per_pixel); fb->pixel_format = mode_cmd->pixel_format; return 0; } Loading drivers/gpu/drm/drm_drv.c +4 −0 Original line number Diff line number Diff line Loading @@ -136,8 +136,11 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED), Loading @@ -150,6 +153,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), Loading drivers/gpu/drm/i915/intel_display.c +21 −18 Original line number Diff line number Diff line Loading @@ -6279,7 +6279,7 @@ static struct drm_display_mode load_detect_mode = { static struct drm_framebuffer * intel_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { struct intel_framebuffer *intel_fb; Loading Loading @@ -6321,7 +6321,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, int depth, int bpp) { struct drm_i915_gem_object *obj; struct drm_mode_fb_cmd mode_cmd; struct drm_mode_fb_cmd2 mode_cmd; obj = i915_gem_alloc_object(dev, intel_framebuffer_size_for_mode(mode, bpp)); Loading @@ -6330,9 +6330,9 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, mode_cmd.width = mode->hdisplay; mode_cmd.height = mode->vdisplay; mode_cmd.depth = depth; mode_cmd.bpp = bpp; mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp); mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp); mode_cmd.pixel_format = 0; return intel_framebuffer_create(dev, &mode_cmd, obj); } Loading Loading @@ -7573,7 +7573,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = { int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *intel_fb, struct drm_mode_fb_cmd *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { int ret; Loading @@ -7581,21 +7581,23 @@ int intel_framebuffer_init(struct drm_device *dev, if (obj->tiling_mode == I915_TILING_Y) return -EINVAL; if (mode_cmd->pitch & 63) if (mode_cmd->pitches[0] & 63) return -EINVAL; switch (mode_cmd->bpp) { case 8: case 16: /* Only pre-ILK can handle 5:5:5 */ if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev)) return -EINVAL; switch (mode_cmd->pixel_format) { case DRM_FOURCC_RGB332: case DRM_FOURCC_RGB565: case DRM_FOURCC_RGB24: case DRM_INTEL_RGB30: /* RGB formats are common across chipsets */ break; case 24: case 32: case DRM_FOURCC_YUYV: case DRM_FOURCC_UYVY: case DRM_FOURCC_YVYU: case DRM_FOURCC_VYUY: break; default: DRM_ERROR("unsupported pixel format\n"); return -EINVAL; } Loading @@ -7613,11 +7615,12 @@ int intel_framebuffer_init(struct drm_device *dev, static struct drm_framebuffer * intel_user_framebuffer_create(struct drm_device *dev, struct drm_file *filp, struct drm_mode_fb_cmd *mode_cmd) struct drm_mode_fb_cmd2 *mode_cmd) { struct drm_i915_gem_object *obj; obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle)); obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handles[0])); if (&obj->base == NULL) return ERR_PTR(-ENOENT); Loading drivers/gpu/drm/i915/intel_drv.h +1 −1 Original line number Diff line number Diff line Loading @@ -359,7 +359,7 @@ extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, extern int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *ifb, struct drm_mode_fb_cmd *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj); extern int intel_fbdev_init(struct drm_device *dev); extern void intel_fbdev_fini(struct drm_device *dev); Loading Loading
drivers/gpu/drm/drm_crtc.c +357 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -324,6 +325,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; Loading @@ -340,6 +342,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--; Loading Loading @@ -540,6 +551,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 * sizeof(uint32_t)); 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 Loading Loading @@ -871,6 +926,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); Loading Loading @@ -947,6 +1003,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) { Loading @@ -971,6 +1028,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); Loading Loading @@ -1470,6 +1531,197 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, 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 Loading Loading @@ -1664,6 +1916,42 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, 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 Loading @@ -1684,19 +1972,28 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, 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)) { 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)) { if ((config->min_height > r.height) || (r.height > config->max_height)) { DRM_ERROR("mode new framebuffer height not within limits\n"); return -EINVAL; } Loading @@ -1706,6 +2003,63 @@ int drm_mode_addfb(struct drm_device *dev, /* 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; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; if ((config->min_width > r->width) || (r->width > config->max_width)) { 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("bad framebuffer height %d, should be >= %d && <= %d\n", r->height, config->min_height, config->max_height); return -EINVAL; } mutex_lock(&dev->mode_config.mutex); fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); if (IS_ERR(fb)) { DRM_ERROR("could not create framebuffer\n"); Loading
drivers/gpu/drm/drm_crtc_helper.c +47 −4 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "drmP.h" #include "drm_crtc.h" #include "drm_fourcc.h" #include "drm_crtc_helper.h" #include "drm_fb_helper.h" Loading Loading @@ -810,14 +811,56 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) } EXPORT_SYMBOL(drm_helper_connector_dpms); /* * Just need to support RGB formats here for compat with code that doesn't * use pixel formats directly yet. */ void drm_helper_get_fb_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_helper_get_fb_bpp_depth); int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, struct drm_mode_fb_cmd *mode_cmd) struct drm_mode_fb_cmd2 *mode_cmd) { fb->width = mode_cmd->width; fb->height = mode_cmd->height; fb->pitch = mode_cmd->pitch; fb->bits_per_pixel = mode_cmd->bpp; fb->depth = mode_cmd->depth; fb->pitch = mode_cmd->pitches[0]; drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format, &fb->depth, &fb->bits_per_pixel); fb->pixel_format = mode_cmd->pixel_format; return 0; } Loading
drivers/gpu/drm/drm_drv.c +4 −0 Original line number Diff line number Diff line Loading @@ -136,8 +136,11 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED), Loading @@ -150,6 +153,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), Loading
drivers/gpu/drm/i915/intel_display.c +21 −18 Original line number Diff line number Diff line Loading @@ -6279,7 +6279,7 @@ static struct drm_display_mode load_detect_mode = { static struct drm_framebuffer * intel_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { struct intel_framebuffer *intel_fb; Loading Loading @@ -6321,7 +6321,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, int depth, int bpp) { struct drm_i915_gem_object *obj; struct drm_mode_fb_cmd mode_cmd; struct drm_mode_fb_cmd2 mode_cmd; obj = i915_gem_alloc_object(dev, intel_framebuffer_size_for_mode(mode, bpp)); Loading @@ -6330,9 +6330,9 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, mode_cmd.width = mode->hdisplay; mode_cmd.height = mode->vdisplay; mode_cmd.depth = depth; mode_cmd.bpp = bpp; mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp); mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp); mode_cmd.pixel_format = 0; return intel_framebuffer_create(dev, &mode_cmd, obj); } Loading Loading @@ -7573,7 +7573,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = { int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *intel_fb, struct drm_mode_fb_cmd *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { int ret; Loading @@ -7581,21 +7581,23 @@ int intel_framebuffer_init(struct drm_device *dev, if (obj->tiling_mode == I915_TILING_Y) return -EINVAL; if (mode_cmd->pitch & 63) if (mode_cmd->pitches[0] & 63) return -EINVAL; switch (mode_cmd->bpp) { case 8: case 16: /* Only pre-ILK can handle 5:5:5 */ if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev)) return -EINVAL; switch (mode_cmd->pixel_format) { case DRM_FOURCC_RGB332: case DRM_FOURCC_RGB565: case DRM_FOURCC_RGB24: case DRM_INTEL_RGB30: /* RGB formats are common across chipsets */ break; case 24: case 32: case DRM_FOURCC_YUYV: case DRM_FOURCC_UYVY: case DRM_FOURCC_YVYU: case DRM_FOURCC_VYUY: break; default: DRM_ERROR("unsupported pixel format\n"); return -EINVAL; } Loading @@ -7613,11 +7615,12 @@ int intel_framebuffer_init(struct drm_device *dev, static struct drm_framebuffer * intel_user_framebuffer_create(struct drm_device *dev, struct drm_file *filp, struct drm_mode_fb_cmd *mode_cmd) struct drm_mode_fb_cmd2 *mode_cmd) { struct drm_i915_gem_object *obj; obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle)); obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handles[0])); if (&obj->base == NULL) return ERR_PTR(-ENOENT); Loading
drivers/gpu/drm/i915/intel_drv.h +1 −1 Original line number Diff line number Diff line Loading @@ -359,7 +359,7 @@ extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, extern int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *ifb, struct drm_mode_fb_cmd *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj); extern int intel_fbdev_init(struct drm_device *dev); extern void intel_fbdev_fini(struct drm_device *dev); Loading