diff options
46 files changed, 2268 insertions, 1150 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e79577cb4665..d7a8370e3cdc 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
| @@ -1319,6 +1319,9 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out, | |||
| 1319 | if (in->clock > INT_MAX || in->vrefresh > INT_MAX) | 1319 | if (in->clock > INT_MAX || in->vrefresh > INT_MAX) |
| 1320 | return -ERANGE; | 1320 | return -ERANGE; |
| 1321 | 1321 | ||
| 1322 | if ((in->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX) | ||
| 1323 | return -EINVAL; | ||
| 1324 | |||
| 1322 | out->clock = in->clock; | 1325 | out->clock = in->clock; |
| 1323 | out->hdisplay = in->hdisplay; | 1326 | out->hdisplay = in->hdisplay; |
| 1324 | out->hsync_start = in->hsync_start; | 1327 | out->hsync_start = in->hsync_start; |
| @@ -1581,6 +1584,19 @@ out: | |||
| 1581 | return ret; | 1584 | return ret; |
| 1582 | } | 1585 | } |
| 1583 | 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 | |||
| 1584 | /** | 1600 | /** |
| 1585 | * drm_mode_getconnector - get connector configuration | 1601 | * drm_mode_getconnector - get connector configuration |
| 1586 | * @dev: drm device for the ioctl | 1602 | * @dev: drm device for the ioctl |
| @@ -1646,7 +1662,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
| 1646 | 1662 | ||
| 1647 | /* delayed so we get modes regardless of pre-fill_modes state */ | 1663 | /* delayed so we get modes regardless of pre-fill_modes state */ |
| 1648 | list_for_each_entry(mode, &connector->modes, head) | 1664 | list_for_each_entry(mode, &connector->modes, head) |
| 1649 | mode_count++; | 1665 | if (drm_mode_expose_to_userspace(mode, file_priv)) |
| 1666 | mode_count++; | ||
| 1650 | 1667 | ||
| 1651 | out_resp->connector_id = connector->base.id; | 1668 | out_resp->connector_id = connector->base.id; |
| 1652 | out_resp->connector_type = connector->connector_type; | 1669 | out_resp->connector_type = connector->connector_type; |
| @@ -1668,6 +1685,9 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
| 1668 | copied = 0; | 1685 | copied = 0; |
| 1669 | 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; |
| 1670 | 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 | |||
| 1671 | drm_crtc_convert_to_umode(&u_mode, mode); | 1691 | drm_crtc_convert_to_umode(&u_mode, mode); |
| 1672 | if (copy_to_user(mode_ptr + copied, | 1692 | if (copy_to_user(mode_ptr + copied, |
| 1673 | &u_mode, sizeof(u_mode))) { | 1693 | &u_mode, sizeof(u_mode))) { |
| @@ -2042,6 +2062,45 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) | |||
| 2042 | } | 2062 | } |
| 2043 | EXPORT_SYMBOL(drm_mode_set_config_internal); | 2063 | EXPORT_SYMBOL(drm_mode_set_config_internal); |
| 2044 | 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 | |||
| 2045 | /** | 2104 | /** |
| 2046 | * drm_mode_setcrtc - set CRTC configuration | 2105 | * drm_mode_setcrtc - set CRTC configuration |
| 2047 | * @dev: drm device for the ioctl | 2106 | * @dev: drm device for the ioctl |
| @@ -2089,7 +2148,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
| 2089 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); | 2148 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
| 2090 | 2149 | ||
| 2091 | if (crtc_req->mode_valid) { | 2150 | if (crtc_req->mode_valid) { |
| 2092 | int hdisplay, vdisplay; | ||
| 2093 | /* If we have a mode we need a framebuffer. */ | 2151 | /* If we have a mode we need a framebuffer. */ |
| 2094 | /* 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 */ |
| 2095 | if (crtc_req->fb_id == -1) { | 2153 | if (crtc_req->fb_id == -1) { |
| @@ -2125,23 +2183,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
| 2125 | 2183 | ||
| 2126 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); | 2184 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
