diff options
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 153 |
1 files changed, 98 insertions, 55 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index bff2fa941f60..d6cf77c472e7 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -202,6 +202,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = | |||
202 | { DRM_MODE_CONNECTOR_TV, "TV" }, | 202 | { DRM_MODE_CONNECTOR_TV, "TV" }, |
203 | { DRM_MODE_CONNECTOR_eDP, "eDP" }, | 203 | { DRM_MODE_CONNECTOR_eDP, "eDP" }, |
204 | { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, | 204 | { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, |
205 | { DRM_MODE_CONNECTOR_DSI, "DSI" }, | ||
205 | }; | 206 | }; |
206 | 207 | ||
207 | static const struct drm_prop_enum_list drm_encoder_enum_list[] = | 208 | static const struct drm_prop_enum_list drm_encoder_enum_list[] = |
@@ -211,6 +212,7 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] = | |||
211 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, | 212 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, |
212 | { DRM_MODE_ENCODER_TVDAC, "TV" }, | 213 | { DRM_MODE_ENCODER_TVDAC, "TV" }, |
213 | { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, | 214 | { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, |
215 | { DRM_MODE_ENCODER_DSI, "DSI" }, | ||
214 | }; | 216 | }; |
215 | 217 | ||
216 | void drm_connector_ida_init(void) | 218 | void drm_connector_ida_init(void) |
@@ -1301,7 +1303,7 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, | |||
1301 | } | 1303 | } |
1302 | 1304 | ||
1303 | /** | 1305 | /** |
1304 | * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode | 1306 | * drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode |
1305 | * @out: drm_display_mode to return to the user | 1307 | * @out: drm_display_mode to return to the user |
1306 | * @in: drm_mode_modeinfo to use | 1308 | * @in: drm_mode_modeinfo to use |
1307 | * | 1309 | * |
@@ -1317,6 +1319,9 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out, | |||
1317 | if (in->clock > INT_MAX || in->vrefresh > INT_MAX) | 1319 | if (in->clock > INT_MAX || in->vrefresh > INT_MAX) |
1318 | return -ERANGE; | 1320 | return -ERANGE; |
1319 | 1321 | ||
1322 | if ((in->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX) | ||
1323 | return -EINVAL; | ||
1324 | |||
1320 | out->clock = in->clock; | 1325 | out->clock = in->clock; |
1321 | out->hdisplay = in->hdisplay; | 1326 | out->hdisplay = in->hdisplay; |
1322 | out->hsync_start = in->hsync_start; | 1327 | out->hsync_start = in->hsync_start; |
@@ -1552,7 +1557,7 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
1552 | obj = drm_mode_object_find(dev, crtc_resp->crtc_id, | 1557 | obj = drm_mode_object_find(dev, crtc_resp->crtc_id, |
1553 | DRM_MODE_OBJECT_CRTC); | 1558 | DRM_MODE_OBJECT_CRTC); |
1554 | if (!obj) { | 1559 | if (!obj) { |
1555 | ret = -EINVAL; | 1560 | ret = -ENOENT; |
1556 | goto out; | 1561 | goto out; |
1557 | } | 1562 | } |
1558 | crtc = obj_to_crtc(obj); | 1563 | crtc = obj_to_crtc(obj); |
@@ -1579,6 +1584,19 @@ out: | |||
1579 | return ret; | 1584 | return ret; |
1580 | } | 1585 | } |
1581 | 1586 | ||
1587 | static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, | ||
1588 | const struct drm_file *file_priv) | ||
1589 | { | ||
1590 | /* | ||
1591 | * If user-space hasn't configured the driver to expose the stereo 3D | ||
1592 | * modes, don't expose them. | ||
1593 | */ | ||
1594 | if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode)) | ||
1595 | return false; | ||
1596 | |||
1597 | return true; | ||
1598 | } | ||
1599 | |||
1582 | /** | 1600 | /** |
1583 | * drm_mode_getconnector - get connector configuration | 1601 | * drm_mode_getconnector - get connector configuration |
1584 | * @dev: drm device for the ioctl | 1602 | * @dev: drm device for the ioctl |
@@ -1623,7 +1641,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
1623 | obj = drm_mode_object_find(dev, out_resp->connector_id, | 1641 | obj = drm_mode_object_find(dev, out_resp->connector_id, |
1624 | DRM_MODE_OBJECT_CONNECTOR); | 1642 | DRM_MODE_OBJECT_CONNECTOR); |
1625 | if (!obj) { | 1643 | if (!obj) { |
1626 | ret = -EINVAL; | 1644 | ret = -ENOENT; |
1627 | goto out; | 1645 | goto out; |
1628 | } | 1646 | } |
1629 | connector = obj_to_connector(obj); | 1647 | connector = obj_to_connector(obj); |
@@ -1644,7 +1662,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
1644 | 1662 | ||
1645 | /* delayed so we get modes regardless of pre-fill_modes state */ | 1663 | /* delayed so we get modes regardless of pre-fill_modes state */ |
1646 | list_for_each_entry(mode, &connector->modes, head) | 1664 | list_for_each_entry(mode, &connector->modes, head) |
1647 | mode_count++; | 1665 | if (drm_mode_expose_to_userspace(mode, file_priv)) |
1666 | mode_count++; | ||
1648 | 1667 | ||
1649 | out_resp->connector_id = connector->base.id; | 1668 | out_resp->connector_id = connector->base.id; |
1650 | out_resp->connector_type = connector->connector_type; | 1669 | out_resp->connector_type = connector->connector_type; |
@@ -1666,6 +1685,9 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
1666 | copied = 0; | 1685 | copied = 0; |
1667 | mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; | 1686 | mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; |
1668 | list_for_each_entry(mode, &connector->modes, head) { | 1687 | list_for_each_entry(mode, &connector->modes, head) { |
1688 | if (!drm_mode_expose_to_userspace(mode, file_priv)) | ||
1689 | continue; | ||
1690 | |||
1669 | drm_crtc_convert_to_umode(&u_mode, mode); | 1691 | drm_crtc_convert_to_umode(&u_mode, mode); |
1670 | if (copy_to_user(mode_ptr + copied, | 1692 | if (copy_to_user(mode_ptr + copied, |
1671 | &u_mode, sizeof(u_mode))) { | 1693 | &u_mode, sizeof(u_mode))) { |
@@ -1735,7 +1757,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, | |||
1735 | obj = drm_mode_object_find(dev, enc_resp->encoder_id, | 1757 | obj = drm_mode_object_find(dev, enc_resp->encoder_id, |
1736 | DRM_MODE_OBJECT_ENCODER); | 1758 | DRM_MODE_OBJECT_ENCODER); |
1737 | if (!obj) { | 1759 | if (!obj) { |
1738 | ret = -EINVAL; | 1760 | ret = -ENOENT; |
1739 | goto out; | 1761 | goto out; |
1740 | } | 1762 | } |
1741 | encoder = obj_to_encoder(obj); | 1763 | encoder = obj_to_encoder(obj); |
@@ -2040,6 +2062,45 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) | |||
2040 | } | 2062 | } |
2041 | EXPORT_SYMBOL(drm_mode_set_config_internal); | 2063 | EXPORT_SYMBOL(drm_mode_set_config_internal); |
2042 | 2064 | ||
2065 | /* | ||
2066 | * Checks that the framebuffer is big enough for the CRTC viewport | ||
2067 | * (x, y, hdisplay, vdisplay) | ||
2068 | */ | ||
2069 | static int drm_crtc_check_viewport(const struct drm_crtc *crtc, | ||
2070 | int x, int y, | ||
2071 | const struct drm_display_mode *mode, | ||
2072 | const struct drm_framebuffer *fb) | ||
2073 | |||
2074 | { | ||
2075 | int hdisplay, vdisplay; | ||
2076 | |||
2077 | hdisplay = mode->hdisplay; | ||
2078 | vdisplay = mode->vdisplay; | ||
2079 | |||
2080 | if (drm_mode_is_stereo(mode)) { | ||
2081 | struct drm_display_mode adjusted = *mode; | ||
2082 | |||
2083 | drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE); | ||
2084 | hdisplay = adjusted.crtc_hdisplay; | ||
2085 | vdisplay = adjusted.crtc_vdisplay; | ||
2086 | } | ||
2087 | |||
2088 | if (crtc->invert_dimensions) | ||
2089 | swap(hdisplay, vdisplay); | ||
2090 | |||
2091 | if (hdisplay > fb->width || | ||
2092 | vdisplay > fb->height || | ||
2093 | x > fb->width - hdisplay || | ||
2094 | y > fb->height - vdisplay) { | ||
2095 | DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", | ||
2096 | fb->width, fb->height, hdisplay, vdisplay, x, y, | ||
2097 | crtc->invert_dimensions ? " (inverted)" : ""); | ||
2098 | return -ENOSPC; | ||
2099 | } | ||
2100 | |||
2101 | return 0; | ||
2102 | } | ||
2103 | |||
2043 | /** | 2104 | /** |
2044 | * drm_mode_setcrtc - set CRTC configuration | 2105 | * drm_mode_setcrtc - set CRTC configuration |
2045 | * @dev: drm device for the ioctl | 2106 | * @dev: drm device for the ioctl |
@@ -2080,14 +2141,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
2080 | DRM_MODE_OBJECT_CRTC); | 2141 | DRM_MODE_OBJECT_CRTC); |
2081 | if (!obj) { | 2142 | if (!obj) { |
2082 | DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); | 2143 | DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); |
2083 | ret = -EINVAL; | 2144 | ret = -ENOENT; |
2084 | goto out; | 2145 | goto out; |
2085 | } | 2146 | } |
2086 | crtc = obj_to_crtc(obj); | 2147 | crtc = obj_to_crtc(obj); |
2087 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); | 2148 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
2088 | 2149 | ||
2089 | if (crtc_req->mode_valid) { | 2150 | if (crtc_req->mode_valid) { |
2090 | int hdisplay, vdisplay; | ||
2091 | /* If we have a mode we need a framebuffer. */ | 2151 | /* If we have a mode we need a framebuffer. */ |
2092 | /* If we pass -1, set the mode with the currently bound fb */ | 2152 | /* If we pass -1, set the mode with the currently bound fb */ |
2093 | if (crtc_req->fb_id == -1) { | 2153 | if (crtc_req->fb_id == -1) { |
@@ -2104,7 +2164,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
2104 | if (!fb) { | 2164 | if (!fb) { |
2105 | DRM_DEBUG_KMS("Unknown FB ID%d\n", | 2165 | DRM_DEBUG_KMS("Unknown FB ID%d\n", |
2106 | crtc_req->fb_id); | 2166 | crtc_req->fb_id); |
2107 | ret = -EINVAL; | 2167 | ret = -ENOENT; |
2108 | goto out; | 2168 | goto out; |
2109 | } | 2169 | } |
2110 | } | 2170 | } |
@@ -2123,23 +2183,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
2123 | 2183 | ||
2124 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); | 2184 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
2125 | 2185 | ||
2126 | hdisplay = mode->hdisplay; | 2186 | ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y, |
2127 | vdisplay = mode->vdisplay; | 2187 | mode, fb); |
2128 | 2188 | if (ret) | |
2129 | if (crtc->invert_dimensions) | ||
2130 | swap(hdisplay, vdisplay); | ||
2131 | |||
2132 | if (hdisplay > fb->width || | ||
2133 | vdisplay > fb->height || | ||
2134 | crtc_req->x > fb->width - hdisplay || | ||
2135 | crtc_req->y > fb->height - vdisplay) { | ||
2136 | DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", | ||
2137 | fb->width, fb->height, | ||
2138 | hdisplay, vdisplay, crtc_req->x, crtc_req->y, | ||
2139 | crtc->invert_dimensions ? " (inverted)" : ""); | ||
2140 | ret = -ENOSPC; | ||
2141 | goto out; | 2189 | goto out; |
2142 | } | 2190 | |
2143 | } | 2191 | } |
2144 | 2192 | ||
2145 | if (crtc_req->count_connectors == 0 && mode) { | 2193 | if (crtc_req->count_connectors == 0 && mode) { |
@@ -2184,7 +2232,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
2184 | if (!obj) { | 2232 | if (!obj) { |
2185 | DRM_DEBUG_KMS("Connector id %d unknown\n", | 2233 | DRM_DEBUG_KMS("Connector id %d unknown\n", |
2186 | out_id); | 2234 | out_id); |
2187 | ret = -EINVAL; | 2235 | ret = -ENOENT; |
2188 | goto out; | 2236 | goto out; |
2189 | } | 2237 | } |
2190 | connector = obj_to_connector(obj); | 2238 | connector = obj_to_connector(obj); |
@@ -2232,7 +2280,7 @@ static int drm_mode_cursor_common(struct drm_device *dev, | |||
2232 | obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); | 2280 | obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); |
2233 | if (!obj) { | 2281 | if (!obj) { |
2234 | DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); | 2282 | DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); |
2235 | return -EINVAL; | 2283 | return -ENOENT; |
2236 | } | 2284 | } |
2237 | crtc = obj_to_crtc(obj); | 2285 | crtc = obj_to_crtc(obj); |
2238 | 2286 | ||
@@ -2441,6 +2489,8 @@ static int format_check(const struct drm_mode_fb_cmd2 *r) | |||
2441 | case DRM_FORMAT_YVU444: | 2489 | case DRM_FORMAT_YVU444: |
2442 | return 0; | 2490 | return 0; |
2443 | default: | 2491 | default: |
2492 | DRM_DEBUG_KMS("invalid pixel format %s\n", | ||
2493 | drm_get_format_name(r->pixel_format)); | ||
2444 | return -EINVAL; | 2494 | return -EINVAL; |
2445 | } | 2495 | } |
2446 | } | 2496 | } |
@@ -2606,7 +2656,7 @@ fail_lookup: | |||
2606 | mutex_unlock(&dev->mode_config.fb_lock); | 2656 | mutex_unlock(&dev->mode_config.fb_lock); |
2607 | mutex_unlock(&file_priv->fbs_lock); | 2657 | mutex_unlock(&file_priv->fbs_lock); |
2608 | 2658 | ||
2609 | return -EINVAL; | 2659 | return -ENOENT; |
2610 | } | 2660 | } |
2611 | 2661 | ||
2612 | /** | 2662 | /** |
@@ -2634,7 +2684,7 @@ int drm_mode_getfb(struct drm_device *dev, | |||
2634 | 2684 | ||
2635 | fb = drm_framebuffer_lookup(dev, r->fb_id); | 2685 | fb = drm_framebuffer_lookup(dev, r->fb_id); |
2636 | if (!fb) | 2686 | if (!fb) |
2637 | return -EINVAL; | 2687 | return -ENOENT; |
2638 | 2688 | ||
2639 | r->height = fb->height; | 2689 | r->height = fb->height; |
2640 | r->width = fb->width; | 2690 | r->width = fb->width; |
@@ -2679,7 +2729,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | |||
2679 | 2729 | ||
2680 | fb = drm_framebuffer_lookup(dev, r->fb_id); | 2730 | fb = drm_framebuffer_lookup(dev, r->fb_id); |
2681 | if (!fb) | 2731 | if (!fb) |
2682 | return -EINVAL; | 2732 | return -ENOENT; |
2683 | 2733 | ||
2684 | num_clips = r->num_clips; | 2734 | num_clips = r->num_clips; |
2685 | clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; | 2735 | clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; |
@@ -3011,7 +3061,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3011 | drm_modeset_lock_all(dev); | 3061 | drm_modeset_lock_all(dev); |
3012 | obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); | 3062 | obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); |
3013 | if (!obj) { | 3063 | if (!obj) { |
3014 | ret = -EINVAL; | 3064 | ret = -ENOENT; |
3015 | goto done; | 3065 | goto done; |
3016 | } | 3066 | } |
3017 | property = obj_to_property(obj); | 3067 | property = obj_to_property(obj); |
@@ -3140,7 +3190,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, | |||
3140 | drm_modeset_lock_all(dev); | 3190 | drm_modeset_lock_all(dev); |
3141 | obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); | 3191 | obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); |
3142 | if (!obj) { | 3192 | if (!obj) { |
3143 | ret = -EINVAL; | 3193 | ret = -ENOENT; |
3144 | goto done; | 3194 | goto done; |
3145 | } | 3195 | } |
3146 | blob = obj_to_blob(obj); | 3196 | blob = obj_to_blob(obj); |
@@ -3301,7 +3351,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | |||
3301 | 3351 | ||
3302 | obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); | 3352 | obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); |
3303 | if (!obj) { | 3353 | if (!obj) { |
3304 | ret = -EINVAL; | 3354 | ret = -ENOENT; |
3305 | goto out; | 3355 | goto out; |
3306 | } | 3356 | } |
3307 | if (!obj->properties) { | 3357 | if (!obj->properties) { |
@@ -3354,8 +3404,10 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | |||
3354 | drm_modeset_lock_all(dev); | 3404 | drm_modeset_lock_all(dev); |
3355 | 3405 | ||
3356 | arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); | 3406 | arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); |
3357 | if (!arg_obj) | 3407 | if (!arg_obj) { |
3408 | ret = -ENOENT; | ||
3358 | goto out; | 3409 | goto out; |
3410 | } | ||
3359 | if (!arg_obj->properties) | 3411 | if (!arg_obj->properties) |
3360 | goto out; | 3412 | goto out; |
3361 | 3413 | ||
@@ -3368,8 +3420,10 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | |||
3368 | 3420 | ||
3369 | prop_obj = drm_mode_object_find(dev, arg->prop_id, | 3421 | prop_obj = drm_mode_object_find(dev, arg->prop_id, |
3370 | DRM_MODE_OBJECT_PROPERTY); | 3422 | DRM_MODE_OBJECT_PROPERTY); |
3371 | if (!prop_obj) | 3423 | if (!prop_obj) { |
3424 | ret = -ENOENT; | ||
3372 | goto out; | 3425 | goto out; |
3426 | } | ||
3373 | property = obj_to_property(prop_obj); | 3427 | property = obj_to_property(prop_obj); |
3374 | 3428 | ||
3375 | if (!drm_property_change_is_valid(property, arg->value)) | 3429 | if (!drm_property_change_is_valid(property, arg->value)) |
@@ -3454,7 +3508,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, | |||
3454 | drm_modeset_lock_all(dev); | 3508 | drm_modeset_lock_all(dev); |
3455 | obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); | 3509 | obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); |
3456 | if (!obj) { | 3510 | if (!obj) { |
3457 | ret = -EINVAL; | 3511 | ret = -ENOENT; |
3458 | goto out; | 3512 | goto out; |
3459 | } | 3513 | } |
3460 | crtc = obj_to_crtc(obj); | 3514 | crtc = obj_to_crtc(obj); |
@@ -3513,7 +3567,7 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, | |||
3513 | drm_modeset_lock_all(dev); | 3567 | drm_modeset_lock_all(dev); |
3514 | obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); | 3568 | obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); |
3515 | if (!obj) { | 3569 | if (!obj) { |
3516 | ret = -EINVAL; | 3570 | ret = -ENOENT; |
3517 | goto out; | 3571 | goto out; |
3518 | } | 3572 | } |
3519 | crtc = obj_to_crtc(obj); | 3573 | crtc = obj_to_crtc(obj); |
@@ -3556,7 +3610,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
3556 | struct drm_framebuffer *fb = NULL, *old_fb = NULL; | 3610 | struct drm_framebuffer *fb = NULL, *old_fb = NULL; |
3557 | struct drm_pending_vblank_event *e = NULL; | 3611 | struct drm_pending_vblank_event *e = NULL; |
3558 | unsigned long flags; | 3612 | unsigned long flags; |
3559 | int hdisplay, vdisplay; | ||
3560 | int ret = -EINVAL; | 3613 | int ret = -EINVAL; |
3561 | 3614 | ||
3562 | if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || | 3615 | if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || |
@@ -3568,7 +3621,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
3568 | 3621 | ||
3569 | obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); | 3622 | obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); |
3570 | if (!obj) | 3623 | if (!obj) |
3571 | return -EINVAL; | 3624 | return -ENOENT; |
3572 | crtc = obj_to_crtc(obj); | 3625 | crtc = obj_to_crtc(obj); |
3573 | 3626 | ||
3574 | mutex_lock(&crtc->mutex); | 3627 | mutex_lock(&crtc->mutex); |
@@ -3585,25 +3638,14 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
3585 | goto out; | 3638 | goto out; |
3586 | 3639 | ||
3587 | fb = drm_framebuffer_lookup(dev, page_flip->fb_id); | 3640 | fb = drm_framebuffer_lookup(dev, page_flip->fb_id); |
3588 | if (!fb) | 3641 | if (!fb) { |
3642 | ret = -ENOENT; | ||
3589 | goto out; | 3643 | goto out; |
3644 | } | ||
3590 | 3645 | ||
3591 | hdisplay = crtc->mode.hdisplay; | 3646 | ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb); |
3592 | vdisplay = crtc->mode.vdisplay; | 3647 | if (ret) |
3593 | |||
3594 | if (crtc->invert_dimensions) | ||
3595 | swap(hdisplay, vdisplay); | ||
3596 | |||
3597 | if (hdisplay > fb->width || | ||
3598 | vdisplay > fb->height || | ||
3599 | crtc->x > fb->width - hdisplay || | ||
3600 | crtc->y > fb->height - vdisplay) { | ||
3601 | DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", | ||
3602 | fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y, | ||
3603 | crtc->invert_dimensions ? " (inverted)" : ""); | ||
3604 | ret = -ENOSPC; | ||
3605 | goto out; | 3648 | goto out; |
3606 | } | ||
3607 | 3649 | ||
3608 | if (crtc->fb->pixel_format != fb->pixel_format) { | 3650 | if (crtc->fb->pixel_format != fb->pixel_format) { |
3609 | DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n"); | 3651 | DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n"); |
@@ -3788,7 +3830,8 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, | |||
3788 | *bpp = 32; | 3830 | *bpp = 32; |
3789 | break; | 3831 | break; |
3790 | default: | 3832 | default: |
3791 | DRM_DEBUG_KMS("unsupported pixel format\n"); | 3833 | DRM_DEBUG_KMS("unsupported pixel format %s\n", |
3834 | drm_get_format_name(format)); | ||
3792 | *depth = 0; | 3835 | *depth = 0; |
3793 | *bpp = 0; | 3836 | *bpp = 0; |
3794 | break; | 3837 | break; |