Well, that escalated quickly.
I've been looking at adding modesetting support to the atomic ioctl, and this is what I've ended up with so far. It's definitely not perfect, but given how out of hand it's got at the moment, I wanted to send this out as an RFC before I spent too long polishing it up.
This series ends up touching pretty much all the drivers, by virtue of turning crtc->mode (in particular) into both a const and a pointer.
The reasoning behind this is that currently, we just treat modes as unboxed data to shovel around. With atomic modesetting, and user-supplied modes, we want to do better here. Whilst sketching out userspace/compositor requirements, I came up with the following invariants, which necessitated turning modes into a refcounted, immutable, type: - modes can come from one of three sources: connector list, current mode, userspace-created - as far as possible, modes should be relateable to their source, e.g. if Plymouth pulls a particular mode from the encoder, and you pick up on that mode as part of current configuration during handover, you should be able to work backwards to where Plymouth sourced it, i.e. the encoder list - userspace should be able to tell the current status by looking at the IDs returned by property queries, rather than having to pull the entire mode out: if we make them do that, they won't bother minimising the deltas and will just dump the full state in every time, and that makes debugging the entire thing that much harder - setting a mode current should hold a reference for as long as it's current, e.g. if you create a magic user-supplied mode, set that on the CRTC and then terminate the connection, the mode should still live on for handover purposes - persistence of system-supplied (from-connector or from-CRTC) modes is not important beyond their natural lifetime: if you pick a mode up from a connector's probed list and then that connector disappears, setting that mode is unlikely to be what you want, so failure because the mode no longer exists is entirely acceptable
The patchset so far breaks down into a few natural sets:
Hopefully-uncontroversial fixes (2).
drm: mode: Fix typo in kerneldoc drm: fb_helper: Simplify exit condition drm: mode: Allow NULL modes for equality check
Stop drivers changing crtc->mode (7) - some drivers were directly bashing crtc->mode at various points they shouldn't, which destroys our immutability guarantees, and is also generally bad form. Some of them didn't have an obvious way to pass adjusted_mode through, so I've resurrected the earlier usage of hwmode, to allow them to store and retrieve adjusted_mode from there.
drm: crtc_helper: Update hwmode before mode_set call drm: Exynos: Remove mode validation inside mode_fixup drm: Exynos: Use hwmode for adjusted_mode drm: sti: Use crtc->hwmode for adjusted mode drm: ast: Split register set from get_vbios_mode_info drm: ast: Split mode adjustment from get_vbios_mode_info drm: armada: Use crtc->hwmode for adjusted mode
Make crtc->mode const (9) - this is what I used to discover the previous 7, and is perhaps a good idea anyway. Currently this causes a bunch of warnings, which I'll get to below; the vmwgfx conversion is also totally botched and needs re-doing. i915 is probably already broken by this point.
drm: bridge: Constify mode parameters drm: encoder-slave: Constify mode parameters drm: connector-helper: Constify mode_valid parameter drm: connector-helper: Constify mode_set parameters drm: crtc-helper: Constify mode_set parameters drm: fb_helper: Constify modeset mode member DRM: Atomic: Use pointer for mode in CRTC state DRM: CRTC: Use pointer for display mode DRM: Constify crtc->mode pointer
Modes as first-class objects (9) - make modes refcountable; by this stage they're already immutable.
DRM: mode: Rename and combine drm_crtc_convert_umode DRM: mode: Un-staticise drm_mode_new_from_umode DRM: mode: Un-staticise drm_crtc_convert_to_umode drm: mode: Cache userspace mode representation drm: mode: Use cached usermode representation drm: atomic: Expose CRTC active property drm: atomic: Allow setting CRTC active property drm: mode: Add kref to modes drm: mode: Add drm_mode_reference
Use mode references throughout (4) - duplicating modes invalidates a bunch of the requirements listed above. Go through and push the core to reference every mode it gets, rather than duplicating/copying it. Applying this series causes a boatload of constness warnings due to reference counting, which I intend to fix.
drm: fb_helper: Reference, not duplicate, modes drm: crtc_helper: Reference, not duplicate, modes drm: atomic_helper: Reference, not duplicate, modes drm: i915/tegra: atomic: Reference, not duplicate, modes
Modes as properties (4) - expose the mode as a property, and also allow users to create their own mode-properties. The getblob one I'm probably most iffy about: I'd previously created a drm_property_blob underneath the mode, however juggling the translation between our two object IDs (mode and blob) was much more error-prone. It also meant we lost information just looking at the raw property stream, and had to add type/priv pointers to drm_property_blob. In the end I settled on just keeping a single drm_display_mode object, and overloading getblob to also be able to pull the userspace representation of modes.
drm: mode: Allow userspace to fetch mode as blob drm: atomic: Add MODE_ID property drm: property: Allow non-global blob properties drm: mode: Add user object-creation ioctl
Misc (1) - hi Thierry. This could probably just get squashed into the commit where we make crtc->mode a pointer though ...
Tegra: SOR: Don't always assume a valid mode
If this doesn't seem like a totally insane approach, I'll continue on with it. I think it's going to be really hard to develop a credible userspace interface without the invariance guarantees above - without that, userspace is just going to dump (hopefully) its entire state on us every frame, which is extra overhead to process, and also makes it more difficult to reason about the deltas it's providing us; debugging that is a pain.
This is in a pretty rough state right now. It's enough to get it working on Tegra (well, once hacked to claim DRIVER_ATOMIC), and is compile-tested on everything else I could enable on ARM. I haven't been able to run it on i915 or Exynos as yet, thanks to unrelated breakage in linux-next. I'm planning to sort that out this week, and get those two actually working.
Don't look too closely at the exact usage of reference counting: we're definitely leaking quite a few references, though those are easily enough fixed.
Also, the constness warnings need to be fixed up, though it hits a moderate impasse: having userspace-exposed mode objects be more obviously immutable is a good thing, however drm_display_mode is also used for internal driver code, and for generating modes in the first place; these shouldn't be immutable. My rough thought around that would be to split modes like so:
struct drm_mode_timings { hdisplay, vdisplay, ...; };
struct drm_mode_internal { struct drm_mode_timings base_timings; struct drm_mode_timings crtc_timings; };
struct drm_mode_user { struct drm_mode_object base; struct kref refcount; struct drm_mode_timings base_timings; };
struct drm_mode *drm_mode_from_internal(const struct drm_mode_internal *src); struct drm_mode *drm_mode_from_user(const struct drm_mode_modeinfo *src);
That would be a pretty huge Coccinelle run though, and certainly more invasive than what I've done right now, so whilst it's a good idea, I didn't want to go off and do it if it was just going to be immediately shot down.
So ... anyone feel like casting an eye over it?
Cheers, Daniel
drivers/gpu/drm/armada/armada_crtc.c | 21 +- drivers/gpu/drm/armada/armada_output.c | 2 +- drivers/gpu/drm/armada/armada_output.h | 2 +- drivers/gpu/drm/armada/armada_overlay.c | 4 +- drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_mode.c | 174 ++++++----- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 2 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 6 +- drivers/gpu/drm/bochs/bochs.h | 2 +- drivers/gpu/drm/bochs/bochs_hw.c | 2 +- drivers/gpu/drm/bochs/bochs_kms.c | 10 +- drivers/gpu/drm/bridge/dw_hdmi.c | 9 +- drivers/gpu/drm/cirrus/cirrus_mode.c | 8 +- drivers/gpu/drm/drm_atomic.c | 56 +++- drivers/gpu/drm/drm_atomic_helper.c | 67 +++-- drivers/gpu/drm/drm_crtc.c | 332 ++++++++++++++------- drivers/gpu/drm/drm_crtc_helper.c | 65 ++-- drivers/gpu/drm/drm_encoder_slave.c | 4 +- drivers/gpu/drm/drm_fb_helper.c | 35 ++- drivers/gpu/drm/drm_fops.c | 7 +- drivers/gpu/drm/drm_ioctl.c | 2 + drivers/gpu/drm/drm_modes.c | 147 ++++++++- drivers/gpu/drm/drm_plane_helper.c | 6 +- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_connector.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 14 +- drivers/gpu/drm/exynos/exynos_drm_drv.h | 4 +- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 14 +- drivers/gpu/drm/exynos/exynos_hdmi.c | 49 +-- drivers/gpu/drm/exynos/exynos_mixer.c | 2 +- drivers/gpu/drm/exynos/exynos_mixer.h | 2 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 6 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_dp.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 6 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 6 +- drivers/gpu/drm/gma500/mdfld_dsi_dpi.c | 4 +- drivers/gpu/drm/gma500/mdfld_dsi_dpi.h | 4 +- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 2 +- drivers/gpu/drm/gma500/mdfld_intel_display.c | 8 +- drivers/gpu/drm/gma500/oaktrail.h | 6 +- drivers/gpu/drm/gma500/oaktrail_crtc.c | 4 +- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 10 +- drivers/gpu/drm/gma500/oaktrail_lvds.c | 4 +- drivers/gpu/drm/gma500/psb_intel_display.c | 4 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 6 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 6 +- drivers/gpu/drm/i2c/adv7511.c | 6 +- drivers/gpu/drm/i2c/ch7006_drv.c | 6 +- drivers/gpu/drm/i2c/sil164_drv.c | 8 +- drivers/gpu/drm/i2c/tda998x_drv.c | 24 +- drivers/gpu/drm/i915/intel_atomic.c | 12 +- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_dp_mst.c | 2 +- drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_fbdev.c | 4 + drivers/gpu/drm/i915/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- drivers/gpu/drm/i915/intel_tv.c | 2 +- drivers/gpu/drm/imx/dw_hdmi-imx.c | 8 +- drivers/gpu/drm/imx/imx-ldb.c | 4 +- drivers/gpu/drm/imx/imx-tve.c | 6 +- drivers/gpu/drm/imx/ipuv3-crtc.c | 4 +- drivers/gpu/drm/imx/ipuv3-plane.c | 2 +- drivers/gpu/drm/imx/ipuv3-plane.h | 2 +- drivers/gpu/drm/imx/parallel-display.c | 4 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 12 +- drivers/gpu/drm/msm/edp/edp_bridge.c | 4 +- drivers/gpu/drm/msm/edp/edp_connector.c | 2 +- drivers/gpu/drm/msm/edp/edp_ctrl.c | 2 +- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 7 +- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 2 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c | 6 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c | 6 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c | 2 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 17 +- drivers/gpu/drm/nouveau/dispnv04/cursor.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/dac.c | 4 +- drivers/gpu/drm/nouveau/dispnv04/dfp.c | 4 +- drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c | 4 +- drivers/gpu/drm/nouveau/dispnv04/tvnv04.c | 4 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 8 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 4 +- drivers/gpu/drm/nouveau/nv50_display.c | 29 +- drivers/gpu/drm/omapdrm/omap_connector.c | 9 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +- drivers/gpu/drm/omapdrm/omap_drv.h | 2 +- drivers/gpu/drm/omapdrm/omap_encoder.c | 4 +- drivers/gpu/drm/qxl/qxl_display.c | 16 +- drivers/gpu/drm/radeon/atombios_crtc.c | 27 +- drivers/gpu/drm/radeon/atombios_dp.c | 2 +- drivers/gpu/drm/radeon/atombios_encoders.c | 10 +- drivers/gpu/drm/radeon/cik.c | 8 +- drivers/gpu/drm/radeon/evergreen.c | 14 +- drivers/gpu/drm/radeon/r100.c | 8 +- drivers/gpu/drm/radeon/radeon_asic.h | 4 +- drivers/gpu/drm/radeon/radeon_audio.c | 20 +- drivers/gpu/drm/radeon/radeon_audio.h | 7 +- drivers/gpu/drm/radeon/radeon_connectors.c | 12 +- drivers/gpu/drm/radeon/radeon_cursor.c | 4 +- drivers/gpu/drm/radeon/radeon_display.c | 12 +- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 14 +- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 20 +- drivers/gpu/drm/radeon/radeon_legacy_tv.c | 4 +- drivers/gpu/drm/radeon/radeon_mode.h | 10 +- drivers/gpu/drm/radeon/rs600.c | 8 +- drivers/gpu/drm/radeon/rs690.c | 28 +- drivers/gpu/drm/radeon/rs780_dpm.c | 4 +- drivers/gpu/drm/radeon/rv515.c | 32 +- drivers/gpu/drm/radeon/si.c | 14 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 6 +- drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 6 +- drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 2 +- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 6 +- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 12 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 10 +- drivers/gpu/drm/sti/sti_cursor.c | 4 +- drivers/gpu/drm/sti/sti_drm_crtc.c | 19 +- drivers/gpu/drm/sti/sti_drm_plane.c | 2 +- drivers/gpu/drm/sti/sti_dvo.c | 6 +- drivers/gpu/drm/sti/sti_gdp.c | 2 +- drivers/gpu/drm/sti/sti_hda.c | 8 +- drivers/gpu/drm/sti/sti_hdmi.c | 6 +- drivers/gpu/drm/sti/sti_layer.c | 2 +- drivers/gpu/drm/sti/sti_layer.h | 4 +- drivers/gpu/drm/sti/sti_mixer.c | 4 +- drivers/gpu/drm/sti/sti_mixer.h | 2 +- drivers/gpu/drm/sti/sti_tvout.c | 4 +- drivers/gpu/drm/sti/sti_vid.c | 2 +- drivers/gpu/drm/tegra/dc.c | 7 + drivers/gpu/drm/tegra/dsi.c | 10 +- drivers/gpu/drm/tegra/hdmi.c | 10 +- drivers/gpu/drm/tegra/rgb.c | 8 +- drivers/gpu/drm/tegra/sor.c | 11 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 17 +- drivers/gpu/drm/tilcdc/tilcdc_drv.h | 3 +- drivers/gpu/drm/tilcdc/tilcdc_panel.c | 6 +- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 3 +- drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 6 +- drivers/gpu/drm/udl/udl_connector.c | 2 +- drivers/gpu/drm/udl/udl_encoder.c | 4 +- drivers/gpu/drm/udl/udl_modeset.c | 7 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 32 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 12 +- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 10 +- include/drm/bridge/dw_hdmi.h | 2 +- include/drm/drmP.h | 6 + include/drm/drm_crtc.h | 25 +- include/drm/drm_crtc_helper.h | 20 +- include/drm/drm_encoder_slave.h | 10 +- include/drm/drm_fb_helper.h | 3 + include/drm/drm_modes.h | 10 + include/uapi/drm/drm.h | 2 + include/uapi/drm/drm_mode.h | 22 ++ 164 files changed, 1253 insertions(+), 798 deletions(-)
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_modes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 2cca85f..5388596 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1148,7 +1148,7 @@ EXPORT_SYMBOL(drm_mode_sort); /** * drm_mode_connector_list_update - update the mode list for the connector * @connector: the connector to update - * @merge_type_bits: whether to merge or overright type bits. + * @merge_type_bits: whether to merge or overwrite type bits * * This moves the modes from the @connector probed_modes list * to the actual mode list. It compares the probed mode against the current
mode is always NULL at this point in the function, so make our intention clear.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_fb_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1a20db7..27f5617 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1288,7 +1288,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
cmdline_mode = &fb_helper_conn->connector->cmdline_mode; if (cmdline_mode->specified == false) - return mode; + return NULL;
/* attempt to find a matching mode in the list of modes * we have gotten so far, if not add a CVT mode that conforms
On Thu, Mar 19, 2015 at 04:33:01AM +0000, Daniel Stone wrote:
mode is always NULL at this point in the function, so make our intention clear.
Signed-off-by: Daniel Stone daniels@collabora.com
drivers/gpu/drm/drm_fb_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1a20db7..27f5617 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1288,7 +1288,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
cmdline_mode = &fb_helper_conn->connector->cmdline_mode; if (cmdline_mode->specified == false)
return mode;
return NULL;
We can stop clearing mode with this change, so I did that on top. And there was a ugly space 2 lines below. Bikeshedding bikesheds, yay!
Applied to drm-misc, thanks. -Daniel
/* attempt to find a matching mode in the list of modes * we have gotten so far, if not add a CVT mode that conforms -- 2.3.2
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Since we're now using mode == NULL to represent disabled, it's not wholly surprising that we'd want to compare NULL modes.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_modes.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 5388596..213b11e 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -903,6 +903,12 @@ EXPORT_SYMBOL(drm_mode_duplicate); */ bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2) { + if (!mode1 && !mode2) + return true; + + if (!mode1 || !mode2) + return false; + /* do clock check convert to PICOS so fb modes get matched * the same */ if (mode1->clock && mode2->clock) {
Just as we provide crtc->mode pre-populated with the requested mode, move adjusted_mode into hwmode before we call the crtc's mode_set, making sure to restore it on failure.
Allows drivers which thoughtlessly discard adjusted_mode in their mode_set hooks (e.g. Exynos) to use hwmode directly, and also provides some neat symmetry with crtc->mode.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc_helper.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 3053aab..dd895c4 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -270,7 +270,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; - struct drm_display_mode *adjusted_mode, saved_mode; + struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct drm_encoder_helper_funcs *encoder_funcs; int saved_x, saved_y; @@ -292,6 +292,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, }
saved_mode = crtc->mode; + saved_hwmode = crtc->hwmode; saved_x = crtc->x; saved_y = crtc->y;
@@ -334,6 +335,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, } DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
+ crtc->hwmode = *adjusted_mode; + /* Prepare the encoders and CRTCs before setting the mode. */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -396,9 +399,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, encoder->bridge->funcs->enable(encoder->bridge); }
- /* Store real post-adjustment hardware mode. */ - crtc->hwmode = *adjusted_mode; - /* Calculate and store various constants which * are later needed by vblank and swap-completion * timestamping. They are derived from true hwmode. @@ -411,6 +411,7 @@ done: if (!ret) { crtc->enabled = saved_enabled; crtc->mode = saved_mode; + crtc->hwmode = saved_hwmode; crtc->x = saved_x; crtc->y = saved_y; }
On Thu, Mar 19, 2015 at 04:33:03AM +0000, Daniel Stone wrote:
Just as we provide crtc->mode pre-populated with the requested mode, move adjusted_mode into hwmode before we call the crtc's mode_set, making sure to restore it on failure.
Allows drivers which thoughtlessly discard adjusted_mode in their mode_set hooks (e.g. Exynos) to use hwmode directly, and also provides some neat symmetry with crtc->mode.
Signed-off-by: Daniel Stone daniels@collabora.com
Merged up to this patch to drm-misc, thanks. -Daniel
mode_valid is the callback we already have to check whether or not a mode is valid. So there's no need to validate again inside mode_fixup, and there's really very definitely no need to select a totally different mode.
Apparently the plan was to, if a 1366x768 mode was advertised but couldn't be expressed in the PHY, silently pick 1024x768 instead and never tell the user about it, resulting in a good chunk of the display going missing.
Just remove the entire double-validation-and-find-new-mode code; if we need to fiddle around the margins to find an acceptable pixel clock, that should be done at the very least by not completely mangling [hv]display.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/exynos/exynos_hdmi.c | 28 ---------------------------- 1 file changed, 28 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 229b361..1593b89 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1155,37 +1155,9 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct drm_display_mode *m; - int mode_ok; - DRM_DEBUG_KMS("%s\n", __FILE__);
drm_mode_set_crtcinfo(adjusted_mode, 0); - - mode_ok = hdmi_mode_valid(connector, adjusted_mode); - - /* just return if user desired mode exists. */ - if (mode_ok == MODE_OK) - return; - - /* - * otherwise, find the most suitable mode among modes and change it - * to adjusted_mode. - */ - list_for_each_entry(m, &connector->modes, head) { - mode_ok = hdmi_mode_valid(connector, m); - - if (mode_ok == MODE_OK) { - DRM_INFO("desired mode doesn't exist so\n"); - DRM_INFO("use the most suitable mode among modes.\n"); - - DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n", - m->hdisplay, m->vdisplay, m->vrefresh); - - drm_mode_copy(adjusted_mode, m); - break; - } - } }
static void hdmi_set_acr(u32 freq, u8 *acr)
On Thu, Mar 19, 2015 at 04:33:04AM +0000, Daniel Stone wrote:
mode_valid is the callback we already have to check whether or not a mode is valid. So there's no need to validate again inside mode_fixup, and there's really very definitely no need to select a totally different mode.
There is. mode_fixup is called for modeset, mode_valid by the probe helpers. But userspace can just ignore the mode list and add their owns. So yeah you'll need to validate twice.
Fixing that up is somewhere on my todo ... -Daniel
There's no need to copy adjusted_mode into crtc->mode, because that's already what crtc->hwmode is. Use that consistently instead.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 4 ++-- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 6 ------ drivers/gpu/drm/exynos/exynos_drm_fimd.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 14 ++++++++------ 4 files changed, 11 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 63f02e2..57c39bf 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -190,7 +190,7 @@ static bool decon_mode_fixup(struct exynos_drm_crtc *crtc, static void decon_commit(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; - struct drm_display_mode *mode = &crtc->base.mode; + struct drm_display_mode *mode = &crtc->base.hwmode; u32 val, clkdiv;
if (ctx->suspended) @@ -452,7 +452,7 @@ static void decon_shadow_protect_win(struct decon_context *ctx, static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos) { struct decon_context *ctx = crtc->ctx; - struct drm_display_mode *mode = &crtc->base.mode; + struct drm_display_mode *mode = &crtc->base.hwmode; struct decon_win_data *win_data; int win = zpos; unsigned long val, alpha; diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 48ccab7..5f1816c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -92,12 +92,6 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, unsigned int crtc_h; int ret;
- /* - * copy the mode data adjusted by mode_fixup() into crtc->mode - * so that hardware can be seet to proper mode. - */ - memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); - ret = exynos_check_plane(crtc->primary, fb); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 925fc69..d73b4d3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -353,7 +353,7 @@ static bool fimd_mode_fixup(struct exynos_drm_crtc *crtc, static void fimd_commit(struct exynos_drm_crtc *crtc) { struct fimd_context *ctx = crtc->ctx; - struct drm_display_mode *mode = &crtc->base.mode; + struct drm_display_mode *mode = &crtc->base.hwmode; struct fimd_driver_data *driver_data = ctx->driver_data; void *timing_base = ctx->regs + driver_data->timing_base; u32 val, clkdiv; diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 8ad5b72..5b992f9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -96,8 +96,10 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, unsigned int actual_w; unsigned int actual_h;
- actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay); - actual_h = exynos_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay); + actual_w = exynos_plane_get_size(crtc_x, crtc_w, + crtc->hwmode.hdisplay); + actual_h = exynos_plane_get_size(crtc_y, crtc_h, + crtc->hwmode.vdisplay);
if (crtc_x < 0) { if (actual_w) @@ -129,10 +131,10 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, exynos_plane->crtc_height = actual_h;
/* set drm mode data. */ - exynos_plane->mode_width = crtc->mode.hdisplay; - exynos_plane->mode_height = crtc->mode.vdisplay; - exynos_plane->refresh = crtc->mode.vrefresh; - exynos_plane->scan_flag = crtc->mode.flags; + exynos_plane->mode_width = crtc->hwmode.hdisplay; + exynos_plane->mode_height = crtc->hwmode.vdisplay; + exynos_plane->refresh = crtc->hwmode.vrefresh; + exynos_plane->scan_flag = crtc->hwmode.flags;
DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)", exynos_plane->crtc_x, exynos_plane->crtc_y,
crtc->hwmode contains the adjusted_mode from mode_set; no reason to overwrite crtc->mode (the user-specified mode) with this anymore. This mode can also be const, since we don't modify it anywhere.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/sti/sti_cursor.c | 4 ++-- drivers/gpu/drm/sti/sti_drm_crtc.c | 11 +++-------- drivers/gpu/drm/sti/sti_drm_plane.c | 2 +- drivers/gpu/drm/sti/sti_gdp.c | 2 +- drivers/gpu/drm/sti/sti_layer.c | 2 +- drivers/gpu/drm/sti/sti_layer.h | 4 ++-- drivers/gpu/drm/sti/sti_mixer.c | 4 ++-- drivers/gpu/drm/sti/sti_mixer.h | 2 +- drivers/gpu/drm/sti/sti_vid.c | 2 +- 9 files changed, 14 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index 010eaee..998b13c 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c @@ -99,7 +99,7 @@ static void sti_cursor_argb8888_to_clut8(struct sti_layer *layer) static int sti_cursor_prepare_layer(struct sti_layer *layer, bool first_prepare) { struct sti_cursor *cursor = to_sti_cursor(layer); - struct drm_display_mode *mode = layer->mode; + const struct drm_display_mode *mode = layer->mode; u32 y, x; u32 val;
@@ -166,7 +166,7 @@ static int sti_cursor_prepare_layer(struct sti_layer *layer, bool first_prepare) static int sti_cursor_commit_layer(struct sti_layer *layer) { struct sti_cursor *cursor = to_sti_cursor(layer); - struct drm_display_mode *mode = layer->mode; + const struct drm_display_mode *mode = layer->mode; u32 ydo, xdo;
dev_dbg(layer->dev, "%s %s\n", __func__, sti_layer_to_str(layer)); diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c index e6f6ef7..4721e91 100644 --- a/drivers/gpu/drm/sti/sti_drm_crtc.c +++ b/drivers/gpu/drm/sti/sti_drm_crtc.c @@ -129,17 +129,12 @@ sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, return -EINVAL; }
- /* copy the mode data adjusted by mode_fixup() into crtc->mode - * so that hardware can be set to proper mode - */ - memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); - res = sti_mixer_set_layer_depth(mixer, layer); if (res) { DRM_ERROR("Can not set layer depth\n"); return -EINVAL; } - res = sti_mixer_active_video_area(mixer, &crtc->mode); + res = sti_mixer_active_video_area(mixer, adjusted_mode); if (res) { DRM_ERROR("Can not set active video area\n"); return -EINVAL; @@ -149,7 +144,7 @@ sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, h = crtc->primary->fb->height - y;
return sti_layer_prepare(layer, crtc, - crtc->primary->fb, &crtc->mode, + crtc->primary->fb, adjusted_mode, mixer->id, 0, 0, w, h, x, y, w, h); }
@@ -177,7 +172,7 @@ static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, h = crtc->primary->fb->height - crtc->y;
ret = sti_layer_prepare(layer, crtc, - crtc->primary->fb, &crtc->mode, + crtc->primary->fb, &crtc->hwmode, mixer->id, 0, 0, w, h, crtc->x, crtc->y, w, h); if (ret) { diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c index bb6a293..42edba3 100644 --- a/drivers/gpu/drm/sti/sti_drm_plane.c +++ b/drivers/gpu/drm/sti/sti_drm_plane.c @@ -46,7 +46,7 @@ sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
/* src_x are in 16.16 format. */ res = sti_layer_prepare(layer, crtc, fb, - &crtc->mode, mixer->id, + &crtc->hwmode, mixer->id, crtc_x, crtc_y, crtc_w, crtc_h, src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16); diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 087906f..af81e8a 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -251,7 +251,7 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare) { struct sti_gdp_node_list *list; struct sti_gdp_node *top_field, *btm_field; - struct drm_display_mode *mode = layer->mode; + const struct drm_display_mode *mode = layer->mode; struct device *dev = layer->dev; struct sti_gdp *gdp = to_sti_gdp(layer); struct sti_compositor *compo = dev_get_drvdata(dev); diff --git a/drivers/gpu/drm/sti/sti_layer.c b/drivers/gpu/drm/sti/sti_layer.c index 899104f..f514989 100644 --- a/drivers/gpu/drm/sti/sti_layer.c +++ b/drivers/gpu/drm/sti/sti_layer.c @@ -83,7 +83,7 @@ EXPORT_SYMBOL(sti_layer_create); int sti_layer_prepare(struct sti_layer *layer, struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_display_mode *mode, int mixer_id, + const struct drm_display_mode *mode, int mixer_id, int dest_x, int dest_y, int dest_w, int dest_h, int src_x, int src_y, int src_w, int src_h) { diff --git a/drivers/gpu/drm/sti/sti_layer.h b/drivers/gpu/drm/sti/sti_layer.h index ceff497..50dd638 100644 --- a/drivers/gpu/drm/sti/sti_layer.h +++ b/drivers/gpu/drm/sti/sti_layer.h @@ -92,7 +92,7 @@ struct sti_layer { struct drm_plane plane; struct drm_framebuffer *fb; struct drm_crtc *crtc; - struct drm_display_mode *mode; + const struct drm_display_mode *mode; enum sti_layer_desc desc; struct device *dev; void __iomem *regs; @@ -116,7 +116,7 @@ struct sti_layer *sti_layer_create(struct device *dev, int desc, int sti_layer_prepare(struct sti_layer *layer, struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, int mixer_id, int dest_x, int dest_y, int dest_w, int dest_h, diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c index 13a4b84..45aa842 100644 --- a/drivers/gpu/drm/sti/sti_mixer.c +++ b/drivers/gpu/drm/sti/sti_mixer.c @@ -88,7 +88,7 @@ static void sti_mixer_set_background_color(struct sti_mixer *mixer, }
static void sti_mixer_set_background_area(struct sti_mixer *mixer, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { u32 ydo, xdo, yds, xds;
@@ -155,7 +155,7 @@ int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer) }
int sti_mixer_active_video_area(struct sti_mixer *mixer, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { u32 ydo, xdo, yds, xds;
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h index b972821..239f2a4 100644 --- a/drivers/gpu/drm/sti/sti_mixer.h +++ b/drivers/gpu/drm/sti/sti_mixer.h @@ -44,7 +44,7 @@ int sti_mixer_set_layer_status(struct sti_mixer *mixer, void sti_mixer_clear_all_layers(struct sti_mixer *mixer); int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer); int sti_mixer_active_video_area(struct sti_mixer *mixer, - struct drm_display_mode *mode); + const struct drm_display_mode *mode);
void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable);
diff --git a/drivers/gpu/drm/sti/sti_vid.c b/drivers/gpu/drm/sti/sti_vid.c index 10ced6a..5add4a7 100644 --- a/drivers/gpu/drm/sti/sti_vid.c +++ b/drivers/gpu/drm/sti/sti_vid.c @@ -57,7 +57,7 @@ static int sti_vid_prepare_layer(struct sti_layer *vid, bool first_prepare)
static int sti_vid_commit_layer(struct sti_layer *vid) { - struct drm_display_mode *mode = vid->mode; + const struct drm_display_mode *mode = vid->mode; u32 ydo, xdo, yds, xds;
ydo = sti_vtg_get_line_number(*mode, vid->dst_y);
Split the register-setting component of ast_get_vbios_mode_info into a separate function.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_mode.c | 70 +++++++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 86205a2..4d8b16c 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -302,6 +302,7 @@ struct ast_vbios_dclk_info { struct ast_vbios_mode_info { struct ast_vbios_stdtable *std_table; struct ast_vbios_enhtable *enh_table; + u32 color_index; };
extern int ast_mode_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index b7ee263..e8c24a5 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -78,8 +78,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo struct drm_display_mode *adjusted_mode, struct ast_vbios_mode_info *vbios_mode) { - struct ast_private *ast = crtc->dev->dev_private; - u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate; + u32 refresh_rate_index = 0, refresh_rate; u32 hborder, vborder; bool check_sync; struct ast_vbios_enhtable *best = NULL; @@ -87,16 +86,16 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo switch (crtc->primary->fb->bits_per_pixel) { case 8: vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; - color_index = VGAModeIndex - 1; + vbios_mode->color_index = VGAModeIndex - 1; break; case 16: vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; - color_index = HiCModeIndex; + vbios_mode->color_index = HiCModeIndex; break; case 24: case 32: vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; - color_index = TrueCModeIndex; + vbios_mode->color_index = TrueCModeIndex; break; default: return false; @@ -194,33 +193,45 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo vbios_mode->enh_table->vfp + vbios_mode->enh_table->vsync);
- refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; - mode_id = vbios_mode->enh_table->mode_id; - - if (ast->chip == AST1180) { - /* TODO 1180 */ - } else { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0xf) << 4)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); - - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); - if (vbios_mode->enh_table->flags & NewModeInfo) { - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->primary->fb->bits_per_pixel); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); - - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); - } - } - return true; +} + +static void ast_set_port_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) +{ + struct ast_private *ast = crtc->dev->dev_private; + u32 refresh_rate_index, mode_id, color_index;
+ if (ast->chip == AST1180) + return;
+ refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; + mode_id = vbios_mode->enh_table->mode_id; + color_index = vbios_mode->color_index; + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0xf) << 4)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); + if (vbios_mode->enh_table->flags & NewModeInfo) { + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, + crtc->primary->fb->bits_per_pixel); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, + mode->clock / 1000); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, + mode->crtc_hdisplay); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, + mode->crtc_hdisplay >> 8); + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, + mode->crtc_vdisplay); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, + mode->crtc_vdisplay >> 8); + } } + static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { @@ -579,6 +590,9 @@ static int ast_crtc_mode_set(struct drm_crtc *crtc, ret = ast_get_vbios_mode_info(crtc, mode, adjusted_mode, &vbios_mode); if (ret == false) return -EINVAL; + + ast_set_port_reg(crtc, adjusted_mode, &vbios_mode); + ast_open_key(ast);
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
Further to the previous commit, instead of performing mode adjustment inside a getter function called from mode_set, actually perform it in mode_fixup instead. This allows us to drop the extra mode argument and constify our original mode.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/ast/ast_mode.c | 63 +++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index e8c24a5..fcef5a6 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -74,12 +74,11 @@ static void ast_crtc_load_lut(struct drm_crtc *crtc) ast_crtc->lut_g[i], ast_crtc->lut_b[i]); }
-static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, +static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, + const struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { u32 refresh_rate_index = 0, refresh_rate; - u32 hborder, vborder; bool check_sync; struct ast_vbios_enhtable *best = NULL;
@@ -172,27 +171,6 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo if (best) vbios_mode->enh_table = best;
- hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; - vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; - - adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht; - adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder; - adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder; - adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder + - vbios_mode->enh_table->hfp; - adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder + - vbios_mode->enh_table->hfp + - vbios_mode->enh_table->hsync); - - adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt; - adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder; - adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder; - adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder + - vbios_mode->enh_table->vfp; - adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder + - vbios_mode->enh_table->vfp + - vbios_mode->enh_table->vsync); - return true; }
@@ -512,6 +490,37 @@ static bool ast_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + struct ast_vbios_mode_info vbios_mode; + u32 hborder, vborder; + bool ret; + + ret = ast_get_vbios_mode_info(crtc, mode, &vbios_mode); + if (!ret) + return false; + + hborder = (vbios_mode.enh_table->flags & HBorder) ? 8 : 0; + vborder = (vbios_mode.enh_table->flags & VBorder) ? 8 : 0; + + adjusted_mode->crtc_htotal = vbios_mode.enh_table->ht; + adjusted_mode->crtc_hblank_start = vbios_mode.enh_table->hde + hborder; + adjusted_mode->crtc_hblank_end = vbios_mode.enh_table->ht - hborder; + adjusted_mode->crtc_hsync_start = + vbios_mode.enh_table->hde + hborder + vbios_mode.enh_table->hfp; + adjusted_mode->crtc_hsync_end = + (vbios_mode.enh_table->hde + hborder + + vbios_mode.enh_table->hfp + + vbios_mode.enh_table->hsync); + + adjusted_mode->crtc_vtotal = vbios_mode.enh_table->vt; + adjusted_mode->crtc_vblank_start = vbios_mode.enh_table->vde + vborder; + adjusted_mode->crtc_vblank_end = vbios_mode.enh_table->vt - vborder; + adjusted_mode->crtc_vsync_start = + vbios_mode.enh_table->vde + vborder + vbios_mode.enh_table->vfp; + adjusted_mode->crtc_vsync_end = + (vbios_mode.enh_table->vde + vborder + + vbios_mode.enh_table->vfp + + vbios_mode.enh_table->vsync); + return true; }
@@ -587,7 +596,11 @@ static int ast_crtc_mode_set(struct drm_crtc *crtc, return -EINVAL; }
- ret = ast_get_vbios_mode_info(crtc, mode, adjusted_mode, &vbios_mode); + /* mode_fixup should have already returned false if + * ast_get_vbios_mode_info would have failed, so if that happens + * here then something has gone wrong. */ + ret = ast_get_vbios_mode_info(crtc, mode, &vbios_mode); + WARN_ON(ret == false); if (ret == false) return -EINVAL;
crtc->hwmode contains the adjusted_mode from mode_set; no reason to overwrite crtc->mode (the user-specified mode) with this anymore.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/armada/armada_crtc.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 42d2ffa..c74faf9 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -133,11 +133,11 @@ static void armada_drm_crtc_update(struct armada_crtc *dcrtc) * The non-inverted state of the sync signals is active high. * Setting these bits makes the appropriate signal active low. */ - if (dcrtc->crtc.mode.flags & DRM_MODE_FLAG_NCSYNC) + if (dcrtc->crtc.hwmode.flags & DRM_MODE_FLAG_NCSYNC) dumb_ctrl |= CFG_INV_CSYNC; - if (dcrtc->crtc.mode.flags & DRM_MODE_FLAG_NHSYNC) + if (dcrtc->crtc.hwmode.flags & DRM_MODE_FLAG_NHSYNC) dumb_ctrl |= CFG_INV_HSYNC; - if (dcrtc->crtc.mode.flags & DRM_MODE_FLAG_NVSYNC) + if (dcrtc->crtc.hwmode.flags & DRM_MODE_FLAG_NVSYNC) dumb_ctrl |= CFG_INV_VSYNC;
if (dcrtc->dumb_ctrl != dumb_ctrl) { @@ -457,7 +457,7 @@ void armada_drm_crtc_enable_irq(struct armada_crtc *dcrtc, u32 mask)
static uint32_t armada_drm_crtc_calculate_csc(struct armada_crtc *dcrtc) { - struct drm_display_mode *adj = &dcrtc->crtc.mode; + struct drm_display_mode *adj = &dcrtc->crtc.hwmode; uint32_t val = 0;
if (dcrtc->csc_yuv_mode == CSC_YUV_CCIR709) @@ -531,8 +531,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
- crtc->mode = *adj; - val = dcrtc->dumb_ctrl & ~CFG_DUMB_ENA; if (val != dcrtc->dumb_ctrl) { dcrtc->dumb_ctrl = val; @@ -735,10 +733,10 @@ static int armada_drm_crtc_cursor_update(struct armada_crtc *dcrtc, bool reload) xoff = -dcrtc->cursor_x; xscr = 0; w -= min(xoff, w); - } else if (dcrtc->cursor_x + w > dcrtc->crtc.mode.hdisplay) { + } else if (dcrtc->cursor_x + w > dcrtc->crtc.hwmode.hdisplay) { xoff = 0; xscr = dcrtc->cursor_x; - w = max_t(int, dcrtc->crtc.mode.hdisplay - dcrtc->cursor_x, 0); + w = max_t(int, dcrtc->crtc.hwmode.hdisplay - dcrtc->cursor_x, 0); } else { xoff = 0; xscr = dcrtc->cursor_x; @@ -748,10 +746,10 @@ static int armada_drm_crtc_cursor_update(struct armada_crtc *dcrtc, bool reload) yoff = -dcrtc->cursor_y; yscr = 0; h -= min(yoff, h); - } else if (dcrtc->cursor_y + h > dcrtc->crtc.mode.vdisplay) { + } else if (dcrtc->cursor_y + h > dcrtc->crtc.hwmode.vdisplay) { yoff = 0; yscr = dcrtc->cursor_y; - h = max_t(int, dcrtc->crtc.mode.vdisplay - dcrtc->cursor_y, 0); + h = max_t(int, dcrtc->crtc.hwmode.vdisplay - dcrtc->cursor_y, 0); } else { yoff = 0; yscr = dcrtc->cursor_y;
Enforce the existing rules on when modes can be modified (never modify the passed-in mode; only modify adjusted_mode in mode_fixup), by adding const.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/bridge/dw_hdmi.c | 7 ++++--- drivers/gpu/drm/msm/edp/edp_bridge.c | 4 ++-- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 7 +++---- drivers/gpu/drm/sti/sti_dvo.c | 4 ++-- drivers/gpu/drm/sti/sti_hda.c | 4 ++-- drivers/gpu/drm/sti/sti_hdmi.c | 4 ++-- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 3 ++- drivers/gpu/drm/tilcdc/tilcdc_drv.h | 3 ++- include/drm/drm_crtc.h | 4 ++-- 9 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c index cd6a706..7b1dbb4 100644 --- a/drivers/gpu/drm/bridge/dw_hdmi.c +++ b/drivers/gpu/drm/bridge/dw_hdmi.c @@ -1174,7 +1174,8 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) HDMI_IH_MUTE_FC_STAT2); }
-static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) +static int dw_hdmi_setup(struct dw_hdmi *hdmi, + const struct drm_display_mode *mode) { int ret;
@@ -1341,8 +1342,8 @@ static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) }
static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge, - struct drm_display_mode *orig_mode, - struct drm_display_mode *mode) + const struct drm_display_mode *orig_mode, + const struct drm_display_mode *mode) { struct dw_hdmi *hdmi = bridge->driver_private;
diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c index 2bc73f8..8c09a2e 100644 --- a/drivers/gpu/drm/msm/edp/edp_bridge.c +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c @@ -52,8 +52,8 @@ static void edp_bridge_post_disable(struct drm_bridge *bridge) }
static void edp_bridge_mode_set(struct drm_bridge *bridge, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = bridge->dev; struct drm_connector *connector; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index a7a1d82..2eb59eb 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -130,16 +130,15 @@ static void hdmi_bridge_post_disable(struct drm_bridge *bridge) }
static void hdmi_bridge_mode_set(struct drm_bridge *bridge, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *drm_mode, + const struct drm_display_mode *adjusted_mode) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; + const struct drm_display_mode *mode = adjusted_mode; int hstart, hend, vstart, vend; uint32_t frame_ctrl;
- mode = adjusted_mode; - hdmi->pixclock = mode->clock * 1000;
hdmi->hdmi_mode = drm_match_cea_mode(mode) > 1; diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index aeb5070..b29272c 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -226,8 +226,8 @@ static void sti_dvo_pre_enable(struct drm_bridge *bridge) }
static void sti_dvo_set_mode(struct drm_bridge *bridge, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct sti_dvo *dvo = bridge->driver_private; struct sti_mixer *mixer = to_sti_mixer(dvo->encoder->crtc); diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index a9bbb08..4a15d45 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -459,8 +459,8 @@ static void sti_hda_pre_enable(struct drm_bridge *bridge) }
static void sti_hda_set_mode(struct drm_bridge *bridge, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct sti_hda *hda = bridge->driver_private; u32 mode_idx; diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 1485ade..fc26a8c 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -527,8 +527,8 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge) }
static void sti_hdmi_set_mode(struct drm_bridge *bridge, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct sti_hdmi *hdmi = bridge->driver_private; int ret; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index c735884..8514055 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -438,7 +438,8 @@ int tilcdc_crtc_max_width(struct drm_crtc *crtc) return max_width; }
-int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) +int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct tilcdc_drm_private *priv = crtc->dev->dev_private; unsigned int bandwidth; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 7596c14..f53c278 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -166,7 +166,8 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc); void tilcdc_crtc_update_clk(struct drm_crtc *crtc); void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, const struct tilcdc_panel_info *info); -int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode); +int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode); int tilcdc_crtc_max_width(struct drm_crtc *crtc);
#endif /* __TILCDC_DRV_H__ */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 2e80ad1..dbc1510 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -886,8 +886,8 @@ struct drm_bridge_funcs { void (*disable)(struct drm_bridge *bridge); void (*post_disable)(struct drm_bridge *bridge); void (*mode_set)(struct drm_bridge *bridge, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode); void (*pre_enable)(struct drm_bridge *bridge); void (*enable)(struct drm_bridge *bridge); };
Enforce the existing rules on when modes can be modified (never modify the passed-in mode; only modify adjusted_mode in mode_fixup), by adding const.
tilcdc gains an interim helper function, as it registers an encoder mode_set (as yet non-const), which directly calls the slave helper (newly const). This can disappear when normal encoder functions gain constness.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/armada/armada_slave.c | 10 +++++++++- drivers/gpu/drm/drm_encoder_slave.c | 4 ++-- drivers/gpu/drm/i2c/adv7511.c | 6 +++--- drivers/gpu/drm/i2c/ch7006_drv.c | 6 +++--- drivers/gpu/drm/i2c/sil164_drv.c | 6 +++--- drivers/gpu/drm/i2c/tda998x_drv.c | 18 ++++++++++-------- drivers/gpu/drm/msm/edp/edp_ctrl.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 4 ++-- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 8 +++++++- include/drm/drm_encoder_slave.h | 10 +++++----- 10 files changed, 45 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_slave.c b/drivers/gpu/drm/armada/armada_slave.c index 00d0fac..a58f4f9 100644 --- a/drivers/gpu/drm/armada/armada_slave.c +++ b/drivers/gpu/drm/armada/armada_slave.c @@ -42,6 +42,14 @@ static void armada_drm_slave_destroy(struct drm_encoder *enc) kfree(slave); }
+static void armada_drm_slave_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + drm_i2c_encoder_mode_set(encoder, mode, adjusted_mode); +} + + static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = { .destroy = armada_drm_slave_destroy, }; @@ -59,7 +67,7 @@ static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = { .mode_fixup = drm_i2c_encoder_mode_fixup, .prepare = drm_i2c_encoder_prepare, .commit = drm_i2c_encoder_commit, - .mode_set = drm_i2c_encoder_mode_set, + .mode_set = armada_drm_slave_mode_set, .detect = drm_i2c_encoder_detect, };
diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c index d18b88b..41edd73 100644 --- a/drivers/gpu/drm/drm_encoder_slave.c +++ b/drivers/gpu/drm/drm_encoder_slave.c @@ -157,8 +157,8 @@ void drm_i2c_encoder_commit(struct drm_encoder *encoder) EXPORT_SYMBOL(drm_i2c_encoder_commit);
void drm_i2c_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode); } diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c index 61aa824..534f0a3 100644 --- a/drivers/gpu/drm/i2c/adv7511.c +++ b/drivers/gpu/drm/i2c/adv7511.c @@ -639,7 +639,7 @@ adv7511_encoder_detect(struct drm_encoder *encoder, }
static int adv7511_encoder_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock > 165000) return MODE_CLOCK_HIGH; @@ -648,8 +648,8 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder, }
static void adv7511_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adj_mode) { struct adv7511 *adv7511 = encoder_to_adv7511(encoder); unsigned int low_refresh_rate; diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 51fa323..77c6c95 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -102,7 +102,7 @@ static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, }
static int ch7006_encoder_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (ch7006_lookup_mode(encoder, mode)) return MODE_OK; @@ -111,8 +111,8 @@ static int ch7006_encoder_mode_valid(struct drm_encoder *encoder, }
static void ch7006_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *drm_mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *drm_mode, + const struct drm_display_mode *adjusted_mode) { struct i2c_client *client = drm_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c index 002ce78..dd7cea2 100644 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ b/drivers/gpu/drm/i2c/sil164_drv.c @@ -262,7 +262,7 @@ sil164_encoder_mode_fixup(struct drm_encoder *encoder,
static int sil164_encoder_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct sil164_priv *priv = to_sil164_priv(encoder);
@@ -278,8 +278,8 @@ sil164_encoder_mode_valid(struct drm_encoder *encoder,
static void sil164_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct sil164_priv *priv = to_sil164_priv(encoder); bool duallink = adjusted_mode->clock > 165000; diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 5febffd..f697443 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -632,7 +632,8 @@ tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) }
static void -tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode) +tda998x_write_avi(struct tda998x_priv *priv, + const struct drm_display_mode *mode) { u8 buf[PB(HDMI_AVI_INFOFRAME_SIZE) + 1];
@@ -662,7 +663,8 @@ static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
static void tda998x_configure_audio(struct tda998x_priv *priv, - struct drm_display_mode *mode, struct tda998x_encoder_params *p) + const struct drm_display_mode *mode, + struct tda998x_encoder_params *p) { uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv; uint32_t n; @@ -825,7 +827,7 @@ tda998x_encoder_mode_fixup(struct drm_encoder *encoder, }
static int tda998x_encoder_mode_valid(struct tda998x_priv *priv, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock > 150000) return MODE_CLOCK_HIGH; @@ -838,8 +840,8 @@ static int tda998x_encoder_mode_valid(struct tda998x_priv *priv,
static void tda998x_encoder_mode_set(struct tda998x_priv *priv, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { uint16_t ref_pix, ref_line, n_pix, n_line; uint16_t hs_pix_s, hs_pix_e; @@ -1176,15 +1178,15 @@ static void tda998x_encoder_slave_dpms(struct drm_encoder *encoder, int mode) }
static int tda998x_encoder_slave_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { return tda998x_encoder_mode_valid(to_tda998x_priv(encoder), mode); }
static void tda998x_encoder_slave_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { tda998x_encoder_mode_set(to_tda998x_priv(encoder), mode, adjusted_mode); } diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c index 0ec5abd..f5ae491 100644 --- a/drivers/gpu/drm/msm/edp/edp_ctrl.c +++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c @@ -1280,7 +1280,7 @@ unlock_ret: }
int msm_edp_ctrl_timing_cfg(struct edp_ctrl *ctrl, - const struct drm_display_mode *mode, + const const struct drm_display_mode *mode, const struct drm_display_info *info) { u32 hstart_from_sync, vstart_from_sync; diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index 731d74e..c77ffe3 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -309,7 +309,7 @@ static int nv17_tv_get_modes(struct drm_encoder *encoder, }
static int nv17_tv_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
@@ -524,7 +524,7 @@ static void nv17_tv_mode_set(struct drm_encoder *encoder, tv_regs->tv_enc[i] = tv_norm->tv_enc_mode.tv_enc[i];
} else { - struct drm_display_mode *output_mode = + const struct drm_display_mode *output_mode = &tv_norm->ctv_enc_mode.mode;
/* The registers in PRAMDAC+0xc00 control some timings and CSC diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index 3775fd4..5842845 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -96,6 +96,12 @@ static bool slave_encoder_fixup(struct drm_encoder *encoder, return drm_i2c_encoder_mode_fixup(encoder, mode, adjusted_mode); }
+static void slave_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + drm_i2c_encoder_mode_set(encoder, mode, adjusted_mode); +}
static const struct drm_encoder_funcs slave_encoder_funcs = { .destroy = slave_encoder_destroy, @@ -106,7 +112,7 @@ static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = { .mode_fixup = slave_encoder_fixup, .prepare = slave_encoder_prepare, .commit = drm_i2c_encoder_commit, - .mode_set = drm_i2c_encoder_mode_set, + .mode_set = slave_encoder_mode_set, .save = drm_i2c_encoder_save, .restore = drm_i2c_encoder_restore, }; diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h index 8b9cc36..c99c636 100644 --- a/include/drm/drm_encoder_slave.h +++ b/include/drm/drm_encoder_slave.h @@ -57,10 +57,10 @@ struct drm_encoder_slave_funcs { const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); int (*mode_valid)(struct drm_encoder *encoder, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); void (*mode_set)(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode);
enum drm_connector_status (*detect)(struct drm_encoder *encoder, struct drm_connector *connector); @@ -171,8 +171,8 @@ bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder, void drm_i2c_encoder_prepare(struct drm_encoder *encoder); void drm_i2c_encoder_commit(struct drm_encoder *encoder); void drm_i2c_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode); enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder, struct drm_connector *connector); void drm_i2c_encoder_save(struct drm_encoder *encoder);
Enforce the existing rules on when modes can be modified (never modify the passed-in mode; only modify adjusted_mode in mode_fixup), by adding const.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/armada/armada_output.c | 2 +- drivers/gpu/drm/armada/armada_output.h | 2 +- drivers/gpu/drm/ast/ast_mode.c | 2 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 2 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 2 +- drivers/gpu/drm/bochs/bochs_kms.c | 2 +- drivers/gpu/drm/bridge/dw_hdmi.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_connector.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 +- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 2 +- drivers/gpu/drm/exynos/exynos_hdmi.c | 2 +- drivers/gpu/drm/exynos/exynos_mixer.c | 2 +- drivers/gpu/drm/exynos/exynos_mixer.h | 2 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 2 +- drivers/gpu/drm/gma500/cdv_intel_dp.c | 2 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 2 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 2 +- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 2 +- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 2 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 2 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 2 +- drivers/gpu/drm/i2c/tda998x_drv.c | 2 +- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_dp_mst.c | 2 +- drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- drivers/gpu/drm/i915/intel_tv.c | 2 +- drivers/gpu/drm/imx/dw_hdmi-imx.c | 4 ++-- drivers/gpu/drm/imx/imx-tve.c | 2 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 4 ++-- drivers/gpu/drm/msm/edp/edp_connector.c | 2 +- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 2 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +- drivers/gpu/drm/omapdrm/omap_connector.c | 9 ++++----- drivers/gpu/drm/omapdrm/omap_drv.h | 2 +- drivers/gpu/drm/qxl/qxl_display.c | 2 +- drivers/gpu/drm/radeon/atombios_dp.c | 2 +- drivers/gpu/drm/radeon/radeon_connectors.c | 10 +++++----- drivers/gpu/drm/radeon/radeon_mode.h | 2 +- drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 2 +- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- drivers/gpu/drm/sti/sti_dvo.c | 2 +- drivers/gpu/drm/sti/sti_hda.c | 4 ++-- drivers/gpu/drm/sti/sti_hdmi.c | 2 +- drivers/gpu/drm/tegra/dsi.c | 2 +- drivers/gpu/drm/tegra/hdmi.c | 2 +- drivers/gpu/drm/tegra/rgb.c | 2 +- drivers/gpu/drm/tegra/sor.c | 2 +- drivers/gpu/drm/tilcdc/tilcdc_panel.c | 2 +- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 2 +- drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 2 +- drivers/gpu/drm/udl/udl_connector.c | 2 +- include/drm/bridge/dw_hdmi.h | 2 +- include/drm/drm_crtc_helper.h | 2 +- 59 files changed, 69 insertions(+), 70 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c index abbc309..9bf80e9 100644 --- a/drivers/gpu/drm/armada/armada_output.c +++ b/drivers/gpu/drm/armada/armada_output.c @@ -90,7 +90,7 @@ bool armada_drm_encoder_mode_fixup(struct drm_encoder *encoder,
/* Shouldn't this be a generic helper function? */ int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_encoder *encoder = armada_drm_connector_encoder(conn); int valid = MODE_BAD; diff --git a/drivers/gpu/drm/armada/armada_output.h b/drivers/gpu/drm/armada/armada_output.h index 4126d43..f0ffc5c 100644 --- a/drivers/gpu/drm/armada/armada_output.h +++ b/drivers/gpu/drm/armada/armada_output.h @@ -28,7 +28,7 @@ bool armada_drm_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adj);
int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn, - struct drm_display_mode *mode); + const struct drm_display_mode *mode);
int armada_drm_slave_encoder_set_property(struct drm_connector *conn, struct drm_property *property, uint64_t value); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index fcef5a6..8069448 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -815,7 +815,7 @@ static int ast_get_modes(struct drm_connector *connector) }
static int ast_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct ast_private *ast = connector->dev->dev_private; int flags = MODE_NOMODE; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index c4bb1f9f..40852c6 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -141,7 +141,7 @@ static const struct of_device_id atmel_hlcdc_of_match[] = { };
int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int vfront_porch = mode->vsync_start - mode->vdisplay; int vback_porch = mode->vtotal - mode->vsync_end; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c index 9c45130..b6a7ee4 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c @@ -169,7 +169,7 @@ static int atmel_hlcdc_panel_get_modes(struct drm_connector *connector) }
static int atmel_hlcdc_rgb_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct atmel_hlcdc_rgb_output *rgb = drm_connector_to_atmel_hlcdc_rgb_output(connector); diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 26bcd03..a61a42e 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -211,7 +211,7 @@ int bochs_connector_get_modes(struct drm_connector *connector) }
static int bochs_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct bochs_device *bochs = container_of(connector, struct bochs_device, connector); diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c index 7b1dbb4..f8c09c7 100644 --- a/drivers/gpu/drm/bridge/dw_hdmi.c +++ b/drivers/gpu/drm/bridge/dw_hdmi.c @@ -1416,7 +1416,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
static enum drm_mode_status dw_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector); diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index ba9b3d5..fbd400a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -95,7 +95,7 @@ out: }
static int exynos_drm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct exynos_drm_connector *exynos_connector = to_exynos_connector(connector); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 9afd390..0910c66 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -139,7 +139,7 @@ struct exynos_drm_display_ops { void (*mode_set)(struct exynos_drm_display *display, struct drm_display_mode *mode); int (*check_mode)(struct exynos_drm_display *display, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); void (*dpms)(struct exynos_drm_display *display, int mode); void (*commit)(struct exynos_drm_display *display); }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 05fe93d..885317a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1474,7 +1474,7 @@ static int exynos_dsi_get_modes(struct drm_connector *connector) }
static int exynos_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { return MODE_OK; } diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 1593b89..abbe438 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1091,7 +1091,7 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) }
static int hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct hdmi_context *hdata = ctx_from_connector(connector); int ret; diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 3518bc4..2924c44 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1162,7 +1162,7 @@ static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode) }
/* Only valid for Mixer version 16.0.33.0 */ -int mixer_check_mode(struct drm_display_mode *mode) +int mixer_check_mode(const struct drm_display_mode *mode) { u32 w, h;
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.h b/drivers/gpu/drm/exynos/exynos_mixer.h index 3811e41..3d8fda7 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.h +++ b/drivers/gpu/drm/exynos/exynos_mixer.h @@ -15,6 +15,6 @@ #define _EXYNOS_MIXER_H_
/* This function returns 0 if the given timing is valid for the mixer */ -int mixer_check_mode(struct drm_display_mode *mode); +int mixer_check_mode(const struct drm_display_mode *mode);
#endif diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 248c33a..9152105 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -65,7 +65,7 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) }
static int cdv_intel_crt_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 0fafb8e..506f5d2 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -508,7 +508,7 @@ static void cdv_intel_edp_backlight_off (struct gma_encoder *intel_encoder)
static int cdv_intel_dp_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct gma_encoder *encoder = gma_attached_encoder(connector); struct cdv_intel_dp *intel_dp = encoder->dev_priv; diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index 4268bf2..19a73c8 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -224,7 +224,7 @@ static int cdv_hdmi_get_modes(struct drm_connector *connector) }
static int cdv_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock > 165000) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index 0b77039..c416fbe 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -245,7 +245,7 @@ static void cdv_intel_lvds_restore(struct drm_connector *connector) }
static int cdv_intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct drm_psb_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c index abf2248..c018af6 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c @@ -352,7 +352,7 @@ static int mdfld_dsi_connector_get_modes(struct drm_connector *connector) }
static int mdfld_dsi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct mdfld_dsi_connector *dsi_connector = mdfld_dsi_connector(connector); diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index 54f73f5..fcdfe78 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -510,7 +510,7 @@ static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode) }
static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock > 165000) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index 88aad95..12fac19 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -344,7 +344,7 @@ static void psb_intel_lvds_restore(struct drm_connector *connector) }
int psb_intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_psb_private *dev_priv = connector->dev->dev_private; struct gma_encoder *gma_encoder = gma_attached_encoder(connector); diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 58529ce..73b17eb 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -1159,7 +1159,7 @@ static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) }
static int psb_intel_sdvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector);
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index f697443..f20754b 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1451,7 +1451,7 @@ static int tda998x_connector_get_modes(struct drm_connector *connector) }
static int tda998x_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index e66e17a..1470a37 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -277,7 +277,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
static enum drm_mode_status intel_crt_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 33d5877..58bf6e9 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -197,7 +197,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_dp *intel_dp = intel_attached_dp(connector); struct intel_connector *intel_connector = to_intel_connector(connector); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index be12492..5d28e3f 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -326,7 +326,7 @@ static int intel_dp_mst_get_modes(struct drm_connector *connector)
static enum drm_mode_status intel_dp_mst_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { /* TODO - validate mode against available PBN for link */ if (mode->clock < 10000) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index c8c8b24..8b4e87c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -642,7 +642,7 @@ static void intel_dsi_get_config(struct intel_encoder *encoder,
static enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index d857951..14fa27c 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -242,7 +242,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
static enum drm_mode_status intel_dvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 995c5b2..37cdc74 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -932,7 +932,7 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit)
static enum drm_mode_status intel_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int clock = mode->clock;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 24e8730..0f1470b 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -264,7 +264,7 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
static enum drm_mode_status intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 9e554c2..04956d3 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1552,7 +1552,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
static enum drm_mode_status intel_sdvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 892d23c..86a526e 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -893,7 +893,7 @@ intel_tv_mode_find(struct intel_tv *intel_tv)
static enum drm_mode_status intel_tv_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_tv *intel_tv = intel_attached_tv(connector); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index 87fe8ed..543ce72 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c @@ -139,7 +139,7 @@ static struct drm_encoder_funcs dw_hdmi_imx_encoder_funcs = { };
static enum drm_mode_status imx6q_hdmi_mode_valid(struct drm_connector *con, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock < 13500) return MODE_CLOCK_LOW; @@ -150,7 +150,7 @@ static enum drm_mode_status imx6q_hdmi_mode_valid(struct drm_connector *con, }
static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock < 13500) return MODE_CLOCK_LOW; diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index 4216e47..165a9d6 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -246,7 +246,7 @@ static int imx_tve_connector_get_modes(struct drm_connector *connector) }
static int imx_tve_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct imx_tve *tve = con_to_tve(connector); unsigned long rate; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 9872ba9..f99c53d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1453,7 +1453,7 @@ static int mga_vga_get_modes(struct drm_connector *connector) return ret; }
-static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode *mode, +static uint32_t mga_vga_calculate_mode_bandwidth(const struct drm_display_mode *mode, int bits_per_pixel) { uint32_t total_area, divisor; @@ -1480,7 +1480,7 @@ static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode *mode, #define MODE_BANDWIDTH MODE_BAD
static int mga_vga_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct mga_device *mdev = (struct mga_device*)dev->dev_private; diff --git a/drivers/gpu/drm/msm/edp/edp_connector.c b/drivers/gpu/drm/msm/edp/edp_connector.c index d8812e8..101504a 100644 --- a/drivers/gpu/drm/msm/edp/edp_connector.c +++ b/drivers/gpu/drm/msm/edp/edp_connector.c @@ -64,7 +64,7 @@ static int edp_connector_get_modes(struct drm_connector *connector) }
static int edp_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct edp_connector *edp_connector = to_edp_connector(connector); struct msm_edp *edp = edp_connector->edp; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index b62cdb9..9ecaf4e 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -350,7 +350,7 @@ static int hdmi_connector_get_modes(struct drm_connector *connector) }
static int hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector); struct hdmi *hdmi = hdmi_connector->hdmi; diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c index 9211851..ed571eb 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c @@ -67,7 +67,7 @@ static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) }
static int mdp4_lvds_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct mdp4_lvds_connector *mdp4_lvds_connector = to_mdp4_lvds_connector(connector); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index db7095a..604d944 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -828,7 +828,7 @@ get_tmds_link_bandwidth(struct drm_connector *connector)
static int nouveau_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 2c2173b..7889c19 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -74,7 +74,7 @@ void copy_timings_omap_to_drm(struct drm_display_mode *mode, }
void copy_timings_drm_to_omap(struct omap_video_timings *timings, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { timings->pixelclock = mode->clock * 1000;
@@ -198,7 +198,7 @@ static int omap_connector_get_modes(struct drm_connector *connector) }
static int omap_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; @@ -209,7 +209,6 @@ static int omap_connector_mode_valid(struct drm_connector *connector, int r, ret = MODE_BAD;
copy_timings_drm_to_omap(&timings, mode); - mode->vrefresh = drm_mode_vrefresh(mode);
/* * if the panel driver doesn't have a check_timings, it's most likely @@ -242,8 +241,8 @@ static int omap_connector_mode_valid(struct drm_connector *connector, DBG("connector: mode %s: " "%d:"%s" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", (ret == MODE_OK) ? "valid" : "invalid", - mode->base.id, mode->name, mode->vrefresh, mode->clock, - mode->hdisplay, mode->hsync_start, + mode->base.id, mode->name, drm_mode_vrefresh(mode), + mode->clock, mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal, mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal, mode->type, mode->flags); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 60e47b3..3a57093 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -193,7 +193,7 @@ bool omap_connector_get_hdmi_mode(struct drm_connector *connector); void copy_timings_omap_to_drm(struct drm_display_mode *mode, struct omap_video_timings *timings); void copy_timings_drm_to_omap(struct omap_video_timings *timings, - struct drm_display_mode *mode); + const struct drm_display_mode *mode);
uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats, uint32_t max_formats, enum omap_color_mode supported_modes); diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 4a0a8b2..77fb4b4 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -821,7 +821,7 @@ static int qxl_conn_get_modes(struct drm_connector *connector) }
static int qxl_conn_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { /* TODO: is this called for user defined modes? (xrandr --add-mode) * TODO: check that the mode fits in the framebuffer */ diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 8d74de8..6c3fd45 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -493,7 +493,7 @@ void radeon_dp_set_link_config(struct drm_connector *connector, }
int radeon_dp_mode_valid_helper(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 27def67..2aae77f 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -801,7 +801,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector) }
static int radeon_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_encoder *encoder = radeon_best_single_encoder(connector);
@@ -944,7 +944,7 @@ static int radeon_vga_get_modes(struct drm_connector *connector) }
static int radeon_vga_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct radeon_device *rdev = dev->dev_private; @@ -1083,7 +1083,7 @@ static int radeon_tv_get_modes(struct drm_connector *connector) }
static int radeon_tv_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if ((mode->hdisplay > 1024) || (mode->vdisplay > 768)) return MODE_CLOCK_RANGE; @@ -1387,7 +1387,7 @@ static void radeon_dvi_force(struct drm_connector *connector) }
static int radeon_dvi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct radeon_device *rdev = dev->dev_private; @@ -1670,7 +1670,7 @@ out: }
static int radeon_dp_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 920a8be..391f78e 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -698,7 +698,7 @@ extern struct edid *radeon_connector_edid(struct drm_connector *connector);
extern void radeon_connector_hotplug(struct drm_connector *connector); extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); extern void radeon_dp_set_link_config(struct drm_connector *connector, const struct drm_display_mode *mode); extern void radeon_dp_link_train(struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c index 96f2eb4..511ff2d 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c @@ -37,7 +37,7 @@ static int rcar_du_hdmi_connector_get_modes(struct drm_connector *connector) }
static int rcar_du_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct rcar_du_connector *con = to_rcar_connector(connector); struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(con->encoder); diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index d236faa..a58cdac 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -156,7 +156,7 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
static enum drm_mode_status dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; int pclk = mode->clock * 1000; diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index b29272c..7dfb468 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -296,7 +296,7 @@ static int sti_dvo_connector_get_modes(struct drm_connector *connector) #define CLK_TOLERANCE_HZ 50
static int sti_dvo_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int target = mode->clock * 1000; int target_min = target - CLK_TOLERANCE_HZ; diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index 4a15d45..d5edfdf 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -278,7 +278,7 @@ static void hda_write(struct sti_hda *hda, u32 val, int offset) * * Return true if mode is found */ -static bool hda_get_mode_idx(struct drm_display_mode mode, int *idx) +static bool hda_get_mode_idx(const struct drm_display_mode mode, int *idx) { unsigned int i;
@@ -550,7 +550,7 @@ static int sti_hda_connector_get_modes(struct drm_connector *connector) #define CLK_TOLERANCE_HZ 50
static int sti_hda_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int target = mode->clock * 1000; int target_min = target - CLK_TOLERANCE_HZ; diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index fc26a8c..036a26d 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -594,7 +594,7 @@ fail: #define CLK_TOLERANCE_HZ 50
static int sti_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int target = mode->clock * 1000; int target_min = target - CLK_TOLERANCE_HZ; diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index ed970f6..97bfa42 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -767,7 +767,7 @@ static const struct drm_connector_funcs tegra_dsi_connector_funcs = {
static enum drm_mode_status tegra_dsi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { return MODE_OK; } diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 7eaaee74..b502f4e 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -789,7 +789,7 @@ static const struct drm_connector_funcs tegra_hdmi_connector_funcs = {
static enum drm_mode_status tegra_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct tegra_output *output = connector_to_output(connector); struct tegra_hdmi *hdmi = to_hdmi(output); diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 7cd833f..b120cc2 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -105,7 +105,7 @@ static const struct drm_connector_funcs tegra_rgb_connector_funcs = {
static enum drm_mode_status tegra_rgb_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { /* * FIXME: For now, always assume that the mode is okay. There are diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index e6caacc..a2ed3b6 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -753,7 +753,7 @@ static int tegra_sor_connector_get_modes(struct drm_connector *connector)
static enum drm_mode_status tegra_sor_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { return MODE_OK; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 7a03158..9580467 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -198,7 +198,7 @@ static int panel_connector_get_modes(struct drm_connector *connector) }
static int panel_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct tilcdc_drm_private *priv = connector->dev->dev_private; /* our only constraints are what the crtc can generate: */ diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index 5842845..8363848 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -192,7 +192,7 @@ static int slave_connector_get_modes(struct drm_connector *connector) }
static int slave_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_encoder *encoder = to_slave_connector(connector)->encoder; struct tilcdc_drm_private *priv = connector->dev->dev_private; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index 354c47c..695f66d 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -203,7 +203,7 @@ static int tfp410_connector_get_modes(struct drm_connector *connector) }
static int tfp410_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct tilcdc_drm_private *priv = connector->dev->dev_private; /* our only constraints are what the crtc can generate: */ diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 0110d95..a724bcc 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -81,7 +81,7 @@ static int udl_get_modes(struct drm_connector *connector) }
static int udl_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct udl_device *udl = connector->dev->dev_private; if (!udl->sku_pixel_limit) diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 5a4f490..e63cfa8 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -50,7 +50,7 @@ struct dw_hdmi_plat_data { const struct dw_hdmi_curr_ctrl *cur_ctr; const struct dw_hdmi_sym_term *sym_term; enum drm_mode_status (*mode_valid)(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); };
void dw_hdmi_unbind(struct device *dev, struct device *master, void *data); diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 92d5135..29204f4 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -174,7 +174,7 @@ struct drm_encoder_helper_funcs { struct drm_connector_helper_funcs { int (*get_modes)(struct drm_connector *connector); enum drm_mode_status (*mode_valid)(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); struct drm_encoder *(*best_encoder)(struct drm_connector *connector); };
Enforce the existing rules on when modes can be modified (never modify the passed-in mode; only modify adjusted_mode in mode_fixup), by adding const.
This removes the interim mode_set helper functions introduced in tilcdc and armada during the encoder-slave mode_set constification, as the encoder and encoder-slave types are now compatible.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/armada/armada_slave.c | 10 +--------- drivers/gpu/drm/ast/ast_mode.c | 4 ++-- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 4 ++-- drivers/gpu/drm/bochs/bochs_kms.c | 4 ++-- drivers/gpu/drm/cirrus/cirrus_mode.c | 4 ++-- drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 +- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 4 ++-- drivers/gpu/drm/exynos/exynos_hdmi.c | 19 ++++++++----------- drivers/gpu/drm/gma500/cdv_intel_crt.c | 4 ++-- drivers/gpu/drm/gma500/cdv_intel_dp.c | 5 +++-- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 4 ++-- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 4 ++-- drivers/gpu/drm/gma500/mdfld_dsi_dpi.c | 4 ++-- drivers/gpu/drm/gma500/mdfld_dsi_dpi.h | 4 ++-- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 4 ++-- drivers/gpu/drm/gma500/oaktrail_lvds.c | 4 ++-- drivers/gpu/drm/gma500/psb_intel_lvds.c | 4 ++-- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 4 ++-- drivers/gpu/drm/i2c/tda998x_drv.c | 8 ++++---- drivers/gpu/drm/imx/dw_hdmi-imx.c | 4 ++-- drivers/gpu/drm/imx/imx-ldb.c | 4 ++-- drivers/gpu/drm/imx/imx-tve.c | 4 ++-- drivers/gpu/drm/imx/parallel-display.c | 4 ++-- drivers/gpu/drm/mgag200/mgag200_mode.c | 4 ++-- drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c | 6 ++---- drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c | 6 ++---- drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 6 ++---- drivers/gpu/drm/nouveau/dispnv04/dac.c | 4 ++-- drivers/gpu/drm/nouveau/dispnv04/dfp.c | 4 ++-- drivers/gpu/drm/nouveau/dispnv04/tvnv04.c | 4 ++-- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 4 ++-- drivers/gpu/drm/nouveau/nv50_display.c | 21 +++++++++++++-------- drivers/gpu/drm/omapdrm/omap_encoder.c | 4 ++-- drivers/gpu/drm/qxl/qxl_display.c | 4 ++-- drivers/gpu/drm/radeon/atombios_encoders.c | 10 +++++----- drivers/gpu/drm/radeon/radeon_audio.c | 20 +++++++++++--------- drivers/gpu/drm/radeon/radeon_audio.h | 7 ++++--- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 20 ++++++++++---------- drivers/gpu/drm/radeon/radeon_legacy_tv.c | 4 ++-- drivers/gpu/drm/radeon/radeon_mode.h | 4 ++-- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 4 ++-- drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 4 ++-- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 ++-- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 4 ++-- drivers/gpu/drm/sti/sti_tvout.c | 4 ++-- drivers/gpu/drm/tegra/dsi.c | 4 ++-- drivers/gpu/drm/tegra/hdmi.c | 6 +++--- drivers/gpu/drm/tegra/rgb.c | 4 ++-- drivers/gpu/drm/tegra/sor.c | 6 +++--- drivers/gpu/drm/tilcdc/tilcdc_panel.c | 4 ++-- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 9 +-------- drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 4 ++-- drivers/gpu/drm/udl/udl_encoder.c | 4 ++-- include/drm/drm_crtc_helper.h | 4 ++-- 55 files changed, 150 insertions(+), 165 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_slave.c b/drivers/gpu/drm/armada/armada_slave.c index a58f4f9..00d0fac 100644 --- a/drivers/gpu/drm/armada/armada_slave.c +++ b/drivers/gpu/drm/armada/armada_slave.c @@ -42,14 +42,6 @@ static void armada_drm_slave_destroy(struct drm_encoder *enc) kfree(slave); }
-static void armada_drm_slave_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - drm_i2c_encoder_mode_set(encoder, mode, adjusted_mode); -} - - static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = { .destroy = armada_drm_slave_destroy, }; @@ -67,7 +59,7 @@ static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = { .mode_fixup = drm_i2c_encoder_mode_fixup, .prepare = drm_i2c_encoder_prepare, .commit = drm_i2c_encoder_commit, - .mode_set = armada_drm_slave_mode_set, + .mode_set = drm_i2c_encoder_mode_set, .detect = drm_i2c_encoder_detect, };
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 8069448..76e7d56 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -743,8 +743,8 @@ static bool ast_mode_fixup(struct drm_encoder *encoder, }
static void ast_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { }
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c index b6a7ee4..de24d55 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c @@ -114,8 +114,8 @@ atmel_hlcdc_panel_encoder_mode_fixup(struct drm_encoder *encoder,
static void atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted) { struct atmel_hlcdc_rgb_output *rgb = drm_encoder_to_atmel_hlcdc_rgb_output(encoder); diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index a61a42e..3967559 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -160,8 +160,8 @@ static bool bochs_encoder_mode_fixup(struct drm_encoder *encoder, }
static void bochs_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { }
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 61385f2..b77938d 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -439,8 +439,8 @@ static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder, }
static void cirrus_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 0910c66..dc9cc99 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -137,7 +137,7 @@ struct exynos_drm_display_ops { const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); void (*mode_set)(struct exynos_drm_display *display, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); int (*check_mode)(struct exynos_drm_display *display, const struct drm_display_mode *mode); void (*dpms)(struct exynos_drm_display *display, int mode); diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 885317a..e30f875 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1518,7 +1518,7 @@ static int exynos_dsi_create_connector(struct exynos_drm_display *display, }
static void exynos_dsi_mode_set(struct exynos_drm_display *display, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct exynos_dsi *dsi = display_to_dsi(display); struct videomode *vm = &dsi->vm; diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 57de0bd..4dceb34 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -66,8 +66,8 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, }
static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); struct exynos_drm_display *display = exynos_encoder->display; diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index abbe438..504d012 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1762,14 +1762,13 @@ static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value) }
static void hdmi_v13_mode_set(struct hdmi_context *hdata, - struct drm_display_mode *m) + const struct drm_display_mode *m) { struct hdmi_v13_core_regs *core = &hdata->mode_conf.conf.v13_conf.core; struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg; unsigned int val;
- hdata->mode_conf.cea_video_id = - drm_match_cea_mode((struct drm_display_mode *)m); + hdata->mode_conf.cea_video_id = drm_match_cea_mode(m); hdata->mode_conf.pixel_clock = m->clock * 1000; hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
@@ -1859,14 +1858,13 @@ static void hdmi_v13_mode_set(struct hdmi_context *hdata, }
static void hdmi_v14_mode_set(struct hdmi_context *hdata, - struct drm_display_mode *m) + const struct drm_display_mode *m) { struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg; struct hdmi_v14_core_regs *core = &hdata->mode_conf.conf.v14_conf.core;
- hdata->mode_conf.cea_video_id = - drm_match_cea_mode((struct drm_display_mode *)m); + hdata->mode_conf.cea_video_id = drm_match_cea_mode(m); hdata->mode_conf.pixel_clock = m->clock * 1000; hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
@@ -1971,10 +1969,9 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata, }
static void hdmi_mode_set(struct exynos_drm_display *display, - struct drm_display_mode *mode) + const struct drm_display_mode *m) { struct hdmi_context *hdata = display_to_hdmi(display); - struct drm_display_mode *m = mode;
DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n", m->hdisplay, m->vdisplay, @@ -1982,12 +1979,12 @@ static void hdmi_mode_set(struct exynos_drm_display *display, "INTERLACED" : "PROGERESSIVE");
/* preserve mode information for later use. */ - drm_mode_copy(&hdata->current_mode, mode); + drm_mode_copy(&hdata->current_mode, m);
if (hdata->type == HDMI_TYPE13) - hdmi_v13_mode_set(hdata, mode); + hdmi_v13_mode_set(hdata, m); else - hdmi_v14_mode_set(hdata, mode); + hdmi_v14_mode_set(hdata, m); }
static void hdmi_commit(struct exynos_drm_display *display) diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 9152105..fbf5524 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -82,8 +82,8 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, }
static void cdv_intel_crt_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) {
struct drm_device *dev = encoder->dev; diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 506f5d2..a303cb9 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -1036,8 +1036,9 @@ cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, }
static void -cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +cdv_intel_dp_mode_set(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct gma_encoder *intel_encoder = to_gma_encoder(encoder); struct drm_crtc *crtc = encoder->crtc; diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index 19a73c8..96b8ee1 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -60,8 +60,8 @@ struct mid_intel_hdmi_priv { };
static void cdv_hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct gma_encoder *gma_encoder = to_gma_encoder(encoder); diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index c416fbe..afe6d5d 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -351,8 +351,8 @@ static void cdv_intel_lvds_commit(struct drm_encoder *encoder) }
static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct drm_psb_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c index d4813e0..ca31291 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c @@ -810,8 +810,8 @@ static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config, int pipe) /* End for TC35876X */
void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); struct mdfld_dsi_dpi_output *dpi_output = diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h index 2b40663..66e62c7 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h +++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h @@ -70,8 +70,8 @@ extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode); extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe); extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index fcdfe78..877b63c 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -585,8 +585,8 @@ static int oaktrail_hdmi_get_modes(struct drm_connector *connector) }
static void oaktrail_hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev;
diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c index 83bbc27..7b8fd50 100644 --- a/drivers/gpu/drm/gma500/oaktrail_lvds.c +++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c @@ -89,8 +89,8 @@ static void oaktrail_lvds_dpms(struct drm_encoder *encoder, int mode) }
static void oaktrail_lvds_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct drm_psb_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index 12fac19..335f2a7 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -467,8 +467,8 @@ static void psb_intel_lvds_commit(struct drm_encoder *encoder) }
static void psb_intel_lvds_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct drm_psb_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 73b17eb..2f243b3 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -985,8 +985,8 @@ static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, }
static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct drm_crtc *crtc = encoder->crtc; diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index f20754b..cfde036 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -840,8 +840,8 @@ static int tda998x_encoder_mode_valid(struct tda998x_priv *priv,
static void tda998x_encoder_mode_set(struct tda998x_priv *priv, - const struct drm_display_mode *mode, - const struct drm_display_mode *adjusted_mode) + const const struct drm_display_mode *mode, + const const struct drm_display_mode *adjusted_mode) { uint16_t ref_pix, ref_line, n_pix, n_line; uint16_t hs_pix_s, hs_pix_e; @@ -1413,8 +1413,8 @@ static void tda998x_encoder_commit(struct drm_encoder *encoder) }
static void tda998x_encoder2_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index 543ce72..5a4bdba 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c @@ -106,8 +106,8 @@ static bool dw_hdmi_imx_encoder_mode_fixup(struct drm_encoder *encoder, }
static void dw_hdmi_imx_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adj_mode) { }
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 2d6dc94..938feff 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -226,8 +226,8 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder) }
static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *orig_mode, - struct drm_display_mode *mode) + const struct drm_display_mode *orig_mode, + const struct drm_display_mode *mode) { struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); struct imx_ldb *ldb = imx_ldb_ch->ldb; diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index 165a9d6..6a275bb 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -311,8 +311,8 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder) }
static void imx_tve_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *orig_mode, - struct drm_display_mode *mode) + const struct drm_display_mode *orig_mode, + const struct drm_display_mode *mode) { struct imx_tve *tve = enc_to_tve(encoder); unsigned long rounded_rate; diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 900dda6..03928c2 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -130,8 +130,8 @@ static void imx_pd_encoder_commit(struct drm_encoder *encoder) }
static void imx_pd_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *orig_mode, - struct drm_display_mode *mode) + const struct drm_display_mode *orig_mode, + const struct drm_display_mode *mode) { }
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index f99c53d..a0f3cd9 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1380,8 +1380,8 @@ static bool mga_encoder_mode_fixup(struct drm_encoder *encoder, }
static void mga_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) {
} diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c index 7896323..189d1e2 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c @@ -102,8 +102,8 @@ static bool mdp4_dtv_encoder_mode_fixup(struct drm_encoder *encoder, }
static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *drm_mode, + const struct drm_display_mode *mode) { struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder); struct mdp4_kms *mdp4_kms = get_kms(encoder); @@ -111,8 +111,6 @@ static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder, uint32_t display_v_start, display_v_end; uint32_t hsync_start_x, hsync_end_x;
- mode = adjusted_mode; - DBG("set mode: %d:"%s" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", mode->base.id, mode->name, mode->vrefresh, mode->clock, diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c index 60ec822..a80679a 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c @@ -267,8 +267,8 @@ static bool mdp4_lcdc_encoder_mode_fixup(struct drm_encoder *encoder, }
static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *drm_mode, + const struct drm_display_mode *mode) { struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); @@ -277,8 +277,6 @@ static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder, uint32_t display_v_start, display_v_end; uint32_t hsync_start_x, hsync_end_x;
- mode = adjusted_mode; - DBG("set mode: %d:"%s" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", mode->base.id, mode->name, mode->vrefresh, mode->clock, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c index af0e02f..23d4aae 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c @@ -119,8 +119,8 @@ static bool mdp5_encoder_mode_fixup(struct drm_encoder *encoder, }
static void mdp5_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *drm_mode, + const struct drm_display_mode *mode) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); struct mdp5_kms *mdp5_kms = get_kms(encoder); @@ -133,8 +133,6 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder, uint32_t format = 0x2100; unsigned long flags;
- mode = adjusted_mode; - DBG("set mode: %d:"%s" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", mode->base.id, mode->name, mode->vrefresh, mode->clock, diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c index d7b495a..0dfe9b8 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dac.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c @@ -368,8 +368,8 @@ static void nv04_dac_prepare(struct drm_encoder *encoder) }
static void nv04_dac_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index f6ca343..2660585 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -277,8 +277,8 @@ static void nv04_dfp_prepare(struct drm_encoder *encoder)
static void nv04_dfp_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct nvif_device *device = &nouveau_drm(dev)->device; diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index d9664b3..435696d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -135,8 +135,8 @@ static void nv04_tv_prepare(struct drm_encoder *encoder) }
static void nv04_tv_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index c77ffe3..e4b8afc 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -463,8 +463,8 @@ static void nv17_tv_prepare(struct drm_encoder *encoder) }
static void nv17_tv_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *drm_mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *drm_mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 7da7958..0819978 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1549,8 +1549,9 @@ nv50_dac_commit(struct drm_encoder *encoder) }
static void -nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +nv50_dac_mode_set(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct nv50_mast *mast = nv50_mast(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -1703,7 +1704,8 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) * Audio *****************************************************************************/ static void -nv50_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) +nv50_audio_mode_set(struct drm_encoder *encoder, + const struct drm_display_mode *mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); @@ -1757,7 +1759,8 @@ nv50_audio_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) * HDMI *****************************************************************************/ static void -nv50_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) +nv50_hdmi_mode_set(struct drm_encoder *encoder, + const struct drm_display_mode *mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); @@ -1905,8 +1908,9 @@ nv50_sor_commit(struct drm_encoder *encoder) }
static void -nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, - struct drm_display_mode *mode) +nv50_sor_mode_set(struct drm_encoder *encoder, + const struct drm_display_mode *umode, + const struct drm_display_mode *mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); @@ -2135,8 +2139,9 @@ nv50_pior_commit(struct drm_encoder *encoder) }
static void -nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +nv50_pior_mode_set(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct nv50_mast *mast = nv50_mast(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index 7445fb1..0b68dc6 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c @@ -88,8 +88,8 @@ static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, }
static void omap_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct omap_encoder *omap_encoder = to_omap_encoder(encoder); diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 77fb4b4..481612a 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -795,8 +795,8 @@ static void qxl_enc_commit(struct drm_encoder *encoder) }
static void qxl_enc_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { DRM_DEBUG("\n"); } diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index c39c1d0..b91c6f1 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1957,7 +1957,7 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
static void atombios_apply_encoder_quirks(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -2137,8 +2137,8 @@ radeon_atom_encoder_init(struct radeon_device *rdev)
static void radeon_atom_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -2483,8 +2483,8 @@ static void radeon_atom_ext_commit(struct drm_encoder *encoder)
static void radeon_atom_ext_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) {
} diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index b21ef69..dbd4052 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -57,9 +57,11 @@ void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, u8 *sadb, int sad_count); void dce4_afmt_write_latency_fields(struct drm_encoder *encoder, - struct drm_connector *connector, struct drm_display_mode *mode); + struct drm_connector *connector, + const struct drm_display_mode *mode); void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, - struct drm_connector *connector, struct drm_display_mode *mode); + struct drm_connector *connector, + const struct drm_display_mode *mode); struct r600_audio_pin* r600_audio_get_pin(struct radeon_device *rdev); struct r600_audio_pin* dce6_audio_get_pin(struct radeon_device *rdev); void dce6_afmt_select_pin(struct drm_encoder *encoder); @@ -96,9 +98,9 @@ void r600_set_mute(struct drm_encoder *encoder, u32 offset, bool mute); void dce3_2_set_mute(struct drm_encoder *encoder, u32 offset, bool mute); void dce4_set_mute(struct drm_encoder *encoder, u32 offset, bool mute); static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); void r600_hdmi_enable(struct drm_encoder *encoder, bool enable); void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable); void evergreen_dp_enable(struct drm_encoder *encoder, bool enable); @@ -400,7 +402,7 @@ static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) }
static void radeon_audio_write_latency_fields(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct radeon_encoder *radeon_encoder; struct drm_connector *connector; @@ -515,7 +517,7 @@ static void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock }
static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct radeon_device *rdev = encoder->dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -691,7 +693,7 @@ static void radeon_audio_set_mute(struct drm_encoder *encoder, bool mute) * update the info frames with the data from the current display mode */ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; @@ -718,7 +720,7 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, }
static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -747,7 +749,7 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, }
void radeon_audio_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h index c92d059..ed08a54 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.h +++ b/drivers/gpu/drm/radeon/radeon_audio.h @@ -46,7 +46,8 @@ struct radeon_audio_funcs void (*select_pin)(struct drm_encoder *encoder); struct r600_audio_pin* (*get_pin)(struct radeon_device *rdev); void (*write_latency_fields)(struct drm_encoder *encoder, - struct drm_connector *connector, struct drm_display_mode *mode); + struct drm_connector *connector, + const struct drm_display_mode *mode); void (*write_sad_regs)(struct drm_encoder *encoder, struct cea_sad *sads, int sad_count); void (*write_speaker_allocation)(struct drm_encoder *encoder, @@ -62,7 +63,7 @@ struct radeon_audio_funcs void (*set_audio_packet)(struct drm_encoder *encoder, u32 offset); void (*set_mute)(struct drm_encoder *encoder, u32 offset, bool mute); void (*mode_set)(struct drm_encoder *encoder, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); void (*dpms)(struct drm_encoder *encoder, bool mode); };
@@ -78,7 +79,7 @@ void radeon_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, u8 enable_mask); void radeon_audio_fini(struct radeon_device *rdev); void radeon_audio_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); void radeon_audio_dpms(struct drm_encoder *encoder, int mode);
#endif diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index c89971d..21ad6ab 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -174,8 +174,8 @@ static void radeon_legacy_lvds_commit(struct drm_encoder *encoder) }
static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -574,8 +574,8 @@ static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder) }
static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -771,8 +771,8 @@ static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder) }
static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -936,8 +936,8 @@ static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder) }
static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -1142,8 +1142,8 @@ static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder) }
static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_tv.c b/drivers/gpu/drm/radeon/radeon_legacy_tv.c index 49750d0..d73c08b 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_tv.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_tv.c @@ -529,8 +529,8 @@ static bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder) }
void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 391f78e..7c4f6be 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -911,8 +911,8 @@ void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder, uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div, uint32_t *p2pll_div_0, uint32_t *pixclks_cntl); void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode);
/* fmt blocks */ void avivo_program_fmt(struct drm_encoder *encoder); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index d0ae1e8..0db6a54 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -100,8 +100,8 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder, }
static void rcar_du_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c index 81da841..c000850 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c @@ -85,8 +85,8 @@ static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder, }
static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index a58cdac..2a8f7a7 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -190,8 +190,8 @@ dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, }
static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adj_mode) { }
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 859ccb6..fdba183 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -575,8 +575,8 @@ static void shmob_drm_encoder_mode_prepare(struct drm_encoder *encoder) }
static void shmob_drm_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { /* No-op, everything is handled in the CRTC code. */ } diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index 5cc5311..64ecc23 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c @@ -448,8 +448,8 @@ static bool sti_tvout_encoder_mode_fixup(struct drm_encoder *encoder, }
static void sti_tvout_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { }
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index 97bfa42..4714eb4 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -795,8 +795,8 @@ static void tegra_dsi_encoder_commit(struct drm_encoder *encoder) }
static void tegra_dsi_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted) { struct tegra_output *output = encoder_to_output(encoder); struct tegra_dc *dc = to_tegra_dc(encoder->crtc); diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index b502f4e..68d315e 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -638,7 +638,7 @@ static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data, }
static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct hdmi_avi_infoframe frame; u8 buffer[17]; @@ -831,8 +831,8 @@ static void tegra_hdmi_encoder_commit(struct drm_encoder *encoder) }
static void tegra_hdmi_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted) { unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey; struct tegra_output *output = encoder_to_output(encoder); diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index b120cc2..745759a 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -138,8 +138,8 @@ static void tegra_rgb_encoder_commit(struct drm_encoder *encoder) }
static void tegra_rgb_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted) { struct tegra_output *output = encoder_to_output(encoder); struct tegra_rgb *rgb = to_rgb(output); diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index a2ed3b6..fe86207 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -384,7 +384,7 @@ static int tegra_sor_compute_params(struct tegra_sor *sor, }
static int tegra_sor_calc_config(struct tegra_sor *sor, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, struct tegra_sor_config *config, struct drm_dp_link *link) { @@ -781,8 +781,8 @@ static void tegra_sor_encoder_commit(struct drm_encoder *encoder) }
static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted) { struct tegra_output *output = encoder_to_output(encoder); struct tegra_dc *dc = to_tegra_dc(encoder->crtc); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 9580467..ede8846 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -91,8 +91,8 @@ static void panel_encoder_commit(struct drm_encoder *encoder) }
static void panel_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { /* nothing needed */ } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index 8363848..6fc064f 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -96,13 +96,6 @@ static bool slave_encoder_fixup(struct drm_encoder *encoder, return drm_i2c_encoder_mode_fixup(encoder, mode, adjusted_mode); }
-static void slave_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - drm_i2c_encoder_mode_set(encoder, mode, adjusted_mode); -} - static const struct drm_encoder_funcs slave_encoder_funcs = { .destroy = slave_encoder_destroy, }; @@ -112,7 +105,7 @@ static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = { .mode_fixup = slave_encoder_fixup, .prepare = slave_encoder_prepare, .commit = drm_i2c_encoder_commit, - .mode_set = slave_encoder_mode_set, + .mode_set = drm_i2c_encoder_mode_set, .save = drm_i2c_encoder_save, .restore = drm_i2c_encoder_restore, }; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index 695f66d..f616a09 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -100,8 +100,8 @@ static void tfp410_encoder_commit(struct drm_encoder *encoder) }
static void tfp410_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { /* nothing needed */ } diff --git a/drivers/gpu/drm/udl/udl_encoder.c b/drivers/gpu/drm/udl/udl_encoder.c index 4052c46..d9cd5d8 100644 --- a/drivers/gpu/drm/udl/udl_encoder.c +++ b/drivers/gpu/drm/udl/udl_encoder.c @@ -42,8 +42,8 @@ static void udl_encoder_commit(struct drm_encoder *encoder) }
static void udl_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { }
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 29204f4..a356a59 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -147,8 +147,8 @@ struct drm_encoder_helper_funcs { void (*prepare)(struct drm_encoder *encoder); void (*commit)(struct drm_encoder *encoder); void (*mode_set)(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode); struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder); /* detect for DAC style encoders */ enum drm_connector_status (*detect)(struct drm_encoder *encoder,
Enforce the existing rules on when modes can be modified (never modify the passed-in mode; only modify adjusted_mode in mode_fixup), by adding const.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/armada/armada_crtc.c | 3 ++- drivers/gpu/drm/ast/ast_mode.c | 31 +++++++++++++++++----------- drivers/gpu/drm/bochs/bochs.h | 2 +- drivers/gpu/drm/bochs/bochs_hw.c | 2 +- drivers/gpu/drm/bochs/bochs_kms.c | 4 ++-- drivers/gpu/drm/cirrus/cirrus_mode.c | 4 ++-- drivers/gpu/drm/drm_crtc_helper.c | 8 ++++--- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 8 ++++--- drivers/gpu/drm/gma500/cdv_intel_display.c | 4 ++-- drivers/gpu/drm/gma500/mdfld_intel_display.c | 8 +++---- drivers/gpu/drm/gma500/oaktrail.h | 6 ++++-- drivers/gpu/drm/gma500/oaktrail_crtc.c | 4 ++-- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 4 ++-- drivers/gpu/drm/gma500/psb_intel_display.c | 4 ++-- drivers/gpu/drm/imx/ipuv3-crtc.c | 4 ++-- drivers/gpu/drm/imx/ipuv3-plane.c | 2 +- drivers/gpu/drm/imx/ipuv3-plane.h | 2 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 4 ++-- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 15 +++++++++----- drivers/gpu/drm/nouveau/nv50_display.c | 6 ++++-- drivers/gpu/drm/omapdrm/omap_crtc.c | 6 ++---- drivers/gpu/drm/qxl/qxl_display.c | 4 ++-- drivers/gpu/drm/radeon/atombios_crtc.c | 15 +++++++------- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 14 +++++++------ drivers/gpu/drm/radeon/radeon_mode.h | 4 ++-- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++-- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 4 ++-- drivers/gpu/drm/sti/sti_drm_crtc.c | 6 ++++-- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 ++-- drivers/gpu/drm/udl/udl_modeset.c | 7 ++++--- include/drm/drm_crtc_helper.h | 14 ++++++++----- 31 files changed, 118 insertions(+), 89 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index c74faf9..187cdd2 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -493,7 +493,8 @@ static uint32_t armada_drm_crtc_calculate_csc(struct armada_crtc *dcrtc)
/* The mode_config.mutex will be held for this call */ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, struct drm_display_mode *adj, + const struct drm_display_mode *mode, + const struct drm_display_mode *adj, int x, int y, struct drm_framebuffer *old_fb) { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 76e7d56..fb11f75 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -174,7 +174,8 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, return true; }
-static void ast_set_port_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, +static void ast_set_port_reg(struct drm_crtc *crtc, + const struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { struct ast_private *ast = crtc->dev->dev_private; @@ -210,7 +211,8 @@ static void ast_set_port_reg(struct drm_crtc *crtc, struct drm_display_mode *mod } }
-static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, +static void ast_set_std_reg(struct drm_crtc *crtc, + const struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { struct ast_private *ast = crtc->dev->dev_private; @@ -255,7 +257,8 @@ static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]); }
-static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, +static void ast_set_crtc_reg(struct drm_crtc *crtc, + const struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { struct ast_private *ast = crtc->dev->dev_private; @@ -366,7 +369,8 @@ static void ast_set_offset_reg(struct drm_crtc *crtc) ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f); }
-static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mode, +static void ast_set_dclk_reg(struct drm_device *dev, + const struct drm_display_mode *mode, struct ast_vbios_mode_info *vbios_mode) { struct ast_private *ast = dev->dev_private; @@ -380,8 +384,9 @@ static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mo (clk_info->param3 & 0x80) | ((clk_info->param3 & 0x3) << 4)); }
-static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) +static void ast_set_ext_reg(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) { struct ast_private *ast = crtc->dev->dev_private; u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; @@ -425,8 +430,9 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode } }
-static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) +static void ast_set_sync_reg(struct drm_device *dev, + const struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) { struct ast_private *ast = dev->dev_private; u8 jreg; @@ -438,8 +444,9 @@ static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mo ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); }
-static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) +static bool ast_set_dac_reg(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct ast_vbios_mode_info *vbios_mode) { switch (crtc->primary->fb->bits_per_pixel) { case 8: @@ -582,8 +589,8 @@ static int ast_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, }
static int ast_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index 71f2687..dee026c 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -129,7 +129,7 @@ int bochs_hw_init(struct drm_device *dev, uint32_t flags); void bochs_hw_fini(struct drm_device *dev);
void bochs_hw_setmode(struct bochs_device *bochs, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); void bochs_hw_setbase(struct bochs_device *bochs, int x, int y, u64 addr);
diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c index 4603897..09031e2 100644 --- a/drivers/gpu/drm/bochs/bochs_hw.c +++ b/drivers/gpu/drm/bochs/bochs_hw.c @@ -150,7 +150,7 @@ void bochs_hw_fini(struct drm_device *dev) }
void bochs_hw_setmode(struct bochs_device *bochs, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { bochs->xres = mode->hdisplay; bochs->yres = mode->vdisplay; diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 3967559..f1ad0b5 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -80,8 +80,8 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, }
static int bochs_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { struct bochs_device *bochs = diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index b77938d..bf8f36a 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -191,8 +191,8 @@ static int cirrus_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, * be something that can be correctly programmed and displayed */ static int cirrus_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index dd895c4..c6063ff 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -265,7 +265,7 @@ drm_crtc_prepare_encoders(struct drm_device *dev) * True if the mode was set successfully, false otherwise. */ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb) { @@ -931,8 +931,10 @@ EXPORT_SYMBOL(drm_helper_resume_force_mode); * This is a transitional helper useful for converting drivers to the atomic * interfaces. */ -int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, +int drm_helper_crtc_mode_set(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb) { struct drm_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 5f1816c..bd27444 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -83,9 +83,11 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, }
static int -exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, - struct drm_framebuffer *old_fb) +exynos_drm_crtc_mode_set(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb) { struct drm_framebuffer *fb = crtc->primary->fb; unsigned int crtc_w; diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 6672732..b1ef8c0 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -576,8 +576,8 @@ static int cdv_intel_panel_fitter_pipe(struct drm_device *dev) }
static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c index 8cc8a5a..0c842c4 100644 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c @@ -663,10 +663,10 @@ mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk, }
static int mdfld_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; struct gma_crtc *gma_crtc = to_gma_crtc(crtc); diff --git a/drivers/gpu/drm/gma500/oaktrail.h b/drivers/gpu/drm/gma500/oaktrail.h index 30adbbe2..3a58c93 100644 --- a/drivers/gpu/drm/gma500/oaktrail.h +++ b/drivers/gpu/drm/gma500/oaktrail.h @@ -249,8 +249,10 @@ extern void oaktrail_hdmi_i2c_exit(struct pci_dev *dev); extern void oaktrail_hdmi_save(struct drm_device *dev); extern void oaktrail_hdmi_restore(struct drm_device *dev); extern void oaktrail_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); -extern int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, +extern int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb); extern void oaktrail_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode);
diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index 2de216c..18c408c 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -362,8 +362,8 @@ static int oaktrail_panel_fitter_pipe(struct drm_device *dev) }
static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index 877b63c..428ccbe 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -257,8 +257,8 @@ static void oaktrail_hdmi_reset(struct drm_device *dev) }
int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index b21a094..29a472c 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -100,8 +100,8 @@ static int psb_intel_panel_fitter_pipe(struct drm_device *dev) }
static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 98551e3..28e6b4e 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -135,8 +135,8 @@ static const struct drm_crtc_funcs ipu_crtc_funcs = { };
static int ipu_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *orig_mode, - struct drm_display_mode *mode, + const struct drm_display_mode *orig_mode, + const struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 6987e16..5035fff 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -95,7 +95,7 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, }
int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, 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, diff --git a/drivers/gpu/drm/imx/ipuv3-plane.h b/drivers/gpu/drm/imx/ipuv3-plane.h index af125fb..ee13a37 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.h +++ b/drivers/gpu/drm/imx/ipuv3-plane.h @@ -38,7 +38,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
/* Init IDMAC, DMFC, DP */ int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, 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, diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index a0f3cd9..2153c28 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -778,8 +778,8 @@ static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, }
static int mga_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 542bb266..093a420 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -108,7 +108,9 @@ static void nv_crtc_set_image_sharpening(struct drm_crtc *crtc, int level) * bits 28-31: related to single stage mode? (bit 8/12) */
-static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mode * mode, int dot_clock) +static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, + const struct drm_display_mode * mode, + int dot_clock) { struct drm_device *dev = crtc->dev; struct nouveau_drm *drm = nouveau_drm(dev); @@ -235,7 +237,8 @@ nv_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, }
static void -nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) +nv_crtc_mode_set_vga(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); @@ -459,7 +462,8 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) * be easily turned on/off after this. */ static void -nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) +nv_crtc_mode_set_regs(struct drm_crtc *crtc, + const struct drm_display_mode * mode) { struct drm_device *dev = crtc->dev; struct nouveau_drm *drm = nouveau_drm(dev); @@ -633,8 +637,9 @@ nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) * be easily turned on/off after this. */ static int -nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, +nv_crtc_mode_set(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 0819978..05b21ef 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1109,8 +1109,10 @@ nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) }
static int -nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, - struct drm_display_mode *mode, int x, int y, +nv50_crtc_mode_set(struct drm_crtc *crtc, + const struct drm_display_mode *umode, + const struct drm_display_mode *mode, + int x, int y, struct drm_framebuffer *old_fb) { struct nv50_mast *mast = nv50_mast(crtc->dev); diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index b0566a1..f394fdd 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -237,15 +237,13 @@ static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, }
static int omap_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *drm_mode, + const struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- mode = adjusted_mode; - DBG("%s: set mode: %d:"%s" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", omap_crtc->name, mode->base.id, mode->name, mode->vrefresh, mode->clock, diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 481612a..189119d 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -585,8 +585,8 @@ static void qxl_monitors_config_set(struct qxl_device *qdev, }
static int qxl_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 86807ee..050e908 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -32,8 +32,8 @@ #include "atom-bits.h"
static void atombios_overscan_setup(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; @@ -295,7 +295,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
static void atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; @@ -340,7 +340,7 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, }
static void atombios_crtc_set_timing(struct drm_crtc *crtc, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; @@ -1038,7 +1038,8 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_ return true; }
-static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) +static void atombios_crtc_set_pll(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; @@ -2005,8 +2006,8 @@ void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) }
int atombios_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 678b438..fa8f7da 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -31,7 +31,7 @@ #include "atom.h"
static void radeon_overscan_setup(struct drm_crtc *crtc, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; @@ -43,7 +43,7 @@ static void radeon_overscan_setup(struct drm_crtc *crtc, }
static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; @@ -571,7 +571,8 @@ retry: return 0; }
-static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mode *mode) +static bool radeon_set_crtc_timing(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; @@ -730,7 +731,8 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod return true; }
-static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) +static void radeon_set_pll(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; @@ -1033,8 +1035,8 @@ static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, }
static int radeon_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 7c4f6be..9b9cd14 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -793,8 +793,8 @@ extern int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, int x, int y, enum mode_set_atomic state); extern int atombios_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb); extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 9a5c571..25f89b3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -832,8 +832,8 @@ static int vop_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, }
static int vop_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *fb) { struct vop *vop = to_vop(crtc); diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index fdba183..ab3b4f4 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -372,8 +372,8 @@ static void shmob_drm_crtc_mode_prepare(struct drm_crtc *crtc) }
static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c index 4721e91..cfb75dc 100644 --- a/drivers/gpu/drm/sti/sti_drm_crtc.c +++ b/drivers/gpu/drm/sti/sti_drm_crtc.c @@ -77,8 +77,10 @@ static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc, }
static int -sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, +sti_drm_crtc_mode_set(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb) { struct sti_mixer *mixer = to_sti_mixer(crtc); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 8514055..d5fafef 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -227,8 +227,8 @@ static void tilcdc_crtc_commit(struct drm_crtc *crtc) }
static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 677190a6..7c694f5 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -160,7 +160,8 @@ static char *udl_set_register_lfsr16(char *wrptr, u8 reg, u16 value)
ERR(vbuf(dev, WRITE_VIDREG_UNLOCK, DSIZEOF(WRITE_VIDREG_UNLOCK))); */ -static char *udl_set_vid_cmds(char *wrptr, struct drm_display_mode *mode) +static char *udl_set_vid_cmds(char *wrptr, + const struct drm_display_mode *mode) { u16 xds, yds; u16 xde, yde; @@ -304,8 +305,8 @@ udl_pipe_set_base(struct drm_crtc *crtc, int x, int y, #endif
static int udl_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb)
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index a356a59..ece3819 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -86,8 +86,10 @@ struct drm_crtc_helper_funcs { const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); /* Actually set the mode */ - int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, + int (*mode_set)(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb); /* Actually set the mode for atomic helpers, optional */ void (*mode_set_nofb)(struct drm_crtc *crtc); @@ -181,7 +183,7 @@ struct drm_connector_helper_funcs { extern void drm_helper_disable_unused_functions(struct drm_device *dev); extern int drm_crtc_helper_set_config(struct drm_mode_set *set); extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb); extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); @@ -214,8 +216,10 @@ static inline void drm_connector_helper_add(struct drm_connector *connector,
extern void drm_helper_resume_force_mode(struct drm_device *dev);
-int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, +int drm_helper_crtc_mode_set(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb); int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb);
Enforce the existing rules on when modes can be modified (never modify the passed-in mode; only modify adjusted_mode in mode_fixup), by adding const.
This requires duplicating the existing crtc_info->modeset->mode member in the fb_helper, to keep a non-const version to free later.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_fb_helper.c | 27 +++++++++++++++++++-------- drivers/gpu/drm/i915/intel_fbdev.c | 4 ++++ drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 4 ++-- include/drm/drm_crtc.h | 2 +- include/drm/drm_fb_helper.h | 3 +++ 6 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 27f5617..71e2420 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -579,8 +579,9 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) kfree(helper->connector_info); for (i = 0; i < helper->crtc_count; i++) { kfree(helper->crtc_info[i].mode_set.connectors); - if (helper->crtc_info[i].mode_set.mode) - drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode); + if (helper->crtc_info[i].mode) + drm_mode_destroy(helper->dev, + helper->crtc_info[i].mode); } kfree(helper->crtc_info); } @@ -1525,11 +1526,17 @@ retry: DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n", fb_helper_conn->connector->base.id, fb_helper_conn->connector->tile_group ? fb_helper_conn->connector->tile_group->id : 0); modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height); + if (modes[i]) + modes[i] = drm_mode_duplicate(fb_helper->dev, + modes[i]); } /* No preferred modes, pick one off the list */ if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) { list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head) break; + if (modes[i]) + modes[i] = drm_mode_duplicate(fb_helper->dev, + modes[i]); } DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : "none"); @@ -1695,10 +1702,11 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) fb_crtc->desired_mode = mode; fb_crtc->x = offset->x; fb_crtc->y = offset->y; - if (modeset->mode) - drm_mode_destroy(dev, modeset->mode); - modeset->mode = drm_mode_duplicate(dev, + if (fb_crtc->mode) + drm_mode_destroy(dev, fb_crtc->mode); + fb_crtc->mode = drm_mode_duplicate(dev, fb_crtc->desired_mode); + modeset->mode = fb_crtc->mode; modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector; modeset->fb = fb_helper->fb; modeset->x = offset->x; @@ -1708,11 +1716,14 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
/* Clear out any old modes if there are no more connected outputs. */ for (i = 0; i < fb_helper->crtc_count; i++) { - modeset = &fb_helper->crtc_info[i].mode_set; + struct drm_fb_helper_crtc *fb_crtc = &fb_helper->crtc_info[i]; + + modeset = &fb_crtc->mode_set; if (modeset->num_connectors == 0) { BUG_ON(modeset->fb); - if (modeset->mode) - drm_mode_destroy(dev, modeset->mode); + if (fb_crtc->mode) + drm_mode_destroy(dev, fb_crtc->mode); + fb_crtc->mode = NULL; modeset->mode = NULL; } } diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 757c0d2..83566e0 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -471,6 +471,10 @@ retry: to_intel_crtc(encoder->crtc)->config); modes[i] = &encoder->crtc->hwmode; } + + if (modes[i]) + modes[i] = + drm_mode_duplicate(encoder->crtc->dev, modes[i]); crtcs[i] = new_crtc;
DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n", diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 5c289f7..3c231b2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -212,7 +212,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set) struct vmw_private *dev_priv; struct vmw_legacy_display_unit *ldu; struct drm_connector *connector; - struct drm_display_mode *mode; + const struct drm_display_mode *mode; struct drm_encoder *encoder; struct vmw_framebuffer *vfb; struct drm_framebuffer *fb; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 7dc591d..213afa5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -104,7 +104,7 @@ static void vmw_sou_add_active(struct vmw_private *vmw_priv, static int vmw_sou_fifo_create(struct vmw_private *dev_priv, struct vmw_screen_object_unit *sou, uint32_t x, uint32_t y, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { size_t fifo_size;
@@ -254,7 +254,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set) struct vmw_private *dev_priv; struct vmw_screen_object_unit *sou; struct drm_connector *connector; - struct drm_display_mode *mode; + const struct drm_display_mode *mode; struct drm_encoder *encoder; struct vmw_framebuffer *vfb; struct drm_framebuffer *fb; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index dbc1510..7b141d837 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -961,7 +961,7 @@ struct drm_atomic_state { struct drm_mode_set { struct drm_framebuffer *fb; struct drm_crtc *crtc; - struct drm_display_mode *mode; + const struct drm_display_mode *mode;
uint32_t x; uint32_t y; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 0dfd94def..e6a4b8c 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -40,6 +40,9 @@ struct drm_fb_offset {
struct drm_fb_helper_crtc { struct drm_mode_set mode_set; + /* mode here is a duplicate of mode_set.mode, but non-const so we + * can later free it */ + struct drm_display_mode *mode; struct drm_display_mode *desired_mode; int x, y; };
Holding a pointer to the mode, rather than an embed, allows us to get towards sharing refcounted modes.
XXX: atomic_destroy_state does _not_ seem to be optional - so we should remove any fallback paths which compensate for its lack! the crtc_state->mode handling is particularly ugly here :\
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_atomic_helper.c | 35 +++++++++++++++++++++++-------- drivers/gpu/drm/drm_crtc.c | 2 +- drivers/gpu/drm/drm_crtc_helper.c | 32 ++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_atomic.c | 18 +++++++++++++++- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 2 +- drivers/gpu/drm/tegra/dc.c | 8 +++++++ drivers/gpu/drm/tegra/dsi.c | 4 ++-- drivers/gpu/drm/tegra/hdmi.c | 2 +- drivers/gpu/drm/tegra/rgb.c | 2 +- drivers/gpu/drm/tegra/sor.c | 2 +- include/drm/drm_crtc.h | 2 +- 12 files changed, 88 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 5bcb4ba..962443d 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -260,7 +260,7 @@ mode_fixup(struct drm_atomic_state *state) if (!crtc_state || !crtc_state->mode_changed) continue;
- drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode); + drm_mode_copy(&crtc_state->adjusted_mode, crtc_state->mode); }
for (i = 0; i < state->num_connector; i++) { @@ -289,7 +289,7 @@ mode_fixup(struct drm_atomic_state *state)
if (encoder->bridge && encoder->bridge->funcs->mode_fixup) { ret = encoder->bridge->funcs->mode_fixup( - encoder->bridge, &crtc_state->mode, + encoder->bridge, crtc_state->mode, &crtc_state->adjusted_mode); if (!ret) { DRM_DEBUG_ATOMIC("Bridge fixup failed\n"); @@ -306,7 +306,7 @@ mode_fixup(struct drm_atomic_state *state) return ret; } } else { - ret = funcs->mode_fixup(encoder, &crtc_state->mode, + ret = funcs->mode_fixup(encoder, crtc_state->mode, &crtc_state->adjusted_mode); if (!ret) { DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] fixup failed\n", @@ -327,7 +327,7 @@ mode_fixup(struct drm_atomic_state *state) continue;
funcs = crtc->helper_private; - ret = funcs->mode_fixup(crtc, &crtc_state->mode, + ret = funcs->mode_fixup(crtc, crtc_state->mode, &crtc_state->adjusted_mode); if (!ret) { DRM_DEBUG_ATOMIC("[CRTC:%d] fixup failed\n", @@ -383,7 +383,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, if (!crtc) continue;
- if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) { + if (!drm_mode_equal(crtc->state->mode, crtc_state->mode)) { DRM_DEBUG_ATOMIC("[CRTC:%d] mode changed\n", crtc->base.id); crtc_state->mode_changed = true; @@ -699,7 +699,7 @@ set_routing_links(struct drm_device *dev, struct drm_atomic_state *old_state) if (!crtc) continue;
- crtc->mode = crtc->state->mode; + crtc->mode = *crtc->state->mode; crtc->enabled = crtc->state->enable; crtc->x = crtc->primary->state->src_x >> 16; crtc->y = crtc->primary->state->src_y >> 16; @@ -746,7 +746,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) encoder = connector->state->best_encoder; funcs = encoder->helper_private; new_crtc_state = connector->state->crtc->state; - mode = &new_crtc_state->mode; + mode = new_crtc_state->mode; adjusted_mode = &new_crtc_state->adjusted_mode;
if (!new_crtc_state->mode_changed) @@ -1643,7 +1643,7 @@ retry:
crtc_state->enable = true; crtc_state->active = true; - drm_mode_copy(&crtc_state->mode, set->mode); + drm_mode_copy(crtc_state->mode, set->mode);
ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); if (ret != 0) @@ -2058,11 +2058,22 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms); */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) { + if (crtc->state) + kfree(crtc->state->mode); + kfree(crtc->state); crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
- if (crtc->state) + if (crtc->state) { crtc->state->crtc = crtc; + crtc->state->mode = + kzalloc(sizeof(*crtc->state->mode), GFP_KERNEL); + } + + if (crtc->state && !crtc->state->mode) { + kfree(crtc->state); + crtc->state = NULL; + } } EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
@@ -2088,6 +2099,11 @@ drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) state->active_changed = false; state->planes_changed = false; state->event = NULL; + state->mode = drm_mode_duplicate(crtc->dev, crtc->state->mode); + if (!state->mode) { + kfree(state); + state = NULL; + } }
return state; @@ -2105,6 +2121,7 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { + kfree(state->mode); kfree(state); } EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5785336..6023851 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2008,7 +2008,7 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->primary->state->src_x >> 16; crtc_resp->y = crtc->primary->state->src_y >> 16; if (crtc->state->enable) { - drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->state->mode); + drm_crtc_convert_to_umode(&crtc_resp->mode, crtc->state->mode); crtc_resp->mode_valid = 1;
} else { diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index c6063ff..8a9a045 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -943,11 +943,32 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc,
if (crtc->funcs->atomic_duplicate_state) crtc_state = crtc->funcs->atomic_duplicate_state(crtc); - else if (crtc->state) + else if (crtc->state) { crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), GFP_KERNEL); - else + /* XXX: this is unpleasant: we should mandate dup instead */ + if (crtc_state) { + crtc_state->mode = + drm_mode_duplicate(crtc->dev, + crtc->state->mode); + if (!crtc_state->mode) { + kfree(crtc_state); + crtc_state = NULL; + } + } + } + else { crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); + if (crtc_state) { + crtc_state->mode = kzalloc(sizeof(*crtc_state->mode), + GFP_KERNEL); + /* XXX: as above, but mandate a new_state */ + if (!crtc_state->mode) { + kfree(crtc_state); + crtc_state = NULL; + } + } + } if (!crtc_state) return -ENOMEM; crtc_state->crtc = crtc; @@ -955,12 +976,13 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, crtc_state->enable = true; crtc_state->planes_changed = true; crtc_state->mode_changed = true; - drm_mode_copy(&crtc_state->mode, mode); + drm_mode_copy(crtc_state->mode, mode); drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode);
if (crtc_funcs->atomic_check) { ret = crtc_funcs->atomic_check(crtc, crtc_state); if (ret) { + kfree(crtc_state->mode); kfree(crtc_state);
return ret; @@ -974,8 +996,10 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, if (crtc_state) { if (crtc->funcs->atomic_destroy_state) crtc->funcs->atomic_destroy_state(crtc, crtc_state); - else + else { + kfree(crtc_state->mode); kfree(crtc_state); + } }
return drm_helper_crtc_mode_set_base(crtc, x, y, old_fb); diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 3903b90..c479386 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -222,9 +222,25 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state = kmemdup(intel_crtc->config, sizeof(*intel_crtc->config), GFP_KERNEL);
- if (crtc_state) + if (crtc_state) { crtc_state->base.crtc = crtc;
+ /* XXX: this is tedious */ + if (intel_crtc->config) { + crtc_state->mode = + drm_mode_duplicate(crtc->dev, + intel_crtc->config->mode); + } else { + crtc_state->mode = + kzalloc(sizeof(*crtc_state->mode), GFP_KERNEL); + } + + if (!crtc_state->mode) { + kfree(crtc_state); + crtc_state = NULL; + } + } + return &crtc_state->base; }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 0db6a54..14d74b4 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -64,7 +64,7 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder, { struct rcar_du_encoder *renc = to_rcar_encoder(encoder); struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; - const struct drm_display_mode *mode = &crtc_state->mode; + const struct drm_display_mode *mode = crtc_state->mode; const struct drm_display_mode *panel_mode; struct drm_connector *connector = conn_state->connector; struct drm_device *dev = encoder->dev; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c index c000850..1c9b6f0 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c @@ -69,7 +69,7 @@ static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder, struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; - const struct drm_display_mode *mode = &crtc_state->mode; + const struct drm_display_mode *mode = crtc_state->mode;
/* The internal LVDS encoder has a clock frequency operating range of * 30MHz to 150MHz. Clamp the clock accordingly. diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index b7f7815..40f6e74 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1015,6 +1015,13 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) if (!copy) return NULL;
+ /* XXX: tedium */ + copy->base.mode = drm_mode_duplicate(crtc->dev, state->base.mode); + if (!copy->base.mode) { + kfree(copy); + return NULL; + } + copy->base.mode_changed = false; copy->base.active_changed = false; copy->base.planes_changed = false; @@ -1026,6 +1033,7 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { + kfree(state->mode); kfree(state); }
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index 4714eb4..cfd4da7 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -887,7 +887,7 @@ tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder, unsigned long plld; int err;
- state->pclk = crtc_state->mode.clock * 1000; + state->pclk = crtc_state->mode->clock * 1000;
err = tegra_dsi_get_muldiv(dsi->format, &state->mul, &state->div); if (err < 0) @@ -899,7 +899,7 @@ tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder, if (err < 0) return err;
- state->vrefresh = drm_mode_vrefresh(&crtc_state->mode); + state->vrefresh = drm_mode_vrefresh(crtc_state->mode);
/* compute byte clock */ state->bclk = (state->pclk * state->mul) / (state->div * state->lanes); diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 68d315e..d80de91 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -1060,7 +1060,7 @@ tegra_hdmi_encoder_atomic_check(struct drm_encoder *encoder, { struct tegra_output *output = encoder_to_output(encoder); struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); - unsigned long pclk = crtc_state->mode.clock * 1000; + unsigned long pclk = crtc_state->mode->clock * 1000; struct tegra_hdmi *hdmi = to_hdmi(output); int err;
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 745759a..5b4d86a 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -196,7 +196,7 @@ tegra_rgb_encoder_atomic_check(struct drm_encoder *encoder, { struct tegra_output *output = encoder_to_output(encoder); struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); - unsigned long pclk = crtc_state->mode.clock * 1000; + unsigned long pclk = crtc_state->mode->clock * 1000; struct tegra_rgb *rgb = to_rgb(output); unsigned int div; int err; diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index fe86207..d0eaa48 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -1282,7 +1282,7 @@ tegra_sor_encoder_atomic_check(struct drm_encoder *encoder, { struct tegra_output *output = encoder_to_output(encoder); struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); - unsigned long pclk = crtc_state->mode.clock * 1000; + unsigned long pclk = crtc_state->mode->clock * 1000; struct tegra_sor *sor = to_sor(output); int err;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 7b141d837..2bce96e 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -294,7 +294,7 @@ struct drm_crtc_state { /* adjusted_mode: for use by helpers and drivers */ struct drm_display_mode adjusted_mode;
- struct drm_display_mode mode; + struct drm_display_mode *mode;
struct drm_pending_vblank_event *event;
On Thu, Mar 19, 2015 at 04:33:16AM +0000, Daniel Stone wrote:
Holding a pointer to the mode, rather than an embed, allows us to get towards sharing refcounted modes.
XXX: atomic_destroy_state does _not_ seem to be optional - so we should remove any fallback paths which compensate for its lack! the crtc_state->mode handling is particularly ugly here :\
duplicate/destroy callbacks are optional in the transitional helpers. And that's fairly intentional to avoid the need for switching to the full state scaffolding at once.
For these couldn't we instead just store a pointer to crtc->mode instead? Lifetimes should be fully in sync.
@@ -2058,11 +2058,22 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms); */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) {
- if (crtc->state)
kfree(crtc->state->mode);
- kfree(crtc->state); crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
- if (crtc->state)
- if (crtc->state) { crtc->state->crtc = crtc;
crtc->state->mode =
kzalloc(sizeof(*crtc->state->mode), GFP_KERNEL);
Allocating an empty mode object seems superflous. Why do we need this?
- }
- if (crtc->state && !crtc->state->mode) {
kfree(crtc->state);
crtc->state = NULL;
- }
} EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
@@ -2088,6 +2099,11 @@ drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) state->active_changed = false; state->planes_changed = false; state->event = NULL;
state->mode = drm_mode_duplicate(crtc->dev, crtc->state->mode);
if (!state->mode) {
kfree(state);
state = NULL;
}
}
return state;
@@ -2105,6 +2121,7 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) {
- kfree(state->mode); kfree(state);
} EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5785336..6023851 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2008,7 +2008,7 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->primary->state->src_x >> 16; crtc_resp->y = crtc->primary->state->src_y >> 16; if (crtc->state->enable) {
drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
drm_crtc_convert_to_umode(&crtc_resp->mode, crtc->state->mode); crtc_resp->mode_valid = 1;
} else {
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index c6063ff..8a9a045 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -943,11 +943,32 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc,
if (crtc->funcs->atomic_duplicate_state) crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
- else if (crtc->state)
- else if (crtc->state) { crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), GFP_KERNEL);
- else
/* XXX: this is unpleasant: we should mandate dup instead */
if (crtc_state) {
crtc_state->mode =
drm_mode_duplicate(crtc->dev,
crtc->state->mode);
if (!crtc_state->mode) {
kfree(crtc_state);
crtc_state = NULL;
}
}
- }
- else { crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
if (crtc_state) {
crtc_state->mode = kzalloc(sizeof(*crtc_state->mode),
GFP_KERNEL);
/* XXX: as above, but mandate a new_state */
if (!crtc_state->mode) {
kfree(crtc_state);
crtc_state = NULL;
}
}
- }
I think for transitional helpers if we just do a crtc_state->mode = crtc->mode that should be all that's needed. -Daniel
Holding a pointer to the mode, rather than an embed, allows us to get towards sharing refcounted modes.
XXX: split into two - drm_mode_copy changes first, then the others
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/armada/armada_overlay.c | 4 +-- drivers/gpu/drm/ast/ast_mode.c | 8 ++--- drivers/gpu/drm/drm_atomic_helper.c | 47 +++++++++++++++----------- drivers/gpu/drm/drm_crtc.c | 11 ++++-- drivers/gpu/drm/drm_crtc_helper.c | 34 ++++++++++++------- drivers/gpu/drm/drm_plane_helper.c | 6 ++-- drivers/gpu/drm/i2c/sil164_drv.c | 2 +- drivers/gpu/drm/i915/intel_atomic.c | 26 ++++++-------- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 4 +-- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/cursor.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c | 4 +-- drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +- drivers/gpu/drm/nouveau/nv50_display.c | 2 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 4 +-- drivers/gpu/drm/qxl/qxl_display.c | 4 +-- drivers/gpu/drm/radeon/atombios_crtc.c | 12 +++---- drivers/gpu/drm/radeon/cik.c | 4 +-- drivers/gpu/drm/radeon/evergreen.c | 6 ++-- drivers/gpu/drm/radeon/r100.c | 4 +-- drivers/gpu/drm/radeon/radeon_connectors.c | 2 +- drivers/gpu/drm/radeon/radeon_cursor.c | 4 +-- drivers/gpu/drm/radeon/radeon_display.c | 12 +++---- drivers/gpu/drm/radeon/rs600.c | 4 +-- drivers/gpu/drm/radeon/rs690.c | 16 ++++----- drivers/gpu/drm/radeon/rs780_dpm.c | 4 +-- drivers/gpu/drm/radeon/rv515.c | 20 +++++------ drivers/gpu/drm/radeon/si.c | 6 ++-- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 ++--- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 2 +- drivers/gpu/drm/sti/sti_drm_crtc.c | 2 +- drivers/gpu/drm/tegra/dc.c | 16 ++++++--- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 10 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 32 +++++++++--------- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 10 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 6 ++-- include/drm/drm_crtc.h | 2 +- 39 files changed, 187 insertions(+), 161 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index c5b06fd..4e586ab 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -109,8 +109,8 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, unsigned idx = 0; int ret;
- crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode.hdisplay); - crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode.vdisplay); + crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode->hdisplay); + crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode->vdisplay); ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index fb11f75..3585624 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -100,7 +100,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, return false; }
- switch (crtc->mode.crtc_hdisplay) { + switch (crtc->mode->crtc_hdisplay) { case 640: vbios_mode->enh_table = &res_640x480[refresh_rate_index]; break; @@ -111,7 +111,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, vbios_mode->enh_table = &res_1024x768[refresh_rate_index]; break; case 1280: - if (crtc->mode.crtc_vdisplay == 800) + if (crtc->mode->crtc_vdisplay == 800) vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; else vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; @@ -123,7 +123,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; break; case 1600: - if (crtc->mode.crtc_vdisplay == 900) + if (crtc->mode->crtc_vdisplay == 900) vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; else vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; @@ -132,7 +132,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; break; case 1920: - if (crtc->mode.crtc_vdisplay == 1080) + if (crtc->mode->crtc_vdisplay == 1080) vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; else vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 962443d..bc7b629 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -699,7 +699,14 @@ set_routing_links(struct drm_device *dev, struct drm_atomic_state *old_state) if (!crtc) continue;
- crtc->mode = *crtc->state->mode; + if (crtc->state->mode) { + if (crtc->mode) + drm_mode_destroy(dev, crtc->mode); + crtc->mode = drm_mode_duplicate(dev, crtc->state->mode); + } else if (crtc->mode) { + drm_mode_destroy(dev, crtc->mode); + crtc->mode = NULL; + } crtc->enabled = crtc->state->enable; crtc->x = crtc->primary->state->src_x >> 16; crtc->y = crtc->primary->state->src_y >> 16; @@ -1643,7 +1650,9 @@ retry:
crtc_state->enable = true; crtc_state->active = true; - drm_mode_copy(crtc_state->mode, set->mode); + if (crtc_state->mode) + drm_mode_destroy(crtc->dev, crtc_state->mode); + crtc_state->mode = drm_mode_duplicate(crtc->dev, set->mode);
ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); if (ret != 0) @@ -2058,22 +2067,16 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms); */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) { - if (crtc->state) - kfree(crtc->state->mode); + if (crtc->state && crtc->state->mode) + drm_mode_destroy(crtc->dev, crtc->state->mode);
kfree(crtc->state); crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
- if (crtc->state) { - crtc->state->crtc = crtc; - crtc->state->mode = - kzalloc(sizeof(*crtc->state->mode), GFP_KERNEL); - } + if (!crtc->state) + return;
- if (crtc->state && !crtc->state->mode) { - kfree(crtc->state); - crtc->state = NULL; - } + crtc->state->crtc = crtc; } EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
@@ -2094,12 +2097,18 @@ drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
state = kmemdup(crtc->state, sizeof(*crtc->state), GFP_KERNEL);
- if (state) { - state->mode_changed = false; - state->active_changed = false; - state->planes_changed = false; - state->event = NULL; - state->mode = drm_mode_duplicate(crtc->dev, crtc->state->mode); + if (!state) + return NULL; + + state->mode_changed = false; + state->active_changed = false; + state->planes_changed = false; + state->event = NULL; + + if (crtc->state->mode) { + state->mode = + drm_mode_duplicate(crtc->dev, + crtc->state->mode); if (!state->mode) { kfree(state); state = NULL; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 6023851..cf44403 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -662,6 +662,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, crtc->dev = dev; crtc->funcs = funcs; crtc->invert_dimensions = false; + crtc->mode = NULL;
drm_modeset_lock_init(&crtc->mutex); ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); @@ -700,6 +701,9 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev;
+ kfree(crtc->mode); + crtc->mode = NULL; + kfree(crtc->gamma_store); crtc->gamma_store = NULL;
@@ -2008,6 +2012,7 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->primary->state->src_x >> 16; crtc_resp->y = crtc->primary->state->src_y >> 16; if (crtc->state->enable) { + WARN_ON(!crtc->state->mode); drm_crtc_convert_to_umode(&crtc_resp->mode, crtc->state->mode); crtc_resp->mode_valid = 1;
@@ -2018,7 +2023,9 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->x; crtc_resp->y = crtc->y; if (crtc->enabled) { - drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); + WARN_ON(!crtc->mode); + drm_crtc_convert_to_umode(&crtc_resp->mode, + crtc->mode); crtc_resp->mode_valid = 1;
} else { @@ -4942,7 +4949,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, goto out; }
- ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb); + ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, crtc->mode, fb); if (ret) goto out;
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 8a9a045..46497dd 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -270,7 +270,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; - struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; + const struct drm_display_mode *saved_mode; + struct drm_display_mode *adjusted_mode, saved_hwmode; struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct drm_encoder_helper_funcs *encoder_funcs; int saved_x, saved_y; @@ -292,14 +293,17 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, }
saved_mode = crtc->mode; - saved_hwmode = crtc->hwmode; + drm_mode_copy(&saved_hwmode, &crtc->hwmode); saved_x = crtc->x; saved_y = crtc->y;
/* Update crtc values up front so the driver can rely on them for mode * setting. */ - crtc->mode = *mode; + if (mode) + crtc->mode = drm_mode_duplicate(crtc->dev, mode); + else + crtc->mode = NULL; crtc->x = x; crtc->y = y;
@@ -335,7 +339,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, } DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
- crtc->hwmode = *adjusted_mode; + drm_mode_copy(&crtc->hwmode, adjusted_mode);
/* Prepare the encoders and CRTCs before setting the mode. */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { @@ -410,10 +414,14 @@ done: drm_mode_destroy(dev, adjusted_mode); if (!ret) { crtc->enabled = saved_enabled; + if (crtc->mode) + drm_mode_destroy(crtc->dev, crtc->mode); crtc->mode = saved_mode; - crtc->hwmode = saved_hwmode; + drm_mode_copy(&crtc->hwmode, &saved_hwmode); crtc->x = saved_x; crtc->y = saved_y; + } else { + drm_mode_destroy(dev, saved_mode); }
return ret; @@ -539,7 +547,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) }
save_set.crtc = set->crtc; - save_set.mode = &set->crtc->mode; + save_set.mode = set->crtc->mode; save_set.x = set->crtc->x; save_set.y = set->crtc->y; save_set.fb = set->crtc->primary->fb; @@ -563,9 +571,9 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (set->x != set->crtc->x || set->y != set->crtc->y) fb_changed = true;
- if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { + if (set->mode && !drm_mode_equal(set->mode, set->crtc->mode)) { DRM_DEBUG_KMS("modes are different, full mode set\n"); - drm_mode_debug_printmodeline(&set->crtc->mode); + drm_mode_debug_printmodeline(set->crtc->mode); drm_mode_debug_printmodeline(set->mode); mode_changed = true; } @@ -881,7 +889,7 @@ void drm_helper_resume_force_mode(struct drm_device *dev) if (!crtc->enabled) continue;
- ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, + ret = drm_crtc_helper_set_mode(crtc, crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
/* Restoring the old config should never fail! */ @@ -1040,12 +1048,12 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb); plane_state->crtc_x = 0; plane_state->crtc_y = 0; - plane_state->crtc_h = crtc->mode.vdisplay; - plane_state->crtc_w = crtc->mode.hdisplay; + plane_state->crtc_h = crtc->mode ? crtc->mode->vdisplay : 0; + plane_state->crtc_w = crtc->mode ? crtc->mode->hdisplay : 0; plane_state->src_x = x << 16; plane_state->src_y = y << 16; - plane_state->src_h = crtc->mode.vdisplay << 16; - plane_state->src_w = crtc->mode.hdisplay << 16; + plane_state->src_h = crtc->mode ? crtc->mode->vdisplay << 16 : 0; + plane_state->src_w = crtc->mode ? crtc->mode->hdisplay << 16 : 0;
return drm_plane_helper_commit(plane, plane_state, old_fb); } diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 33807e0..079ac2b 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -230,7 +230,7 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_mode_set set = { .crtc = crtc, .fb = fb, - .mode = &crtc->mode, + .mode = crtc->mode, .x = src_x >> 16, .y = src_y >> 16, }; @@ -247,8 +247,8 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, .y2 = crtc_y + crtc_h, }; const struct drm_rect clip = { - .x2 = crtc->mode.hdisplay, - .y2 = crtc->mode.vdisplay, + .x2 = crtc->mode ? crtc->mode->hdisplay : 0, + .y2 = crtc->mode ? crtc->mode->vdisplay : 0, }; struct drm_connector **connector_list; int num_connectors, ret; diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c index dd7cea2..f8baf08 100644 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ b/drivers/gpu/drm/i2c/sil164_drv.c @@ -218,7 +218,7 @@ sil164_encoder_dpms(struct drm_encoder *encoder, int mode) { struct sil164_priv *priv = to_sil164_priv(encoder); bool on = (mode == DRM_MODE_DPMS_ON); - bool duallink = (on && encoder->crtc->mode.clock > 165000); + bool duallink = (on && encoder->crtc->mode->clock > 165000);
sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on);
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index c479386..80cb562 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -222,26 +222,22 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state = kmemdup(intel_crtc->config, sizeof(*intel_crtc->config), GFP_KERNEL);
- if (crtc_state) { - crtc_state->base.crtc = crtc; + if (!crtc_state) + return NULL;
- /* XXX: this is tedious */ - if (intel_crtc->config) { - crtc_state->mode = - drm_mode_duplicate(crtc->dev, - intel_crtc->config->mode); - } else { - crtc_state->mode = - kzalloc(sizeof(*crtc_state->mode), GFP_KERNEL); - } + crtc_state->base.crtc = crtc;
- if (!crtc_state->mode) { - kfree(crtc_state); - crtc_state = NULL; - } + if (intel_crtc->config && intel_crtc->config->mode) { + crtc_state->mode = + drm_mode_duplicate(crtc->dev, intel_crtc->config->mode); + if (!crtc_state->mode) + goto err; }
return &crtc_state->base; +err: + kfree(crtc_state); + return NULL; }
/** diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 2f2863c..1d6c510 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -414,8 +414,8 @@ static int mdp5_crtc_set_property(struct drm_crtc *crtc, static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h) { struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); - uint32_t xres = crtc->mode.hdisplay; - uint32_t yres = crtc->mode.vdisplay; + uint32_t xres = crtc->mode->hdisplay; + uint32_t yres = crtc->mode->vdisplay;
/* * Cursor Region Of Interest (ROI) is a plane read from cursor diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 093a420..c9d19c6 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -886,7 +886,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start);
/* Update the arbitration parameters. */ - nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel, + nouveau_calc_arb(dev, crtc->mode->clock, drm_fb->bits_per_pixel, &arb_burst, &arb_lwm);
regp->CRTC[NV_CIO_CRE_FF_INDEX] = arb_burst; diff --git a/drivers/gpu/drm/nouveau/dispnv04/cursor.c b/drivers/gpu/drm/nouveau/dispnv04/cursor.c index 4e61173..e9a83aa 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/cursor.c +++ b/drivers/gpu/drm/nouveau/dispnv04/cursor.c @@ -47,7 +47,7 @@ nv04_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) XLATE(offset, 17, NV_CIO_CRE_HCUR_ADDR0_ADR); regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] = XLATE(offset, 11, NV_CIO_CRE_HCUR_ADDR1_ADR); - if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) + if (crtc->mode->flags & DRM_MODE_FLAG_DBLSCAN) regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] |= MASK(NV_CIO_CRE_HCUR_ADDR1_CUR_DBL); regp->CRTC[NV_CIO_CRE_HCUR_ADDR2_INDEX] = offset >> 24; diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c index 08c6f5e..eb11ec8 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c @@ -317,7 +317,7 @@ static void tv_setup_filter(struct drm_encoder *encoder) { struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); - struct drm_display_mode *mode = &encoder->crtc->mode; + struct drm_display_mode *mode = encoder->crtc->mode; uint32_t (*filters[])[4][7] = {&tv_enc->state.hfilter, &tv_enc->state.vfilter}; int i, j, k; @@ -546,7 +546,7 @@ void nv17_ctv_update_rescaler(struct drm_encoder *encoder) struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); int head = nouveau_crtc(encoder->crtc)->index; struct nv04_crtc_reg *regs = &nv04_display(dev)->mode_reg.crtc_reg[head]; - struct drm_display_mode *crtc_mode = &encoder->crtc->mode; + struct drm_display_mode *crtc_mode = encoder->crtc->mode; struct drm_display_mode *output_mode = &get_tv_norm(encoder)->ctv_enc_mode.mode; int overscan, hmargin, vmargin, hratio, vratio; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 604d944..1b4ac68 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -501,7 +501,7 @@ nouveau_connector_set_property(struct drm_connector *connector,
if (modeset || !nv_crtc->set_scale) { ret = drm_crtc_helper_set_mode(&nv_crtc->base, - &nv_crtc->base.mode, + nv_crtc->base.mode, nv_crtc->base.x, nv_crtc->base.y, NULL); if (!ret) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 05b21ef..b1da742 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -722,7 +722,7 @@ static int nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) { struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); - struct drm_display_mode *omode, *umode = &nv_crtc->base.mode; + struct drm_display_mode *omode, *umode = nv_crtc->base.mode; struct drm_crtc *crtc = &nv_crtc->base; struct nouveau_connector *nv_connector; int mode = DRM_MODE_SCALE_NONE; diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index f394fdd..b3ea6ae 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -282,7 +282,7 @@ static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct drm_plane *plane = omap_crtc->plane; - struct drm_display_mode *mode = &crtc->mode; + struct drm_display_mode *mode = crtc->mode;
return omap_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, mode->hdisplay, mode->vdisplay, @@ -315,7 +315,7 @@ static void page_flip_worker(struct work_struct *work) struct omap_crtc *omap_crtc = container_of(work, struct omap_crtc, page_flip_work); struct drm_crtc *crtc = &omap_crtc->base; - struct drm_display_mode *mode = &crtc->mode; + struct drm_display_mode *mode = crtc->mode; struct drm_gem_object *bo;
drm_modeset_lock(&crtc->mutex, NULL); diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 189119d..83180e4 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -665,7 +665,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, static void qxl_crtc_prepare(struct drm_crtc *crtc) { DRM_DEBUG("current: %dx%d+%d+%d (%d).\n", - crtc->mode.hdisplay, crtc->mode.vdisplay, + crtc->mode->hdisplay, crtc->mode->vdisplay, crtc->x, crtc->y, crtc->enabled); }
@@ -765,7 +765,7 @@ static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev, head = &qdev->monitors_config->heads[i]; head->id = i; if (encoder->crtc->enabled) { - mode = &encoder->crtc->mode; + mode = encoder->crtc->mode; head->width = mode->hdisplay; head->height = mode->vdisplay; head->x = encoder->crtc->x; diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 050e908..269e9fb 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1404,10 +1404,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, y &= ~1; WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y); - viewport_w = crtc->mode.hdisplay; - viewport_h = (crtc->mode.vdisplay + 1) & ~1; + viewport_w = crtc->mode->hdisplay; + viewport_h = (crtc->mode->vdisplay + 1) & ~1; if ((rdev->family >= CHIP_BONAIRE) && - (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)) + (crtc->mode->flags & DRM_MODE_FLAG_INTERLACE)) viewport_h *= 2; WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, (viewport_w << 16) | viewport_h); @@ -1607,8 +1607,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, y &= ~1; WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y); - viewport_w = crtc->mode.hdisplay; - viewport_h = (crtc->mode.vdisplay + 1) & ~1; + viewport_w = crtc->mode->hdisplay; + viewport_h = (crtc->mode->vdisplay + 1) & ~1; WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, (viewport_w << 16) | viewport_h);
@@ -1780,7 +1780,7 @@ static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc) } /* for non-DP check the clock */ test_adjusted_clock = test_radeon_crtc->adjusted_clock; - if ((crtc->mode.clock == test_crtc->mode.clock) && + if ((crtc->mode->clock == test_crtc->mode->clock) && (adjusted_clock == test_adjusted_clock) && (radeon_crtc->ss_enabled == test_radeon_crtc->ss_enabled) && (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 3e670d3..bb604f0 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -9325,7 +9325,7 @@ static void dce8_program_watermarks(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, u32 lb_size, u32 num_heads) { - struct drm_display_mode *mode = &radeon_crtc->base.mode; + struct drm_display_mode *mode = radeon_crtc->base.mode; struct dce8_wm_params wm_low, wm_high; u32 pixel_period; u32 line_time = 0; @@ -9467,7 +9467,7 @@ void dce8_bandwidth_update(struct radeon_device *rdev) num_heads++; } for (i = 0; i < rdev->num_crtc; i++) { - mode = &rdev->mode_info.crtcs[i]->base.mode; + mode = rdev->mode_info.crtcs[i]->base.mode; lb_size = dce8_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i], mode); dce8_program_watermarks(rdev, rdev->mode_info.crtcs[i], lb_size, num_heads); } diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 973df06..439a0ee 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2180,7 +2180,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, u32 lb_size, u32 num_heads) { - struct drm_display_mode *mode = &radeon_crtc->base.mode; + struct drm_display_mode *mode = radeon_crtc->base.mode; struct evergreen_wm_params wm_low, wm_high; u32 dram_channels; u32 pixel_period; @@ -2356,8 +2356,8 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) num_heads++; } for (i = 0; i < rdev->num_crtc; i += 2) { - mode0 = &rdev->mode_info.crtcs[i]->base.mode; - mode1 = &rdev->mode_info.crtcs[i+1]->base.mode; + mode0 = rdev->mode_info.crtcs[i]->base.mode; + mode1 = rdev->mode_info.crtcs[i+1]->base.mode; lb_size = evergreen_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i], mode0, mode1); evergreen_program_watermarks(rdev, rdev->mode_info.crtcs[i], lb_size, num_heads); lb_size = evergreen_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i+1], mode1, mode0); diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 04f2514..31fc514 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) radeon_update_display_priority(rdev);
if (rdev->mode_info.crtcs[0]->base.enabled) { - mode1 = &rdev->mode_info.crtcs[0]->base.mode; + mode1 = rdev->mode_info.crtcs[0]->base.mode; 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; + mode2 = rdev->mode_info.crtcs[1]->base.mode; 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 2aae77f..91eeb6d 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -90,7 +90,7 @@ static void radeon_property_change_mode(struct drm_encoder *encoder) struct drm_crtc *crtc = encoder->crtc;
if (crtc && crtc->enabled) { - drm_crtc_helper_set_mode(crtc, &crtc->mode, + drm_crtc_helper_set_mode(crtc, crtc->mode, crtc->x, crtc->y, crtc->primary->fb); } } diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 45e5406..fc2c51b 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -162,7 +162,7 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y) int cursor_end, frame_end;
cursor_end = x - xorigin + w; - frame_end = crtc->x + crtc->mode.crtc_hdisplay; + frame_end = crtc->x + crtc->mode->crtc_hdisplay; if (cursor_end >= frame_end) { w = w - (cursor_end - frame_end); if (!(frame_end & 0x7f)) @@ -193,7 +193,7 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y) WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); } else { - if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) + if (crtc->mode->flags & DRM_MODE_FLAG_DBLSCAN) y *= 2;
WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset, diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 913fafa..4f2ebe0e 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1702,9 +1702,9 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, memcpy(&radeon_crtc->native_mode, &radeon_encoder->native_mode, sizeof(struct drm_display_mode)); - src_v = crtc->mode.vdisplay; + src_v = crtc->mode->vdisplay; dst_v = radeon_crtc->native_mode.vdisplay; - src_h = crtc->mode.hdisplay; + src_h = crtc->mode->hdisplay; dst_h = radeon_crtc->native_mode.hdisplay;
/* fix up for overscan on hdmi */ @@ -1723,10 +1723,10 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, else radeon_crtc->v_border = (mode->vdisplay >> 5) + 16; radeon_crtc->rmx_type = RMX_FULL; - src_v = crtc->mode.vdisplay; - dst_v = crtc->mode.vdisplay - (radeon_crtc->v_border * 2); - src_h = crtc->mode.hdisplay; - dst_h = crtc->mode.hdisplay - (radeon_crtc->h_border * 2); + src_v = crtc->mode->vdisplay; + dst_v = crtc->mode->vdisplay - (radeon_crtc->v_border * 2); + src_h = crtc->mode->hdisplay; + dst_h = crtc->mode->hdisplay - (radeon_crtc->h_border * 2); } first = false; } else { diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 97a9048..15c9085 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -894,9 +894,9 @@ void rs600_bandwidth_update(struct radeon_device *rdev) radeon_update_display_priority(rdev);
if (rdev->mode_info.crtcs[0]->base.enabled) - mode0 = &rdev->mode_info.crtcs[0]->base.mode; + mode0 = rdev->mode_info.crtcs[0]->base.mode; if (rdev->mode_info.crtcs[1]->base.enabled) - mode1 = &rdev->mode_info.crtcs[1]->base.mode; + mode1 = rdev->mode_info.crtcs[1]->base.mode;
rs690_line_buffer_adjust(rdev, mode0, mode1);
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 516ca27..0a8ce19 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -263,7 +263,7 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, struct rs690_watermark *wm, bool low) { - struct drm_display_mode *mode = &crtc->base.mode; + struct drm_display_mode *mode = crtc->base.mode; fixed20_12 a, b, c; fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; @@ -337,7 +337,7 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, * LineTime = total number of horizontal pixels * pclk = pixel clock period(ns) */ - a.full = dfixed_const(crtc->base.mode.crtc_htotal); + a.full = dfixed_const(crtc->base.mode->crtc_htotal); line_time.full = dfixed_mul(a, pclk);
/* Determine active time @@ -345,8 +345,8 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, * hactive = total number of horizontal active pixels * htotal = total number of horizontal pixels */ - a.full = dfixed_const(crtc->base.mode.crtc_htotal); - b.full = dfixed_const(crtc->base.mode.crtc_hdisplay); + a.full = dfixed_const(crtc->base.mode->crtc_htotal); + b.full = dfixed_const(crtc->base.mode->crtc_hdisplay); wm->active_time.full = dfixed_mul(line_time, b); wm->active_time.full = dfixed_div(wm->active_time, a);
@@ -429,14 +429,14 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, * width = viewport width in pixels */ a.full = dfixed_const(16); - wm->priority_mark_max.full = dfixed_const(crtc->base.mode.crtc_hdisplay); + wm->priority_mark_max.full = dfixed_const(crtc->base.mode->crtc_hdisplay); wm->priority_mark_max.full = dfixed_div(wm->priority_mark_max, a); wm->priority_mark_max.full = dfixed_ceil(wm->priority_mark_max);
/* Determine estimated width */ estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; estimated_width.full = dfixed_div(estimated_width, consumption_time); - if (dfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { + if (dfixed_trunc(estimated_width) > crtc->base.mode->crtc_hdisplay) { wm->priority_mark.full = dfixed_const(10); } else { a.full = dfixed_const(16); @@ -586,9 +586,9 @@ void rs690_bandwidth_update(struct radeon_device *rdev) radeon_update_display_priority(rdev);
if (rdev->mode_info.crtcs[0]->base.enabled) - mode0 = &rdev->mode_info.crtcs[0]->base.mode; + mode0 = rdev->mode_info.crtcs[0]->base.mode; if (rdev->mode_info.crtcs[1]->base.enabled) - mode1 = &rdev->mode_info.crtcs[1]->base.mode; + mode1 = rdev->mode_info.crtcs[1]->base.mode; /* * Set display0/1 priority up in the memory controller for * modes if the user specifies HIGH for displaypriority diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c index 9031f4b..d0b7213 100644 --- a/drivers/gpu/drm/radeon/rs780_dpm.c +++ b/drivers/gpu/drm/radeon/rs780_dpm.c @@ -62,8 +62,8 @@ static void rs780_get_pm_mode_parameters(struct radeon_device *rdev) if (crtc && crtc->enabled) { radeon_crtc = to_radeon_crtc(crtc); pi->crtc_id = radeon_crtc->crtc_id; - if (crtc->mode.htotal && crtc->mode.vtotal) - pi->refresh_rate = drm_mode_vrefresh(&crtc->mode); + if (crtc->mode->htotal && crtc->mode->vtotal) + pi->refresh_rate = drm_mode_vrefresh(crtc->mode); break; } } diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index c55d653..23da03f 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -955,7 +955,7 @@ static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, struct rv515_watermark *wm, bool low) { - struct drm_display_mode *mode = &crtc->base.mode; + struct drm_display_mode *mode = crtc->base.mode; fixed20_12 a, b, c; fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; @@ -1026,7 +1026,7 @@ static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, * LineTime = total number of horizontal pixels * pclk = pixel clock period(ns) */ - a.full = dfixed_const(crtc->base.mode.crtc_htotal); + a.full = dfixed_const(crtc->base.mode->crtc_htotal); line_time.full = dfixed_mul(a, pclk);
/* Determine active time @@ -1034,8 +1034,8 @@ static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, * hactive = total number of horizontal active pixels * htotal = total number of horizontal pixels */ - a.full = dfixed_const(crtc->base.mode.crtc_htotal); - b.full = dfixed_const(crtc->base.mode.crtc_hdisplay); + a.full = dfixed_const(crtc->base.mode->crtc_htotal); + b.full = dfixed_const(crtc->base.mode->crtc_hdisplay); wm->active_time.full = dfixed_mul(line_time, b); wm->active_time.full = dfixed_div(wm->active_time, a);
@@ -1089,14 +1089,14 @@ static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, * width = viewport width in pixels */ a.full = dfixed_const(16); - wm->priority_mark_max.full = dfixed_const(crtc->base.mode.crtc_hdisplay); + wm->priority_mark_max.full = dfixed_const(crtc->base.mode->crtc_hdisplay); wm->priority_mark_max.full = dfixed_div(wm->priority_mark_max, a); wm->priority_mark_max.full = dfixed_ceil(wm->priority_mark_max);
/* Determine estimated width */ estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; estimated_width.full = dfixed_div(estimated_width, consumption_time); - if (dfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { + if (dfixed_trunc(estimated_width) > crtc->base.mode->crtc_hdisplay) { wm->priority_mark.full = wm->priority_mark_max.full; } else { a.full = dfixed_const(16); @@ -1241,9 +1241,9 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev) u32 d2mode_priority_a_cnt, d2mode_priority_b_cnt;
if (rdev->mode_info.crtcs[0]->base.enabled) - mode0 = &rdev->mode_info.crtcs[0]->base.mode; + mode0 = rdev->mode_info.crtcs[0]->base.mode; if (rdev->mode_info.crtcs[1]->base.enabled) - mode1 = &rdev->mode_info.crtcs[1]->base.mode; + mode1 = rdev->mode_info.crtcs[1]->base.mode; rs690_line_buffer_adjust(rdev, mode0, mode1);
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0_high, false); @@ -1283,9 +1283,9 @@ void rv515_bandwidth_update(struct radeon_device *rdev) radeon_update_display_priority(rdev);
if (rdev->mode_info.crtcs[0]->base.enabled) - mode0 = &rdev->mode_info.crtcs[0]->base.mode; + mode0 = rdev->mode_info.crtcs[0]->base.mode; if (rdev->mode_info.crtcs[1]->base.enabled) - mode1 = &rdev->mode_info.crtcs[1]->base.mode; + mode1 = rdev->mode_info.crtcs[1]->base.mode; /* * Set display0/1 priority up in the memory controller for * modes if the user specifies HIGH for displaypriority diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index e088e55..6c7ac2b 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2222,7 +2222,7 @@ static void dce6_program_watermarks(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, u32 lb_size, u32 num_heads) { - struct drm_display_mode *mode = &radeon_crtc->base.mode; + struct drm_display_mode *mode = radeon_crtc->base.mode; struct dce6_wm_params wm_low, wm_high; u32 dram_channels; u32 pixel_period; @@ -2395,8 +2395,8 @@ void dce6_bandwidth_update(struct radeon_device *rdev) num_heads++; } for (i = 0; i < rdev->num_crtc; i += 2) { - mode0 = &rdev->mode_info.crtcs[i]->base.mode; - mode1 = &rdev->mode_info.crtcs[i+1]->base.mode; + mode0 = rdev->mode_info.crtcs[i]->base.mode; + mode1 = rdev->mode_info.crtcs[i+1]->base.mode; lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i], mode0, mode1); dce6_program_watermarks(rdev, rdev->mode_info.crtcs[i], lb_size, num_heads); lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i+1], mode1, mode0); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 9e72133..18a1ad9 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -373,7 +373,7 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) * sync mode (with the HSYNC and VSYNC signals configured as outputs and * actively driven). */ - interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE; + interlaced = rcrtc->crtc.mode->flags & DRM_MODE_FLAG_INTERLACE; rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK, (interlaced ? DSYSR_SCM_INT_VIDEO : 0) | DSYSR_TVM_MASTER); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c index 85043c5..98c7cb9 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c @@ -41,7 +41,7 @@ static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data) static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, struct rcar_du_crtc *rcrtc) { - const struct drm_display_mode *mode = &rcrtc->crtc.mode; + const struct drm_display_mode *mode = rcrtc->crtc.mode; unsigned int freq = mode->clock; u32 lvdcr0; u32 lvdhcr; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 25f89b3..88e99aa 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -542,8 +542,8 @@ static int vop_update_plane_event(struct drm_plane *plane, .y2 = src_y + src_h, }; const struct drm_rect clip = { - .x2 = crtc->mode.hdisplay, - .y2 = crtc->mode.vdisplay, + .x2 = crtc->mode->hdisplay, + .y2 = crtc->mode->vdisplay, }; bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
@@ -576,8 +576,8 @@ static int vop_update_plane_event(struct drm_plane *plane, crtc_x = max(0, crtc_x); crtc_y = max(0, crtc_y);
- dsp_stx = crtc_x + crtc->mode.htotal - crtc->mode.hsync_start; - dsp_sty = crtc_y + crtc->mode.vtotal - crtc->mode.vsync_start; + dsp_stx = crtc_x + crtc->mode->htotal - crtc->mode->hsync_start; + dsp_sty = crtc_y + crtc->mode->vtotal - crtc->mode->vsync_start;
offset = (src.x1 >> 16) * (fb->bits_per_pixel >> 3); offset += (src.y1 >> 16) * fb->pitches[0]; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index ab3b4f4..7414766 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -74,7 +74,7 @@ static void shmob_drm_crtc_setup_geometry(struct shmob_drm_crtc *scrtc) struct drm_crtc *crtc = &scrtc->crtc; struct shmob_drm_device *sdev = crtc->dev->dev_private; const struct shmob_drm_interface_data *idata = &sdev->pdata->iface; - const struct drm_display_mode *mode = &crtc->mode; + const struct drm_display_mode *mode = crtc->mode; u32 value;
value = sdev->ldmt1r diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c index cfb75dc..b92e7e08 100644 --- a/drivers/gpu/drm/sti/sti_drm_crtc.c +++ b/drivers/gpu/drm/sti/sti_drm_crtc.c @@ -122,7 +122,7 @@ sti_drm_crtc_mode_set(struct drm_crtc *crtc, }
sti_vtg_set_config(mixer->id == STI_MIXER_MAIN ? - compo->vtg_main : compo->vtg_aux, &crtc->mode); + compo->vtg_main : compo->vtg_aux, crtc->mode);
/* a GDP is reserved to the CRTC FB */ layer = to_sti_layer(crtc->primary); diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 40f6e74..6717f07 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -995,6 +995,9 @@ static void tegra_crtc_reset(struct drm_crtc *crtc) { struct tegra_dc_state *state;
+ if (crtc->state && crtc->state->mode) + drm_mode_destroy(crtc->dev, crtc->state->mode); + kfree(crtc->state); crtc->state = NULL;
@@ -1015,11 +1018,11 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) if (!copy) return NULL;
- /* XXX: tedium */ - copy->base.mode = drm_mode_duplicate(crtc->dev, state->base.mode); - if (!copy->base.mode) { - kfree(copy); - return NULL; + if (state->base.mode) { + copy->base.mode = + drm_mode_duplicate(crtc->dev, state->base.mode); + if (!copy->base.mode) + goto err; }
copy->base.mode_changed = false; @@ -1028,6 +1031,9 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) copy->base.event = NULL;
return ©->base; +err: + kfree(copy); + return NULL; }
static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index d5fafef..2734deb 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -96,7 +96,7 @@ static void update_scanout(struct drm_crtc *crtc) (crtc->y * fb->pitches[0]) + (crtc->x * bpp/8);
tilcdc_crtc->end = tilcdc_crtc->start + - (crtc->mode.vdisplay * fb->pitches[0]); + (crtc->mode->vdisplay * fb->pitches[0]);
if (tilcdc_crtc->dpms == DRM_MODE_DPMS_ON) { /* already enabled, so just mark the frames that need @@ -549,17 +549,17 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc) tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
/* in raster mode, minimum divisor is 2: */ - ret = clk_set_rate(priv->disp_clk, crtc->mode.clock * 1000 * 2); + ret = clk_set_rate(priv->disp_clk, crtc->mode->clock * 1000 * 2); if (ret) { dev_err(dev->dev, "failed to set display clock rate to: %d\n", - crtc->mode.clock); + crtc->mode->clock); goto out; }
lcd_clk = clk_get_rate(priv->clk); - div = lcd_clk / (crtc->mode.clock * 1000); + div = lcd_clk / (crtc->mode->clock * 1000);
- DBG("lcd_clk=%u, mode clock=%d, div=%u", lcd_clk, crtc->mode.clock, div); + DBG("lcd_clk=%u, mode clock=%d, div=%u", lcd_clk, crtc->mode->clock, div); DBG("fck=%lu, dpll_disp_ck=%lu", clk_get_rate(priv->clk), clk_get_rate(priv->disp_clk));
/* Configure the LCD clock divisor. */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 8725b79..172aa3d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -536,8 +536,8 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, clip.y2 = bottom - unit->crtc.y;
/* skip any crtcs that misses the clip region */ - if (clip.x1 >= unit->crtc.mode.hdisplay || - clip.y1 >= unit->crtc.mode.vdisplay || + if (clip.x1 >= unit->crtc.mode->hdisplay || + clip.y1 >= unit->crtc.mode->vdisplay || clip.x2 <= 0 || clip.y2 <= 0) continue;
@@ -551,8 +551,8 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, cmd->body.destRect.bottom = clip.y2;
/* create a clip rect of the crtc in dest coords */ - clip.x2 = unit->crtc.mode.hdisplay - clip.x1; - clip.y2 = unit->crtc.mode.vdisplay - clip.y1; + clip.x2 = unit->crtc.mode->hdisplay - clip.x1; + clip.y2 = unit->crtc.mode->vdisplay - clip.y1; clip.x1 = 0 - clip.x1; clip.y1 = 0 - clip.y1;
@@ -900,14 +900,14 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, int move_x, move_y;
/* skip any crtcs that misses the clip region */ - if (clip_x1 >= unit->crtc.mode.hdisplay || - clip_y1 >= unit->crtc.mode.vdisplay || + if (clip_x1 >= unit->crtc.mode->hdisplay || + clip_y1 >= unit->crtc.mode->vdisplay || clip_x2 <= 0 || clip_y2 <= 0) continue;
/* clip size to crtc size */ - clip_x2 = min_t(int, clip_x2, unit->crtc.mode.hdisplay); - clip_y2 = min_t(int, clip_y2, unit->crtc.mode.vdisplay); + clip_x2 = min_t(int, clip_x2, unit->crtc.mode->hdisplay); + clip_y2 = min_t(int, clip_y2, unit->crtc.mode->vdisplay);
/* translate both src and dest to bring clip into screen */ move_x = min_t(int, clip_x1, 0); @@ -1306,8 +1306,8 @@ int vmw_kms_present(struct vmw_private *dev_priv, clip.y2 = bottom + destY - unit->crtc.y;
/* skip any crtcs that misses the clip region */ - if (clip.x1 >= unit->crtc.mode.hdisplay || - clip.y1 >= unit->crtc.mode.vdisplay || + if (clip.x1 >= unit->crtc.mode->hdisplay || + clip.y1 >= unit->crtc.mode->vdisplay || clip.x2 <= 0 || clip.y2 <= 0) continue;
@@ -1321,8 +1321,8 @@ int vmw_kms_present(struct vmw_private *dev_priv, cmd->body.destRect.bottom = clip.y2;
/* create a clip rect of the crtc in dest coords */ - clip.x2 = unit->crtc.mode.hdisplay - clip.x1; - clip.y2 = unit->crtc.mode.vdisplay - clip.y1; + clip.x2 = unit->crtc.mode->hdisplay - clip.x1; + clip.y2 = unit->crtc.mode->vdisplay - clip.y1; clip.x1 = 0 - clip.x1; clip.y1 = 0 - clip.y1;
@@ -1429,12 +1429,12 @@ int vmw_kms_readback(struct vmw_private *dev_priv, /* clip */ clip_x1 = max(clip_x1, 0); clip_y1 = max(clip_y1, 0); - clip_x2 = min(clip_x2, units[i]->crtc.mode.hdisplay); - clip_y2 = min(clip_y2, units[i]->crtc.mode.vdisplay); + clip_x2 = min(clip_x2, units[i]->crtc.mode->hdisplay); + clip_y2 = min(clip_y2, units[i]->crtc.mode->vdisplay);
/* and cull any rects that misses the crtc */ - if (clip_x1 >= units[i]->crtc.mode.hdisplay || - clip_y1 >= units[i]->crtc.mode.vdisplay || + if (clip_x1 >= units[i]->crtc.mode->hdisplay || + clip_y1 >= units[i]->crtc.mode->vdisplay || clip_x2 <= 0 || clip_y2 <= 0) continue;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 3c231b2..e71b7b2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -87,8 +87,8 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) int w = 0, h = 0; list_for_each_entry(entry, &lds->active, active) { crtc = &entry->base.crtc; - w = max(w, crtc->x + crtc->mode.hdisplay); - h = max(h, crtc->y + crtc->mode.vdisplay); + w = max(w, crtc->x + crtc->mode->hdisplay); + h = max(h, crtc->y + crtc->mode->vdisplay); i++; }
@@ -120,8 +120,8 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i); vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, crtc->x); vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, crtc->y); - vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, crtc->mode.hdisplay); - vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, crtc->mode.vdisplay); + vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, crtc->mode->hdisplay); + vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, crtc->mode->vdisplay); vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
i++; @@ -286,7 +286,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set) connector->encoder = encoder; crtc->x = set->x; crtc->y = set->y; - crtc->mode = *mode; + drm_mode_copy(crtc->mode, mode); crtc->enabled = true;
vmw_ldu_add_active(dev_priv, ldu, vfb); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 213afa5..9f13ba0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -333,8 +333,8 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
vmw_fb_off(dev_priv);
- if (mode->hdisplay != crtc->mode.hdisplay || - mode->vdisplay != crtc->mode.vdisplay) { + if (mode->hdisplay != crtc->mode->hdisplay || + mode->vdisplay != crtc->mode->vdisplay) { /* no need to check if depth is different, because backing * store depth is forced to 4 by the device. */ @@ -381,7 +381,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
connector->encoder = encoder; encoder->crtc = crtc; - crtc->mode = *mode; + drm_mode_copy(crtc->mode, mode); crtc->primary->fb = fb; crtc->x = set->x; crtc->y = set->y; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 2bce96e..7e91b8f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -446,7 +446,7 @@ struct drm_crtc { bool enabled;
/* Requested mode from modesetting. */ - struct drm_display_mode mode; + struct drm_display_mode *mode;
/* Programmed mode in hw, after adjustments for encoders, * crtc, panel scaling etc. Needed for timestamping etc.
Make it really very clear that you shouldn't be changing this.
XXX: This currently breaks for core helpers who don't have a separate non-const copy stashed, in order to change refs.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c | 4 ++-- drivers/gpu/drm/nouveau/nv50_display.c | 2 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 4 ++-- drivers/gpu/drm/qxl/qxl_display.c | 2 +- drivers/gpu/drm/radeon/cik.c | 6 +++--- drivers/gpu/drm/radeon/evergreen.c | 10 +++++----- drivers/gpu/drm/radeon/r100.c | 4 ++-- drivers/gpu/drm/radeon/radeon_asic.h | 4 ++-- drivers/gpu/drm/radeon/rs600.c | 4 ++-- drivers/gpu/drm/radeon/rs690.c | 14 +++++++------- drivers/gpu/drm/radeon/rv515.c | 14 +++++++------- drivers/gpu/drm/radeon/si.c | 10 +++++----- include/drm/drm_crtc.h | 2 +- 13 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c index eb11ec8..021631c 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c @@ -317,7 +317,7 @@ static void tv_setup_filter(struct drm_encoder *encoder) { struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); - struct drm_display_mode *mode = encoder->crtc->mode; + const struct drm_display_mode *mode = encoder->crtc->mode; uint32_t (*filters[])[4][7] = {&tv_enc->state.hfilter, &tv_enc->state.vfilter}; int i, j, k; @@ -546,7 +546,7 @@ void nv17_ctv_update_rescaler(struct drm_encoder *encoder) struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); int head = nouveau_crtc(encoder->crtc)->index; struct nv04_crtc_reg *regs = &nv04_display(dev)->mode_reg.crtc_reg[head]; - struct drm_display_mode *crtc_mode = encoder->crtc->mode; + const struct drm_display_mode *crtc_mode = encoder->crtc->mode; struct drm_display_mode *output_mode = &get_tv_norm(encoder)->ctv_enc_mode.mode; int overscan, hmargin, vmargin, hratio, vratio; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index b1da742..7a60ada 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -722,7 +722,7 @@ static int nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) { struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); - struct drm_display_mode *omode, *umode = nv_crtc->base.mode; + const struct drm_display_mode *omode, *umode = nv_crtc->base.mode; struct drm_crtc *crtc = &nv_crtc->base; struct nouveau_connector *nv_connector; int mode = DRM_MODE_SCALE_NONE; diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index b3ea6ae..0e36e86 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -282,7 +282,7 @@ static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct drm_plane *plane = omap_crtc->plane; - struct drm_display_mode *mode = crtc->mode; + const struct drm_display_mode *mode = crtc->mode;
return omap_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, mode->hdisplay, mode->vdisplay, @@ -315,7 +315,7 @@ static void page_flip_worker(struct work_struct *work) struct omap_crtc *omap_crtc = container_of(work, struct omap_crtc, page_flip_work); struct drm_crtc *crtc = &omap_crtc->base; - struct drm_display_mode *mode = crtc->mode; + const struct drm_display_mode *mode = crtc->mode; struct drm_gem_object *bo;
drm_modeset_lock(&crtc->mutex, NULL); diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 83180e4..47d1a57 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -742,7 +742,7 @@ static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev, int i; struct qxl_output *output = drm_encoder_to_qxl_output(encoder); struct qxl_head *head; - struct drm_display_mode *mode; + const struct drm_display_mode *mode;
BUG_ON(!encoder); /* TODO: ugly, do better */ diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index bb604f0..0b30839 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -8881,7 +8881,7 @@ void dce8_program_fmt(struct drm_encoder *encoder) */ static u32 dce8_line_buffer_adjust(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { u32 tmp, buffer_alloc, i; u32 pipe_offset = radeon_crtc->crtc_id * 0x20; @@ -9325,7 +9325,7 @@ static void dce8_program_watermarks(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, u32 lb_size, u32 num_heads) { - struct drm_display_mode *mode = radeon_crtc->base.mode; + const struct drm_display_mode *mode = radeon_crtc->base.mode; struct dce8_wm_params wm_low, wm_high; u32 pixel_period; u32 line_time = 0; @@ -9453,7 +9453,7 @@ static void dce8_program_watermarks(struct radeon_device *rdev, */ void dce8_bandwidth_update(struct radeon_device *rdev) { - struct drm_display_mode *mode = NULL; + const struct drm_display_mode *mode = NULL; u32 num_heads = 0, lb_size; int i;
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 439a0ee..acd175b 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1843,8 +1843,8 @@ void evergreen_hpd_fini(struct radeon_device *rdev)
static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, - struct drm_display_mode *mode, - struct drm_display_mode *other_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *other_mode) { u32 tmp, buffer_alloc, i; u32 pipe_offset = radeon_crtc->crtc_id * 0x20; @@ -2180,7 +2180,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, u32 lb_size, u32 num_heads) { - struct drm_display_mode *mode = radeon_crtc->base.mode; + const struct drm_display_mode *mode = radeon_crtc->base.mode; struct evergreen_wm_params wm_low, wm_high; u32 dram_channels; u32 pixel_period; @@ -2341,8 +2341,8 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, */ void evergreen_bandwidth_update(struct radeon_device *rdev) { - struct drm_display_mode *mode0 = NULL; - struct drm_display_mode *mode1 = NULL; + const struct drm_display_mode *mode0 = NULL; + const struct drm_display_mode *mode1 = NULL; u32 num_heads = 0, lb_size; int i;
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 31fc514..c4a5d65 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3212,8 +3212,8 @@ void r100_bandwidth_update(struct radeon_device *rdev) int critical_point = 0, critical_point2; /* uint32_t read_return_rate, time_disp1_drop_priority; */ int stop_req, max_stop_req; - struct drm_display_mode *mode1 = NULL; - struct drm_display_mode *mode2 = NULL; + const struct drm_display_mode *mode1 = NULL; + const struct drm_display_mode *mode2 = NULL; uint32_t pixel_bytes1 = 0; uint32_t pixel_bytes2 = 0;
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 72bdd3b..e3295c0 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -267,8 +267,8 @@ uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg); void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs690_bandwidth_update(struct radeon_device *rdev); void rs690_line_buffer_adjust(struct radeon_device *rdev, - struct drm_display_mode *mode1, - struct drm_display_mode *mode2); + const struct drm_display_mode *mode1, + const struct drm_display_mode *mode2); extern int rs690_mc_wait_for_idle(struct radeon_device *rdev);
/* diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 15c9085..2c3108f 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -883,8 +883,8 @@ static void rs600_mc_init(struct radeon_device *rdev)
void rs600_bandwidth_update(struct radeon_device *rdev) { - struct drm_display_mode *mode0 = NULL; - struct drm_display_mode *mode1 = NULL; + const struct drm_display_mode *mode0 = NULL; + const struct drm_display_mode *mode1 = NULL; u32 d1mode_priority_a_cnt, d2mode_priority_a_cnt; /* FIXME: implement full support */
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 0a8ce19..5bebf94 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -202,8 +202,8 @@ static void rs690_mc_init(struct radeon_device *rdev) }
void rs690_line_buffer_adjust(struct radeon_device *rdev, - struct drm_display_mode *mode1, - struct drm_display_mode *mode2) + const struct drm_display_mode *mode1, + const struct drm_display_mode *mode2) { u32 tmp;
@@ -263,7 +263,7 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, struct rs690_watermark *wm, bool low) { - struct drm_display_mode *mode = crtc->base.mode; + const struct drm_display_mode *mode = crtc->base.mode; fixed20_12 a, b, c; fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; @@ -449,8 +449,8 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, static void rs690_compute_mode_priority(struct radeon_device *rdev, struct rs690_watermark *wm0, struct rs690_watermark *wm1, - struct drm_display_mode *mode0, - struct drm_display_mode *mode1, + const struct drm_display_mode *mode0, + const struct drm_display_mode *mode1, u32 *d1mode_priority_a_cnt, u32 *d2mode_priority_a_cnt) { @@ -572,8 +572,8 @@ static void rs690_compute_mode_priority(struct radeon_device *rdev,
void rs690_bandwidth_update(struct radeon_device *rdev) { - struct drm_display_mode *mode0 = NULL; - struct drm_display_mode *mode1 = NULL; + const struct drm_display_mode *mode0 = NULL; + const struct drm_display_mode *mode1 = NULL; struct rs690_watermark wm0_high, wm0_low; struct rs690_watermark wm1_high, wm1_low; u32 tmp; diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 23da03f..86e0be8 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -955,7 +955,7 @@ static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, struct rv515_watermark *wm, bool low) { - struct drm_display_mode *mode = crtc->base.mode; + const struct drm_display_mode *mode = crtc->base.mode; fixed20_12 a, b, c; fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; @@ -1109,8 +1109,8 @@ static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, static void rv515_compute_mode_priority(struct radeon_device *rdev, struct rv515_watermark *wm0, struct rv515_watermark *wm1, - struct drm_display_mode *mode0, - struct drm_display_mode *mode1, + const struct drm_display_mode *mode0, + const struct drm_display_mode *mode1, u32 *d1mode_priority_a_cnt, u32 *d2mode_priority_a_cnt) { @@ -1232,8 +1232,8 @@ static void rv515_compute_mode_priority(struct radeon_device *rdev,
void rv515_bandwidth_avivo_update(struct radeon_device *rdev) { - struct drm_display_mode *mode0 = NULL; - struct drm_display_mode *mode1 = NULL; + const struct drm_display_mode *mode0 = NULL; + const struct drm_display_mode *mode1 = NULL; struct rv515_watermark wm0_high, wm0_low; struct rv515_watermark wm1_high, wm1_low; u32 tmp; @@ -1274,8 +1274,8 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev) void rv515_bandwidth_update(struct radeon_device *rdev) { uint32_t tmp; - struct drm_display_mode *mode0 = NULL; - struct drm_display_mode *mode1 = NULL; + const struct drm_display_mode *mode0 = NULL; + const struct drm_display_mode *mode1 = NULL;
if (!rdev->mode_info.mode_config_initialized) return; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6c7ac2b..da0480c 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1880,8 +1880,8 @@ out: /* watermark setup */ static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, - struct drm_display_mode *mode, - struct drm_display_mode *other_mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *other_mode) { u32 tmp, buffer_alloc, i; u32 pipe_offset = radeon_crtc->crtc_id * 0x20; @@ -2222,7 +2222,7 @@ static void dce6_program_watermarks(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, u32 lb_size, u32 num_heads) { - struct drm_display_mode *mode = radeon_crtc->base.mode; + const struct drm_display_mode *mode = radeon_crtc->base.mode; struct dce6_wm_params wm_low, wm_high; u32 dram_channels; u32 pixel_period; @@ -2380,8 +2380,8 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
void dce6_bandwidth_update(struct radeon_device *rdev) { - struct drm_display_mode *mode0 = NULL; - struct drm_display_mode *mode1 = NULL; + const struct drm_display_mode *mode0 = NULL; + const struct drm_display_mode *mode1 = NULL; u32 num_heads = 0, lb_size; int i;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 7e91b8f..7683527 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -446,7 +446,7 @@ struct drm_crtc { bool enabled;
/* Requested mode from modesetting. */ - struct drm_display_mode *mode; + const struct drm_display_mode *mode;
/* Programmed mode in hw, after adjustments for encoders, * crtc, panel scaling etc. Needed for timestamping etc.
Change drm_crtc_convert_umode into a helper which creates a new mode object and also performs validation.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index cf44403..c7ee172 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1747,24 +1747,30 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, }
/** - * drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode - * @out: drm_display_mode to return to the user + * drm_mode_new_from_umode - convert a modeinfo into a drm_display_mode + * @dev: DRM device to create mode for * @in: drm_mode_modeinfo to use * * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to * the caller. * * Returns: - * Zero on success, negative errno on failure. + * New drm_display_mode on success, NULL on failure */ -static int drm_crtc_convert_umode(struct drm_display_mode *out, +static struct drm_display_mode *drm_mode_new_from_umode(struct drm_device *dev, const struct drm_mode_modeinfo *in) { + struct drm_display_mode *out; + + out = drm_mode_create(dev); + if (!out) + return NULL; + if (in->clock > INT_MAX || in->vrefresh > INT_MAX) - return -ERANGE; + goto err;
if ((in->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX) - return -EINVAL; + goto err;
out->clock = in->clock; out->hdisplay = in->hdisplay; @@ -1783,7 +1789,14 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out, strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
- return 0; + out->status = drm_mode_validate_basic(out); + if (out->status != MODE_OK) + goto err; + + return out; +err: + drm_mode_destroy(dev, out); + return NULL; }
/** @@ -2785,20 +2798,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, } }
- mode = drm_mode_create(dev); + mode = drm_mode_new_from_umode(dev, &crtc_req->mode); if (!mode) { - ret = -ENOMEM; - goto out; - } - - ret = drm_crtc_convert_umode(mode, &crtc_req->mode); - if (ret) { DRM_DEBUG_KMS("Invalid mode\n"); - goto out; - } - - mode->status = drm_mode_validate_basic(mode); - if (mode->status != MODE_OK) { ret = -EINVAL; goto out; }
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc.c | 51 ------------------------------------------- drivers/gpu/drm/drm_modes.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_modes.h | 2 ++ 3 files changed, 55 insertions(+), 51 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c7ee172..8bb8dbf 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1746,58 +1746,7 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, out->name[DRM_DISPLAY_MODE_LEN-1] = 0; }
-/** - * drm_mode_new_from_umode - convert a modeinfo into a drm_display_mode - * @dev: DRM device to create mode for - * @in: drm_mode_modeinfo to use - * - * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to - * the caller. - * - * Returns: - * New drm_display_mode on success, NULL on failure - */ -static struct drm_display_mode *drm_mode_new_from_umode(struct drm_device *dev, - const struct drm_mode_modeinfo *in) -{ - struct drm_display_mode *out; - - out = drm_mode_create(dev); - if (!out) - return NULL; - - if (in->clock > INT_MAX || in->vrefresh > INT_MAX) - goto err; - - if ((in->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX) - goto err; - - out->clock = in->clock; - out->hdisplay = in->hdisplay; - out->hsync_start = in->hsync_start; - out->hsync_end = in->hsync_end; - out->htotal = in->htotal; - out->hskew = in->hskew; - out->vdisplay = in->vdisplay; - out->vsync_start = in->vsync_start; - out->vsync_end = in->vsync_end; - out->vtotal = in->vtotal; - out->vscan = in->vscan; - out->vrefresh = in->vrefresh; - out->flags = in->flags; - out->type = in->type; - strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); - out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
- out->status = drm_mode_validate_basic(out); - if (out->status != MODE_OK) - goto err; - - return out; -err: - drm_mode_destroy(dev, out); - return NULL; -}
/** * drm_mode_getresources - get graphics configuration diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 213b11e..f4922e9 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -892,6 +892,59 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, EXPORT_SYMBOL(drm_mode_duplicate);
/** + * drm_mode_new_from_umode - convert a modeinfo into a drm_display_mode + * @dev: DRM device to create mode for + * @in: drm_mode_modeinfo to use + * + * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to + * the caller. + * + * Returns: + * New drm_display_mode on success, NULL on failure + */ +struct drm_display_mode *drm_mode_new_from_umode(struct drm_device *dev, + const struct drm_mode_modeinfo *in) +{ + struct drm_display_mode *out; + + out = drm_mode_create(dev); + if (!out) + return NULL; + + if (in->clock > INT_MAX || in->vrefresh > INT_MAX) + goto err; + + if ((in->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX) + goto err; + + out->clock = in->clock; + out->hdisplay = in->hdisplay; + out->hsync_start = in->hsync_start; + out->hsync_end = in->hsync_end; + out->htotal = in->htotal; + out->hskew = in->hskew; + out->vdisplay = in->vdisplay; + out->vsync_start = in->vsync_start; + out->vsync_end = in->vsync_end; + out->vtotal = in->vtotal; + out->vscan = in->vscan; + out->vrefresh = in->vrefresh; + out->flags = in->flags; + out->type = in->type; + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); + out->name[DRM_DISPLAY_MODE_LEN-1] = 0; + + out->status = drm_mode_validate_basic(out); + if (out->status != MODE_OK) + goto err; + + return out; +err: + drm_mode_destroy(dev, out); + return NULL; +} + +/** * drm_mode_equal - test modes for equality * @mode1: first mode * @mode2: second mode diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 0616188..cd014c0 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -216,6 +216,8 @@ void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src); struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, const struct drm_display_mode *mode); +struct drm_display_mode *drm_mode_new_from_umode(struct drm_device *dev, + const struct drm_mode_modeinfo *in); bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2); bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
This will become useful for us in generic mode-handling code later.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc.c | 44 +++----------------------------------------- drivers/gpu/drm/drm_modes.c | 36 ++++++++++++++++++++++++++++++++++++ include/drm/drm_modes.h | 2 ++ 3 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 8bb8dbf..6a7f07f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1711,44 +1711,6 @@ void drm_reinit_primary_mode_group(struct drm_device *dev) EXPORT_SYMBOL(drm_reinit_primary_mode_group);
/** - * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo - * @out: drm_mode_modeinfo struct to return to the user - * @in: drm_display_mode to use - * - * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to - * the user. - */ -static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, - const struct drm_display_mode *in) -{ - WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX || - in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX || - in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX || - in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX || - in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX, - "timing values too large for mode info\n"); - - out->clock = in->clock; - out->hdisplay = in->hdisplay; - out->hsync_start = in->hsync_start; - out->hsync_end = in->hsync_end; - out->htotal = in->htotal; - out->hskew = in->hskew; - out->vdisplay = in->vdisplay; - out->vsync_start = in->vsync_start; - out->vsync_end = in->vsync_end; - out->vtotal = in->vtotal; - out->vscan = in->vscan; - out->vrefresh = in->vrefresh; - out->flags = in->flags; - out->type = in->type; - strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); - out->name[DRM_DISPLAY_MODE_LEN-1] = 0; -} - - - -/** * drm_mode_getresources - get graphics configuration * @dev: drm device for the ioctl * @data: data pointer for the ioctl @@ -1975,7 +1937,7 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->y = crtc->primary->state->src_y >> 16; if (crtc->state->enable) { WARN_ON(!crtc->state->mode); - drm_crtc_convert_to_umode(&crtc_resp->mode, crtc->state->mode); + drm_mode_convert_to_umode(&crtc_resp->mode, crtc->state->mode); crtc_resp->mode_valid = 1;
} else { @@ -1986,7 +1948,7 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->y = crtc->y; if (crtc->enabled) { WARN_ON(!crtc->mode); - drm_crtc_convert_to_umode(&crtc_resp->mode, + drm_mode_convert_to_umode(&crtc_resp->mode, crtc->mode); crtc_resp->mode_valid = 1;
@@ -2144,7 +2106,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, if (!drm_mode_expose_to_userspace(mode, file_priv)) continue;
- drm_crtc_convert_to_umode(&u_mode, mode); + drm_mode_convert_to_umode(&u_mode, mode); if (copy_to_user(mode_ptr + copied, &u_mode, sizeof(u_mode))) { ret = -EFAULT; diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index f4922e9..bb46335 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -892,6 +892,42 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, EXPORT_SYMBOL(drm_mode_duplicate);
/** + * drm_mode_convert_to_umode - convert a drm_display_mode into a modeinfo + * @out: drm_mode_modeinfo struct to return to the user + * @in: drm_display_mode to use + * + * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to + * the user. + */ +void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, + const struct drm_display_mode *in) +{ + WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX || + in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX || + in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX || + in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX || + in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX, + "timing values too large for mode info\n"); + + out->clock = in->clock; + out->hdisplay = in->hdisplay; + out->hsync_start = in->hsync_start; + out->hsync_end = in->hsync_end; + out->htotal = in->htotal; + out->hskew = in->hskew; + out->vdisplay = in->vdisplay; + out->vsync_start = in->vsync_start; + out->vsync_end = in->vsync_end; + out->vtotal = in->vtotal; + out->vscan = in->vscan; + out->vrefresh = in->vrefresh; + out->flags = in->flags; + out->type = in->type; + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); + out->name[DRM_DISPLAY_MODE_LEN-1] = 0; +} + +/** * drm_mode_new_from_umode - convert a modeinfo into a drm_display_mode * @dev: DRM device to create mode for * @in: drm_mode_modeinfo to use diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index cd014c0..ea2f0c2 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -218,6 +218,8 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, const struct drm_display_mode *mode); struct drm_display_mode *drm_mode_new_from_umode(struct drm_device *dev, const struct drm_mode_modeinfo *in); +void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, + const struct drm_display_mode *in); bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2); bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
For every mode which may be visible to userspace - either current on a CRTC as a result of setcrtc, or advertised through the connector's mode list - cache the drm_mode_modeinfo representation to send back to userspace.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_modes.c | 2 ++ include/drm/drm_modes.h | 1 + 2 files changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index bb46335..803e00a 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -969,6 +969,7 @@ struct drm_display_mode *drm_mode_new_from_umode(struct drm_device *dev, out->type = in->type; strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0; + out->umode = *in;
out->status = drm_mode_validate_basic(out); if (out->status != MODE_OK) @@ -1282,6 +1283,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector, }
if (!found_it) { + drm_mode_convert_to_umode(&pmode->umode, pmode); list_move_tail(&pmode->head, &connector->modes); } } diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index ea2f0c2..e7eb727 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -100,6 +100,7 @@ struct drm_display_mode { /* Header */ struct list_head head; struct drm_mode_object base; + struct drm_mode_modeinfo umode;
char name[DRM_DISPLAY_MODE_LEN];
Instead of generating a new usermode every time we need to copy a mode back to userspace, just use the cached one we already have.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc.c | 15 +++++---------- drivers/gpu/drm/drm_modes.c | 4 ++-- include/drm/drm_modes.h | 2 -- 3 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 6a7f07f..af9628b 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1936,8 +1936,8 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->primary->state->src_x >> 16; crtc_resp->y = crtc->primary->state->src_y >> 16; if (crtc->state->enable) { - WARN_ON(!crtc->state->mode); - drm_mode_convert_to_umode(&crtc_resp->mode, crtc->state->mode); + memcpy(&crtc_resp->mode, &crtc->mode->umode, + sizeof(crtc_resp->mode)); crtc_resp->mode_valid = 1;
} else { @@ -1947,9 +1947,8 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->x; crtc_resp->y = crtc->y; if (crtc->enabled) { - WARN_ON(!crtc->mode); - drm_mode_convert_to_umode(&crtc_resp->mode, - crtc->mode); + memcpy(&crtc_resp->mode, &crtc->mode->umode, + sizeof(crtc_resp->mode)); crtc_resp->mode_valid = 1;
} else { @@ -2046,15 +2045,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, int ret = 0; int copied = 0; int i; - struct drm_mode_modeinfo u_mode; struct drm_mode_modeinfo __user *mode_ptr; uint32_t __user *encoder_ptr;
if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL;
- memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); - DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
mutex_lock(&dev->mode_config.mutex); @@ -2106,9 +2102,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, if (!drm_mode_expose_to_userspace(mode, file_priv)) continue;
- drm_mode_convert_to_umode(&u_mode, mode); if (copy_to_user(mode_ptr + copied, - &u_mode, sizeof(u_mode))) { + &mode->umode, sizeof(mode->umode))) { ret = -EFAULT; goto out; } diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 803e00a..0883f64 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -899,8 +899,8 @@ EXPORT_SYMBOL(drm_mode_duplicate); * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to * the user. */ -void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, - const struct drm_display_mode *in) +static void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, + const struct drm_display_mode *in) { WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX || in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX || diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index e7eb727..46ed207 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -219,8 +219,6 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, const struct drm_display_mode *mode); struct drm_display_mode *drm_mode_new_from_umode(struct drm_device *dev, const struct drm_mode_modeinfo *in); -void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, - const struct drm_display_mode *in); bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2); bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
Overload the getblob ioctl to allow passing in a mode ID, which will return the userspace representation (drm_mode_modeinfo) of that mode.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc.c | 26 ++++++++++++++++++++------ include/drm/drm_crtc.h | 8 ++++++++ 2 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index af9628b..e50eda2 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4163,9 +4163,12 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_get_blob *out_resp = data; - struct drm_property_blob *blob; + const struct drm_property_blob *blob = NULL; + const struct drm_display_mode *mode = NULL; + void __user *user_ptr = (void __user *)(unsigned long)out_resp->data; + u32 length; + const void *data_src; int ret = 0; - void __user *blob_ptr;
if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; @@ -4173,18 +4176,29 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, drm_modeset_lock_all(dev); blob = drm_property_blob_find(dev, out_resp->blob_id); if (!blob) { + /* If we don't find a blob, they might be trying to get a mode + * instead. */ + mode = drm_mode_find(dev, out_resp->blob_id); + } + + if (blob) { + length = blob->length; + data_src = blob->data; + } else if (mode) { + length = sizeof(mode->umode); + data_src = &mode->umode; + } else { ret = -ENOENT; goto done; }
- if (out_resp->length == blob->length) { - blob_ptr = (void __user *)(unsigned long)out_resp->data; - if (copy_to_user(blob_ptr, blob->data, blob->length)) { + if (out_resp->length == length) { + if (copy_to_user(user_ptr, data_src, length)) { ret = -EFAULT; goto done; } } - out_resp->length = blob->length; + out_resp->length = length;
done: drm_modeset_unlock_all(dev); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 7683527..3ab70a7 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1533,6 +1533,14 @@ drm_property_blob_find(struct drm_device *dev, uint32_t id) return mo ? obj_to_blob(mo) : NULL; }
+static inline struct drm_display_mode *drm_mode_find(struct drm_device *dev, + uint32_t id) +{ + struct drm_mode_object *mo; + mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_MODE); + return mo ? obj_to_mode(mo) : NULL; +} + /* Plane list iterator for legacy (overlay only) planes. */ #define drm_for_each_legacy_plane(plane, planelist) \ list_for_each_entry(plane, planelist, head) \
Active was here, and we allowed users to set it, but not to get it as well.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_atomic.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index a6caaae..e7af6b8 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -266,9 +266,17 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc, const struct drm_crtc_state *state, struct drm_property *property, uint64_t *val) { - if (crtc->funcs->atomic_get_property) + struct drm_device *dev = crtc->dev; + struct drm_mode_config *config = &dev->mode_config; + + if (property == config->prop_active) + *val = state->active; + else if (crtc->funcs->atomic_get_property) return crtc->funcs->atomic_get_property(crtc, state, property, val); - return -EINVAL; + else + return -EINVAL; + + return 0; }
/**
Before, we would set the property, but also return -EINVAL because of a broken fallthrough.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_atomic.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index e7af6b8..5d3abe3 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -248,11 +248,14 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, struct drm_mode_config *config = &dev->mode_config;
/* FIXME: Mode prop is missing, which also controls ->enable. */ - if (property == config->prop_active) { + if (property == config->prop_active) state->active = val; - } else if (crtc->funcs->atomic_set_property) + else if (crtc->funcs->atomic_set_property) return crtc->funcs->atomic_set_property(crtc, state, property, val); - return -EINVAL; + else + return -EINVAL; + + return 0; } EXPORT_SYMBOL(drm_atomic_crtc_set_property);
On Thu, Mar 19, 2015 at 04:33:26AM +0000, Daniel Stone wrote:
Before, we would set the property, but also return -EINVAL because of a broken fallthrough.
Signed-off-by: Daniel Stone daniels@collabora.com
Oops. Both of these merged to drm-misc. -Daniel
In order to expose modes to users, we need to be able to reason about their lifetimes. As we currently treat modes as just a bucket of bits to be shovelled around, we can't do that: reference counting them enables us to sensibly deal with their lifetimes, to provide useful guarantees to userspace.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc.c | 2 +- drivers/gpu/drm/drm_crtc_helper.c | 3 ++- drivers/gpu/drm/drm_modes.c | 40 ++++++++++++++++++++++++++++++++------- drivers/gpu/drm/tegra/dc.c | 2 +- include/drm/drm_modes.h | 6 ++++++ 5 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e50eda2..90bf355 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -701,7 +701,7 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev;
- kfree(crtc->mode); + drm_mode_destroy(crtc->dev, crtc->mode); crtc->mode = NULL;
kfree(crtc->gamma_store); diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 46497dd..c23f31f 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -990,7 +990,8 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, if (crtc_funcs->atomic_check) { ret = crtc_funcs->atomic_check(crtc, crtc_state); if (ret) { - kfree(crtc_state->mode); + /* XXX: crtc_state_destroy?! */ + drm_mode_destroy(crtc->dev, crtc_state->mode); kfree(crtc_state);
return ret; diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 0883f64..e87f547 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -82,25 +82,44 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev) return NULL; }
+ kref_init(&nmode->refcount); + nmode->dev = dev; + return nmode; } EXPORT_SYMBOL(drm_mode_create);
/** - * drm_mode_destroy - remove a mode + * drm_mode_free - free a mode + * @kref: Reference count inside mode + * + * Release the unique ID of the mode referred to by @kref, then free the + * structure itself using kfree. + */ +static void drm_mode_free(struct kref *kref) +{ + struct drm_display_mode *mode = + container_of(kref, struct drm_display_mode, refcount); + + drm_mode_object_put(mode->dev, &mode->base); + + kfree(mode); +} + +/** + * drm_mode_destroy - drop reference count on mode * @dev: DRM device * @mode: mode to remove * - * Release @mode's unique ID, then free it @mode structure itself using kfree. + * Drop a reference on a drm_mode. Does not actually free the mode, unless + * the reference count drops to zero. */ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) { if (!mode) return;
- drm_mode_object_put(dev, &mode->base); - - kfree(mode); + kref_put(&mode->refcount, drm_mode_free); } EXPORT_SYMBOL(drm_mode_destroy);
@@ -851,15 +870,17 @@ EXPORT_SYMBOL(drm_mode_set_crtcinfo); * @dst: mode to overwrite * @src: mode to copy * - * Copy an existing mode into another mode, preserving the object id and - * list head of the destination mode. + * Copy an existing mode into another mode, preserving the object id, + * refcount, and list head of the destination mode. */ void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src) { + struct kref refcount = dst->refcount; int id = dst->base.id; struct list_head head = dst->head;
*dst = *src; + dst->refcount = refcount; dst->base.id = id; dst->head = head; } @@ -887,6 +908,11 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
drm_mode_copy(nmode, mode);
+ /* Often modes are duplicated from static lists created upfront without + * the device member set. Ensure that we have a real usable device to + * work from. */ + nmode->dev = dev; + return nmode; } EXPORT_SYMBOL(drm_mode_duplicate); diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 6717f07..4dd51fe 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1039,7 +1039,7 @@ err: static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { - kfree(state->mode); + drm_mode_destroy(crtc->dev, state->mode); kfree(state); }
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 46ed207..70a6c71 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -99,9 +99,15 @@ enum drm_mode_status { struct drm_display_mode { /* Header */ struct list_head head; + struct drm_device *dev; struct drm_mode_object base; struct drm_mode_modeinfo umode;
+ /* As mode objects are now exposed to userspace, rather than just + * having their contents shovelled around, we maintain a refcount + * on them in order to reason about their lifetimes. */ + struct kref refcount; + char name[DRM_DISPLAY_MODE_LEN];
enum drm_mode_status status;
Does what it says on the box.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc.c | 13 +++++++++++++ drivers/gpu/drm/drm_modes.c | 8 ++++++++ include/drm/drm_modes.h | 1 + 3 files changed, 22 insertions(+)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 90bf355..3ef0332 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4382,6 +4382,17 @@ bool drm_property_change_valid_get(struct drm_property *property, } else { return false; } + } else if (property->values[0] == DRM_MODE_OBJECT_MODE) { + struct drm_display_mode *mode; + mode = drm_mode_find(property->dev, value); + if (mode) { + drm_mode_reference(mode); + *ref = &mode->base; + return true; + } else { + return false; + } + } else { return _object_find(property->dev, value, property->values[0]) != NULL; } @@ -4402,6 +4413,8 @@ void drm_property_change_valid_put(struct drm_property *property, if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { if (property->values[0] == DRM_MODE_OBJECT_FB) drm_framebuffer_unreference(obj_to_fb(ref)); + else if (property->values[0] == DRM_MODE_OBJECT_MODE) + drm_mode_destroy(property->dev, obj_to_mode(ref)); } }
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index e87f547..86bb5c1 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -123,6 +123,13 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_mode_destroy);
+struct drm_display_mode *drm_mode_reference(struct drm_display_mode *mode) +{ + kref_get(&mode->refcount); + return mode; +} +EXPORT_SYMBOL(drm_mode_reference); + /** * drm_mode_probed_add - add a mode to a connector's probed_mode list * @connector: connector the new mode @@ -881,6 +888,7 @@ void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *
*dst = *src; dst->refcount = refcount; + dst->base.type = DRM_MODE_OBJECT_MODE; dst->base.id = id; dst->head = head; } diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 70a6c71..a8aaf4b 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -188,6 +188,7 @@ struct drm_connector; struct drm_cmdline_mode;
struct drm_display_mode *drm_mode_create(struct drm_device *dev); +struct drm_display_mode *drm_mode_reference(struct drm_display_mode *mode); void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
Take a reference to existing modes, rather than duplicating them to create new ones.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_fb_helper.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 71e2420..130b35d 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1317,7 +1317,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f if (mode->flags & DRM_MODE_FLAG_INTERLACE) continue; } - return mode; + return drm_mode_reference(mode); }
if (prefer_non_interlace) { @@ -1329,7 +1329,7 @@ create_mode: mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, cmdline_mode); list_add(&mode->head, &fb_helper_conn->connector->modes); - return mode; + return drm_mode_reference(mode); } EXPORT_SYMBOL(drm_pick_cmdline_mode);
@@ -1429,7 +1429,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, fb_helper_conn = fb_helper->connector_info[i]; list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { if (drm_mode_equal(mode, dmt_mode)) - modes[i] = mode; + modes[i] = drm_mode_reference(mode); } if (!modes[i]) can_clone = false; @@ -1527,16 +1527,14 @@ retry: fb_helper_conn->connector->base.id, fb_helper_conn->connector->tile_group ? fb_helper_conn->connector->tile_group->id : 0); modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height); if (modes[i]) - modes[i] = drm_mode_duplicate(fb_helper->dev, - modes[i]); + drm_mode_reference(modes[i]); } /* No preferred modes, pick one off the list */ if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) { list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head) break; if (modes[i]) - modes[i] = drm_mode_duplicate(fb_helper->dev, - modes[i]); + drm_mode_reference(modes[i]); } DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : "none"); @@ -1704,8 +1702,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) fb_crtc->y = offset->y; if (fb_crtc->mode) drm_mode_destroy(dev, fb_crtc->mode); - fb_crtc->mode = drm_mode_duplicate(dev, - fb_crtc->desired_mode); + fb_crtc->mode = + drm_mode_reference(fb_crtc->desired_mode); modeset->mode = fb_crtc->mode; modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector; modeset->fb = fb_helper->fb;
Take a reference to existing modes, rather than duplicating them to create new ones.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc_helper.c | 43 ++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index c23f31f..08f0367 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -301,7 +301,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, * setting. */ if (mode) - crtc->mode = drm_mode_duplicate(crtc->dev, mode); + crtc->mode = drm_mode_reference(mode); else crtc->mode = NULL; crtc->x = x; @@ -421,7 +421,8 @@ done: crtc->x = saved_x; crtc->y = saved_y; } else { - drm_mode_destroy(dev, saved_mode); + if (saved_mode) + drm_mode_destroy(dev, saved_mode); }
return ret; @@ -547,7 +548,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) }
save_set.crtc = set->crtc; - save_set.mode = set->crtc->mode; + if (set->crtc->mode) + save_set.mode = drm_mode_reference(set->crtc->mode); + else + save_set.mode = NULL; save_set.x = set->crtc->x; save_set.y = set->crtc->y; save_set.fb = set->crtc->primary->fb; @@ -718,6 +722,8 @@ fail: save_set.y, save_set.fb)) DRM_ERROR("failed to restore config after modeset failure\n");
+ if (save_set.mode) + drm_mode_destroy(dev, save_set.mode); kfree(save_connectors); kfree(save_encoders); return ret; @@ -954,29 +960,9 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, else if (crtc->state) { crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), GFP_KERNEL); - /* XXX: this is unpleasant: we should mandate dup instead */ - if (crtc_state) { - crtc_state->mode = - drm_mode_duplicate(crtc->dev, - crtc->state->mode); - if (!crtc_state->mode) { - kfree(crtc_state); - crtc_state = NULL; - } - } } - else { + else crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); - if (crtc_state) { - crtc_state->mode = kzalloc(sizeof(*crtc_state->mode), - GFP_KERNEL); - /* XXX: as above, but mandate a new_state */ - if (!crtc_state->mode) { - kfree(crtc_state); - crtc_state = NULL; - } - } - } if (!crtc_state) return -ENOMEM; crtc_state->crtc = crtc; @@ -984,7 +970,12 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, crtc_state->enable = true; crtc_state->planes_changed = true; crtc_state->mode_changed = true; - drm_mode_copy(crtc_state->mode, mode); + if (crtc_state->mode) + drm_mode_destroy(crtc->dev, crtc_state->mode); + if (mode) + crtc_state->mode = drm_mode_reference(mode); + else + crtc_state->mode = NULL; drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode);
if (crtc_funcs->atomic_check) { @@ -1006,7 +997,7 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, if (crtc->funcs->atomic_destroy_state) crtc->funcs->atomic_destroy_state(crtc, crtc_state); else { - kfree(crtc_state->mode); + drm_mode_destroy(crtc->dev, crtc_state->mode); kfree(crtc_state); } }
Take a reference to existing modes, rather than duplicating them to create new ones.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_atomic_helper.c | 49 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bc7b629..f5ee83c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -260,7 +260,12 @@ mode_fixup(struct drm_atomic_state *state) if (!crtc_state || !crtc_state->mode_changed) continue;
- drm_mode_copy(&crtc_state->adjusted_mode, crtc_state->mode); + if (crtc_state->mode) + drm_mode_copy(&crtc_state->adjusted_mode, + crtc_state->mode); + else + memset(&crtc_state->adjusted_mode, 0, + sizeof(crtc_state->adjusted_mode)); }
for (i = 0; i < state->num_connector; i++) { @@ -699,14 +704,12 @@ set_routing_links(struct drm_device *dev, struct drm_atomic_state *old_state) if (!crtc) continue;
- if (crtc->state->mode) { - if (crtc->mode) - drm_mode_destroy(dev, crtc->mode); - crtc->mode = drm_mode_duplicate(dev, crtc->state->mode); - } else if (crtc->mode) { + if (crtc->mode) drm_mode_destroy(dev, crtc->mode); - crtc->mode = NULL; - } + crtc->mode = crtc->state->mode; + if (crtc->mode) + drm_mode_reference(crtc->mode); + crtc->enabled = crtc->state->enable; crtc->x = crtc->primary->state->src_x >> 16; crtc->y = crtc->primary->state->src_y >> 16; @@ -731,8 +734,9 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) funcs = crtc->helper_private;
if (crtc->state->enable && funcs->mode_set_nofb) { - DRM_DEBUG_ATOMIC("modeset on [CRTC:%d]\n", - crtc->base.id); + DRM_DEBUG_ATOMIC("modeset on [CRTC:%d] [MODE:%d]\n", + crtc->base.id, + crtc->state->mode ? crtc->state->mode->base.id : 0);
funcs->mode_set_nofb(crtc); } @@ -1652,7 +1656,9 @@ retry: crtc_state->active = true; if (crtc_state->mode) drm_mode_destroy(crtc->dev, crtc_state->mode); - crtc_state->mode = drm_mode_duplicate(crtc->dev, set->mode); + crtc_state->mode = set->mode; + if (crtc_state->mode) + drm_mode_reference(crtc_state->mode);
ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); if (ret != 0) @@ -1660,12 +1666,12 @@ retry: drm_atomic_set_fb_for_plane(primary_state, set->fb); primary_state->crtc_x = 0; primary_state->crtc_y = 0; - primary_state->crtc_h = set->mode->vdisplay; - primary_state->crtc_w = set->mode->hdisplay; + primary_state->crtc_h = set->mode ? set->mode->vdisplay : 0; + primary_state->crtc_w = set->mode ? set->mode->hdisplay : 0; primary_state->src_x = set->x << 16; primary_state->src_y = set->y << 16; - primary_state->src_h = set->mode->vdisplay << 16; - primary_state->src_w = set->mode->hdisplay << 16; + primary_state->src_h = set->mode ? set->mode->vdisplay << 16 : 0; + primary_state->src_w = set->mode ? set->mode->hdisplay << 16 : 0;
commit: ret = update_output_state(state, set); @@ -2105,15 +2111,8 @@ drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) state->planes_changed = false; state->event = NULL;
- if (crtc->state->mode) { - state->mode = - drm_mode_duplicate(crtc->dev, - crtc->state->mode); - if (!state->mode) { - kfree(state); - state = NULL; - } - } + if (state->mode) + drm_mode_reference(state->mode);
return state; } @@ -2130,7 +2129,7 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { - kfree(state->mode); + drm_mode_destroy(crtc->dev, state->mode); kfree(state); } EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
Take a reference to existing modes, rather than duplicating them to create new ones.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/i915/intel_atomic.c | 8 ++------ drivers/gpu/drm/tegra/dc.c | 11 ++--------- 2 files changed, 4 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 80cb562..8b80a54 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -227,12 +227,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
crtc_state->base.crtc = crtc;
- if (intel_crtc->config && intel_crtc->config->mode) { - crtc_state->mode = - drm_mode_duplicate(crtc->dev, intel_crtc->config->mode); - if (!crtc_state->mode) - goto err; - } + if (crtc_state->base.mode) + drm_mode_reference(crtc_state->base.mode);
return &crtc_state->base; err: diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 4dd51fe..888fcbd 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1018,12 +1018,8 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) if (!copy) return NULL;
- if (state->base.mode) { - copy->base.mode = - drm_mode_duplicate(crtc->dev, state->base.mode); - if (!copy->base.mode) - goto err; - } + if (copy->base.mode) + drm_mode_reference(copy->base.mode);
copy->base.mode_changed = false; copy->base.active_changed = false; @@ -1031,9 +1027,6 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) copy->base.event = NULL;
return ©->base; -err: - kfree(copy); - return NULL; }
static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
Atomic modesetting: now with modesetting support.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_atomic.c | 35 ++++++++++++++++++++++++++++++++++- drivers/gpu/drm/drm_crtc.c | 7 +++++++ include/drm/drm_crtc.h | 1 + 3 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 5d3abe3..9085e04 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -179,6 +179,34 @@ void drm_atomic_state_free(struct drm_atomic_state *state) EXPORT_SYMBOL(drm_atomic_state_free);
/** + * drm_atomic_set_mode_for_crtc - set mode for CRTC + * @crtc_state: atomic state object for the CRTC + * @mode: mode to use for the plane + * + * Changing the display mode for a CRTC requires us to grab a reference + * to the new mode and drop the reference to the old mode, if there is one. + * This function takes care of all these details besides updating the pointer + * in the state object itself. + */ +static void +drm_atomic_set_mode_for_crtc(struct drm_crtc_state *crtc_state, + struct drm_display_mode *mode) +{ + if (mode) + drm_mode_reference(mode); + if (crtc_state->mode) + drm_mode_destroy(crtc_state->crtc->dev, crtc_state->mode); + crtc_state->mode = mode; + + if (mode) + DRM_DEBUG_ATOMIC("Set [MODE:%d] for CRTC state %p\n", + mode->base.id, crtc_state); + else + DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n", + crtc_state); +} + +/** * drm_atomic_get_crtc_state - get crtc state * @state: global atomic state object * @crtc: crtc to get state object for @@ -247,9 +275,12 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_mode_config *config = &dev->mode_config;
- /* FIXME: Mode prop is missing, which also controls ->enable. */ if (property == config->prop_active) state->active = val; + else if (property == config->prop_mode_id) { + struct drm_display_mode *mode = drm_mode_find(dev, val); + drm_atomic_set_mode_for_crtc(state, mode); + } else if (crtc->funcs->atomic_set_property) return crtc->funcs->atomic_set_property(crtc, state, property, val); else @@ -274,6 +305,8 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc,
if (property == config->prop_active) *val = state->active; + else if (property == config->prop_mode_id) + *val = (state->mode) ? state->mode->base.id : 0; else if (crtc->funcs->atomic_get_property) return crtc->funcs->atomic_get_property(crtc, state, property, val); else diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3ef0332..c1b3801 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -683,6 +683,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { drm_object_attach_property(&crtc->base, config->prop_active, 0); + drm_object_attach_property(&crtc->base, config->prop_mode_id, 0); }
return 0; @@ -1429,6 +1430,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.prop_active = prop;
+ prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, + "MODE_ID", DRM_MODE_OBJECT_MODE); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_mode_id = prop; + return 0; }
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 3ab70a7..5c8cb25 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1122,6 +1122,7 @@ struct drm_mode_config { struct drm_property *prop_fb_id; struct drm_property *prop_crtc_id; struct drm_property *prop_active; + struct drm_property *prop_mode_id;
/* DVI-I properties */ struct drm_property *dvi_i_subconnector_property;
All blob properties currently go on the device-global property list, which is reaped at device exit. Make the addition to the list optional, to allow for user properties whose lifetime will be tied to their drm_file.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c1b3801..21e2052 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4118,7 +4118,7 @@ done:
static struct drm_property_blob * drm_property_create_blob(struct drm_device *dev, size_t length, - const void *data) + const void *data, bool global) { struct drm_property_blob *blob; int ret; @@ -4140,7 +4140,10 @@ drm_property_create_blob(struct drm_device *dev, size_t length,
memcpy(blob->data, data, length);
- list_add_tail(&blob->head, &dev->mode_config.property_blob_list); + if (global) + list_add_tail(&blob->head, + &dev->mode_config.property_blob_list); + return blob; }
@@ -4233,7 +4236,7 @@ int drm_mode_connector_set_path_property(struct drm_connector *connector, int ret;
connector->path_blob_ptr = drm_property_create_blob(connector->dev, - size, path); + size, path, true); if (!connector->path_blob_ptr) return -EINVAL;
@@ -4279,7 +4282,7 @@ int drm_mode_connector_set_tile_property(struct drm_connector *connector) size = strlen(tile) + 1;
connector->tile_blob_ptr = drm_property_create_blob(connector->dev, - size, tile); + size, tile, true); if (!connector->tile_blob_ptr) return -EINVAL;
@@ -4324,7 +4327,7 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
size = EDID_LENGTH * (1 + edid->extensions); connector->edid_blob_ptr = drm_property_create_blob(connector->dev, - size, edid); + size, edid, true); if (!connector->edid_blob_ptr) return -EINVAL;
Add an ioctl which allows users to create objects from arbitrary data. Currently this only supports modes, creating a drm_display_mode from the userspace drm_mode_modeinfo.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/drm_crtc.c | 166 ++++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_fops.c | 7 +- drivers/gpu/drm/drm_ioctl.c | 2 + include/drm/drmP.h | 6 ++ include/drm/drm_crtc.h | 6 ++ include/uapi/drm/drm.h | 2 + include/uapi/drm/drm_mode.h | 22 ++++++ 7 files changed, 209 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 21e2052..e258e7c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4155,6 +4155,19 @@ static void drm_property_destroy_blob(struct drm_device *dev, kfree(blob); }
+void drm_property_destroy_user_blobs(struct drm_device *dev, + struct drm_file *file_priv) +{ + struct drm_property_blob *blob, *bt; + + mutex_lock(&file_priv->properties_lock); + list_for_each_entry_safe(blob, bt, &file_priv->properties, head) { + drm_property_destroy_blob(dev, blob); + } + mutex_unlock(&file_priv->properties_lock); + mutex_destroy(&file_priv->properties_lock); +} + /** * drm_mode_getblob_ioctl - get the contents of a blob property value * @dev: DRM device @@ -4216,6 +4229,159 @@ done: }
/** + * drm_mode_createblob_ioctl - create a new blob property + * @dev: DRM device + * @data: ioctl data + * @file_priv: DRM file info + * + * This function creates a new blob property with user-defined values. In order + * to give us sensible validation and checking when creating, rather than at + * every potential use, we also require a type to be provided upfront. + * + * Called by the user via ioctl. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_mode_createblob_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_create_blob *out_resp = data; + uint32_t length = 0; + void *blob_data; + int ret = 0; + void __user *blob_ptr; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + switch (out_resp->type) { + case DRM_MODE_BLOB_TYPE_MODE: { + length = sizeof(struct drm_mode_modeinfo); + if (out_resp->length != length) { + ret = -E2BIG; + goto out_unlocked; + } + break; + } + default: + ret = -EINVAL; + goto out_unlocked; + } + + blob_data = kzalloc(length, GFP_USER); + if (!blob_data) { + ret = -ENOMEM; + goto out_unlocked; + } + + blob_ptr = (void __user *)(unsigned long)out_resp->data; + if (copy_from_user(blob_data, blob_ptr, out_resp->length)) { + ret = -EFAULT; + goto out_data; + } + + drm_modeset_lock_all(dev); + + switch (out_resp->type) { + case DRM_MODE_BLOB_TYPE_MODE: { + struct drm_display_mode *mode; + + mode = drm_mode_new_from_umode(dev, blob_data); + if (!mode) { + ret = -EINVAL; + goto out_locked; + } + + out_resp->blob_id = mode->base.id; + + /* XXX: When we were using a property as the base here, we + * added the mode to the properties list to ensure it + * got cleaned up when the drm_file disappeared. But + * by using drm_display_mode as the base object, we + * can't add it to the list anymore. Adding a specific + * mode list feels pretty unclean though ... + mutex_lock(&file_priv->properties_lock); + list_add_tail(&blob->head, &file_priv->properties); + mutex_unlock(&file_priv->properties_lock); */ + + break; + } + } + +out_locked: + drm_modeset_unlock_all(dev); +out_data: + kfree(blob_data); +out_unlocked: + return ret; +} + +/** + * drm_mode_destroyblob_ioctl - destroy a user blob property + * @dev: DRM device + * @data: ioctl data + * @file_priv: DRM file info + * + * Destroy an existing user-defined blob property. + * + * Called by the user via ioctl. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_mode_destroyblob_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_destroy_blob *out_resp = data; + struct drm_property_blob *blob = NULL, *bt; + struct drm_display_mode *mode = NULL; + bool found = false; + int ret = 0; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + drm_modeset_lock_all(dev); + blob = drm_property_blob_find(dev, out_resp->blob_id); + if (!blob) + mode = drm_mode_find(dev, out_resp->blob_id); + + if (!blob && !mode) { + ret = -ENOENT; + goto out_locked; + } + + /* Ensure the property was actually created by this user. */ + if (blob) { + mutex_lock(&file_priv->properties_lock); + + list_for_each_entry(bt, &file_priv->properties, head) { + if (bt == blob) { + found = true; + break; + } + } + + if (found) { + drm_property_destroy_blob(dev, blob); + ret = 0; + } else { + ret = -EPERM; + } + + mutex_unlock(&file_priv->properties_lock); + } else if (mode) { + /* XXX: This is missing all the nice checking from above ... */ + drm_mode_destroy(dev, mode); + } + +out_locked: + drm_modeset_unlock_all(dev); + return ret; +} + +/** * drm_mode_connector_set_path_property - set tile property on connector * @connector: connector to set property on. * @path: path to use for property. diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 076dd60..6e389ea 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -167,6 +167,8 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) INIT_LIST_HEAD(&priv->lhead); INIT_LIST_HEAD(&priv->fbs); mutex_init(&priv->fbs_lock); + INIT_LIST_HEAD(&priv->properties); + mutex_init(&priv->properties_lock); INIT_LIST_HEAD(&priv->event_list); init_waitqueue_head(&priv->event_wait); priv->event_space = 4096; /* set aside 4k for event buffer */ @@ -408,8 +410,10 @@ int drm_release(struct inode *inode, struct file *filp)
drm_events_release(file_priv);
- if (drm_core_check_feature(dev, DRIVER_MODESET)) + if (drm_core_check_feature(dev, DRIVER_MODESET)) { drm_fb_release(file_priv); + drm_property_destroy_user_blobs(dev, file_priv); + }
if (drm_core_check_feature(dev, DRIVER_GEM)) drm_gem_release(dev, file_priv); @@ -452,7 +456,6 @@ int drm_release(struct inode *inode, struct file *filp) if (dev->driver->postclose) dev->driver->postclose(dev, file_priv);
- if (drm_core_check_feature(dev, DRIVER_PRIME)) drm_prime_destroy_file_private(&file_priv->prime);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index a6d773a..d180377 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -636,6 +636,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB, drm_mode_createblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB, drm_mode_destroyblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), };
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 63c0b01..62b4d8d 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -322,6 +322,12 @@ struct drm_file { struct list_head fbs; struct mutex fbs_lock;
+ /** User-created blob properties; this retains a reference on the + * property. */ + struct list_head properties; + /** Lock for synchronisation of access to properties. */ + struct mutex properties_lock; + wait_queue_head_t event_wait; struct list_head event_list; int event_space; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 5c8cb25..d4d914c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1284,6 +1284,8 @@ extern const char *drm_get_dvi_i_select_name(int val); extern const char *drm_get_tv_subconnector_name(int val); extern const char *drm_get_tv_select_name(int val); extern void drm_fb_release(struct drm_file *file_priv); +extern void drm_property_destroy_user_blobs(struct drm_device *dev, + struct drm_file *file_priv); extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); extern void drm_mode_group_destroy(struct drm_mode_group *group); extern void drm_reinit_primary_mode_group(struct drm_device *dev); @@ -1422,6 +1424,10 @@ extern int drm_mode_getproperty_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_getblob_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_mode_createblob_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_destroyblob_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); extern int drm_mode_connector_property_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_getencoder(struct drm_device *dev, diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index ff6ef62..3801584 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -786,6 +786,8 @@ struct drm_prime_handle { #define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) #define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) #define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) +#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob) +#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob)
/** * Device specific ioctls should only be in their respective headers diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index dbeba94..73ac925 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -558,4 +558,26 @@ struct drm_mode_atomic { __u64 user_data; };
+#define DRM_MODE_BLOB_TYPE_MODE 1 /**< drm_mode_modeinfo */ + +/** + * Create a new 'blob' data property, copying length bytes from data pointer, + * and returning new blob ID. + */ +struct drm_mode_create_blob { + __u32 type; + __u32 length; + /** Pointer to data to create blob. */ + __u64 data; + /** Return: new property ID. */ + __u32 blob_id; +}; + +/** + * Destroy a user-created blob property. + */ +struct drm_mode_destroy_blob { + __u32 blob_id; +}; + #endif
CRTCs might have a NULL mode if they're being disabled.
Signed-off-by: Daniel Stone daniels@collabora.com --- drivers/gpu/drm/tegra/sor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index d0eaa48..0f8aa2c 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -1282,7 +1282,8 @@ tegra_sor_encoder_atomic_check(struct drm_encoder *encoder, { struct tegra_output *output = encoder_to_output(encoder); struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); - unsigned long pclk = crtc_state->mode->clock * 1000; + unsigned long pclk = + crtc_state->mode ? crtc_state->mode->clock * 1000 : 0; struct tegra_sor *sor = to_sor(output); int err;
On Thu, Mar 19, 2015 at 04:32:36AM +0000, Daniel Stone wrote:
Well, that escalated quickly.
I've been looking at adding modesetting support to the atomic ioctl, and this is what I've ended up with so far. It's definitely not perfect, but given how out of hand it's got at the moment, I wanted to send this out as an RFC before I spent too long polishing it up.
This series ends up touching pretty much all the drivers, by virtue of turning crtc->mode (in particular) into both a const and a pointer.
Ok this is quite a bit a different beast than what I expected. I think it's way too intrusive for drivers to land quickly, and there's a big depency chain linking everything. I think we need something much simpler.
The reasoning behind this is that currently, we just treat modes as unboxed data to shovel around. With atomic modesetting, and user-supplied modes, we want to do better here. Whilst sketching out userspace/compositor requirements, I came up with the following invariants, which necessitated turning modes into a refcounted, immutable, type:
- modes can come from one of three sources: connector list, current mode, userspace-created
- as far as possible, modes should be relateable to their source, e.g. if Plymouth pulls a particular mode from the encoder, and you pick up on that mode as part of current configuration during handover, you should be able to work backwards to where Plymouth sourced it, i.e. the encoder list
With legacy setcrtc we already lose this information and thus far no one seems to have cared. And I don't see the use-case since simply comparing it to sources works well enough, in case you want to know where a mode is from.
- userspace should be able to tell the current status by looking at the IDs returned by property queries, rather than having to pull the entire mode out: if we make them do that, they won't bother minimising the deltas and will just dump the full state in every time, and that makes debugging the entire thing that much harder
That doesn't work since idr eagerly reuses ids. Just by looking at the id you can't tell whether it's the same object or a new one accidentally reusing the same id slot. You always have to re-read the blob property too to reconstruct state.
This blew up with edid blob properties where SNA had one clever trick too many and thought that matching edid blob prop id means the edid is unchanged. But since we remove the old blob before we add the new one you're pretty much guranteed to reuse the same slot.
- setting a mode current should hold a reference for as long as it's current, e.g. if you create a magic user-supplied mode, set that on the CRTC and then terminate the connection, the mode should still live on for handover purposes
I think we need much less: If your driver supports atomic (and hence userspace might be asking for the mode blob prop id) then that blob should survive as long as the mode is in use.
- persistence of system-supplied (from-connector or from-CRTC) modes is not important beyond their natural lifetime: if you pick a mode up from a connector's probed list and then that connector disappears, setting that mode is unlikely to be what you want, so failure because the mode no longer exists is entirely acceptable
Somewhat unordered, but here's what I think we need: - Subtyping blob properties is not needed, at least I can't think of a use-case. It will result though in lots of duplicated code for duplicated ref/unref functions and atomic prop handling.
- Since we already have a getblob ioctl I think we should just extend the existing drm_property_blob:
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index adc9ea5acf02..9845b634d2d3 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -217,6 +217,7 @@ struct drm_framebuffer {
struct drm_property_blob { struct drm_mode_object base; + struct kref refcount; struct list_head head; size_t length; unsigned char data[];
Plus ofc changing drm_property_create/destroy_blob into ref/unref functions. And doing the same weak reference trick for idrs as we're using for framebuffers now.
For mode properties the data contained would be struct drm_mode_modeinfo (i.e. the ABI struct we already use for the setcrtc/getconnector ioctls, not the internal one).
- Imo requiring all the legacy users to be converted to pointers isn't needed. crtc->mode/hwmode are deprecated for atomic drivers. Not that I don't think doing this isn't useful, I just think it's not needed to have a minimal atomic mode blob support.
Aside: We don't even need to convert mode structs to pointers if we embedded the kref into the mode - I've done similar horrible conversion tricks with framebuffers, where drivers tend to embed the static fbdev framebuffer into the fbdev emulation struct. You just need raw free/destroy entry points which for safety check that the kref count is exactly 1.
- For the actual atomic integration I think we need a blob prop pointer separate from the mode struct. The blob prop contains the userspace ABI struct, and the embedded one is the one used internally. Doing any kind of conversion just leads to lots of churn, which is especially bad with around 4 still incomplete/unmerged atomic conversion. So just
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index adc9ea5acf02..d6a7a5247b64 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -296,6 +296,7 @@ struct drm_crtc_state { struct drm_display_mode adjusted_mode;
struct drm_display_mode mode; + struct drm_property_blob * mode_blob;
struct drm_pending_vblank_event *event;
Getting the refcounting right for the atomic ioctl should be simple. For the legacy ->set_config entrypoint we need to fix things up in the helper when we update the mode, by manually releasing the old mode blob and creating a new one (owned by the kernel to avoid leaks because old userspace won't clean them up - we've had this bug with compat cursor fbs just recently).
Cheers, Daniel
Hi,
On 23 March 2015 at 08:20, Daniel Vetter daniel@ffwll.ch wrote:
On Thu, Mar 19, 2015 at 04:32:36AM +0000, Daniel Stone wrote:
This series ends up touching pretty much all the drivers, by virtue of turning crtc->mode (in particular) into both a const and a pointer.
Ok this is quite a bit a different beast than what I expected. I think it's way too intrusive for drivers to land quickly, and there's a big depency chain linking everything. I think we need something much simpler.
Yeah, I'm uneasy with how invasive it's got: hence the proposal to drop crtc->mode back into being inlined. I don't think we lose anything from doing that (as crtc->state->mode still changes), and that makes the diff much less scary. The constness changes no longer become required, but I think are still pretty useful from the point of view of setting (and enforcing) our existing expectations. I'd still look to push those anyway, but at a much more sedate pace.
- as far as possible, modes should be relateable to their source, e.g. if Plymouth pulls a particular mode from the encoder, and you pick up on that mode as part of current configuration during handover, you should be able to work backwards to where Plymouth sourced it, i.e. the encoder list
With legacy setcrtc we already lose this information and thus far no one seems to have cared. And I don't see the use-case since simply comparing it to sources works well enough, in case you want to know where a mode is from.
On the other hand, I wouldn't suggest SetCrtc to really be a model to follow. I really don't mind SetCrtc breaking all these expectations above, mind.
- userspace should be able to tell the current status by looking at the IDs returned by property queries, rather than having to pull the entire mode out: if we make them do that, they won't bother minimising the deltas and will just dump the full state in every time, and that makes debugging the entire thing that much harder
That doesn't work since idr eagerly reuses ids. Just by looking at the id you can't tell whether it's the same object or a new one accidentally reusing the same id slot. You always have to re-read the blob property too to reconstruct state.
Do we make any guarantee on connector->modes lifetimes? If it can't change without a hotplug event, then we know the ID is valid until the connector goes dark, at which point we have to drop any local cache relating to it.
Saying that userspace must read every single mode property back every single time is pretty horrible from the point of view of requiring more userspace->kernel->userspace->kernel->[...] trips to do discovery every time, just because we decided not to work out a sensible lifetime strategy to expose to userspace.
This blew up with edid blob properties where SNA had one clever trick too many and thought that matching edid blob prop id means the edid is unchanged. But since we remove the old blob before we add the new one you're pretty much guranteed to reuse the same slot.
Sure, if you're not paying attention to the defined lifetime, then don't do any caching. But this is about _defining_ such a usable lifetime that userspace can.
- setting a mode current should hold a reference for as long as it's current, e.g. if you create a magic user-supplied mode, set that on the CRTC and then terminate the connection, the mode should still live on for handover purposes
I think we need much less: If your driver supports atomic (and hence userspace might be asking for the mode blob prop id) then that blob should survive as long as the mode is in use.
Which not only requires the most invasive of the changes anyway (modulo those to crtc->mode, which can regardless be dropped), but also a bunch of 'every time the state changes, go consult some auxiliary property and potentially expire its lifetime'.
- persistence of system-supplied (from-connector or from-CRTC) modes is not important beyond their natural lifetime: if you pick a mode up from a connector's probed list and then that connector disappears, setting that mode is unlikely to be what you want, so failure because the mode no longer exists is entirely acceptable
Somewhat unordered, but here's what I think we need:
- Subtyping blob properties is not needed, at least I can't think of a use-case. It will result though in lots of duplicated code for duplicated ref/unref functions and atomic prop handling.
When you say 'subtyping', do you mean what I've done with getblob?
- Since we already have a getblob ioctl I think we should just extend the existing drm_property_blob:
That was actually my initial implementation, but didn't like the resulting reference tie-up between drm_display_mode and drm_property_blob (aka drm_mode_modeinfo). I couldn't figure out a really clean way to do it that didn't provably fall down at some point, so abandoned it and went for referencing drm_display_mode instead.
Plus ofc changing drm_property_create/destroy_blob into ref/unref functions. And doing the same weak reference trick for idrs as we're using for framebuffers now.
For mode properties the data contained would be struct drm_mode_modeinfo (i.e. the ABI struct we already use for the setcrtc/getconnector ioctls, not the internal one).
Right, this is what's there: 25/37 is explicitly always returning modeinfo, and the creation does as well. I don't see any benefit to exposing the internal struct.
- Imo requiring all the legacy users to be converted to pointers isn't needed. crtc->mode/hwmode are deprecated for atomic drivers. Not that I don't think doing this isn't useful, I just think it's not needed to have a minimal atomic mode blob support.
Yeah, I agree. I'm moving all this out to be tracked in a separate series. A lot of it was to convince myself that in the process of the mode work I was doing, I wouldn't be breaking drivers.
Aside: We don't even need to convert mode structs to pointers if we embedded the kref into the mode - I've done similar horrible conversion tricks with framebuffers, where drivers tend to embed the static fbdev framebuffer into the fbdev emulation struct. You just need raw free/destroy entry points which for safety check that the kref count is exactly 1.
- For the actual atomic integration I think we need a blob prop pointer separate from the mode struct. The blob prop contains the userspace ABI struct, and the embedded one is the one used internally. Doing any kind of conversion just leads to lots of churn, which is especially bad with around 4 still incomplete/unmerged atomic conversion. So just
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index adc9ea5acf02..d6a7a5247b64 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -296,6 +296,7 @@ struct drm_crtc_state { struct drm_display_mode adjusted_mode;
struct drm_display_mode mode;
struct drm_property_blob * mode_blob; struct drm_pending_vblank_event *event;
Getting the refcounting right for the atomic ioctl should be simple. For the legacy ->set_config entrypoint we need to fix things up in the helper when we update the mode, by manually releasing the old mode blob and creating a new one (owned by the kernel to avoid leaks because old userspace won't clean them up - we've had this bug with compat cursor fbs just recently).
To be honest I think the fb refcnt bug is pretty apropos here - by keeping these awkwardly split out, independently reference-counted, not sensibly linked to each other, and not even verifying the correctness of the users (const), you're inviting another disaster along the same lines. Especially as drivers start to move away from the helpers and are expected to manage more state themselves.
I agree the initial series was too invasive and there's value in having a much more minimal series, so how about I split out the crtc->mode constness (but not pointer - I don't think I have any desire to ever push that through tbqh) changes into another series we can track separately, and then see if we can get a much more minimal patchset that doesn't make me shudder and think of previous refcnt/state-consistency horrors, nor you of atomic conversions past, together. I'm happy to pull in the other guys doing atomic conversions and get some testing out of them to see if it'll work for them and how well, but having it run on Tegra was about as painless as I could've hoped for.
Cheers, Daniel
On Mon, Mar 23, 2015 at 04:58:47PM +0000, Daniel Stone wrote:
Hi,
On 23 March 2015 at 08:20, Daniel Vetter daniel@ffwll.ch wrote:
On Thu, Mar 19, 2015 at 04:32:36AM +0000, Daniel Stone wrote:
This series ends up touching pretty much all the drivers, by virtue of turning crtc->mode (in particular) into both a const and a pointer.
Ok this is quite a bit a different beast than what I expected. I think it's way too intrusive for drivers to land quickly, and there's a big depency chain linking everything. I think we need something much simpler.
Yeah, I'm uneasy with how invasive it's got: hence the proposal to drop crtc->mode back into being inlined. I don't think we lose anything from doing that (as crtc->state->mode still changes), and that makes the diff much less scary. The constness changes no longer become required, but I think are still pretty useful from the point of view of setting (and enforcing) our existing expectations. I'd still look to push those anyway, but at a much more sedate pace.
- as far as possible, modes should be relateable to their source, e.g. if Plymouth pulls a particular mode from the encoder, and you pick up on that mode as part of current configuration during handover, you should be able to work backwards to where Plymouth sourced it, i.e. the encoder list
With legacy setcrtc we already lose this information and thus far no one seems to have cared. And I don't see the use-case since simply comparing it to sources works well enough, in case you want to know where a mode is from.
On the other hand, I wouldn't suggest SetCrtc to really be a model to follow. I really don't mind SetCrtc breaking all these expectations above, mind.
Well setcrtc is bound to stay around, and userspace using it will also stick around for quite a bit I think. If we add new semantic guarantees and then userspace can't rely on them we bear all the cost without much benefit.
- userspace should be able to tell the current status by looking at the IDs returned by property queries, rather than having to pull the entire mode out: if we make them do that, they won't bother minimising the deltas and will just dump the full state in every time, and that makes debugging the entire thing that much harder
That doesn't work since idr eagerly reuses ids. Just by looking at the id you can't tell whether it's the same object or a new one accidentally reusing the same id slot. You always have to re-read the blob property too to reconstruct state.
Do we make any guarantee on connector->modes lifetimes? If it can't change without a hotplug event, then we know the ID is valid until the connector goes dark, at which point we have to drop any local cache relating to it.
Saying that userspace must read every single mode property back every single time is pretty horrible from the point of view of requiring more userspace->kernel->userspace->kernel->[...] trips to do discovery every time, just because we decided not to work out a sensible lifetime strategy to expose to userspace.
Current kernels should send you a hotplug event, so with those that strategy works - you can cache until the next hotplug. But on older kernels (and iirc we've only fixed this very recently) sometimes hotplug events get lost. So there if someone asks for a full reprobe, you have to do the full dance.
This blew up with edid blob properties where SNA had one clever trick too many and thought that matching edid blob prop id means the edid is unchanged. But since we remove the old blob before we add the new one you're pretty much guranteed to reuse the same slot.
Sure, if you're not paying attention to the defined lifetime, then don't do any caching. But this is about _defining_ such a usable lifetime that userspace can.
Hm let's backtrack a bit: What's the upside of this defined lifetime? Atm I see a lot of cost on the kernel side (getting this series in will take a few releases probably because there's so many interlocked subsystem-wide changes). But I don't see a benefit.
The only place we currently read out the current configuration is when the compositor starts up so that it can perfectly take over whatever's been set up by the firmware/boot splash for fastboot. Afterwards everyone just bashes in their own config, even when switching between compositors and all that.
Without a clear use-case that justifies the work I don't think we should do this - someone will come up with clever abuse for it and then we have another hard-to-work-around regression at hand. So from my side the only requirement is that atomic clients should be able to somehow get at the current blob properties like mode, gamma ...
- setting a mode current should hold a reference for as long as it's current, e.g. if you create a magic user-supplied mode, set that on the CRTC and then terminate the connection, the mode should still live on for handover purposes
I think we need much less: If your driver supports atomic (and hence userspace might be asking for the mode blob prop id) then that blob should survive as long as the mode is in use.
Which not only requires the most invasive of the changes anyway (modulo those to crtc->mode, which can regardless be dropped), but also a bunch of 'every time the state changes, go consult some auxiliary property and potentially expire its lifetime'.
Well yeah, but for the mode property the only place it changes (besides the atomic ioctl) is in drm_atomic_helper_set_config. We have a lot more compat glue already than the few lines you'd need to add in there. The crucial bit is that we only need to make this work for atomic drivers, since non-atomic drivers won't ever expose the MODE_ID property. And non-atomic userspace doesn't care anyway.
Also the important part here isn't so much the mode (userspace can get at that), but other new blob properties like per-plane gamma or other color corrections tables.
- persistence of system-supplied (from-connector or from-CRTC) modes is not important beyond their natural lifetime: if you pick a mode up from a connector's probed list and then that connector disappears, setting that mode is unlikely to be what you want, so failure because the mode no longer exists is entirely acceptable
Somewhat unordered, but here's what I think we need:
- Subtyping blob properties is not needed, at least I can't think of a use-case. It will result though in lots of duplicated code for duplicated ref/unref functions and atomic prop handling.
When you say 'subtyping', do you mean what I've done with getblob?
Not just but yes. The other result is that we'd need to duplicate the property decoding code for each type in the atomic ioctl/set_property functions. And you need per-type reference/unreference functions.
- Since we already have a getblob ioctl I think we should just extend the existing drm_property_blob:
That was actually my initial implementation, but didn't like the resulting reference tie-up between drm_display_mode and drm_property_blob (aka drm_mode_modeinfo). I couldn't figure out a really clean way to do it that didn't provably fall down at some point, so abandoned it and went for referencing drm_display_mode instead.
Why refcount drm_display_mode? That's the drm-internal representation, we can just keep that as-is everywhere. I think that's the main point of why you opted for this much more invasive refactoring, and I don't see why we'd need it. The added kref for drm_blob_property is imo really all the krefs I think we need.
Plus ofc changing drm_property_create/destroy_blob into ref/unref functions. And doing the same weak reference trick for idrs as we're using for framebuffers now.
For mode properties the data contained would be struct drm_mode_modeinfo (i.e. the ABI struct we already use for the setcrtc/getconnector ioctls, not the internal one).
Right, this is what's there: 25/37 is explicitly always returning modeinfo, and the creation does as well. I don't see any benefit to exposing the internal struct.
Hm, maybe I need to explain my motiviation for the blob prop stuff: I want to use it for gamma tables (not just the per-crtc one we have, but per-plane tables too) and other bigger properties. Using it for the mode by packing the existing drm_mode_modeinfo into a blob too was just a bit an afterthought - for the mode we could as well just add properties for all the individual members, like we've done with all the other structures.
But loading gamma tables with gamma-0 up to gamma-1024 is way too unwielding, so that's why we imo really need blobs.
- Imo requiring all the legacy users to be converted to pointers isn't needed. crtc->mode/hwmode are deprecated for atomic drivers. Not that I don't think doing this isn't useful, I just think it's not needed to have a minimal atomic mode blob support.
Yeah, I agree. I'm moving all this out to be tracked in a separate series. A lot of it was to convince myself that in the process of the mode work I was doing, I wouldn't be breaking drivers.
Aside: We don't even need to convert mode structs to pointers if we embedded the kref into the mode - I've done similar horrible conversion tricks with framebuffers, where drivers tend to embed the static fbdev framebuffer into the fbdev emulation struct. You just need raw free/destroy entry points which for safety check that the kref count is exactly 1.
- For the actual atomic integration I think we need a blob prop pointer separate from the mode struct. The blob prop contains the userspace ABI struct, and the embedded one is the one used internally. Doing any kind of conversion just leads to lots of churn, which is especially bad with around 4 still incomplete/unmerged atomic conversion. So just
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index adc9ea5acf02..d6a7a5247b64 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -296,6 +296,7 @@ struct drm_crtc_state { struct drm_display_mode adjusted_mode;
struct drm_display_mode mode;
struct drm_property_blob * mode_blob; struct drm_pending_vblank_event *event;
Getting the refcounting right for the atomic ioctl should be simple. For the legacy ->set_config entrypoint we need to fix things up in the helper when we update the mode, by manually releasing the old mode blob and creating a new one (owned by the kernel to avoid leaks because old userspace won't clean them up - we've had this bug with compat cursor fbs just recently).
To be honest I think the fb refcnt bug is pretty apropos here - by keeping these awkwardly split out, independently reference-counted, not sensibly linked to each other, and not even verifying the correctness of the users (const), you're inviting another disaster along the same lines. Especially as drivers start to move away from the helpers and are expected to manage more state themselves.
Which fb refcount bug? We've had piles of them in the past, simply because refcounting is apparently hard. And I don't really see a problem with refcounted objects with atomic, normal driver code shouldn't ever care. The only place we need to be careful is in - duplicate/destroy_state functions: Can be fixed by extracting suitable helpers instead of copypasting. - atomic_set_property: For all the core properties the decoding is done in the core anyway.
And for the oddball driver-private blob property we can provide convienence functions to update pointers which will do the correct unref/ref dance.
I agree the initial series was too invasive and there's value in having a much more minimal series, so how about I split out the crtc->mode constness (but not pointer - I don't think I have any desire to ever push that through tbqh) changes into another series we can track separately, and then see if we can get a much more minimal patchset that doesn't make me shudder and think of previous refcnt/state-consistency horrors, nor you of atomic conversions past, together. I'm happy to pull in the other guys doing atomic conversions and get some testing out of them to see if it'll work for them and how well, but having it run on Tegra was about as painless as I could've hoped for.
Hm, how does a const crtc->mode as a non-pointer work? We do need to update this one in set_config. Or would you do a forced cast in these cases?
But even for that I don't see why we'd need to change crtc->mode really to make the atomic mode a blob property.
Cheers, Daniel
Hi, Yikes, I think we're talking past each other a bit. So I thought a v2 might help.
On 24 March 2015 at 08:55, Daniel Vetter daniel@ffwll.ch wrote:
On Mon, Mar 23, 2015 at 04:58:47PM +0000, Daniel Stone wrote:
On 23 March 2015 at 08:20, Daniel Vetter daniel@ffwll.ch wrote:
Ok this is quite a bit a different beast than what I expected. I think it's way too intrusive for drivers to land quickly, and there's a big depency chain linking everything. I think we need something much simpler.
Yeah, I'm uneasy with how invasive it's got: hence the proposal to drop crtc->mode back into being inlined. I don't think we lose anything from doing that (as crtc->state->mode still changes), and that makes the diff much less scary. The constness changes no longer become required, but I think are still pretty useful from the point of view of setting (and enforcing) our existing expectations. I'd still look to push those anyway, but at a much more sedate pace.
As promised, have pulled this out. I've split the series into two parallel series, which barely intersect (i.e. the merge is trivial): http://cgit.collabora.com/git/user/daniels/linux.git/log/?h=wip/drm-next/drm... is the change to constify all crtc->mode users, without turning crtc->mode itself const, or into a pointer. I think these are all worthwhile cleanups in their own right, but as they're quite invasive, we can push them separately and much more slowly.
http://cgit.collabora.com/git/user/daniels/linux.git/log/?h=wip/drm-next/drm... is the much less invasive[0] work to refcount modes, expose CRTC/connector modes to userspace through properties, and allow user-supplied blob properties. I think this is really quite safe, and the interactions with drivers are pretty minimal.
For now, I don't intend to really talk much about drm-constness, since it's neither interesting nor relevant. So this is just about drm-modes-ref.
- as far as possible, modes should be relateable to their source, e.g. if Plymouth pulls a particular mode from the encoder, and you pick up on that mode as part of current configuration during handover, you should be able to work backwards to where Plymouth sourced it, i.e. the encoder list
With legacy setcrtc we already lose this information and thus far no one seems to have cared. And I don't see the use-case since simply comparing it to sources works well enough, in case you want to know where a mode is from.
On the other hand, I wouldn't suggest SetCrtc to really be a model to follow. I really don't mind SetCrtc breaking all these expectations above, mind.
Well setcrtc is bound to stay around, and userspace using it will also stick around for quite a bit I think. If we add new semantic guarantees and then userspace can't rely on them we bear all the cost without much benefit.
Right, if you're using SetCrtc then you can expect to lose, and that's fine. But I don't think we should hobble new userspace forever to the terrible interfaces we made previously.
Do we make any guarantee on connector->modes lifetimes? If it can't change without a hotplug event, then we know the ID is valid until the connector goes dark, at which point we have to drop any local cache relating to it.
Saying that userspace must read every single mode property back every single time is pretty horrible from the point of view of requiring more userspace->kernel->userspace->kernel->[...] trips to do discovery every time, just because we decided not to work out a sensible lifetime strategy to expose to userspace.
Current kernels should send you a hotplug event, so with those that strategy works - you can cache until the next hotplug. But on older kernels (and iirc we've only fixed this very recently) sometimes hotplug events get lost. So there if someone asks for a full reprobe, you have to do the full dance.
Right, but this isn't in any kernels yet, so we don't exactly need to worry about bad interactions with other parts of old kernels.
This blew up with edid blob properties where SNA had one clever trick too many and thought that matching edid blob prop id means the edid is unchanged. But since we remove the old blob before we add the new one you're pretty much guranteed to reuse the same slot.
Sure, if you're not paying attention to the defined lifetime, then don't do any caching. But this is about _defining_ such a usable lifetime that userspace can.
Hm let's backtrack a bit: What's the upside of this defined lifetime? Atm I see a lot of cost on the kernel side (getting this series in will take a few releases probably because there's so many interlocked subsystem-wide changes). But I don't see a benefit.
I think the current drm-modes-ref branch should take care of the cost argument. The upside is that it gets much easier to debug and trace command streams (i.e. it's pretty easy to remember mode ID 34; much more tedious to dump out the entire modeline every time), and that it's much more difficult to screw up in incredibly subtle ways (two independent mode properties which have to be updated together at all times, including in error paths? what could possibly go wrong ...).
The only place we currently read out the current configuration is when the compositor starts up so that it can perfectly take over whatever's been set up by the firmware/boot splash for fastboot. Afterwards everyone just bashes in their own config, even when switching between compositors and all that.
They bash in their own config, because right now it's about all you can do. As we're giving userspace an interface that allows sensible handovers and incremental updates, why not use it ... ? That we do full mode reprogramming when moving from splash screen to compositor is a bug, not a great piece of design. If we can (even subtly) encourage userspace to be better and smarter, then I don't see why we wouldn't.
It also makes it a nightmare to debug the userspace side of things, because when you just have to smash the entire config in all the time, it becomes much more difficult to separate the intended changes out from the unintended ones. Which means people are more likely to throw their hands up and just blame the kernel.
Without a clear use-case that justifies the work I don't think we should do this - someone will come up with clever abuse for it and then we have another hard-to-work-around regression at hand. So from my side the only requirement is that atomic clients should be able to somehow get at the current blob properties like mode, gamma ...
Which of the requirements are you worried about people abusing?
I think we need much less: If your driver supports atomic (and hence userspace might be asking for the mode blob prop id) then that blob should survive as long as the mode is in use.
Which not only requires the most invasive of the changes anyway (modulo those to crtc->mode, which can regardless be dropped), but also a bunch of 'every time the state changes, go consult some auxiliary property and potentially expire its lifetime'.
Well yeah, but for the mode property the only place it changes (besides the atomic ioctl) is in drm_atomic_helper_set_config.
You forgot intel_crtc_set_config. ;)
We have a lot more compat glue already than the few lines you'd need to add in there. The crucial bit is that we only need to make this work for atomic drivers, since non-atomic drivers won't ever expose the MODE_ID property. And non-atomic userspace doesn't care anyway.
That's actually a fair point, and why I don't so much mind rowing back on the crtc->mode changes. I'm happy to leave never-will-be-atomic drivers in their own little ghetto. But it does make it harder and more fiddly for people to implement atomic drivers: it's one more subtle thing to screw up and get wrong, especially in error paths. Whereas crtc_state->mode = drm_mode_reference(foo) is pretty hard to get wrong.
Also the important part here isn't so much the mode (userspace can get at that), but other new blob properties like per-plane gamma or other color corrections tables.
Sure.
Somewhat unordered, but here's what I think we need:
- Subtyping blob properties is not needed, at least I can't think of a use-case. It will result though in lots of duplicated code for duplicated ref/unref functions and atomic prop handling.
When you say 'subtyping', do you mean what I've done with getblob?
Not just but yes. The other result is that we'd need to duplicate the property decoding code for each type in the atomic ioctl/set_property functions. And you need per-type reference/unreference functions.
At least as far as gamma and other LUTs are concerned, I agree.
- Since we already have a getblob ioctl I think we should just extend the existing drm_property_blob:
That was actually my initial implementation, but didn't like the resulting reference tie-up between drm_display_mode and drm_property_blob (aka drm_mode_modeinfo). I couldn't figure out a really clean way to do it that didn't provably fall down at some point, so abandoned it and went for referencing drm_display_mode instead.
Why refcount drm_display_mode? That's the drm-internal representation, we can just keep that as-is everywhere. I think that's the main point of why you opted for this much more invasive refactoring, and I don't see why we'd need it. The added kref for drm_blob_property is imo really all the krefs I think we need.
I think it's now much less invasive. The reason I opted for doing it like that is because it avoided duplicating the mode structure in such a way that resulted in non-obvious breakage. I just don't like the potential for people to break the synchronisation between the two. (Which was part of the reason I ended up doing the crtc->mode constness dance in the first place ...)
Plus ofc changing drm_property_create/destroy_blob into ref/unref functions. And doing the same weak reference trick for idrs as we're using for framebuffers now.
Indeed.
For mode properties the data contained would be struct drm_mode_modeinfo (i.e. the ABI struct we already use for the setcrtc/getconnector ioctls, not the internal one).
Right, this is what's there: 25/37 is explicitly always returning modeinfo, and the creation does as well. I don't see any benefit to exposing the internal struct.
Hm, maybe I need to explain my motiviation for the blob prop stuff: I want to use it for gamma tables (not just the per-crtc one we have, but per-plane tables too) and other bigger properties. Using it for the mode by packing the existing drm_mode_modeinfo into a blob too was just a bit an afterthought - for the mode we could as well just add properties for all the individual members, like we've done with all the other structures.
But loading gamma tables with gamma-0 up to gamma-1024 is way too unwielding, so that's why we imo really need blobs.
Right, that makes total sense. I don't think anything in here precludes using this, except the precedent of refcounting the mode rather than the blob property. The reason I did that is because we already _have_ a drm_mode_object type for modes, and having two properties tied together in a mutual deathgrip seemed like an invitation for failure.
So for gamma, either we could take the same approach and generate wrapper objects around the blobs - which is useful when you have other representations which are internally widely used (e.g. drm_display_mode vs. drm_mode_modeinfo), or just refcount the blobs and let drivers deal with any conversion. My guess is that the latter would be most useful, as there's nothing we can really standardise on - and at least currently, gamma _only_ tends to come from userspace. Not only do modes have an alternate representation which is already useful enough to have its own object type and ID set, but they basically all come from the kernel, with the drm_mode_modeinfo being a conversion, rather than the other way around. Hence why I chose to keep the current internal representation as the primary.
So I think a lot of the similarities on there are misleading when you scratch the surface of it; again, I had started with that exact approach when I came into this, but later revised it.
Getting the refcounting right for the atomic ioctl should be simple. For the legacy ->set_config entrypoint we need to fix things up in the helper when we update the mode, by manually releasing the old mode blob and creating a new one (owned by the kernel to avoid leaks because old userspace won't clean them up - we've had this bug with compat cursor fbs just recently).
To be honest I think the fb refcnt bug is pretty apropos here - by keeping these awkwardly split out, independently reference-counted, not sensibly linked to each other, and not even verifying the correctness of the users (const), you're inviting another disaster along the same lines. Especially as drivers start to move away from the helpers and are expected to manage more state themselves.
Which fb refcount bug? We've had piles of them in the past, simply because refcounting is apparently hard.
Yeah. So if we're introducing refcounting, why not make it as easy and as clear as possible, rather than splitting your objects between one that's refcounted and used for half of what you're doing, and another that isn't refcounted and is used for the other half? We already know that people screw this up, so why not make it as clear and as difficult to get wrong as possible?
I agree the initial series was too invasive and there's value in having a much more minimal series, so how about I split out the crtc->mode constness (but not pointer - I don't think I have any desire to ever push that through tbqh) changes into another series we can track separately, and then see if we can get a much more minimal patchset that doesn't make me shudder and think of previous refcnt/state-consistency horrors, nor you of atomic conversions past, together. I'm happy to pull in the other guys doing atomic conversions and get some testing out of them to see if it'll work for them and how well, but having it run on Tegra was about as painless as I could've hoped for.
Hm, how does a const crtc->mode as a non-pointer work? We do need to update this one in set_config. Or would you do a forced cast in these cases?
But even for that I don't see why we'd need to change crtc->mode really to make the atomic mode a blob property.
I agree; I'd initially thought that was necessary, and it was only when I'd got a reasonable way down the road that I'd realised it wasn't necessary. By the time I'd done that, it seemed prudent to finish it off and fix the drivers, if only to convince myself that it wouldn't be breaking drivers or introducing bugs by doing all this.
I'm not sure we're going to convince each other at this point, so I'll just skim over the core arguments and leave it at this: - this is no longer really invasive at all - modes aren't as similar to other blobs as they first seem (else we'd just be using drm_mode_modeinfo with no mode-object type everywhere) - refcounting modes provides for much easier debuggability and traceability for both kernel and userspace, and especially across the boundary where you may not be familiar with the other side - giving people another opportunity to screw things up is never a good thing, especially when (both in refcounting and specifically in modes) they've repeatedly proven that they do screw it up horrendously
If you have a good-faith look at the patchset (git URL is in with cgit) and still want it re-done to add the blob properties on the side instead, then I'll do that. But hopefully the much smaller series (I've also squashed some of the more aggressively-split patches, on the grounds that they're not that crucial for bisect) will convince you ... ?
Cheers, Daniel
[0]: drivers/gpu/drm/drm_atomic.c | 35 +++- drivers/gpu/drm/drm_atomic_helper.c | 69 +++++-- drivers/gpu/drm/drm_crtc.c | 325 ++++++++++++++++++++---------- drivers/gpu/drm/drm_crtc_helper.c | 23 ++- drivers/gpu/drm/drm_fb_helper.c | 13 +- drivers/gpu/drm/drm_fops.c | 7 +- drivers/gpu/drm/drm_ioctl.c | 2 + drivers/gpu/drm/drm_modes.c | 139 ++++++++++++- drivers/gpu/drm/i915/intel_atomic.c | 13 +- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 2 +- drivers/gpu/drm/tegra/dc.c | 7 + drivers/gpu/drm/tegra/drm.c | 2 +- drivers/gpu/drm/tegra/dsi.c | 7 +- drivers/gpu/drm/tegra/hdmi.c | 3 +- drivers/gpu/drm/tegra/rgb.c | 3 +- drivers/gpu/drm/tegra/sor.c | 3 +- include/drm/drmP.h | 6 + include/drm/drm_crtc.h | 17 +- include/drm/drm_modes.h | 12 ++ include/uapi/drm/drm.h | 2 + include/uapi/drm/drm_mode.h | 22 ++ 22 files changed, 556 insertions(+), 158 deletions(-)
On Tue, Mar 24, 2015 at 10:49:22PM +0000, Daniel Stone wrote:
Hi, Yikes, I think we're talking past each other a bit. So I thought a v2 might help.
On 24 March 2015 at 08:55, Daniel Vetter daniel@ffwll.ch wrote:
On Mon, Mar 23, 2015 at 04:58:47PM +0000, Daniel Stone wrote:
On 23 March 2015 at 08:20, Daniel Vetter daniel@ffwll.ch wrote:
Ok this is quite a bit a different beast than what I expected. I think it's way too intrusive for drivers to land quickly, and there's a big depency chain linking everything. I think we need something much simpler.
Yeah, I'm uneasy with how invasive it's got: hence the proposal to drop crtc->mode back into being inlined. I don't think we lose anything from doing that (as crtc->state->mode still changes), and that makes the diff much less scary. The constness changes no longer become required, but I think are still pretty useful from the point of view of setting (and enforcing) our existing expectations. I'd still look to push those anyway, but at a much more sedate pace.
As promised, have pulled this out. I've split the series into two parallel series, which barely intersect (i.e. the merge is trivial): http://cgit.collabora.com/git/user/daniels/linux.git/log/?h=wip/drm-next/drm... is the change to constify all crtc->mode users, without turning crtc->mode itself const, or into a pointer. I think these are all worthwhile cleanups in their own right, but as they're quite invasive, we can push them separately and much more slowly.
http://cgit.collabora.com/git/user/daniels/linux.git/log/?h=wip/drm-next/drm... is the much less invasive[0] work to refcount modes, expose CRTC/connector modes to userspace through properties, and allow user-supplied blob properties. I think this is really quite safe, and the interactions with drivers are pretty minimal.
For now, I don't intend to really talk much about drm-constness, since it's neither interesting nor relevant. So this is just about drm-modes-ref.
- as far as possible, modes should be relateable to their source, e.g. if Plymouth pulls a particular mode from the encoder, and you pick up on that mode as part of current configuration during handover, you should be able to work backwards to where Plymouth sourced it, i.e. the encoder list
With legacy setcrtc we already lose this information and thus far no one seems to have cared. And I don't see the use-case since simply comparing it to sources works well enough, in case you want to know where a mode is from.
On the other hand, I wouldn't suggest SetCrtc to really be a model to follow. I really don't mind SetCrtc breaking all these expectations above, mind.
Well setcrtc is bound to stay around, and userspace using it will also stick around for quite a bit I think. If we add new semantic guarantees and then userspace can't rely on them we bear all the cost without much benefit.
Right, if you're using SetCrtc then you can expect to lose, and that's fine. But I don't think we should hobble new userspace forever to the terrible interfaces we made previously.
Do we make any guarantee on connector->modes lifetimes? If it can't change without a hotplug event, then we know the ID is valid until the connector goes dark, at which point we have to drop any local cache relating to it.
Saying that userspace must read every single mode property back every single time is pretty horrible from the point of view of requiring more userspace->kernel->userspace->kernel->[...] trips to do discovery every time, just because we decided not to work out a sensible lifetime strategy to expose to userspace.
Current kernels should send you a hotplug event, so with those that strategy works - you can cache until the next hotplug. But on older kernels (and iirc we've only fixed this very recently) sometimes hotplug events get lost. So there if someone asks for a full reprobe, you have to do the full dance.
Right, but this isn't in any kernels yet, so we don't exactly need to worry about bad interactions with other parts of old kernels.
This blew up with edid blob properties where SNA had one clever trick too many and thought that matching edid blob prop id means the edid is unchanged. But since we remove the old blob before we add the new one you're pretty much guranteed to reuse the same slot.
Sure, if you're not paying attention to the defined lifetime, then don't do any caching. But this is about _defining_ such a usable lifetime that userspace can.
Hm let's backtrack a bit: What's the upside of this defined lifetime? Atm I see a lot of cost on the kernel side (getting this series in will take a few releases probably because there's so many interlocked subsystem-wide changes). But I don't see a benefit.
I think the current drm-modes-ref branch should take care of the cost argument. The upside is that it gets much easier to debug and trace command streams (i.e. it's pretty easy to remember mode ID 34; much more tedious to dump out the entire modeline every time), and that it's much more difficult to screw up in incredibly subtle ways (two independent mode properties which have to be updated together at all times, including in error paths? what could possibly go wrong ...).
That's the price we pay for smooth upgrades - everything in atomic atm keeps old and new things in sync somehow, and yep it's fragile. And I don't see a real problem with keeping them in sync, there's not many users for it. And the tricky bits can be extracted into two helpers (one where you have a mode blob id for atomic, one where you have an already decoded mode struct for legacy/internal paths) like I lined out somewhere below.
The only place we currently read out the current configuration is when the compositor starts up so that it can perfectly take over whatever's been set up by the firmware/boot splash for fastboot. Afterwards everyone just bashes in their own config, even when switching between compositors and all that.
They bash in their own config, because right now it's about all you can do. As we're giving userspace an interface that allows sensible handovers and incremental updates, why not use it ... ? That we do full mode reprogramming when moving from splash screen to compositor is a bug, not a great piece of design. If we can (even subtly) encourage userspace to be better and smarter, then I don't see why we wouldn't.
We don't have full programming when moving from splash to compositor, at least when you're running SNA. It does read out the entire kernel state to reconstruct matching xrandr state. And it works already, no additional guarantees needed.
Maybe splash2compositor isn't the only place we want to do this smooth operation, but even if you do it on all vt switches its still a relatively rare thing.
It also makes it a nightmare to debug the userspace side of things, because when you just have to smash the entire config in all the time, it becomes much more difficult to separate the intended changes out from the unintended ones. Which means people are more likely to throw their hands up and just blame the kernel.
Without a clear use-case that justifies the work I don't think we should do this - someone will come up with clever abuse for it and then we have another hard-to-work-around regression at hand. So from my side the only requirement is that atomic clients should be able to somehow get at the current blob properties like mode, gamma ...
Which of the requirements are you worried about people abusing?
If you really want to allow userspace to be able to compare mode ids everywhere then sooner or later we'll have userspace that fully relies on that. And then we need to add hacks in the kernel to make that work by e.g. switching ids so that there's only ever one mode id per mode. All so that userspace can avoid 1 more getblob ioctl plus a memcmp.
Forcing userspace to do the ioctl+full memcmp really seems like the more solid approach. Especially since kernel state readout will only happen on takeover (boot-up, vt-switch) which is a really rare thing. On top of that libdrm doesn't give you any way currently to read out the kernel state without forcing a full reprobe and edid read. SNA has fixed this since years, Chris even floated a libdrm patch but adoption is minimal. Compare to an ioctl blowing through edid reads unecessarily on takeover is an entirely different beast. Given that I don't think anyone will ever measure the few usec the additional ioctl costs.
I think we need much less: If your driver supports atomic (and hence userspace might be asking for the mode blob prop id) then that blob should survive as long as the mode is in use.
Which not only requires the most invasive of the changes anyway (modulo those to crtc->mode, which can regardless be dropped), but also a bunch of 'every time the state changes, go consult some auxiliary property and potentially expire its lifetime'.
Well yeah, but for the mode property the only place it changes (besides the atomic ioctl) is in drm_atomic_helper_set_config.
You forgot intel_crtc_set_config. ;)
Will go away (mostly at least) once we've converted to atomic. Atomic helpers match i915 modeset design for a reason ;-)
We have a lot more compat glue already than the few lines you'd need to add in there. The crucial bit is that we only need to make this work for atomic drivers, since non-atomic drivers won't ever expose the MODE_ID property. And non-atomic userspace doesn't care anyway.
That's actually a fair point, and why I don't so much mind rowing back on the crtc->mode changes. I'm happy to leave never-will-be-atomic drivers in their own little ghetto. But it does make it harder and more fiddly for people to implement atomic drivers: it's one more subtle thing to screw up and get wrong, especially in error paths. Whereas crtc_state->mode = drm_mode_reference(foo) is pretty hard to get wrong.
Drivers don't care about how the state gets filled in. Or well shouldn't ever, that's all done in helpers. We can easily provide a helper like
drm_atomic_helper_fill_mode(crtc_state, mode_id) { if (crtc_state->mode_blob) drm_blob_unref(crtc_state->mode_blob);
mode_blob = lookup(mode_id); /* assume this grabs a ref */ crtc_state->mode_blob = mode_blob;
drm_umode_to_mode(mode_blob->data, &crtc_state->mode); }
We already have similar helpers to set other things where tricky rules apply. And if you want we can do a similar legacy helper which creates an ad-hoc mode blob (similar to how the cursor ioctls gets remapped to plane functions).
Also the important part here isn't so much the mode (userspace can get at that), but other new blob properties like per-plane gamma or other color corrections tables.
Sure.
Somewhat unordered, but here's what I think we need:
- Subtyping blob properties is not needed, at least I can't think of a use-case. It will result though in lots of duplicated code for duplicated ref/unref functions and atomic prop handling.
When you say 'subtyping', do you mean what I've done with getblob?
Not just but yes. The other result is that we'd need to duplicate the property decoding code for each type in the atomic ioctl/set_property functions. And you need per-type reference/unreference functions.
At least as far as gamma and other LUTs are concerned, I agree.
- Since we already have a getblob ioctl I think we should just extend the existing drm_property_blob:
That was actually my initial implementation, but didn't like the resulting reference tie-up between drm_display_mode and drm_property_blob (aka drm_mode_modeinfo). I couldn't figure out a really clean way to do it that didn't provably fall down at some point, so abandoned it and went for referencing drm_display_mode instead.
Why refcount drm_display_mode? That's the drm-internal representation, we can just keep that as-is everywhere. I think that's the main point of why you opted for this much more invasive refactoring, and I don't see why we'd need it. The added kref for drm_blob_property is imo really all the krefs I think we need.
I think it's now much less invasive. The reason I opted for doing it like that is because it avoided duplicating the mode structure in such a way that resulted in non-obvious breakage. I just don't like the potential for people to break the synchronisation between the two. (Which was part of the reason I ended up doing the crtc->mode constness dance in the first place ...)
Imo we need to justify each and every kref because refcounting tends to be fragile and buggy imo. For blob properties we need the refcount as soon as we allow userspace to create them and the kernel to use them independently. We've tried to do that without refcounts for framebuffers way back, it doesn't work well.
For the internal mode representation which is copied around all over the place in modeset code I don't see any reasons why we need a kref. It's not the userspace representation of a mode, so even if we decide to make some guarantees about uniqueness we can still happily copy the modes around internally. And as long as copying is ok that's much simpler than refcounting.
Plus ofc changing drm_property_create/destroy_blob into ref/unref functions. And doing the same weak reference trick for idrs as we're using for framebuffers now.
Indeed.
For mode properties the data contained would be struct drm_mode_modeinfo (i.e. the ABI struct we already use for the setcrtc/getconnector ioctls, not the internal one).
Right, this is what's there: 25/37 is explicitly always returning modeinfo, and the creation does as well. I don't see any benefit to exposing the internal struct.
Hm, maybe I need to explain my motiviation for the blob prop stuff: I want to use it for gamma tables (not just the per-crtc one we have, but per-plane tables too) and other bigger properties. Using it for the mode by packing the existing drm_mode_modeinfo into a blob too was just a bit an afterthought - for the mode we could as well just add properties for all the individual members, like we've done with all the other structures.
But loading gamma tables with gamma-0 up to gamma-1024 is way too unwielding, so that's why we imo really need blobs.
Right, that makes total sense. I don't think anything in here precludes using this, except the precedent of refcounting the mode rather than the blob property. The reason I did that is because we already _have_ a drm_mode_object type for modes, and having two properties tied together in a mutual deathgrip seemed like an invitation for failure.
So for gamma, either we could take the same approach and generate wrapper objects around the blobs - which is useful when you have other representations which are internally widely used (e.g. drm_display_mode vs. drm_mode_modeinfo), or just refcount the blobs and let drivers deal with any conversion. My guess is that the latter would be most useful, as there's nothing we can really standardise on
- and at least currently, gamma _only_ tends to come from userspace.
Not only do modes have an alternate representation which is already useful enough to have its own object type and ID set, but they basically all come from the kernel, with the drm_mode_modeinfo being a conversion, rather than the other way around. Hence why I chose to keep the current internal representation as the primary.
I think modes are special because we have both uapi and internal versions of it. So there's necessarily some conversion going on. And because atomic state structures are meant to be const once committed it's simpler to just keep both around in parallel.
For gamma otoh we just have the raw data and conversion (if there's any) will happen in the driver when uploading. There it's good enough to carry around just the undecoded blob with it's raw data. Even more so for driver/hw specific properties which might directly represent some register settings.
So I think a lot of the similarities on there are misleading when you scratch the surface of it; again, I had started with that exact approach when I came into this, but later revised it.
Hm I think you've lost me - which similarities are we talking about now?
Getting the refcounting right for the atomic ioctl should be simple. For the legacy ->set_config entrypoint we need to fix things up in the helper when we update the mode, by manually releasing the old mode blob and creating a new one (owned by the kernel to avoid leaks because old userspace won't clean them up - we've had this bug with compat cursor fbs just recently).
To be honest I think the fb refcnt bug is pretty apropos here - by keeping these awkwardly split out, independently reference-counted, not sensibly linked to each other, and not even verifying the correctness of the users (const), you're inviting another disaster along the same lines. Especially as drivers start to move away from the helpers and are expected to manage more state themselves.
Which fb refcount bug? We've had piles of them in the past, simply because refcounting is apparently hard.
Yeah. So if we're introducing refcounting, why not make it as easy and as clear as possible, rather than splitting your objects between one that's refcounted and used for half of what you're doing, and another that isn't refcounted and is used for the other half? We already know that people screw this up, so why not make it as clear and as difficult to get wrong as possible?
Because they're not the same, at least to me. The refcounted blob prop part is just the data transport between userspace and the kernel for all kinds of bigger-ish modeset data. The internal representation is something entirely different and imo doesn't need to be tied to the public one imo.
Well shouldn't even, since drivers exclusively deal with the internal representation, so if we allow them to keep on copying those we'll have no refcounting issues in drivers at all. Becuase there won't be any refcounting going on.
I agree the initial series was too invasive and there's value in having a much more minimal series, so how about I split out the crtc->mode constness (but not pointer - I don't think I have any desire to ever push that through tbqh) changes into another series we can track separately, and then see if we can get a much more minimal patchset that doesn't make me shudder and think of previous refcnt/state-consistency horrors, nor you of atomic conversions past, together. I'm happy to pull in the other guys doing atomic conversions and get some testing out of them to see if it'll work for them and how well, but having it run on Tegra was about as painless as I could've hoped for.
Hm, how does a const crtc->mode as a non-pointer work? We do need to update this one in set_config. Or would you do a forced cast in these cases?
But even for that I don't see why we'd need to change crtc->mode really to make the atomic mode a blob property.
I agree; I'd initially thought that was necessary, and it was only when I'd got a reasonable way down the road that I'd realised it wasn't necessary. By the time I'd done that, it seemed prudent to finish it off and fix the drivers, if only to convince myself that it wouldn't be breaking drivers or introducing bugs by doing all this.
I'm not sure we're going to convince each other at this point, so I'll just skim over the core arguments and leave it at this:
- this is no longer really invasive at all
- modes aren't as similar to other blobs as they first seem (else
we'd just be using drm_mode_modeinfo with no mode-object type everywhere)
- refcounting modes provides for much easier debuggability and
traceability for both kernel and userspace, and especially across the boundary where you may not be familiar with the other side
- giving people another opportunity to screw things up is never a
good thing, especially when (both in refcounting and specifically in modes) they've repeatedly proven that they do screw it up horrendously
Yeah I think I've understood your argument. I wanted to summarize my own but then I suddenly noticed that you're mentioning that drm_mode_modeinfo is a mode-object. That's faithful but useless copypasta from how xrandr works, see
commit c55b6b3da25aa3af36ec51a13a4ed15fef0d7a73 Author: Ville Syrjälä ville.syrjala@linux.intel.com Date: Fri Apr 26 17:40:28 2013 +0300
drm: Kill user_modes list and the associated ioctls
There is no way to use modes added to the user_modes list. We never look at the contents of said list in the kernel, and the only operations userspace can do are attach and detach. So the only "benefit" of this interface is wasting kernel memory.
Fortunately it seems no real user space application ever used these ioctls. So just kill them.
Also remove the prototypes for the non-existing drm_mode_addmode_ioctl() and drm_mode_rmmode_ioctl() functions.
v2: Use drm_noop instead of completely removing the ioctls
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Dave Airlie airlied@redhat.com
Iow that mode id and mode list that still exists can probably be ripped out without side-effects - the only way we transport modes back&forth between the kernel and userspace is through the raw uapi structure.
Might be useful to do an audit of all userspace to check whether we could remove more crap or not.
If you have a good-faith look at the patchset (git URL is in with cgit) and still want it re-done to add the blob properties on the side instead, then I'll do that. But hopefully the much smaller series (I've also squashed some of the more aggressively-split patches, on the grounds that they're not that crucial for bisect) will convince you ... ?
Yeah I'll take a look.
Thanks, Daniel
dri-devel@lists.freedesktop.org