| .. | .. |
|---|
| 29 | 29 | #include <linux/pm_runtime.h> |
|---|
| 30 | 30 | #include <linux/vga_switcheroo.h> |
|---|
| 31 | 31 | |
|---|
| 32 | | -#include <drm/drmP.h> |
|---|
| 33 | 32 | #include <drm/drm_atomic_helper.h> |
|---|
| 34 | 33 | #include <drm/drm_edid.h> |
|---|
| 35 | 34 | #include <drm/drm_crtc_helper.h> |
|---|
| 35 | +#include <drm/drm_probe_helper.h> |
|---|
| 36 | 36 | #include <drm/drm_atomic.h> |
|---|
| 37 | 37 | |
|---|
| 38 | 38 | #include "nouveau_reg.h" |
|---|
| 39 | 39 | #include "nouveau_drv.h" |
|---|
| 40 | 40 | #include "dispnv04/hw.h" |
|---|
| 41 | +#include "dispnv50/disp.h" |
|---|
| 41 | 42 | #include "nouveau_acpi.h" |
|---|
| 42 | 43 | |
|---|
| 43 | 44 | #include "nouveau_display.h" |
|---|
| .. | .. |
|---|
| 59 | 60 | int high_w = 0, high_h = 0, high_v = 0; |
|---|
| 60 | 61 | |
|---|
| 61 | 62 | list_for_each_entry(mode, &connector->probed_modes, head) { |
|---|
| 62 | | - mode->vrefresh = drm_mode_vrefresh(mode); |
|---|
| 63 | 63 | if (helper->mode_valid(connector, mode) != MODE_OK || |
|---|
| 64 | 64 | (mode->flags & DRM_MODE_FLAG_INTERLACE)) |
|---|
| 65 | 65 | continue; |
|---|
| .. | .. |
|---|
| 80 | 80 | continue; |
|---|
| 81 | 81 | |
|---|
| 82 | 82 | if (mode->hdisplay == high_w && mode->vdisplay == high_h && |
|---|
| 83 | | - mode->vrefresh < high_v) |
|---|
| 83 | + drm_mode_vrefresh(mode) < high_v) |
|---|
| 84 | 84 | continue; |
|---|
| 85 | 85 | |
|---|
| 86 | 86 | high_w = mode->hdisplay; |
|---|
| 87 | 87 | high_h = mode->vdisplay; |
|---|
| 88 | | - high_v = mode->vrefresh; |
|---|
| 88 | + high_v = drm_mode_vrefresh(mode); |
|---|
| 89 | 89 | largest = mode; |
|---|
| 90 | 90 | } |
|---|
| 91 | 91 | |
|---|
| .. | .. |
|---|
| 245 | 245 | void |
|---|
| 246 | 246 | nouveau_conn_reset(struct drm_connector *connector) |
|---|
| 247 | 247 | { |
|---|
| 248 | + struct nouveau_connector *nv_connector = nouveau_connector(connector); |
|---|
| 248 | 249 | struct nouveau_conn_atom *asyc; |
|---|
| 249 | 250 | |
|---|
| 250 | | - if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL)))) |
|---|
| 251 | | - return; |
|---|
| 251 | + if (drm_drv_uses_atomic_modeset(connector->dev)) { |
|---|
| 252 | + if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL)))) |
|---|
| 253 | + return; |
|---|
| 252 | 254 | |
|---|
| 253 | | - if (connector->state) |
|---|
| 254 | | - nouveau_conn_atomic_destroy_state(connector, connector->state); |
|---|
| 255 | | - __drm_atomic_helper_connector_reset(connector, &asyc->state); |
|---|
| 255 | + if (connector->state) |
|---|
| 256 | + nouveau_conn_atomic_destroy_state(connector, |
|---|
| 257 | + connector->state); |
|---|
| 258 | + |
|---|
| 259 | + __drm_atomic_helper_connector_reset(connector, &asyc->state); |
|---|
| 260 | + } else { |
|---|
| 261 | + asyc = &nv_connector->properties_state; |
|---|
| 262 | + } |
|---|
| 263 | + |
|---|
| 256 | 264 | asyc->dither.mode = DITHERING_MODE_AUTO; |
|---|
| 257 | 265 | asyc->dither.depth = DITHERING_DEPTH_AUTO; |
|---|
| 258 | 266 | asyc->scaler.mode = DRM_MODE_SCALE_NONE; |
|---|
| .. | .. |
|---|
| 276 | 284 | nouveau_conn_attach_properties(struct drm_connector *connector) |
|---|
| 277 | 285 | { |
|---|
| 278 | 286 | struct drm_device *dev = connector->dev; |
|---|
| 279 | | - struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state); |
|---|
| 280 | 287 | struct nouveau_display *disp = nouveau_display(dev); |
|---|
| 288 | + struct nouveau_connector *nv_connector = nouveau_connector(connector); |
|---|
| 289 | + struct nouveau_conn_atom *armc; |
|---|
| 290 | + |
|---|
| 291 | + if (drm_drv_uses_atomic_modeset(connector->dev)) |
|---|
| 292 | + armc = nouveau_conn_atom(connector->state); |
|---|
| 293 | + else |
|---|
| 294 | + armc = &nv_connector->properties_state; |
|---|
| 281 | 295 | |
|---|
| 282 | 296 | /* Init DVI-I specific properties. */ |
|---|
| 283 | 297 | if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) |
|---|
| .. | .. |
|---|
| 316 | 330 | case DRM_MODE_CONNECTOR_VGA: |
|---|
| 317 | 331 | if (disp->disp.object.oclass < NV50_DISP) |
|---|
| 318 | 332 | break; /* Can only scale on DFPs. */ |
|---|
| 319 | | - /* Fall-through. */ |
|---|
| 333 | + fallthrough; |
|---|
| 320 | 334 | default: |
|---|
| 321 | 335 | drm_object_attach_property(&connector->base, dev->mode_config. |
|---|
| 322 | 336 | scaling_mode_property, |
|---|
| .. | .. |
|---|
| 365 | 379 | { |
|---|
| 366 | 380 | struct nouveau_encoder *nv_encoder; |
|---|
| 367 | 381 | struct drm_encoder *enc; |
|---|
| 368 | | - int i; |
|---|
| 369 | 382 | |
|---|
| 370 | | - drm_connector_for_each_possible_encoder(connector, enc, i) { |
|---|
| 383 | + drm_connector_for_each_possible_encoder(connector, enc) { |
|---|
| 371 | 384 | nv_encoder = nouveau_encoder(enc); |
|---|
| 372 | 385 | |
|---|
| 373 | 386 | if (type == DCB_OUTPUT_ANY || |
|---|
| .. | .. |
|---|
| 378 | 391 | return NULL; |
|---|
| 379 | 392 | } |
|---|
| 380 | 393 | |
|---|
| 381 | | -struct nouveau_connector * |
|---|
| 382 | | -nouveau_encoder_connector_get(struct nouveau_encoder *encoder) |
|---|
| 383 | | -{ |
|---|
| 384 | | - struct drm_device *dev = to_drm_encoder(encoder)->dev; |
|---|
| 385 | | - struct drm_connector *drm_connector; |
|---|
| 386 | | - |
|---|
| 387 | | - list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) { |
|---|
| 388 | | - if (drm_connector->encoder == to_drm_encoder(encoder)) |
|---|
| 389 | | - return nouveau_connector(drm_connector); |
|---|
| 390 | | - } |
|---|
| 391 | | - |
|---|
| 392 | | - return NULL; |
|---|
| 393 | | -} |
|---|
| 394 | | - |
|---|
| 395 | 394 | static void |
|---|
| 396 | 395 | nouveau_connector_destroy(struct drm_connector *connector) |
|---|
| 397 | 396 | { |
|---|
| 398 | 397 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
|---|
| 399 | | - nvif_notify_fini(&nv_connector->hpd); |
|---|
| 398 | + nvif_notify_dtor(&nv_connector->hpd); |
|---|
| 400 | 399 | kfree(nv_connector->edid); |
|---|
| 401 | 400 | drm_connector_unregister(connector); |
|---|
| 402 | 401 | drm_connector_cleanup(connector); |
|---|
| 403 | | - if (nv_connector->aux.transfer) |
|---|
| 402 | + if (nv_connector->aux.transfer) { |
|---|
| 403 | + drm_dp_cec_unregister_connector(&nv_connector->aux); |
|---|
| 404 | 404 | drm_dp_aux_unregister(&nv_connector->aux); |
|---|
| 405 | + kfree(nv_connector->aux.name); |
|---|
| 406 | + } |
|---|
| 405 | 407 | kfree(connector); |
|---|
| 406 | 408 | } |
|---|
| 407 | 409 | |
|---|
| .. | .. |
|---|
| 411 | 413 | struct drm_device *dev = connector->dev; |
|---|
| 412 | 414 | struct nouveau_encoder *nv_encoder = NULL, *found = NULL; |
|---|
| 413 | 415 | struct drm_encoder *encoder; |
|---|
| 414 | | - int i, ret; |
|---|
| 416 | + int ret; |
|---|
| 415 | 417 | bool switcheroo_ddc = false; |
|---|
| 416 | 418 | |
|---|
| 417 | | - drm_connector_for_each_possible_encoder(connector, encoder, i) { |
|---|
| 419 | + drm_connector_for_each_possible_encoder(connector, encoder) { |
|---|
| 418 | 420 | nv_encoder = nouveau_encoder(encoder); |
|---|
| 419 | 421 | |
|---|
| 420 | 422 | switch (nv_encoder->dcb->type) { |
|---|
| 421 | 423 | case DCB_OUTPUT_DP: |
|---|
| 422 | | - ret = nouveau_dp_detect(nv_encoder); |
|---|
| 424 | + ret = nouveau_dp_detect(nouveau_connector(connector), |
|---|
| 425 | + nv_encoder); |
|---|
| 423 | 426 | if (ret == NOUVEAU_DP_MST) |
|---|
| 424 | 427 | return NULL; |
|---|
| 425 | 428 | else if (ret == NOUVEAU_DP_SST) |
|---|
| .. | .. |
|---|
| 429 | 432 | case DCB_OUTPUT_LVDS: |
|---|
| 430 | 433 | switcheroo_ddc = !!(vga_switcheroo_handler_flags() & |
|---|
| 431 | 434 | VGA_SWITCHEROO_CAN_SWITCH_DDC); |
|---|
| 432 | | - /* fall-through */ |
|---|
| 435 | + fallthrough; |
|---|
| 433 | 436 | default: |
|---|
| 434 | 437 | if (!nv_encoder->i2c) |
|---|
| 435 | 438 | break; |
|---|
| .. | .. |
|---|
| 493 | 496 | nv_connector->detected_encoder = nv_encoder; |
|---|
| 494 | 497 | |
|---|
| 495 | 498 | if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { |
|---|
| 496 | | - connector->interlace_allowed = true; |
|---|
| 499 | + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) |
|---|
| 500 | + connector->interlace_allowed = |
|---|
| 501 | + nv_encoder->caps.dp_interlace; |
|---|
| 502 | + else |
|---|
| 503 | + connector->interlace_allowed = |
|---|
| 504 | + drm->client.device.info.family < NV_DEVICE_INFO_V0_VOLTA; |
|---|
| 497 | 505 | connector->doublescan_allowed = true; |
|---|
| 498 | 506 | } else |
|---|
| 499 | 507 | if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS || |
|---|
| .. | .. |
|---|
| 521 | 529 | } |
|---|
| 522 | 530 | } |
|---|
| 523 | 531 | |
|---|
| 532 | +static void |
|---|
| 533 | +nouveau_connector_set_edid(struct nouveau_connector *nv_connector, |
|---|
| 534 | + struct edid *edid) |
|---|
| 535 | +{ |
|---|
| 536 | + if (nv_connector->edid != edid) { |
|---|
| 537 | + struct edid *old_edid = nv_connector->edid; |
|---|
| 538 | + |
|---|
| 539 | + drm_connector_update_edid_property(&nv_connector->base, edid); |
|---|
| 540 | + kfree(old_edid); |
|---|
| 541 | + nv_connector->edid = edid; |
|---|
| 542 | + } |
|---|
| 543 | +} |
|---|
| 544 | + |
|---|
| 524 | 545 | static enum drm_connector_status |
|---|
| 525 | 546 | nouveau_connector_detect(struct drm_connector *connector, bool force) |
|---|
| 526 | 547 | { |
|---|
| .. | .. |
|---|
| 534 | 555 | int ret; |
|---|
| 535 | 556 | enum drm_connector_status conn_status = connector_status_disconnected; |
|---|
| 536 | 557 | |
|---|
| 537 | | - /* Cleanup the previous EDID block. */ |
|---|
| 538 | | - if (nv_connector->edid) { |
|---|
| 539 | | - drm_connector_update_edid_property(connector, NULL); |
|---|
| 540 | | - kfree(nv_connector->edid); |
|---|
| 541 | | - nv_connector->edid = NULL; |
|---|
| 542 | | - } |
|---|
| 543 | | - |
|---|
| 544 | 558 | /* Outputs are only polled while runtime active, so resuming the |
|---|
| 545 | 559 | * device here is unnecessary (and would deadlock upon runtime suspend |
|---|
| 546 | 560 | * because it waits for polling to finish). We do however, want to |
|---|
| .. | .. |
|---|
| 553 | 567 | ret = pm_runtime_get_sync(dev->dev); |
|---|
| 554 | 568 | if (ret < 0 && ret != -EACCES) { |
|---|
| 555 | 569 | pm_runtime_put_autosuspend(dev->dev); |
|---|
| 570 | + nouveau_connector_set_edid(nv_connector, NULL); |
|---|
| 556 | 571 | return conn_status; |
|---|
| 557 | 572 | } |
|---|
| 558 | 573 | } |
|---|
| 559 | 574 | |
|---|
| 560 | 575 | nv_encoder = nouveau_connector_ddc_detect(connector); |
|---|
| 561 | 576 | if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { |
|---|
| 577 | + struct edid *new_edid; |
|---|
| 578 | + |
|---|
| 562 | 579 | if ((vga_switcheroo_handler_flags() & |
|---|
| 563 | 580 | VGA_SWITCHEROO_CAN_SWITCH_DDC) && |
|---|
| 564 | 581 | nv_connector->type == DCB_CONNECTOR_LVDS) |
|---|
| 565 | | - nv_connector->edid = drm_get_edid_switcheroo(connector, |
|---|
| 566 | | - i2c); |
|---|
| 582 | + new_edid = drm_get_edid_switcheroo(connector, i2c); |
|---|
| 567 | 583 | else |
|---|
| 568 | | - nv_connector->edid = drm_get_edid(connector, i2c); |
|---|
| 584 | + new_edid = drm_get_edid(connector, i2c); |
|---|
| 569 | 585 | |
|---|
| 570 | | - drm_connector_update_edid_property(connector, |
|---|
| 571 | | - nv_connector->edid); |
|---|
| 586 | + nouveau_connector_set_edid(nv_connector, new_edid); |
|---|
| 572 | 587 | if (!nv_connector->edid) { |
|---|
| 573 | 588 | NV_ERROR(drm, "DDC responded, but no EDID for %s\n", |
|---|
| 574 | 589 | connector->name); |
|---|
| .. | .. |
|---|
| 600 | 615 | |
|---|
| 601 | 616 | nouveau_connector_set_encoder(connector, nv_encoder); |
|---|
| 602 | 617 | conn_status = connector_status_connected; |
|---|
| 618 | + drm_dp_cec_set_edid(&nv_connector->aux, nv_connector->edid); |
|---|
| 603 | 619 | goto out; |
|---|
| 620 | + } else { |
|---|
| 621 | + nouveau_connector_set_edid(nv_connector, NULL); |
|---|
| 604 | 622 | } |
|---|
| 605 | 623 | |
|---|
| 606 | 624 | nv_encoder = nouveau_connector_of_detect(connector); |
|---|
| .. | .. |
|---|
| 625 | 643 | conn_status = connector_status_connected; |
|---|
| 626 | 644 | goto out; |
|---|
| 627 | 645 | } |
|---|
| 628 | | - |
|---|
| 629 | 646 | } |
|---|
| 630 | 647 | |
|---|
| 631 | 648 | out: |
|---|
| 649 | + if (!nv_connector->edid) |
|---|
| 650 | + drm_dp_cec_unset_edid(&nv_connector->aux); |
|---|
| 632 | 651 | |
|---|
| 633 | 652 | pm_runtime_mark_last_busy(dev->dev); |
|---|
| 634 | 653 | pm_runtime_put_autosuspend(dev->dev); |
|---|
| .. | .. |
|---|
| 643 | 662 | struct nouveau_drm *drm = nouveau_drm(dev); |
|---|
| 644 | 663 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
|---|
| 645 | 664 | struct nouveau_encoder *nv_encoder = NULL; |
|---|
| 665 | + struct edid *edid = NULL; |
|---|
| 646 | 666 | enum drm_connector_status status = connector_status_disconnected; |
|---|
| 647 | | - |
|---|
| 648 | | - /* Cleanup the previous EDID block. */ |
|---|
| 649 | | - if (nv_connector->edid) { |
|---|
| 650 | | - drm_connector_update_edid_property(connector, NULL); |
|---|
| 651 | | - kfree(nv_connector->edid); |
|---|
| 652 | | - nv_connector->edid = NULL; |
|---|
| 653 | | - } |
|---|
| 654 | 667 | |
|---|
| 655 | 668 | nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); |
|---|
| 656 | 669 | if (!nv_encoder) |
|---|
| 657 | | - return connector_status_disconnected; |
|---|
| 670 | + goto out; |
|---|
| 658 | 671 | |
|---|
| 659 | 672 | /* Try retrieving EDID via DDC */ |
|---|
| 660 | 673 | if (!drm->vbios.fp_no_ddc) { |
|---|
| 661 | 674 | status = nouveau_connector_detect(connector, force); |
|---|
| 662 | | - if (status == connector_status_connected) |
|---|
| 675 | + if (status == connector_status_connected) { |
|---|
| 676 | + edid = nv_connector->edid; |
|---|
| 663 | 677 | goto out; |
|---|
| 678 | + } |
|---|
| 664 | 679 | } |
|---|
| 665 | 680 | |
|---|
| 666 | 681 | /* On some laptops (Sony, i'm looking at you) there appears to |
|---|
| .. | .. |
|---|
| 673 | 688 | * valid - it's not (rh#613284) |
|---|
| 674 | 689 | */ |
|---|
| 675 | 690 | if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { |
|---|
| 676 | | - if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) { |
|---|
| 691 | + edid = nouveau_acpi_edid(dev, connector); |
|---|
| 692 | + if (edid) { |
|---|
| 677 | 693 | status = connector_status_connected; |
|---|
| 678 | 694 | goto out; |
|---|
| 679 | 695 | } |
|---|
| .. | .. |
|---|
| 693 | 709 | * stored for the panel stored in them. |
|---|
| 694 | 710 | */ |
|---|
| 695 | 711 | if (!drm->vbios.fp_no_ddc) { |
|---|
| 696 | | - struct edid *edid = |
|---|
| 697 | | - (struct edid *)nouveau_bios_embedded_edid(dev); |
|---|
| 712 | + edid = (struct edid *)nouveau_bios_embedded_edid(dev); |
|---|
| 698 | 713 | if (edid) { |
|---|
| 699 | | - nv_connector->edid = |
|---|
| 700 | | - kmemdup(edid, EDID_LENGTH, GFP_KERNEL); |
|---|
| 701 | | - if (nv_connector->edid) |
|---|
| 714 | + edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); |
|---|
| 715 | + if (edid) |
|---|
| 702 | 716 | status = connector_status_connected; |
|---|
| 703 | 717 | } |
|---|
| 704 | 718 | } |
|---|
| .. | .. |
|---|
| 711 | 725 | status = connector_status_unknown; |
|---|
| 712 | 726 | #endif |
|---|
| 713 | 727 | |
|---|
| 714 | | - drm_connector_update_edid_property(connector, nv_connector->edid); |
|---|
| 728 | + nouveau_connector_set_edid(nv_connector, edid); |
|---|
| 715 | 729 | nouveau_connector_set_encoder(connector, nv_encoder); |
|---|
| 716 | 730 | return status; |
|---|
| 717 | 731 | } |
|---|
| .. | .. |
|---|
| 747 | 761 | nouveau_connector_set_property(struct drm_connector *connector, |
|---|
| 748 | 762 | struct drm_property *property, uint64_t value) |
|---|
| 749 | 763 | { |
|---|
| 750 | | - struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state); |
|---|
| 751 | 764 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
|---|
| 752 | 765 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
|---|
| 766 | + struct nouveau_conn_atom *asyc = &nv_connector->properties_state; |
|---|
| 753 | 767 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); |
|---|
| 754 | 768 | int ret; |
|---|
| 755 | 769 | |
|---|
| .. | .. |
|---|
| 885 | 899 | } |
|---|
| 886 | 900 | |
|---|
| 887 | 901 | static int |
|---|
| 902 | +nouveau_connector_late_register(struct drm_connector *connector) |
|---|
| 903 | +{ |
|---|
| 904 | + int ret; |
|---|
| 905 | + |
|---|
| 906 | + ret = nouveau_backlight_init(connector); |
|---|
| 907 | + |
|---|
| 908 | + return ret; |
|---|
| 909 | +} |
|---|
| 910 | + |
|---|
| 911 | +static void |
|---|
| 912 | +nouveau_connector_early_unregister(struct drm_connector *connector) |
|---|
| 913 | +{ |
|---|
| 914 | + nouveau_backlight_fini(connector); |
|---|
| 915 | +} |
|---|
| 916 | + |
|---|
| 917 | +static int |
|---|
| 888 | 918 | nouveau_connector_get_modes(struct drm_connector *connector) |
|---|
| 889 | 919 | { |
|---|
| 890 | 920 | struct drm_device *dev = connector->dev; |
|---|
| .. | .. |
|---|
| 952 | 982 | } |
|---|
| 953 | 983 | |
|---|
| 954 | 984 | static unsigned |
|---|
| 955 | | -get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi) |
|---|
| 985 | +get_tmds_link_bandwidth(struct drm_connector *connector) |
|---|
| 956 | 986 | { |
|---|
| 957 | 987 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
|---|
| 988 | + struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
|---|
| 958 | 989 | struct nouveau_drm *drm = nouveau_drm(connector->dev); |
|---|
| 959 | 990 | struct dcb_output *dcb = nv_connector->detected_encoder->dcb; |
|---|
| 991 | + struct drm_display_info *info = NULL; |
|---|
| 992 | + unsigned duallink_scale = |
|---|
| 993 | + nouveau_duallink && nv_encoder->dcb->duallink_possible ? 2 : 1; |
|---|
| 960 | 994 | |
|---|
| 961 | | - if (hdmi) { |
|---|
| 995 | + if (drm_detect_hdmi_monitor(nv_connector->edid)) { |
|---|
| 996 | + info = &nv_connector->base.display_info; |
|---|
| 997 | + duallink_scale = 1; |
|---|
| 998 | + } |
|---|
| 999 | + |
|---|
| 1000 | + if (info) { |
|---|
| 962 | 1001 | if (nouveau_hdmimhz > 0) |
|---|
| 963 | 1002 | return nouveau_hdmimhz * 1000; |
|---|
| 964 | 1003 | /* Note: these limits are conservative, some Fermi's |
|---|
| 965 | 1004 | * can do 297 MHz. Unclear how this can be determined. |
|---|
| 966 | 1005 | */ |
|---|
| 1006 | + if (drm->client.device.info.chipset >= 0x120) { |
|---|
| 1007 | + const int max_tmds_clock = |
|---|
| 1008 | + info->hdmi.scdc.scrambling.supported ? |
|---|
| 1009 | + 594000 : 340000; |
|---|
| 1010 | + return info->max_tmds_clock ? |
|---|
| 1011 | + min(info->max_tmds_clock, max_tmds_clock) : |
|---|
| 1012 | + max_tmds_clock; |
|---|
| 1013 | + } |
|---|
| 967 | 1014 | if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_KEPLER) |
|---|
| 968 | 1015 | return 297000; |
|---|
| 969 | 1016 | if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI) |
|---|
| 970 | 1017 | return 225000; |
|---|
| 971 | 1018 | } |
|---|
| 1019 | + |
|---|
| 972 | 1020 | if (dcb->location != DCB_LOC_ON_CHIP || |
|---|
| 973 | 1021 | drm->client.device.info.chipset >= 0x46) |
|---|
| 974 | | - return 165000; |
|---|
| 1022 | + return 165000 * duallink_scale; |
|---|
| 975 | 1023 | else if (drm->client.device.info.chipset >= 0x40) |
|---|
| 976 | | - return 155000; |
|---|
| 1024 | + return 155000 * duallink_scale; |
|---|
| 977 | 1025 | else if (drm->client.device.info.chipset >= 0x18) |
|---|
| 978 | | - return 135000; |
|---|
| 1026 | + return 135000 * duallink_scale; |
|---|
| 979 | 1027 | else |
|---|
| 980 | | - return 112000; |
|---|
| 1028 | + return 112000 * duallink_scale; |
|---|
| 981 | 1029 | } |
|---|
| 982 | 1030 | |
|---|
| 983 | 1031 | static enum drm_mode_status |
|---|
| .. | .. |
|---|
| 987 | 1035 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
|---|
| 988 | 1036 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
|---|
| 989 | 1037 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); |
|---|
| 990 | | - unsigned min_clock = 25000, max_clock = min_clock; |
|---|
| 991 | | - unsigned clock = mode->clock; |
|---|
| 992 | | - bool hdmi; |
|---|
| 1038 | + unsigned int min_clock = 25000, max_clock = min_clock, clock = mode->clock; |
|---|
| 993 | 1039 | |
|---|
| 994 | 1040 | switch (nv_encoder->dcb->type) { |
|---|
| 995 | 1041 | case DCB_OUTPUT_LVDS: |
|---|
| .. | .. |
|---|
| 1002 | 1048 | max_clock = 400000; |
|---|
| 1003 | 1049 | break; |
|---|
| 1004 | 1050 | case DCB_OUTPUT_TMDS: |
|---|
| 1005 | | - hdmi = drm_detect_hdmi_monitor(nv_connector->edid); |
|---|
| 1006 | | - max_clock = get_tmds_link_bandwidth(connector, hdmi); |
|---|
| 1007 | | - if (!hdmi && nouveau_duallink && |
|---|
| 1008 | | - nv_encoder->dcb->duallink_possible) |
|---|
| 1009 | | - max_clock *= 2; |
|---|
| 1051 | + max_clock = get_tmds_link_bandwidth(connector); |
|---|
| 1010 | 1052 | break; |
|---|
| 1011 | 1053 | case DCB_OUTPUT_ANALOG: |
|---|
| 1012 | 1054 | max_clock = nv_encoder->dcb->crtconf.maxfreq; |
|---|
| .. | .. |
|---|
| 1016 | 1058 | case DCB_OUTPUT_TV: |
|---|
| 1017 | 1059 | return get_slave_funcs(encoder)->mode_valid(encoder, mode); |
|---|
| 1018 | 1060 | case DCB_OUTPUT_DP: |
|---|
| 1019 | | - max_clock = nv_encoder->dp.link_nr; |
|---|
| 1020 | | - max_clock *= nv_encoder->dp.link_bw; |
|---|
| 1021 | | - clock = clock * (connector->display_info.bpc * 3) / 10; |
|---|
| 1022 | | - break; |
|---|
| 1061 | + return nv50_dp_mode_valid(connector, nv_encoder, mode, NULL); |
|---|
| 1023 | 1062 | default: |
|---|
| 1024 | 1063 | BUG(); |
|---|
| 1025 | 1064 | return MODE_BAD; |
|---|
| .. | .. |
|---|
| 1030 | 1069 | |
|---|
| 1031 | 1070 | if (clock < min_clock) |
|---|
| 1032 | 1071 | return MODE_CLOCK_LOW; |
|---|
| 1033 | | - |
|---|
| 1034 | 1072 | if (clock > max_clock) |
|---|
| 1035 | 1073 | return MODE_CLOCK_HIGH; |
|---|
| 1036 | 1074 | |
|---|
| .. | .. |
|---|
| 1068 | 1106 | .atomic_destroy_state = nouveau_conn_atomic_destroy_state, |
|---|
| 1069 | 1107 | .atomic_set_property = nouveau_conn_atomic_set_property, |
|---|
| 1070 | 1108 | .atomic_get_property = nouveau_conn_atomic_get_property, |
|---|
| 1109 | + .late_register = nouveau_connector_late_register, |
|---|
| 1110 | + .early_unregister = nouveau_connector_early_unregister, |
|---|
| 1071 | 1111 | }; |
|---|
| 1072 | 1112 | |
|---|
| 1073 | 1113 | static const struct drm_connector_funcs |
|---|
| .. | .. |
|---|
| 1083 | 1123 | .atomic_destroy_state = nouveau_conn_atomic_destroy_state, |
|---|
| 1084 | 1124 | .atomic_set_property = nouveau_conn_atomic_set_property, |
|---|
| 1085 | 1125 | .atomic_get_property = nouveau_conn_atomic_get_property, |
|---|
| 1126 | + .late_register = nouveau_connector_late_register, |
|---|
| 1127 | + .early_unregister = nouveau_connector_early_unregister, |
|---|
| 1086 | 1128 | }; |
|---|
| 1129 | + |
|---|
| 1130 | +void |
|---|
| 1131 | +nouveau_connector_hpd(struct drm_connector *connector) |
|---|
| 1132 | +{ |
|---|
| 1133 | + struct nouveau_drm *drm = nouveau_drm(connector->dev); |
|---|
| 1134 | + u32 mask = drm_connector_mask(connector); |
|---|
| 1135 | + |
|---|
| 1136 | + mutex_lock(&drm->hpd_lock); |
|---|
| 1137 | + if (!(drm->hpd_pending & mask)) { |
|---|
| 1138 | + drm->hpd_pending |= mask; |
|---|
| 1139 | + schedule_work(&drm->hpd_work); |
|---|
| 1140 | + } |
|---|
| 1141 | + mutex_unlock(&drm->hpd_lock); |
|---|
| 1142 | +} |
|---|
| 1087 | 1143 | |
|---|
| 1088 | 1144 | static int |
|---|
| 1089 | 1145 | nouveau_connector_hotplug(struct nvif_notify *notify) |
|---|
| .. | .. |
|---|
| 1091 | 1147 | struct nouveau_connector *nv_connector = |
|---|
| 1092 | 1148 | container_of(notify, typeof(*nv_connector), hpd); |
|---|
| 1093 | 1149 | struct drm_connector *connector = &nv_connector->base; |
|---|
| 1094 | | - struct nouveau_drm *drm = nouveau_drm(connector->dev); |
|---|
| 1150 | + struct drm_device *dev = connector->dev; |
|---|
| 1151 | + struct nouveau_drm *drm = nouveau_drm(dev); |
|---|
| 1095 | 1152 | const struct nvif_notify_conn_rep_v0 *rep = notify->data; |
|---|
| 1096 | | - const char *name = connector->name; |
|---|
| 1097 | | - struct nouveau_encoder *nv_encoder; |
|---|
| 1098 | | - int ret; |
|---|
| 1099 | | - |
|---|
| 1100 | | - ret = pm_runtime_get(drm->dev->dev); |
|---|
| 1101 | | - if (ret == 0) { |
|---|
| 1102 | | - /* We can't block here if there's a pending PM request |
|---|
| 1103 | | - * running, as we'll deadlock nouveau_display_fini() when it |
|---|
| 1104 | | - * calls nvif_put() on our nvif_notify struct. So, simply |
|---|
| 1105 | | - * defer the hotplug event until the device finishes resuming |
|---|
| 1106 | | - */ |
|---|
| 1107 | | - NV_DEBUG(drm, "Deferring HPD on %s until runtime resume\n", |
|---|
| 1108 | | - name); |
|---|
| 1109 | | - schedule_work(&drm->hpd_work); |
|---|
| 1110 | | - |
|---|
| 1111 | | - pm_runtime_put_noidle(drm->dev->dev); |
|---|
| 1112 | | - return NVIF_NOTIFY_KEEP; |
|---|
| 1113 | | - } else if (ret != 1 && ret != -EACCES) { |
|---|
| 1114 | | - NV_WARN(drm, "HPD on %s dropped due to RPM failure: %d\n", |
|---|
| 1115 | | - name, ret); |
|---|
| 1116 | | - return NVIF_NOTIFY_DROP; |
|---|
| 1117 | | - } |
|---|
| 1153 | + bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG); |
|---|
| 1118 | 1154 | |
|---|
| 1119 | 1155 | if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) { |
|---|
| 1120 | | - NV_DEBUG(drm, "service %s\n", name); |
|---|
| 1121 | | - if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) |
|---|
| 1122 | | - nv50_mstm_service(nv_encoder->dp.mstm); |
|---|
| 1123 | | - } else { |
|---|
| 1124 | | - bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG); |
|---|
| 1125 | | - |
|---|
| 1126 | | - NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); |
|---|
| 1127 | | - if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) { |
|---|
| 1128 | | - if (!plugged) |
|---|
| 1129 | | - nv50_mstm_remove(nv_encoder->dp.mstm); |
|---|
| 1130 | | - } |
|---|
| 1131 | | - |
|---|
| 1132 | | - drm_helper_hpd_irq_event(connector->dev); |
|---|
| 1156 | + nouveau_dp_irq(drm, nv_connector); |
|---|
| 1157 | + return NVIF_NOTIFY_KEEP; |
|---|
| 1133 | 1158 | } |
|---|
| 1134 | 1159 | |
|---|
| 1135 | | - pm_runtime_mark_last_busy(drm->dev->dev); |
|---|
| 1136 | | - pm_runtime_put_autosuspend(drm->dev->dev); |
|---|
| 1160 | + NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", connector->name); |
|---|
| 1161 | + nouveau_connector_hpd(connector); |
|---|
| 1162 | + |
|---|
| 1137 | 1163 | return NVIF_NOTIFY_KEEP; |
|---|
| 1138 | 1164 | } |
|---|
| 1139 | 1165 | |
|---|
| .. | .. |
|---|
| 1184 | 1210 | case DCB_CONNECTOR_LVDS_SPWG: return DRM_MODE_CONNECTOR_LVDS; |
|---|
| 1185 | 1211 | case DCB_CONNECTOR_DMS59_DP0: |
|---|
| 1186 | 1212 | case DCB_CONNECTOR_DMS59_DP1: |
|---|
| 1187 | | - case DCB_CONNECTOR_DP : return DRM_MODE_CONNECTOR_DisplayPort; |
|---|
| 1213 | + case DCB_CONNECTOR_DP : |
|---|
| 1214 | + case DCB_CONNECTOR_mDP : |
|---|
| 1215 | + case DCB_CONNECTOR_USB_C : return DRM_MODE_CONNECTOR_DisplayPort; |
|---|
| 1188 | 1216 | case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP; |
|---|
| 1189 | 1217 | case DCB_CONNECTOR_HDMI_0 : |
|---|
| 1190 | 1218 | case DCB_CONNECTOR_HDMI_1 : |
|---|
| .. | .. |
|---|
| 1198 | 1226 | } |
|---|
| 1199 | 1227 | |
|---|
| 1200 | 1228 | struct drm_connector * |
|---|
| 1201 | | -nouveau_connector_create(struct drm_device *dev, int index) |
|---|
| 1229 | +nouveau_connector_create(struct drm_device *dev, |
|---|
| 1230 | + const struct dcb_output *dcbe) |
|---|
| 1202 | 1231 | { |
|---|
| 1203 | 1232 | const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; |
|---|
| 1204 | 1233 | struct nouveau_drm *drm = nouveau_drm(dev); |
|---|
| .. | .. |
|---|
| 1206 | 1235 | struct nouveau_connector *nv_connector = NULL; |
|---|
| 1207 | 1236 | struct drm_connector *connector; |
|---|
| 1208 | 1237 | struct drm_connector_list_iter conn_iter; |
|---|
| 1238 | + char aux_name[48] = {0}; |
|---|
| 1239 | + int index = dcbe->connector; |
|---|
| 1209 | 1240 | int type, ret = 0; |
|---|
| 1210 | 1241 | bool dummy; |
|---|
| 1211 | 1242 | |
|---|
| .. | .. |
|---|
| 1306 | 1337 | break; |
|---|
| 1307 | 1338 | case DRM_MODE_CONNECTOR_DisplayPort: |
|---|
| 1308 | 1339 | case DRM_MODE_CONNECTOR_eDP: |
|---|
| 1309 | | - nv_connector->aux.dev = dev->dev; |
|---|
| 1340 | + nv_connector->aux.dev = connector->kdev; |
|---|
| 1310 | 1341 | nv_connector->aux.transfer = nouveau_connector_aux_xfer; |
|---|
| 1342 | + snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x", |
|---|
| 1343 | + dcbe->hasht, dcbe->hashm); |
|---|
| 1344 | + nv_connector->aux.name = kstrdup(aux_name, GFP_KERNEL); |
|---|
| 1311 | 1345 | ret = drm_dp_aux_register(&nv_connector->aux); |
|---|
| 1312 | 1346 | if (ret) { |
|---|
| 1313 | 1347 | NV_ERROR(drm, "failed to register aux channel\n"); |
|---|
| 1314 | 1348 | kfree(nv_connector); |
|---|
| 1315 | 1349 | return ERR_PTR(ret); |
|---|
| 1316 | 1350 | } |
|---|
| 1317 | | - |
|---|
| 1318 | 1351 | funcs = &nouveau_connector_funcs; |
|---|
| 1319 | 1352 | break; |
|---|
| 1320 | 1353 | default: |
|---|
| .. | .. |
|---|
| 1368 | 1401 | break; |
|---|
| 1369 | 1402 | } |
|---|
| 1370 | 1403 | |
|---|
| 1371 | | - ret = nvif_notify_init(&disp->disp.object, nouveau_connector_hotplug, |
|---|
| 1404 | + switch (type) { |
|---|
| 1405 | + case DRM_MODE_CONNECTOR_DisplayPort: |
|---|
| 1406 | + case DRM_MODE_CONNECTOR_eDP: |
|---|
| 1407 | + drm_dp_cec_register_connector(&nv_connector->aux, connector); |
|---|
| 1408 | + break; |
|---|
| 1409 | + } |
|---|
| 1410 | + |
|---|
| 1411 | + ret = nvif_notify_ctor(&disp->disp.object, "kmsHotplug", |
|---|
| 1412 | + nouveau_connector_hotplug, |
|---|
| 1372 | 1413 | true, NV04_DISP_NTFY_CONN, |
|---|
| 1373 | 1414 | &(struct nvif_notify_conn_req_v0) { |
|---|
| 1374 | 1415 | .mask = NVIF_NOTIFY_CONN_V0_ANY, |
|---|