X-Git-Url: http://plrg.eecs.uci.edu/git/?p=firefly-linux-kernel-4.4.55.git;a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fdrm_crtc.c;h=4900d2f76e2494a37fc0940290c55493ae4cfb44;hp=dc84003f694e1bb12d6e72568f15707a76a5b1c7;hb=534c1ca9c257a81dd1b456f9244c1a1bfa0f7af7;hpb=da9a92f0cde9ce34a930d7edcaef30429e41d14a diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index dc84003f694e..4900d2f76e24 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -657,6 +657,7 @@ DEFINE_WW_CLASS(crtc_ww_class); * @primary: Primary plane for CRTC * @cursor: Cursor plane for CRTC * @funcs: callbacks for the new CRTC + * @name: printf style format string for the CRTC name, or NULL for default name * * Inits a new object created as base part of a driver crtc object. * @@ -666,7 +667,8 @@ DEFINE_WW_CLASS(crtc_ww_class); int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, struct drm_plane *cursor, - const struct drm_crtc_funcs *funcs) + const struct drm_crtc_funcs *funcs, + const char *name, ...) { struct drm_mode_config *config = &dev->mode_config; int ret; @@ -1075,6 +1077,7 @@ EXPORT_SYMBOL(drm_connector_unplug_all); * @encoder: the encoder to init * @funcs: callbacks for this encoder * @encoder_type: user visible type of the encoder + * @name: printf style format string for the encoder name, or NULL for default name * * Initialises a preallocated encoder. Encoder should be * subclassed as part of driver encoder objects. @@ -1085,7 +1088,7 @@ EXPORT_SYMBOL(drm_connector_unplug_all); int drm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, const struct drm_encoder_funcs *funcs, - int encoder_type) + int encoder_type, const char *name, ...) { int ret; @@ -1150,6 +1153,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup); * @formats: array of supported formats (%DRM_FORMAT_*) * @format_count: number of elements in @formats * @type: type of plane (overlay, primary, cursor) + * @name: printf style format string for the plane name, or NULL for default name * * Initializes a plane object of type @type. * @@ -1160,7 +1164,8 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, unsigned int format_count, - enum drm_plane_type type) + enum drm_plane_type type, + const char *name, ...) { struct drm_mode_config *config = &dev->mode_config; int ret; @@ -1240,10 +1245,100 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; return drm_universal_plane_init(dev, plane, possible_crtcs, funcs, - formats, format_count, type); + formats, format_count, type, NULL); } EXPORT_SYMBOL(drm_plane_init); +/** + * drm_share_plane_init - Initialize a share plane + * @dev: DRM device + * @plane: plane object to init + * @parent: this plane share some resources with parent plane. + * @possible_crtcs: bitmask of possible CRTCs + * @funcs: callbacks for the new plane + * @formats: array of supported formats (%DRM_FORMAT_*) + * @format_count: number of elements in @formats + * @type: type of plane (overlay, primary, cursor) + * + * With this API, the plane can share hardware resources with other planes. + * + * -------------------------------------------------- + * | scanout | + * | ------------------ | + * | | parent plane | | + * | | active scanout | | + * | | | ----------------- | + * | ------------------ | share plane 1 | | + * | ----------------- |active scanout | | + * | | share plane 0 | | | | + * | |active scanout | ----------------- | + * | | | | + * | ----------------- | + * -------------------------------------------------- + * + * parent plane + * |---share plane 0 + * |---share plane 1 + * ... + * + * The plane hardware is used when the display scanout run into plane active + * scanout, that means we can reuse the plane hardware resources on plane + * non-active scanout. + * + * Because resource share, There are some limit on share plane: one group + * of share planes need use same zpos, can't not overlap, etc. + * + * Here assume share plane is a universal plane with some limit flags. + * people who use the share plane need know the limit, should call the ioctl + * DRM_CLIENT_CAP_SHARE_PLANES, and judge the planes limit before use it. + * + * Returns: + * Zero on success, error code on failure. + */ + +int drm_share_plane_init(struct drm_device *dev, struct drm_plane *plane, + struct drm_plane *parent, + unsigned long possible_crtcs, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, unsigned int format_count, + enum drm_plane_type type) +{ + struct drm_mode_config *config = &dev->mode_config; + int ret; + int share_id; + + /* + * TODO: only verified on ATOMIC drm driver. + */ + if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) + return -EINVAL; + + ret = drm_universal_plane_init(dev, plane, possible_crtcs, funcs, + formats, format_count, type, NULL); + if (ret) + return ret; + + if (parent) { + /* + * Can't support more than two level plane share. + */ + WARN_ON(parent->parent); + share_id = parent->base.id; + plane->parent = parent; + + config->num_share_plane++; + if (plane->type == DRM_PLANE_TYPE_OVERLAY) + config->num_share_overlay_plane++; + } else { + share_id = plane->base.id; + } + + drm_object_attach_property(&plane->base, + config->prop_share_id, share_id); + return 0; +} +EXPORT_SYMBOL(drm_share_plane_init); + /** * drm_plane_cleanup - Clean up the core plane usage * @plane: plane to cleanup @@ -1266,6 +1361,11 @@ void drm_plane_cleanup(struct drm_plane *plane) dev->mode_config.num_total_plane--; if (plane->type == DRM_PLANE_TYPE_OVERLAY) dev->mode_config.num_overlay_plane--; + if (plane->parent) { + dev->mode_config.num_share_plane--; + if (plane->type == DRM_PLANE_TYPE_OVERLAY) + dev->mode_config.num_share_overlay_plane--; + } drm_modeset_unlock_all(dev); WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); @@ -1397,6 +1497,18 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.plane_type_property = prop; + prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, + "SHARE_ID", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + + dev->mode_config.prop_share_id = prop; + prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, + "SHARE_FLAGS", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_share_flags = prop; + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "SRC_X", 0, UINT_MAX); if (!prop) @@ -2203,6 +2315,12 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, num_planes = config->num_total_plane; else num_planes = config->num_overlay_plane; + if (!file_priv->share_planes) { + if (file_priv->universal_planes) + num_planes -= config->num_share_plane; + else + num_planes -= config->num_share_overlay_plane; + } /* * This ioctl is called twice, once to determine how much space is @@ -2221,6 +2339,8 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, if (plane->type != DRM_PLANE_TYPE_OVERLAY && !file_priv->universal_planes) continue; + if (plane->parent && !file_priv->share_planes) + continue; if (put_user(plane->base.id, plane_ptr + copied)) return -EFAULT; @@ -5031,6 +5151,20 @@ int drm_mode_connector_attach_encoder(struct drm_connector *connector, { int i; + /* + * In the past, drivers have attempted to model the static association + * of connector to encoder in simple connector/encoder devices using a + * direct assignment of connector->encoder = encoder. This connection + * is a logical one and the responsibility of the core, so drivers are + * expected not to mess with this. + * + * Note that the error return should've been enough here, but a large + * majority of drivers ignores the return value, so add in a big WARN + * to get people's attention. + */ + if (WARN_ON(connector->encoder)) + return -EINVAL; + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { if (connector->encoder_ids[i] == 0) { connector->encoder_ids[i] = encoder->base.id;