diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-01-12 17:54:34 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-02-08 18:44:02 -0500 |
commit | bcc1c2a1d22974215e39dc87ce746ba9a39223e5 (patch) | |
tree | 62ae9dfab266202240307fc3998806c1d4655552 /drivers/gpu/drm/radeon/atombios_crtc.c | |
parent | e97bd974448ce90f8e4720499d84580bcd6a2f7a (diff) |
drm/radeon/kms: add initial Evergreen support (Radeon HD 5xxx)
This adds initial Evergreen KMS support, it doesn't include
any acceleration features or interrupt handling yet.
Major changes are DCE4 handling for PLLs for the > 2 crtcs.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 370 |
1 files changed, 342 insertions, 28 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index bb45517719ae..7e7c0b32bb65 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -249,13 +249,17 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
249 | if (ASIC_IS_DCE3(rdev)) | 249 | if (ASIC_IS_DCE3(rdev)) |
250 | atombios_enable_crtc_memreq(crtc, 1); | 250 | atombios_enable_crtc_memreq(crtc, 1); |
251 | atombios_blank_crtc(crtc, 0); | 251 | atombios_blank_crtc(crtc, 0); |
252 | drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); | 252 | /* XXX re-enable when interrupt support is added */ |
253 | if (!ASIC_IS_DCE4(rdev)) | ||
254 | drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); | ||
253 | radeon_crtc_load_lut(crtc); | 255 | radeon_crtc_load_lut(crtc); |
254 | break; | 256 | break; |
255 | case DRM_MODE_DPMS_STANDBY: | 257 | case DRM_MODE_DPMS_STANDBY: |
256 | case DRM_MODE_DPMS_SUSPEND: | 258 | case DRM_MODE_DPMS_SUSPEND: |
257 | case DRM_MODE_DPMS_OFF: | 259 | case DRM_MODE_DPMS_OFF: |
258 | drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); | 260 | /* XXX re-enable when interrupt support is added */ |
261 | if (!ASIC_IS_DCE4(rdev)) | ||
262 | drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); | ||
259 | atombios_blank_crtc(crtc, 1); | 263 | atombios_blank_crtc(crtc, 1); |
260 | if (ASIC_IS_DCE3(rdev)) | 264 | if (ASIC_IS_DCE3(rdev)) |
261 | atombios_enable_crtc_memreq(crtc, 0); | 265 | atombios_enable_crtc_memreq(crtc, 0); |
@@ -367,6 +371,10 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) | |||
367 | uint16_t percentage = 0; | 371 | uint16_t percentage = 0; |
368 | uint8_t type = 0, step = 0, delay = 0, range = 0; | 372 | uint8_t type = 0, step = 0, delay = 0, range = 0; |
369 | 373 | ||
374 | /* XXX add ss support for DCE4 */ | ||
375 | if (ASIC_IS_DCE4(rdev)) | ||
376 | return; | ||
377 | |||
370 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 378 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
371 | if (encoder->crtc == crtc) { | 379 | if (encoder->crtc == crtc) { |
372 | radeon_encoder = to_radeon_encoder(encoder); | 380 | radeon_encoder = to_radeon_encoder(encoder); |
@@ -411,6 +419,7 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) | |||
411 | 419 | ||
412 | union adjust_pixel_clock { | 420 | union adjust_pixel_clock { |
413 | ADJUST_DISPLAY_PLL_PS_ALLOCATION v1; | 421 | ADJUST_DISPLAY_PLL_PS_ALLOCATION v1; |
422 | ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3; | ||
414 | }; | 423 | }; |
415 | 424 | ||
416 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, | 425 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, |
@@ -422,6 +431,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
422 | struct drm_encoder *encoder = NULL; | 431 | struct drm_encoder *encoder = NULL; |
423 | struct radeon_encoder *radeon_encoder = NULL; | 432 | struct radeon_encoder *radeon_encoder = NULL; |
424 | u32 adjusted_clock = mode->clock; | 433 | u32 adjusted_clock = mode->clock; |
434 | int encoder_mode = 0; | ||
425 | 435 | ||
426 | /* reset the pll flags */ | 436 | /* reset the pll flags */ |
427 | pll->flags = 0; | 437 | pll->flags = 0; |
@@ -459,6 +469,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
459 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 469 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
460 | if (encoder->crtc == crtc) { | 470 | if (encoder->crtc == crtc) { |
461 | radeon_encoder = to_radeon_encoder(encoder); | 471 | radeon_encoder = to_radeon_encoder(encoder); |
472 | encoder_mode = atombios_get_encoder_mode(encoder); | ||
462 | if (ASIC_IS_AVIVO(rdev)) { | 473 | if (ASIC_IS_AVIVO(rdev)) { |
463 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ | 474 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ |
464 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) | 475 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) |
@@ -484,14 +495,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
484 | */ | 495 | */ |
485 | if (ASIC_IS_DCE3(rdev)) { | 496 | if (ASIC_IS_DCE3(rdev)) { |
486 | union adjust_pixel_clock args; | 497 | union adjust_pixel_clock args; |
487 | struct radeon_encoder_atom_dig *dig; | ||
488 | u8 frev, crev; | 498 | u8 frev, crev; |
489 | int index; | 499 | int index; |
490 | 500 | ||
491 | if (!radeon_encoder->enc_priv) | ||
492 | return adjusted_clock; | ||
493 | dig = radeon_encoder->enc_priv; | ||
494 | |||
495 | index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); | 501 | index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); |
496 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, | 502 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, |
497 | &crev); | 503 | &crev); |
@@ -505,12 +511,51 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
505 | case 2: | 511 | case 2: |
506 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); | 512 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); |
507 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; | 513 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; |
508 | args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder); | 514 | args.v1.ucEncodeMode = encoder_mode; |
509 | 515 | ||
510 | atom_execute_table(rdev->mode_info.atom_context, | 516 | atom_execute_table(rdev->mode_info.atom_context, |
511 | index, (uint32_t *)&args); | 517 | index, (uint32_t *)&args); |
512 | adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; | 518 | adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; |
513 | break; | 519 | break; |
520 | case 3: | ||
521 | args.v3.sInput.usPixelClock = cpu_to_le16(mode->clock / 10); | ||
522 | args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; | ||
523 | args.v3.sInput.ucEncodeMode = encoder_mode; | ||
524 | args.v3.sInput.ucDispPllConfig = 0; | ||
525 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | ||
526 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
527 | |||
528 | if (encoder_mode == ATOM_ENCODER_MODE_DP) | ||
529 | args.v3.sInput.ucDispPllConfig |= | ||
530 | DISPPLL_CONFIG_COHERENT_MODE; | ||
531 | else { | ||
532 | if (dig->coherent_mode) | ||
533 | args.v3.sInput.ucDispPllConfig |= | ||
534 | DISPPLL_CONFIG_COHERENT_MODE; | ||
535 | if (mode->clock > 165000) | ||
536 | args.v3.sInput.ucDispPllConfig |= | ||
537 | DISPPLL_CONFIG_DUAL_LINK; | ||
538 | } | ||
539 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
540 | /* may want to enable SS on DP/eDP eventually */ | ||
541 | args.v3.sInput.ucDispPllConfig |= | ||
542 | DISPPLL_CONFIG_SS_ENABLE; | ||
543 | if (mode->clock > 165000) | ||
544 | args.v3.sInput.ucDispPllConfig |= | ||
545 | DISPPLL_CONFIG_DUAL_LINK; | ||
546 | } | ||
547 | atom_execute_table(rdev->mode_info.atom_context, | ||
548 | index, (uint32_t *)&args); | ||
549 | adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; | ||
550 | if (args.v3.sOutput.ucRefDiv) { | ||
551 | pll->flags |= RADEON_PLL_USE_REF_DIV; | ||
552 | pll->reference_div = args.v3.sOutput.ucRefDiv; | ||
553 | } | ||
554 | if (args.v3.sOutput.ucPostDiv) { | ||
555 | pll->flags |= RADEON_PLL_USE_POST_DIV; | ||
556 | pll->post_div = args.v3.sOutput.ucPostDiv; | ||
557 | } | ||
558 | break; | ||
514 | default: | 559 | default: |
515 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | 560 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); |
516 | return adjusted_clock; | 561 | return adjusted_clock; |
@@ -529,9 +574,47 @@ union set_pixel_clock { | |||
529 | PIXEL_CLOCK_PARAMETERS v1; | 574 | PIXEL_CLOCK_PARAMETERS v1; |
530 | PIXEL_CLOCK_PARAMETERS_V2 v2; | 575 | PIXEL_CLOCK_PARAMETERS_V2 v2; |
531 | PIXEL_CLOCK_PARAMETERS_V3 v3; | 576 | PIXEL_CLOCK_PARAMETERS_V3 v3; |
577 | PIXEL_CLOCK_PARAMETERS_V5 v5; | ||
532 | }; | 578 | }; |
533 | 579 | ||
534 | void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | 580 | static void atombios_crtc_set_dcpll(struct drm_crtc *crtc) |
581 | { | ||
582 | struct drm_device *dev = crtc->dev; | ||
583 | struct radeon_device *rdev = dev->dev_private; | ||
584 | u8 frev, crev; | ||
585 | int index; | ||
586 | union set_pixel_clock args; | ||
587 | |||
588 | memset(&args, 0, sizeof(args)); | ||
589 | |||
590 | index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); | ||
591 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, | ||
592 | &crev); | ||
593 | |||
594 | switch (frev) { | ||
595 | case 1: | ||
596 | switch (crev) { | ||
597 | case 5: | ||
598 | /* if the default dcpll clock is specified, | ||
599 | * SetPixelClock provides the dividers | ||
600 | */ | ||
601 | args.v5.ucCRTC = ATOM_CRTC_INVALID; | ||
602 | args.v5.usPixelClock = rdev->clock.default_dispclk; | ||
603 | args.v5.ucPpll = ATOM_DCPLL; | ||
604 | break; | ||
605 | default: | ||
606 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | ||
607 | return; | ||
608 | } | ||
609 | break; | ||
610 | default: | ||
611 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | ||
612 | return; | ||
613 | } | ||
614 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
615 | } | ||
616 | |||
617 | static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | ||
535 | { | 618 | { |
536 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 619 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
537 | struct drm_device *dev = crtc->dev; | 620 | struct drm_device *dev = crtc->dev; |
@@ -545,12 +628,14 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
545 | u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; | 628 | u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; |
546 | struct radeon_pll *pll; | 629 | struct radeon_pll *pll; |
547 | u32 adjusted_clock; | 630 | u32 adjusted_clock; |
631 | int encoder_mode = 0; | ||
548 | 632 | ||
549 | memset(&args, 0, sizeof(args)); | 633 | memset(&args, 0, sizeof(args)); |
550 | 634 | ||
551 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 635 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
552 | if (encoder->crtc == crtc) { | 636 | if (encoder->crtc == crtc) { |
553 | radeon_encoder = to_radeon_encoder(encoder); | 637 | radeon_encoder = to_radeon_encoder(encoder); |
638 | encoder_mode = atombios_get_encoder_mode(encoder); | ||
554 | break; | 639 | break; |
555 | } | 640 | } |
556 | } | 641 | } |
@@ -558,10 +643,18 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
558 | if (!radeon_encoder) | 643 | if (!radeon_encoder) |
559 | return; | 644 | return; |
560 | 645 | ||
561 | if (radeon_crtc->crtc_id == 0) | 646 | switch (radeon_crtc->pll_id) { |
647 | case ATOM_PPLL1: | ||
562 | pll = &rdev->clock.p1pll; | 648 | pll = &rdev->clock.p1pll; |
563 | else | 649 | break; |
650 | case ATOM_PPLL2: | ||
564 | pll = &rdev->clock.p2pll; | 651 | pll = &rdev->clock.p2pll; |
652 | break; | ||
653 | case ATOM_DCPLL: | ||
654 | case ATOM_PPLL_INVALID: | ||
655 | pll = &rdev->clock.dcpll; | ||
656 | break; | ||
657 | } | ||
565 | 658 | ||
566 | /* adjust pixel clock as needed */ | 659 | /* adjust pixel clock as needed */ |
567 | adjusted_clock = atombios_adjust_pll(crtc, mode, pll); | 660 | adjusted_clock = atombios_adjust_pll(crtc, mode, pll); |
@@ -582,8 +675,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
582 | args.v1.usFbDiv = cpu_to_le16(fb_div); | 675 | args.v1.usFbDiv = cpu_to_le16(fb_div); |
583 | args.v1.ucFracFbDiv = frac_fb_div; | 676 | args.v1.ucFracFbDiv = frac_fb_div; |
584 | args.v1.ucPostDiv = post_div; | 677 | args.v1.ucPostDiv = post_div; |
585 | args.v1.ucPpll = | 678 | args.v1.ucPpll = radeon_crtc->pll_id; |
586 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | ||
587 | args.v1.ucCRTC = radeon_crtc->crtc_id; | 679 | args.v1.ucCRTC = radeon_crtc->crtc_id; |
588 | args.v1.ucRefDivSrc = 1; | 680 | args.v1.ucRefDivSrc = 1; |
589 | break; | 681 | break; |
@@ -593,8 +685,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
593 | args.v2.usFbDiv = cpu_to_le16(fb_div); | 685 | args.v2.usFbDiv = cpu_to_le16(fb_div); |
594 | args.v2.ucFracFbDiv = frac_fb_div; | 686 | args.v2.ucFracFbDiv = frac_fb_div; |
595 | args.v2.ucPostDiv = post_div; | 687 | args.v2.ucPostDiv = post_div; |
596 | args.v2.ucPpll = | 688 | args.v2.ucPpll = radeon_crtc->pll_id; |
597 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | ||
598 | args.v2.ucCRTC = radeon_crtc->crtc_id; | 689 | args.v2.ucCRTC = radeon_crtc->crtc_id; |
599 | args.v2.ucRefDivSrc = 1; | 690 | args.v2.ucRefDivSrc = 1; |
600 | break; | 691 | break; |
@@ -604,12 +695,22 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
604 | args.v3.usFbDiv = cpu_to_le16(fb_div); | 695 | args.v3.usFbDiv = cpu_to_le16(fb_div); |
605 | args.v3.ucFracFbDiv = frac_fb_div; | 696 | args.v3.ucFracFbDiv = frac_fb_div; |
606 | args.v3.ucPostDiv = post_div; | 697 | args.v3.ucPostDiv = post_div; |
607 | args.v3.ucPpll = | 698 | args.v3.ucPpll = radeon_crtc->pll_id; |
608 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 699 | args.v3.ucMiscInfo = (radeon_crtc->pll_id << 2); |
609 | args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2); | ||
610 | args.v3.ucTransmitterId = radeon_encoder->encoder_id; | 700 | args.v3.ucTransmitterId = radeon_encoder->encoder_id; |
611 | args.v3.ucEncoderMode = | 701 | args.v3.ucEncoderMode = encoder_mode; |
612 | atombios_get_encoder_mode(encoder); | 702 | break; |
703 | case 5: | ||
704 | args.v5.ucCRTC = radeon_crtc->crtc_id; | ||
705 | args.v5.usPixelClock = cpu_to_le16(mode->clock / 10); | ||
706 | args.v5.ucRefDiv = ref_div; | ||
707 | args.v5.usFbDiv = cpu_to_le16(fb_div); | ||
708 | args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); | ||
709 | args.v5.ucPostDiv = post_div; | ||
710 | args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ | ||
711 | args.v5.ucTransmitterID = radeon_encoder->encoder_id; | ||
712 | args.v5.ucEncoderMode = encoder_mode; | ||
713 | args.v5.ucPpll = radeon_crtc->pll_id; | ||
613 | break; | 714 | break; |
614 | default: | 715 | default: |
615 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | 716 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); |
@@ -624,6 +725,140 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
624 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 725 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
625 | } | 726 | } |
626 | 727 | ||
728 | static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | ||
729 | struct drm_framebuffer *old_fb) | ||
730 | { | ||
731 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
732 | struct drm_device *dev = crtc->dev; | ||
733 | struct radeon_device *rdev = dev->dev_private; | ||
734 | struct radeon_framebuffer *radeon_fb; | ||
735 | struct drm_gem_object *obj; | ||
736 | struct radeon_bo *rbo; | ||
737 | uint64_t fb_location; | ||
738 | uint32_t fb_format, fb_pitch_pixels, tiling_flags; | ||
739 | int r; | ||
740 | |||
741 | /* no fb bound */ | ||
742 | if (!crtc->fb) { | ||
743 | DRM_DEBUG("No FB bound\n"); | ||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | radeon_fb = to_radeon_framebuffer(crtc->fb); | ||
748 | |||
749 | /* Pin framebuffer & get tilling informations */ | ||
750 | obj = radeon_fb->obj; | ||
751 | rbo = obj->driver_private; | ||
752 | r = radeon_bo_reserve(rbo, false); | ||
753 | if (unlikely(r != 0)) | ||
754 | return r; | ||
755 | r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); | ||
756 | if (unlikely(r != 0)) { | ||
757 | radeon_bo_unreserve(rbo); | ||
758 | return -EINVAL; | ||
759 | } | ||
760 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); | ||
761 | radeon_bo_unreserve(rbo); | ||
762 | |||
763 | switch (crtc->fb->bits_per_pixel) { | ||
764 | case 8: | ||
765 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) | | ||
766 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED)); | ||
767 | break; | ||
768 | case 15: | ||
769 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | | ||
770 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555)); | ||
771 | break; | ||
772 | case 16: | ||
773 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | | ||
774 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565)); | ||
775 | break; | ||
776 | case 24: | ||
777 | case 32: | ||
778 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | | ||
779 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888)); | ||
780 | break; | ||
781 | default: | ||
782 | DRM_ERROR("Unsupported screen depth %d\n", | ||
783 | crtc->fb->bits_per_pixel); | ||
784 | return -EINVAL; | ||
785 | } | ||
786 | |||
787 | switch (radeon_crtc->crtc_id) { | ||
788 | case 0: | ||
789 | WREG32(AVIVO_D1VGA_CONTROL, 0); | ||
790 | break; | ||
791 | case 1: | ||
792 | WREG32(AVIVO_D2VGA_CONTROL, 0); | ||
793 | break; | ||
794 | case 2: | ||
795 | WREG32(EVERGREEN_D3VGA_CONTROL, 0); | ||
796 | break; | ||
797 | case 3: | ||
798 | WREG32(EVERGREEN_D4VGA_CONTROL, 0); | ||
799 | break; | ||
800 | case 4: | ||
801 | WREG32(EVERGREEN_D5VGA_CONTROL, 0); | ||
802 | break; | ||
803 | case 5: | ||
804 | WREG32(EVERGREEN_D6VGA_CONTROL, 0); | ||
805 | break; | ||
806 | default: | ||
807 | break; | ||
808 | } | ||
809 | |||
810 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, | ||
811 | upper_32_bits(fb_location)); | ||
812 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, | ||
813 | upper_32_bits(fb_location)); | ||
814 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
815 | (u32)fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); | ||
816 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
817 | (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); | ||
818 | WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); | ||
819 | |||
820 | WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); | ||
821 | WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); | ||
822 | WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0); | ||
823 | WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0); | ||
824 | WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width); | ||
825 | WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height); | ||
826 | |||
827 | fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); | ||
828 | WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); | ||
829 | WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); | ||
830 | |||
831 | WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, | ||
832 | crtc->mode.vdisplay); | ||
833 | x &= ~3; | ||
834 | y &= ~1; | ||
835 | WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, | ||
836 | (x << 16) | y); | ||
837 | WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, | ||
838 | (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); | ||
839 | |||
840 | if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) | ||
841 | WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, | ||
842 | EVERGREEN_INTERLEAVE_EN); | ||
843 | else | ||
844 | WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0); | ||
845 | |||
846 | if (old_fb && old_fb != crtc->fb) { | ||
847 | radeon_fb = to_radeon_framebuffer(old_fb); | ||
848 | rbo = radeon_fb->obj->driver_private; | ||
849 | r = radeon_bo_reserve(rbo, false); | ||
850 | if (unlikely(r != 0)) | ||
851 | return r; | ||
852 | radeon_bo_unpin(rbo); | ||
853 | radeon_bo_unreserve(rbo); | ||
854 | } | ||
855 | |||
856 | /* Bytes per pixel may have changed */ | ||
857 | radeon_bandwidth_update(rdev); | ||
858 | |||
859 | return 0; | ||
860 | } | ||
861 | |||
627 | static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 862 | static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, |
628 | struct drm_framebuffer *old_fb) | 863 | struct drm_framebuffer *old_fb) |
629 | { | 864 | { |
@@ -761,7 +996,9 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
761 | struct drm_device *dev = crtc->dev; | 996 | struct drm_device *dev = crtc->dev; |
762 | struct radeon_device *rdev = dev->dev_private; | 997 | struct radeon_device *rdev = dev->dev_private; |
763 | 998 | ||
764 | if (ASIC_IS_AVIVO(rdev)) | 999 | if (ASIC_IS_DCE4(rdev)) |
1000 | return evergreen_crtc_set_base(crtc, x, y, old_fb); | ||
1001 | else if (ASIC_IS_AVIVO(rdev)) | ||
765 | return avivo_crtc_set_base(crtc, x, y, old_fb); | 1002 | return avivo_crtc_set_base(crtc, x, y, old_fb); |
766 | else | 1003 | else |
767 | return radeon_crtc_set_base(crtc, x, y, old_fb); | 1004 | return radeon_crtc_set_base(crtc, x, y, old_fb); |
@@ -791,6 +1028,46 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc) | |||
791 | } | 1028 | } |
792 | } | 1029 | } |
793 | 1030 | ||
1031 | static int radeon_atom_pick_pll(struct drm_crtc *crtc) | ||
1032 | { | ||
1033 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
1034 | struct drm_device *dev = crtc->dev; | ||
1035 | struct radeon_device *rdev = dev->dev_private; | ||
1036 | struct drm_encoder *test_encoder; | ||
1037 | struct drm_crtc *test_crtc; | ||
1038 | uint32_t pll_in_use = 0; | ||
1039 | |||
1040 | if (ASIC_IS_DCE4(rdev)) { | ||
1041 | /* if crtc is driving DP and we have an ext clock, use that */ | ||
1042 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { | ||
1043 | if (test_encoder->crtc && (test_encoder->crtc == crtc)) { | ||
1044 | if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) { | ||
1045 | if (rdev->clock.dp_extclk) | ||
1046 | return ATOM_PPLL_INVALID; | ||
1047 | } | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1051 | /* otherwise, pick one of the plls */ | ||
1052 | list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { | ||
1053 | struct radeon_crtc *radeon_test_crtc; | ||
1054 | |||
1055 | if (crtc == test_crtc) | ||
1056 | continue; | ||
1057 | |||
1058 | radeon_test_crtc = to_radeon_crtc(test_crtc); | ||
1059 | if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) && | ||
1060 | (radeon_test_crtc->pll_id <= ATOM_PPLL2)) | ||
1061 | pll_in_use |= (1 << radeon_test_crtc->pll_id); | ||
1062 | } | ||
1063 | if (!(pll_in_use & 1)) | ||
1064 | return ATOM_PPLL1; | ||
1065 | return ATOM_PPLL2; | ||
1066 | } else | ||
1067 | return radeon_crtc->crtc_id; | ||
1068 | |||
1069 | } | ||
1070 | |||
794 | int atombios_crtc_mode_set(struct drm_crtc *crtc, | 1071 | int atombios_crtc_mode_set(struct drm_crtc *crtc, |
795 | struct drm_display_mode *mode, | 1072 | struct drm_display_mode *mode, |
796 | struct drm_display_mode *adjusted_mode, | 1073 | struct drm_display_mode *adjusted_mode, |
@@ -802,19 +1079,27 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
802 | 1079 | ||
803 | /* TODO color tiling */ | 1080 | /* TODO color tiling */ |
804 | 1081 | ||
1082 | /* pick pll */ | ||
1083 | radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); | ||
1084 | |||
805 | atombios_set_ss(crtc, 0); | 1085 | atombios_set_ss(crtc, 0); |
1086 | /* always set DCPLL */ | ||
1087 | if (ASIC_IS_DCE4(rdev)) | ||
1088 | atombios_crtc_set_dcpll(crtc); | ||
806 | atombios_crtc_set_pll(crtc, adjusted_mode); | 1089 | atombios_crtc_set_pll(crtc, adjusted_mode); |
807 | atombios_set_ss(crtc, 1); | 1090 | atombios_set_ss(crtc, 1); |
808 | atombios_crtc_set_timing(crtc, adjusted_mode); | ||
809 | 1091 | ||
810 | if (ASIC_IS_AVIVO(rdev)) | 1092 | if (ASIC_IS_DCE4(rdev)) |
811 | atombios_crtc_set_base(crtc, x, y, old_fb); | 1093 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); |
1094 | else if (ASIC_IS_AVIVO(rdev)) | ||
1095 | atombios_crtc_set_timing(crtc, adjusted_mode); | ||
812 | else { | 1096 | else { |
1097 | atombios_crtc_set_timing(crtc, adjusted_mode); | ||
813 | if (radeon_crtc->crtc_id == 0) | 1098 | if (radeon_crtc->crtc_id == 0) |
814 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); | 1099 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); |
815 | atombios_crtc_set_base(crtc, x, y, old_fb); | ||
816 | radeon_legacy_atom_fixup(crtc); | 1100 | radeon_legacy_atom_fixup(crtc); |
817 | } | 1101 | } |
1102 | atombios_crtc_set_base(crtc, x, y, old_fb); | ||
818 | atombios_overscan_setup(crtc, mode, adjusted_mode); | 1103 | atombios_overscan_setup(crtc, mode, adjusted_mode); |
819 | atombios_scaler_setup(crtc); | 1104 | atombios_scaler_setup(crtc); |
820 | return 0; | 1105 | return 0; |
@@ -854,8 +1139,37 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = { | |||
854 | void radeon_atombios_init_crtc(struct drm_device *dev, | 1139 | void radeon_atombios_init_crtc(struct drm_device *dev, |
855 | struct radeon_crtc *radeon_crtc) | 1140 | struct radeon_crtc *radeon_crtc) |
856 | { | 1141 | { |
857 | if (radeon_crtc->crtc_id == 1) | 1142 | struct radeon_device *rdev = dev->dev_private; |
858 | radeon_crtc->crtc_offset = | 1143 | |
859 | AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; | 1144 | if (ASIC_IS_DCE4(rdev)) { |
1145 | switch (radeon_crtc->crtc_id) { | ||
1146 | case 0: | ||
1147 | default: | ||
1148 | radeon_crtc->crtc_id = EVERGREEN_CRTC0_REGISTER_OFFSET; | ||
1149 | break; | ||
1150 | case 1: | ||
1151 | radeon_crtc->crtc_id = EVERGREEN_CRTC1_REGISTER_OFFSET; | ||
1152 | break; | ||
1153 | case 2: | ||
1154 | radeon_crtc->crtc_id = EVERGREEN_CRTC2_REGISTER_OFFSET; | ||
1155 | break; | ||
1156 | case 3: | ||
1157 | radeon_crtc->crtc_id = EVERGREEN_CRTC3_REGISTER_OFFSET; | ||
1158 | break; | ||
1159 | case 4: | ||
1160 | radeon_crtc->crtc_id = EVERGREEN_CRTC4_REGISTER_OFFSET; | ||
1161 | break; | ||
1162 | case 5: | ||
1163 | radeon_crtc->crtc_id = EVERGREEN_CRTC5_REGISTER_OFFSET; | ||
1164 | break; | ||
1165 | } | ||
1166 | } else { | ||
1167 | if (radeon_crtc->crtc_id == 1) | ||
1168 | radeon_crtc->crtc_offset = | ||
1169 | AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; | ||
1170 | else | ||
1171 | radeon_crtc->crtc_offset = 0; | ||
1172 | } | ||
1173 | radeon_crtc->pll_id = -1; | ||
860 | drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); | 1174 | drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); |
861 | } | 1175 | } |