diff options
| author | Inki Dae <inki.dae@samsung.com> | 2012-08-17 04:58:38 -0400 |
|---|---|---|
| committer | Inki Dae <inki.dae@samsung.com> | 2012-10-03 21:06:00 -0400 |
| commit | 1b85a0715f4615f953733c4afa6ec59cd0e73b52 (patch) | |
| tree | f6048a7139c5415b6758426a7dba59a51f5e3403 /drivers/gpu | |
| parent | 01ed812671c1163b35bf6ce9be221bd371bf9a8f (diff) | |
drm/exynos: update crtc to plane safely
if old_crtc isn't same as encoder->crtc then it means that
user changed crtc id to another one so a plane to old_crtc
should be disabled so that current plane can be updated safely
and plane->crtc should be set to new crtc(encoder->crtc)
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_encoder.c | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index f4531167fda6..92f9acf77b7f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | * @dpms: store the encoder dpms value. | 45 | * @dpms: store the encoder dpms value. |
| 46 | */ | 46 | */ |
| 47 | struct exynos_drm_encoder { | 47 | struct exynos_drm_encoder { |
| 48 | struct drm_crtc *old_crtc; | ||
| 48 | struct drm_encoder drm_encoder; | 49 | struct drm_encoder drm_encoder; |
| 49 | struct exynos_drm_manager *manager; | 50 | struct exynos_drm_manager *manager; |
| 50 | int dpms; | 51 | int dpms; |
| @@ -124,22 +125,74 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, | |||
| 124 | return true; | 125 | return true; |
| 125 | } | 126 | } |
| 126 | 127 | ||
| 128 | static void disable_plane_to_crtc(struct drm_device *dev, | ||
| 129 | struct drm_crtc *old_crtc, | ||
| 130 | struct drm_crtc *new_crtc) | ||
| 131 | { | ||
| 132 | struct drm_plane *plane; | ||
| 133 | |||
| 134 | /* | ||
| 135 | * if old_crtc isn't same as encoder->crtc then it means that | ||
| 136 | * user changed crtc id to another one so the plane to old_crtc | ||
| 137 | * should be disabled and plane->crtc should be set to new_crtc | ||
| 138 | * (encoder->crtc) | ||
| 139 | */ | ||
| 140 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) { | ||
| 141 | if (plane->crtc == old_crtc) { | ||
| 142 | /* | ||
| 143 | * do not change below call order. | ||
| 144 | * | ||
| 145 | * plane->funcs->disable_plane call checks | ||
| 146 | * if encoder->crtc is same as plane->crtc and if same | ||
| 147 | * then overlay_ops->disable callback will be called | ||
| 148 | * to diasble current hw overlay so plane->crtc should | ||
| 149 | * have new_crtc because new_crtc was set to | ||
| 150 | * encoder->crtc in advance. | ||
| 151 | */ | ||
| 152 | plane->crtc = new_crtc; | ||
| 153 | plane->funcs->disable_plane(plane); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 127 | static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, | 158 | static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, |
| 128 | struct drm_display_mode *mode, | 159 | struct drm_display_mode *mode, |
| 129 | struct drm_display_mode *adjusted_mode) | 160 | struct drm_display_mode *adjusted_mode) |
| 130 | { | 161 | { |
| 131 | struct drm_device *dev = encoder->dev; | 162 | struct drm_device *dev = encoder->dev; |
| 132 | struct drm_connector *connector; | 163 | struct drm_connector *connector; |
| 133 | struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); | 164 | struct exynos_drm_manager *manager; |
| 134 | struct exynos_drm_manager_ops *manager_ops = manager->ops; | 165 | struct exynos_drm_manager_ops *manager_ops; |
| 135 | 166 | ||
| 136 | DRM_DEBUG_KMS("%s\n", __FILE__); | 167 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 137 | 168 | ||
| 138 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 169 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 139 | if (connector->encoder == encoder) | 170 | if (connector->encoder == encoder) { |
| 171 | struct exynos_drm_encoder *exynos_encoder; | ||
| 172 | |||
| 173 | exynos_encoder = to_exynos_encoder(encoder); | ||
| 174 | |||
| 175 | if (exynos_encoder->old_crtc != encoder->crtc && | ||
| 176 | exynos_encoder->old_crtc) { | ||
| 177 | |||
| 178 | /* | ||
| 179 | * disable a plane to old crtc and change | ||
| 180 | * crtc of the plane to new one. | ||
| 181 | */ | ||
| 182 | disable_plane_to_crtc(dev, | ||
| 183 | exynos_encoder->old_crtc, | ||
| 184 | encoder->crtc); | ||
| 185 | } | ||
| 186 | |||
| 187 | manager = exynos_drm_get_manager(encoder); | ||
| 188 | manager_ops = manager->ops; | ||
| 189 | |||
| 140 | if (manager_ops && manager_ops->mode_set) | 190 | if (manager_ops && manager_ops->mode_set) |
| 141 | manager_ops->mode_set(manager->dev, | 191 | manager_ops->mode_set(manager->dev, |
| 142 | adjusted_mode); | 192 | adjusted_mode); |
| 193 | |||
| 194 | exynos_encoder->old_crtc = encoder->crtc; | ||
| 195 | } | ||
| 143 | } | 196 | } |
| 144 | } | 197 | } |
| 145 | 198 | ||
