aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c189
1 files changed, 138 insertions, 51 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 960ca987c20f..d8b7099abece 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -121,6 +121,13 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] =
121 121
122DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) 122DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
123 123
124static const struct drm_prop_enum_list drm_plane_type_enum_list[] =
125{
126 { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
127 { DRM_PLANE_TYPE_PRIMARY, "Primary" },
128 { DRM_PLANE_TYPE_CURSOR, "Cursor" },
129};
130
124/* 131/*
125 * Optional properties 132 * Optional properties
126 */ 133 */
@@ -662,7 +669,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
662 drm_modeset_lock_all(dev); 669 drm_modeset_lock_all(dev);
663 /* remove from any CRTC */ 670 /* remove from any CRTC */
664 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 671 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
665 if (crtc->fb == fb) { 672 if (crtc->primary->fb == fb) {
666 /* should turn off the crtc */ 673 /* should turn off the crtc */
667 memset(&set, 0, sizeof(struct drm_mode_set)); 674 memset(&set, 0, sizeof(struct drm_mode_set));
668 set.crtc = crtc; 675 set.crtc = crtc;
@@ -685,9 +692,12 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
685EXPORT_SYMBOL(drm_framebuffer_remove); 692EXPORT_SYMBOL(drm_framebuffer_remove);
686 693
687/** 694/**
688 * drm_crtc_init - Initialise a new CRTC object 695 * drm_crtc_init_with_planes - Initialise a new CRTC object with
696 * specified primary and cursor planes.
689 * @dev: DRM device 697 * @dev: DRM device
690 * @crtc: CRTC object to init 698 * @crtc: CRTC object to init
699 * @primary: Primary plane for CRTC
700 * @cursor: Cursor plane for CRTC
691 * @funcs: callbacks for the new CRTC 701 * @funcs: callbacks for the new CRTC
692 * 702 *
693 * Inits a new object created as base part of a driver crtc object. 703 * Inits a new object created as base part of a driver crtc object.
@@ -695,8 +705,10 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
695 * Returns: 705 * Returns:
696 * Zero on success, error code on failure. 706 * Zero on success, error code on failure.
697 */ 707 */
698int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, 708int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
699 const struct drm_crtc_funcs *funcs) 709 struct drm_plane *primary,
710 void *cursor,
711 const struct drm_crtc_funcs *funcs)
700{ 712{
701 int ret; 713 int ret;
702 714
@@ -717,12 +729,16 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
717 list_add_tail(&crtc->head, &dev->mode_config.crtc_list); 729 list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
718 dev->mode_config.num_crtc++; 730 dev->mode_config.num_crtc++;
719 731
732 crtc->primary = primary;
733 if (primary)
734 primary->possible_crtcs = 1 << drm_crtc_index(crtc);
735
720 out: 736 out:
721 drm_modeset_unlock_all(dev); 737 drm_modeset_unlock_all(dev);
722 738
723 return ret; 739 return ret;
724} 740}
725EXPORT_SYMBOL(drm_crtc_init); 741EXPORT_SYMBOL(drm_crtc_init_with_planes);
726 742
727/** 743/**
728 * drm_crtc_cleanup - Clean up the core crtc usage 744 * drm_crtc_cleanup - Clean up the core crtc usage
@@ -1000,26 +1016,25 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
1000EXPORT_SYMBOL(drm_encoder_cleanup); 1016EXPORT_SYMBOL(drm_encoder_cleanup);
1001 1017
1002/** 1018/**
1003 * drm_plane_init - Initialise a new plane object 1019 * drm_universal_plane_init - Initialize a new universal plane object
1004 * @dev: DRM device 1020 * @dev: DRM device
1005 * @plane: plane object to init 1021 * @plane: plane object to init
1006 * @possible_crtcs: bitmask of possible CRTCs 1022 * @possible_crtcs: bitmask of possible CRTCs
1007 * @funcs: callbacks for the new plane 1023 * @funcs: callbacks for the new plane
1008 * @formats: array of supported formats (%DRM_FORMAT_*) 1024 * @formats: array of supported formats (%DRM_FORMAT_*)
1009 * @format_count: number of elements in @formats 1025 * @format_count: number of elements in @formats
1010 * @priv: plane is private (hidden from userspace)? 1026 * @type: type of plane (overlay, primary, cursor)
1011 * 1027 *
1012 * Inits a preallocate plane object created as base part of a driver plane 1028 * Initializes a plane object of type @type.
1013 * object.
1014 * 1029 *
1015 * Returns: 1030 * Returns:
1016 * Zero on success, error code on failure. 1031 * Zero on success, error code on failure.
1017 */ 1032 */
1018int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, 1033int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
1019 unsigned long possible_crtcs, 1034 unsigned long possible_crtcs,
1020 const struct drm_plane_funcs *funcs, 1035 const struct drm_plane_funcs *funcs,
1021 const uint32_t *formats, uint32_t format_count, 1036 const uint32_t *formats, uint32_t format_count,
1022 bool priv) 1037 enum drm_plane_type type)
1023{ 1038{
1024 int ret; 1039 int ret;
1025 1040
@@ -1044,23 +1059,53 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
1044 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); 1059 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
1045 plane->format_count = format_count; 1060 plane->format_count = format_count;
1046 plane->possible_crtcs = possible_crtcs; 1061 plane->possible_crtcs = possible_crtcs;
1062 plane->type = type;
1047 1063
1048 /* private planes are not exposed to userspace, but depending on 1064 list_add_tail(&plane->head, &dev->mode_config.plane_list);
1049 * display hardware, might be convenient to allow sharing programming 1065 dev->mode_config.num_total_plane++;
1050 * for the scanout engine with the crtc implementation. 1066 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
1051 */ 1067 dev->mode_config.num_overlay_plane++;
1052 if (!priv) { 1068
1053 list_add_tail(&plane->head, &dev->mode_config.plane_list); 1069 drm_object_attach_property(&plane->base,
1054 dev->mode_config.num_plane++; 1070 dev->mode_config.plane_type_property,
1055 } else { 1071 plane->type);
1056 INIT_LIST_HEAD(&plane->head);
1057 }
1058 1072
1059 out: 1073 out:
1060 drm_modeset_unlock_all(dev); 1074 drm_modeset_unlock_all(dev);
1061 1075
1062 return ret; 1076 return ret;
1063} 1077}
1078EXPORT_SYMBOL(drm_universal_plane_init);
1079
1080/**
1081 * drm_plane_init - Initialize a legacy plane
1082 * @dev: DRM device
1083 * @plane: plane object to init
1084 * @possible_crtcs: bitmask of possible CRTCs
1085 * @funcs: callbacks for the new plane
1086 * @formats: array of supported formats (%DRM_FORMAT_*)
1087 * @format_count: number of elements in @formats
1088 * @is_primary: plane type (primary vs overlay)
1089 *
1090 * Legacy API to initialize a DRM plane.
1091 *
1092 * New drivers should call drm_universal_plane_init() instead.
1093 *
1094 * Returns:
1095 * Zero on success, error code on failure.
1096 */
1097int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
1098 unsigned long possible_crtcs,
1099 const struct drm_plane_funcs *funcs,
1100 const uint32_t *formats, uint32_t format_count,
1101 bool is_primary)
1102{
1103 enum drm_plane_type type;
1104
1105 type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
1106 return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
1107 formats, format_count, type);
1108}
1064EXPORT_SYMBOL(drm_plane_init); 1109EXPORT_SYMBOL(drm_plane_init);
1065 1110
1066/** 1111/**
@@ -1078,11 +1123,13 @@ void drm_plane_cleanup(struct drm_plane *plane)
1078 drm_modeset_lock_all(dev); 1123 drm_modeset_lock_all(dev);
1079 kfree(plane->format_types); 1124 kfree(plane->format_types);
1080 drm_mode_object_put(dev, &plane->base); 1125 drm_mode_object_put(dev, &plane->base);
1081 /* if not added to a list, it must be a private plane */ 1126
1082 if (!list_empty(&plane->head)) { 1127 BUG_ON(list_empty(&plane->head));
1083 list_del(&plane->head); 1128
1084 dev->mode_config.num_plane--; 1129 list_del(&plane->head);
1085 } 1130 dev->mode_config.num_total_plane--;
1131 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
1132 dev->mode_config.num_overlay_plane--;
1086 drm_modeset_unlock_all(dev); 1133 drm_modeset_unlock_all(dev);
1087} 1134}
1088EXPORT_SYMBOL(drm_plane_cleanup); 1135EXPORT_SYMBOL(drm_plane_cleanup);
@@ -1134,6 +1181,21 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
1134 return 0; 1181 return 0;
1135} 1182}
1136 1183
1184static int drm_mode_create_standard_plane_properties(struct drm_device *dev)
1185{
1186 struct drm_property *type;
1187
1188 /*
1189 * Standard properties (apply to all planes)
1190 */
1191 type = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1192 "type", drm_plane_type_enum_list,
1193 ARRAY_SIZE(drm_plane_type_enum_list));
1194 dev->mode_config.plane_type_property = type;
1195
1196 return 0;
1197}
1198
1137/** 1199/**
1138 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties 1200 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
1139 * @dev: DRM device 1201 * @dev: DRM device
@@ -1652,8 +1714,8 @@ int drm_mode_getcrtc(struct drm_device *dev,
1652 crtc_resp->x = crtc->x; 1714 crtc_resp->x = crtc->x;
1653 crtc_resp->y = crtc->y; 1715 crtc_resp->y = crtc->y;
1654 crtc_resp->gamma_size = crtc->gamma_size; 1716 crtc_resp->gamma_size = crtc->gamma_size;
1655 if (crtc->fb) 1717 if (crtc->primary->fb)
1656 crtc_resp->fb_id = crtc->fb->base.id; 1718 crtc_resp->fb_id = crtc->primary->fb->base.id;
1657 else 1719 else
1658 crtc_resp->fb_id = 0; 1720 crtc_resp->fb_id = 0;
1659 1721
@@ -1897,6 +1959,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
1897 struct drm_plane *plane; 1959 struct drm_plane *plane;
1898 uint32_t __user *plane_ptr; 1960 uint32_t __user *plane_ptr;
1899 int copied = 0, ret = 0; 1961 int copied = 0, ret = 0;
1962 unsigned num_planes;
1900 1963
1901 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1964 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1902 return -EINVAL; 1965 return -EINVAL;
@@ -1904,15 +1967,28 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
1904 drm_modeset_lock_all(dev); 1967 drm_modeset_lock_all(dev);
1905 config = &dev->mode_config; 1968 config = &dev->mode_config;
1906 1969
1970 if (file_priv->universal_planes)
1971 num_planes = config->num_total_plane;
1972 else
1973 num_planes = config->num_overlay_plane;
1974
1907 /* 1975 /*
1908 * This ioctl is called twice, once to determine how much space is 1976 * This ioctl is called twice, once to determine how much space is
1909 * needed, and the 2nd time to fill it. 1977 * needed, and the 2nd time to fill it.
1910 */ 1978 */
1911 if (config->num_plane && 1979 if (num_planes &&
1912 (plane_resp->count_planes >= config->num_plane)) { 1980 (plane_resp->count_planes >= num_planes)) {
1913 plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; 1981 plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
1914 1982
1915 list_for_each_entry(plane, &config->plane_list, head) { 1983 list_for_each_entry(plane, &config->plane_list, head) {
1984 /*
1985 * Unless userspace set the 'universal planes'
1986 * capability bit, only advertise overlays.
1987 */
1988 if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
1989 !file_priv->universal_planes)
1990 continue;
1991
1916 if (put_user(plane->base.id, plane_ptr + copied)) { 1992 if (put_user(plane->base.id, plane_ptr + copied)) {
1917 ret = -EFAULT; 1993 ret = -EFAULT;
1918 goto out; 1994 goto out;
@@ -1920,7 +1996,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
1920 copied++; 1996 copied++;
1921 } 1997 }
1922 } 1998 }
1923 plane_resp->count_planes = config->num_plane; 1999 plane_resp->count_planes = num_planes;
1924 2000
1925out: 2001out:
1926 drm_modeset_unlock_all(dev); 2002 drm_modeset_unlock_all(dev);
@@ -2156,19 +2232,21 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
2156 * crtcs. Atomic modeset will have saner semantics ... 2232 * crtcs. Atomic modeset will have saner semantics ...
2157 */ 2233 */
2158 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) 2234 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
2159 tmp->old_fb = tmp->fb; 2235 tmp->old_fb = tmp->primary->fb;
2160 2236
2161 fb = set->fb; 2237 fb = set->fb;
2162 2238
2163 ret = crtc->funcs->set_config(set); 2239 ret = crtc->funcs->set_config(set);
2164 if (ret == 0) { 2240 if (ret == 0) {
2241 crtc->primary->crtc = crtc;
2242
2165 /* crtc->fb must be updated by ->set_config, enforces this. */ 2243 /* crtc->fb must be updated by ->set_config, enforces this. */
2166 WARN_ON(fb != crtc->fb); 2244 WARN_ON(fb != crtc->primary->fb);
2167 } 2245 }
2168 2246
2169 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { 2247 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
2170 if (tmp->fb) 2248 if (tmp->primary->fb)
2171 drm_framebuffer_reference(tmp->fb); 2249 drm_framebuffer_reference(tmp->primary->fb);
2172 if (tmp->old_fb) 2250 if (tmp->old_fb)
2173 drm_framebuffer_unreference(tmp->old_fb); 2251 drm_framebuffer_unreference(tmp->old_fb);
2174 } 2252 }
@@ -2177,14 +2255,19 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
2177} 2255}
2178EXPORT_SYMBOL(drm_mode_set_config_internal); 2256EXPORT_SYMBOL(drm_mode_set_config_internal);
2179 2257
2180/* 2258/**
2181 * Checks that the framebuffer is big enough for the CRTC viewport 2259 * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
2182 * (x, y, hdisplay, vdisplay) 2260 * CRTC viewport
2261 * @crtc: CRTC that framebuffer will be displayed on
2262 * @x: x panning
2263 * @y: y panning
2264 * @mode: mode that framebuffer will be displayed under
2265 * @fb: framebuffer to check size of
2183 */ 2266 */
2184static int drm_crtc_check_viewport(const struct drm_crtc *crtc, 2267int drm_crtc_check_viewport(const struct drm_crtc *crtc,
2185 int x, int y, 2268 int x, int y,
2186 const struct drm_display_mode *mode, 2269 const struct drm_display_mode *mode,
2187 const struct drm_framebuffer *fb) 2270 const struct drm_framebuffer *fb)
2188 2271
2189{ 2272{
2190 int hdisplay, vdisplay; 2273 int hdisplay, vdisplay;
@@ -2215,6 +2298,7 @@ static int drm_crtc_check_viewport(const struct drm_crtc *crtc,
2215 2298
2216 return 0; 2299 return 0;
2217} 2300}
2301EXPORT_SYMBOL(drm_crtc_check_viewport);
2218 2302
2219/** 2303/**
2220 * drm_mode_setcrtc - set CRTC configuration 2304 * drm_mode_setcrtc - set CRTC configuration
@@ -2266,12 +2350,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
2266 /* If we have a mode we need a framebuffer. */ 2350 /* If we have a mode we need a framebuffer. */
2267 /* If we pass -1, set the mode with the currently bound fb */ 2351 /* If we pass -1, set the mode with the currently bound fb */
2268 if (crtc_req->fb_id == -1) { 2352 if (crtc_req->fb_id == -1) {
2269 if (!crtc->fb) { 2353 if (!crtc->primary->fb) {
2270 DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); 2354 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
2271 ret = -EINVAL; 2355 ret = -EINVAL;
2272 goto out; 2356 goto out;
2273 } 2357 }
2274 fb = crtc->fb; 2358 fb = crtc->primary->fb;
2275 /* Make refcounting symmetric with the lookup path. */ 2359 /* Make refcounting symmetric with the lookup path. */
2276 drm_framebuffer_reference(fb); 2360 drm_framebuffer_reference(fb);
2277 } else { 2361 } else {
@@ -4065,7 +4149,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4065 crtc = obj_to_crtc(obj); 4149 crtc = obj_to_crtc(obj);
4066 4150
4067 mutex_lock(&crtc->mutex); 4151 mutex_lock(&crtc->mutex);
4068 if (crtc->fb == NULL) { 4152 if (crtc->primary->fb == NULL) {
4069 /* The framebuffer is currently unbound, presumably 4153 /* The framebuffer is currently unbound, presumably
4070 * due to a hotplug event, that userspace has not 4154 * due to a hotplug event, that userspace has not
4071 * yet discovered. 4155 * yet discovered.
@@ -4087,7 +4171,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4087 if (ret) 4171 if (ret)
4088 goto out; 4172 goto out;
4089 4173
4090 if (crtc->fb->pixel_format != fb->pixel_format) { 4174 if (crtc->primary->fb->pixel_format != fb->pixel_format) {
4091 DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n"); 4175 DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
4092 ret = -EINVAL; 4176 ret = -EINVAL;
4093 goto out; 4177 goto out;
@@ -4120,7 +4204,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4120 (void (*) (struct drm_pending_event *)) kfree; 4204 (void (*) (struct drm_pending_event *)) kfree;
4121 } 4205 }
4122 4206
4123 old_fb = crtc->fb; 4207 old_fb = crtc->primary->fb;
4124 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); 4208 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
4125 if (ret) { 4209 if (ret) {
4126 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 4210 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -4138,7 +4222,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4138 * Failing to do so will screw with the reference counting 4222 * Failing to do so will screw with the reference counting
4139 * on framebuffers. 4223 * on framebuffers.
4140 */ 4224 */
4141 WARN_ON(crtc->fb != fb); 4225 WARN_ON(crtc->primary->fb != fb);
4142 /* Unref only the old framebuffer. */ 4226 /* Unref only the old framebuffer. */
4143 fb = NULL; 4227 fb = NULL;
4144 } 4228 }
@@ -4527,6 +4611,7 @@ void drm_mode_config_init(struct drm_device *dev)
4527 4611
4528 drm_modeset_lock_all(dev); 4612 drm_modeset_lock_all(dev);
4529 drm_mode_create_standard_connector_properties(dev); 4613 drm_mode_create_standard_connector_properties(dev);
4614 drm_mode_create_standard_plane_properties(dev);
4530 drm_modeset_unlock_all(dev); 4615 drm_modeset_unlock_all(dev);
4531 4616
4532 /* Just to be sure */ 4617 /* Just to be sure */
@@ -4534,6 +4619,8 @@ void drm_mode_config_init(struct drm_device *dev)
4534 dev->mode_config.num_connector = 0; 4619 dev->mode_config.num_connector = 0;
4535 dev->mode_config.num_crtc = 0; 4620 dev->mode_config.num_crtc = 0;
4536 dev->mode_config.num_encoder = 0; 4621 dev->mode_config.num_encoder = 0;
4622 dev->mode_config.num_overlay_plane = 0;
4623 dev->mode_config.num_total_plane = 0;
4537} 4624}
4538EXPORT_SYMBOL(drm_mode_config_init); 4625EXPORT_SYMBOL(drm_mode_config_init);
4539 4626