diff options
Diffstat (limited to 'drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c')
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 123 |
1 files changed, 80 insertions, 43 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index c396d459a9d0..3eb0749223d9 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | |||
@@ -148,7 +148,15 @@ static int mdp5_set_split_display(struct msm_kms *kms, | |||
148 | return mdp5_cmd_encoder_set_split_display(encoder, | 148 | return mdp5_cmd_encoder_set_split_display(encoder, |
149 | slave_encoder); | 149 | slave_encoder); |
150 | else | 150 | else |
151 | return mdp5_encoder_set_split_display(encoder, slave_encoder); | 151 | return mdp5_vid_encoder_set_split_display(encoder, |
152 | slave_encoder); | ||
153 | } | ||
154 | |||
155 | static void mdp5_set_encoder_mode(struct msm_kms *kms, | ||
156 | struct drm_encoder *encoder, | ||
157 | bool cmd_mode) | ||
158 | { | ||
159 | mdp5_encoder_set_intf_mode(encoder, cmd_mode); | ||
152 | } | 160 | } |
153 | 161 | ||
154 | static void mdp5_kms_destroy(struct msm_kms *kms) | 162 | static void mdp5_kms_destroy(struct msm_kms *kms) |
@@ -230,6 +238,7 @@ static const struct mdp_kms_funcs kms_funcs = { | |||
230 | .get_format = mdp_get_format, | 238 | .get_format = mdp_get_format, |
231 | .round_pixclk = mdp5_round_pixclk, | 239 | .round_pixclk = mdp5_round_pixclk, |
232 | .set_split_display = mdp5_set_split_display, | 240 | .set_split_display = mdp5_set_split_display, |
241 | .set_encoder_mode = mdp5_set_encoder_mode, | ||
233 | .destroy = mdp5_kms_destroy, | 242 | .destroy = mdp5_kms_destroy, |
234 | #ifdef CONFIG_DEBUG_FS | 243 | #ifdef CONFIG_DEBUG_FS |
235 | .debugfs_init = mdp5_kms_debugfs_init, | 244 | .debugfs_init = mdp5_kms_debugfs_init, |
@@ -267,7 +276,7 @@ int mdp5_enable(struct mdp5_kms *mdp5_kms) | |||
267 | 276 | ||
268 | static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms, | 277 | static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms, |
269 | enum mdp5_intf_type intf_type, int intf_num, | 278 | enum mdp5_intf_type intf_type, int intf_num, |
270 | enum mdp5_intf_mode intf_mode, struct mdp5_ctl *ctl) | 279 | struct mdp5_ctl *ctl) |
271 | { | 280 | { |
272 | struct drm_device *dev = mdp5_kms->dev; | 281 | struct drm_device *dev = mdp5_kms->dev; |
273 | struct msm_drm_private *priv = dev->dev_private; | 282 | struct msm_drm_private *priv = dev->dev_private; |
@@ -275,21 +284,15 @@ static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms, | |||
275 | struct mdp5_interface intf = { | 284 | struct mdp5_interface intf = { |
276 | .num = intf_num, | 285 | .num = intf_num, |
277 | .type = intf_type, | 286 | .type = intf_type, |
278 | .mode = intf_mode, | 287 | .mode = MDP5_INTF_MODE_NONE, |
279 | }; | 288 | }; |
280 | 289 | ||
281 | if ((intf_type == INTF_DSI) && | 290 | encoder = mdp5_encoder_init(dev, &intf, ctl); |
282 | (intf_mode == MDP5_INTF_DSI_MODE_COMMAND)) | ||
283 | encoder = mdp5_cmd_encoder_init(dev, &intf, ctl); | ||
284 | else | ||
285 | encoder = mdp5_encoder_init(dev, &intf, ctl); | ||
286 | |||
287 | if (IS_ERR(encoder)) { | 291 | if (IS_ERR(encoder)) { |
288 | dev_err(dev->dev, "failed to construct encoder\n"); | 292 | dev_err(dev->dev, "failed to construct encoder\n"); |
289 | return encoder; | 293 | return encoder; |
290 | } | 294 | } |
291 | 295 | ||
292 | encoder->possible_crtcs = (1 << priv->num_crtcs) - 1; | ||
293 | priv->encoders[priv->num_encoders++] = encoder; | 296 | priv->encoders[priv->num_encoders++] = encoder; |
294 | 297 | ||
295 | return encoder; | 298 | return encoder; |
@@ -338,8 +341,7 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num) | |||
338 | break; | 341 | break; |
339 | } | 342 | } |
340 | 343 | ||
341 | encoder = construct_encoder(mdp5_kms, INTF_eDP, intf_num, | 344 | encoder = construct_encoder(mdp5_kms, INTF_eDP, intf_num, ctl); |
342 | MDP5_INTF_MODE_NONE, ctl); | ||
343 | if (IS_ERR(encoder)) { | 345 | if (IS_ERR(encoder)) { |
344 | ret = PTR_ERR(encoder); | 346 | ret = PTR_ERR(encoder); |
345 | break; | 347 | break; |
@@ -357,8 +359,7 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num) | |||
357 | break; | 359 | break; |
358 | } | 360 | } |
359 | 361 | ||
360 | encoder = construct_encoder(mdp5_kms, INTF_HDMI, intf_num, | 362 | encoder = construct_encoder(mdp5_kms, INTF_HDMI, intf_num, ctl); |
361 | MDP5_INTF_MODE_NONE, ctl); | ||
362 | if (IS_ERR(encoder)) { | 363 | if (IS_ERR(encoder)) { |
363 | ret = PTR_ERR(encoder); | 364 | ret = PTR_ERR(encoder); |
364 | break; | 365 | break; |
@@ -369,9 +370,6 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num) | |||
369 | case INTF_DSI: | 370 | case INTF_DSI: |
370 | { | 371 | { |
371 | int dsi_id = get_dsi_id_from_intf(hw_cfg, intf_num); | 372 | int dsi_id = get_dsi_id_from_intf(hw_cfg, intf_num); |
372 | struct drm_encoder *dsi_encs[MSM_DSI_ENCODER_NUM]; | ||
373 | enum mdp5_intf_mode mode; | ||
374 | int i; | ||
375 | 373 | ||
376 | if ((dsi_id >= ARRAY_SIZE(priv->dsi)) || (dsi_id < 0)) { | 374 | if ((dsi_id >= ARRAY_SIZE(priv->dsi)) || (dsi_id < 0)) { |
377 | dev_err(dev->dev, "failed to find dsi from intf %d\n", | 375 | dev_err(dev->dev, "failed to find dsi from intf %d\n", |
@@ -389,19 +387,13 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num) | |||
389 | break; | 387 | break; |
390 | } | 388 | } |
391 | 389 | ||
392 | for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) { | 390 | encoder = construct_encoder(mdp5_kms, INTF_DSI, intf_num, ctl); |
393 | mode = (i == MSM_DSI_CMD_ENCODER_ID) ? | 391 | if (IS_ERR(encoder)) { |
394 | MDP5_INTF_DSI_MODE_COMMAND : | 392 | ret = PTR_ERR(encoder); |
395 | MDP5_INTF_DSI_MODE_VIDEO; | 393 | break; |
396 | dsi_encs[i] = construct_encoder(mdp5_kms, INTF_DSI, | ||
397 | intf_num, mode, ctl); | ||
398 | if (IS_ERR(dsi_encs[i])) { | ||
399 | ret = PTR_ERR(dsi_encs[i]); | ||
400 | break; | ||
401 | } | ||
402 | } | 394 | } |
403 | 395 | ||
404 | ret = msm_dsi_modeset_init(priv->dsi[dsi_id], dev, dsi_encs); | 396 | ret = msm_dsi_modeset_init(priv->dsi[dsi_id], dev, encoder); |
405 | break; | 397 | break; |
406 | } | 398 | } |
407 | default: | 399 | default: |
@@ -418,20 +410,48 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) | |||
418 | struct drm_device *dev = mdp5_kms->dev; | 410 | struct drm_device *dev = mdp5_kms->dev; |
419 | struct msm_drm_private *priv = dev->dev_private; | 411 | struct msm_drm_private *priv = dev->dev_private; |
420 | const struct mdp5_cfg_hw *hw_cfg; | 412 | const struct mdp5_cfg_hw *hw_cfg; |
421 | int i, ret; | 413 | unsigned int num_crtcs; |
414 | int i, ret, pi = 0, ci = 0; | ||
415 | struct drm_plane *primary[MAX_BASES] = { NULL }; | ||
416 | struct drm_plane *cursor[MAX_BASES] = { NULL }; | ||
422 | 417 | ||
423 | hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); | 418 | hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); |
424 | 419 | ||
425 | /* Construct planes equaling the number of hw pipes, and CRTCs | 420 | /* |
426 | * for the N layer-mixers (LM). The first N planes become primary | 421 | * Construct encoders and modeset initialize connector devices |
422 | * for each external display interface. | ||
423 | */ | ||
424 | for (i = 0; i < ARRAY_SIZE(hw_cfg->intf.connect); i++) { | ||
425 | ret = modeset_init_intf(mdp5_kms, i); | ||
426 | if (ret) | ||
427 | goto fail; | ||
428 | } | ||
429 | |||
430 | /* | ||
431 | * We should ideally have less number of encoders (set up by parsing | ||
432 | * the MDP5 interfaces) than the number of layer mixers present in HW, | ||
433 | * but let's be safe here anyway | ||
434 | */ | ||
435 | num_crtcs = min(priv->num_encoders, mdp5_cfg->lm.count); | ||
436 | |||
437 | /* | ||
438 | * Construct planes equaling the number of hw pipes, and CRTCs for the | ||
439 | * N encoders set up by the driver. The first N planes become primary | ||
427 | * planes for the CRTCs, with the remainder as overlay planes: | 440 | * planes for the CRTCs, with the remainder as overlay planes: |
428 | */ | 441 | */ |
429 | for (i = 0; i < mdp5_kms->num_hwpipes; i++) { | 442 | for (i = 0; i < mdp5_kms->num_hwpipes; i++) { |
430 | bool primary = i < mdp5_cfg->lm.count; | 443 | struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i]; |
431 | struct drm_plane *plane; | 444 | struct drm_plane *plane; |
432 | struct drm_crtc *crtc; | 445 | enum drm_plane_type type; |
433 | 446 | ||
434 | plane = mdp5_plane_init(dev, primary); | 447 | if (i < num_crtcs) |
448 | type = DRM_PLANE_TYPE_PRIMARY; | ||
449 | else if (hwpipe->caps & MDP_PIPE_CAP_CURSOR) | ||
450 | type = DRM_PLANE_TYPE_CURSOR; | ||
451 | else | ||
452 | type = DRM_PLANE_TYPE_OVERLAY; | ||
453 | |||
454 | plane = mdp5_plane_init(dev, type); | ||
435 | if (IS_ERR(plane)) { | 455 | if (IS_ERR(plane)) { |
436 | ret = PTR_ERR(plane); | 456 | ret = PTR_ERR(plane); |
437 | dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret); | 457 | dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret); |
@@ -439,10 +459,16 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) | |||
439 | } | 459 | } |
440 | priv->planes[priv->num_planes++] = plane; | 460 | priv->planes[priv->num_planes++] = plane; |
441 | 461 | ||
442 | if (!primary) | 462 | if (type == DRM_PLANE_TYPE_PRIMARY) |
443 | continue; | 463 | primary[pi++] = plane; |
464 | if (type == DRM_PLANE_TYPE_CURSOR) | ||
465 | cursor[ci++] = plane; | ||
466 | } | ||
467 | |||
468 | for (i = 0; i < num_crtcs; i++) { | ||
469 | struct drm_crtc *crtc; | ||
444 | 470 | ||
445 | crtc = mdp5_crtc_init(dev, plane, i); | 471 | crtc = mdp5_crtc_init(dev, primary[i], cursor[i], i); |
446 | if (IS_ERR(crtc)) { | 472 | if (IS_ERR(crtc)) { |
447 | ret = PTR_ERR(crtc); | 473 | ret = PTR_ERR(crtc); |
448 | dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret); | 474 | dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret); |
@@ -451,13 +477,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) | |||
451 | priv->crtcs[priv->num_crtcs++] = crtc; | 477 | priv->crtcs[priv->num_crtcs++] = crtc; |
452 | } | 478 | } |
453 | 479 | ||
454 | /* Construct encoders and modeset initialize connector devices | 480 | /* |
455 | * for each external display interface. | 481 | * Now that we know the number of crtcs we've created, set the possible |
482 | * crtcs for the encoders | ||
456 | */ | 483 | */ |
457 | for (i = 0; i < ARRAY_SIZE(hw_cfg->intf.connect); i++) { | 484 | for (i = 0; i < priv->num_encoders; i++) { |
458 | ret = modeset_init_intf(mdp5_kms, i); | 485 | struct drm_encoder *encoder = priv->encoders[i]; |
459 | if (ret) | 486 | |
460 | goto fail; | 487 | encoder->possible_crtcs = (1 << priv->num_crtcs) - 1; |
461 | } | 488 | } |
462 | 489 | ||
463 | return 0; | 490 | return 0; |
@@ -773,6 +800,9 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms) | |||
773 | static const enum mdp5_pipe dma_planes[] = { | 800 | static const enum mdp5_pipe dma_planes[] = { |
774 | SSPP_DMA0, SSPP_DMA1, | 801 | SSPP_DMA0, SSPP_DMA1, |
775 | }; | 802 | }; |
803 | static const enum mdp5_pipe cursor_planes[] = { | ||
804 | SSPP_CURSOR0, SSPP_CURSOR1, | ||
805 | }; | ||
776 | const struct mdp5_cfg_hw *hw_cfg; | 806 | const struct mdp5_cfg_hw *hw_cfg; |
777 | int ret; | 807 | int ret; |
778 | 808 | ||
@@ -796,6 +826,13 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms) | |||
796 | if (ret) | 826 | if (ret) |
797 | return ret; | 827 | return ret; |
798 | 828 | ||
829 | /* Construct cursor pipes: */ | ||
830 | ret = construct_pipes(mdp5_kms, hw_cfg->pipe_cursor.count, | ||
831 | cursor_planes, hw_cfg->pipe_cursor.base, | ||
832 | hw_cfg->pipe_cursor.caps); | ||
833 | if (ret) | ||
834 | return ret; | ||
835 | |||
799 | return 0; | 836 | return 0; |
800 | } | 837 | } |
801 | 838 | ||