diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-03-05 08:02:22 -0500 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2018-09-03 09:13:27 -0400 |
commit | 2ee767922e1bc7ede9ceb7aed9a14141480836a7 (patch) | |
tree | 46eb1f71530ca4e198d48852095463326ab7c339 /drivers/gpu/drm/omapdrm/omap_drv.c | |
parent | ac3b13189333c224e800b3421ac89536d0109b78 (diff) |
drm/omap: Group CRTC, encoder, connector and dssdev in a structure
Create an omap_drm_pipeline structure to model display pipelines, made
of a CRTC, an encoder, a connector and a DSS display device. This allows
grouping related parameters together instead of storing them in
independent arrays and thus improves code readability.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 144 |
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 | ||
132 | static int get_connector_type(struct omap_dss_device *dssdev) | 132 | static 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 | ||
154 | static void omap_disconnect_dssdevs(struct drm_device *ddev) | 154 | static 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 | ||
170 | static int omap_compare_dssdevs(const void *a, const void *b) | 170 | static 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 | ||
182 | static int omap_connect_dssdevs(struct drm_device *ddev) | 182 | static 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: | |||
621 | err_gem_deinit: | 615 | err_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); |
625 | err_crtc_uninit: | 619 | err_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 | ||