| /* |
| * Copyright 2016 Advanced Micro Devices, Inc. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| * OTHER DEALINGS IN THE SOFTWARE. |
| * |
| */ |
| |
| #include "ppatomfwctrl.h" |
| #include "atomfirmware.h" |
| #include "pp_debug.h" |
| |
| |
| static const union atom_voltage_object_v4 *pp_atomfwctrl_lookup_voltage_type_v4( |
| const struct atom_voltage_objects_info_v4_1 *voltage_object_info_table, |
| uint8_t voltage_type, uint8_t voltage_mode) |
| { |
| unsigned int size = le16_to_cpu( |
| voltage_object_info_table->table_header.structuresize); |
| unsigned int offset = |
| offsetof(struct atom_voltage_objects_info_v4_1, voltage_object[0]); |
| unsigned long start = (unsigned long)voltage_object_info_table; |
| |
| while (offset < size) { |
| const union atom_voltage_object_v4 *voltage_object = |
| (const union atom_voltage_object_v4 *)(start + offset); |
| |
| if (voltage_type == voltage_object->gpio_voltage_obj.header.voltage_type && |
| voltage_mode == voltage_object->gpio_voltage_obj.header.voltage_mode) |
| return voltage_object; |
| |
| offset += le16_to_cpu(voltage_object->gpio_voltage_obj.header.object_size); |
| |
| } |
| |
| return NULL; |
| } |
| |
| static struct atom_voltage_objects_info_v4_1 *pp_atomfwctrl_get_voltage_info_table( |
| struct pp_hwmgr *hwmgr) |
| { |
| const void *table_address; |
| uint16_t idx; |
| |
| idx = GetIndexIntoMasterDataTable(voltageobject_info); |
| table_address = cgs_atom_get_data_table(hwmgr->device, |
| idx, NULL, NULL, NULL); |
| |
| PP_ASSERT_WITH_CODE( |
| table_address, |
| "Error retrieving BIOS Table Address!", |
| return NULL); |
| |
| return (struct atom_voltage_objects_info_v4_1 *)table_address; |
| } |
| |
| /** |
| * Returns TRUE if the given voltage type is controlled by GPIO pins. |
| * voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. |
| * voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE |
| */ |
| bool pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(struct pp_hwmgr *hwmgr, |
| uint8_t voltage_type, uint8_t voltage_mode) |
| { |
| struct atom_voltage_objects_info_v4_1 *voltage_info = |
| (struct atom_voltage_objects_info_v4_1 *) |
| pp_atomfwctrl_get_voltage_info_table(hwmgr); |
| bool ret; |
| |
| /* If we cannot find the table do NOT try to control this voltage. */ |
| PP_ASSERT_WITH_CODE(voltage_info, |
| "Could not find Voltage Table in BIOS.", |
| return false); |
| |
| ret = (pp_atomfwctrl_lookup_voltage_type_v4(voltage_info, |
| voltage_type, voltage_mode)) ? true : false; |
| |
| return ret; |
| } |
| |
| int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr *hwmgr, |
| uint8_t voltage_type, uint8_t voltage_mode, |
| struct pp_atomfwctrl_voltage_table *voltage_table) |
| { |
| struct atom_voltage_objects_info_v4_1 *voltage_info = |
| (struct atom_voltage_objects_info_v4_1 *) |
| pp_atomfwctrl_get_voltage_info_table(hwmgr); |
| const union atom_voltage_object_v4 *voltage_object; |
| unsigned int i; |
| int result = 0; |
| |
| PP_ASSERT_WITH_CODE(voltage_info, |
| "Could not find Voltage Table in BIOS.", |
| return -1); |
| |
| voltage_object = pp_atomfwctrl_lookup_voltage_type_v4(voltage_info, |
| voltage_type, voltage_mode); |
| |
| if (!voltage_object) |
| return -1; |
| |
| voltage_table->count = 0; |
| if (voltage_mode == VOLTAGE_OBJ_GPIO_LUT) { |
| PP_ASSERT_WITH_CODE( |
| (voltage_object->gpio_voltage_obj.gpio_entry_num <= |
| PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES), |
| "Too many voltage entries!", |
| result = -1); |
| |
| if (!result) { |
| for (i = 0; i < voltage_object->gpio_voltage_obj. |
| gpio_entry_num; i++) { |
| voltage_table->entries[i].value = |
| le16_to_cpu(voltage_object->gpio_voltage_obj. |
| voltage_gpio_lut[i].voltage_level_mv); |
| voltage_table->entries[i].smio_low = |
| le32_to_cpu(voltage_object->gpio_voltage_obj. |
| voltage_gpio_lut[i].voltage_gpio_reg_val); |
| } |
| voltage_table->count = |
| voltage_object->gpio_voltage_obj.gpio_entry_num; |
| voltage_table->mask_low = |
| le32_to_cpu( |
| voltage_object->gpio_voltage_obj.gpio_mask_val); |
| voltage_table->phase_delay = |
| voltage_object->gpio_voltage_obj.phase_delay_us; |
| } |
| } else if (voltage_mode == VOLTAGE_OBJ_SVID2) { |
| voltage_table->psi1_enable = |
| (voltage_object->svid2_voltage_obj.loadline_psi1 & 0x20) >> 5; |
| voltage_table->psi0_enable = |
| voltage_object->svid2_voltage_obj.psi0_enable & 0x1; |
| voltage_table->max_vid_step = |
| voltage_object->svid2_voltage_obj.maxvstep; |
| voltage_table->telemetry_offset = |
| voltage_object->svid2_voltage_obj.telemetry_offset; |
| voltage_table->telemetry_slope = |
| voltage_object->svid2_voltage_obj.telemetry_gain; |
| } else |
| PP_ASSERT_WITH_CODE(false, |
| "Unsupported Voltage Object Mode!", |
| result = -1); |
| |
| return result; |
| } |
| |
| |
| static struct atom_gpio_pin_lut_v2_1 *pp_atomfwctrl_get_gpio_lookup_table( |
| struct pp_hwmgr *hwmgr) |
| { |
| const void *table_address; |
| uint16_t idx; |
| |
| idx = GetIndexIntoMasterDataTable(gpio_pin_lut); |
| table_address = cgs_atom_get_data_table(hwmgr->device, |
| idx, NULL, NULL, NULL); |
| PP_ASSERT_WITH_CODE(table_address, |
| "Error retrieving BIOS Table Address!", |
| return NULL); |
| |
| return (struct atom_gpio_pin_lut_v2_1 *)table_address; |
| } |
| |
| static bool pp_atomfwctrl_lookup_gpio_pin( |
| struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table, |
| const uint32_t pin_id, |
| struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment) |
| { |
| unsigned int size = le16_to_cpu( |
| gpio_lookup_table->table_header.structuresize); |
| unsigned int offset = |
| offsetof(struct atom_gpio_pin_lut_v2_1, gpio_pin[0]); |
| unsigned long start = (unsigned long)gpio_lookup_table; |
| |
| while (offset < size) { |
| const struct atom_gpio_pin_assignment *pin_assignment = |
| (const struct atom_gpio_pin_assignment *)(start + offset); |
| |
| if (pin_id == pin_assignment->gpio_id) { |
| gpio_pin_assignment->uc_gpio_pin_bit_shift = |
| pin_assignment->gpio_bitshift; |
| gpio_pin_assignment->us_gpio_pin_aindex = |
| le16_to_cpu(pin_assignment->data_a_reg_index); |
| return true; |
| } |
| offset += offsetof(struct atom_gpio_pin_assignment, gpio_id) + 1; |
| } |
| return false; |
| } |
| |
| /** |
| * Returns TRUE if the given pin id find in lookup table. |
| */ |
| bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, |
| const uint32_t pin_id, |
| struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment) |
| { |
| bool ret = false; |
| struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table = |
| pp_atomfwctrl_get_gpio_lookup_table(hwmgr); |
| |
| /* If we cannot find the table do NOT try to control this voltage. */ |
| PP_ASSERT_WITH_CODE(gpio_lookup_table, |
| "Could not find GPIO lookup Table in BIOS.", |
| return false); |
| |
| ret = pp_atomfwctrl_lookup_gpio_pin(gpio_lookup_table, |
| pin_id, gpio_pin_assignment); |
| |
| return ret; |
| } |
| |
| /** |
| * Enter to SelfRefresh mode. |
| * @param hwmgr |
| */ |
| int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr) |
| { |
| /* 0 - no action |
| * 1 - leave power to video memory always on |
| */ |
| return 0; |
| } |
| |
| /** pp_atomfwctrl_get_gpu_pll_dividers_vega10(). |
| * |
| * @param hwmgr input parameter: pointer to HwMgr |
| * @param clock_type input parameter: Clock type: 1 - GFXCLK, 2 - UCLK, 0 - All other clocks |
| * @param clock_value input parameter: Clock |
| * @param dividers output parameter:Clock dividers |
| */ |
| int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr, |
| uint32_t clock_type, uint32_t clock_value, |
| struct pp_atomfwctrl_clock_dividers_soc15 *dividers) |
| { |
| struct compute_gpu_clock_input_parameter_v1_8 pll_parameters; |
| struct compute_gpu_clock_output_parameter_v1_8 *pll_output; |
| int result; |
| uint32_t idx; |
| |
| pll_parameters.gpuclock_10khz = (uint32_t)clock_value; |
| pll_parameters.gpu_clock_type = clock_type; |
| |
| idx = GetIndexIntoMasterCmdTable(computegpuclockparam); |
| result = cgs_atom_exec_cmd_table(hwmgr->device, idx, &pll_parameters); |
| |
| if (!result) { |
| pll_output = (struct compute_gpu_clock_output_parameter_v1_8 *) |
| &pll_parameters; |
| dividers->ulClock = le32_to_cpu(pll_output->gpuclock_10khz); |
| dividers->ulDid = le32_to_cpu(pll_output->dfs_did); |
| dividers->ulPll_fb_mult = le32_to_cpu(pll_output->pll_fb_mult); |
| dividers->ulPll_ss_fbsmult = le32_to_cpu(pll_output->pll_ss_fbsmult); |
| dividers->usPll_ss_slew_frac = le16_to_cpu(pll_output->pll_ss_slew_frac); |
| dividers->ucPll_ss_enable = pll_output->pll_ss_enable; |
| } |
| return result; |
| } |
| |
| int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr, |
| struct pp_atomfwctrl_avfs_parameters *param) |
| { |
| uint16_t idx; |
| uint8_t format_revision, content_revision; |
| |
| struct atom_asic_profiling_info_v4_1 *profile; |
| struct atom_asic_profiling_info_v4_2 *profile_v4_2; |
| |
| idx = GetIndexIntoMasterDataTable(asic_profiling_info); |
| profile = (struct atom_asic_profiling_info_v4_1 *) |
| cgs_atom_get_data_table(hwmgr->device, |
| idx, NULL, NULL, NULL); |
| |
| if (!profile) |
| return -1; |
| |
| format_revision = ((struct atom_common_table_header *)profile)->format_revision; |
| content_revision = ((struct atom_common_table_header *)profile)->content_revision; |
| |
| if (format_revision == 4 && content_revision == 1) { |
| param->ulMaxVddc = le32_to_cpu(profile->maxvddc); |
| param->ulMinVddc = le32_to_cpu(profile->minvddc); |
| param->ulMeanNsigmaAcontant0 = |
| le32_to_cpu(profile->avfs_meannsigma_acontant0); |
| param->ulMeanNsigmaAcontant1 = |
| le32_to_cpu(profile->avfs_meannsigma_acontant1); |
| param->ulMeanNsigmaAcontant2 = |
| le32_to_cpu(profile->avfs_meannsigma_acontant2); |
| param->usMeanNsigmaDcTolSigma = |
| le16_to_cpu(profile->avfs_meannsigma_dc_tol_sigma); |
| param->usMeanNsigmaPlatformMean = |
| le16_to_cpu(profile->avfs_meannsigma_platform_mean); |
| param->usMeanNsigmaPlatformSigma = |
| le16_to_cpu(profile->avfs_meannsigma_platform_sigma); |
| param->ulGbVdroopTableCksoffA0 = |
| le32_to_cpu(profile->gb_vdroop_table_cksoff_a0); |
| param->ulGbVdroopTableCksoffA1 = |
| le32_to_cpu(profile->gb_vdroop_table_cksoff_a1); |
| param->ulGbVdroopTableCksoffA2 = |
| le32_to_cpu(profile->gb_vdroop_table_cksoff_a2); |
| param->ulGbVdroopTableCksonA0 = |
| le32_to_cpu(profile->gb_vdroop_table_ckson_a0); |
| param->ulGbVdroopTableCksonA1 = |
| le32_to_cpu(profile->gb_vdroop_table_ckson_a1); |
| param->ulGbVdroopTableCksonA2 = |
| le32_to_cpu(profile->gb_vdroop_table_ckson_a2); |
| param->ulGbFuseTableCksoffM1 = |
| le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m1); |
| param->ulGbFuseTableCksoffM2 = |
| le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m2); |
| param->ulGbFuseTableCksoffB = |
| le32_to_cpu(profile->avfsgb_fuse_table_cksoff_b); |
| param->ulGbFuseTableCksonM1 = |
| le32_to_cpu(profile->avfsgb_fuse_table_ckson_m1); |
| param->ulGbFuseTableCksonM2 = |
| le32_to_cpu(profile->avfsgb_fuse_table_ckson_m2); |
| param->ulGbFuseTableCksonB = |
| le32_to_cpu(profile->avfsgb_fuse_table_ckson_b); |
| |
| param->ucEnableGbVdroopTableCkson = |
| profile->enable_gb_vdroop_table_ckson; |
| param->ucEnableGbFuseTableCkson = |
| profile->enable_gb_fuse_table_ckson; |
| param->usPsmAgeComfactor = |
| le16_to_cpu(profile->psm_age_comfactor); |
| |
| param->ulDispclk2GfxclkM1 = |
| le32_to_cpu(profile->dispclk2gfxclk_a); |
| param->ulDispclk2GfxclkM2 = |
| le32_to_cpu(profile->dispclk2gfxclk_b); |
| param->ulDispclk2GfxclkB = |
| le32_to_cpu(profile->dispclk2gfxclk_c); |
| param->ulDcefclk2GfxclkM1 = |
| le32_to_cpu(profile->dcefclk2gfxclk_a); |
| param->ulDcefclk2GfxclkM2 = |
| le32_to_cpu(profile->dcefclk2gfxclk_b); |
| param->ulDcefclk2GfxclkB = |
| le32_to_cpu(profile->dcefclk2gfxclk_c); |
| param->ulPixelclk2GfxclkM1 = |
| le32_to_cpu(profile->pixclk2gfxclk_a); |
| param->ulPixelclk2GfxclkM2 = |
| le32_to_cpu(profile->pixclk2gfxclk_b); |
| param->ulPixelclk2GfxclkB = |
| le32_to_cpu(profile->pixclk2gfxclk_c); |
| param->ulPhyclk2GfxclkM1 = |
| le32_to_cpu(profile->phyclk2gfxclk_a); |
| param->ulPhyclk2GfxclkM2 = |
| le32_to_cpu(profile->phyclk2gfxclk_b); |
| param->ulPhyclk2GfxclkB = |
| le32_to_cpu(profile->phyclk2gfxclk_c); |
| param->ulAcgGbVdroopTableA0 = 0; |
| param->ulAcgGbVdroopTableA1 = 0; |
| param->ulAcgGbVdroopTableA2 = 0; |
| param->ulAcgGbFuseTableM1 = 0; |
| param->ulAcgGbFuseTableM2 = 0; |
| param->ulAcgGbFuseTableB = 0; |
| param->ucAcgEnableGbVdroopTable = 0; |
| param->ucAcgEnableGbFuseTable = 0; |
| } else if (format_revision == 4 && content_revision == 2) { |
| profile_v4_2 = (struct atom_asic_profiling_info_v4_2 *)profile; |
| param->ulMaxVddc = le32_to_cpu(profile_v4_2->maxvddc); |
| param->ulMinVddc = le32_to_cpu(profile_v4_2->minvddc); |
| param->ulMeanNsigmaAcontant0 = |
| le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant0); |
| param->ulMeanNsigmaAcontant1 = |
| le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant1); |
| param->ulMeanNsigmaAcontant2 = |
| le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant2); |
| param->usMeanNsigmaDcTolSigma = |
| le16_to_cpu(profile_v4_2->avfs_meannsigma_dc_tol_sigma); |
| param->usMeanNsigmaPlatformMean = |
| le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_mean); |
| param->usMeanNsigmaPlatformSigma = |
| le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_sigma); |
| param->ulGbVdroopTableCksoffA0 = |
| le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a0); |
| param->ulGbVdroopTableCksoffA1 = |
| le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a1); |
| param->ulGbVdroopTableCksoffA2 = |
| le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a2); |
| param->ulGbVdroopTableCksonA0 = |
| le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a0); |
| param->ulGbVdroopTableCksonA1 = |
| le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a1); |
| param->ulGbVdroopTableCksonA2 = |
| le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a2); |
| param->ulGbFuseTableCksoffM1 = |
| le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m1); |
| param->ulGbFuseTableCksoffM2 = |
| le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m2); |
| param->ulGbFuseTableCksoffB = |
| le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_b); |
| param->ulGbFuseTableCksonM1 = |
| le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m1); |
| param->ulGbFuseTableCksonM2 = |
| le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m2); |
| param->ulGbFuseTableCksonB = |
| le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_b); |
| |
| param->ucEnableGbVdroopTableCkson = |
| profile_v4_2->enable_gb_vdroop_table_ckson; |
| param->ucEnableGbFuseTableCkson = |
| profile_v4_2->enable_gb_fuse_table_ckson; |
| param->usPsmAgeComfactor = |
| le16_to_cpu(profile_v4_2->psm_age_comfactor); |
| |
| param->ulDispclk2GfxclkM1 = |
| le32_to_cpu(profile_v4_2->dispclk2gfxclk_a); |
| param->ulDispclk2GfxclkM2 = |
| le32_to_cpu(profile_v4_2->dispclk2gfxclk_b); |
| param->ulDispclk2GfxclkB = |
| le32_to_cpu(profile_v4_2->dispclk2gfxclk_c); |
| param->ulDcefclk2GfxclkM1 = |
| le32_to_cpu(profile_v4_2->dcefclk2gfxclk_a); |
| param->ulDcefclk2GfxclkM2 = |
| le32_to_cpu(profile_v4_2->dcefclk2gfxclk_b); |
| param->ulDcefclk2GfxclkB = |
| le32_to_cpu(profile_v4_2->dcefclk2gfxclk_c); |
| param->ulPixelclk2GfxclkM1 = |
| le32_to_cpu(profile_v4_2->pixclk2gfxclk_a); |
| param->ulPixelclk2GfxclkM2 = |
| le32_to_cpu(profile_v4_2->pixclk2gfxclk_b); |
| param->ulPixelclk2GfxclkB = |
| le32_to_cpu(profile_v4_2->pixclk2gfxclk_c); |
| param->ulPhyclk2GfxclkM1 = |
| le32_to_cpu(profile->phyclk2gfxclk_a); |
| param->ulPhyclk2GfxclkM2 = |
| le32_to_cpu(profile_v4_2->phyclk2gfxclk_b); |
| param->ulPhyclk2GfxclkB = |
| le32_to_cpu(profile_v4_2->phyclk2gfxclk_c); |
| param->ulAcgGbVdroopTableA0 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a0); |
| param->ulAcgGbVdroopTableA1 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a1); |
| param->ulAcgGbVdroopTableA2 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a2); |
| param->ulAcgGbFuseTableM1 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m1); |
| param->ulAcgGbFuseTableM2 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m2); |
| param->ulAcgGbFuseTableB = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_b); |
| param->ucAcgEnableGbVdroopTable = le32_to_cpu(profile_v4_2->enable_acg_gb_vdroop_table); |
| param->ucAcgEnableGbFuseTable = le32_to_cpu(profile_v4_2->enable_acg_gb_fuse_table); |
| } else { |
| pr_info("Invalid VBIOS AVFS ProfilingInfo Revision!\n"); |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr, |
| struct pp_atomfwctrl_gpio_parameters *param) |
| { |
| struct atom_smu_info_v3_1 *info; |
| uint16_t idx; |
| |
| idx = GetIndexIntoMasterDataTable(smu_info); |
| info = (struct atom_smu_info_v3_1 *) |
| cgs_atom_get_data_table(hwmgr->device, |
| idx, NULL, NULL, NULL); |
| |
| if (!info) { |
| pr_info("Error retrieving BIOS smu_info Table Address!"); |
| return -1; |
| } |
| |
| param->ucAcDcGpio = info->ac_dc_gpio_bit; |
| param->ucAcDcPolarity = info->ac_dc_polarity; |
| param->ucVR0HotGpio = info->vr0hot_gpio_bit; |
| param->ucVR0HotPolarity = info->vr0hot_polarity; |
| param->ucVR1HotGpio = info->vr1hot_gpio_bit; |
| param->ucVR1HotPolarity = info->vr1hot_polarity; |
| param->ucFwCtfGpio = info->fw_ctf_gpio_bit; |
| param->ucFwCtfPolarity = info->fw_ctf_polarity; |
| |
| return 0; |
| } |
| |
| int pp_atomfwctrl__get_clk_information_by_clkid(struct pp_hwmgr *hwmgr, BIOS_CLKID id, uint32_t *frequency) |
| { |
| struct atom_get_smu_clock_info_parameters_v3_1 parameters; |
| struct atom_get_smu_clock_info_output_parameters_v3_1 *output; |
| uint32_t ix; |
| |
| parameters.clk_id = id; |
| parameters.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ; |
| |
| ix = GetIndexIntoMasterCmdTable(getsmuclockinfo); |
| if (!cgs_atom_exec_cmd_table(hwmgr->device, ix, ¶meters)) { |
| output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)¶meters; |
| *frequency = output->atom_smu_outputclkfreq.smu_clock_freq_hz / 10000; |
| } else { |
| pr_info("Error execute_table getsmuclockinfo!"); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr, |
| struct pp_atomfwctrl_bios_boot_up_values *boot_values) |
| { |
| struct atom_firmware_info_v3_1 *info = NULL; |
| uint16_t ix; |
| uint32_t frequency = 0; |
| |
| ix = GetIndexIntoMasterDataTable(firmwareinfo); |
| info = (struct atom_firmware_info_v3_1 *) |
| cgs_atom_get_data_table(hwmgr->device, |
| ix, NULL, NULL, NULL); |
| |
| if (!info) { |
| pr_info("Error retrieving BIOS firmwareinfo!"); |
| return -EINVAL; |
| } |
| |
| boot_values->ulRevision = info->firmware_revision; |
| boot_values->ulGfxClk = info->bootup_sclk_in10khz; |
| boot_values->ulUClk = info->bootup_mclk_in10khz; |
| boot_values->usVddc = info->bootup_vddc_mv; |
| boot_values->usVddci = info->bootup_vddci_mv; |
| boot_values->usMvddc = info->bootup_mvddc_mv; |
| boot_values->usVddGfx = info->bootup_vddgfx_mv; |
| boot_values->ulSocClk = 0; |
| boot_values->ulDCEFClk = 0; |
| |
| if (!pp_atomfwctrl__get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_SOCCLK_ID, &frequency)) |
| boot_values->ulSocClk = frequency; |
| |
| if (!pp_atomfwctrl__get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_DCEFCLK_ID, &frequency)) |
| boot_values->ulDCEFClk = frequency; |
| |
| return 0; |
| } |