diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/gpu/drm/radeon/atombios_crtc.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 636 |
1 files changed, 458 insertions, 178 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index cd0290f946cf..9541995e4b21 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -48,29 +48,29 @@ static void atombios_overscan_setup(struct drm_crtc *crtc, | |||
48 | 48 | ||
49 | switch (radeon_crtc->rmx_type) { | 49 | switch (radeon_crtc->rmx_type) { |
50 | case RMX_CENTER: | 50 | case RMX_CENTER: |
51 | args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; | 51 | args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2); |
52 | args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; | 52 | args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2); |
53 | args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; | 53 | args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2); |
54 | args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; | 54 | args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2); |
55 | break; | 55 | break; |
56 | case RMX_ASPECT: | 56 | case RMX_ASPECT: |
57 | a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay; | 57 | a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay; |
58 | a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay; | 58 | a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay; |
59 | 59 | ||
60 | if (a1 > a2) { | 60 | if (a1 > a2) { |
61 | args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; | 61 | args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); |
62 | args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; | 62 | args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); |
63 | } else if (a2 > a1) { | 63 | } else if (a2 > a1) { |
64 | args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; | 64 | args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); |
65 | args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; | 65 | args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); |
66 | } | 66 | } |
67 | break; | 67 | break; |
68 | case RMX_FULL: | 68 | case RMX_FULL: |
69 | default: | 69 | default: |
70 | args.usOverscanRight = radeon_crtc->h_border; | 70 | args.usOverscanRight = cpu_to_le16(radeon_crtc->h_border); |
71 | args.usOverscanLeft = radeon_crtc->h_border; | 71 | args.usOverscanLeft = cpu_to_le16(radeon_crtc->h_border); |
72 | args.usOverscanBottom = radeon_crtc->v_border; | 72 | args.usOverscanBottom = cpu_to_le16(radeon_crtc->v_border); |
73 | args.usOverscanTop = radeon_crtc->v_border; | 73 | args.usOverscanTop = cpu_to_le16(radeon_crtc->v_border); |
74 | break; | 74 | break; |
75 | } | 75 | } |
76 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 76 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
@@ -253,7 +253,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
253 | case DRM_MODE_DPMS_SUSPEND: | 253 | case DRM_MODE_DPMS_SUSPEND: |
254 | case DRM_MODE_DPMS_OFF: | 254 | case DRM_MODE_DPMS_OFF: |
255 | drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); | 255 | drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); |
256 | atombios_blank_crtc(crtc, ATOM_ENABLE); | 256 | if (radeon_crtc->enabled) |
257 | atombios_blank_crtc(crtc, ATOM_ENABLE); | ||
257 | if (ASIC_IS_DCE3(rdev)) | 258 | if (ASIC_IS_DCE3(rdev)) |
258 | atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); | 259 | atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); |
259 | atombios_enable_crtc(crtc, ATOM_DISABLE); | 260 | atombios_enable_crtc(crtc, ATOM_DISABLE); |
@@ -398,65 +399,106 @@ static void atombios_disable_ss(struct drm_crtc *crtc) | |||
398 | 399 | ||
399 | 400 | ||
400 | union atom_enable_ss { | 401 | union atom_enable_ss { |
401 | ENABLE_LVDS_SS_PARAMETERS legacy; | 402 | ENABLE_LVDS_SS_PARAMETERS lvds_ss; |
403 | ENABLE_LVDS_SS_PARAMETERS_V2 lvds_ss_2; | ||
402 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1; | 404 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1; |
405 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 v2; | ||
406 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3; | ||
403 | }; | 407 | }; |
404 | 408 | ||
405 | static void atombios_enable_ss(struct drm_crtc *crtc) | 409 | static void atombios_crtc_program_ss(struct drm_crtc *crtc, |
410 | int enable, | ||
411 | int pll_id, | ||
412 | struct radeon_atom_ss *ss) | ||
406 | { | 413 | { |
407 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
408 | struct drm_device *dev = crtc->dev; | 414 | struct drm_device *dev = crtc->dev; |
409 | struct radeon_device *rdev = dev->dev_private; | 415 | struct radeon_device *rdev = dev->dev_private; |
410 | struct drm_encoder *encoder = NULL; | ||
411 | struct radeon_encoder *radeon_encoder = NULL; | ||
412 | struct radeon_encoder_atom_dig *dig = NULL; | ||
413 | int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); | 416 | int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); |
414 | union atom_enable_ss args; | 417 | union atom_enable_ss args; |
415 | uint16_t percentage = 0; | ||
416 | uint8_t type = 0, step = 0, delay = 0, range = 0; | ||
417 | 418 | ||
418 | /* XXX add ss support for DCE4 */ | 419 | memset(&args, 0, sizeof(args)); |
419 | if (ASIC_IS_DCE4(rdev)) | ||
420 | return; | ||
421 | 420 | ||
422 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 421 | if (ASIC_IS_DCE5(rdev)) { |
423 | if (encoder->crtc == crtc) { | 422 | args.v3.usSpreadSpectrumAmountFrac = cpu_to_le16(0); |
424 | radeon_encoder = to_radeon_encoder(encoder); | 423 | args.v3.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; |
425 | /* only enable spread spectrum on LVDS */ | 424 | switch (pll_id) { |
426 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 425 | case ATOM_PPLL1: |
427 | dig = radeon_encoder->enc_priv; | 426 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; |
428 | if (dig && dig->ss) { | 427 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); |
429 | percentage = dig->ss->percentage; | 428 | args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); |
430 | type = dig->ss->type; | 429 | break; |
431 | step = dig->ss->step; | 430 | case ATOM_PPLL2: |
432 | delay = dig->ss->delay; | 431 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL; |
433 | range = dig->ss->range; | 432 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); |
434 | } else | 433 | args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); |
435 | return; | 434 | break; |
436 | } else | 435 | case ATOM_DCPLL: |
437 | return; | 436 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL; |
437 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(0); | ||
438 | args.v3.usSpreadSpectrumStep = cpu_to_le16(0); | ||
438 | break; | 439 | break; |
440 | case ATOM_PPLL_INVALID: | ||
441 | return; | ||
439 | } | 442 | } |
440 | } | 443 | args.v3.ucEnable = enable; |
441 | 444 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK)) | |
442 | if (!radeon_encoder) | 445 | args.v3.ucEnable = ATOM_DISABLE; |
443 | return; | 446 | } else if (ASIC_IS_DCE4(rdev)) { |
444 | 447 | args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); | |
445 | memset(&args, 0, sizeof(args)); | 448 | args.v2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; |
446 | if (ASIC_IS_AVIVO(rdev)) { | 449 | switch (pll_id) { |
447 | args.v1.usSpreadSpectrumPercentage = cpu_to_le16(percentage); | 450 | case ATOM_PPLL1: |
448 | args.v1.ucSpreadSpectrumType = type; | 451 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; |
449 | args.v1.ucSpreadSpectrumStep = step; | 452 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); |
450 | args.v1.ucSpreadSpectrumDelay = delay; | 453 | args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); |
451 | args.v1.ucSpreadSpectrumRange = range; | 454 | break; |
452 | args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 455 | case ATOM_PPLL2: |
453 | args.v1.ucEnable = ATOM_ENABLE; | 456 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL; |
457 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
458 | args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
459 | break; | ||
460 | case ATOM_DCPLL: | ||
461 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL; | ||
462 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(0); | ||
463 | args.v2.usSpreadSpectrumStep = cpu_to_le16(0); | ||
464 | break; | ||
465 | case ATOM_PPLL_INVALID: | ||
466 | return; | ||
467 | } | ||
468 | args.v2.ucEnable = enable; | ||
469 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK)) | ||
470 | args.v2.ucEnable = ATOM_DISABLE; | ||
471 | } else if (ASIC_IS_DCE3(rdev)) { | ||
472 | args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); | ||
473 | args.v1.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; | ||
474 | args.v1.ucSpreadSpectrumStep = ss->step; | ||
475 | args.v1.ucSpreadSpectrumDelay = ss->delay; | ||
476 | args.v1.ucSpreadSpectrumRange = ss->range; | ||
477 | args.v1.ucPpll = pll_id; | ||
478 | args.v1.ucEnable = enable; | ||
479 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
480 | if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || | ||
481 | (ss->type & ATOM_EXTERNAL_SS_MASK)) { | ||
482 | atombios_disable_ss(crtc); | ||
483 | return; | ||
484 | } | ||
485 | args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); | ||
486 | args.lvds_ss_2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; | ||
487 | args.lvds_ss_2.ucSpreadSpectrumStep = ss->step; | ||
488 | args.lvds_ss_2.ucSpreadSpectrumDelay = ss->delay; | ||
489 | args.lvds_ss_2.ucSpreadSpectrumRange = ss->range; | ||
490 | args.lvds_ss_2.ucEnable = enable; | ||
454 | } else { | 491 | } else { |
455 | args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage); | 492 | if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || |
456 | args.legacy.ucSpreadSpectrumType = type; | 493 | (ss->type & ATOM_EXTERNAL_SS_MASK)) { |
457 | args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2; | 494 | atombios_disable_ss(crtc); |
458 | args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4; | 495 | return; |
459 | args.legacy.ucEnable = ATOM_ENABLE; | 496 | } |
497 | args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); | ||
498 | args.lvds_ss.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; | ||
499 | args.lvds_ss.ucSpreadSpectrumStepSize_Delay = (ss->step & 3) << 2; | ||
500 | args.lvds_ss.ucSpreadSpectrumStepSize_Delay |= (ss->delay & 7) << 4; | ||
501 | args.lvds_ss.ucEnable = enable; | ||
460 | } | 502 | } |
461 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 503 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
462 | } | 504 | } |
@@ -468,12 +510,15 @@ union adjust_pixel_clock { | |||
468 | 510 | ||
469 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, | 511 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, |
470 | struct drm_display_mode *mode, | 512 | struct drm_display_mode *mode, |
471 | struct radeon_pll *pll) | 513 | struct radeon_pll *pll, |
514 | bool ss_enabled, | ||
515 | struct radeon_atom_ss *ss) | ||
472 | { | 516 | { |
473 | struct drm_device *dev = crtc->dev; | 517 | struct drm_device *dev = crtc->dev; |
474 | struct radeon_device *rdev = dev->dev_private; | 518 | struct radeon_device *rdev = dev->dev_private; |
475 | struct drm_encoder *encoder = NULL; | 519 | struct drm_encoder *encoder = NULL; |
476 | struct radeon_encoder *radeon_encoder = NULL; | 520 | struct radeon_encoder *radeon_encoder = NULL; |
521 | struct drm_connector *connector = NULL; | ||
477 | u32 adjusted_clock = mode->clock; | 522 | u32 adjusted_clock = mode->clock; |
478 | int encoder_mode = 0; | 523 | int encoder_mode = 0; |
479 | u32 dp_clock = mode->clock; | 524 | u32 dp_clock = mode->clock; |
@@ -482,19 +527,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
482 | /* reset the pll flags */ | 527 | /* reset the pll flags */ |
483 | pll->flags = 0; | 528 | pll->flags = 0; |
484 | 529 | ||
485 | /* select the PLL algo */ | ||
486 | if (ASIC_IS_AVIVO(rdev)) { | ||
487 | if (radeon_new_pll == 0) | ||
488 | pll->algo = PLL_ALGO_LEGACY; | ||
489 | else | ||
490 | pll->algo = PLL_ALGO_NEW; | ||
491 | } else { | ||
492 | if (radeon_new_pll == 1) | ||
493 | pll->algo = PLL_ALGO_NEW; | ||
494 | else | ||
495 | pll->algo = PLL_ALGO_LEGACY; | ||
496 | } | ||
497 | |||
498 | if (ASIC_IS_AVIVO(rdev)) { | 530 | if (ASIC_IS_AVIVO(rdev)) { |
499 | if ((rdev->family == CHIP_RS600) || | 531 | if ((rdev->family == CHIP_RS600) || |
500 | (rdev->family == CHIP_RS690) || | 532 | (rdev->family == CHIP_RS690) || |
@@ -506,6 +538,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
506 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | 538 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
507 | else | 539 | else |
508 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | 540 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; |
541 | |||
542 | if (rdev->family < CHIP_RV770) | ||
543 | pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP; | ||
509 | } else { | 544 | } else { |
510 | pll->flags |= RADEON_PLL_LEGACY; | 545 | pll->flags |= RADEON_PLL_LEGACY; |
511 | 546 | ||
@@ -513,15 +548,17 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
513 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | 548 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
514 | else | 549 | else |
515 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | 550 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; |
516 | |||
517 | } | 551 | } |
518 | 552 | ||
519 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 553 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
520 | if (encoder->crtc == crtc) { | 554 | if (encoder->crtc == crtc) { |
521 | radeon_encoder = to_radeon_encoder(encoder); | 555 | radeon_encoder = to_radeon_encoder(encoder); |
556 | connector = radeon_get_connector_for_encoder(encoder); | ||
557 | if (connector) | ||
558 | bpc = connector->display_info.bpc; | ||
522 | encoder_mode = atombios_get_encoder_mode(encoder); | 559 | encoder_mode = atombios_get_encoder_mode(encoder); |
523 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) { | 560 | if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || |
524 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | 561 | radeon_encoder_is_dp_bridge(encoder)) { |
525 | if (connector) { | 562 | if (connector) { |
526 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 563 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
527 | struct radeon_connector_atom_dig *dig_connector = | 564 | struct radeon_connector_atom_dig *dig_connector = |
@@ -531,29 +568,26 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
531 | } | 568 | } |
532 | } | 569 | } |
533 | 570 | ||
571 | /* use recommended ref_div for ss */ | ||
572 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
573 | if (ss_enabled) { | ||
574 | if (ss->refdiv) { | ||
575 | pll->flags |= RADEON_PLL_USE_REF_DIV; | ||
576 | pll->reference_div = ss->refdiv; | ||
577 | if (ASIC_IS_AVIVO(rdev)) | ||
578 | pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV; | ||
579 | } | ||
580 | } | ||
581 | } | ||
582 | |||
534 | if (ASIC_IS_AVIVO(rdev)) { | 583 | if (ASIC_IS_AVIVO(rdev)) { |
535 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ | 584 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ |
536 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) | 585 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) |
537 | adjusted_clock = mode->clock * 2; | 586 | adjusted_clock = mode->clock * 2; |
538 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { | 587 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
539 | pll->algo = PLL_ALGO_LEGACY; | ||
540 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; | 588 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; |
541 | } | 589 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) |
542 | /* There is some evidence (often anecdotal) that RV515/RV620 LVDS | 590 | pll->flags |= RADEON_PLL_IS_LCD; |
543 | * (on some boards at least) prefers the legacy algo. I'm not | ||
544 | * sure whether this should handled generically or on a | ||
545 | * case-by-case quirk basis. Both algos should work fine in the | ||
546 | * majority of cases. | ||
547 | */ | ||
548 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && | ||
549 | ((rdev->family == CHIP_RV515) || | ||
550 | (rdev->family == CHIP_RV620))) { | ||
551 | /* allow the user to overrride just in case */ | ||
552 | if (radeon_new_pll == 1) | ||
553 | pll->algo = PLL_ALGO_NEW; | ||
554 | else | ||
555 | pll->algo = PLL_ALGO_LEGACY; | ||
556 | } | ||
557 | } else { | 591 | } else { |
558 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | 592 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) |
559 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; | 593 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; |
@@ -588,14 +622,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
588 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); | 622 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); |
589 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; | 623 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; |
590 | args.v1.ucEncodeMode = encoder_mode; | 624 | args.v1.ucEncodeMode = encoder_mode; |
591 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { | 625 | if (ss_enabled && ss->percentage) |
592 | /* may want to enable SS on DP eventually */ | ||
593 | /* args.v1.ucConfig |= | ||
594 | ADJUST_DISPLAY_CONFIG_SS_ENABLE;*/ | ||
595 | } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { | ||
596 | args.v1.ucConfig |= | 626 | args.v1.ucConfig |= |
597 | ADJUST_DISPLAY_CONFIG_SS_ENABLE; | 627 | ADJUST_DISPLAY_CONFIG_SS_ENABLE; |
598 | } | ||
599 | 628 | ||
600 | atom_execute_table(rdev->mode_info.atom_context, | 629 | atom_execute_table(rdev->mode_info.atom_context, |
601 | index, (uint32_t *)&args); | 630 | index, (uint32_t *)&args); |
@@ -606,13 +635,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
606 | args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; | 635 | args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; |
607 | args.v3.sInput.ucEncodeMode = encoder_mode; | 636 | args.v3.sInput.ucEncodeMode = encoder_mode; |
608 | args.v3.sInput.ucDispPllConfig = 0; | 637 | args.v3.sInput.ucDispPllConfig = 0; |
609 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | 638 | if (ss_enabled && ss->percentage) |
639 | args.v3.sInput.ucDispPllConfig |= | ||
640 | DISPPLL_CONFIG_SS_ENABLE; | ||
641 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT) || | ||
642 | radeon_encoder_is_dp_bridge(encoder)) { | ||
610 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 643 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
611 | |||
612 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { | 644 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { |
613 | /* may want to enable SS on DP/eDP eventually */ | ||
614 | /*args.v3.sInput.ucDispPllConfig |= | ||
615 | DISPPLL_CONFIG_SS_ENABLE;*/ | ||
616 | args.v3.sInput.ucDispPllConfig |= | 645 | args.v3.sInput.ucDispPllConfig |= |
617 | DISPPLL_CONFIG_COHERENT_MODE; | 646 | DISPPLL_CONFIG_COHERENT_MODE; |
618 | /* 16200 or 27000 */ | 647 | /* 16200 or 27000 */ |
@@ -632,31 +661,33 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
632 | } | 661 | } |
633 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 662 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
634 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { | 663 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { |
635 | /* may want to enable SS on DP/eDP eventually */ | ||
636 | /*args.v3.sInput.ucDispPllConfig |= | ||
637 | DISPPLL_CONFIG_SS_ENABLE;*/ | ||
638 | args.v3.sInput.ucDispPllConfig |= | 664 | args.v3.sInput.ucDispPllConfig |= |
639 | DISPPLL_CONFIG_COHERENT_MODE; | 665 | DISPPLL_CONFIG_COHERENT_MODE; |
640 | /* 16200 or 27000 */ | 666 | /* 16200 or 27000 */ |
641 | args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); | 667 | args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); |
642 | } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { | 668 | } else if (encoder_mode != ATOM_ENCODER_MODE_LVDS) { |
643 | /* want to enable SS on LVDS eventually */ | ||
644 | /*args.v3.sInput.ucDispPllConfig |= | ||
645 | DISPPLL_CONFIG_SS_ENABLE;*/ | ||
646 | } else { | ||
647 | if (mode->clock > 165000) | 669 | if (mode->clock > 165000) |
648 | args.v3.sInput.ucDispPllConfig |= | 670 | args.v3.sInput.ucDispPllConfig |= |
649 | DISPPLL_CONFIG_DUAL_LINK; | 671 | DISPPLL_CONFIG_DUAL_LINK; |
650 | } | 672 | } |
651 | } | 673 | } |
674 | if (radeon_encoder_is_dp_bridge(encoder)) { | ||
675 | struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); | ||
676 | struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); | ||
677 | args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id; | ||
678 | } else | ||
679 | args.v3.sInput.ucExtTransmitterID = 0; | ||
680 | |||
652 | atom_execute_table(rdev->mode_info.atom_context, | 681 | atom_execute_table(rdev->mode_info.atom_context, |
653 | index, (uint32_t *)&args); | 682 | index, (uint32_t *)&args); |
654 | adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; | 683 | adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; |
655 | if (args.v3.sOutput.ucRefDiv) { | 684 | if (args.v3.sOutput.ucRefDiv) { |
685 | pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV; | ||
656 | pll->flags |= RADEON_PLL_USE_REF_DIV; | 686 | pll->flags |= RADEON_PLL_USE_REF_DIV; |
657 | pll->reference_div = args.v3.sOutput.ucRefDiv; | 687 | pll->reference_div = args.v3.sOutput.ucRefDiv; |
658 | } | 688 | } |
659 | if (args.v3.sOutput.ucPostDiv) { | 689 | if (args.v3.sOutput.ucPostDiv) { |
690 | pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV; | ||
660 | pll->flags |= RADEON_PLL_USE_POST_DIV; | 691 | pll->flags |= RADEON_PLL_USE_POST_DIV; |
661 | pll->post_div = args.v3.sOutput.ucPostDiv; | 692 | pll->post_div = args.v3.sOutput.ucPostDiv; |
662 | } | 693 | } |
@@ -680,9 +711,14 @@ union set_pixel_clock { | |||
680 | PIXEL_CLOCK_PARAMETERS_V2 v2; | 711 | PIXEL_CLOCK_PARAMETERS_V2 v2; |
681 | PIXEL_CLOCK_PARAMETERS_V3 v3; | 712 | PIXEL_CLOCK_PARAMETERS_V3 v3; |
682 | PIXEL_CLOCK_PARAMETERS_V5 v5; | 713 | PIXEL_CLOCK_PARAMETERS_V5 v5; |
714 | PIXEL_CLOCK_PARAMETERS_V6 v6; | ||
683 | }; | 715 | }; |
684 | 716 | ||
685 | static void atombios_crtc_set_dcpll(struct drm_crtc *crtc) | 717 | /* on DCE5, make sure the voltage is high enough to support the |
718 | * required disp clk. | ||
719 | */ | ||
720 | static void atombios_crtc_set_dcpll(struct drm_crtc *crtc, | ||
721 | u32 dispclk) | ||
686 | { | 722 | { |
687 | struct drm_device *dev = crtc->dev; | 723 | struct drm_device *dev = crtc->dev; |
688 | struct radeon_device *rdev = dev->dev_private; | 724 | struct radeon_device *rdev = dev->dev_private; |
@@ -705,9 +741,16 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc) | |||
705 | * SetPixelClock provides the dividers | 741 | * SetPixelClock provides the dividers |
706 | */ | 742 | */ |
707 | args.v5.ucCRTC = ATOM_CRTC_INVALID; | 743 | args.v5.ucCRTC = ATOM_CRTC_INVALID; |
708 | args.v5.usPixelClock = rdev->clock.default_dispclk; | 744 | args.v5.usPixelClock = cpu_to_le16(dispclk); |
709 | args.v5.ucPpll = ATOM_DCPLL; | 745 | args.v5.ucPpll = ATOM_DCPLL; |
710 | break; | 746 | break; |
747 | case 6: | ||
748 | /* if the default dcpll clock is specified, | ||
749 | * SetPixelClock provides the dividers | ||
750 | */ | ||
751 | args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk); | ||
752 | args.v6.ucPpll = ATOM_DCPLL; | ||
753 | break; | ||
711 | default: | 754 | default: |
712 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | 755 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); |
713 | return; | 756 | return; |
@@ -729,7 +772,10 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, | |||
729 | u32 ref_div, | 772 | u32 ref_div, |
730 | u32 fb_div, | 773 | u32 fb_div, |
731 | u32 frac_fb_div, | 774 | u32 frac_fb_div, |
732 | u32 post_div) | 775 | u32 post_div, |
776 | int bpc, | ||
777 | bool ss_enabled, | ||
778 | struct radeon_atom_ss *ss) | ||
733 | { | 779 | { |
734 | struct drm_device *dev = crtc->dev; | 780 | struct drm_device *dev = crtc->dev; |
735 | struct radeon_device *rdev = dev->dev_private; | 781 | struct radeon_device *rdev = dev->dev_private; |
@@ -776,6 +822,8 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, | |||
776 | args.v3.ucPostDiv = post_div; | 822 | args.v3.ucPostDiv = post_div; |
777 | args.v3.ucPpll = pll_id; | 823 | args.v3.ucPpll = pll_id; |
778 | args.v3.ucMiscInfo = (pll_id << 2); | 824 | args.v3.ucMiscInfo = (pll_id << 2); |
825 | if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) | ||
826 | args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; | ||
779 | args.v3.ucTransmitterId = encoder_id; | 827 | args.v3.ucTransmitterId = encoder_id; |
780 | args.v3.ucEncoderMode = encoder_mode; | 828 | args.v3.ucEncoderMode = encoder_mode; |
781 | break; | 829 | break; |
@@ -787,10 +835,50 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, | |||
787 | args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); | 835 | args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); |
788 | args.v5.ucPostDiv = post_div; | 836 | args.v5.ucPostDiv = post_div; |
789 | args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ | 837 | args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ |
838 | if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) | ||
839 | args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC; | ||
840 | switch (bpc) { | ||
841 | case 8: | ||
842 | default: | ||
843 | args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; | ||
844 | break; | ||
845 | case 10: | ||
846 | args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; | ||
847 | break; | ||
848 | } | ||
790 | args.v5.ucTransmitterID = encoder_id; | 849 | args.v5.ucTransmitterID = encoder_id; |
791 | args.v5.ucEncoderMode = encoder_mode; | 850 | args.v5.ucEncoderMode = encoder_mode; |
792 | args.v5.ucPpll = pll_id; | 851 | args.v5.ucPpll = pll_id; |
793 | break; | 852 | break; |
853 | case 6: | ||
854 | args.v6.ulCrtcPclkFreq.ucCRTC = crtc_id; | ||
855 | args.v6.ulCrtcPclkFreq.ulPixelClock = cpu_to_le32(clock / 10); | ||
856 | args.v6.ucRefDiv = ref_div; | ||
857 | args.v6.usFbDiv = cpu_to_le16(fb_div); | ||
858 | args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); | ||
859 | args.v6.ucPostDiv = post_div; | ||
860 | args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */ | ||
861 | if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) | ||
862 | args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC; | ||
863 | switch (bpc) { | ||
864 | case 8: | ||
865 | default: | ||
866 | args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; | ||
867 | break; | ||
868 | case 10: | ||
869 | args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP; | ||
870 | break; | ||
871 | case 12: | ||
872 | args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP; | ||
873 | break; | ||
874 | case 16: | ||
875 | args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; | ||
876 | break; | ||
877 | } | ||
878 | args.v6.ucTransmitterID = encoder_id; | ||
879 | args.v6.ucEncoderMode = encoder_mode; | ||
880 | args.v6.ucPpll = pll_id; | ||
881 | break; | ||
794 | default: | 882 | default: |
795 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | 883 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); |
796 | return; | 884 | return; |
@@ -816,6 +904,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
816 | struct radeon_pll *pll; | 904 | struct radeon_pll *pll; |
817 | u32 adjusted_clock; | 905 | u32 adjusted_clock; |
818 | int encoder_mode = 0; | 906 | int encoder_mode = 0; |
907 | struct radeon_atom_ss ss; | ||
908 | bool ss_enabled = false; | ||
909 | int bpc = 8; | ||
819 | 910 | ||
820 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 911 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
821 | if (encoder->crtc == crtc) { | 912 | if (encoder->crtc == crtc) { |
@@ -842,54 +933,166 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
842 | break; | 933 | break; |
843 | } | 934 | } |
844 | 935 | ||
936 | if (radeon_encoder->active_device & | ||
937 | (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) { | ||
938 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
939 | struct drm_connector *connector = | ||
940 | radeon_get_connector_for_encoder(encoder); | ||
941 | struct radeon_connector *radeon_connector = | ||
942 | to_radeon_connector(connector); | ||
943 | struct radeon_connector_atom_dig *dig_connector = | ||
944 | radeon_connector->con_priv; | ||
945 | int dp_clock; | ||
946 | bpc = connector->display_info.bpc; | ||
947 | |||
948 | switch (encoder_mode) { | ||
949 | case ATOM_ENCODER_MODE_DP: | ||
950 | /* DP/eDP */ | ||
951 | dp_clock = dig_connector->dp_clock / 10; | ||
952 | if (ASIC_IS_DCE4(rdev)) | ||
953 | ss_enabled = | ||
954 | radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
955 | ASIC_INTERNAL_SS_ON_DP, | ||
956 | dp_clock); | ||
957 | else { | ||
958 | if (dp_clock == 16200) { | ||
959 | ss_enabled = | ||
960 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | ||
961 | ATOM_DP_SS_ID2); | ||
962 | if (!ss_enabled) | ||
963 | ss_enabled = | ||
964 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | ||
965 | ATOM_DP_SS_ID1); | ||
966 | } else | ||
967 | ss_enabled = | ||
968 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | ||
969 | ATOM_DP_SS_ID1); | ||
970 | } | ||
971 | break; | ||
972 | case ATOM_ENCODER_MODE_LVDS: | ||
973 | if (ASIC_IS_DCE4(rdev)) | ||
974 | ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
975 | dig->lcd_ss_id, | ||
976 | mode->clock / 10); | ||
977 | else | ||
978 | ss_enabled = radeon_atombios_get_ppll_ss_info(rdev, &ss, | ||
979 | dig->lcd_ss_id); | ||
980 | break; | ||
981 | case ATOM_ENCODER_MODE_DVI: | ||
982 | if (ASIC_IS_DCE4(rdev)) | ||
983 | ss_enabled = | ||
984 | radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
985 | ASIC_INTERNAL_SS_ON_TMDS, | ||
986 | mode->clock / 10); | ||
987 | break; | ||
988 | case ATOM_ENCODER_MODE_HDMI: | ||
989 | if (ASIC_IS_DCE4(rdev)) | ||
990 | ss_enabled = | ||
991 | radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
992 | ASIC_INTERNAL_SS_ON_HDMI, | ||
993 | mode->clock / 10); | ||
994 | break; | ||
995 | default: | ||
996 | break; | ||
997 | } | ||
998 | } | ||
999 | |||
845 | /* adjust pixel clock as needed */ | 1000 | /* adjust pixel clock as needed */ |
846 | adjusted_clock = atombios_adjust_pll(crtc, mode, pll); | 1001 | adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss); |
1002 | |||
1003 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) | ||
1004 | /* TV seems to prefer the legacy algo on some boards */ | ||
1005 | radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | ||
1006 | &ref_div, &post_div); | ||
1007 | else if (ASIC_IS_AVIVO(rdev)) | ||
1008 | radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | ||
1009 | &ref_div, &post_div); | ||
1010 | else | ||
1011 | radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | ||
1012 | &ref_div, &post_div); | ||
847 | 1013 | ||
848 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | 1014 | atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss); |
849 | &ref_div, &post_div); | ||
850 | 1015 | ||
851 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, | 1016 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, |
852 | encoder_mode, radeon_encoder->encoder_id, mode->clock, | 1017 | encoder_mode, radeon_encoder->encoder_id, mode->clock, |
853 | ref_div, fb_div, frac_fb_div, post_div); | 1018 | ref_div, fb_div, frac_fb_div, post_div, bpc, ss_enabled, &ss); |
1019 | |||
1020 | if (ss_enabled) { | ||
1021 | /* calculate ss amount and step size */ | ||
1022 | if (ASIC_IS_DCE4(rdev)) { | ||
1023 | u32 step_size; | ||
1024 | u32 amount = (((fb_div * 10) + frac_fb_div) * ss.percentage) / 10000; | ||
1025 | ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK; | ||
1026 | ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & | ||
1027 | ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK; | ||
1028 | if (ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD) | ||
1029 | step_size = (4 * amount * ref_div * (ss.rate * 2048)) / | ||
1030 | (125 * 25 * pll->reference_freq / 100); | ||
1031 | else | ||
1032 | step_size = (2 * amount * ref_div * (ss.rate * 2048)) / | ||
1033 | (125 * 25 * pll->reference_freq / 100); | ||
1034 | ss.step = step_size; | ||
1035 | } | ||
854 | 1036 | ||
1037 | atombios_crtc_program_ss(crtc, ATOM_ENABLE, radeon_crtc->pll_id, &ss); | ||
1038 | } | ||
855 | } | 1039 | } |
856 | 1040 | ||
857 | static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 1041 | static int dce4_crtc_do_set_base(struct drm_crtc *crtc, |
858 | struct drm_framebuffer *old_fb) | 1042 | struct drm_framebuffer *fb, |
1043 | int x, int y, int atomic) | ||
859 | { | 1044 | { |
860 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 1045 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
861 | struct drm_device *dev = crtc->dev; | 1046 | struct drm_device *dev = crtc->dev; |
862 | struct radeon_device *rdev = dev->dev_private; | 1047 | struct radeon_device *rdev = dev->dev_private; |
863 | struct radeon_framebuffer *radeon_fb; | 1048 | struct radeon_framebuffer *radeon_fb; |
1049 | struct drm_framebuffer *target_fb; | ||
864 | struct drm_gem_object *obj; | 1050 | struct drm_gem_object *obj; |
865 | struct radeon_bo *rbo; | 1051 | struct radeon_bo *rbo; |
866 | uint64_t fb_location; | 1052 | uint64_t fb_location; |
867 | uint32_t fb_format, fb_pitch_pixels, tiling_flags; | 1053 | uint32_t fb_format, fb_pitch_pixels, tiling_flags; |
1054 | u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); | ||
1055 | u32 tmp, viewport_w, viewport_h; | ||
868 | int r; | 1056 | int r; |
869 | 1057 | ||
870 | /* no fb bound */ | 1058 | /* no fb bound */ |
871 | if (!crtc->fb) { | 1059 | if (!atomic && !crtc->fb) { |
872 | DRM_DEBUG_KMS("No FB bound\n"); | 1060 | DRM_DEBUG_KMS("No FB bound\n"); |
873 | return 0; | 1061 | return 0; |
874 | } | 1062 | } |
875 | 1063 | ||
876 | radeon_fb = to_radeon_framebuffer(crtc->fb); | 1064 | if (atomic) { |
1065 | radeon_fb = to_radeon_framebuffer(fb); | ||
1066 | target_fb = fb; | ||
1067 | } | ||
1068 | else { | ||
1069 | radeon_fb = to_radeon_framebuffer(crtc->fb); | ||
1070 | target_fb = crtc->fb; | ||
1071 | } | ||
877 | 1072 | ||
878 | /* Pin framebuffer & get tilling informations */ | 1073 | /* If atomic, assume fb object is pinned & idle & fenced and |
1074 | * just update base pointers | ||
1075 | */ | ||
879 | obj = radeon_fb->obj; | 1076 | obj = radeon_fb->obj; |
880 | rbo = obj->driver_private; | 1077 | rbo = gem_to_radeon_bo(obj); |
881 | r = radeon_bo_reserve(rbo, false); | 1078 | r = radeon_bo_reserve(rbo, false); |
882 | if (unlikely(r != 0)) | 1079 | if (unlikely(r != 0)) |
883 | return r; | 1080 | return r; |
884 | r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); | 1081 | |
885 | if (unlikely(r != 0)) { | 1082 | if (atomic) |
886 | radeon_bo_unreserve(rbo); | 1083 | fb_location = radeon_bo_gpu_offset(rbo); |
887 | return -EINVAL; | 1084 | else { |
1085 | r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); | ||
1086 | if (unlikely(r != 0)) { | ||
1087 | radeon_bo_unreserve(rbo); | ||
1088 | return -EINVAL; | ||
1089 | } | ||
888 | } | 1090 | } |
1091 | |||
889 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); | 1092 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); |
890 | radeon_bo_unreserve(rbo); | 1093 | radeon_bo_unreserve(rbo); |
891 | 1094 | ||
892 | switch (crtc->fb->bits_per_pixel) { | 1095 | switch (target_fb->bits_per_pixel) { |
893 | case 8: | 1096 | case 8: |
894 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) | | 1097 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) | |
895 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED)); | 1098 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED)); |
@@ -901,15 +1104,21 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
901 | case 16: | 1104 | case 16: |
902 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | | 1105 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | |
903 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565)); | 1106 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565)); |
1107 | #ifdef __BIG_ENDIAN | ||
1108 | fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16); | ||
1109 | #endif | ||
904 | break; | 1110 | break; |
905 | case 24: | 1111 | case 24: |
906 | case 32: | 1112 | case 32: |
907 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | | 1113 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | |
908 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888)); | 1114 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888)); |
1115 | #ifdef __BIG_ENDIAN | ||
1116 | fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32); | ||
1117 | #endif | ||
909 | break; | 1118 | break; |
910 | default: | 1119 | default: |
911 | DRM_ERROR("Unsupported screen depth %d\n", | 1120 | DRM_ERROR("Unsupported screen depth %d\n", |
912 | crtc->fb->bits_per_pixel); | 1121 | target_fb->bits_per_pixel); |
913 | return -EINVAL; | 1122 | return -EINVAL; |
914 | } | 1123 | } |
915 | 1124 | ||
@@ -950,15 +1159,16 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
950 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | 1159 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, |
951 | (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); | 1160 | (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); |
952 | WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); | 1161 | WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); |
1162 | WREG32(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); | ||
953 | 1163 | ||
954 | WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); | 1164 | WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); |
955 | WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); | 1165 | WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); |
956 | WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0); | 1166 | WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0); |
957 | WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0); | 1167 | WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0); |
958 | WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width); | 1168 | WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); |
959 | WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height); | 1169 | WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); |
960 | 1170 | ||
961 | fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); | 1171 | fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); |
962 | WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); | 1172 | WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); |
963 | WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); | 1173 | WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); |
964 | 1174 | ||
@@ -968,18 +1178,23 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
968 | y &= ~1; | 1178 | y &= ~1; |
969 | WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, | 1179 | WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, |
970 | (x << 16) | y); | 1180 | (x << 16) | y); |
1181 | viewport_w = crtc->mode.hdisplay; | ||
1182 | viewport_h = (crtc->mode.vdisplay + 1) & ~1; | ||
971 | WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, | 1183 | WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, |
972 | (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); | 1184 | (viewport_w << 16) | viewport_h); |
973 | 1185 | ||
974 | if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) | 1186 | /* pageflip setup */ |
975 | WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, | 1187 | /* make sure flip is at vb rather than hb */ |
976 | EVERGREEN_INTERLEAVE_EN); | 1188 | tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); |
977 | else | 1189 | tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; |
978 | WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0); | 1190 | WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); |
1191 | |||
1192 | /* set pageflip to happen anywhere in vblank interval */ | ||
1193 | WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); | ||
979 | 1194 | ||
980 | if (old_fb && old_fb != crtc->fb) { | 1195 | if (!atomic && fb && fb != crtc->fb) { |
981 | radeon_fb = to_radeon_framebuffer(old_fb); | 1196 | radeon_fb = to_radeon_framebuffer(fb); |
982 | rbo = radeon_fb->obj->driver_private; | 1197 | rbo = gem_to_radeon_bo(radeon_fb->obj); |
983 | r = radeon_bo_reserve(rbo, false); | 1198 | r = radeon_bo_reserve(rbo, false); |
984 | if (unlikely(r != 0)) | 1199 | if (unlikely(r != 0)) |
985 | return r; | 1200 | return r; |
@@ -993,8 +1208,9 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
993 | return 0; | 1208 | return 0; |
994 | } | 1209 | } |
995 | 1210 | ||
996 | static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 1211 | static int avivo_crtc_do_set_base(struct drm_crtc *crtc, |
997 | struct drm_framebuffer *old_fb) | 1212 | struct drm_framebuffer *fb, |
1213 | int x, int y, int atomic) | ||
998 | { | 1214 | { |
999 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 1215 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
1000 | struct drm_device *dev = crtc->dev; | 1216 | struct drm_device *dev = crtc->dev; |
@@ -1002,33 +1218,50 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1002 | struct radeon_framebuffer *radeon_fb; | 1218 | struct radeon_framebuffer *radeon_fb; |
1003 | struct drm_gem_object *obj; | 1219 | struct drm_gem_object *obj; |
1004 | struct radeon_bo *rbo; | 1220 | struct radeon_bo *rbo; |
1221 | struct drm_framebuffer *target_fb; | ||
1005 | uint64_t fb_location; | 1222 | uint64_t fb_location; |
1006 | uint32_t fb_format, fb_pitch_pixels, tiling_flags; | 1223 | uint32_t fb_format, fb_pitch_pixels, tiling_flags; |
1224 | u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; | ||
1225 | u32 tmp, viewport_w, viewport_h; | ||
1007 | int r; | 1226 | int r; |
1008 | 1227 | ||
1009 | /* no fb bound */ | 1228 | /* no fb bound */ |
1010 | if (!crtc->fb) { | 1229 | if (!atomic && !crtc->fb) { |
1011 | DRM_DEBUG_KMS("No FB bound\n"); | 1230 | DRM_DEBUG_KMS("No FB bound\n"); |
1012 | return 0; | 1231 | return 0; |
1013 | } | 1232 | } |
1014 | 1233 | ||
1015 | radeon_fb = to_radeon_framebuffer(crtc->fb); | 1234 | if (atomic) { |
1235 | radeon_fb = to_radeon_framebuffer(fb); | ||
1236 | target_fb = fb; | ||
1237 | } | ||
1238 | else { | ||
1239 | radeon_fb = to_radeon_framebuffer(crtc->fb); | ||
1240 | target_fb = crtc->fb; | ||
1241 | } | ||
1016 | 1242 | ||
1017 | /* Pin framebuffer & get tilling informations */ | ||
1018 | obj = radeon_fb->obj; | 1243 | obj = radeon_fb->obj; |
1019 | rbo = obj->driver_private; | 1244 | rbo = gem_to_radeon_bo(obj); |
1020 | r = radeon_bo_reserve(rbo, false); | 1245 | r = radeon_bo_reserve(rbo, false); |
1021 | if (unlikely(r != 0)) | 1246 | if (unlikely(r != 0)) |
1022 | return r; | 1247 | return r; |
1023 | r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); | 1248 | |
1024 | if (unlikely(r != 0)) { | 1249 | /* If atomic, assume fb object is pinned & idle & fenced and |
1025 | radeon_bo_unreserve(rbo); | 1250 | * just update base pointers |
1026 | return -EINVAL; | 1251 | */ |
1252 | if (atomic) | ||
1253 | fb_location = radeon_bo_gpu_offset(rbo); | ||
1254 | else { | ||
1255 | r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); | ||
1256 | if (unlikely(r != 0)) { | ||
1257 | radeon_bo_unreserve(rbo); | ||
1258 | return -EINVAL; | ||
1259 | } | ||
1027 | } | 1260 | } |
1028 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); | 1261 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); |
1029 | radeon_bo_unreserve(rbo); | 1262 | radeon_bo_unreserve(rbo); |
1030 | 1263 | ||
1031 | switch (crtc->fb->bits_per_pixel) { | 1264 | switch (target_fb->bits_per_pixel) { |
1032 | case 8: | 1265 | case 8: |
1033 | fb_format = | 1266 | fb_format = |
1034 | AVIVO_D1GRPH_CONTROL_DEPTH_8BPP | | 1267 | AVIVO_D1GRPH_CONTROL_DEPTH_8BPP | |
@@ -1043,16 +1276,22 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1043 | fb_format = | 1276 | fb_format = |
1044 | AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | | 1277 | AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | |
1045 | AVIVO_D1GRPH_CONTROL_16BPP_RGB565; | 1278 | AVIVO_D1GRPH_CONTROL_16BPP_RGB565; |
1279 | #ifdef __BIG_ENDIAN | ||
1280 | fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT; | ||
1281 | #endif | ||
1046 | break; | 1282 | break; |
1047 | case 24: | 1283 | case 24: |
1048 | case 32: | 1284 | case 32: |
1049 | fb_format = | 1285 | fb_format = |
1050 | AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | | 1286 | AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | |
1051 | AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888; | 1287 | AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888; |
1288 | #ifdef __BIG_ENDIAN | ||
1289 | fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT; | ||
1290 | #endif | ||
1052 | break; | 1291 | break; |
1053 | default: | 1292 | default: |
1054 | DRM_ERROR("Unsupported screen depth %d\n", | 1293 | DRM_ERROR("Unsupported screen depth %d\n", |
1055 | crtc->fb->bits_per_pixel); | 1294 | target_fb->bits_per_pixel); |
1056 | return -EINVAL; | 1295 | return -EINVAL; |
1057 | } | 1296 | } |
1058 | 1297 | ||
@@ -1088,15 +1327,17 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1088 | WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + | 1327 | WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + |
1089 | radeon_crtc->crtc_offset, (u32) fb_location); | 1328 | radeon_crtc->crtc_offset, (u32) fb_location); |
1090 | WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); | 1329 | WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); |
1330 | if (rdev->family >= CHIP_R600) | ||
1331 | WREG32(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); | ||
1091 | 1332 | ||
1092 | WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); | 1333 | WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); |
1093 | WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); | 1334 | WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); |
1094 | WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0); | 1335 | WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0); |
1095 | WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0); | 1336 | WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0); |
1096 | WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width); | 1337 | WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); |
1097 | WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height); | 1338 | WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); |
1098 | 1339 | ||
1099 | fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); | 1340 | fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); |
1100 | WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); | 1341 | WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); |
1101 | WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); | 1342 | WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); |
1102 | 1343 | ||
@@ -1106,18 +1347,23 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1106 | y &= ~1; | 1347 | y &= ~1; |
1107 | WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, | 1348 | WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, |
1108 | (x << 16) | y); | 1349 | (x << 16) | y); |
1350 | viewport_w = crtc->mode.hdisplay; | ||
1351 | viewport_h = (crtc->mode.vdisplay + 1) & ~1; | ||
1109 | WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, | 1352 | WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, |
1110 | (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); | 1353 | (viewport_w << 16) | viewport_h); |
1111 | 1354 | ||
1112 | if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) | 1355 | /* pageflip setup */ |
1113 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, | 1356 | /* make sure flip is at vb rather than hb */ |
1114 | AVIVO_D1MODE_INTERLEAVE_EN); | 1357 | tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); |
1115 | else | 1358 | tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; |
1116 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); | 1359 | WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); |
1117 | 1360 | ||
1118 | if (old_fb && old_fb != crtc->fb) { | 1361 | /* set pageflip to happen anywhere in vblank interval */ |
1119 | radeon_fb = to_radeon_framebuffer(old_fb); | 1362 | WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); |
1120 | rbo = radeon_fb->obj->driver_private; | 1363 | |
1364 | if (!atomic && fb && fb != crtc->fb) { | ||
1365 | radeon_fb = to_radeon_framebuffer(fb); | ||
1366 | rbo = gem_to_radeon_bo(radeon_fb->obj); | ||
1121 | r = radeon_bo_reserve(rbo, false); | 1367 | r = radeon_bo_reserve(rbo, false); |
1122 | if (unlikely(r != 0)) | 1368 | if (unlikely(r != 0)) |
1123 | return r; | 1369 | return r; |
@@ -1138,11 +1384,26 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1138 | struct radeon_device *rdev = dev->dev_private; | 1384 | struct radeon_device *rdev = dev->dev_private; |
1139 | 1385 | ||
1140 | if (ASIC_IS_DCE4(rdev)) | 1386 | if (ASIC_IS_DCE4(rdev)) |
1141 | return evergreen_crtc_set_base(crtc, x, y, old_fb); | 1387 | return dce4_crtc_do_set_base(crtc, old_fb, x, y, 0); |
1142 | else if (ASIC_IS_AVIVO(rdev)) | 1388 | else if (ASIC_IS_AVIVO(rdev)) |
1143 | return avivo_crtc_set_base(crtc, x, y, old_fb); | 1389 | return avivo_crtc_do_set_base(crtc, old_fb, x, y, 0); |
1144 | else | 1390 | else |
1145 | return radeon_crtc_set_base(crtc, x, y, old_fb); | 1391 | return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0); |
1392 | } | ||
1393 | |||
1394 | int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, | ||
1395 | struct drm_framebuffer *fb, | ||
1396 | int x, int y, enum mode_set_atomic state) | ||
1397 | { | ||
1398 | struct drm_device *dev = crtc->dev; | ||
1399 | struct radeon_device *rdev = dev->dev_private; | ||
1400 | |||
1401 | if (ASIC_IS_DCE4(rdev)) | ||
1402 | return dce4_crtc_do_set_base(crtc, fb, x, y, 1); | ||
1403 | else if (ASIC_IS_AVIVO(rdev)) | ||
1404 | return avivo_crtc_do_set_base(crtc, fb, x, y, 1); | ||
1405 | else | ||
1406 | return radeon_crtc_do_set_base(crtc, fb, x, y, 1); | ||
1146 | } | 1407 | } |
1147 | 1408 | ||
1148 | /* properly set additional regs when using atombios */ | 1409 | /* properly set additional regs when using atombios */ |
@@ -1179,11 +1440,19 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) | |||
1179 | uint32_t pll_in_use = 0; | 1440 | uint32_t pll_in_use = 0; |
1180 | 1441 | ||
1181 | if (ASIC_IS_DCE4(rdev)) { | 1442 | if (ASIC_IS_DCE4(rdev)) { |
1182 | /* if crtc is driving DP and we have an ext clock, use that */ | ||
1183 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { | 1443 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { |
1184 | if (test_encoder->crtc && (test_encoder->crtc == crtc)) { | 1444 | if (test_encoder->crtc && (test_encoder->crtc == crtc)) { |
1445 | /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, | ||
1446 | * depending on the asic: | ||
1447 | * DCE4: PPLL or ext clock | ||
1448 | * DCE5: DCPLL or ext clock | ||
1449 | * | ||
1450 | * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip | ||
1451 | * PPLL/DCPLL programming and only program the DP DTO for the | ||
1452 | * crtc virtual pixel clock. | ||
1453 | */ | ||
1185 | if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) { | 1454 | if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) { |
1186 | if (rdev->clock.dp_extclk) | 1455 | if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk) |
1187 | return ATOM_PPLL_INVALID; | 1456 | return ATOM_PPLL_INVALID; |
1188 | } | 1457 | } |
1189 | } | 1458 | } |
@@ -1230,12 +1499,20 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
1230 | } | 1499 | } |
1231 | } | 1500 | } |
1232 | 1501 | ||
1233 | atombios_disable_ss(crtc); | ||
1234 | /* always set DCPLL */ | 1502 | /* always set DCPLL */ |
1235 | if (ASIC_IS_DCE4(rdev)) | 1503 | if (ASIC_IS_DCE4(rdev)) { |
1236 | atombios_crtc_set_dcpll(crtc); | 1504 | struct radeon_atom_ss ss; |
1505 | bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
1506 | ASIC_INTERNAL_SS_ON_DCPLL, | ||
1507 | rdev->clock.default_dispclk); | ||
1508 | if (ss_enabled) | ||
1509 | atombios_crtc_program_ss(crtc, ATOM_DISABLE, ATOM_DCPLL, &ss); | ||
1510 | /* XXX: DCE5, make sure voltage, dispclk is high enough */ | ||
1511 | atombios_crtc_set_dcpll(crtc, rdev->clock.default_dispclk); | ||
1512 | if (ss_enabled) | ||
1513 | atombios_crtc_program_ss(crtc, ATOM_ENABLE, ATOM_DCPLL, &ss); | ||
1514 | } | ||
1237 | atombios_crtc_set_pll(crtc, adjusted_mode); | 1515 | atombios_crtc_set_pll(crtc, adjusted_mode); |
1238 | atombios_enable_ss(crtc); | ||
1239 | 1516 | ||
1240 | if (ASIC_IS_DCE4(rdev)) | 1517 | if (ASIC_IS_DCE4(rdev)) |
1241 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); | 1518 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); |
@@ -1291,6 +1568,8 @@ static void atombios_crtc_commit(struct drm_crtc *crtc) | |||
1291 | static void atombios_crtc_disable(struct drm_crtc *crtc) | 1568 | static void atombios_crtc_disable(struct drm_crtc *crtc) |
1292 | { | 1569 | { |
1293 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 1570 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
1571 | struct radeon_atom_ss ss; | ||
1572 | |||
1294 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | 1573 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); |
1295 | 1574 | ||
1296 | switch (radeon_crtc->pll_id) { | 1575 | switch (radeon_crtc->pll_id) { |
@@ -1298,7 +1577,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) | |||
1298 | case ATOM_PPLL2: | 1577 | case ATOM_PPLL2: |
1299 | /* disable the ppll */ | 1578 | /* disable the ppll */ |
1300 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, | 1579 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, |
1301 | 0, 0, ATOM_DISABLE, 0, 0, 0, 0); | 1580 | 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss); |
1302 | break; | 1581 | break; |
1303 | default: | 1582 | default: |
1304 | break; | 1583 | break; |
@@ -1311,6 +1590,7 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = { | |||
1311 | .mode_fixup = atombios_crtc_mode_fixup, | 1590 | .mode_fixup = atombios_crtc_mode_fixup, |
1312 | .mode_set = atombios_crtc_mode_set, | 1591 | .mode_set = atombios_crtc_mode_set, |
1313 | .mode_set_base = atombios_crtc_set_base, | 1592 | .mode_set_base = atombios_crtc_set_base, |
1593 | .mode_set_base_atomic = atombios_crtc_set_base_atomic, | ||
1314 | .prepare = atombios_crtc_prepare, | 1594 | .prepare = atombios_crtc_prepare, |
1315 | .commit = atombios_crtc_commit, | 1595 | .commit = atombios_crtc_commit, |
1316 | .load_lut = radeon_crtc_load_lut, | 1596 | .load_lut = radeon_crtc_load_lut, |