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 at 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 &copy->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.
-- 
2.3.2

Reply via email to