diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 196 |
1 files changed, 121 insertions, 75 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 7a8cdf2813dc..e619aca5423f 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -409,30 +409,22 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) | |||
409 | } | 409 | } |
410 | } | 410 | } |
411 | 411 | ||
412 | void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | 412 | union adjust_pixel_clock { |
413 | ADJUST_DISPLAY_PLL_PS_ALLOCATION v1; | ||
414 | }; | ||
415 | |||
416 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, | ||
417 | struct drm_display_mode *mode, | ||
418 | struct radeon_pll *pll) | ||
413 | { | 419 | { |
414 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
415 | struct drm_device *dev = crtc->dev; | 420 | struct drm_device *dev = crtc->dev; |
416 | struct radeon_device *rdev = dev->dev_private; | 421 | struct radeon_device *rdev = dev->dev_private; |
417 | struct drm_encoder *encoder = NULL; | 422 | struct drm_encoder *encoder = NULL; |
418 | struct radeon_encoder *radeon_encoder = NULL; | 423 | struct radeon_encoder *radeon_encoder = NULL; |
419 | uint8_t frev, crev; | 424 | u32 adjusted_clock = mode->clock; |
420 | int index; | ||
421 | SET_PIXEL_CLOCK_PS_ALLOCATION args; | ||
422 | PIXEL_CLOCK_PARAMETERS *spc1_ptr; | ||
423 | PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr; | ||
424 | PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr; | ||
425 | uint32_t pll_clock = mode->clock; | ||
426 | uint32_t adjusted_clock; | ||
427 | uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; | ||
428 | struct radeon_pll *pll; | ||
429 | 425 | ||
430 | if (radeon_crtc->crtc_id == 0) | 426 | /* reset the pll flags */ |
431 | pll = &rdev->clock.p1pll; | 427 | pll->flags = 0; |
432 | else | ||
433 | pll = &rdev->clock.p2pll; | ||
434 | |||
435 | memset(&args, 0, sizeof(args)); | ||
436 | 428 | ||
437 | if (ASIC_IS_AVIVO(rdev)) { | 429 | if (ASIC_IS_AVIVO(rdev)) { |
438 | if ((rdev->family == CHIP_RS600) || | 430 | if ((rdev->family == CHIP_RS600) || |
@@ -457,15 +449,17 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
457 | 449 | ||
458 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 450 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
459 | if (encoder->crtc == crtc) { | 451 | if (encoder->crtc == crtc) { |
460 | if (!ASIC_IS_AVIVO(rdev)) { | 452 | radeon_encoder = to_radeon_encoder(encoder); |
461 | if (encoder->encoder_type != | 453 | if (ASIC_IS_AVIVO(rdev)) { |
462 | DRM_MODE_ENCODER_DAC) | 454 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ |
455 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) | ||
456 | adjusted_clock = mode->clock * 2; | ||
457 | } else { | ||
458 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | ||
463 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; | 459 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; |
464 | if (encoder->encoder_type == | 460 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) |
465 | DRM_MODE_ENCODER_LVDS) | ||
466 | pll->flags |= RADEON_PLL_USE_REF_DIV; | 461 | pll->flags |= RADEON_PLL_USE_REF_DIV; |
467 | } | 462 | } |
468 | radeon_encoder = to_radeon_encoder(encoder); | ||
469 | break; | 463 | break; |
470 | } | 464 | } |
471 | } | 465 | } |
@@ -475,28 +469,88 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
475 | * special hw requirements. | 469 | * special hw requirements. |
476 | */ | 470 | */ |
477 | if (ASIC_IS_DCE3(rdev)) { | 471 | if (ASIC_IS_DCE3(rdev)) { |
478 | ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args; | 472 | union adjust_pixel_clock args; |
479 | 473 | struct radeon_encoder_atom_dig *dig; | |
480 | if (!encoder) | 474 | u8 frev, crev; |
481 | return; | 475 | int index; |
482 | 476 | ||
483 | memset(&adjust_pll_args, 0, sizeof(adjust_pll_args)); | 477 | if (!radeon_encoder->enc_priv) |
484 | adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10); | 478 | return adjusted_clock; |
485 | adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id; | 479 | dig = radeon_encoder->enc_priv; |
486 | adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder); | ||
487 | 480 | ||
488 | index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); | 481 | index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); |
489 | atom_execute_table(rdev->mode_info.atom_context, | 482 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, |
490 | index, (uint32_t *)&adjust_pll_args); | 483 | &crev); |
491 | adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10; | 484 | |
492 | } else { | 485 | memset(&args, 0, sizeof(args)); |
493 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ | 486 | |
494 | if (ASIC_IS_AVIVO(rdev) && | 487 | switch (frev) { |
495 | (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)) | 488 | case 1: |
496 | adjusted_clock = mode->clock * 2; | 489 | switch (crev) { |
497 | else | 490 | case 1: |
498 | adjusted_clock = mode->clock; | 491 | case 2: |
492 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); | ||
493 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; | ||
494 | args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder); | ||
495 | |||
496 | atom_execute_table(rdev->mode_info.atom_context, | ||
497 | index, (uint32_t *)&args); | ||
498 | adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; | ||
499 | break; | ||
500 | default: | ||
501 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | ||
502 | return adjusted_clock; | ||
503 | } | ||
504 | break; | ||
505 | default: | ||
506 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | ||
507 | return adjusted_clock; | ||
508 | } | ||
499 | } | 509 | } |
510 | return adjusted_clock; | ||
511 | } | ||
512 | |||
513 | union set_pixel_clock { | ||
514 | SET_PIXEL_CLOCK_PS_ALLOCATION base; | ||
515 | PIXEL_CLOCK_PARAMETERS v1; | ||
516 | PIXEL_CLOCK_PARAMETERS_V2 v2; | ||
517 | PIXEL_CLOCK_PARAMETERS_V3 v3; | ||
518 | }; | ||
519 | |||
520 | void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | ||
521 | { | ||
522 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
523 | struct drm_device *dev = crtc->dev; | ||
524 | struct radeon_device *rdev = dev->dev_private; | ||
525 | struct drm_encoder *encoder = NULL; | ||
526 | struct radeon_encoder *radeon_encoder = NULL; | ||
527 | u8 frev, crev; | ||
528 | int index; | ||
529 | union set_pixel_clock args; | ||
530 | u32 pll_clock = mode->clock; | ||
531 | u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; | ||
532 | struct radeon_pll *pll; | ||
533 | u32 adjusted_clock; | ||
534 | |||
535 | memset(&args, 0, sizeof(args)); | ||
536 | |||
537 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
538 | if (encoder->crtc == crtc) { | ||
539 | radeon_encoder = to_radeon_encoder(encoder); | ||
540 | break; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | if (!radeon_encoder) | ||
545 | return; | ||
546 | |||
547 | if (radeon_crtc->crtc_id == 0) | ||
548 | pll = &rdev->clock.p1pll; | ||
549 | else | ||
550 | pll = &rdev->clock.p2pll; | ||
551 | |||
552 | /* adjust pixel clock as needed */ | ||
553 | adjusted_clock = atombios_adjust_pll(crtc, mode, pll); | ||
500 | 554 | ||
501 | if (ASIC_IS_AVIVO(rdev)) { | 555 | if (ASIC_IS_AVIVO(rdev)) { |
502 | if (radeon_new_pll) | 556 | if (radeon_new_pll) |
@@ -519,45 +573,38 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
519 | case 1: | 573 | case 1: |
520 | switch (crev) { | 574 | switch (crev) { |
521 | case 1: | 575 | case 1: |
522 | spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput; | 576 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); |
523 | spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); | 577 | args.v1.usRefDiv = cpu_to_le16(ref_div); |
524 | spc1_ptr->usRefDiv = cpu_to_le16(ref_div); | 578 | args.v1.usFbDiv = cpu_to_le16(fb_div); |
525 | spc1_ptr->usFbDiv = cpu_to_le16(fb_div); | 579 | args.v1.ucFracFbDiv = frac_fb_div; |
526 | spc1_ptr->ucFracFbDiv = frac_fb_div; | 580 | args.v1.ucPostDiv = post_div; |
527 | spc1_ptr->ucPostDiv = post_div; | 581 | args.v1.ucPpll = |
528 | spc1_ptr->ucPpll = | ||
529 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 582 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; |
530 | spc1_ptr->ucCRTC = radeon_crtc->crtc_id; | 583 | args.v1.ucCRTC = radeon_crtc->crtc_id; |
531 | spc1_ptr->ucRefDivSrc = 1; | 584 | args.v1.ucRefDivSrc = 1; |
532 | break; | 585 | break; |
533 | case 2: | 586 | case 2: |
534 | spc2_ptr = | 587 | args.v2.usPixelClock = cpu_to_le16(mode->clock / 10); |
535 | (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput; | 588 | args.v2.usRefDiv = cpu_to_le16(ref_div); |
536 | spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); | 589 | args.v2.usFbDiv = cpu_to_le16(fb_div); |
537 | spc2_ptr->usRefDiv = cpu_to_le16(ref_div); | 590 | args.v2.ucFracFbDiv = frac_fb_div; |
538 | spc2_ptr->usFbDiv = cpu_to_le16(fb_div); | 591 | args.v2.ucPostDiv = post_div; |
539 | spc2_ptr->ucFracFbDiv = frac_fb_div; | 592 | args.v2.ucPpll = |
540 | spc2_ptr->ucPostDiv = post_div; | ||
541 | spc2_ptr->ucPpll = | ||
542 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 593 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; |
543 | spc2_ptr->ucCRTC = radeon_crtc->crtc_id; | 594 | args.v2.ucCRTC = radeon_crtc->crtc_id; |
544 | spc2_ptr->ucRefDivSrc = 1; | 595 | args.v2.ucRefDivSrc = 1; |
545 | break; | 596 | break; |
546 | case 3: | 597 | case 3: |
547 | if (!encoder) | 598 | args.v3.usPixelClock = cpu_to_le16(mode->clock / 10); |
548 | return; | 599 | args.v3.usRefDiv = cpu_to_le16(ref_div); |
549 | spc3_ptr = | 600 | args.v3.usFbDiv = cpu_to_le16(fb_div); |
550 | (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput; | 601 | args.v3.ucFracFbDiv = frac_fb_div; |
551 | spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); | 602 | args.v3.ucPostDiv = post_div; |
552 | spc3_ptr->usRefDiv = cpu_to_le16(ref_div); | 603 | args.v3.ucPpll = |
553 | spc3_ptr->usFbDiv = cpu_to_le16(fb_div); | ||
554 | spc3_ptr->ucFracFbDiv = frac_fb_div; | ||
555 | spc3_ptr->ucPostDiv = post_div; | ||
556 | spc3_ptr->ucPpll = | ||
557 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 604 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; |
558 | spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2); | 605 | args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2); |
559 | spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id; | 606 | args.v3.ucTransmitterId = radeon_encoder->encoder_id; |
560 | spc3_ptr->ucEncoderMode = | 607 | args.v3.ucEncoderMode = |
561 | atombios_get_encoder_mode(encoder); | 608 | atombios_get_encoder_mode(encoder); |
562 | break; | 609 | break; |
563 | default: | 610 | default: |
@@ -570,7 +617,6 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
570 | return; | 617 | return; |
571 | } | 618 | } |
572 | 619 | ||
573 | printk("executing set pll\n"); | ||
574 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 620 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
575 | } | 621 | } |
576 | 622 | ||