diff options
author | Dave Airlie <airlied@redhat.com> | 2014-07-08 20:38:42 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-07-08 20:38:42 -0400 |
commit | ca5a1b9ba0fb5291b555a23b76dbe5f6c30bfd7a (patch) | |
tree | 9a012a2a610ad4e9500c8e4f0aa68ecdc23c4dba /drivers/gpu/drm/drm_crtc.c | |
parent | c7dbc6c9ae5c3baa3be755a228a349374d043b5b (diff) | |
parent | 34882298b93e998d5fccde852b860e8fbe6c8f6b (diff) |
Merge tag 'drm-intel-next-2014-06-20' of git://anongit.freedesktop.org/drm-intel into drm-next
- Accurate frontbuffer tracking and frontbuffer rendering invalidate, flush and
flip events. This is prep work for proper PSR support and should also be
useful for DRRS&fbc.
- Runtime suspend hardware on system suspend to support the new SOix sleep
states, from Jesse.
- PSR updates for broadwell (Rodrigo)
- Universal plane support for cursors (Matt Roper), including core drm patches.
- Prefault gtt mappings (Chris)
- baytrail write-enable pte bit support (Akash Goel)
- mmio based flips (Sourab Gupta) instead of blitter ring flips
- interrupt handling race fixes (Oscar Mateo)
And old, not yet merged features from the previous round:
- rps/turbo support for chv (Deepak)
- some other straggling chv patches (Ville)
- proper universal plane conversion for the primary plane (Matt Roper)
- ppgtt on vlv from Jesse
- pile of cleanups, little fixes for insane corner cases and improved debug
support all over
* tag 'drm-intel-next-2014-06-20' of git://anongit.freedesktop.org/drm-intel: (99 commits)
drm/i915: Update DRIVER_DATE to 20140620
drivers/i915: Fix unnoticed failure of init_ring_common()
drm/i915: Track frontbuffer invalidation/flushing
drm/i915: Use new frontbuffer bits to increase pll clock
drm/i915: don't take runtime PM reference around freeze/thaw
drm/i915: use runtime irq suspend/resume in freeze/thaw
drm/i915: Properly track domain of the fbcon fb
drm/i915: Print obj->frontbuffer_bits in debugfs output
drm/i915: Introduce accurate frontbuffer tracking
drm/i915: Drop schedule_back from psr_exit
drm/i915: Ditch intel_edp_psr_update
drm/i915: Drop unecessary complexity from psr_inactivate
drm/i915: Remove ctx->last_ring
drm/i915/chv: Ack interrupts before handling them (CHV)
drm/i915/bdw: Ack interrupts before handling them (GEN8)
drm/i915/vlv: Ack interrupts before handling them (VLV)
drm/i915: Ack interrupts before handling them (GEN5 - GEN7)
drm/i915: Don't BUG_ON in i915_gem_obj_offset
drm/i915: Grab dev->struct_mutex in i915_gem_pageflip_info
drm/i915: Add some L3 registers to the parser whitelist
...
Conflicts:
drivers/gpu/drm/i915/i915_drv.c
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 357 |
1 files changed, 255 insertions, 102 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index bd7422676638..c808a092d824 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -41,6 +41,10 @@ | |||
41 | 41 | ||
42 | #include "drm_crtc_internal.h" | 42 | #include "drm_crtc_internal.h" |
43 | 43 | ||
44 | static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, | ||
45 | struct drm_mode_fb_cmd2 *r, | ||
46 | struct drm_file *file_priv); | ||
47 | |||
44 | /** | 48 | /** |
45 | * drm_modeset_lock_all - take all modeset locks | 49 | * drm_modeset_lock_all - take all modeset locks |
46 | * @dev: drm device | 50 | * @dev: drm device |
@@ -723,7 +727,7 @@ DEFINE_WW_CLASS(crtc_ww_class); | |||
723 | */ | 727 | */ |
724 | int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, | 728 | int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, |
725 | struct drm_plane *primary, | 729 | struct drm_plane *primary, |
726 | void *cursor, | 730 | struct drm_plane *cursor, |
727 | const struct drm_crtc_funcs *funcs) | 731 | const struct drm_crtc_funcs *funcs) |
728 | { | 732 | { |
729 | struct drm_mode_config *config = &dev->mode_config; | 733 | struct drm_mode_config *config = &dev->mode_config; |
@@ -748,8 +752,11 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, | |||
748 | config->num_crtc++; | 752 | config->num_crtc++; |
749 | 753 | ||
750 | crtc->primary = primary; | 754 | crtc->primary = primary; |
755 | crtc->cursor = cursor; | ||
751 | if (primary) | 756 | if (primary) |
752 | primary->possible_crtcs = 1 << drm_crtc_index(crtc); | 757 | primary->possible_crtcs = 1 << drm_crtc_index(crtc); |
758 | if (cursor) | ||
759 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); | ||
753 | 760 | ||
754 | out: | 761 | out: |
755 | drm_modeset_unlock_all(dev); | 762 | drm_modeset_unlock_all(dev); |
@@ -2177,45 +2184,32 @@ out: | |||
2177 | return ret; | 2184 | return ret; |
2178 | } | 2185 | } |
2179 | 2186 | ||
2180 | /** | 2187 | /* |
2181 | * drm_mode_setplane - configure a plane's configuration | 2188 | * setplane_internal - setplane handler for internal callers |
2182 | * @dev: DRM device | ||
2183 | * @data: ioctl data* | ||
2184 | * @file_priv: DRM file info | ||
2185 | * | 2189 | * |
2186 | * Set plane configuration, including placement, fb, scaling, and other factors. | 2190 | * Note that we assume an extra reference has already been taken on fb. If the |
2187 | * Or pass a NULL fb to disable. | 2191 | * update fails, this reference will be dropped before return; if it succeeds, |
2192 | * the previous framebuffer (if any) will be unreferenced instead. | ||
2188 | * | 2193 | * |
2189 | * Returns: | 2194 | * src_{x,y,w,h} are provided in 16.16 fixed point format |
2190 | * Zero on success, errno on failure. | ||
2191 | */ | 2195 | */ |
2192 | int drm_mode_setplane(struct drm_device *dev, void *data, | 2196 | static int setplane_internal(struct drm_plane *plane, |
2193 | struct drm_file *file_priv) | 2197 | struct drm_crtc *crtc, |
2198 | struct drm_framebuffer *fb, | ||
2199 | int32_t crtc_x, int32_t crtc_y, | ||
2200 | uint32_t crtc_w, uint32_t crtc_h, | ||
2201 | /* src_{x,y,w,h} values are 16.16 fixed point */ | ||
2202 | uint32_t src_x, uint32_t src_y, | ||
2203 | uint32_t src_w, uint32_t src_h) | ||
2194 | { | 2204 | { |
2195 | struct drm_mode_set_plane *plane_req = data; | 2205 | struct drm_device *dev = plane->dev; |
2196 | struct drm_plane *plane; | 2206 | struct drm_framebuffer *old_fb = NULL; |
2197 | struct drm_crtc *crtc; | ||
2198 | struct drm_framebuffer *fb = NULL, *old_fb = NULL; | ||
2199 | int ret = 0; | 2207 | int ret = 0; |
2200 | unsigned int fb_width, fb_height; | 2208 | unsigned int fb_width, fb_height; |
2201 | int i; | 2209 | int i; |
2202 | 2210 | ||
2203 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
2204 | return -EINVAL; | ||
2205 | |||
2206 | /* | ||
2207 | * First, find the plane, crtc, and fb objects. If not available, | ||
2208 | * we don't bother to call the driver. | ||
2209 | */ | ||
2210 | plane = drm_plane_find(dev, plane_req->plane_id); | ||
2211 | if (!plane) { | ||
2212 | DRM_DEBUG_KMS("Unknown plane ID %d\n", | ||
2213 | plane_req->plane_id); | ||
2214 | return -ENOENT; | ||
2215 | } | ||
2216 | |||
2217 | /* No fb means shut it down */ | 2211 | /* No fb means shut it down */ |
2218 | if (!plane_req->fb_id) { | 2212 | if (!fb) { |
2219 | drm_modeset_lock_all(dev); | 2213 | drm_modeset_lock_all(dev); |
2220 | old_fb = plane->fb; | 2214 | old_fb = plane->fb; |
2221 | ret = plane->funcs->disable_plane(plane); | 2215 | ret = plane->funcs->disable_plane(plane); |
@@ -2229,14 +2223,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2229 | goto out; | 2223 | goto out; |
2230 | } | 2224 | } |
2231 | 2225 | ||
2232 | crtc = drm_crtc_find(dev, plane_req->crtc_id); | ||
2233 | if (!crtc) { | ||
2234 | DRM_DEBUG_KMS("Unknown crtc ID %d\n", | ||
2235 | plane_req->crtc_id); | ||
2236 | ret = -ENOENT; | ||
2237 | goto out; | ||
2238 | } | ||
2239 | |||
2240 | /* Check whether this plane is usable on this CRTC */ | 2226 | /* Check whether this plane is usable on this CRTC */ |
2241 | if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) { | 2227 | if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) { |
2242 | DRM_DEBUG_KMS("Invalid crtc for plane\n"); | 2228 | DRM_DEBUG_KMS("Invalid crtc for plane\n"); |
@@ -2244,14 +2230,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2244 | goto out; | 2230 | goto out; |
2245 | } | 2231 | } |
2246 | 2232 | ||
2247 | fb = drm_framebuffer_lookup(dev, plane_req->fb_id); | ||
2248 | if (!fb) { | ||
2249 | DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", | ||
2250 | plane_req->fb_id); | ||
2251 | ret = -ENOENT; | ||
2252 | goto out; | ||
2253 | } | ||
2254 | |||
2255 | /* Check whether this plane supports the fb pixel format. */ | 2233 | /* Check whether this plane supports the fb pixel format. */ |
2256 | for (i = 0; i < plane->format_count; i++) | 2234 | for (i = 0; i < plane->format_count; i++) |
2257 | if (fb->pixel_format == plane->format_types[i]) | 2235 | if (fb->pixel_format == plane->format_types[i]) |
@@ -2267,43 +2245,25 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2267 | fb_height = fb->height << 16; | 2245 | fb_height = fb->height << 16; |
2268 | 2246 | ||
2269 | /* Make sure source coordinates are inside the fb. */ | 2247 | /* Make sure source coordinates are inside the fb. */ |
2270 | if (plane_req->src_w > fb_width || | 2248 | if (src_w > fb_width || |
2271 | plane_req->src_x > fb_width - plane_req->src_w || | 2249 | src_x > fb_width - src_w || |
2272 | plane_req->src_h > fb_height || | 2250 | src_h > fb_height || |
2273 | plane_req->src_y > fb_height - plane_req->src_h) { | 2251 | src_y > fb_height - src_h) { |
2274 | DRM_DEBUG_KMS("Invalid source coordinates " | 2252 | DRM_DEBUG_KMS("Invalid source coordinates " |
2275 | "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", | 2253 | "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", |
2276 | plane_req->src_w >> 16, | 2254 | src_w >> 16, ((src_w & 0xffff) * 15625) >> 10, |
2277 | ((plane_req->src_w & 0xffff) * 15625) >> 10, | 2255 | src_h >> 16, ((src_h & 0xffff) * 15625) >> 10, |
2278 | plane_req->src_h >> 16, | 2256 | src_x >> 16, ((src_x & 0xffff) * 15625) >> 10, |
2279 | ((plane_req->src_h & 0xffff) * 15625) >> 10, | 2257 | src_y >> 16, ((src_y & 0xffff) * 15625) >> 10); |
2280 | plane_req->src_x >> 16, | ||
2281 | ((plane_req->src_x & 0xffff) * 15625) >> 10, | ||
2282 | plane_req->src_y >> 16, | ||
2283 | ((plane_req->src_y & 0xffff) * 15625) >> 10); | ||
2284 | ret = -ENOSPC; | 2258 | ret = -ENOSPC; |
2285 | goto out; | 2259 | goto out; |
2286 | } | 2260 | } |
2287 | 2261 | ||
2288 | /* Give drivers some help against integer overflows */ | ||
2289 | if (plane_req->crtc_w > INT_MAX || | ||
2290 | plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || | ||
2291 | plane_req->crtc_h > INT_MAX || | ||
2292 | plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { | ||
2293 | DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", | ||
2294 | plane_req->crtc_w, plane_req->crtc_h, | ||
2295 | plane_req->crtc_x, plane_req->crtc_y); | ||
2296 | ret = -ERANGE; | ||
2297 | goto out; | ||
2298 | } | ||
2299 | |||
2300 | drm_modeset_lock_all(dev); | 2262 | drm_modeset_lock_all(dev); |
2301 | old_fb = plane->fb; | 2263 | old_fb = plane->fb; |
2302 | ret = plane->funcs->update_plane(plane, crtc, fb, | 2264 | ret = plane->funcs->update_plane(plane, crtc, fb, |
2303 | plane_req->crtc_x, plane_req->crtc_y, | 2265 | crtc_x, crtc_y, crtc_w, crtc_h, |
2304 | plane_req->crtc_w, plane_req->crtc_h, | 2266 | src_x, src_y, src_w, src_h); |
2305 | plane_req->src_x, plane_req->src_y, | ||
2306 | plane_req->src_w, plane_req->src_h); | ||
2307 | if (!ret) { | 2267 | if (!ret) { |
2308 | plane->crtc = crtc; | 2268 | plane->crtc = crtc; |
2309 | plane->fb = fb; | 2269 | plane->fb = fb; |
@@ -2320,6 +2280,85 @@ out: | |||
2320 | drm_framebuffer_unreference(old_fb); | 2280 | drm_framebuffer_unreference(old_fb); |
2321 | 2281 | ||
2322 | return ret; | 2282 | return ret; |
2283 | |||
2284 | } | ||
2285 | |||
2286 | /** | ||
2287 | * drm_mode_setplane - configure a plane's configuration | ||
2288 | * @dev: DRM device | ||
2289 | * @data: ioctl data* | ||
2290 | * @file_priv: DRM file info | ||
2291 | * | ||
2292 | * Set plane configuration, including placement, fb, scaling, and other factors. | ||
2293 | * Or pass a NULL fb to disable (planes may be disabled without providing a | ||
2294 | * valid crtc). | ||
2295 | * | ||
2296 | * Returns: | ||
2297 | * Zero on success, errno on failure. | ||
2298 | */ | ||
2299 | int drm_mode_setplane(struct drm_device *dev, void *data, | ||
2300 | struct drm_file *file_priv) | ||
2301 | { | ||
2302 | struct drm_mode_set_plane *plane_req = data; | ||
2303 | struct drm_mode_object *obj; | ||
2304 | struct drm_plane *plane; | ||
2305 | struct drm_crtc *crtc = NULL; | ||
2306 | struct drm_framebuffer *fb = NULL; | ||
2307 | |||
2308 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
2309 | return -EINVAL; | ||
2310 | |||
2311 | /* Give drivers some help against integer overflows */ | ||
2312 | if (plane_req->crtc_w > INT_MAX || | ||
2313 | plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || | ||
2314 | plane_req->crtc_h > INT_MAX || | ||
2315 | plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { | ||
2316 | DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", | ||
2317 | plane_req->crtc_w, plane_req->crtc_h, | ||
2318 | plane_req->crtc_x, plane_req->crtc_y); | ||
2319 | return -ERANGE; | ||
2320 | } | ||
2321 | |||
2322 | /* | ||
2323 | * First, find the plane, crtc, and fb objects. If not available, | ||
2324 | * we don't bother to call the driver. | ||
2325 | */ | ||
2326 | obj = drm_mode_object_find(dev, plane_req->plane_id, | ||
2327 | DRM_MODE_OBJECT_PLANE); | ||
2328 | if (!obj) { | ||
2329 | DRM_DEBUG_KMS("Unknown plane ID %d\n", | ||
2330 | plane_req->plane_id); | ||
2331 | return -ENOENT; | ||
2332 | } | ||
2333 | plane = obj_to_plane(obj); | ||
2334 | |||
2335 | if (plane_req->fb_id) { | ||
2336 | fb = drm_framebuffer_lookup(dev, plane_req->fb_id); | ||
2337 | if (!fb) { | ||
2338 | DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", | ||
2339 | plane_req->fb_id); | ||
2340 | return -ENOENT; | ||
2341 | } | ||
2342 | |||
2343 | obj = drm_mode_object_find(dev, plane_req->crtc_id, | ||
2344 | DRM_MODE_OBJECT_CRTC); | ||
2345 | if (!obj) { | ||
2346 | DRM_DEBUG_KMS("Unknown crtc ID %d\n", | ||
2347 | plane_req->crtc_id); | ||
2348 | return -ENOENT; | ||
2349 | } | ||
2350 | crtc = obj_to_crtc(obj); | ||
2351 | } | ||
2352 | |||
2353 | /* | ||
2354 | * setplane_internal will take care of deref'ing either the old or new | ||
2355 | * framebuffer depending on success. | ||
2356 | */ | ||
2357 | return setplane_internal(plane, crtc, fb, | ||
2358 | plane_req->crtc_x, plane_req->crtc_y, | ||
2359 | plane_req->crtc_w, plane_req->crtc_h, | ||
2360 | plane_req->src_x, plane_req->src_y, | ||
2361 | plane_req->src_w, plane_req->src_h); | ||
2323 | } | 2362 | } |
2324 | 2363 | ||
2325 | /** | 2364 | /** |
@@ -2568,6 +2607,102 @@ out: | |||
2568 | return ret; | 2607 | return ret; |
2569 | } | 2608 | } |
2570 | 2609 | ||
2610 | /** | ||
2611 | * drm_mode_cursor_universal - translate legacy cursor ioctl call into a | ||
2612 | * universal plane handler call | ||
2613 | * @crtc: crtc to update cursor for | ||
2614 | * @req: data pointer for the ioctl | ||
2615 | * @file_priv: drm file for the ioctl call | ||
2616 | * | ||
2617 | * Legacy cursor ioctl's work directly with driver buffer handles. To | ||
2618 | * translate legacy ioctl calls into universal plane handler calls, we need to | ||
2619 | * wrap the native buffer handle in a drm_framebuffer. | ||
2620 | * | ||
2621 | * Note that we assume any handle passed to the legacy ioctls was a 32-bit ARGB | ||
2622 | * buffer with a pitch of 4*width; the universal plane interface should be used | ||
2623 | * directly in cases where the hardware can support other buffer settings and | ||
2624 | * userspace wants to make use of these capabilities. | ||
2625 | * | ||
2626 | * Returns: | ||
2627 | * Zero on success, errno on failure. | ||
2628 | */ | ||
2629 | static int drm_mode_cursor_universal(struct drm_crtc *crtc, | ||
2630 | struct drm_mode_cursor2 *req, | ||
2631 | struct drm_file *file_priv) | ||
2632 | { | ||
2633 | struct drm_device *dev = crtc->dev; | ||
2634 | struct drm_framebuffer *fb = NULL; | ||
2635 | struct drm_mode_fb_cmd2 fbreq = { | ||
2636 | .width = req->width, | ||
2637 | .height = req->height, | ||
2638 | .pixel_format = DRM_FORMAT_ARGB8888, | ||
2639 | .pitches = { req->width * 4 }, | ||
2640 | .handles = { req->handle }, | ||
2641 | }; | ||
2642 | int32_t crtc_x, crtc_y; | ||
2643 | uint32_t crtc_w = 0, crtc_h = 0; | ||
2644 | uint32_t src_w = 0, src_h = 0; | ||
2645 | int ret = 0; | ||
2646 | |||
2647 | BUG_ON(!crtc->cursor); | ||
2648 | |||
2649 | /* | ||
2650 | * Obtain fb we'll be using (either new or existing) and take an extra | ||
2651 | * reference to it if fb != null. setplane will take care of dropping | ||
2652 | * the reference if the plane update fails. | ||
2653 | */ | ||
2654 | if (req->flags & DRM_MODE_CURSOR_BO) { | ||
2655 | if (req->handle) { | ||
2656 | fb = add_framebuffer_internal(dev, &fbreq, file_priv); | ||
2657 | if (IS_ERR(fb)) { | ||
2658 | DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n"); | ||
2659 | return PTR_ERR(fb); | ||
2660 | } | ||
2661 | |||
2662 | drm_framebuffer_reference(fb); | ||
2663 | } else { | ||
2664 | fb = NULL; | ||
2665 | } | ||
2666 | } else { | ||
2667 | mutex_lock(&dev->mode_config.mutex); | ||
2668 | fb = crtc->cursor->fb; | ||
2669 | if (fb) | ||
2670 | drm_framebuffer_reference(fb); | ||
2671 | mutex_unlock(&dev->mode_config.mutex); | ||
2672 | } | ||
2673 | |||
2674 | if (req->flags & DRM_MODE_CURSOR_MOVE) { | ||
2675 | crtc_x = req->x; | ||
2676 | crtc_y = req->y; | ||
2677 | } else { | ||
2678 | crtc_x = crtc->cursor_x; | ||
2679 | crtc_y = crtc->cursor_y; | ||
2680 | } | ||
2681 | |||
2682 | if (fb) { | ||
2683 | crtc_w = fb->width; | ||
2684 | crtc_h = fb->height; | ||
2685 | src_w = fb->width << 16; | ||
2686 | src_h = fb->height << 16; | ||
2687 | } | ||
2688 | |||
2689 | /* | ||
2690 | * setplane_internal will take care of deref'ing either the old or new | ||
2691 | * framebuffer depending on success. | ||
2692 | */ | ||
2693 | ret = setplane_internal(crtc->cursor, crtc, fb, | ||
2694 | crtc_x, crtc_y, crtc_w, crtc_h, | ||
2695 | 0, 0, src_w, src_h); | ||
2696 | |||
2697 | /* Update successful; save new cursor position, if necessary */ | ||
2698 | if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { | ||
2699 | crtc->cursor_x = req->x; | ||
2700 | crtc->cursor_y = req->y; | ||
2701 | } | ||
2702 | |||
2703 | return ret; | ||
2704 | } | ||
2705 | |||
2571 | static int drm_mode_cursor_common(struct drm_device *dev, | 2706 | static int drm_mode_cursor_common(struct drm_device *dev, |
2572 | struct drm_mode_cursor2 *req, | 2707 | struct drm_mode_cursor2 *req, |
2573 | struct drm_file *file_priv) | 2708 | struct drm_file *file_priv) |
@@ -2587,6 +2722,13 @@ static int drm_mode_cursor_common(struct drm_device *dev, | |||
2587 | return -ENOENT; | 2722 | return -ENOENT; |
2588 | } | 2723 | } |
2589 | 2724 | ||
2725 | /* | ||
2726 | * If this crtc has a universal cursor plane, call that plane's update | ||
2727 | * handler rather than using legacy cursor handlers. | ||
2728 | */ | ||
2729 | if (crtc->cursor) | ||
2730 | return drm_mode_cursor_universal(crtc, req, file_priv); | ||
2731 | |||
2590 | drm_modeset_lock(&crtc->mutex, NULL); | 2732 | drm_modeset_lock(&crtc->mutex, NULL); |
2591 | if (req->flags & DRM_MODE_CURSOR_BO) { | 2733 | if (req->flags & DRM_MODE_CURSOR_BO) { |
2592 | if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { | 2734 | if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { |
@@ -2886,56 +3028,38 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | |||
2886 | return 0; | 3028 | return 0; |
2887 | } | 3029 | } |
2888 | 3030 | ||
2889 | /** | 3031 | static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, |
2890 | * drm_mode_addfb2 - add an FB to the graphics configuration | 3032 | struct drm_mode_fb_cmd2 *r, |
2891 | * @dev: drm device for the ioctl | 3033 | struct drm_file *file_priv) |
2892 | * @data: data pointer for the ioctl | ||
2893 | * @file_priv: drm file for the ioctl call | ||
2894 | * | ||
2895 | * Add a new FB to the specified CRTC, given a user request with format. This is | ||
2896 | * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers | ||
2897 | * and uses fourcc codes as pixel format specifiers. | ||
2898 | * | ||
2899 | * Called by the user via ioctl. | ||
2900 | * | ||
2901 | * Returns: | ||
2902 | * Zero on success, errno on failure. | ||
2903 | */ | ||
2904 | int drm_mode_addfb2(struct drm_device *dev, | ||
2905 | void *data, struct drm_file *file_priv) | ||
2906 | { | 3034 | { |
2907 | struct drm_mode_fb_cmd2 *r = data; | ||
2908 | struct drm_mode_config *config = &dev->mode_config; | 3035 | struct drm_mode_config *config = &dev->mode_config; |
2909 | struct drm_framebuffer *fb; | 3036 | struct drm_framebuffer *fb; |
2910 | int ret; | 3037 | int ret; |
2911 | 3038 | ||
2912 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
2913 | return -EINVAL; | ||
2914 | |||
2915 | if (r->flags & ~DRM_MODE_FB_INTERLACED) { | 3039 | if (r->flags & ~DRM_MODE_FB_INTERLACED) { |
2916 | DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); | 3040 | DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); |
2917 | return -EINVAL; | 3041 | return ERR_PTR(-EINVAL); |
2918 | } | 3042 | } |
2919 | 3043 | ||
2920 | if ((config->min_width > r->width) || (r->width > config->max_width)) { | 3044 | if ((config->min_width > r->width) || (r->width > config->max_width)) { |
2921 | DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", | 3045 | DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", |
2922 | r->width, config->min_width, config->max_width); | 3046 | r->width, config->min_width, config->max_width); |
2923 | return -EINVAL; | 3047 | return ERR_PTR(-EINVAL); |
2924 | } | 3048 | } |
2925 | if ((config->min_height > r->height) || (r->height > config->max_height)) { | 3049 | if ((config->min_height > r->height) || (r->height > config->max_height)) { |
2926 | DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", | 3050 | DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", |
2927 | r->height, config->min_height, config->max_height); | 3051 | r->height, config->min_height, config->max_height); |
2928 | return -EINVAL; | 3052 | return ERR_PTR(-EINVAL); |
2929 | } | 3053 | } |
2930 | 3054 | ||
2931 | ret = framebuffer_check(r); | 3055 | ret = framebuffer_check(r); |
2932 | if (ret) | 3056 | if (ret) |
2933 | return ret; | 3057 | return ERR_PTR(ret); |
2934 | 3058 | ||
2935 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); | 3059 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
2936 | if (IS_ERR(fb)) { | 3060 | if (IS_ERR(fb)) { |
2937 | DRM_DEBUG_KMS("could not create framebuffer\n"); | 3061 | DRM_DEBUG_KMS("could not create framebuffer\n"); |
2938 | return PTR_ERR(fb); | 3062 | return fb; |
2939 | } | 3063 | } |
2940 | 3064 | ||
2941 | mutex_lock(&file_priv->fbs_lock); | 3065 | mutex_lock(&file_priv->fbs_lock); |
@@ -2944,8 +3068,37 @@ int drm_mode_addfb2(struct drm_device *dev, | |||
2944 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); | 3068 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
2945 | mutex_unlock(&file_priv->fbs_lock); | 3069 | mutex_unlock(&file_priv->fbs_lock); |
2946 | 3070 | ||
3071 | return fb; | ||
3072 | } | ||
2947 | 3073 | ||
2948 | return ret; | 3074 | /** |
3075 | * drm_mode_addfb2 - add an FB to the graphics configuration | ||
3076 | * @dev: drm device for the ioctl | ||
3077 | * @data: data pointer for the ioctl | ||
3078 | * @file_priv: drm file for the ioctl call | ||
3079 | * | ||
3080 | * Add a new FB to the specified CRTC, given a user request with format. This is | ||
3081 | * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers | ||
3082 | * and uses fourcc codes as pixel format specifiers. | ||
3083 | * | ||
3084 | * Called by the user via ioctl. | ||
3085 | * | ||
3086 | * Returns: | ||
3087 | * Zero on success, errno on failure. | ||
3088 | */ | ||
3089 | int drm_mode_addfb2(struct drm_device *dev, | ||
3090 | void *data, struct drm_file *file_priv) | ||
3091 | { | ||
3092 | struct drm_framebuffer *fb; | ||
3093 | |||
3094 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
3095 | return -EINVAL; | ||
3096 | |||
3097 | fb = add_framebuffer_internal(dev, data, file_priv); | ||
3098 | if (IS_ERR(fb)) | ||
3099 | return PTR_ERR(fb); | ||
3100 | |||
3101 | return 0; | ||
2949 | } | 3102 | } |
2950 | 3103 | ||
2951 | /** | 3104 | /** |