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/drm/exynos/exynos_drm_encoder.c | |
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/drm/exynos/exynos_drm_encoder.c')
-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 | ||