Rev 2997 | Rev 5078 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2997 | Rev 3764 | ||
---|---|---|---|
Line 2026... | Line 2026... | ||
2026 | } |
2026 | } |
2027 | } |
2027 | } |
2028 | num_modes = power_info->info.ucNumOfPowerModeEntries; |
2028 | num_modes = power_info->info.ucNumOfPowerModeEntries; |
2029 | if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) |
2029 | if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) |
2030 | num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; |
2030 | num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; |
- | 2031 | if (num_modes == 0) |
|
- | 2032 | return state_index; |
|
2031 | rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL); |
2033 | rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL); |
2032 | if (!rdev->pm.power_state) |
2034 | if (!rdev->pm.power_state) |
2033 | return state_index; |
2035 | return state_index; |
2034 | /* last mode is usually default, array is low to high */ |
2036 | /* last mode is usually default, array is low to high */ |
2035 | for (i = 0; i < num_modes; i++) { |
2037 | for (i = 0; i < num_modes; i++) { |
Line 2305... | Line 2307... | ||
2305 | rdev->pm.power_state[state_index].type = |
2307 | rdev->pm.power_state[state_index].type = |
2306 | POWER_STATE_TYPE_DEFAULT; |
2308 | POWER_STATE_TYPE_DEFAULT; |
2307 | rdev->pm.default_power_state_index = state_index; |
2309 | rdev->pm.default_power_state_index = state_index; |
2308 | rdev->pm.power_state[state_index].default_clock_mode = |
2310 | rdev->pm.power_state[state_index].default_clock_mode = |
2309 | &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; |
2311 | &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; |
2310 | if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) { |
2312 | if ((rdev->family >= CHIP_BARTS) && !(rdev->flags & RADEON_IS_IGP)) { |
2311 | /* NI chips post without MC ucode, so default clocks are strobe mode only */ |
2313 | /* NI chips post without MC ucode, so default clocks are strobe mode only */ |
2312 | rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk; |
2314 | rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk; |
2313 | rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk; |
2315 | rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk; |
2314 | rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; |
2316 | rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; |
2315 | rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci; |
2317 | rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci; |
Line 2343... | Line 2345... | ||
2343 | } else { |
2345 | } else { |
2344 | sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow); |
2346 | sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow); |
2345 | sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; |
2347 | sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; |
2346 | rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; |
2348 | rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; |
2347 | } |
2349 | } |
2348 | } else if (ASIC_IS_DCE6(rdev)) { |
2350 | } else if (rdev->family >= CHIP_TAHITI) { |
2349 | sclk = le16_to_cpu(clock_info->si.usEngineClockLow); |
2351 | sclk = le16_to_cpu(clock_info->si.usEngineClockLow); |
2350 | sclk |= clock_info->si.ucEngineClockHigh << 16; |
2352 | sclk |= clock_info->si.ucEngineClockHigh << 16; |
2351 | mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); |
2353 | mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); |
2352 | mclk |= clock_info->si.ucMemoryClockHigh << 16; |
2354 | mclk |= clock_info->si.ucMemoryClockHigh << 16; |
2353 | rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; |
2355 | rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; |
Line 2356... | Line 2358... | ||
2356 | VOLTAGE_SW; |
2358 | VOLTAGE_SW; |
2357 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = |
2359 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = |
2358 | le16_to_cpu(clock_info->si.usVDDC); |
2360 | le16_to_cpu(clock_info->si.usVDDC); |
2359 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = |
2361 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = |
2360 | le16_to_cpu(clock_info->si.usVDDCI); |
2362 | le16_to_cpu(clock_info->si.usVDDCI); |
2361 | } else if (ASIC_IS_DCE4(rdev)) { |
2363 | } else if (rdev->family >= CHIP_CEDAR) { |
2362 | sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow); |
2364 | sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow); |
2363 | sclk |= clock_info->evergreen.ucEngineClockHigh << 16; |
2365 | sclk |= clock_info->evergreen.ucEngineClockHigh << 16; |
2364 | mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow); |
2366 | mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow); |
2365 | mclk |= clock_info->evergreen.ucMemoryClockHigh << 16; |
2367 | mclk |= clock_info->evergreen.ucMemoryClockHigh << 16; |
2366 | rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; |
2368 | rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; |
Line 2430... | Line 2432... | ||
2430 | &frev, &crev, &data_offset)) |
2432 | &frev, &crev, &data_offset)) |
2431 | return state_index; |
2433 | return state_index; |
2432 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); |
2434 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); |
Line 2433... | Line 2435... | ||
2433 | 2435 | ||
- | 2436 | radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); |
|
- | 2437 | if (power_info->pplib.ucNumStates == 0) |
|
2434 | radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); |
2438 | return state_index; |
2435 | rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * |
2439 | rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * |
2436 | power_info->pplib.ucNumStates, GFP_KERNEL); |
2440 | power_info->pplib.ucNumStates, GFP_KERNEL); |
2437 | if (!rdev->pm.power_state) |
2441 | if (!rdev->pm.power_state) |
2438 | return state_index; |
2442 | return state_index; |
Line 2512... | Line 2516... | ||
2512 | bool valid; |
2516 | bool valid; |
2513 | union power_info *power_info; |
2517 | union power_info *power_info; |
2514 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); |
2518 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); |
2515 | u16 data_offset; |
2519 | u16 data_offset; |
2516 | u8 frev, crev; |
2520 | u8 frev, crev; |
- | 2521 | u8 *power_state_offset; |
|
Line 2517... | Line 2522... | ||
2517 | 2522 | ||
2518 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, |
2523 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, |
2519 | &frev, &crev, &data_offset)) |
2524 | &frev, &crev, &data_offset)) |
2520 | return state_index; |
2525 | return state_index; |
Line 2528... | Line 2533... | ||
2528 | (mode_info->atom_context->bios + data_offset + |
2533 | (mode_info->atom_context->bios + data_offset + |
2529 | le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); |
2534 | le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); |
2530 | non_clock_info_array = (struct _NonClockInfoArray *) |
2535 | non_clock_info_array = (struct _NonClockInfoArray *) |
2531 | (mode_info->atom_context->bios + data_offset + |
2536 | (mode_info->atom_context->bios + data_offset + |
2532 | le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); |
2537 | le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); |
- | 2538 | if (state_array->ucNumEntries == 0) |
|
- | 2539 | return state_index; |
|
2533 | rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * |
2540 | rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * |
2534 | state_array->ucNumEntries, GFP_KERNEL); |
2541 | state_array->ucNumEntries, GFP_KERNEL); |
2535 | if (!rdev->pm.power_state) |
2542 | if (!rdev->pm.power_state) |
2536 | return state_index; |
2543 | return state_index; |
- | 2544 | power_state_offset = (u8 *)state_array->states; |
|
2537 | for (i = 0; i < state_array->ucNumEntries; i++) { |
2545 | for (i = 0; i < state_array->ucNumEntries; i++) { |
2538 | mode_index = 0; |
2546 | mode_index = 0; |
2539 | power_state = (union pplib_power_state *)&state_array->states[i]; |
2547 | power_state = (union pplib_power_state *)power_state_offset; |
2540 | /* XXX this might be an inagua bug... */ |
- | |
2541 | non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ |
2548 | non_clock_array_index = power_state->v2.nonClockInfoIndex; |
2542 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) |
2549 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) |
2543 | &non_clock_info_array->nonClockInfo[non_clock_array_index]; |
2550 | &non_clock_info_array->nonClockInfo[non_clock_array_index]; |
2544 | rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * |
2551 | rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * |
2545 | (power_state->v2.ucNumDPMLevels ? |
2552 | (power_state->v2.ucNumDPMLevels ? |
2546 | power_state->v2.ucNumDPMLevels : 1), |
2553 | power_state->v2.ucNumDPMLevels : 1), |
Line 2548... | Line 2555... | ||
2548 | if (!rdev->pm.power_state[i].clock_info) |
2555 | if (!rdev->pm.power_state[i].clock_info) |
2549 | return state_index; |
2556 | return state_index; |
2550 | if (power_state->v2.ucNumDPMLevels) { |
2557 | if (power_state->v2.ucNumDPMLevels) { |
2551 | for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { |
2558 | for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { |
2552 | clock_array_index = power_state->v2.clockInfoIndex[j]; |
2559 | clock_array_index = power_state->v2.clockInfoIndex[j]; |
2553 | /* XXX this might be an inagua bug... */ |
- | |
2554 | if (clock_array_index >= clock_info_array->ucNumEntries) |
- | |
2555 | continue; |
- | |
2556 | clock_info = (union pplib_clock_info *) |
2560 | clock_info = (union pplib_clock_info *) |
2557 | &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; |
2561 | &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; |
2558 | valid = radeon_atombios_parse_pplib_clock_info(rdev, |
2562 | valid = radeon_atombios_parse_pplib_clock_info(rdev, |
2559 | state_index, mode_index, |
2563 | state_index, mode_index, |
2560 | clock_info); |
2564 | clock_info); |
Line 2572... | Line 2576... | ||
2572 | if (mode_index) { |
2576 | if (mode_index) { |
2573 | radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, |
2577 | radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, |
2574 | non_clock_info); |
2578 | non_clock_info); |
2575 | state_index++; |
2579 | state_index++; |
2576 | } |
2580 | } |
- | 2581 | power_state_offset += 2 + power_state->v2.ucNumDPMLevels; |
|
2577 | } |
2582 | } |
2578 | /* if multiple clock modes, mark the lowest as no display */ |
2583 | /* if multiple clock modes, mark the lowest as no display */ |
2579 | for (i = 0; i < state_index; i++) { |
2584 | for (i = 0; i < state_index; i++) { |
2580 | if (rdev->pm.power_state[i].num_clock_modes > 1) |
2585 | if (rdev->pm.power_state[i].num_clock_modes > 1) |
2581 | rdev->pm.power_state[i].clock_info[0].flags |= |
2586 | rdev->pm.power_state[i].clock_info[0].flags |= |
Line 2618... | Line 2623... | ||
2618 | state_index = radeon_atombios_parse_power_table_6(rdev); |
2623 | state_index = radeon_atombios_parse_power_table_6(rdev); |
2619 | break; |
2624 | break; |
2620 | default: |
2625 | default: |
2621 | break; |
2626 | break; |
2622 | } |
2627 | } |
2623 | } else { |
2628 | } |
- | 2629 | ||
- | 2630 | if (state_index == 0) { |
|
2624 | rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL); |
2631 | rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL); |
2625 | if (rdev->pm.power_state) { |
2632 | if (rdev->pm.power_state) { |
2626 | rdev->pm.power_state[0].clock_info = |
2633 | rdev->pm.power_state[0].clock_info = |
2627 | kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); |
2634 | kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); |
2628 | if (rdev->pm.power_state[0].clock_info) { |
2635 | if (rdev->pm.power_state[0].clock_info) { |
Line 2652... | Line 2659... | ||
2652 | rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; |
2659 | rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; |
2653 | else |
2660 | else |
2654 | rdev->pm.current_vddc = 0; |
2661 | rdev->pm.current_vddc = 0; |
2655 | } |
2662 | } |
Line -... | Line 2663... | ||
- | 2663 | ||
- | 2664 | union get_clock_dividers { |
|
- | 2665 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS v1; |
|
- | 2666 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2 v2; |
|
- | 2667 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 v3; |
|
- | 2668 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 v4; |
|
- | 2669 | struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 v5; |
|
- | 2670 | }; |
|
- | 2671 | ||
- | 2672 | int radeon_atom_get_clock_dividers(struct radeon_device *rdev, |
|
- | 2673 | u8 clock_type, |
|
- | 2674 | u32 clock, |
|
- | 2675 | bool strobe_mode, |
|
- | 2676 | struct atom_clock_dividers *dividers) |
|
- | 2677 | { |
|
- | 2678 | union get_clock_dividers args; |
|
- | 2679 | int index = GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL); |
|
- | 2680 | u8 frev, crev; |
|
- | 2681 | ||
- | 2682 | memset(&args, 0, sizeof(args)); |
|
- | 2683 | memset(dividers, 0, sizeof(struct atom_clock_dividers)); |
|
- | 2684 | ||
- | 2685 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) |
|
- | 2686 | return -EINVAL; |
|
- | 2687 | ||
- | 2688 | switch (crev) { |
|
- | 2689 | case 1: |
|
- | 2690 | /* r4xx, r5xx */ |
|
- | 2691 | args.v1.ucAction = clock_type; |
|
- | 2692 | args.v1.ulClock = cpu_to_le32(clock); /* 10 khz */ |
|
- | 2693 | ||
- | 2694 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
- | 2695 | ||
- | 2696 | dividers->post_div = args.v1.ucPostDiv; |
|
- | 2697 | dividers->fb_div = args.v1.ucFbDiv; |
|
- | 2698 | dividers->enable_post_div = true; |
|
- | 2699 | break; |
|
- | 2700 | case 2: |
|
- | 2701 | case 3: |
|
- | 2702 | /* r6xx, r7xx, evergreen, ni */ |
|
- | 2703 | if (rdev->family <= CHIP_RV770) { |
|
- | 2704 | args.v2.ucAction = clock_type; |
|
- | 2705 | args.v2.ulClock = cpu_to_le32(clock); /* 10 khz */ |
|
- | 2706 | ||
- | 2707 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
- | 2708 | ||
- | 2709 | dividers->post_div = args.v2.ucPostDiv; |
|
- | 2710 | dividers->fb_div = le16_to_cpu(args.v2.usFbDiv); |
|
- | 2711 | dividers->ref_div = args.v2.ucAction; |
|
- | 2712 | if (rdev->family == CHIP_RV770) { |
|
- | 2713 | dividers->enable_post_div = (le32_to_cpu(args.v2.ulClock) & (1 << 24)) ? |
|
- | 2714 | true : false; |
|
- | 2715 | dividers->vco_mode = (le32_to_cpu(args.v2.ulClock) & (1 << 25)) ? 1 : 0; |
|
- | 2716 | } else |
|
- | 2717 | dividers->enable_post_div = (dividers->fb_div & 1) ? true : false; |
|
- | 2718 | } else { |
|
- | 2719 | if (clock_type == COMPUTE_ENGINE_PLL_PARAM) { |
|
- | 2720 | args.v3.ulClockParams = cpu_to_le32((clock_type << 24) | clock); |
|
- | 2721 | ||
- | 2722 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
- | 2723 | ||
- | 2724 | dividers->post_div = args.v3.ucPostDiv; |
|
- | 2725 | dividers->enable_post_div = (args.v3.ucCntlFlag & |
|
- | 2726 | ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; |
|
- | 2727 | dividers->enable_dithen = (args.v3.ucCntlFlag & |
|
- | 2728 | ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; |
|
- | 2729 | dividers->fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv); |
|
- | 2730 | dividers->frac_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDivFrac); |
|
- | 2731 | dividers->ref_div = args.v3.ucRefDiv; |
|
- | 2732 | dividers->vco_mode = (args.v3.ucCntlFlag & |
|
- | 2733 | ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; |
|
- | 2734 | } else { |
|
- | 2735 | args.v5.ulClockParams = cpu_to_le32((clock_type << 24) | clock); |
|
- | 2736 | if (strobe_mode) |
|
- | 2737 | args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN; |
|
- | 2738 | ||
- | 2739 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
- | 2740 | ||
- | 2741 | dividers->post_div = args.v5.ucPostDiv; |
|
- | 2742 | dividers->enable_post_div = (args.v5.ucCntlFlag & |
|
- | 2743 | ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; |
|
- | 2744 | dividers->enable_dithen = (args.v5.ucCntlFlag & |
|
- | 2745 | ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; |
|
- | 2746 | dividers->whole_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDiv); |
|
- | 2747 | dividers->frac_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDivFrac); |
|
- | 2748 | dividers->ref_div = args.v5.ucRefDiv; |
|
- | 2749 | dividers->vco_mode = (args.v5.ucCntlFlag & |
|
- | 2750 | ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; |
|
- | 2751 | } |
|
- | 2752 | } |
|
- | 2753 | break; |
|
- | 2754 | case 4: |
|
- | 2755 | /* fusion */ |
|
- | 2756 | args.v4.ulClock = cpu_to_le32(clock); /* 10 khz */ |
|
- | 2757 | ||
- | 2758 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
- | 2759 | ||
- | 2760 | dividers->post_div = args.v4.ucPostDiv; |
|
- | 2761 | dividers->real_clock = le32_to_cpu(args.v4.ulClock); |
|
- | 2762 | break; |
|
- | 2763 | default: |
|
- | 2764 | return -EINVAL; |
|
- | 2765 | } |
|
- | 2766 | return 0; |
|
- | 2767 | } |
|
2656 | 2768 | ||
2657 | void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) |
2769 | void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) |
2658 | { |
2770 | { |
2659 | DYNAMIC_CLOCK_GATING_PS_ALLOCATION args; |
2771 | DYNAMIC_CLOCK_GATING_PS_ALLOCATION args; |