diff options
| -rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 12854ac9d542..a619f120f801 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c | |||
| @@ -1142,7 +1142,7 @@ static int vop_create_crtc(struct vop *vop) | |||
| 1142 | const struct vop_data *vop_data = vop->data; | 1142 | const struct vop_data *vop_data = vop->data; |
| 1143 | struct device *dev = vop->dev; | 1143 | struct device *dev = vop->dev; |
| 1144 | struct drm_device *drm_dev = vop->drm_dev; | 1144 | struct drm_device *drm_dev = vop->drm_dev; |
| 1145 | struct drm_plane *primary = NULL, *cursor = NULL, *plane; | 1145 | struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp; |
| 1146 | struct drm_crtc *crtc = &vop->crtc; | 1146 | struct drm_crtc *crtc = &vop->crtc; |
| 1147 | struct device_node *port; | 1147 | struct device_node *port; |
| 1148 | int ret; | 1148 | int ret; |
| @@ -1182,7 +1182,7 @@ static int vop_create_crtc(struct vop *vop) | |||
| 1182 | ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, | 1182 | ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, |
| 1183 | &vop_crtc_funcs, NULL); | 1183 | &vop_crtc_funcs, NULL); |
| 1184 | if (ret) | 1184 | if (ret) |
| 1185 | return ret; | 1185 | goto err_cleanup_planes; |
| 1186 | 1186 | ||
| 1187 | drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs); | 1187 | drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs); |
| 1188 | 1188 | ||
| @@ -1215,6 +1215,7 @@ static int vop_create_crtc(struct vop *vop) | |||
| 1215 | if (!port) { | 1215 | if (!port) { |
| 1216 | DRM_ERROR("no port node found in %s\n", | 1216 | DRM_ERROR("no port node found in %s\n", |
| 1217 | dev->of_node->full_name); | 1217 | dev->of_node->full_name); |
| 1218 | ret = -ENOENT; | ||
| 1218 | goto err_cleanup_crtc; | 1219 | goto err_cleanup_crtc; |
| 1219 | } | 1220 | } |
| 1220 | 1221 | ||
| @@ -1228,7 +1229,8 @@ static int vop_create_crtc(struct vop *vop) | |||
| 1228 | err_cleanup_crtc: | 1229 | err_cleanup_crtc: |
| 1229 | drm_crtc_cleanup(crtc); | 1230 | drm_crtc_cleanup(crtc); |
| 1230 | err_cleanup_planes: | 1231 | err_cleanup_planes: |
| 1231 | list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head) | 1232 | list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, |
| 1233 | head) | ||
| 1232 | drm_plane_cleanup(plane); | 1234 | drm_plane_cleanup(plane); |
| 1233 | return ret; | 1235 | return ret; |
| 1234 | } | 1236 | } |
| @@ -1236,9 +1238,28 @@ err_cleanup_planes: | |||
| 1236 | static void vop_destroy_crtc(struct vop *vop) | 1238 | static void vop_destroy_crtc(struct vop *vop) |
| 1237 | { | 1239 | { |
| 1238 | struct drm_crtc *crtc = &vop->crtc; | 1240 | struct drm_crtc *crtc = &vop->crtc; |
| 1241 | struct drm_device *drm_dev = vop->drm_dev; | ||
| 1242 | struct drm_plane *plane, *tmp; | ||
| 1239 | 1243 | ||
| 1240 | rockchip_unregister_crtc_funcs(crtc); | 1244 | rockchip_unregister_crtc_funcs(crtc); |
| 1241 | of_node_put(crtc->port); | 1245 | of_node_put(crtc->port); |
| 1246 | |||
| 1247 | /* | ||
| 1248 | * We need to cleanup the planes now. Why? | ||
| 1249 | * | ||
| 1250 | * The planes are "&vop->win[i].base". That means the memory is | ||
| 1251 | * all part of the big "struct vop" chunk of memory. That memory | ||
| 1252 | * was devm allocated and associated with this component. We need to | ||
| 1253 | * free it ourselves before vop_unbind() finishes. | ||
| 1254 | */ | ||
| 1255 | list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, | ||
| 1256 | head) | ||
| 1257 | vop_plane_destroy(plane); | ||
| 1258 | |||
| 1259 | /* | ||
| 1260 | * Destroy CRTC after vop_plane_destroy() since vop_disable_plane() | ||
| 1261 | * references the CRTC. | ||
| 1262 | */ | ||
| 1242 | drm_crtc_cleanup(crtc); | 1263 | drm_crtc_cleanup(crtc); |
| 1243 | } | 1264 | } |
| 1244 | 1265 | ||
