diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2016-09-30 12:37:36 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-10-25 14:38:06 -0400 |
commit | 66264ba80492571d9177158f2989e267a591507b (patch) | |
tree | d2a155d7ee14e5177e3bf1b170779809519a8d5c /drivers/gpu/drm | |
parent | 9405e47dbab33706c43caba72cf8d83b5746f843 (diff) |
drm/amdgpu: simplify encoder and connector setup (v2)
No need to emulate all of the stuff for real hw.
v2: warning fix
Reviewed-By: Emily Deng <Emily.Deng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 93 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 231 |
2 files changed, 144 insertions, 180 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index e3281d4e3e41..3af8ffb45b64 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | |||
@@ -1517,88 +1517,6 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = { | |||
1517 | .force = amdgpu_connector_dvi_force, | 1517 | .force = amdgpu_connector_dvi_force, |
1518 | }; | 1518 | }; |
1519 | 1519 | ||
1520 | static struct drm_encoder * | ||
1521 | amdgpu_connector_virtual_encoder(struct drm_connector *connector) | ||
1522 | { | ||
1523 | int enc_id = connector->encoder_ids[0]; | ||
1524 | struct drm_encoder *encoder; | ||
1525 | int i; | ||
1526 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
1527 | if (connector->encoder_ids[i] == 0) | ||
1528 | break; | ||
1529 | |||
1530 | encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); | ||
1531 | if (!encoder) | ||
1532 | continue; | ||
1533 | |||
1534 | if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) | ||
1535 | return encoder; | ||
1536 | } | ||
1537 | |||
1538 | /* pick the first one */ | ||
1539 | if (enc_id) | ||
1540 | return drm_encoder_find(connector->dev, enc_id); | ||
1541 | return NULL; | ||
1542 | } | ||
1543 | |||
1544 | static int amdgpu_connector_virtual_get_modes(struct drm_connector *connector) | ||
1545 | { | ||
1546 | struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector); | ||
1547 | |||
1548 | if (encoder) { | ||
1549 | amdgpu_connector_add_common_modes(encoder, connector); | ||
1550 | } | ||
1551 | |||
1552 | return 0; | ||
1553 | } | ||
1554 | |||
1555 | static int amdgpu_connector_virtual_mode_valid(struct drm_connector *connector, | ||
1556 | struct drm_display_mode *mode) | ||
1557 | { | ||
1558 | return MODE_OK; | ||
1559 | } | ||
1560 | |||
1561 | static int | ||
1562 | amdgpu_connector_virtual_dpms(struct drm_connector *connector, int mode) | ||
1563 | { | ||
1564 | return 0; | ||
1565 | } | ||
1566 | |||
1567 | static enum drm_connector_status | ||
1568 | |||
1569 | amdgpu_connector_virtual_detect(struct drm_connector *connector, bool force) | ||
1570 | { | ||
1571 | return connector_status_connected; | ||
1572 | } | ||
1573 | |||
1574 | static int | ||
1575 | amdgpu_connector_virtual_set_property(struct drm_connector *connector, | ||
1576 | struct drm_property *property, | ||
1577 | uint64_t val) | ||
1578 | { | ||
1579 | return 0; | ||
1580 | } | ||
1581 | |||
1582 | static void amdgpu_connector_virtual_force(struct drm_connector *connector) | ||
1583 | { | ||
1584 | return; | ||
1585 | } | ||
1586 | |||
1587 | static const struct drm_connector_helper_funcs amdgpu_connector_virtual_helper_funcs = { | ||
1588 | .get_modes = amdgpu_connector_virtual_get_modes, | ||
1589 | .mode_valid = amdgpu_connector_virtual_mode_valid, | ||
1590 | .best_encoder = amdgpu_connector_virtual_encoder, | ||
1591 | }; | ||
1592 | |||
1593 | static const struct drm_connector_funcs amdgpu_connector_virtual_funcs = { | ||
1594 | .dpms = amdgpu_connector_virtual_dpms, | ||
1595 | .detect = amdgpu_connector_virtual_detect, | ||
1596 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
1597 | .set_property = amdgpu_connector_virtual_set_property, | ||
1598 | .destroy = amdgpu_connector_destroy, | ||
1599 | .force = amdgpu_connector_virtual_force, | ||
1600 | }; | ||
1601 | |||
1602 | void | 1520 | void |
1603 | amdgpu_connector_add(struct amdgpu_device *adev, | 1521 | amdgpu_connector_add(struct amdgpu_device *adev, |
1604 | uint32_t connector_id, | 1522 | uint32_t connector_id, |
@@ -1983,17 +1901,6 @@ amdgpu_connector_add(struct amdgpu_device *adev, | |||
1983 | connector->interlace_allowed = false; | 1901 | connector->interlace_allowed = false; |
1984 | connector->doublescan_allowed = false; | 1902 | connector->doublescan_allowed = false; |
1985 | break; | 1903 | break; |
1986 | case DRM_MODE_CONNECTOR_VIRTUAL: | ||
1987 | amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL); | ||
1988 | if (!amdgpu_dig_connector) | ||
1989 | goto failed; | ||
1990 | amdgpu_connector->con_priv = amdgpu_dig_connector; | ||
1991 | drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_virtual_funcs, connector_type); | ||
1992 | drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_virtual_helper_funcs); | ||
1993 | subpixel_order = SubPixelHorizontalRGB; | ||
1994 | connector->interlace_allowed = false; | ||
1995 | connector->doublescan_allowed = false; | ||
1996 | break; | ||
1997 | } | 1904 | } |
1998 | } | 1905 | } |
1999 | 1906 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index bc8f5e332915..b981e769603b 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c | |||
@@ -39,6 +39,8 @@ | |||
39 | 39 | ||
40 | static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); | 40 | static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); |
41 | static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); | 41 | static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); |
42 | static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, | ||
43 | int index); | ||
42 | 44 | ||
43 | /** | 45 | /** |
44 | * dce_virtual_vblank_wait - vblank wait asic callback. | 46 | * dce_virtual_vblank_wait - vblank wait asic callback. |
@@ -274,24 +276,6 @@ static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc, | |||
274 | const struct drm_display_mode *mode, | 276 | const struct drm_display_mode *mode, |
275 | struct drm_display_mode *adjusted_mode) | 277 | struct drm_display_mode *adjusted_mode) |
276 | { | 278 | { |
277 | struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); | ||
278 | struct drm_device *dev = crtc->dev; | ||
279 | struct drm_encoder *encoder; | ||
280 | |||
281 | /* assign the encoder to the amdgpu crtc to avoid repeated lookups later */ | ||
282 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
283 | if (encoder->crtc == crtc) { | ||
284 | amdgpu_crtc->encoder = encoder; | ||
285 | amdgpu_crtc->connector = amdgpu_get_connector_for_encoder(encoder); | ||
286 | break; | ||
287 | } | ||
288 | } | ||
289 | if ((amdgpu_crtc->encoder == NULL) || (amdgpu_crtc->connector == NULL)) { | ||
290 | amdgpu_crtc->encoder = NULL; | ||
291 | amdgpu_crtc->connector = NULL; | ||
292 | return false; | ||
293 | } | ||
294 | |||
295 | return true; | 279 | return true; |
296 | } | 280 | } |
297 | 281 | ||
@@ -370,38 +354,120 @@ static int dce_virtual_early_init(void *handle) | |||
370 | return 0; | 354 | return 0; |
371 | } | 355 | } |
372 | 356 | ||
373 | static bool dce_virtual_get_connector_info(struct amdgpu_device *adev) | 357 | static struct drm_encoder * |
358 | dce_virtual_encoder(struct drm_connector *connector) | ||
374 | { | 359 | { |
375 | struct amdgpu_i2c_bus_rec ddc_bus; | 360 | int enc_id = connector->encoder_ids[0]; |
376 | struct amdgpu_router router; | 361 | struct drm_encoder *encoder; |
377 | struct amdgpu_hpd hpd; | 362 | int i; |
363 | |||
364 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
365 | if (connector->encoder_ids[i] == 0) | ||
366 | break; | ||
367 | |||
368 | encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); | ||
369 | if (!encoder) | ||
370 | continue; | ||
378 | 371 | ||
379 | /* look up gpio for ddc, hpd */ | 372 | if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) |
380 | ddc_bus.valid = false; | 373 | return encoder; |
381 | hpd.hpd = AMDGPU_HPD_NONE; | 374 | } |
382 | /* needed for aux chan transactions */ | ||
383 | ddc_bus.hpd = hpd.hpd; | ||
384 | 375 | ||
385 | memset(&router, 0, sizeof(router)); | 376 | /* pick the first one */ |
386 | router.ddc_valid = false; | 377 | if (enc_id) |
387 | router.cd_valid = false; | 378 | return drm_encoder_find(connector->dev, enc_id); |
388 | amdgpu_display_add_connector(adev, | 379 | return NULL; |
389 | 0, | 380 | } |
390 | ATOM_DEVICE_CRT1_SUPPORT, | 381 | |
391 | DRM_MODE_CONNECTOR_VIRTUAL, &ddc_bus, | 382 | static int dce_virtual_get_modes(struct drm_connector *connector) |
392 | CONNECTOR_OBJECT_ID_VIRTUAL, | 383 | { |
393 | &hpd, | 384 | struct drm_device *dev = connector->dev; |
394 | &router); | 385 | struct drm_display_mode *mode = NULL; |
386 | unsigned i; | ||
387 | static const struct mode_size { | ||
388 | int w; | ||
389 | int h; | ||
390 | } common_modes[17] = { | ||
391 | { 640, 480}, | ||
392 | { 720, 480}, | ||
393 | { 800, 600}, | ||
394 | { 848, 480}, | ||
395 | {1024, 768}, | ||
396 | {1152, 768}, | ||
397 | {1280, 720}, | ||
398 | {1280, 800}, | ||
399 | {1280, 854}, | ||
400 | {1280, 960}, | ||
401 | {1280, 1024}, | ||
402 | {1440, 900}, | ||
403 | {1400, 1050}, | ||
404 | {1680, 1050}, | ||
405 | {1600, 1200}, | ||
406 | {1920, 1080}, | ||
407 | {1920, 1200} | ||
408 | }; | ||
409 | |||
410 | for (i = 0; i < 17; i++) { | ||
411 | mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); | ||
412 | drm_mode_probed_add(connector, mode); | ||
413 | } | ||
395 | 414 | ||
396 | amdgpu_display_add_encoder(adev, ENCODER_VIRTUAL_ENUM_VIRTUAL, | 415 | return 0; |
397 | ATOM_DEVICE_CRT1_SUPPORT, | 416 | } |
398 | 0); | ||
399 | 417 | ||
400 | amdgpu_link_encoder_connector(adev->ddev); | 418 | static int dce_virtual_mode_valid(struct drm_connector *connector, |
419 | struct drm_display_mode *mode) | ||
420 | { | ||
421 | return MODE_OK; | ||
422 | } | ||
401 | 423 | ||
402 | return true; | 424 | static int |
425 | dce_virtual_dpms(struct drm_connector *connector, int mode) | ||
426 | { | ||
427 | return 0; | ||
403 | } | 428 | } |
404 | 429 | ||
430 | static enum drm_connector_status | ||
431 | dce_virtual_detect(struct drm_connector *connector, bool force) | ||
432 | { | ||
433 | return connector_status_connected; | ||
434 | } | ||
435 | |||
436 | static int | ||
437 | dce_virtual_set_property(struct drm_connector *connector, | ||
438 | struct drm_property *property, | ||
439 | uint64_t val) | ||
440 | { | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static void dce_virtual_destroy(struct drm_connector *connector) | ||
445 | { | ||
446 | drm_connector_unregister(connector); | ||
447 | drm_connector_cleanup(connector); | ||
448 | kfree(connector); | ||
449 | } | ||
450 | |||
451 | static void dce_virtual_force(struct drm_connector *connector) | ||
452 | { | ||
453 | return; | ||
454 | } | ||
455 | |||
456 | static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = { | ||
457 | .get_modes = dce_virtual_get_modes, | ||
458 | .mode_valid = dce_virtual_mode_valid, | ||
459 | .best_encoder = dce_virtual_encoder, | ||
460 | }; | ||
461 | |||
462 | static const struct drm_connector_funcs dce_virtual_connector_funcs = { | ||
463 | .dpms = dce_virtual_dpms, | ||
464 | .detect = dce_virtual_detect, | ||
465 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
466 | .set_property = dce_virtual_set_property, | ||
467 | .destroy = dce_virtual_destroy, | ||
468 | .force = dce_virtual_force, | ||
469 | }; | ||
470 | |||
405 | static int dce_virtual_sw_init(void *handle) | 471 | static int dce_virtual_sw_init(void *handle) |
406 | { | 472 | { |
407 | int r, i; | 473 | int r, i; |
@@ -430,16 +496,16 @@ static int dce_virtual_sw_init(void *handle) | |||
430 | adev->ddev->mode_config.max_width = 16384; | 496 | adev->ddev->mode_config.max_width = 16384; |
431 | adev->ddev->mode_config.max_height = 16384; | 497 | adev->ddev->mode_config.max_height = 16384; |
432 | 498 | ||
433 | /* allocate crtcs */ | 499 | /* allocate crtcs, encoders, connectors */ |
434 | for (i = 0; i < adev->mode_info.num_crtc; i++) { | 500 | for (i = 0; i < adev->mode_info.num_crtc; i++) { |
435 | r = dce_virtual_crtc_init(adev, i); | 501 | r = dce_virtual_crtc_init(adev, i); |
436 | if (r) | 502 | if (r) |
437 | return r; | 503 | return r; |
504 | r = dce_virtual_connector_encoder_init(adev, i); | ||
505 | if (r) | ||
506 | return r; | ||
438 | } | 507 | } |
439 | 508 | ||
440 | dce_virtual_get_connector_info(adev); | ||
441 | amdgpu_print_display_setup(adev->ddev); | ||
442 | |||
443 | drm_kms_helper_poll_init(adev->ddev); | 509 | drm_kms_helper_poll_init(adev->ddev); |
444 | 510 | ||
445 | adev->mode_info.mode_config_initialized = true; | 511 | adev->mode_info.mode_config_initialized = true; |
@@ -536,8 +602,8 @@ static void dce_virtual_encoder_commit(struct drm_encoder *encoder) | |||
536 | 602 | ||
537 | static void | 603 | static void |
538 | dce_virtual_encoder_mode_set(struct drm_encoder *encoder, | 604 | dce_virtual_encoder_mode_set(struct drm_encoder *encoder, |
539 | struct drm_display_mode *mode, | 605 | struct drm_display_mode *mode, |
540 | struct drm_display_mode *adjusted_mode) | 606 | struct drm_display_mode *adjusted_mode) |
541 | { | 607 | { |
542 | return; | 608 | return; |
543 | } | 609 | } |
@@ -557,10 +623,6 @@ static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder, | |||
557 | const struct drm_display_mode *mode, | 623 | const struct drm_display_mode *mode, |
558 | struct drm_display_mode *adjusted_mode) | 624 | struct drm_display_mode *adjusted_mode) |
559 | { | 625 | { |
560 | |||
561 | /* set the active encoder to connector routing */ | ||
562 | amdgpu_encoder_set_active_device(encoder); | ||
563 | |||
564 | return true; | 626 | return true; |
565 | } | 627 | } |
566 | 628 | ||
@@ -586,45 +648,40 @@ static const struct drm_encoder_funcs dce_virtual_encoder_funcs = { | |||
586 | .destroy = dce_virtual_encoder_destroy, | 648 | .destroy = dce_virtual_encoder_destroy, |
587 | }; | 649 | }; |
588 | 650 | ||
589 | static void dce_virtual_encoder_add(struct amdgpu_device *adev, | 651 | static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, |
590 | uint32_t encoder_enum, | 652 | int index) |
591 | uint32_t supported_device, | ||
592 | u16 caps) | ||
593 | { | 653 | { |
594 | struct drm_device *dev = adev->ddev; | ||
595 | struct drm_encoder *encoder; | 654 | struct drm_encoder *encoder; |
596 | struct amdgpu_encoder *amdgpu_encoder; | 655 | struct drm_connector *connector; |
597 | |||
598 | /* see if we already added it */ | ||
599 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
600 | amdgpu_encoder = to_amdgpu_encoder(encoder); | ||
601 | if (amdgpu_encoder->encoder_enum == encoder_enum) { | ||
602 | amdgpu_encoder->devices |= supported_device; | ||
603 | return; | ||
604 | } | ||
605 | 656 | ||
657 | /* add a new encoder */ | ||
658 | encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL); | ||
659 | if (!encoder) | ||
660 | return -ENOMEM; | ||
661 | encoder->possible_crtcs = 1 << index; | ||
662 | drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs, | ||
663 | DRM_MODE_ENCODER_VIRTUAL, NULL); | ||
664 | drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs); | ||
665 | |||
666 | connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL); | ||
667 | if (!connector) { | ||
668 | kfree(encoder); | ||
669 | return -ENOMEM; | ||
606 | } | 670 | } |
607 | 671 | ||
608 | /* add a new one */ | 672 | /* add a new connector */ |
609 | amdgpu_encoder = kzalloc(sizeof(struct amdgpu_encoder), GFP_KERNEL); | 673 | drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs, |
610 | if (!amdgpu_encoder) | 674 | DRM_MODE_CONNECTOR_VIRTUAL); |
611 | return; | 675 | drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs); |
676 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | ||
677 | connector->interlace_allowed = false; | ||
678 | connector->doublescan_allowed = false; | ||
679 | drm_connector_register(connector); | ||
612 | 680 | ||
613 | encoder = &amdgpu_encoder->base; | 681 | /* link them */ |
614 | encoder->possible_crtcs = 0x1; | 682 | drm_mode_connector_attach_encoder(connector, encoder); |
615 | amdgpu_encoder->enc_priv = NULL; | 683 | |
616 | amdgpu_encoder->encoder_enum = encoder_enum; | 684 | return 0; |
617 | amdgpu_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; | ||
618 | amdgpu_encoder->devices = supported_device; | ||
619 | amdgpu_encoder->rmx_type = RMX_OFF; | ||
620 | amdgpu_encoder->underscan_type = UNDERSCAN_OFF; | ||
621 | amdgpu_encoder->is_ext_encoder = false; | ||
622 | amdgpu_encoder->caps = caps; | ||
623 | |||
624 | drm_encoder_init(dev, encoder, &dce_virtual_encoder_funcs, | ||
625 | DRM_MODE_ENCODER_VIRTUAL, NULL); | ||
626 | drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs); | ||
627 | DRM_INFO("[FM]encoder: %d is VIRTUAL\n", amdgpu_encoder->encoder_id); | ||
628 | } | 685 | } |
629 | 686 | ||
630 | static const struct amdgpu_display_funcs dce_virtual_display_funcs = { | 687 | static const struct amdgpu_display_funcs dce_virtual_display_funcs = { |
@@ -640,8 +697,8 @@ static const struct amdgpu_display_funcs dce_virtual_display_funcs = { | |||
640 | .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg, | 697 | .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg, |
641 | .page_flip = &dce_virtual_page_flip, | 698 | .page_flip = &dce_virtual_page_flip, |
642 | .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos, | 699 | .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos, |
643 | .add_encoder = &dce_virtual_encoder_add, | 700 | .add_encoder = NULL, |
644 | .add_connector = &amdgpu_connector_add, | 701 | .add_connector = NULL, |
645 | .stop_mc_access = &dce_virtual_stop_mc_access, | 702 | .stop_mc_access = &dce_virtual_stop_mc_access, |
646 | .resume_mc_access = &dce_virtual_resume_mc_access, | 703 | .resume_mc_access = &dce_virtual_resume_mc_access, |
647 | }; | 704 | }; |