One of the stepping stones on the way to atomic/nuclear operation is to expose all types of hardware planes to userspace via a consistent interface. Until now, the DRM plane interface has only operated on planes that drivers consider "overlay" or "sprite" planes; primary planes were simply represented by extra state hanging off the CRTC, and cursor planes had no direct representation in userspace, but were manipulated via separate ioctl's. This patch set begins the process of unifying the various plane types into a single, consistent interface.
With this patchset, userspace clients that set a DRM_CLIENT_CAP_UNIVERSAL_PLANES client capability bit will receive a full list of all hardware planes, including primary planes and cursor planes, not just the overlay/sprite planes that have historically been returned. Userspace should be able to make drmModeSetPlane() calls against any type of plane and have them operate as expected (to the extent supported by the underlying hardware).
This benefits of this unified interface will be most evident once driver state is fully property-ized as part of the upcoming atomic modeset / nuclear pageflip work. However there are a few benefits that may be achieved even before then: * Drivers for hardware with scaling-capable primary planes may honor userspace scaling requests for the primary plane made with the drmModeSetPlane() call. Previously there was no interface that allowed userspace to specify desired scaling on primary planes. * Drivers for hardware that may disable primary planes independently from the underlying CRTC may now do so when userspace passes a NULL framebuffer to the drmModeSetPlane() interface.
This patchset is organized as follows: - Patch 1 updates the DRM core with the general concept of multiple plane types and prepares for there to be multiple types of planes on the DRM plane list.
- Patch 2 adds a set of primary plane helper functions that drivers may use to quickly support plane operations against primary planes. These helpers implement plane update operations by calling into the driver's modeset interface. These helpers are optional; drivers are free to provide their own implementation.
- Patches 3 and 4 update loops over the DRM plane list in the exynos and i915 drivers to ignore non-overlay planes. This ensures that the behavior of these loops will not change when new plane types show up on the DRM plane list in future patches.
- Patch 5 adds a "plane type" property that allows userspace to identify the types of the planes it receives. Note that we replace the 'priv' parameter to drm_plane_init() with the type that should be used for this property; in doing so, we create the first opportunity for non-overlay planes to appear on the DRM plane list for some drivers ( msm, omap, and imx), although they will not be visible to userspace at this time.
- Patch 6 updates all drivers to call drm_primary_helper_create_plane() before CRTC creation and then pass the resulting plane to drm_crtc_init(). This will create a primary plane via the primary plane helper and add it to the DRM plane list. Note that this is the first time that *all* drivers will have non-overlay planes on their plane list (msm, omap, and imx had their previously-private planes show up in the plane list in patch 5). These non-overlay planes still cannot be exposed to userspace.
- Patch 7 drops the 'fb' field from drm_crtc and switches everything to using crtc->primary->fb instead.
- Patch 8 adds the client capability bit which allows userspace to request the full plane list rather than just the overlay list. This is the first patch that may have a userspace-visible effect.
- Patch 9 is a simple function name update in i915 to avoid confusion.
- Patch 10 replaces the primary plane helper usage in i915 with a custom implementation of primary planes. On Intel hardware, we can disable the primary plane without disabling the entire CRTC; the custom implementation here allows us to avoid that limitation assumed by the helpers.
This patch set is still a work in progress. Specific work that still needs to be done: * Update msm, omap, and imx to properly associate their primary planes with the appropriate CRTC (and stop creating a separate dummy primary plane). At the moment the formerly "private" planes that these drivers use are created as primary planes, but they're never specifically associated with the correct CRTC (i.e., passed at drm_crtc_init()). I think this should be pretty straightforward, but I just haven't had enough time to look through how those drivers are structured yet to make the change. [suggested by Rob Clark]
* Add cursor plane implementation. The general infrastructure necessary to support cursors is present, but no default helpers exist yet and no driver actually registers any cursor planes.
* Add extra read-only plane properties to inform userspace of what a plane's true limitations and capabilities are. Although the "plane type" property is probably enough to get by with something like a driver-specific DDX in userspace, hardware-independent userspace like Weston will need more information about what can and can't be done with each plane. This is especially important for cursor planes since they can largely be viewed as additional overlay planes that just have some extra limitations attached.
* Disallow usage of legacy cursor interfaces by clients that request universal plane support. Make the new, unified interface the only interface for clients that can support it. [suggested by Ville Syrjälä]
Matt Roper (10): drm: Add support for multiple plane types drm: Add primary plane helpers drm/exynos: Restrict plane loops to only operate on overlay planes drm/i915: Restrict plane loops to only operate on overlay planes drm: Add plane type property drm: Specify primary plane at CRTC initialization drm: Replace crtc fb with primary plane fb drm: Allow userspace to ask for full plane list (universal planes) drm/i915: Rename similar plane functions to avoid confusion drm/i915: Intel-specific primary plane handling
drivers/gpu/drm/armada/armada_crtc.c | 4 +- drivers/gpu/drm/armada/armada_overlay.c | 3 +- drivers/gpu/drm/ast/ast_mode.c | 4 +- drivers/gpu/drm/bochs/bochs_kms.c | 4 +- drivers/gpu/drm/cirrus/cirrus_mode.c | 4 +- drivers/gpu/drm/drm_crtc.c | 447 ++++++++++++++++++++++------ drivers/gpu/drm/drm_crtc_helper.c | 21 +- drivers/gpu/drm/drm_fb_helper.c | 9 +- drivers/gpu/drm/drm_ioctl.c | 5 + drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 6 + drivers/gpu/drm/exynos/exynos_drm_plane.c | 4 +- drivers/gpu/drm/gma500/psb_intel_display.c | 4 +- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 5 +- drivers/gpu/drm/i915/i915_irq.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 238 +++++++++++---- drivers/gpu/drm/i915/intel_dp.c | 5 +- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_overlay.c | 4 +- drivers/gpu/drm/i915/intel_pm.c | 39 +-- drivers/gpu/drm/i915/intel_sprite.c | 2 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 4 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 4 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 3 +- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 24 +- drivers/gpu/drm/nouveau/dispnv04/dfp.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 4 +- drivers/gpu/drm/nouveau/nouveau_display.c | 8 +- drivers/gpu/drm/nouveau/nv50_display.c | 21 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 4 +- drivers/gpu/drm/omapdrm/omap_plane.c | 4 +- drivers/gpu/drm/qxl/qxl_display.c | 4 +- drivers/gpu/drm/radeon/atombios_crtc.c | 20 +- drivers/gpu/drm/radeon/r100.c | 4 +- drivers/gpu/drm/radeon/radeon_connectors.c | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 3 +- drivers/gpu/drm/radeon/radeon_display.c | 8 +- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 16 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 +- drivers/gpu/drm/tegra/dc.c | 7 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +- drivers/gpu/drm/udl/udl_modeset.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 4 +- drivers/staging/imx-drm/imx-drm-core.c | 4 +- drivers/staging/imx-drm/ipuv3-plane.c | 4 +- include/drm/drmP.h | 5 + include/drm/drm_crtc.h | 108 ++++++- include/uapi/drm/drm.h | 8 + 55 files changed, 853 insertions(+), 275 deletions(-)
The DRM core currently only tracks "overlay"-style planes. Start refactoring the plane handling to allow other plane types (primary and cursor) to also be placed on the DRM plane list.
Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/drm_crtc.c | 21 ++++++++++++++++----- drivers/gpu/drm/drm_fb_helper.c | 3 ++- include/drm/drm_crtc.h | 19 ++++++++++++++++++- 3 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 35ea15d..71c7fdc 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -964,6 +964,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); plane->format_count = format_count; plane->possible_crtcs = possible_crtcs; + plane->type = DRM_PLANE_TYPE_OVERLAY;
/* private planes are not exposed to userspace, but depending on * display hardware, might be convenient to allow sharing programming @@ -971,7 +972,9 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, */ if (!priv) { list_add_tail(&plane->head, &dev->mode_config.plane_list); - dev->mode_config.num_plane++; + dev->mode_config.num_total_plane++; + if (plane->type == DRM_PLANE_TYPE_OVERLAY) + dev->mode_config.num_overlay_plane++; } else { INIT_LIST_HEAD(&plane->head); } @@ -1001,7 +1004,9 @@ void drm_plane_cleanup(struct drm_plane *plane) /* if not added to a list, it must be a private plane */ if (!list_empty(&plane->head)) { list_del(&plane->head); - dev->mode_config.num_plane--; + dev->mode_config.num_total_plane--; + if (plane->type == DRM_PLANE_TYPE_OVERLAY) + dev->mode_config.num_overlay_plane--; } drm_modeset_unlock_all(dev); } @@ -1849,11 +1854,15 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, * This ioctl is called twice, once to determine how much space is * needed, and the 2nd time to fill it. */ - if (config->num_plane && - (plane_resp->count_planes >= config->num_plane)) { + if (config->num_overlay_plane && + (plane_resp->count_planes >= config->num_overlay_plane)) { plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
list_for_each_entry(plane, &config->plane_list, head) { + /* Only advertise overlays to userspace for now. */ + if (plane->type != DRM_PLANE_TYPE_OVERLAY) + continue; + if (put_user(plane->base.id, plane_ptr + copied)) { ret = -EFAULT; goto out; @@ -1861,7 +1870,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, copied++; } } - plane_resp->count_planes = config->num_plane; + plane_resp->count_planes = config->num_overlay_plane;
out: drm_modeset_unlock_all(dev); @@ -4060,6 +4069,8 @@ void drm_mode_config_init(struct drm_device *dev) dev->mode_config.num_connector = 0; dev->mode_config.num_crtc = 0; dev->mode_config.num_encoder = 0; + dev->mode_config.num_overlay_plane = 0; + dev->mode_config.num_total_plane = 0; } EXPORT_SYMBOL(drm_mode_config_init);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d99df15..fee5759 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -291,7 +291,8 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) drm_warn_on_modeset_not_all_locked(dev);
list_for_each_entry(plane, &dev->mode_config.plane_list, head) - drm_plane_force_disable(plane); + if (plane->type != DRM_PLANE_TYPE_PRIMARY) + drm_plane_force_disable(plane);
for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f764654..80ea77f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -665,6 +665,12 @@ struct drm_plane_funcs { struct drm_property *property, uint64_t val); };
+enum drm_plane_type { + DRM_PLANE_TYPE_OVERLAY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_CURSOR, +}; + /** * drm_plane - central DRM plane control structure * @dev: DRM device this plane belongs to @@ -677,6 +683,7 @@ struct drm_plane_funcs { * @fb: currently bound fb * @funcs: helper functions * @properties: property tracking for this plane + * @type: type of plane (overlay, primary, cursor) */ struct drm_plane { struct drm_device *dev; @@ -694,6 +701,8 @@ struct drm_plane { const struct drm_plane_funcs *funcs;
struct drm_object_properties properties; + + enum drm_plane_type type; };
/** @@ -856,7 +865,15 @@ struct drm_mode_config { struct list_head bridge_list; int num_encoder; struct list_head encoder_list; - int num_plane; + + /* + * Track # of overlay planes separately from # of total planes. By + * default we only advertise overlay planes to userspace; if userspace + * sets the "universal plane" capability bit, we'll go ahead and + * expose all planes. + */ + int num_overlay_plane; + int num_total_plane; struct list_head plane_list;
int num_crtc;
When we expose non-overlay planes to userspace, they will become accessible via standard userspace plane API's. We should be able to handle the standard plane operations against primary planes in a generic way via the page flip handler and modeset handler.
Drivers that can program primary planes more efficiently, that want to use their own primary plane structure to track additional information, or that don't have the limitations assumed by the helpers are free to provide their own implementation of some or all of these handlers.
Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/drm_crtc.c | 293 +++++++++++++++++++++++++++++++++++++++------ include/drm/drm_crtc.h | 81 +++++++++++++ 2 files changed, 335 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 71c7fdc..93fc2dd 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1038,6 +1038,260 @@ void drm_plane_force_disable(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_force_disable);
+/* + * Checks that the framebuffer is big enough for the CRTC viewport + * (x, y, hdisplay, vdisplay) + */ +static int drm_crtc_check_viewport(const struct drm_crtc *crtc, + int x, int y, + const struct drm_display_mode *mode, + const struct drm_framebuffer *fb) + +{ + int hdisplay, vdisplay; + + hdisplay = mode->hdisplay; + vdisplay = mode->vdisplay; + + if (drm_mode_is_stereo(mode)) { + struct drm_display_mode adjusted = *mode; + + drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE); + hdisplay = adjusted.crtc_hdisplay; + vdisplay = adjusted.crtc_vdisplay; + } + + if (crtc->invert_dimensions) + swap(hdisplay, vdisplay); + + if (hdisplay > fb->width || + vdisplay > fb->height || + x > fb->width - hdisplay || + y > fb->height - vdisplay) { + DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", + fb->width, fb->height, hdisplay, vdisplay, x, y, + crtc->invert_dimensions ? " (inverted)" : ""); + return -ENOSPC; + } + + return 0; +} + +/* + * Returns the connectors currently associated with a CRTC. This function + * should be called twice: once with a NULL connector list to retrieve + * the list size, and once with the properly allocated list to be filled in. + */ +static int get_connectors_for_crtc(struct drm_crtc *crtc, + struct drm_connector **connector_list, + int num_connectors) +{ + struct drm_device *dev = crtc->dev; + struct drm_connector *connector; + int count = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + if (connector->encoder && connector->encoder->crtc == crtc) { + if (connector_list != NULL && count < num_connectors) + *(connector_list++) = connector; + + count++; + } + + return count; +} + +/** + * drm_primary_helper_update() - Helper for primary plane update + * @plane: plane object to update + * @crtc: owning CRTC of owning plane + * @fb: framebuffer to flip onto plane + * @crtc_x: x offset of primary plane on crtc + * @crtc_y: y offset of primary plane on crtc + * @crtc_w: width of primary plane rectangle on crtc + * @crtc_h: height of primary plane rectangle on crtc + * @src_x: x offset of @fb for panning + * @src_y: y offset of @fb for panning + * @src_w: width of source rectangle in @fb + * @src_h: height of source rectangle in @fb + * + * Provides a default plane update handler for primary planes. This is handler + * is called in response to a userspace SetPlane operation on the plane with a + * non-NULL framebuffer. We call the driver's pageflip handler to update the + * framebuffer. + * + * SetPlane() on a primary plane of a disabled CRTC is not supported, and will + * return an error. + * + * Note that we assume most hardware can't reposition or scale the primary + * plane, so we require that crtc_x = crtc_y = 0 and that src_w/src_h match the + * current mode. Drivers for hardware that don't have these restrictions can + * provide their own implementation rather than using this helper. + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) +{ + struct drm_mode_set set = { + .crtc = crtc, + .fb = fb, + .mode = &crtc->mode, + .x = crtc_x, + .y = crtc_y, + }; + struct drm_connector **connector_list; + struct drm_framebuffer *tmpfb; + int num_connectors, ret; + + /* setplane API takes shifted source rectangle values; unshift them */ + src_x >>= 16; + src_y >>= 16; + src_w >>= 16; + src_h >>= 16; + + /* Primary planes are locked to their owning CRTC */ + if (plane->possible_crtcs != drm_crtc_mask(crtc)) { + DRM_DEBUG_KMS("Cannot change primary plane CRTC\n"); + return -EINVAL; + } + + if (!crtc->enabled) { + DRM_DEBUG_KMS("Cannot update primary plane of a disabled CRTC.\n"); + return -EINVAL; + } + + if (crtc->funcs->page_flip == NULL) { + DRM_DEBUG_KMS("Driver does not support pageflip\n"); + return -EINVAL; + } + + ret = drm_crtc_check_viewport(crtc, crtc_x, crtc_y, &crtc->mode, fb); + if (ret) + return ret; + + /* Find current connectors for CRTC */ + num_connectors = get_connectors_for_crtc(crtc, NULL, 0); + BUG_ON(num_connectors == 0); + connector_list = kzalloc(num_connectors * sizeof(*connector_list), + GFP_KERNEL); + if (!connector_list) + return -ENOMEM; + get_connectors_for_crtc(crtc, connector_list, num_connectors); + + set.connectors = connector_list; + set.num_connectors = num_connectors; + + /* + * set_config() adjusts crtc->primary->fb; however the DRM setplane + * code that called us expects to handle the framebuffer update and + * reference counting; save and restore the current fb before + * calling it. + */ + tmpfb = plane->fb; + ret = crtc->funcs->set_config(&set); + plane->fb = tmpfb; + + kfree(connector_list); + return ret; +} +EXPORT_SYMBOL(drm_primary_helper_update); + +/** + * drm_primary_helper_disable() - Helper for primary plane disable + * @plane: plane to disable + * + * Provides a default plane disable handler for primary planes. This is handler + * is called in response to a userspace SetPlane operation on the plane with a + * NULL framebuffer parameter. We call the driver's modeset handler with a NULL + * framebuffer to disable the CRTC. + * + * Note that some hardware may be able to disable the primary plane without + * disabling the whole CRTC. Drivers for such hardware should provide their + * own disable handler that disables just the primary plane (and they'll likely + * need to provide their own update handler as well to properly re-enable a + * disabled primary plane). + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_primary_helper_disable(struct drm_plane *plane) +{ + struct drm_mode_set set = { + .crtc = plane->crtc, + .fb = NULL, + }; + + if (plane->crtc == NULL || plane->fb == NULL) + /* Already disabled */ + return 0; + + return plane->crtc->funcs->set_config(&set); +} +EXPORT_SYMBOL(drm_primary_helper_disable); + +/** + * drm_primary_helper_destroy() - Helper for primary plane destruction + * @plane: plane to destroy + * + * Provides a default plane destroy handler for primary planes. This is handler + * is called during CRTC destruction. We disable the primary plane, remove + * it from the DRM plane list, and deallocate the plane structure. + */ +void drm_primary_helper_destroy(struct drm_plane *plane) +{ + plane->funcs->disable_plane(plane); + drm_plane_cleanup(plane); + kfree(plane); +} +EXPORT_SYMBOL(drm_primary_helper_destroy); + +const struct drm_plane_funcs drm_primary_helper_funcs = { + .update_plane = drm_primary_helper_update, + .disable_plane = drm_primary_helper_disable, + .destroy = drm_primary_helper_destroy, +}; +EXPORT_SYMBOL(drm_primary_helper_funcs); + +/** + * drm_primary_helper_create_plane() - Create a generic primary plane + * @dev: drm device + * + * Allocates and initializes a primary plane that can be used with the primary + * plane helpers. Drivers that wish to use driver-specific plane structures or + * provide custom handler functions may perform their own allocation and + * initialization rather than calling this function. + */ +struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev) +{ + struct drm_plane *primary; + int ret; + + primary = kzalloc(sizeof(*primary), GFP_KERNEL); + if (primary == NULL) { + DRM_DEBUG_KMS("Failed to allocate primary plane\n"); + return NULL; + } + + /* possible_crtc's will be filled in later by crtc_init */ + ret = drm_plane_init(dev, primary, 0, &drm_primary_helper_funcs, + legacy_modeset_formats, + ARRAY_SIZE(legacy_modeset_formats), + DRM_PLANE_TYPE_PRIMARY); + if (ret) { + kfree(primary); + primary = NULL; + } + + return primary; +} +EXPORT_SYMBOL(drm_primary_helper_create_plane); + /** * drm_mode_create - create a new display mode * @dev: DRM device @@ -2117,45 +2371,6 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) } EXPORT_SYMBOL(drm_mode_set_config_internal);
-/* - * Checks that the framebuffer is big enough for the CRTC viewport - * (x, y, hdisplay, vdisplay) - */ -static int drm_crtc_check_viewport(const struct drm_crtc *crtc, - int x, int y, - const struct drm_display_mode *mode, - const struct drm_framebuffer *fb) - -{ - int hdisplay, vdisplay; - - hdisplay = mode->hdisplay; - vdisplay = mode->vdisplay; - - if (drm_mode_is_stereo(mode)) { - struct drm_display_mode adjusted = *mode; - - drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE); - hdisplay = adjusted.crtc_hdisplay; - vdisplay = adjusted.crtc_vdisplay; - } - - if (crtc->invert_dimensions) - swap(hdisplay, vdisplay); - - if (hdisplay > fb->width || - vdisplay > fb->height || - x > fb->width - hdisplay || - y > fb->height - vdisplay) { - DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", - fb->width, fb->height, hdisplay, vdisplay, x, y, - crtc->invert_dimensions ? " (inverted)" : ""); - return -ENOSPC; - } - - return 0; -} - /** * drm_mode_setcrtc - set CRTC configuration * @dev: drm device for the ioctl diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 80ea77f..6ecfc9d 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -705,6 +705,87 @@ struct drm_plane { enum drm_plane_type type; };
+extern int drm_primary_helper_update(struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h); +extern int drm_primary_helper_disable(struct drm_plane *plane); +extern void drm_primary_helper_destroy(struct drm_plane *plane); +extern const struct drm_plane_funcs drm_primary_helper_funcs; +extern struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev); + +/* + * This is the list of formats that have historically been accepted by the + * modeset API. The primary plane helpers use this list by default, but + * individual drivers may provide their own primary plane initialization + * that provides a more hw-specific format list. + */ +const static uint32_t legacy_modeset_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_RGB332, + DRM_FORMAT_BGR233, + DRM_FORMAT_XRGB4444, + DRM_FORMAT_XBGR4444, + DRM_FORMAT_RGBX4444, + DRM_FORMAT_BGRX4444, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_ABGR4444, + DRM_FORMAT_RGBA4444, + DRM_FORMAT_BGRA4444, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_RGBX5551, + DRM_FORMAT_BGRX5551, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_BGRA5551, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, + DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBX8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_BGRA8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_RGBX1010102, + DRM_FORMAT_BGRX1010102, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_RGBA1010102, + DRM_FORMAT_BGRA1010102, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_AYUV, + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, + DRM_FORMAT_NV61, + DRM_FORMAT_NV24, + DRM_FORMAT_NV42, + DRM_FORMAT_YUV410, + DRM_FORMAT_YVU410, + DRM_FORMAT_YUV411, + DRM_FORMAT_YVU411, + DRM_FORMAT_YUV420, + DRM_FORMAT_YVU420, + DRM_FORMAT_YUV422, + DRM_FORMAT_YVU422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU444, +}; + /** * drm_bridge_funcs - drm_bridge control functions * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge
Before we add additional types of planes to the DRM plane list, ensure that existing loops over all planes continue to operate only on "overlay" planes and ignore primary & cursor planes.
Cc: Inki Dae inki.dae@samsung.com Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 06f1b2a..2fa2685 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -127,6 +127,9 @@ static void disable_plane_to_crtc(struct drm_device *dev, * (encoder->crtc) */ list_for_each_entry(plane, &dev->mode_config.plane_list, head) { + if (plane->type != DRM_PLANE_TYPE_OVERLAY) + continue; + if (plane->crtc == old_crtc) { /* * do not change below call order. @@ -247,6 +250,9 @@ static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
/* all planes connected to this encoder should be also disabled. */ list_for_each_entry(plane, &dev->mode_config.plane_list, head) { + if (plane->type != DRM_PLANE_TYPE_OVERLAY) + continue; + if (plane->crtc == encoder->crtc) plane->funcs->disable_plane(plane); }
Before we add additional types of planes to the DRM plane list, ensure that existing loops over all planes continue to operate only on "overlay" planes and ignore primary & cursor planes.
Cc: Intel Graphics Development intel-gfx@lists.freedesktop.org Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/i915/intel_display.c | 6 ++++++ drivers/gpu/drm/i915/intel_pm.c | 3 +++ 2 files changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6f15627..53f7c9c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3421,6 +3421,9 @@ static void intel_enable_planes(struct drm_crtc *crtc) struct intel_plane *intel_plane;
list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) + if (intel_plane->base.type != DRM_PLANE_TYPE_OVERLAY) + continue; + if (intel_plane->pipe == pipe) intel_plane_restore(&intel_plane->base); } @@ -3432,6 +3435,9 @@ static void intel_disable_planes(struct drm_crtc *crtc) struct intel_plane *intel_plane;
list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) + if (intel_plane->base.type != DRM_PLANE_TYPE_OVERLAY) + continue; + if (intel_plane->pipe == pipe) intel_plane_disable(&intel_plane->base); } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c8347ae..4a534c4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2129,6 +2129,9 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc, list_for_each_entry(plane, &dev->mode_config.plane_list, head) { struct intel_plane *intel_plane = to_intel_plane(plane);
+ if (plane->type != DRM_PLANE_TYPE_OVERLAY) + continue; + if (intel_plane->pipe == pipe) p->spr = intel_plane->wm;
Add a plane type property to allow userspace to distinguish plane types. The type of the plane will now be established at drm_plane_init() time (replacing the 'priv' parameter previously used).
Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/armada/armada_overlay.c | 3 +- drivers/gpu/drm/drm_crtc.c | 65 ++++++++++++++++++++---------- drivers/gpu/drm/exynos/exynos_drm_plane.c | 4 +- drivers/gpu/drm/i915/intel_sprite.c | 2 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 3 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 4 +- drivers/gpu/drm/omapdrm/omap_plane.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 +- drivers/gpu/drm/tegra/dc.c | 3 +- drivers/staging/imx-drm/ipuv3-plane.c | 4 +- include/drm/drm_crtc.h | 3 +- 13 files changed, 69 insertions(+), 35 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index c5b06fd..ef68c42 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -444,7 +444,8 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) dplane);
drm_plane_init(dev, &dplane->base, crtcs, &armada_plane_funcs, - armada_formats, ARRAY_SIZE(armada_formats), false); + armada_formats, ARRAY_SIZE(armada_formats), + DRM_PLANE_TYPE_OVERLAY);
dplane->prop.colorkey_yr = 0xfefefe00; dplane->prop.colorkey_ug = 0x01010100; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 93fc2dd..5b9b512 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -114,6 +114,15 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] =
DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
+static const struct drm_prop_enum_list drm_plane_type_enum_list[] = +{ + { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, + { DRM_PLANE_TYPE_PRIMARY, "Primary" }, + { DRM_PLANE_TYPE_CURSOR, "Cursor" }, +}; + +DRM_ENUM_NAME_FN(drm_get_plane_type, drm_plane_type_enum_list) + /* * Optional properties */ @@ -928,7 +937,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup); * @funcs: callbacks for the new plane * @formats: array of supported formats (%DRM_FORMAT_*) * @format_count: number of elements in @formats - * @priv: plane is private (hidden from userspace)? + * @type: type of plane (overlay, primary, cursor) * * Inits a new object created as base part of a driver plane object. * @@ -939,7 +948,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, uint32_t format_count, - bool priv) + enum drm_plane_type type) { int ret;
@@ -964,20 +973,16 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); plane->format_count = format_count; plane->possible_crtcs = possible_crtcs; - plane->type = DRM_PLANE_TYPE_OVERLAY; + plane->type = type;
- /* private planes are not exposed to userspace, but depending on - * display hardware, might be convenient to allow sharing programming - * for the scanout engine with the crtc implementation. - */ - if (!priv) { - list_add_tail(&plane->head, &dev->mode_config.plane_list); - dev->mode_config.num_total_plane++; - if (plane->type == DRM_PLANE_TYPE_OVERLAY) - dev->mode_config.num_overlay_plane++; - } else { - INIT_LIST_HEAD(&plane->head); - } + list_add_tail(&plane->head, &dev->mode_config.plane_list); + dev->mode_config.num_total_plane++; + if (plane->type == DRM_PLANE_TYPE_OVERLAY) + dev->mode_config.num_overlay_plane++; + + drm_object_attach_property(&plane->base, + dev->mode_config.plane_type_property, + plane->type);
out: drm_modeset_unlock_all(dev); @@ -1001,13 +1006,13 @@ void drm_plane_cleanup(struct drm_plane *plane) drm_modeset_lock_all(dev); kfree(plane->format_types); drm_mode_object_put(dev, &plane->base); - /* if not added to a list, it must be a private plane */ - if (!list_empty(&plane->head)) { - list_del(&plane->head); - dev->mode_config.num_total_plane--; - if (plane->type == DRM_PLANE_TYPE_OVERLAY) - dev->mode_config.num_overlay_plane--; - } + + BUG_ON(list_empty(&plane->head)); + + list_del(&plane->head); + dev->mode_config.num_total_plane--; + if (plane->type == DRM_PLANE_TYPE_OVERLAY) + dev->mode_config.num_overlay_plane--; drm_modeset_unlock_all(dev); } EXPORT_SYMBOL(drm_plane_cleanup); @@ -1357,6 +1362,21 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) return 0; }
+static int drm_mode_create_standard_plane_properties(struct drm_device *dev) +{ + struct drm_property *type; + + /* + * Standard properties (apply to all planes) + */ + type = drm_property_create_enum(dev, 0, + "TYPE", drm_plane_type_enum_list, + ARRAY_SIZE(drm_plane_type_enum_list)); + dev->mode_config.plane_type_property = type; + + return 0; +} + /** * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties * @dev: DRM device @@ -4277,6 +4297,7 @@ void drm_mode_config_init(struct drm_device *dev)
drm_modeset_lock_all(dev); drm_mode_create_standard_connector_properties(dev); + drm_mode_create_standard_plane_properties(dev); drm_modeset_unlock_all(dev);
/* Just to be sure */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index fcb0652..7943dd3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -263,14 +263,16 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev, { struct exynos_plane *exynos_plane; int err; + enum drm_plane_type type;
exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); if (!exynos_plane) return NULL;
+ type = priv ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; err = drm_plane_init(dev, &exynos_plane->base, possible_crtcs, &exynos_plane_funcs, formats, ARRAY_SIZE(formats), - priv); + type); if (err) { DRM_ERROR("failed to initialize plane\n"); kfree(exynos_plane); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 336ae6c..630485c 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1145,7 +1145,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, plane_formats, num_plane_formats, - false); + DRM_PLANE_TYPE_OVERLAY); if (ret) kfree(intel_plane);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 1e893dd..afa9c67 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -222,6 +222,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, struct drm_plane *plane = NULL; struct mdp4_plane *mdp4_plane; int ret; + enum drm_plane_type type;
mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL); if (!mdp4_plane) { @@ -237,9 +238,10 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats, ARRAY_SIZE(mdp4_plane->formats));
+ type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; drm_plane_init(dev, plane, 0xff, &mdp4_plane_funcs, mdp4_plane->formats, mdp4_plane->nformats, - private_plane); + type);
mdp4_plane_install_properties(plane, &plane->base);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 0ac8bb5..faf179c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -373,9 +373,10 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats, ARRAY_SIZE(mdp5_plane->formats));
+ type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; drm_plane_init(dev, plane, 0xff, &mdp5_plane_funcs, mdp5_plane->formats, mdp5_plane->nformats, - private_plane); + type);
mdp5_plane_install_properties(plane, &plane->base);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index ab03f77..0b4f35d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -276,7 +276,7 @@ nv10_overlay_init(struct drm_device *device)
ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */, &nv10_plane_funcs, - formats, num_formats, false); + formats, num_formats, DRM_PLANE_TYPE_OVERLAY); if (ret) goto err;
@@ -456,7 +456,7 @@ nv04_overlay_init(struct drm_device *device)
ret = drm_plane_init(device, &plane->base, 1 /* single crtc */, &nv04_plane_funcs, - formats, 2, false); + formats, 2, DRM_PLANE_TYPE_OVERLAY); if (ret) goto err;
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 046d5e6..d4179b2 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -384,6 +384,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, struct omap_plane *omap_plane; struct omap_overlay_info *info; int ret; + enum drm_plane_type type;
DBG("%s: priv=%d", plane_names[id], private_plane);
@@ -413,8 +414,9 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, omap_plane->error_irq.irq = omap_plane_error_irq; omap_irq_register(dev, &omap_plane->error_irq);
+ type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs, - omap_plane->formats, omap_plane->nformats, private_plane); + omap_plane->formats, omap_plane->nformats, type);
omap_plane_install_properties(plane, &plane->base);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 3fb69d9..27f1531 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -499,7 +499,8 @@ int rcar_du_planes_register(struct rcar_du_group *rgrp)
ret = drm_plane_init(rcdu->ddev, &plane->plane, crtcs, &rcar_du_plane_funcs, formats, - ARRAY_SIZE(formats), false); + ARRAY_SIZE(formats), + DRM_PLANE_TYPE_OVERLAY); if (ret < 0) return ret;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 060ae03..2b03fff 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -257,7 +257,7 @@ int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index)
ret = drm_plane_init(sdev->ddev, &splane->plane, 1, &shmob_drm_plane_funcs, formats, - ARRAY_SIZE(formats), false); + ARRAY_SIZE(formats), DRM_PLANE_TYPE_OVERLAY);
return ret; } diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 9336006..76e5b22 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -137,7 +137,8 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
err = drm_plane_init(drm, &plane->base, 1 << dc->pipe, &tegra_plane_funcs, plane_formats, - ARRAY_SIZE(plane_formats), false); + ARRAY_SIZE(plane_formats), + DRM_PLANE_TYPE_OVERLAY); if (err < 0) { kfree(plane); return err; diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c index 34b642a..7975369 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.c +++ b/drivers/staging/imx-drm/ipuv3-plane.c @@ -355,6 +355,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, { struct ipu_plane *ipu_plane; int ret; + enum drm_plane_type type;
DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n", dma, dp, possible_crtcs); @@ -369,10 +370,11 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, ipu_plane->dma = dma; ipu_plane->dp_flow = dp;
+ type = priv ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs, &ipu_plane_funcs, ipu_plane_formats, ARRAY_SIZE(ipu_plane_formats), - priv); + type); if (ret) { DRM_ERROR("failed to initialize plane\n"); kfree(ipu_plane); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 6ecfc9d..d8a1dc8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -976,6 +976,7 @@ struct drm_mode_config { struct list_head property_blob_list; struct drm_property *edid_property; struct drm_property *dpms_property; + struct drm_property *plane_type_property;
/* DVI-I properties */ struct drm_property *dvi_i_subconnector_property; @@ -1084,7 +1085,7 @@ extern int drm_plane_init(struct drm_device *dev, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, uint32_t format_count, - bool priv); + enum drm_plane_type type); extern void drm_plane_cleanup(struct drm_plane *plane); extern void drm_plane_force_disable(struct drm_plane *plane);
On Fri, 7 Mar 2014 16:03:17 -0800 Matt Roper matthew.d.roper@intel.com wrote:
Add a plane type property to allow userspace to distinguish plane types. The type of the plane will now be established at drm_plane_init() time (replacing the 'priv' parameter previously used).
Signed-off-by: Matt Roper matthew.d.roper@intel.com
drivers/gpu/drm/armada/armada_overlay.c | 3 +- drivers/gpu/drm/drm_crtc.c | 65 ++++++++++++++++++++---------- drivers/gpu/drm/exynos/exynos_drm_plane.c | 4 +- drivers/gpu/drm/i915/intel_sprite.c | 2 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 3 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 4 +- drivers/gpu/drm/omapdrm/omap_plane.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 +- drivers/gpu/drm/tegra/dc.c | 3 +- drivers/staging/imx-drm/ipuv3-plane.c | 4 +- include/drm/drm_crtc.h | 3 +- 13 files changed, 69 insertions(+), 35 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index c5b06fd..ef68c42 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -444,7 +444,8 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) dplane);
drm_plane_init(dev, &dplane->base, crtcs, &armada_plane_funcs,
armada_formats, ARRAY_SIZE(armada_formats), false);
armada_formats, ARRAY_SIZE(armada_formats),
DRM_PLANE_TYPE_OVERLAY);
dplane->prop.colorkey_yr = 0xfefefe00; dplane->prop.colorkey_ug = 0x01010100;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 93fc2dd..5b9b512 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -114,6 +114,15 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] =
DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
+static const struct drm_prop_enum_list drm_plane_type_enum_list[] = +{
- { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
- { DRM_PLANE_TYPE_PRIMARY, "Primary" },
- { DRM_PLANE_TYPE_CURSOR, "Cursor" },
+};
+DRM_ENUM_NAME_FN(drm_get_plane_type, drm_plane_type_enum_list)
/*
- Optional properties
*/ @@ -928,7 +937,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup);
- @funcs: callbacks for the new plane
- @formats: array of supported formats (%DRM_FORMAT_*)
- @format_count: number of elements in @formats
- @priv: plane is private (hidden from userspace)?
- @type: type of plane (overlay, primary, cursor)
- Inits a new object created as base part of a driver plane object.
@@ -939,7 +948,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, uint32_t format_count,
bool priv)
enum drm_plane_type type)
{ int ret;
@@ -964,20 +973,16 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); plane->format_count = format_count; plane->possible_crtcs = possible_crtcs;
- plane->type = DRM_PLANE_TYPE_OVERLAY;
- plane->type = type;
- /* private planes are not exposed to userspace, but depending on
* display hardware, might be convenient to allow sharing programming
* for the scanout engine with the crtc implementation.
*/
- if (!priv) {
list_add_tail(&plane->head, &dev->mode_config.plane_list);
dev->mode_config.num_total_plane++;
if (plane->type == DRM_PLANE_TYPE_OVERLAY)
dev->mode_config.num_overlay_plane++;
- } else {
INIT_LIST_HEAD(&plane->head);
- }
list_add_tail(&plane->head, &dev->mode_config.plane_list);
dev->mode_config.num_total_plane++;
if (plane->type == DRM_PLANE_TYPE_OVERLAY)
dev->mode_config.num_overlay_plane++;
drm_object_attach_property(&plane->base,
dev->mode_config.plane_type_property,
plane->type);
out: drm_modeset_unlock_all(dev);
@@ -1001,13 +1006,13 @@ void drm_plane_cleanup(struct drm_plane *plane) drm_modeset_lock_all(dev); kfree(plane->format_types); drm_mode_object_put(dev, &plane->base);
- /* if not added to a list, it must be a private plane */
- if (!list_empty(&plane->head)) {
list_del(&plane->head);
dev->mode_config.num_total_plane--;
if (plane->type == DRM_PLANE_TYPE_OVERLAY)
dev->mode_config.num_overlay_plane--;
- }
- BUG_ON(list_empty(&plane->head));
- list_del(&plane->head);
- dev->mode_config.num_total_plane--;
- if (plane->type == DRM_PLANE_TYPE_OVERLAY)
drm_modeset_unlock_all(dev);dev->mode_config.num_overlay_plane--;
} EXPORT_SYMBOL(drm_plane_cleanup); @@ -1357,6 +1362,21 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) return 0; }
+static int drm_mode_create_standard_plane_properties(struct drm_device *dev) +{
- struct drm_property *type;
- /*
* Standard properties (apply to all planes)
*/
- type = drm_property_create_enum(dev, 0,
"TYPE", drm_plane_type_enum_list,
ARRAY_SIZE(drm_plane_type_enum_list));
Should this property be created with DRM_MODE_PROP_IMMUTABLE set? What happens if user space tries to change this property to a different type?
- dev->mode_config.plane_type_property = type;
- return 0;
+}
/**
- drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
- @dev: DRM device
@@ -4277,6 +4297,7 @@ void drm_mode_config_init(struct drm_device *dev)
drm_modeset_lock_all(dev); drm_mode_create_standard_connector_properties(dev);
drm_mode_create_standard_plane_properties(dev); drm_modeset_unlock_all(dev);
/* Just to be sure */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index fcb0652..7943dd3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -263,14 +263,16 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev, { struct exynos_plane *exynos_plane; int err;
enum drm_plane_type type;
exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); if (!exynos_plane) return NULL;
type = priv ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; err = drm_plane_init(dev, &exynos_plane->base, possible_crtcs, &exynos_plane_funcs, formats, ARRAY_SIZE(formats),
priv);
if (err) { DRM_ERROR("failed to initialize plane\n"); kfree(exynos_plane);type);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 336ae6c..630485c 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1145,7 +1145,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, plane_formats, num_plane_formats,
false);
if (ret) kfree(intel_plane);DRM_PLANE_TYPE_OVERLAY);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 1e893dd..afa9c67 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -222,6 +222,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, struct drm_plane *plane = NULL; struct mdp4_plane *mdp4_plane; int ret;
enum drm_plane_type type;
mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL); if (!mdp4_plane) {
@@ -237,9 +238,10 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats, ARRAY_SIZE(mdp4_plane->formats));
- type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; drm_plane_init(dev, plane, 0xff, &mdp4_plane_funcs, mdp4_plane->formats, mdp4_plane->nformats,
private_plane);
type);
mdp4_plane_install_properties(plane, &plane->base);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 0ac8bb5..faf179c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -373,9 +373,10 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats, ARRAY_SIZE(mdp5_plane->formats));
- type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; drm_plane_init(dev, plane, 0xff, &mdp5_plane_funcs, mdp5_plane->formats, mdp5_plane->nformats,
private_plane);
type);
mdp5_plane_install_properties(plane, &plane->base);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index ab03f77..0b4f35d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -276,7 +276,7 @@ nv10_overlay_init(struct drm_device *device)
ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */, &nv10_plane_funcs,
formats, num_formats, false);
if (ret) goto err;formats, num_formats, DRM_PLANE_TYPE_OVERLAY);
@@ -456,7 +456,7 @@ nv04_overlay_init(struct drm_device *device)
ret = drm_plane_init(device, &plane->base, 1 /* single crtc */, &nv04_plane_funcs,
formats, 2, false);
if (ret) goto err;formats, 2, DRM_PLANE_TYPE_OVERLAY);
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 046d5e6..d4179b2 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -384,6 +384,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, struct omap_plane *omap_plane; struct omap_overlay_info *info; int ret;
enum drm_plane_type type;
DBG("%s: priv=%d", plane_names[id], private_plane);
@@ -413,8 +414,9 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, omap_plane->error_irq.irq = omap_plane_error_irq; omap_irq_register(dev, &omap_plane->error_irq);
- type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs,
omap_plane->formats, omap_plane->nformats, private_plane);
omap_plane->formats, omap_plane->nformats, type);
omap_plane_install_properties(plane, &plane->base);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 3fb69d9..27f1531 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -499,7 +499,8 @@ int rcar_du_planes_register(struct rcar_du_group *rgrp)
ret = drm_plane_init(rcdu->ddev, &plane->plane, crtcs, &rcar_du_plane_funcs, formats,
ARRAY_SIZE(formats), false);
ARRAY_SIZE(formats),
if (ret < 0) return ret;DRM_PLANE_TYPE_OVERLAY);
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 060ae03..2b03fff 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -257,7 +257,7 @@ int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index)
ret = drm_plane_init(sdev->ddev, &splane->plane, 1, &shmob_drm_plane_funcs, formats,
ARRAY_SIZE(formats), false);
ARRAY_SIZE(formats), DRM_PLANE_TYPE_OVERLAY);
return ret;
} diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 9336006..76e5b22 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -137,7 +137,8 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
err = drm_plane_init(drm, &plane->base, 1 << dc->pipe, &tegra_plane_funcs, plane_formats,
ARRAY_SIZE(plane_formats), false);
ARRAY_SIZE(plane_formats),
if (err < 0) { kfree(plane); return err;DRM_PLANE_TYPE_OVERLAY);
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c index 34b642a..7975369 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.c +++ b/drivers/staging/imx-drm/ipuv3-plane.c @@ -355,6 +355,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, { struct ipu_plane *ipu_plane; int ret;
enum drm_plane_type type;
DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n", dma, dp, possible_crtcs);
@@ -369,10 +370,11 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, ipu_plane->dma = dma; ipu_plane->dp_flow = dp;
- type = priv ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs, &ipu_plane_funcs, ipu_plane_formats, ARRAY_SIZE(ipu_plane_formats),
priv);
if (ret) { DRM_ERROR("failed to initialize plane\n"); kfree(ipu_plane);type);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 6ecfc9d..d8a1dc8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -976,6 +976,7 @@ struct drm_mode_config { struct list_head property_blob_list; struct drm_property *edid_property; struct drm_property *dpms_property;
struct drm_property *plane_type_property;
/* DVI-I properties */ struct drm_property *dvi_i_subconnector_property;
@@ -1084,7 +1085,7 @@ extern int drm_plane_init(struct drm_device *dev, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, uint32_t format_count,
bool priv);
enum drm_plane_type type);
extern void drm_plane_cleanup(struct drm_plane *plane); extern void drm_plane_force_disable(struct drm_plane *plane);
On Tue, Mar 11, 2014 at 04:45:00PM -0700, Bob Paauwe wrote:
On Fri, 7 Mar 2014 16:03:17 -0800 Matt Roper matthew.d.roper@intel.com wrote:
...
+static int drm_mode_create_standard_plane_properties(struct drm_device *dev) +{
- struct drm_property *type;
- /*
* Standard properties (apply to all planes)
*/
- type = drm_property_create_enum(dev, 0,
"TYPE", drm_plane_type_enum_list,
ARRAY_SIZE(drm_plane_type_enum_list));
Should this property be created with DRM_MODE_PROP_IMMUTABLE set? What happens if user space tries to change this property to a different type?
Yep, good point. I'll add that flag in my next revision of the patchset.
Thanks!
Matt
Add primary plane as a parameter to drm_crtc_init() and update all existing DRM drivers to use a helper-provided primary plane.
Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/armada/armada_crtc.c | 4 +++- drivers/gpu/drm/ast/ast_mode.c | 4 +++- drivers/gpu/drm/bochs/bochs_kms.c | 4 +++- drivers/gpu/drm/cirrus/cirrus_mode.c | 4 +++- drivers/gpu/drm/drm_crtc.c | 8 +++++++- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +++- drivers/gpu/drm/gma500/psb_intel_display.c | 4 +++- drivers/gpu/drm/i915/intel_display.c | 4 +++- drivers/gpu/drm/mgag200/mgag200_mode.c | 4 +++- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 4 +++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 4 +++- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 4 +++- drivers/gpu/drm/nouveau/nv50_display.c | 4 +++- drivers/gpu/drm/omapdrm/omap_crtc.c | 4 +++- drivers/gpu/drm/qxl/qxl_display.c | 4 +++- drivers/gpu/drm/radeon/radeon_display.c | 4 +++- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 +++- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 3 ++- drivers/gpu/drm/tegra/dc.c | 4 +++- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +++- drivers/gpu/drm/udl/udl_modeset.c | 4 +++- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 4 +++- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 4 +++- drivers/staging/imx-drm/imx-drm-core.c | 4 +++- include/drm/drm_crtc.h | 4 ++++ 25 files changed, 79 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index d8e3982..0a14d24 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1030,6 +1030,7 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num, { struct armada_private *priv = dev->dev_private; struct armada_crtc *dcrtc; + struct drm_plane *primary; void __iomem *base; int ret;
@@ -1086,7 +1087,8 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
priv->dcrtc[dcrtc->num] = dcrtc;
- drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, &dcrtc->crtc, primary, &armada_crtc_funcs); drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop, diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index cca063b..44f0d32 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -626,13 +626,15 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { static int ast_crtc_init(struct drm_device *dev) { struct ast_crtc *crtc; + struct drm_plane *primary; int i;
crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL); if (!crtc) return -ENOMEM;
- drm_crtc_init(dev, &crtc->base, &ast_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, &crtc->base, primary, &ast_crtc_funcs); drm_mode_crtc_set_gamma_size(&crtc->base, 256); drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 62ec7d4..182f5c9 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -129,8 +129,10 @@ static void bochs_crtc_init(struct drm_device *dev) { struct bochs_device *bochs = dev->dev_private; struct drm_crtc *crtc = &bochs->crtc; + struct drm_plane *primary;
- drm_crtc_init(dev, crtc, &bochs_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, crtc, primary, &bochs_crtc_funcs); drm_mode_crtc_set_gamma_size(crtc, 256); drm_crtc_helper_add(crtc, &bochs_helper_funcs); } diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 530f78f..449246f 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -381,6 +381,7 @@ static void cirrus_crtc_init(struct drm_device *dev) { struct cirrus_device *cdev = dev->dev_private; struct cirrus_crtc *cirrus_crtc; + struct drm_plane *primary; int i;
cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) + @@ -390,7 +391,8 @@ static void cirrus_crtc_init(struct drm_device *dev) if (cirrus_crtc == NULL) return;
- drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, &cirrus_crtc->base, primary, &cirrus_crtc_funcs);
drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE); cdev->mode_info.crtc = cirrus_crtc; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5b9b512..35e78a4 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -657,7 +657,8 @@ EXPORT_SYMBOL(drm_framebuffer_remove); * Zero on success, error code on failure. */ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, - const struct drm_crtc_funcs *funcs) + struct drm_plane *primary, + const struct drm_crtc_funcs *funcs) { int ret;
@@ -678,6 +679,9 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, list_add_tail(&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++;
+ crtc->primary = primary; + primary->possible_crtcs = 1 << drm_crtc_index(crtc); + out: drm_modeset_unlock_all(dev);
@@ -2376,6 +2380,8 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
ret = crtc->funcs->set_config(set); if (ret == 0) { + crtc->primary->crtc = crtc; + /* crtc->fb must be updated by ->set_config, enforces this. */ WARN_ON(fb != crtc->fb); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 6f3400f..507abd5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -323,6 +323,7 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) struct exynos_drm_crtc *exynos_crtc; struct exynos_drm_private *private = dev->dev_private; struct drm_crtc *crtc; + struct drm_plane *primary;
exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); if (!exynos_crtc) @@ -342,7 +343,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
private->crtc[nr] = crtc;
- drm_crtc_init(dev, crtc, &exynos_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, crtc, primary, &exynos_crtc_funcs); drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
exynos_drm_crtc_attach_mode_property(crtc); diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index c8841ac..c8f833d 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -491,6 +491,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, { struct drm_psb_private *dev_priv = dev->dev_private; struct gma_crtc *gma_crtc; + struct drm_plane *primary; int i; uint16_t *r_base, *g_base, *b_base;
@@ -511,7 +512,8 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, }
/* Set the CRTC operations from the chip specific data */ - drm_crtc_init(dev, &gma_crtc->base, dev_priv->ops->crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, &gma_crtc->base, primary, dev_priv->ops->crtc_funcs);
/* Set the CRTC clock functions from chip specific data */ gma_crtc->clock_funcs = dev_priv->ops->clock_funcs; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 53f7c9c..9a92895 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10280,13 +10280,15 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc; + struct drm_plane *primary; int i;
intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); if (intel_crtc == NULL) return;
- drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, &intel_crtc->base, primary, &intel_crtc_funcs);
drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); for (i = 0; i < 256; i++) { diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 9683747..4d6a043 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1314,6 +1314,7 @@ static const struct drm_crtc_helper_funcs mga_helper_funcs = { static void mga_crtc_init(struct mga_device *mdev) { struct mga_crtc *mga_crtc; + struct drm_plane *primary; int i;
mga_crtc = kzalloc(sizeof(struct mga_crtc) + @@ -1323,7 +1324,8 @@ static void mga_crtc_init(struct mga_device *mdev) if (mga_crtc == NULL) return;
- drm_crtc_init(mdev->dev, &mga_crtc->base, &mga_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(mdev->dev, &mga_crtc->base, primary, &mga_crtc_funcs);
drm_mode_crtc_set_gamma_size(&mga_crtc->base, MGAG200_LUT_SIZE); mdev->mode_info.crtc = mga_crtc; diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 84c5b13..372670e 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -753,6 +753,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, enum mdp4_dma dma_id) { struct drm_crtc *crtc = NULL; + struct drm_plane *primary; struct mdp4_crtc *mdp4_crtc; int ret;
@@ -791,7 +792,8 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
- drm_crtc_init(dev, crtc, &mdp4_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, crtc, primary, &mdp4_crtc_funcs); drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs);
mdp4_plane_install_properties(mdp4_crtc->plane, &crtc->base); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index f279402..da27348 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -533,6 +533,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, { struct drm_crtc *crtc = NULL; struct mdp5_crtc *mdp5_crtc; + struct drm_plane *primary; int ret;
mdp5_crtc = kzalloc(sizeof(*mdp5_crtc), GFP_KERNEL); @@ -559,7 +560,8 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
INIT_FENCE_CB(&mdp5_crtc->pageflip_cb, pageflip_cb);
- drm_crtc_init(dev, crtc, &mdp5_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, crtc, primary, &mdp5_crtc_funcs); drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs);
mdp5_plane_install_properties(mdp5_crtc->plane, &crtc->base); diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 0e3270c..b55be84 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1106,6 +1106,7 @@ int nv04_crtc_create(struct drm_device *dev, int crtc_num) { struct nouveau_crtc *nv_crtc; + struct drm_plane *primary; int ret, i;
nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); @@ -1122,7 +1123,8 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) nv_crtc->index = crtc_num; nv_crtc->last_dpms = NV_DPMS_CLEARED;
- drm_crtc_init(dev, &nv_crtc->base, &nv04_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, &nv_crtc->base, primary, &nv04_crtc_funcs); drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 2dccafc..5706842 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1348,6 +1348,7 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index) struct nv50_disp *disp = nv50_disp(dev); struct nv50_head *head; struct drm_crtc *crtc; + struct drm_plane *primary; int ret, i;
head = kzalloc(sizeof(*head), GFP_KERNEL); @@ -1369,7 +1370,8 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index) }
crtc = &head->base.base; - drm_crtc_init(dev, crtc, &nv50_crtc_func); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, crtc, primary, &nv50_crtc_func); drm_crtc_helper_add(crtc, &nv50_crtc_hfunc); drm_mode_crtc_set_gamma_size(crtc, 256);
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 4313bb0..2015715 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -633,6 +633,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id) { struct drm_crtc *crtc = NULL; + struct drm_plane *primary; struct omap_crtc *omap_crtc; struct omap_overlay_manager_info *info;
@@ -677,7 +678,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; info->trans_enabled = false;
- drm_crtc_init(dev, crtc, &omap_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, crtc, primary, &omap_crtc_funcs); drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
omap_plane_install_properties(omap_crtc->plane, &crtc->base); diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 798bde2..24b6112 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -636,12 +636,14 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { static int qdev_crtc_init(struct drm_device *dev, int crtc_id) { struct qxl_crtc *qxl_crtc; + struct drm_plane *primary;
qxl_crtc = kzalloc(sizeof(struct qxl_crtc), GFP_KERNEL); if (!qxl_crtc) return -ENOMEM;
- drm_crtc_init(dev, &qxl_crtc->base, &qxl_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, &qxl_crtc->base, primary, &qxl_crtc_funcs); qxl_crtc->index = crtc_id; drm_mode_crtc_set_gamma_size(&qxl_crtc->base, 256); drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index fbd8b93..a29d217 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -552,13 +552,15 @@ static void radeon_crtc_init(struct drm_device *dev, int index) { struct radeon_device *rdev = dev->dev_private; struct radeon_crtc *radeon_crtc; + struct drm_plane *primary; int i;
radeon_crtc = kzalloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); if (radeon_crtc == NULL) return;
- drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, &radeon_crtc->base, primary, &radeon_crtc_funcs);
drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); radeon_crtc->crtc_id = index; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index fbf4be3..151ffaa 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -540,6 +540,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) struct platform_device *pdev = to_platform_device(rcdu->dev); struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; struct drm_crtc *crtc = &rcrtc->crtc; + struct drm_plane *primary; unsigned int irqflags; char clk_name[5]; char *name; @@ -568,7 +569,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->plane->crtc = crtc;
- ret = drm_crtc_init(rcdu->ddev, crtc, &crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + ret = drm_crtc_init(rcdu->ddev, crtc, primary, &crtc_funcs); if (ret < 0) return ret;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 0428076..e806553 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -512,11 +512,12 @@ static const struct drm_crtc_funcs crtc_funcs = { int shmob_drm_crtc_create(struct shmob_drm_device *sdev) { struct drm_crtc *crtc = &sdev->crtc.crtc; + struct drm_plane *primary; int ret;
sdev->crtc.dpms = DRM_MODE_DPMS_OFF;
- ret = drm_crtc_init(sdev->ddev, crtc, &crtc_funcs); + ret = drm_crtc_init(sdev->ddev, crtc, primary, &crtc_funcs); if (ret < 0) return ret;
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 76e5b22..5e2ee9d 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1099,9 +1099,11 @@ static int tegra_dc_init(struct host1x_client *client) { struct tegra_drm *tegra = dev_get_drvdata(client->parent); struct tegra_dc *dc = host1x_client_to_dc(client); + struct drm_plane *primary; int err;
- drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(tegra->drm, &dc->base, primary, &tegra_crtc_funcs); drm_mode_crtc_set_gamma_size(&dc->base, 256); drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index d36efc1..310314c 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -651,6 +651,7 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) { struct tilcdc_crtc *tilcdc_crtc; struct drm_crtc *crtc; + struct drm_plane *primary; int ret;
tilcdc_crtc = kzalloc(sizeof(*tilcdc_crtc), GFP_KERNEL); @@ -671,7 +672,8 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) goto fail; }
- ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + ret = drm_crtc_init(dev, crtc, primary, &tilcdc_crtc_funcs); if (ret < 0) goto fail;
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 2ae1eb7..1255944 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -389,12 +389,14 @@ static const struct drm_crtc_funcs udl_crtc_funcs = { static int udl_crtc_init(struct drm_device *dev) { struct drm_crtc *crtc; + struct drm_plane *primary;
crtc = kzalloc(sizeof(struct drm_crtc) + sizeof(struct drm_connector *), GFP_KERNEL); if (crtc == NULL) return -ENOMEM;
- drm_crtc_init(dev, crtc, &udl_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, crtc, primary, &udl_crtc_funcs); drm_crtc_helper_add(crtc, &udl_helper_funcs);
return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index a055a26..001ec81 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -343,6 +343,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) struct drm_connector *connector; struct drm_encoder *encoder; struct drm_crtc *crtc; + struct drm_plane *primary;
ldu = kzalloc(sizeof(*ldu), GFP_KERNEL); if (!ldu) @@ -373,7 +374,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
(void) drm_sysfs_connector_add(connector);
- drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, crtc, primary, &vmw_legacy_crtc_funcs);
drm_mode_crtc_set_gamma_size(crtc, 256);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 22406c8..585da43 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -439,6 +439,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) struct drm_connector *connector; struct drm_encoder *encoder; struct drm_crtc *crtc; + struct drm_plane *primary;
sou = kzalloc(sizeof(*sou), GFP_KERNEL); if (!sou) @@ -469,7 +470,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
(void) drm_sysfs_connector_add(connector);
- drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs); + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(dev, crtc, primary, &vmw_screen_object_crtc_funcs);
drm_mode_crtc_set_gamma_size(crtc, 256);
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 236ed66..8c7b1d3 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -475,6 +475,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc, { struct imx_drm_device *imxdrm = __imx_drm_device(); struct imx_drm_crtc *imx_drm_crtc; + struct drm_plane *primary; int ret;
mutex_lock(&imxdrm->mutex); @@ -520,7 +521,8 @@ int imx_drm_add_crtc(struct drm_crtc *crtc, drm_crtc_helper_add(crtc, imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
- drm_crtc_init(imxdrm->drm, crtc, + primary = drm_primary_helper_create_plane(dev); + drm_crtc_init(imxdrm->drm, crtc, primary, imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
drm_mode_group_reinit(imxdrm->drm); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d8a1dc8..c83321b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -422,6 +422,9 @@ struct drm_crtc {
struct drm_mode_object base;
+ /* primary plane for CRTC */ + struct drm_plane *primary; + /* framebuffer the connector is currently bound to */ struct drm_framebuffer *fb;
@@ -1031,6 +1034,7 @@ extern void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
extern int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, + struct drm_plane *primary, const struct drm_crtc_funcs *funcs); extern void drm_crtc_cleanup(struct drm_crtc *crtc); extern unsigned int drm_crtc_index(struct drm_crtc *crtc);
On Fri, Mar 7, 2014 at 7:03 PM, Matt Roper matthew.d.roper@intel.com wrote:
Add primary plane as a parameter to drm_crtc_init() and update all existing DRM drivers to use a helper-provided primary plane.
Signed-off-by: Matt Roper matthew.d.roper@intel.com
drivers/gpu/drm/armada/armada_crtc.c | 4 +++- drivers/gpu/drm/ast/ast_mode.c | 4 +++- drivers/gpu/drm/bochs/bochs_kms.c | 4 +++- drivers/gpu/drm/cirrus/cirrus_mode.c | 4 +++- drivers/gpu/drm/drm_crtc.c | 8 +++++++- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +++- drivers/gpu/drm/gma500/psb_intel_display.c | 4 +++- drivers/gpu/drm/i915/intel_display.c | 4 +++- drivers/gpu/drm/mgag200/mgag200_mode.c | 4 +++- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 4 +++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 4 +++- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 4 +++- drivers/gpu/drm/nouveau/nv50_display.c | 4 +++- drivers/gpu/drm/omapdrm/omap_crtc.c | 4 +++- drivers/gpu/drm/qxl/qxl_display.c | 4 +++- drivers/gpu/drm/radeon/radeon_display.c | 4 +++- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 +++- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 3 ++- drivers/gpu/drm/tegra/dc.c | 4 +++- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +++- drivers/gpu/drm/udl/udl_modeset.c | 4 +++- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 4 +++- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 4 +++- drivers/staging/imx-drm/imx-drm-core.c | 4 +++- include/drm/drm_crtc.h | 4 ++++ 25 files changed, 79 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index d8e3982..0a14d24 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1030,6 +1030,7 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num, { struct armada_private *priv = dev->dev_private; struct armada_crtc *dcrtc;
struct drm_plane *primary; void __iomem *base; int ret;
@@ -1086,7 +1087,8 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
priv->dcrtc[dcrtc->num] = dcrtc;
drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &dcrtc->crtc, primary, &armada_crtc_funcs); drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs); drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index cca063b..44f0d32 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -626,13 +626,15 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { static int ast_crtc_init(struct drm_device *dev) { struct ast_crtc *crtc;
struct drm_plane *primary; int i; crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL); if (!crtc) return -ENOMEM;
drm_crtc_init(dev, &crtc->base, &ast_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &crtc->base, primary, &ast_crtc_funcs); drm_mode_crtc_set_gamma_size(&crtc->base, 256); drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 62ec7d4..182f5c9 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -129,8 +129,10 @@ static void bochs_crtc_init(struct drm_device *dev) { struct bochs_device *bochs = dev->dev_private; struct drm_crtc *crtc = &bochs->crtc;
struct drm_plane *primary;
drm_crtc_init(dev, crtc, &bochs_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &bochs_crtc_funcs); drm_mode_crtc_set_gamma_size(crtc, 256); drm_crtc_helper_add(crtc, &bochs_helper_funcs);
} diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 530f78f..449246f 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -381,6 +381,7 @@ static void cirrus_crtc_init(struct drm_device *dev) { struct cirrus_device *cdev = dev->dev_private; struct cirrus_crtc *cirrus_crtc;
struct drm_plane *primary; int i; cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) +
@@ -390,7 +391,8 @@ static void cirrus_crtc_init(struct drm_device *dev) if (cirrus_crtc == NULL) return;
drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &cirrus_crtc->base, primary, &cirrus_crtc_funcs); drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE); cdev->mode_info.crtc = cirrus_crtc;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5b9b512..35e78a4 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -657,7 +657,8 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
- Zero on success, error code on failure.
*/ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
const struct drm_crtc_funcs *funcs)
struct drm_plane *primary,
const struct drm_crtc_funcs *funcs)
{ int ret;
@@ -678,6 +679,9 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, list_add_tail(&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++;
crtc->primary = primary;
primary->possible_crtcs = 1 << drm_crtc_index(crtc);
- out: drm_modeset_unlock_all(dev);
@@ -2376,6 +2380,8 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
ret = crtc->funcs->set_config(set); if (ret == 0) {
crtc->primary->crtc = crtc;
/* crtc->fb must be updated by ->set_config, enforces this. */ WARN_ON(fb != crtc->fb); }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 6f3400f..507abd5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -323,6 +323,7 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) struct exynos_drm_crtc *exynos_crtc; struct exynos_drm_private *private = dev->dev_private; struct drm_crtc *crtc;
struct drm_plane *primary; exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); if (!exynos_crtc)
@@ -342,7 +343,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
private->crtc[nr] = crtc;
drm_crtc_init(dev, crtc, &exynos_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &exynos_crtc_funcs); drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); exynos_drm_crtc_attach_mode_property(crtc);
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index c8841ac..c8f833d 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -491,6 +491,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, { struct drm_psb_private *dev_priv = dev->dev_private; struct gma_crtc *gma_crtc;
struct drm_plane *primary; int i; uint16_t *r_base, *g_base, *b_base;
@@ -511,7 +512,8 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, }
/* Set the CRTC operations from the chip specific data */
drm_crtc_init(dev, &gma_crtc->base, dev_priv->ops->crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &gma_crtc->base, primary, dev_priv->ops->crtc_funcs); /* Set the CRTC clock functions from chip specific data */ gma_crtc->clock_funcs = dev_priv->ops->clock_funcs;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 53f7c9c..9a92895 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10280,13 +10280,15 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc;
struct drm_plane *primary; int i; intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); if (intel_crtc == NULL) return;
drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &intel_crtc->base, primary, &intel_crtc_funcs); drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); for (i = 0; i < 256; i++) {
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 9683747..4d6a043 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1314,6 +1314,7 @@ static const struct drm_crtc_helper_funcs mga_helper_funcs = { static void mga_crtc_init(struct mga_device *mdev) { struct mga_crtc *mga_crtc;
struct drm_plane *primary; int i; mga_crtc = kzalloc(sizeof(struct mga_crtc) +
@@ -1323,7 +1324,8 @@ static void mga_crtc_init(struct mga_device *mdev) if (mga_crtc == NULL) return;
drm_crtc_init(mdev->dev, &mga_crtc->base, &mga_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(mdev->dev, &mga_crtc->base, primary, &mga_crtc_funcs); drm_mode_crtc_set_gamma_size(&mga_crtc->base, MGAG200_LUT_SIZE); mdev->mode_info.crtc = mga_crtc;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 84c5b13..372670e 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -753,6 +753,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, enum mdp4_dma dma_id) { struct drm_crtc *crtc = NULL;
struct drm_plane *primary; struct mdp4_crtc *mdp4_crtc; int ret;
@@ -791,7 +792,8 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
drm_crtc_init(dev, crtc, &mdp4_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &mdp4_crtc_funcs);
note that msm, omap, and iirc exynos (and maybe even some others) already have their own private (now primary) planes. I suspect they should be using their existing plane, rather than creating a helper plane.
BR, -R
drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs); mdp4_plane_install_properties(mdp4_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index f279402..da27348 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -533,6 +533,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, { struct drm_crtc *crtc = NULL; struct mdp5_crtc *mdp5_crtc;
struct drm_plane *primary; int ret; mdp5_crtc = kzalloc(sizeof(*mdp5_crtc), GFP_KERNEL);
@@ -559,7 +560,8 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
INIT_FENCE_CB(&mdp5_crtc->pageflip_cb, pageflip_cb);
drm_crtc_init(dev, crtc, &mdp5_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &mdp5_crtc_funcs); drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs); mdp5_plane_install_properties(mdp5_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 0e3270c..b55be84 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1106,6 +1106,7 @@ int nv04_crtc_create(struct drm_device *dev, int crtc_num) { struct nouveau_crtc *nv_crtc;
struct drm_plane *primary; int ret, i; nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
@@ -1122,7 +1123,8 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) nv_crtc->index = crtc_num; nv_crtc->last_dpms = NV_DPMS_CLEARED;
drm_crtc_init(dev, &nv_crtc->base, &nv04_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &nv_crtc->base, primary, &nv04_crtc_funcs); drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 2dccafc..5706842 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1348,6 +1348,7 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index) struct nv50_disp *disp = nv50_disp(dev); struct nv50_head *head; struct drm_crtc *crtc;
struct drm_plane *primary; int ret, i; head = kzalloc(sizeof(*head), GFP_KERNEL);
@@ -1369,7 +1370,8 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index) }
crtc = &head->base.base;
drm_crtc_init(dev, crtc, &nv50_crtc_func);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &nv50_crtc_func); drm_crtc_helper_add(crtc, &nv50_crtc_hfunc); drm_mode_crtc_set_gamma_size(crtc, 256);
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 4313bb0..2015715 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -633,6 +633,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id) { struct drm_crtc *crtc = NULL;
struct drm_plane *primary; struct omap_crtc *omap_crtc; struct omap_overlay_manager_info *info;
@@ -677,7 +678,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; info->trans_enabled = false;
drm_crtc_init(dev, crtc, &omap_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &omap_crtc_funcs); drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); omap_plane_install_properties(omap_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 798bde2..24b6112 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -636,12 +636,14 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { static int qdev_crtc_init(struct drm_device *dev, int crtc_id) { struct qxl_crtc *qxl_crtc;
struct drm_plane *primary; qxl_crtc = kzalloc(sizeof(struct qxl_crtc), GFP_KERNEL); if (!qxl_crtc) return -ENOMEM;
drm_crtc_init(dev, &qxl_crtc->base, &qxl_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &qxl_crtc->base, primary, &qxl_crtc_funcs); qxl_crtc->index = crtc_id; drm_mode_crtc_set_gamma_size(&qxl_crtc->base, 256); drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index fbd8b93..a29d217 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -552,13 +552,15 @@ static void radeon_crtc_init(struct drm_device *dev, int index) { struct radeon_device *rdev = dev->dev_private; struct radeon_crtc *radeon_crtc;
struct drm_plane *primary; int i; radeon_crtc = kzalloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); if (radeon_crtc == NULL) return;
drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &radeon_crtc->base, primary, &radeon_crtc_funcs); drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); radeon_crtc->crtc_id = index;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index fbf4be3..151ffaa 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -540,6 +540,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) struct platform_device *pdev = to_platform_device(rcdu->dev); struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; struct drm_crtc *crtc = &rcrtc->crtc;
struct drm_plane *primary; unsigned int irqflags; char clk_name[5]; char *name;
@@ -568,7 +569,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->plane->crtc = crtc;
ret = drm_crtc_init(rcdu->ddev, crtc, &crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
ret = drm_crtc_init(rcdu->ddev, crtc, primary, &crtc_funcs); if (ret < 0) return ret;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 0428076..e806553 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -512,11 +512,12 @@ static const struct drm_crtc_funcs crtc_funcs = { int shmob_drm_crtc_create(struct shmob_drm_device *sdev) { struct drm_crtc *crtc = &sdev->crtc.crtc;
struct drm_plane *primary; int ret; sdev->crtc.dpms = DRM_MODE_DPMS_OFF;
ret = drm_crtc_init(sdev->ddev, crtc, &crtc_funcs);
ret = drm_crtc_init(sdev->ddev, crtc, primary, &crtc_funcs); if (ret < 0) return ret;
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 76e5b22..5e2ee9d 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1099,9 +1099,11 @@ static int tegra_dc_init(struct host1x_client *client) { struct tegra_drm *tegra = dev_get_drvdata(client->parent); struct tegra_dc *dc = host1x_client_to_dc(client);
struct drm_plane *primary; int err;
drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(tegra->drm, &dc->base, primary, &tegra_crtc_funcs); drm_mode_crtc_set_gamma_size(&dc->base, 256); drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index d36efc1..310314c 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -651,6 +651,7 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) { struct tilcdc_crtc *tilcdc_crtc; struct drm_crtc *crtc;
struct drm_plane *primary; int ret; tilcdc_crtc = kzalloc(sizeof(*tilcdc_crtc), GFP_KERNEL);
@@ -671,7 +672,8 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) goto fail; }
ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
ret = drm_crtc_init(dev, crtc, primary, &tilcdc_crtc_funcs); if (ret < 0) goto fail;
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 2ae1eb7..1255944 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -389,12 +389,14 @@ static const struct drm_crtc_funcs udl_crtc_funcs = { static int udl_crtc_init(struct drm_device *dev) { struct drm_crtc *crtc;
struct drm_plane *primary; crtc = kzalloc(sizeof(struct drm_crtc) + sizeof(struct drm_connector *), GFP_KERNEL); if (crtc == NULL) return -ENOMEM;
drm_crtc_init(dev, crtc, &udl_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &udl_crtc_funcs); drm_crtc_helper_add(crtc, &udl_helper_funcs); return 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index a055a26..001ec81 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -343,6 +343,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) struct drm_connector *connector; struct drm_encoder *encoder; struct drm_crtc *crtc;
struct drm_plane *primary; ldu = kzalloc(sizeof(*ldu), GFP_KERNEL); if (!ldu)
@@ -373,7 +374,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
(void) drm_sysfs_connector_add(connector);
drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &vmw_legacy_crtc_funcs); drm_mode_crtc_set_gamma_size(crtc, 256);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 22406c8..585da43 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -439,6 +439,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) struct drm_connector *connector; struct drm_encoder *encoder; struct drm_crtc *crtc;
struct drm_plane *primary; sou = kzalloc(sizeof(*sou), GFP_KERNEL); if (!sou)
@@ -469,7 +470,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
(void) drm_sysfs_connector_add(connector);
drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &vmw_screen_object_crtc_funcs); drm_mode_crtc_set_gamma_size(crtc, 256);
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 236ed66..8c7b1d3 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -475,6 +475,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc, { struct imx_drm_device *imxdrm = __imx_drm_device(); struct imx_drm_crtc *imx_drm_crtc;
struct drm_plane *primary; int ret; mutex_lock(&imxdrm->mutex);
@@ -520,7 +521,8 @@ int imx_drm_add_crtc(struct drm_crtc *crtc, drm_crtc_helper_add(crtc, imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
drm_crtc_init(imxdrm->drm, crtc,
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(imxdrm->drm, crtc, primary, imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs); drm_mode_group_reinit(imxdrm->drm);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d8a1dc8..c83321b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -422,6 +422,9 @@ struct drm_crtc {
struct drm_mode_object base;
/* primary plane for CRTC */
struct drm_plane *primary;
/* framebuffer the connector is currently bound to */ struct drm_framebuffer *fb;
@@ -1031,6 +1034,7 @@ extern void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
extern int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
struct drm_plane *primary, const struct drm_crtc_funcs *funcs);
extern void drm_crtc_cleanup(struct drm_crtc *crtc); extern unsigned int drm_crtc_index(struct drm_crtc *crtc); -- 1.8.5.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
On Sun, Mar 09, 2014 at 05:12:31PM -0400, Rob Clark wrote:
On Fri, Mar 7, 2014 at 7:03 PM, Matt Roper matthew.d.roper@intel.com wrote:
Add primary plane as a parameter to drm_crtc_init() and update all existing DRM drivers to use a helper-provided primary plane.
Signed-off-by: Matt Roper matthew.d.roper@intel.com
drivers/gpu/drm/armada/armada_crtc.c | 4 +++- drivers/gpu/drm/ast/ast_mode.c | 4 +++- drivers/gpu/drm/bochs/bochs_kms.c | 4 +++- drivers/gpu/drm/cirrus/cirrus_mode.c | 4 +++- drivers/gpu/drm/drm_crtc.c | 8 +++++++- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +++- drivers/gpu/drm/gma500/psb_intel_display.c | 4 +++- drivers/gpu/drm/i915/intel_display.c | 4 +++- drivers/gpu/drm/mgag200/mgag200_mode.c | 4 +++- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 4 +++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 4 +++- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 4 +++- drivers/gpu/drm/nouveau/nv50_display.c | 4 +++- drivers/gpu/drm/omapdrm/omap_crtc.c | 4 +++- drivers/gpu/drm/qxl/qxl_display.c | 4 +++- drivers/gpu/drm/radeon/radeon_display.c | 4 +++- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 +++- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 3 ++- drivers/gpu/drm/tegra/dc.c | 4 +++- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +++- drivers/gpu/drm/udl/udl_modeset.c | 4 +++- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 4 +++- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 4 +++- drivers/staging/imx-drm/imx-drm-core.c | 4 +++- include/drm/drm_crtc.h | 4 ++++ 25 files changed, 79 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index d8e3982..0a14d24 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1030,6 +1030,7 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num, { struct armada_private *priv = dev->dev_private; struct armada_crtc *dcrtc;
struct drm_plane *primary; void __iomem *base; int ret;
@@ -1086,7 +1087,8 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
priv->dcrtc[dcrtc->num] = dcrtc;
drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &dcrtc->crtc, primary, &armada_crtc_funcs); drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs); drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index cca063b..44f0d32 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -626,13 +626,15 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { static int ast_crtc_init(struct drm_device *dev) { struct ast_crtc *crtc;
struct drm_plane *primary; int i; crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL); if (!crtc) return -ENOMEM;
drm_crtc_init(dev, &crtc->base, &ast_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &crtc->base, primary, &ast_crtc_funcs); drm_mode_crtc_set_gamma_size(&crtc->base, 256); drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 62ec7d4..182f5c9 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -129,8 +129,10 @@ static void bochs_crtc_init(struct drm_device *dev) { struct bochs_device *bochs = dev->dev_private; struct drm_crtc *crtc = &bochs->crtc;
struct drm_plane *primary;
drm_crtc_init(dev, crtc, &bochs_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &bochs_crtc_funcs); drm_mode_crtc_set_gamma_size(crtc, 256); drm_crtc_helper_add(crtc, &bochs_helper_funcs);
} diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 530f78f..449246f 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -381,6 +381,7 @@ static void cirrus_crtc_init(struct drm_device *dev) { struct cirrus_device *cdev = dev->dev_private; struct cirrus_crtc *cirrus_crtc;
struct drm_plane *primary; int i; cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) +
@@ -390,7 +391,8 @@ static void cirrus_crtc_init(struct drm_device *dev) if (cirrus_crtc == NULL) return;
drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &cirrus_crtc->base, primary, &cirrus_crtc_funcs); drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE); cdev->mode_info.crtc = cirrus_crtc;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5b9b512..35e78a4 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -657,7 +657,8 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
- Zero on success, error code on failure.
*/ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
const struct drm_crtc_funcs *funcs)
struct drm_plane *primary,
const struct drm_crtc_funcs *funcs)
{ int ret;
@@ -678,6 +679,9 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, list_add_tail(&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++;
crtc->primary = primary;
primary->possible_crtcs = 1 << drm_crtc_index(crtc);
- out: drm_modeset_unlock_all(dev);
@@ -2376,6 +2380,8 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
ret = crtc->funcs->set_config(set); if (ret == 0) {
crtc->primary->crtc = crtc;
/* crtc->fb must be updated by ->set_config, enforces this. */ WARN_ON(fb != crtc->fb); }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 6f3400f..507abd5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -323,6 +323,7 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) struct exynos_drm_crtc *exynos_crtc; struct exynos_drm_private *private = dev->dev_private; struct drm_crtc *crtc;
struct drm_plane *primary; exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); if (!exynos_crtc)
@@ -342,7 +343,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
private->crtc[nr] = crtc;
drm_crtc_init(dev, crtc, &exynos_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &exynos_crtc_funcs); drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); exynos_drm_crtc_attach_mode_property(crtc);
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index c8841ac..c8f833d 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -491,6 +491,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, { struct drm_psb_private *dev_priv = dev->dev_private; struct gma_crtc *gma_crtc;
struct drm_plane *primary; int i; uint16_t *r_base, *g_base, *b_base;
@@ -511,7 +512,8 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, }
/* Set the CRTC operations from the chip specific data */
drm_crtc_init(dev, &gma_crtc->base, dev_priv->ops->crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &gma_crtc->base, primary, dev_priv->ops->crtc_funcs); /* Set the CRTC clock functions from chip specific data */ gma_crtc->clock_funcs = dev_priv->ops->clock_funcs;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 53f7c9c..9a92895 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10280,13 +10280,15 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc;
struct drm_plane *primary; int i; intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); if (intel_crtc == NULL) return;
drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &intel_crtc->base, primary, &intel_crtc_funcs); drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); for (i = 0; i < 256; i++) {
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 9683747..4d6a043 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1314,6 +1314,7 @@ static const struct drm_crtc_helper_funcs mga_helper_funcs = { static void mga_crtc_init(struct mga_device *mdev) { struct mga_crtc *mga_crtc;
struct drm_plane *primary; int i; mga_crtc = kzalloc(sizeof(struct mga_crtc) +
@@ -1323,7 +1324,8 @@ static void mga_crtc_init(struct mga_device *mdev) if (mga_crtc == NULL) return;
drm_crtc_init(mdev->dev, &mga_crtc->base, &mga_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(mdev->dev, &mga_crtc->base, primary, &mga_crtc_funcs); drm_mode_crtc_set_gamma_size(&mga_crtc->base, MGAG200_LUT_SIZE); mdev->mode_info.crtc = mga_crtc;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 84c5b13..372670e 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -753,6 +753,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, enum mdp4_dma dma_id) { struct drm_crtc *crtc = NULL;
struct drm_plane *primary; struct mdp4_crtc *mdp4_crtc; int ret;
@@ -791,7 +792,8 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
drm_crtc_init(dev, crtc, &mdp4_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &mdp4_crtc_funcs);
note that msm, omap, and iirc exynos (and maybe even some others) already have their own private (now primary) planes. I suspect they should be using their existing plane, rather than creating a helper plane.
BR, -R
Yep, agreed. This is one of the items I called out as a TODO in the patch set cover letter. I just haven't had enough time to look at those drivers in detail yet to figure out how they work. Right now I believe they all register the same set of plane handler functions at drm_plane_init() that they do for their other overlay planes; I need to figure out whether those handler functions will actually operate properly on the private/primary planes, or whether the drivers were previously just assuming that the handlers would never get called on private planes and something different is needed.
Matt
drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs); mdp4_plane_install_properties(mdp4_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index f279402..da27348 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -533,6 +533,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, { struct drm_crtc *crtc = NULL; struct mdp5_crtc *mdp5_crtc;
struct drm_plane *primary; int ret; mdp5_crtc = kzalloc(sizeof(*mdp5_crtc), GFP_KERNEL);
@@ -559,7 +560,8 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
INIT_FENCE_CB(&mdp5_crtc->pageflip_cb, pageflip_cb);
drm_crtc_init(dev, crtc, &mdp5_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &mdp5_crtc_funcs); drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs); mdp5_plane_install_properties(mdp5_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 0e3270c..b55be84 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1106,6 +1106,7 @@ int nv04_crtc_create(struct drm_device *dev, int crtc_num) { struct nouveau_crtc *nv_crtc;
struct drm_plane *primary; int ret, i; nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
@@ -1122,7 +1123,8 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) nv_crtc->index = crtc_num; nv_crtc->last_dpms = NV_DPMS_CLEARED;
drm_crtc_init(dev, &nv_crtc->base, &nv04_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &nv_crtc->base, primary, &nv04_crtc_funcs); drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 2dccafc..5706842 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1348,6 +1348,7 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index) struct nv50_disp *disp = nv50_disp(dev); struct nv50_head *head; struct drm_crtc *crtc;
struct drm_plane *primary; int ret, i; head = kzalloc(sizeof(*head), GFP_KERNEL);
@@ -1369,7 +1370,8 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index) }
crtc = &head->base.base;
drm_crtc_init(dev, crtc, &nv50_crtc_func);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &nv50_crtc_func); drm_crtc_helper_add(crtc, &nv50_crtc_hfunc); drm_mode_crtc_set_gamma_size(crtc, 256);
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 4313bb0..2015715 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -633,6 +633,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id) { struct drm_crtc *crtc = NULL;
struct drm_plane *primary; struct omap_crtc *omap_crtc; struct omap_overlay_manager_info *info;
@@ -677,7 +678,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; info->trans_enabled = false;
drm_crtc_init(dev, crtc, &omap_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &omap_crtc_funcs); drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); omap_plane_install_properties(omap_crtc->plane, &crtc->base);
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 798bde2..24b6112 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -636,12 +636,14 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { static int qdev_crtc_init(struct drm_device *dev, int crtc_id) { struct qxl_crtc *qxl_crtc;
struct drm_plane *primary; qxl_crtc = kzalloc(sizeof(struct qxl_crtc), GFP_KERNEL); if (!qxl_crtc) return -ENOMEM;
drm_crtc_init(dev, &qxl_crtc->base, &qxl_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &qxl_crtc->base, primary, &qxl_crtc_funcs); qxl_crtc->index = crtc_id; drm_mode_crtc_set_gamma_size(&qxl_crtc->base, 256); drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index fbd8b93..a29d217 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -552,13 +552,15 @@ static void radeon_crtc_init(struct drm_device *dev, int index) { struct radeon_device *rdev = dev->dev_private; struct radeon_crtc *radeon_crtc;
struct drm_plane *primary; int i; radeon_crtc = kzalloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); if (radeon_crtc == NULL) return;
drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, &radeon_crtc->base, primary, &radeon_crtc_funcs); drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); radeon_crtc->crtc_id = index;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index fbf4be3..151ffaa 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -540,6 +540,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) struct platform_device *pdev = to_platform_device(rcdu->dev); struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; struct drm_crtc *crtc = &rcrtc->crtc;
struct drm_plane *primary; unsigned int irqflags; char clk_name[5]; char *name;
@@ -568,7 +569,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->plane->crtc = crtc;
ret = drm_crtc_init(rcdu->ddev, crtc, &crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
ret = drm_crtc_init(rcdu->ddev, crtc, primary, &crtc_funcs); if (ret < 0) return ret;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 0428076..e806553 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -512,11 +512,12 @@ static const struct drm_crtc_funcs crtc_funcs = { int shmob_drm_crtc_create(struct shmob_drm_device *sdev) { struct drm_crtc *crtc = &sdev->crtc.crtc;
struct drm_plane *primary; int ret; sdev->crtc.dpms = DRM_MODE_DPMS_OFF;
ret = drm_crtc_init(sdev->ddev, crtc, &crtc_funcs);
ret = drm_crtc_init(sdev->ddev, crtc, primary, &crtc_funcs); if (ret < 0) return ret;
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 76e5b22..5e2ee9d 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1099,9 +1099,11 @@ static int tegra_dc_init(struct host1x_client *client) { struct tegra_drm *tegra = dev_get_drvdata(client->parent); struct tegra_dc *dc = host1x_client_to_dc(client);
struct drm_plane *primary; int err;
drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(tegra->drm, &dc->base, primary, &tegra_crtc_funcs); drm_mode_crtc_set_gamma_size(&dc->base, 256); drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index d36efc1..310314c 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -651,6 +651,7 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) { struct tilcdc_crtc *tilcdc_crtc; struct drm_crtc *crtc;
struct drm_plane *primary; int ret; tilcdc_crtc = kzalloc(sizeof(*tilcdc_crtc), GFP_KERNEL);
@@ -671,7 +672,8 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) goto fail; }
ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
ret = drm_crtc_init(dev, crtc, primary, &tilcdc_crtc_funcs); if (ret < 0) goto fail;
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 2ae1eb7..1255944 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -389,12 +389,14 @@ static const struct drm_crtc_funcs udl_crtc_funcs = { static int udl_crtc_init(struct drm_device *dev) { struct drm_crtc *crtc;
struct drm_plane *primary; crtc = kzalloc(sizeof(struct drm_crtc) + sizeof(struct drm_connector *), GFP_KERNEL); if (crtc == NULL) return -ENOMEM;
drm_crtc_init(dev, crtc, &udl_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &udl_crtc_funcs); drm_crtc_helper_add(crtc, &udl_helper_funcs); return 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index a055a26..001ec81 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -343,6 +343,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) struct drm_connector *connector; struct drm_encoder *encoder; struct drm_crtc *crtc;
struct drm_plane *primary; ldu = kzalloc(sizeof(*ldu), GFP_KERNEL); if (!ldu)
@@ -373,7 +374,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
(void) drm_sysfs_connector_add(connector);
drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &vmw_legacy_crtc_funcs); drm_mode_crtc_set_gamma_size(crtc, 256);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 22406c8..585da43 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -439,6 +439,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) struct drm_connector *connector; struct drm_encoder *encoder; struct drm_crtc *crtc;
struct drm_plane *primary; sou = kzalloc(sizeof(*sou), GFP_KERNEL); if (!sou)
@@ -469,7 +470,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
(void) drm_sysfs_connector_add(connector);
drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &vmw_screen_object_crtc_funcs); drm_mode_crtc_set_gamma_size(crtc, 256);
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 236ed66..8c7b1d3 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -475,6 +475,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc, { struct imx_drm_device *imxdrm = __imx_drm_device(); struct imx_drm_crtc *imx_drm_crtc;
struct drm_plane *primary; int ret; mutex_lock(&imxdrm->mutex);
@@ -520,7 +521,8 @@ int imx_drm_add_crtc(struct drm_crtc *crtc, drm_crtc_helper_add(crtc, imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
drm_crtc_init(imxdrm->drm, crtc,
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(imxdrm->drm, crtc, primary, imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs); drm_mode_group_reinit(imxdrm->drm);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d8a1dc8..c83321b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -422,6 +422,9 @@ struct drm_crtc {
struct drm_mode_object base;
/* primary plane for CRTC */
struct drm_plane *primary;
/* framebuffer the connector is currently bound to */ struct drm_framebuffer *fb;
@@ -1031,6 +1034,7 @@ extern void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
extern int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
struct drm_plane *primary, const struct drm_crtc_funcs *funcs);
extern void drm_crtc_cleanup(struct drm_crtc *crtc); extern unsigned int drm_crtc_index(struct drm_crtc *crtc); -- 1.8.5.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
On Mon, Mar 10, 2014 at 10:54 AM, Matt Roper matthew.d.roper@intel.com wrote:
On Sun, Mar 09, 2014 at 05:12:31PM -0400, Rob Clark wrote:
On Fri, Mar 7, 2014 at 7:03 PM, Matt Roper matthew.d.roper@intel.com wrote:
Add primary plane as a parameter to drm_crtc_init() and update all existing DRM drivers to use a helper-provided primary plane.
Signed-off-by: Matt Roper matthew.d.roper@intel.com
[snip]
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 84c5b13..372670e 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -753,6 +753,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, enum mdp4_dma dma_id) { struct drm_crtc *crtc = NULL;
struct drm_plane *primary; struct mdp4_crtc *mdp4_crtc; int ret;
@@ -791,7 +792,8 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
drm_crtc_init(dev, crtc, &mdp4_crtc_funcs);
primary = drm_primary_helper_create_plane(dev);
drm_crtc_init(dev, crtc, primary, &mdp4_crtc_funcs);
note that msm, omap, and iirc exynos (and maybe even some others) already have their own private (now primary) planes. I suspect they should be using their existing plane, rather than creating a helper plane.
BR, -R
Yep, agreed. This is one of the items I called out as a TODO in the patch set cover letter. I just haven't had enough time to look at those drivers in detail yet to figure out how they work. Right now I believe they all register the same set of plane handler functions at drm_plane_init() that they do for their other overlay planes; I need to figure out whether those handler functions will actually operate properly on the private/primary planes, or whether the drivers were previously just assuming that the handlers would never get called on private planes and something different is needed.
ahh, I should have paid more attention to your cover letter. Well, omapdrm and msm are safe to convert (same set of plane handler fxns). I'll update and test msm when I rebase atomic, so their will be a patch that you can squash back in for that one.
BR, -R
Matt
Now that CRTC's have a primary plane, there's no need to track the framebuffer in the CRTC. Replace all references to the CRTC fb with the primary plane's fb.
Also note that this simplifies framebuffer removal slightly; we no longer need to scan all CRTC's and disable the ones that were using the framebuffer since the existing loop over all planes will take care of disabling the primary plane (and on most hardware, the CRTC by extension).
Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/drm_crtc.c | 56 ++++++++++++----------------- drivers/gpu/drm/drm_crtc_helper.c | 21 +++++------ drivers/gpu/drm/drm_fb_helper.c | 6 ++-- drivers/gpu/drm/i915/i915_debugfs.c | 4 +-- drivers/gpu/drm/i915/i915_irq.c | 4 +-- drivers/gpu/drm/i915/intel_display.c | 56 +++++++++++++++-------------- drivers/gpu/drm/i915/intel_dp.c | 5 +-- drivers/gpu/drm/i915/intel_overlay.c | 4 +-- drivers/gpu/drm/i915/intel_pm.c | 36 +++++++++---------- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 20 +++++------ drivers/gpu/drm/nouveau/dispnv04/dfp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_display.c | 8 ++--- drivers/gpu/drm/nouveau/nv50_display.c | 17 ++++----- drivers/gpu/drm/radeon/atombios_crtc.c | 20 +++++------ drivers/gpu/drm/radeon/r100.c | 4 +-- drivers/gpu/drm/radeon/radeon_connectors.c | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 3 +- drivers/gpu/drm/radeon/radeon_display.c | 4 +-- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 16 ++++----- include/drm/drm_crtc.h | 3 -- 20 files changed, 141 insertions(+), 150 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 35e78a4..cdfa61a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -586,7 +586,7 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); * drm_framebuffer_remove - remove and unreference a framebuffer object * @fb: framebuffer to remove * - * Scans all the CRTCs and planes in @dev's mode_config. If they're + * Scans all the planes in @dev's mode_config. If they're * using @fb, removes it, setting it to NULL. Then drops the reference to the * passed-in framebuffer. Might take the modeset locks. * @@ -597,10 +597,7 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); void drm_framebuffer_remove(struct drm_framebuffer *fb) { struct drm_device *dev = fb->dev; - struct drm_crtc *crtc; struct drm_plane *plane; - struct drm_mode_set set; - int ret;
WARN_ON(!list_empty(&fb->filp_head));
@@ -621,19 +618,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) */ if (atomic_read(&fb->refcount.refcount) > 1) { drm_modeset_lock_all(dev); - /* remove from any CRTC */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb == fb) { - /* should turn off the crtc */ - memset(&set, 0, sizeof(struct drm_mode_set)); - set.crtc = crtc; - set.fb = NULL; - ret = drm_mode_set_config_internal(&set); - if (ret) - DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); - } - } - + /* remove from any plane */ list_for_each_entry(plane, &dev->mode_config.plane_list, head) { if (plane->fb == fb) drm_plane_force_disable(plane); @@ -1894,8 +1879,8 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->x; crtc_resp->y = crtc->y; crtc_resp->gamma_size = crtc->gamma_size; - if (crtc->fb) - crtc_resp->fb_id = crtc->fb->base.id; + if (crtc->primary->fb) + crtc_resp->fb_id = crtc->primary->fb->base.id; else crtc_resp->fb_id = 0;
@@ -2374,7 +2359,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) * crtcs. Atomic modeset will have saner semantics ... */ list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) - tmp->old_fb = tmp->fb; + tmp->old_fb = tmp->primary->fb;
fb = set->fb;
@@ -2382,13 +2367,16 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) if (ret == 0) { crtc->primary->crtc = crtc;
- /* crtc->fb must be updated by ->set_config, enforces this. */ - WARN_ON(fb != crtc->fb); + /* + * crtc->primary->fb must be updated by ->set_config, + * enforces this. + */ + WARN_ON(fb != crtc->primary->fb); }
list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { - if (tmp->fb) - drm_framebuffer_reference(tmp->fb); + if (tmp->primary->fb) + drm_framebuffer_reference(tmp->primary->fb); if (tmp->old_fb) drm_framebuffer_unreference(tmp->old_fb); } @@ -2447,12 +2435,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, /* If we have a mode we need a framebuffer. */ /* If we pass -1, set the mode with the currently bound fb */ if (crtc_req->fb_id == -1) { - if (!crtc->fb) { + if (!crtc->primary->fb) { DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); ret = -EINVAL; goto out; } - fb = crtc->fb; + fb = crtc->primary->fb; /* Make refcounting symmetric with the lookup path. */ drm_framebuffer_reference(fb); } else { @@ -3919,7 +3907,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, crtc = obj_to_crtc(obj);
mutex_lock(&crtc->mutex); - if (crtc->fb == NULL) { + if (crtc->primary->fb == NULL) { /* The framebuffer is currently unbound, presumably * due to a hotplug event, that userspace has not * yet discovered. @@ -3941,7 +3929,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (ret) goto out;
- if (crtc->fb->pixel_format != fb->pixel_format) { + if (crtc->primary->fb->pixel_format != fb->pixel_format) { DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n"); ret = -EINVAL; goto out; @@ -3974,7 +3962,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, (void (*) (struct drm_pending_event *)) kfree; }
- old_fb = crtc->fb; + old_fb = crtc->primary->fb; ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); if (ret) { if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { @@ -3987,12 +3975,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, old_fb = NULL; } else { /* - * Warn if the driver hasn't properly updated the crtc->fb - * field to reflect that the new framebuffer is now used. - * Failing to do so will screw with the reference counting - * on framebuffers. + * Warn if the driver hasn't properly updated the + * crtc->primary->fb field to reflect that the new framebuffer + * is now used. Failing to do so will screw with the reference + * counting on framebuffers. */ - WARN_ON(crtc->fb != fb); + WARN_ON(crtc->primary->fb != fb); /* Unref only the old framebuffer. */ fb = NULL; } diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index ea92b82..6d438ef 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -318,7 +318,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev) (*crtc_funcs->disable)(crtc); else (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); - crtc->fb = NULL; + crtc->primary->fb = NULL; } } } @@ -647,19 +647,19 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) save_set.mode = &set->crtc->mode; save_set.x = set->crtc->x; save_set.y = set->crtc->y; - save_set.fb = set->crtc->fb; + save_set.fb = set->crtc->primary->fb;
/* We should be able to check here if the fb has the same properties * and then just flip_or_move it */ - if (set->crtc->fb != set->fb) { + if (set->crtc->primary->fb != set->fb) { /* If we have no fb then treat it as a full mode set */ - if (set->crtc->fb == NULL) { + if (set->crtc->primary->fb == NULL) { DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); mode_changed = true; } else if (set->fb == NULL) { mode_changed = true; } else if (set->fb->pixel_format != - set->crtc->fb->pixel_format) { + set->crtc->primary->fb->pixel_format) { mode_changed = true; } else fb_changed = true; @@ -760,13 +760,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) DRM_DEBUG_KMS("attempting to set mode from" " userspace\n"); drm_mode_debug_printmodeline(set->mode); - set->crtc->fb = set->fb; + set->crtc->primary->fb = set->fb; if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x, set->y, save_set.fb)) { DRM_ERROR("failed to set mode on [CRTC:%d]\n", set->crtc->base.id); - set->crtc->fb = save_set.fb; + set->crtc->primary->fb = save_set.fb; ret = -EINVAL; goto fail; } @@ -781,13 +781,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } else if (fb_changed) { set->crtc->x = set->x; set->crtc->y = set->y; - set->crtc->fb = set->fb; + set->crtc->primary->fb = set->fb; ret = crtc_funcs->mode_set_base(set->crtc, set->x, set->y, save_set.fb); if (ret != 0) { set->crtc->x = save_set.x; set->crtc->y = save_set.y; - set->crtc->fb = save_set.fb; + set->crtc->primary->fb = save_set.fb; goto fail; } } @@ -956,7 +956,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev) continue;
ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, - crtc->x, crtc->y, crtc->fb); + crtc->x, crtc->y, + crtc->primary->fb);
if (ret == false) DRM_ERROR("failed to set mode on crtc %p\n", crtc); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index fee5759..1251260 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -232,7 +232,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
list_for_each_entry(c, &dev->mode_config.crtc_list, head) { if (crtc->base.id == c->base.id) - return c->fb; + return c->primary->fb; }
return NULL; @@ -366,9 +366,9 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) return false;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb) + if (crtc->primary->fb) crtcs_bound++; - if (crtc->fb == fb_helper->fb) + if (crtc->primary->fb == fb_helper->fb) bound++; }
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d90a707..4358751 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2132,8 +2132,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc) struct intel_encoder *intel_encoder;
seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n", - crtc->fb->base.id, crtc->x, crtc->y, - crtc->fb->width, crtc->fb->height); + crtc->primary->fb->base.id, crtc->x, crtc->y, + crtc->primary->fb->width, crtc->primary->fb->height); for_each_encoder_on_crtc(dev, crtc, intel_encoder) intel_encoder_info(m, intel_crtc, intel_encoder); } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 331f89c..9406987 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2347,8 +2347,8 @@ static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, in } else { int dspaddr = DSPADDR(intel_crtc->plane); stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) + - crtc->y * crtc->fb->pitches[0] + - crtc->x * crtc->fb->bits_per_pixel/8); + crtc->y * crtc->primary->fb->pitches[0] + + crtc->x * crtc->primary->fb->bits_per_pixel/8); }
spin_unlock_irqrestore(&dev->event_lock, flags); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9a92895..42cf4b4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -744,7 +744,7 @@ bool intel_crtc_active(struct drm_crtc *crtc) * We can ditch the crtc->fb check as soon as we can * properly reconstruct framebuffers. */ - return intel_crtc->active && crtc->fb && + return intel_crtc->active && crtc->primary->fb && intel_crtc->config.adjusted_mode.crtc_clock; }
@@ -2291,9 +2291,11 @@ void intel_display_handle_reset(struct drm_device *dev) * disabling them without disabling the entire crtc) allow again * a NULL crtc->fb. */ - if (intel_crtc->active && crtc->fb) - dev_priv->display.update_plane(crtc, crtc->fb, - crtc->x, crtc->y); + if (intel_crtc->active && crtc->primary->fb) + dev_priv->display.update_plane(crtc, + crtc->primary->fb, + crtc->x, + crtc->y); mutex_unlock(&crtc->mutex); } } @@ -2393,8 +2395,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; }
- old_fb = crtc->fb; - crtc->fb = fb; + old_fb = crtc->primary->fb; + crtc->primary->fb = fb; crtc->x = x; crtc->y = y;
@@ -3004,7 +3006,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private;
- if (crtc->fb == NULL) + if (crtc->primary->fb == NULL) return;
WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue)); @@ -3013,7 +3015,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) !intel_crtc_has_pending_flip(crtc));
mutex_lock(&dev->struct_mutex); - intel_finish_fb(crtc->fb); + intel_finish_fb(crtc->primary->fb); mutex_unlock(&dev->struct_mutex); }
@@ -4349,11 +4351,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc) assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe); assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
- if (crtc->fb) { + if (crtc->primary->fb) { mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj); + intel_unpin_fb_obj(to_intel_framebuffer(crtc->primary->fb)->obj); mutex_unlock(&dev->struct_mutex); - crtc->fb = NULL; + crtc->primary->fb = NULL; }
/* Update computed state. */ @@ -8213,7 +8215,7 @@ void intel_mark_idle(struct drm_device *dev) return;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (!crtc->fb) + if (!crtc->primary->fb) continue;
intel_decrease_pllclock(crtc); @@ -8233,10 +8235,10 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj, return;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (!crtc->fb) + if (!crtc->primary->fb) continue;
- if (to_intel_framebuffer(crtc->fb)->obj != obj) + if (to_intel_framebuffer(crtc->primary->fb)->obj != obj) continue;
intel_increase_pllclock(crtc); @@ -8664,7 +8666,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_framebuffer *old_fb = crtc->fb; + struct drm_framebuffer *old_fb = crtc->primary->fb; struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; @@ -8672,7 +8674,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, int ret;
/* Can't change pixel format via MI display flips. */ - if (fb->pixel_format != crtc->fb->pixel_format) + if (fb->pixel_format != crtc->primary->fb->pixel_format) return -EINVAL;
/* @@ -8680,8 +8682,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, * Note that pitch changes could also affect these register. */ if (INTEL_INFO(dev)->gen > 3 && - (fb->offsets[0] != crtc->fb->offsets[0] || - fb->pitches[0] != crtc->fb->pitches[0])) + (fb->offsets[0] != crtc->primary->fb->offsets[0] || + fb->pitches[0] != crtc->primary->fb->pitches[0])) return -EINVAL;
work = kzalloc(sizeof(*work), GFP_KERNEL); @@ -8721,7 +8723,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, drm_gem_object_reference(&work->old_fb_obj->base); drm_gem_object_reference(&obj->base);
- crtc->fb = fb; + crtc->primary->fb = fb;
work->pending_flip_obj = obj;
@@ -8744,7 +8746,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
cleanup_pending: atomic_dec(&intel_crtc->unpin_work_count); - crtc->fb = old_fb; + crtc->primary->fb = old_fb; drm_gem_object_unreference(&work->old_fb_obj->base); drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); @@ -9754,7 +9756,7 @@ static int intel_set_mode(struct drm_crtc *crtc,
void intel_crtc_restore_mode(struct drm_crtc *crtc) { - intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb); + intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb); }
#undef for_each_intel_crtc_masked @@ -9878,9 +9880,9 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set, * and then just flip_or_move it */ if (is_crtc_connector_off(set)) { config->mode_changed = true; - } else if (set->crtc->fb != set->fb) { + } else if (set->crtc->primary->fb != set->fb) { /* If we have no fb then treat it as a full mode set */ - if (set->crtc->fb == NULL) { + if (set->crtc->primary->fb == NULL) { struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc);
@@ -9894,7 +9896,7 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set, } else if (set->fb == NULL) { config->mode_changed = true; } else if (set->fb->pixel_format != - set->crtc->fb->pixel_format) { + set->crtc->primary->fb->pixel_format) { config->mode_changed = true; } else { config->fb_changed = true; @@ -10107,7 +10109,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set) save_set.mode = &set->crtc->mode; save_set.x = set->crtc->x; save_set.y = set->crtc->y; - save_set.fb = set->crtc->fb; + save_set.fb = set->crtc->primary->fb;
/* Compute whether we need a full modeset, only an fb base update or no * change at all. In the future we might also check whether only the @@ -11417,7 +11419,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, dev_priv->pipe_to_crtc_mapping[pipe];
__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, - crtc->fb); + crtc->primary->fb); } } else { intel_modeset_update_staged_output_state(dev); @@ -11466,7 +11468,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { /* Skip inactive CRTCs */ - if (!crtc->fb) + if (!crtc->primary->fb) continue;
intel_increase_pllclock(crtc); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c512d78..f47807b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1736,7 +1736,8 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = dig_port->base.base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj; + struct drm_i915_gem_object *obj = + to_intel_framebuffer(crtc->primary->fb)->obj; struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
dev_priv->psr.source_ok = false; @@ -1769,7 +1770,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) return false; }
- obj = to_intel_framebuffer(crtc->fb)->obj; + obj = to_intel_framebuffer(crtc->primary->fb)->obj; if (obj->tiling_mode != I915_TILING_X || obj->fence_reg == I915_FENCE_REG_NONE) { DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n"); diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 312961a..623cd32 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -606,14 +606,14 @@ static void update_colorkey(struct intel_overlay *overlay, { u32 key = overlay->color_key;
- switch (overlay->crtc->base.fb->bits_per_pixel) { + switch (overlay->crtc->base.primary->fb->bits_per_pixel) { case 8: iowrite32(0, ®s->DCLRKV); iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, ®s->DCLRKM); break;
case 16: - if (overlay->crtc->base.fb->depth == 15) { + if (overlay->crtc->base.primary->fb->depth == 15) { iowrite32(RGB15_TO_COLORKEY(key), ®s->DCLRKV); iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE, ®s->DCLRKM); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4a534c4..3ae91d5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -92,7 +92,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_framebuffer *fb = crtc->fb; + struct drm_framebuffer *fb = crtc->primary->fb; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -149,7 +149,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_framebuffer *fb = crtc->fb; + struct drm_framebuffer *fb = crtc->primary->fb; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -221,7 +221,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_framebuffer *fb = crtc->fb; + struct drm_framebuffer *fb = crtc->primary->fb; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -277,7 +277,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_framebuffer *fb = crtc->fb; + struct drm_framebuffer *fb = crtc->primary->fb; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -333,11 +333,11 @@ static void intel_fbc_work_fn(struct work_struct *__work) /* Double check that we haven't switched fb without cancelling * the prior work. */ - if (work->crtc->fb == work->fb) { + if (work->crtc->primary->fb == work->fb) { dev_priv->display.enable_fbc(work->crtc);
dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane; - dev_priv->fbc.fb_id = work->crtc->fb->base.id; + dev_priv->fbc.fb_id = work->crtc->primary->fb->base.id; dev_priv->fbc.y = work->crtc->y; }
@@ -390,7 +390,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc) }
work->crtc = crtc; - work->fb = crtc->fb; + work->fb = crtc->primary->fb; INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
dev_priv->fbc.fbc_work = work; @@ -496,14 +496,14 @@ void intel_update_fbc(struct drm_device *dev) } }
- if (!crtc || crtc->fb == NULL) { + if (!crtc || crtc->primary->fb == NULL) { if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT)) DRM_DEBUG_KMS("no output, disabling\n"); goto out_disable; }
intel_crtc = to_intel_crtc(crtc); - fb = crtc->fb; + fb = crtc->primary->fb; intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; adjusted_mode = &intel_crtc->config.adjusted_mode; @@ -1038,7 +1038,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) crtc = single_enabled_crtc(dev); if (crtc) { const struct drm_display_mode *adjusted_mode; - int pixel_size = crtc->fb->bits_per_pixel / 8; + int pixel_size = crtc->primary->fb->bits_per_pixel / 8; int clock;
adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; @@ -1118,7 +1118,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->crtc_htotal; hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; - pixel_size = crtc->fb->bits_per_pixel / 8; + pixel_size = crtc->primary->fb->bits_per_pixel / 8;
/* Use the small buffer method to calculate plane watermark */ entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; @@ -1205,7 +1205,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->crtc_htotal; hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; - pixel_size = crtc->fb->bits_per_pixel / 8; + pixel_size = crtc->primary->fb->bits_per_pixel / 8;
line_time_us = (htotal * 1000) / clock; line_count = (latency_ns / line_time_us + 1000) / 1000; @@ -1244,7 +1244,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, return false;
clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; - pixel_size = crtc->fb->bits_per_pixel / 8; /* BPP */ + pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */
entries = (clock / 1000) * pixel_size; *plane_prec_mult = (entries > 256) ? @@ -1436,7 +1436,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) int clock = adjusted_mode->crtc_clock; int htotal = adjusted_mode->crtc_htotal; int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; - int pixel_size = crtc->fb->bits_per_pixel / 8; + int pixel_size = crtc->primary->fb->bits_per_pixel / 8; unsigned long line_time_us; int entries;
@@ -1509,7 +1509,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) crtc = intel_get_crtc_for_plane(dev, 0); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode; - int cpp = crtc->fb->bits_per_pixel / 8; + int cpp = crtc->primary->fb->bits_per_pixel / 8; if (IS_GEN2(dev)) cpp = 4;
@@ -1525,7 +1525,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) crtc = intel_get_crtc_for_plane(dev, 1); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode; - int cpp = crtc->fb->bits_per_pixel / 8; + int cpp = crtc->primary->fb->bits_per_pixel / 8; if (IS_GEN2(dev)) cpp = 4;
@@ -1562,7 +1562,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) int clock = adjusted_mode->crtc_clock; int htotal = adjusted_mode->crtc_htotal; int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w; - int pixel_size = enabled->fb->bits_per_pixel / 8; + int pixel_size = enabled->primary->fb->bits_per_pixel / 8; unsigned long line_time_us; int entries;
@@ -2114,7 +2114,7 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc, if (p->active) { p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal; p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc); - p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8; + p->pri.bytes_per_pixel = crtc->primary->fb->bits_per_pixel / 8; p->cur.bytes_per_pixel = 4; p->pri.horiz_pixels = intel_crtc->config.pipe_src_w; p->cur.horiz_pixels = 64; diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index b55be84..2a5e9db 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -239,7 +239,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) struct drm_device *dev = crtc->dev; struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; - struct drm_framebuffer *fb = crtc->fb; + struct drm_framebuffer *fb = crtc->primary->fb;
/* Calculate our timings */ int horizDisplay = (mode->crtc_hdisplay >> 3) - 1; @@ -574,7 +574,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) regp->CRTC[NV_CIO_CRE_86] = 0x1; }
- regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8; + regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->primary->fb->depth + 1) / 8; /* Enable slaved mode (called MODE_TV in nv4ref.h) */ if (lvds_output || tmds_output || tv_output) regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7); @@ -588,7 +588,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS | NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL | NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON; - if (crtc->fb->depth == 16) + if (crtc->primary->fb->depth == 16) regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; if (nv_device(drm->device)->chipset >= 0x11) regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG; @@ -609,7 +609,7 @@ static int nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) { struct nv04_display *disp = nv04_display(crtc->dev); - struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); + struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); int ret;
@@ -808,7 +808,7 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, * mark the lut values as dirty by setting depth==0, and it'll be * uploaded on the first mode_set_base() */ - if (!nv_crtc->base.fb) { + if (!nv_crtc->base.primary->fb) { nv_crtc->lut.depth = 0; return; } @@ -832,7 +832,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, NV_DEBUG(drm, "index %d\n", nv_crtc->index);
/* no fb bound */ - if (!atomic && !crtc->fb) { + if (!atomic && !crtc->primary->fb) { NV_DEBUG(drm, "No FB bound\n"); return 0; } @@ -844,8 +844,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, drm_fb = passed_fb; fb = nouveau_framebuffer(passed_fb); } else { - drm_fb = crtc->fb; - fb = nouveau_framebuffer(crtc->fb); + drm_fb = crtc->primary->fb; + fb = nouveau_framebuffer(crtc->primary->fb); }
nv_crtc->fb.offset = fb->nvbo->bo.offset; @@ -857,9 +857,9 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
/* Update the framebuffer format. */ regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3; - regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8; + regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->primary->fb->depth + 1) / 8; regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; - if (crtc->fb->depth == 16) + if (crtc->primary->fb->depth == 16) regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX); NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL, diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 7fdc51e..a2d669b 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -415,7 +415,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, /* Output property. */ if ((nv_connector->dithering_mode == DITHERING_MODE_ON) || (nv_connector->dithering_mode == DITHERING_MODE_AUTO && - encoder->crtc->fb->depth > connector->display_info.bpc * 3)) { + encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) { if (nv_device(drm->device)->chipset == 0x11) regp->dither = savep->dither | 0x00010000; else { diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 2401159..4e24c72 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -569,7 +569,7 @@ nouveau_display_suspend(struct drm_device *dev) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_framebuffer *nouveau_fb;
- nouveau_fb = nouveau_framebuffer(crtc->fb); + nouveau_fb = nouveau_framebuffer(crtc->primary->fb); if (!nouveau_fb || !nouveau_fb->nvbo) continue;
@@ -596,7 +596,7 @@ nouveau_display_repin(struct drm_device *dev) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_framebuffer *nouveau_fb;
- nouveau_fb = nouveau_framebuffer(crtc->fb); + nouveau_fb = nouveau_framebuffer(crtc->primary->fb); if (!nouveau_fb || !nouveau_fb->nvbo) continue;
@@ -693,7 +693,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1; struct drm_device *dev = crtc->dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; + struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo; struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; struct nouveau_page_flip_state *s; struct nouveau_channel *chan = drm->channel; @@ -767,7 +767,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, goto fail_unreserve;
/* Update the crtc struct and cleanup */ - crtc->fb = fb; + crtc->primary->fb = fb;
nouveau_bo_fence(old_bo, fence); ttm_bo_unreserve(&old_bo->bo); diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 5706842..c744bf6 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -651,7 +651,7 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) nv_connector = nouveau_crtc_connector_get(nv_crtc); connector = &nv_connector->base; if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) { - if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3) + if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3) mode = DITHERING_MODE_DYNAMIC2X2; } else { mode = nv_connector->dithering_mode; @@ -785,7 +785,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
if (update) { nv50_display_flip_stop(crtc); - nv50_display_flip_next(crtc, crtc->fb, NULL, 1); + nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1); } }
@@ -1028,7 +1028,7 @@ nv50_crtc_commit(struct drm_crtc *crtc) }
nv50_crtc_cursor_show_hide(nv_crtc, nv_crtc->cursor.visible, true); - nv50_display_flip_next(crtc, crtc->fb, NULL, 1); + nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1); }
static bool @@ -1042,7 +1042,8 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, static int nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) { - struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); + struct nouveau_framebuffer *nvfb = + nouveau_framebuffer(crtc->primary->fb); struct nv50_head *head = nv50_head(crtc); int ret;
@@ -1139,7 +1140,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, nv50_crtc_set_dither(nv_crtc, false); nv50_crtc_set_scale(nv_crtc, false); nv50_crtc_set_color_vibrance(nv_crtc, false); - nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, false); + nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false); return 0; }
@@ -1151,7 +1152,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); int ret;
- if (!crtc->fb) { + if (!crtc->primary->fb) { NV_DEBUG(drm, "No FB bound\n"); return 0; } @@ -1161,8 +1162,8 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return ret;
nv50_display_flip_stop(crtc); - nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, true); - nv50_display_flip_next(crtc, crtc->fb, NULL, 1); + nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true); + nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1); return 0; }
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index daa4dd3..fb187c7 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1106,7 +1106,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, int r;
/* no fb bound */ - if (!atomic && !crtc->fb) { + if (!atomic && !crtc->primary->fb) { DRM_DEBUG_KMS("No FB bound\n"); return 0; } @@ -1116,8 +1116,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, target_fb = fb; } else { - radeon_fb = to_radeon_framebuffer(crtc->fb); - target_fb = crtc->fb; + radeon_fb = to_radeon_framebuffer(crtc->primary->fb); + target_fb = crtc->primary->fb; }
/* If atomic, assume fb object is pinned & idle & fenced and @@ -1316,7 +1316,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, /* set pageflip to happen anywhere in vblank interval */ WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
- if (!atomic && fb && fb != crtc->fb) { + if (!atomic && fb && fb != crtc->primary->fb) { radeon_fb = to_radeon_framebuffer(fb); rbo = gem_to_radeon_bo(radeon_fb->obj); r = radeon_bo_reserve(rbo, false); @@ -1350,7 +1350,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, int r;
/* no fb bound */ - if (!atomic && !crtc->fb) { + if (!atomic && !crtc->primary->fb) { DRM_DEBUG_KMS("No FB bound\n"); return 0; } @@ -1360,8 +1360,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, target_fb = fb; } else { - radeon_fb = to_radeon_framebuffer(crtc->fb); - target_fb = crtc->fb; + radeon_fb = to_radeon_framebuffer(crtc->primary->fb); + target_fb = crtc->primary->fb; }
obj = radeon_fb->obj; @@ -1485,7 +1485,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, /* set pageflip to happen anywhere in vblank interval */ WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
- if (!atomic && fb && fb != crtc->fb) { + if (!atomic && fb && fb != crtc->primary->fb) { radeon_fb = to_radeon_framebuffer(fb); rbo = gem_to_radeon_bo(radeon_fb->obj); r = radeon_bo_reserve(rbo, false); @@ -1972,12 +1972,12 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) int i;
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); - if (crtc->fb) { + if (crtc->primary->fb) { int r; struct radeon_framebuffer *radeon_fb; struct radeon_bo *rbo;
- radeon_fb = to_radeon_framebuffer(crtc->fb); + radeon_fb = to_radeon_framebuffer(crtc->primary->fb); rbo = gem_to_radeon_bo(radeon_fb->obj); r = radeon_bo_reserve(rbo, false); if (unlikely(r)) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index ef024ce..ea85783 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3223,12 +3223,12 @@ void r100_bandwidth_update(struct radeon_device *rdev)
if (rdev->mode_info.crtcs[0]->base.enabled) { mode1 = &rdev->mode_info.crtcs[0]->base.mode; - pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; + pixel_bytes1 = rdev->mode_info.crtcs[0]->base.primary->fb->bits_per_pixel / 8; } if (!(rdev->flags & RADEON_SINGLE_CRTC)) { if (rdev->mode_info.crtcs[1]->base.enabled) { mode2 = &rdev->mode_info.crtcs[1]->base.mode; - pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; + pixel_bytes2 = rdev->mode_info.crtcs[1]->base.primary->fb->bits_per_pixel / 8; } }
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 82d4f86..33b482b 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -89,7 +89,7 @@ static void radeon_property_change_mode(struct drm_encoder *encoder)
if (crtc && crtc->enabled) { drm_crtc_helper_set_mode(crtc, &crtc->mode, - crtc->x, crtc->y, crtc->fb); + crtc->x, crtc->y, crtc->primary->fb); } }
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index b012cbb..8f5b893 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1426,7 +1426,8 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
/* unpin the front buffers */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); + struct radeon_framebuffer *rfb = + to_radeon_framebuffer(crtc->primary->fb); struct radeon_bo *robj;
if (rfb == NULL || rfb->obj == NULL) { diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index a29d217..4e90049 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -369,7 +369,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, work->event = event; work->rdev = rdev; work->crtc_id = radeon_crtc->crtc_id; - old_radeon_fb = to_radeon_framebuffer(crtc->fb); + old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); new_radeon_fb = to_radeon_framebuffer(fb); /* schedule unpin of the old buffer */ obj = old_radeon_fb->obj; @@ -460,7 +460,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, spin_unlock_irqrestore(&dev->event_lock, flags);
/* update crtc fb */ - crtc->fb = fb; + crtc->primary->fb = fb;
r = drm_vblank_get(dev, radeon_crtc->crtc_id); if (r) { diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 0b158f9..cafb1cc 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -385,7 +385,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
DRM_DEBUG_KMS("\n"); /* no fb bound */ - if (!atomic && !crtc->fb) { + if (!atomic && !crtc->primary->fb) { DRM_DEBUG_KMS("No FB bound\n"); return 0; } @@ -395,8 +395,8 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, target_fb = fb; } else { - radeon_fb = to_radeon_framebuffer(crtc->fb); - target_fb = crtc->fb; + radeon_fb = to_radeon_framebuffer(crtc->primary->fb); + target_fb = crtc->primary->fb; }
switch (target_fb->bits_per_pixel) { @@ -444,7 +444,7 @@ retry: * We don't shutdown the display controller because new buffer * will end up in same spot. */ - if (!atomic && fb && fb != crtc->fb) { + if (!atomic && fb && fb != crtc->primary->fb) { struct radeon_bo *old_rbo; unsigned long nsize, osize;
@@ -555,7 +555,7 @@ retry: WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset); WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
- if (!atomic && fb && fb != crtc->fb) { + if (!atomic && fb && fb != crtc->primary->fb) { radeon_fb = to_radeon_framebuffer(fb); rbo = gem_to_radeon_bo(radeon_fb->obj); r = radeon_bo_reserve(rbo, false); @@ -599,7 +599,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod } }
- switch (crtc->fb->bits_per_pixel) { + switch (crtc->primary->fb->bits_per_pixel) { case 8: format = 2; break; @@ -1087,12 +1087,12 @@ static void radeon_crtc_commit(struct drm_crtc *crtc) static void radeon_crtc_disable(struct drm_crtc *crtc) { radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); - if (crtc->fb) { + if (crtc->primary->fb) { int r; struct radeon_framebuffer *radeon_fb; struct radeon_bo *rbo;
- radeon_fb = to_radeon_framebuffer(crtc->fb); + radeon_fb = to_radeon_framebuffer(crtc->primary->fb); rbo = gem_to_radeon_bo(radeon_fb->obj); r = radeon_bo_reserve(rbo, false); if (unlikely(r)) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c83321b..826e373 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -425,9 +425,6 @@ struct drm_crtc { /* primary plane for CRTC */ struct drm_plane *primary;
- /* framebuffer the connector is currently bound to */ - struct drm_framebuffer *fb; - /* Temporary tracking of the old fb while a modeset is ongoing. Used * by drm_mode_set_config_internal to implement correct refcounting. */ struct drm_framebuffer *old_fb;
Userspace clients which wish to receive all DRM planes (primary and cursor planes in addition to the traditional overlay planes) may set the DRM_CLIENT_CAP_UNIVERSAL_PLANES capability.
Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/drm_crtc.c | 20 +++++++++++++++----- drivers/gpu/drm/drm_ioctl.c | 5 +++++ include/drm/drmP.h | 5 +++++ include/uapi/drm/drm.h | 8 ++++++++ 4 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index cdfa61a..5504c4d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2106,6 +2106,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, struct drm_plane *plane; uint32_t __user *plane_ptr; int copied = 0, ret = 0; + unsigned num_planes;
if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; @@ -2113,17 +2114,26 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, drm_modeset_lock_all(dev); config = &dev->mode_config;
+ if (file_priv->universal_planes) + num_planes = config->num_total_plane; + else + num_planes = config->num_overlay_plane; + /* * This ioctl is called twice, once to determine how much space is * needed, and the 2nd time to fill it. */ - if (config->num_overlay_plane && - (plane_resp->count_planes >= config->num_overlay_plane)) { + if (num_planes && + (plane_resp->count_planes >= num_planes)) { plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
list_for_each_entry(plane, &config->plane_list, head) { - /* Only advertise overlays to userspace for now. */ - if (plane->type != DRM_PLANE_TYPE_OVERLAY) + /* + * Unless userspace set the 'universal planes' + * capability bit, only advertise overlays. + */ + if (plane->type != DRM_PLANE_TYPE_OVERLAY && + !file_priv->universal_planes) continue;
if (put_user(plane->base.id, plane_ptr + copied)) { @@ -2133,7 +2143,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, copied++; } } - plane_resp->count_planes = config->num_overlay_plane; + plane_resp->count_planes = num_planes;
out: drm_modeset_unlock_all(dev); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index f4dc9b7..5eb92b6 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -328,6 +328,11 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; file_priv->stereo_allowed = req->value; break; + case DRM_CLIENT_CAP_UNIVERSAL_PLANES: + if (req->value > 1) + return -EINVAL; + file_priv->universal_planes = req->value; + break; default: return -EINVAL; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 04a7f31..f103d69 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -437,6 +437,11 @@ struct drm_file { unsigned is_master :1; /* this file private is a master for a minor */ /* true when the client has asked us to expose stereo 3D mode flags */ unsigned stereo_allowed :1; + /* + * true if client understands CRTC primary planes and cursor planes + * in the plane list + */ + unsigned universal_planes:1;
struct pid *pid; kuid_t uid; diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index b06c8ed..6e4952b 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -637,6 +637,14 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_STEREO_3D 1
+/** + * DRM_CLIENT_CAP_UNIVERSAL_PLANES + * + * If set to 1, the DRM core will expose all planes (overlay, primary, and + * cursor) to userspace. + */ +#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 + /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability;
The name 'update_plane' was used both for the primary plane functions in intel_display.c and the sprite/overlay functions in intel_sprite.c. Rename the primary plane functions to 'update_primary_plane' to avoid confusion.
On a similar note, intel_display.c already had a function called intel_disable_primary_plane() that programs the hardware to disable a pipe's primary plane. When we hook up primary planes through the DRM plane interface, one of the natural handler names will be intel_primary_plane_disable(), which is very similar. To avoid confusion, rename the existing intel_disable_primary_plane() to intel_disable_primary_hw_plane() to make the two names a little more distinct.
Cc: Intel Graphics Development intel-gfx@lists.freedesktop.org Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 5 +-- drivers/gpu/drm/i915/intel_display.c | 60 ++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 05cfcc1..0e043d4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -450,8 +450,9 @@ struct drm_i915_display_funcs { struct drm_framebuffer *fb, struct drm_i915_gem_object *obj, uint32_t flags); - int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y); + int (*update_primary_plane)(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y); void (*hpd_irq_setup)(struct drm_device *dev); /* clock updates for mode set */ /* cursor updates */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 42cf4b4..7c09d41 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1872,15 +1872,15 @@ void intel_flush_primary_plane(struct drm_i915_private *dev_priv, }
/** - * intel_enable_primary_plane - enable the primary plane on a given pipe + * intel_enable_primary_hw_plane - enable the primary plane on a given pipe * @dev_priv: i915 private structure * @plane: plane to enable * @pipe: pipe being fed * * Enable @plane on @pipe, making sure that @pipe is running first. */ -static void intel_enable_primary_plane(struct drm_i915_private *dev_priv, - enum plane plane, enum pipe pipe) +static void intel_enable_primary_hw_plane(struct drm_i915_private *dev_priv, + enum plane plane, enum pipe pipe) { struct intel_crtc *intel_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); @@ -1905,15 +1905,15 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv, }
/** - * intel_disable_primary_plane - disable the primary plane + * intel_disable_primary_hw_plane - disable the primary hardware plane * @dev_priv: i915 private structure * @plane: plane to disable * @pipe: pipe consuming the data * * Disable @plane; should be an independent operation. */ -static void intel_disable_primary_plane(struct drm_i915_private *dev_priv, - enum plane plane, enum pipe pipe) +static void intel_disable_primary_hw_plane(struct drm_i915_private *dev_priv, + enum plane plane, enum pipe pipe) { struct intel_crtc *intel_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); @@ -2047,8 +2047,9 @@ unsigned long intel_gen4_compute_page_offset(int *x, int *y, } }
-static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y) +static int i9xx_update_primary_plane(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -2147,8 +2148,9 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, return 0; }
-static int ironlake_update_plane(struct drm_crtc *crtc, - struct drm_framebuffer *fb, int x, int y) +static int ironlake_update_primary_plane(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -2252,7 +2254,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, dev_priv->display.disable_fbc(dev); intel_increase_pllclock(crtc);
- return dev_priv->display.update_plane(crtc, fb, x, y); + return dev_priv->display.update_primary_plane(crtc, fb, x, y); }
void intel_display_handle_reset(struct drm_device *dev) @@ -2292,10 +2294,10 @@ void intel_display_handle_reset(struct drm_device *dev) * a NULL crtc->fb. */ if (intel_crtc->active && crtc->primary->fb) - dev_priv->display.update_plane(crtc, - crtc->primary->fb, - crtc->x, - crtc->y); + dev_priv->display.update_primary_plane(crtc, + crtc->primary->fb, + crtc->x, + crtc->y); mutex_unlock(&crtc->mutex); } } @@ -2387,7 +2389,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, intel_crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay; }
- ret = dev_priv->display.update_plane(crtc, fb, x, y); + ret = dev_priv->display.update_primary_plane(crtc, fb, x, y); if (ret) { intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj); mutex_unlock(&dev->struct_mutex); @@ -3589,7 +3591,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); - intel_enable_primary_plane(dev_priv, plane, pipe); + intel_enable_primary_hw_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true);
@@ -3631,7 +3633,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc) int pipe = intel_crtc->pipe; int plane = intel_crtc->plane;
- intel_enable_primary_plane(dev_priv, plane, pipe); + intel_enable_primary_hw_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true);
@@ -3661,7 +3663,7 @@ static void haswell_crtc_disable_planes(struct drm_crtc *crtc)
intel_crtc_update_cursor(crtc, false); intel_disable_planes(crtc); - intel_disable_primary_plane(dev_priv, plane, pipe); + intel_disable_primary_hw_plane(dev_priv, plane, pipe); }
/* @@ -3789,7 +3791,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
intel_crtc_update_cursor(crtc, false); intel_disable_planes(crtc); - intel_disable_primary_plane(dev_priv, plane, pipe); + intel_disable_primary_hw_plane(dev_priv, plane, pipe);
if (intel_crtc->config.has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev, pipe, false); @@ -4160,7 +4162,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); - intel_enable_primary_plane(dev_priv, plane, pipe); + intel_enable_primary_hw_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true);
@@ -4199,7 +4201,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); - intel_enable_primary_plane(dev_priv, plane, pipe); + intel_enable_primary_hw_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); /* The fixup needs to happen before cursor is enabled */ if (IS_G4X(dev)) @@ -4255,7 +4257,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_crtc_dpms_overlay(intel_crtc, false); intel_crtc_update_cursor(crtc, false); intel_disable_planes(crtc); - intel_disable_primary_plane(dev_priv, plane, pipe); + intel_disable_primary_hw_plane(dev_priv, plane, pipe);
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false); intel_disable_pipe(dev_priv, pipe); @@ -10729,28 +10731,32 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.crtc_enable = haswell_crtc_enable; dev_priv->display.crtc_disable = haswell_crtc_disable; dev_priv->display.off = haswell_crtc_off; - dev_priv->display.update_plane = ironlake_update_plane; + dev_priv->display.update_primary_plane = + ironlake_update_primary_plane; } else if (HAS_PCH_SPLIT(dev)) { dev_priv->display.get_pipe_config = ironlake_get_pipe_config; dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; dev_priv->display.crtc_enable = ironlake_crtc_enable; dev_priv->display.crtc_disable = ironlake_crtc_disable; dev_priv->display.off = ironlake_crtc_off; - dev_priv->display.update_plane = ironlake_update_plane; + dev_priv->display.update_primary_plane = + ironlake_update_primary_plane; } else if (IS_VALLEYVIEW(dev)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; dev_priv->display.crtc_enable = valleyview_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; dev_priv->display.off = i9xx_crtc_off; - dev_priv->display.update_plane = i9xx_update_plane; + dev_priv->display.update_primary_plane = + i9xx_update_primary_plane; } else { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; dev_priv->display.crtc_enable = i9xx_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; dev_priv->display.off = i9xx_crtc_off; - dev_priv->display.update_plane = i9xx_update_plane; + dev_priv->display.update_primary_plane = + i9xx_update_primary_plane; }
/* Returns the core display clock speed */
Intel hardware allows the primary plane to be disabled independently of the CRTC. Provide custom primary plane handling to allow this.
Cc: Intel Graphics Development intel-gfx@lists.freedesktop.org Signed-off-by: Matt Roper matthew.d.roper@intel.com --- drivers/gpu/drm/i915/intel_display.c | 132 ++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 1 + 2 files changed, 130 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7c09d41..2b9807a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -39,6 +39,7 @@ #include "i915_trace.h" #include <drm/drm_dp_helper.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_rect.h> #include <linux/dma_remapping.h>
static void intel_increase_pllclock(struct drm_crtc *crtc); @@ -10280,19 +10281,144 @@ static void intel_shared_dpll_init(struct drm_device *dev) BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); }
+static int +intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_framebuffer *tmpfb; + struct drm_rect dest = { + .x1 = crtc_x, + .y1 = crtc_y, + .x2 = crtc_x + crtc_w, + .y2 = crtc_y + crtc_h, + }; + struct drm_rect clip = { + .x2 = crtc->mode.hdisplay, + .y2 = crtc->mode.vdisplay, + }; + int ret; + + /* setplane API takes shifted source rectangle values; unshift them */ + src_x >>= 16; + src_y >>= 16; + src_w >>= 16; + src_h >>= 16; + + /* + * Current hardware can't reposition the primary plane or scale it + * (although this could change in the future). + */ + drm_rect_intersect(&dest, &clip); + if (dest.x1 != 0 || dest.y1 != 0 || + dest.x2 != crtc->mode.hdisplay || dest.y2 != crtc->mode.vdisplay) { + DRM_DEBUG_KMS("Primary plane must cover entire CRTC\n"); + return -EINVAL; + } + + if (crtc_w != src_w || crtc_h != src_h) { + DRM_DEBUG_KMS("Can't scale primary plane\n"); + return -EINVAL; + } + + /* + * pipe_set_base() adjusts crtc->primary->fb; however the DRM setplane + * code that called us expects to handle the framebuffer update and + * reference counting; save and restore the current fb before + * calling it. + */ + tmpfb = plane->fb; + ret = intel_pipe_set_base(crtc, src_x, src_y, fb); + if (ret) + return ret; + plane->fb = tmpfb; + + if (!intel_crtc->primary_enabled) + intel_enable_primary_hw_plane(dev_priv, intel_crtc->plane, + intel_crtc->pipe); + + return 0; +} + +static int +intel_primary_plane_disable(struct drm_plane *plane) +{ + struct drm_device *dev = plane->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_plane *intel_plane = to_intel_plane(plane); + struct intel_crtc *intel_crtc; + + if (!plane->fb) + return 0; + + if (WARN_ON(!plane->crtc)) + return -EINVAL; + + intel_crtc = to_intel_crtc(plane->crtc); + if (intel_crtc->primary_enabled) + intel_disable_primary_hw_plane(dev_priv, intel_plane->plane, + intel_plane->pipe); + + return 0; +} + +static void intel_primary_plane_destroy(struct drm_plane *plane) +{ + struct intel_plane *intel_plane = to_intel_plane(plane); + intel_primary_plane_disable(plane); + drm_plane_cleanup(plane); + kfree(intel_plane); +} + +static const struct drm_plane_funcs intel_primary_plane_funcs = { + .update_plane = intel_primary_plane_setplane, + .disable_plane = intel_primary_plane_disable, + .destroy = intel_primary_plane_destroy, +}; + +static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, + int pipe) +{ + struct intel_plane *primary; + + primary = kzalloc(sizeof(*primary), GFP_KERNEL); + if (primary == NULL) + return NULL; + + primary->can_scale = false; + primary->pipe = pipe; + primary->plane = pipe; + + drm_plane_init(dev, &primary->base, 0, + &intel_primary_plane_funcs, legacy_modeset_formats, + ARRAY_SIZE(legacy_modeset_formats), + DRM_PLANE_TYPE_PRIMARY); + return &primary->base; +} + static void intel_crtc_init(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc; struct drm_plane *primary; - int i; + int i, ret;
intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); if (intel_crtc == NULL) return;
- primary = drm_primary_helper_create_plane(dev); - drm_crtc_init(dev, &intel_crtc->base, primary, &intel_crtc_funcs); + primary = intel_primary_plane_create(dev, pipe); + ret = drm_crtc_init(dev, &intel_crtc->base, primary, &intel_crtc_funcs); + if (ret) { + drm_crtc_cleanup(&intel_crtc->base); + kfree(intel_crtc); + return; + }
drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); for (i = 0; i < 256; i++) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a4ffc02..a6e06eb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -348,6 +348,7 @@ struct intel_crtc { bool active; unsigned long enabled_power_domains; bool eld_vld; + struct intel_plane *primary_plane; bool primary_enabled; /* is the primary plane (partially) visible? */ bool lowfreq_avail; struct intel_overlay *overlay;
dri-devel@lists.freedesktop.org