aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c144
1 files changed, 69 insertions, 75 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index f68948bb2847..f10e5053580b 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -129,9 +129,9 @@ static const struct drm_mode_config_funcs omap_mode_config_funcs = {
129 .atomic_commit = drm_atomic_helper_commit, 129 .atomic_commit = drm_atomic_helper_commit,
130}; 130};
131 131
132static int get_connector_type(struct omap_dss_device *dssdev) 132static int get_connector_type(struct omap_dss_device *display)
133{ 133{
134 switch (dssdev->type) { 134 switch (display->type) {
135 case OMAP_DISPLAY_TYPE_HDMI: 135 case OMAP_DISPLAY_TYPE_HDMI:
136 return DRM_MODE_CONNECTOR_HDMIA; 136 return DRM_MODE_CONNECTOR_HDMIA;
137 case OMAP_DISPLAY_TYPE_DVI: 137 case OMAP_DISPLAY_TYPE_DVI:
@@ -151,65 +151,65 @@ static int get_connector_type(struct omap_dss_device *dssdev)
151 } 151 }
152} 152}
153 153
154static void omap_disconnect_dssdevs(struct drm_device *ddev) 154static void omap_disconnect_pipelines(struct drm_device *ddev)
155{ 155{
156 struct omap_drm_private *priv = ddev->dev_private; 156 struct omap_drm_private *priv = ddev->dev_private;
157 unsigned int i; 157 unsigned int i;
158 158
159 for (i = 0; i < priv->num_dssdevs; i++) { 159 for (i = 0; i < priv->num_pipes; i++) {
160 struct omap_dss_device *dssdev = priv->dssdevs[i]; 160 struct omap_dss_device *display = priv->pipes[i].display;
161 161
162 omapdss_device_disconnect(dssdev, NULL); 162 omapdss_device_disconnect(display, NULL);
163 priv->dssdevs[i] = NULL; 163 priv->pipes[i].display = NULL;
164 omapdss_device_put(dssdev); 164 omapdss_device_put(display);
165 } 165 }
166 166
167 priv->num_dssdevs = 0; 167 priv->num_pipes = 0;
168} 168}
169 169
170static int omap_compare_dssdevs(const void *a, const void *b) 170static int omap_compare_pipes(const void *a, const void *b)
171{ 171{
172 const struct omap_dss_device *dssdev1 = *(struct omap_dss_device **)a; 172 const struct omap_drm_pipeline *pipe1 = a;
173 const struct omap_dss_device *dssdev2 = *(struct omap_dss_device **)b; 173 const struct omap_drm_pipeline *pipe2 = b;
174 174
175 if (dssdev1->alias_id > dssdev2->alias_id) 175 if (pipe1->display->alias_id > pipe2->display->alias_id)
176 return 1; 176 return 1;
177 else if (dssdev1->alias_id < dssdev2->alias_id) 177 else if (pipe1->display->alias_id < pipe2->display->alias_id)
178 return -1; 178 return -1;
179 return 0; 179 return 0;
180} 180}
181 181
182static int omap_connect_dssdevs(struct drm_device *ddev) 182static int omap_connect_pipelines(struct drm_device *ddev)
183{ 183{
184 struct omap_drm_private *priv = ddev->dev_private; 184 struct omap_drm_private *priv = ddev->dev_private;
185 struct omap_dss_device *dssdev = NULL; 185 struct omap_dss_device *display = NULL;
186 int r; 186 int r;
187 187
188 if (!omapdss_stack_is_ready()) 188 if (!omapdss_stack_is_ready())
189 return -EPROBE_DEFER; 189 return -EPROBE_DEFER;
190 190
191 for_each_dss_display(dssdev) { 191 for_each_dss_display(display) {
192 r = omapdss_device_connect(priv->dss, dssdev, NULL); 192 r = omapdss_device_connect(priv->dss, display, NULL);
193 if (r == -EPROBE_DEFER) { 193 if (r == -EPROBE_DEFER) {
194 omapdss_device_put(dssdev); 194 omapdss_device_put(display);
195 goto cleanup; 195 goto cleanup;
196 } else if (r) { 196 } else if (r) {
197 dev_warn(dssdev->dev, "could not connect display: %s\n", 197 dev_warn(display->dev, "could not connect display: %s\n",
198 dssdev->name); 198 display->name);
199 } else { 199 } else {
200 omapdss_device_get(dssdev); 200 omapdss_device_get(display);
201 priv->dssdevs[priv->num_dssdevs++] = dssdev; 201 priv->pipes[priv->num_pipes++].display = display;
202 if (priv->num_dssdevs == ARRAY_SIZE(priv->dssdevs)) { 202 if (priv->num_pipes == ARRAY_SIZE(priv->pipes)) {
203 /* To balance the 'for_each_dss_display' loop */ 203 /* To balance the 'for_each_dss_display' loop */
204 omapdss_device_put(dssdev); 204 omapdss_device_put(display);
205 break; 205 break;
206 } 206 }
207 } 207 }
208 } 208 }
209 209
210 /* Sort the list by DT aliases */ 210 /* Sort the list by DT aliases */
211 sort(priv->dssdevs, priv->num_dssdevs, sizeof(priv->dssdevs[0]), 211 sort(priv->pipes, priv->num_pipes, sizeof(priv->pipes[0]),
212 omap_compare_dssdevs, NULL); 212 omap_compare_pipes, NULL);
213 213
214 return 0; 214 return 0;
215 215
@@ -218,7 +218,7 @@ cleanup:
218 * if we are deferring probe, we disconnect the devices we previously 218 * if we are deferring probe, we disconnect the devices we previously
219 * connected 219 * connected
220 */ 220 */
221 omap_disconnect_dssdevs(ddev); 221 omap_disconnect_pipelines(ddev);
222 222
223 return r; 223 return r;
224} 224}
@@ -241,7 +241,6 @@ static int omap_modeset_init(struct drm_device *dev)
241 struct omap_drm_private *priv = dev->dev_private; 241 struct omap_drm_private *priv = dev->dev_private;
242 int num_ovls = priv->dispc_ops->get_num_ovls(priv->dispc); 242 int num_ovls = priv->dispc_ops->get_num_ovls(priv->dispc);
243 int num_mgrs = priv->dispc_ops->get_num_mgrs(priv->dispc); 243 int num_mgrs = priv->dispc_ops->get_num_mgrs(priv->dispc);
244 int num_crtcs;
245 unsigned int i; 244 unsigned int i;
246 int ret; 245 int ret;
247 u32 plane_crtc_mask; 246 u32 plane_crtc_mask;
@@ -260,22 +259,17 @@ static int omap_modeset_init(struct drm_device *dev)
260 * configuration does not match the expectations or exceeds 259 * configuration does not match the expectations or exceeds
261 * the available resources, the configuration is rejected. 260 * the available resources, the configuration is rejected.
262 */ 261 */
263 num_crtcs = priv->num_dssdevs; 262 if (priv->num_pipes > num_mgrs || priv->num_pipes > num_ovls) {
264 if (num_crtcs > num_mgrs || num_crtcs > num_ovls ||
265 num_crtcs > ARRAY_SIZE(priv->crtcs) ||
266 num_crtcs > ARRAY_SIZE(priv->planes) ||
267 num_crtcs > ARRAY_SIZE(priv->encoders) ||
268 num_crtcs > ARRAY_SIZE(priv->connectors)) {
269 dev_err(dev->dev, "%s(): Too many connected displays\n", 263 dev_err(dev->dev, "%s(): Too many connected displays\n",
270 __func__); 264 __func__);
271 return -EINVAL; 265 return -EINVAL;
272 } 266 }
273 267
274 /* Create all planes first. They can all be put to any CRTC. */ 268 /* Create all planes first. They can all be put to any CRTC. */
275 plane_crtc_mask = (1 << num_crtcs) - 1; 269 plane_crtc_mask = (1 << priv->num_pipes) - 1;
276 270
277 for (i = 0; i < num_ovls; i++) { 271 for (i = 0; i < num_ovls; i++) {
278 enum drm_plane_type type = i < priv->num_dssdevs 272 enum drm_plane_type type = i < priv->num_pipes
279 ? DRM_PLANE_TYPE_PRIMARY 273 ? DRM_PLANE_TYPE_PRIMARY
280 : DRM_PLANE_TYPE_OVERLAY; 274 : DRM_PLANE_TYPE_OVERLAY;
281 struct drm_plane *plane; 275 struct drm_plane *plane;
@@ -291,36 +285,36 @@ static int omap_modeset_init(struct drm_device *dev)
291 } 285 }
292 286
293 /* Create the CRTCs, encoders and connectors. */ 287 /* Create the CRTCs, encoders and connectors. */
294 for (i = 0; i < priv->num_dssdevs; i++) { 288 for (i = 0; i < priv->num_pipes; i++) {
295 struct omap_dss_device *dssdev = priv->dssdevs[i]; 289 struct omap_drm_pipeline *pipe = &priv->pipes[i];
290 struct omap_dss_device *display = pipe->display;
296 struct drm_connector *connector; 291 struct drm_connector *connector;
297 struct drm_encoder *encoder; 292 struct drm_encoder *encoder;
298 struct drm_crtc *crtc; 293 struct drm_crtc *crtc;
299 294
300 encoder = omap_encoder_init(dev, dssdev); 295 encoder = omap_encoder_init(dev, display);
301 if (!encoder) 296 if (!encoder)
302 return -ENOMEM; 297 return -ENOMEM;
303 298
304 connector = omap_connector_init(dev, 299 connector = omap_connector_init(dev,
305 get_connector_type(dssdev), dssdev, encoder); 300 get_connector_type(display), display, encoder);
306 if (!connector) 301 if (!connector)
307 return -ENOMEM; 302 return -ENOMEM;
308 303
309 crtc = omap_crtc_init(dev, priv->planes[i], dssdev); 304 crtc = omap_crtc_init(dev, priv->planes[i], display);
310 if (IS_ERR(crtc)) 305 if (IS_ERR(crtc))
311 return PTR_ERR(crtc); 306 return PTR_ERR(crtc);
312 307
313 drm_connector_attach_encoder(connector, encoder); 308 drm_connector_attach_encoder(connector, encoder);
314 encoder->possible_crtcs = 1 << i; 309 encoder->possible_crtcs = 1 << i;
315 310
316 priv->crtcs[priv->num_crtcs++] = crtc; 311 pipe->crtc = crtc;
317 priv->encoders[priv->num_encoders++] = encoder; 312 pipe->encoder = encoder;
318 priv->connectors[priv->num_connectors++] = connector; 313 pipe->connector = connector;
319 } 314 }
320 315
321 DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n", 316 DBG("registered %u planes, %u crtcs/encoders/connectors\n",
322 priv->num_planes, priv->num_crtcs, priv->num_encoders, 317 priv->num_planes, priv->num_pipes);
323 priv->num_connectors);
324 318
325 dev->mode_config.min_width = 8; 319 dev->mode_config.min_width = 8;
326 dev->mode_config.min_height = 2; 320 dev->mode_config.min_height = 2;
@@ -355,11 +349,11 @@ static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
355 struct omap_drm_private *priv = ddev->dev_private; 349 struct omap_drm_private *priv = ddev->dev_private;
356 int i; 350 int i;
357 351
358 for (i = 0; i < priv->num_dssdevs; i++) { 352 for (i = 0; i < priv->num_pipes; i++) {
359 struct omap_dss_device *dssdev = priv->dssdevs[i]; 353 struct omap_dss_device *display = priv->pipes[i].display;
360 354
361 if (dssdev->driver->enable_hpd) 355 if (display->driver->enable_hpd)
362 dssdev->driver->enable_hpd(dssdev); 356 display->driver->enable_hpd(display);
363 } 357 }
364} 358}
365 359
@@ -371,11 +365,11 @@ static void omap_modeset_disable_external_hpd(struct drm_device *ddev)
371 struct omap_drm_private *priv = ddev->dev_private; 365 struct omap_drm_private *priv = ddev->dev_private;
372 int i; 366 int i;
373 367
374 for (i = 0; i < priv->num_dssdevs; i++) { 368 for (i = 0; i < priv->num_pipes; i++) {
375 struct omap_dss_device *dssdev = priv->dssdevs[i]; 369 struct omap_dss_device *display = priv->pipes[i].display;
376 370
377 if (dssdev->driver->disable_hpd) 371 if (display->driver->disable_hpd)
378 dssdev->driver->disable_hpd(dssdev); 372 display->driver->disable_hpd(display);
379 } 373 }
380} 374}
381 375
@@ -561,7 +555,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
561 555
562 omap_crtc_pre_init(priv); 556 omap_crtc_pre_init(priv);
563 557
564 ret = omap_connect_dssdevs(ddev); 558 ret = omap_connect_pipelines(ddev);
565 if (ret) 559 if (ret)
566 goto err_crtc_uninit; 560 goto err_crtc_uninit;
567 561
@@ -586,14 +580,14 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
586 } 580 }
587 581
588 /* Initialize vblank handling, start with all CRTCs disabled. */ 582 /* Initialize vblank handling, start with all CRTCs disabled. */
589 ret = drm_vblank_init(ddev, priv->num_crtcs); 583 ret = drm_vblank_init(ddev, priv->num_pipes);
590 if (ret) { 584 if (ret) {
591 dev_err(priv->dev, "could not init vblank\n"); 585 dev_err(priv->dev, "could not init vblank\n");
592 goto err_cleanup_modeset; 586 goto err_cleanup_modeset;
593 } 587 }
594 588
595 for (i = 0; i < priv->num_crtcs; i++) 589 for (i = 0; i < priv->num_pipes; i++)
596 drm_crtc_vblank_off(priv->crtcs[i]); 590 drm_crtc_vblank_off(priv->pipes[i].crtc);
597 591
598 omap_fbdev_init(ddev); 592 omap_fbdev_init(ddev);
599 593
@@ -621,7 +615,7 @@ err_cleanup_modeset:
621err_gem_deinit: 615err_gem_deinit:
622 omap_gem_deinit(ddev); 616 omap_gem_deinit(ddev);
623 destroy_workqueue(priv->wq); 617 destroy_workqueue(priv->wq);
624 omap_disconnect_dssdevs(ddev); 618 omap_disconnect_pipelines(ddev);
625err_crtc_uninit: 619err_crtc_uninit:
626 omap_crtc_pre_uninit(priv); 620 omap_crtc_pre_uninit(priv);
627 drm_dev_unref(ddev); 621 drm_dev_unref(ddev);
@@ -650,7 +644,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv)
650 644
651 destroy_workqueue(priv->wq); 645 destroy_workqueue(priv->wq);
652 646
653 omap_disconnect_dssdevs(ddev); 647 omap_disconnect_pipelines(ddev);
654 omap_crtc_pre_uninit(priv); 648 omap_crtc_pre_uninit(priv);
655 649
656 drm_dev_unref(ddev); 650 drm_dev_unref(ddev);
@@ -700,17 +694,17 @@ static int omap_drm_suspend_all_displays(struct drm_device *ddev)
700 struct omap_drm_private *priv = ddev->dev_private; 694 struct omap_drm_private *priv = ddev->dev_private;
701 int i; 695 int i;
702 696
703 for (i = 0; i < priv->num_dssdevs; i++) { 697 for (i = 0; i < priv->num_pipes; i++) {
704 struct omap_dss_device *dssdev = priv->dssdevs[i]; 698 struct omap_dss_device *display = priv->pipes[i].display;
705 699
706 if (!dssdev->driver) 700 if (!display->driver)
707 continue; 701 continue;
708 702
709 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 703 if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
710 dssdev->driver->disable(dssdev); 704 display->driver->disable(display);
711 dssdev->activate_after_resume = true; 705 display->activate_after_resume = true;
712 } else { 706 } else {
713 dssdev->activate_after_resume = false; 707 display->activate_after_resume = false;
714 } 708 }
715 } 709 }
716 710
@@ -722,15 +716,15 @@ static int omap_drm_resume_all_displays(struct drm_device *ddev)
722 struct omap_drm_private *priv = ddev->dev_private; 716 struct omap_drm_private *priv = ddev->dev_private;
723 int i; 717 int i;
724 718
725 for (i = 0; i < priv->num_dssdevs; i++) { 719 for (i = 0; i < priv->num_pipes; i++) {
726 struct omap_dss_device *dssdev = priv->dssdevs[i]; 720 struct omap_dss_device *display = priv->pipes[i].display;
727 721
728 if (!dssdev->driver) 722 if (!display->driver)
729 continue; 723 continue;
730 724
731 if (dssdev->activate_after_resume) { 725 if (display->activate_after_resume) {
732 dssdev->driver->enable(dssdev); 726 display->driver->enable(display);
733 dssdev->activate_after_resume = false; 727 display->activate_after_resume = false;
734 } 728 }
735 } 729 }
736 730