diff options
author | Christian König <deathsimple@vodafone.de> | 2013-04-08 06:41:31 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-04-09 10:31:35 -0400 |
commit | 7062ab67d4c6568ec423da39321423721b925fdc (patch) | |
tree | f7a1dcf559776d529e90951a9ea9ed0ba540177e | |
parent | 73afc70d1153399b01789ff01e04d2cae49acf52 (diff) |
drm/radeon: add radeon_atom_get_clock_dividers helper
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 107 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 23 |
3 files changed, 135 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ac614a45b27f..fb1780a28139 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -206,6 +206,11 @@ void radeon_pm_suspend(struct radeon_device *rdev); | |||
206 | void radeon_pm_resume(struct radeon_device *rdev); | 206 | void radeon_pm_resume(struct radeon_device *rdev); |
207 | void radeon_combios_get_power_modes(struct radeon_device *rdev); | 207 | void radeon_combios_get_power_modes(struct radeon_device *rdev); |
208 | void radeon_atombios_get_power_modes(struct radeon_device *rdev); | 208 | void radeon_atombios_get_power_modes(struct radeon_device *rdev); |
209 | int radeon_atom_get_clock_dividers(struct radeon_device *rdev, | ||
210 | u8 clock_type, | ||
211 | u32 clock, | ||
212 | bool strobe_mode, | ||
213 | struct atom_clock_dividers *dividers); | ||
209 | void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); | 214 | void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); |
210 | void rs690_pm_info(struct radeon_device *rdev); | 215 | void rs690_pm_info(struct radeon_device *rdev); |
211 | extern int rv6xx_get_temp(struct radeon_device *rdev); | 216 | extern int rv6xx_get_temp(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index f22eb5713528..8c1779cba1f3 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -2654,6 +2654,113 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
2654 | rdev->pm.current_vddc = 0; | 2654 | rdev->pm.current_vddc = 0; |
2655 | } | 2655 | } |
2656 | 2656 | ||
2657 | union get_clock_dividers { | ||
2658 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS v1; | ||
2659 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2 v2; | ||
2660 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 v3; | ||
2661 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 v4; | ||
2662 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 v5; | ||
2663 | }; | ||
2664 | |||
2665 | int radeon_atom_get_clock_dividers(struct radeon_device *rdev, | ||
2666 | u8 clock_type, | ||
2667 | u32 clock, | ||
2668 | bool strobe_mode, | ||
2669 | struct atom_clock_dividers *dividers) | ||
2670 | { | ||
2671 | union get_clock_dividers args; | ||
2672 | int index = GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL); | ||
2673 | u8 frev, crev; | ||
2674 | |||
2675 | memset(&args, 0, sizeof(args)); | ||
2676 | memset(dividers, 0, sizeof(struct atom_clock_dividers)); | ||
2677 | |||
2678 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | ||
2679 | return -EINVAL; | ||
2680 | |||
2681 | switch (crev) { | ||
2682 | case 1: | ||
2683 | /* r4xx, r5xx */ | ||
2684 | args.v1.ucAction = clock_type; | ||
2685 | args.v1.ulClock = cpu_to_le32(clock); /* 10 khz */ | ||
2686 | |||
2687 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
2688 | |||
2689 | dividers->post_div = args.v1.ucPostDiv; | ||
2690 | dividers->fb_div = args.v1.ucFbDiv; | ||
2691 | dividers->enable_post_div = true; | ||
2692 | break; | ||
2693 | case 2: | ||
2694 | case 3: | ||
2695 | /* r6xx, r7xx, evergreen, ni */ | ||
2696 | if (rdev->family <= CHIP_RV770) { | ||
2697 | args.v2.ucAction = clock_type; | ||
2698 | args.v2.ulClock = cpu_to_le32(clock); /* 10 khz */ | ||
2699 | |||
2700 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
2701 | |||
2702 | dividers->post_div = args.v2.ucPostDiv; | ||
2703 | dividers->fb_div = le16_to_cpu(args.v2.usFbDiv); | ||
2704 | dividers->ref_div = args.v2.ucAction; | ||
2705 | if (rdev->family == CHIP_RV770) { | ||
2706 | dividers->enable_post_div = (le32_to_cpu(args.v2.ulClock) & (1 << 24)) ? | ||
2707 | true : false; | ||
2708 | dividers->vco_mode = (le32_to_cpu(args.v2.ulClock) & (1 << 25)) ? 1 : 0; | ||
2709 | } else | ||
2710 | dividers->enable_post_div = (dividers->fb_div & 1) ? true : false; | ||
2711 | } else { | ||
2712 | if (clock_type == COMPUTE_ENGINE_PLL_PARAM) { | ||
2713 | args.v3.ulClock.ulComputeClockFlag = clock_type; | ||
2714 | args.v3.ulClock.ulClockFreq = cpu_to_le32(clock); /* 10 khz */ | ||
2715 | |||
2716 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
2717 | |||
2718 | dividers->post_div = args.v3.ucPostDiv; | ||
2719 | dividers->enable_post_div = (args.v3.ucCntlFlag & | ||
2720 | ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; | ||
2721 | dividers->enable_dithen = (args.v3.ucCntlFlag & | ||
2722 | ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; | ||
2723 | dividers->fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv); | ||
2724 | dividers->frac_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDivFrac); | ||
2725 | dividers->ref_div = args.v3.ucRefDiv; | ||
2726 | dividers->vco_mode = (args.v3.ucCntlFlag & | ||
2727 | ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; | ||
2728 | } else { | ||
2729 | args.v5.ulClock.ulComputeClockFlag = clock_type; | ||
2730 | args.v5.ulClock.ulClockFreq = cpu_to_le32(clock); /* 10 khz */ | ||
2731 | if (strobe_mode) | ||
2732 | args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN; | ||
2733 | |||
2734 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
2735 | |||
2736 | dividers->post_div = args.v5.ucPostDiv; | ||
2737 | dividers->enable_post_div = (args.v5.ucCntlFlag & | ||
2738 | ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; | ||
2739 | dividers->enable_dithen = (args.v5.ucCntlFlag & | ||
2740 | ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; | ||
2741 | dividers->whole_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDiv); | ||
2742 | dividers->frac_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDivFrac); | ||
2743 | dividers->ref_div = args.v5.ucRefDiv; | ||
2744 | dividers->vco_mode = (args.v5.ucCntlFlag & | ||
2745 | ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; | ||
2746 | } | ||
2747 | } | ||
2748 | break; | ||
2749 | case 4: | ||
2750 | /* fusion */ | ||
2751 | args.v4.ulClock = cpu_to_le32(clock); /* 10 khz */ | ||
2752 | |||
2753 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
2754 | |||
2755 | dividers->post_div = args.v4.ucPostDiv; | ||
2756 | dividers->real_clock = le32_to_cpu(args.v4.ulClock); | ||
2757 | break; | ||
2758 | default: | ||
2759 | return -EINVAL; | ||
2760 | } | ||
2761 | return 0; | ||
2762 | } | ||
2763 | |||
2657 | void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) | 2764 | void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) |
2658 | { | 2765 | { |
2659 | DYNAMIC_CLOCK_GATING_PS_ALLOCATION args; | 2766 | DYNAMIC_CLOCK_GATING_PS_ALLOCATION args; |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 4003f5a68c09..44e579e75fd0 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -492,6 +492,29 @@ struct radeon_framebuffer { | |||
492 | #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \ | 492 | #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \ |
493 | ((em) == ATOM_ENCODER_MODE_DP_MST)) | 493 | ((em) == ATOM_ENCODER_MODE_DP_MST)) |
494 | 494 | ||
495 | struct atom_clock_dividers { | ||
496 | u32 post_div; | ||
497 | union { | ||
498 | struct { | ||
499 | #ifdef __BIG_ENDIAN | ||
500 | u32 reserved : 6; | ||
501 | u32 whole_fb_div : 12; | ||
502 | u32 frac_fb_div : 14; | ||
503 | #else | ||
504 | u32 frac_fb_div : 14; | ||
505 | u32 whole_fb_div : 12; | ||
506 | u32 reserved : 6; | ||
507 | #endif | ||
508 | }; | ||
509 | u32 fb_div; | ||
510 | }; | ||
511 | u32 ref_div; | ||
512 | bool enable_post_div; | ||
513 | bool enable_dithen; | ||
514 | u32 vco_mode; | ||
515 | u32 real_clock; | ||
516 | }; | ||
517 | |||
495 | extern enum radeon_tv_std | 518 | extern enum radeon_tv_std |
496 | radeon_combios_get_tv_info(struct radeon_device *rdev); | 519 | radeon_combios_get_tv_info(struct radeon_device *rdev); |
497 | extern enum radeon_tv_std | 520 | extern enum radeon_tv_std |