aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorInki Dae <inki.dae@samsung.com>2012-08-17 04:58:38 -0400
committerInki Dae <inki.dae@samsung.com>2012-10-03 21:06:00 -0400
commit1b85a0715f4615f953733c4afa6ec59cd0e73b52 (patch)
treef6048a7139c5415b6758426a7dba59a51f5e3403 /drivers
parent01ed812671c1163b35bf6ce9be221bd371bf9a8f (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')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.c59
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 f4531167fda..92f9acf77b7 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 */
47struct exynos_drm_encoder { 47struct 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
128static 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
127static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, 158static 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