From: Maruthi Srinivas Bayyavarapu <maruthi.bayyavar...@amd.com>

v2: renamed _atom_ to _atombios_ for consistency
    added ulClockParams to _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 and
    _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 to avoid build break

Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu at amd.com>
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 158 +++++++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h |  16 ++-
 drivers/gpu/drm/amd/include/atombios.h       |   2 +
 3 files changed, 175 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 9df1bcb..033a22c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -960,6 +960,48 @@ int amdgpu_atombios_get_clock_dividers(struct 
amdgpu_device *adev,
                return -EINVAL;

        switch (crev) {
+       case 2:
+       case 3:
+       case 5:
+               /* r6xx, r7xx, evergreen, ni, si.
+                * TODO: add support for asic_type <= CHIP_RV770*/
+               if (clock_type == COMPUTE_ENGINE_PLL_PARAM) {
+                       args.v3.ulClockParams = cpu_to_le32((clock_type << 24) 
| clock);
+
+                       amdgpu_atom_execute_table(adev->mode_info.atom_context, 
index, (uint32_t *)&args);
+
+                       dividers->post_div = args.v3.ucPostDiv;
+                       dividers->enable_post_div = (args.v3.ucCntlFlag &
+                                                    
ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false;
+                       dividers->enable_dithen = (args.v3.ucCntlFlag &
+                                                  
ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true;
+                       dividers->whole_fb_div = 
le16_to_cpu(args.v3.ulFbDiv.usFbDiv);
+                       dividers->frac_fb_div = 
le16_to_cpu(args.v3.ulFbDiv.usFbDivFrac);
+                       dividers->ref_div = args.v3.ucRefDiv;
+                       dividers->vco_mode = (args.v3.ucCntlFlag &
+                                             ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) 
? 1 : 0;
+               } else {
+                       /* for SI we use ComputeMemoryClockParam for memory 
plls */
+                       if (adev->asic_type >= CHIP_TAHITI)
+                               return -EINVAL;
+                       args.v5.ulClockParams = cpu_to_le32((clock_type << 24) 
| clock);
+                       if (strobe_mode)
+                               args.v5.ucInputFlag = 
ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN;
+
+                       amdgpu_atom_execute_table(adev->mode_info.atom_context, 
index, (uint32_t *)&args);
+
+                       dividers->post_div = args.v5.ucPostDiv;
+                       dividers->enable_post_div = (args.v5.ucCntlFlag &
+                                                    
ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false;
+                       dividers->enable_dithen = (args.v5.ucCntlFlag &
+                                                  
ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true;
+                       dividers->whole_fb_div = 
le16_to_cpu(args.v5.ulFbDiv.usFbDiv);
+                       dividers->frac_fb_div = 
le16_to_cpu(args.v5.ulFbDiv.usFbDivFrac);
+                       dividers->ref_div = args.v5.ucRefDiv;
+                       dividers->vco_mode = (args.v5.ucCntlFlag &
+                                             ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) 
? 1 : 0;
+               }
+               break;
        case 4:
                /* fusion */
                args.v4.ulClock = cpu_to_le32(clock);   /* 10 khz */
@@ -1104,6 +1146,32 @@ void amdgpu_atombios_set_engine_dram_timings(struct 
amdgpu_device *adev,
        amdgpu_atom_execute_table(adev->mode_info.atom_context, index, 
(uint32_t *)&args);
 }

+void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev,
+                                         u16 *vddc, u16 *vddci, u16 *mvdd)
+{
+       struct amdgpu_mode_info *mode_info = &adev->mode_info;
+       int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+       u8 frev, crev;
+       u16 data_offset;
+       union firmware_info *firmware_info;
+
+       *vddc = 0;
+       *vddci = 0;
+       *mvdd = 0;
+
+       if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               firmware_info =
+                       (union firmware_info *)(mode_info->atom_context->bios +
+                                               data_offset);
+               *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
+               if ((frev == 2) && (crev >= 2)) {
+                       *vddci = 
le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage);
+                       *mvdd = 
le16_to_cpu(firmware_info->info_22.usBootUpMVDDCVoltage);
+               }
+       }
+}
+
 union set_voltage {
        struct _SET_VOLTAGE_PS_ALLOCATION alloc;
        struct _SET_VOLTAGE_PARAMETERS v1;
@@ -1111,6 +1179,52 @@ union set_voltage {
        struct _SET_VOLTAGE_PARAMETERS_V1_3 v3;
 };

+int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
+                            u16 voltage_id, u16 *voltage)
+{
+       union set_voltage args;
+       int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
+       u8 frev, crev;
+
+       if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, 
&frev, &crev))
+               return -EINVAL;
+
+       switch (crev) {
+       case 1:
+               return -EINVAL;
+       case 2:
+               args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE;
+               args.v2.ucVoltageMode = 0;
+               args.v2.usVoltageLevel = 0;
+
+               amdgpu_atom_execute_table(adev->mode_info.atom_context, index, 
(uint32_t *)&args);
+
+               *voltage = le16_to_cpu(args.v2.usVoltageLevel);
+               break;
+       case 3:
+               args.v3.ucVoltageType = voltage_type;
+               args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL;
+               args.v3.usVoltageLevel = cpu_to_le16(voltage_id);
+
+               amdgpu_atom_execute_table(adev->mode_info.atom_context, index, 
(uint32_t *)&args);
+
+               *voltage = le16_to_cpu(args.v3.usVoltageLevel);
+               break;
+       default:
+               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device 
*adev,
+                                                     u16 *voltage,
+                                                     u16 leakage_idx)
+{
+       return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, 
leakage_idx, voltage);
+}
+
 void amdgpu_atombios_set_voltage(struct amdgpu_device *adev,
                                 u16 voltage_level,
                                 u8 voltage_type)
@@ -1331,6 +1445,50 @@ static ATOM_VOLTAGE_OBJECT_V3 
*amdgpu_atombios_lookup_voltage_object_v3(ATOM_VOL
        return NULL;
 }

+int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev,
+                             u8 voltage_type,
+                             u8 *svd_gpio_id, u8 *svc_gpio_id)
+{
+       int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
+       u8 frev, crev;
+       u16 data_offset, size;
+       union voltage_object_info *voltage_info;
+       union voltage_object *voltage_object = NULL;
+
+       if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, 
&size,
+                                  &frev, &crev, &data_offset)) {
+               voltage_info = (union voltage_object_info *)
+                       (adev->mode_info.atom_context->bios + data_offset);
+
+               switch (frev) {
+               case 3:
+                       switch (crev) {
+                       case 1:
+                               voltage_object = (union voltage_object *)
+                                       
amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3,
+                                                                     
voltage_type,
+                                                                     
VOLTAGE_OBJ_SVID2);
+                               if (voltage_object) {
+                                       *svd_gpio_id = 
voltage_object->v3.asSVID2Obj.ucSVDGpioId;
+                                       *svc_gpio_id = 
voltage_object->v3.asSVID2Obj.ucSVCGpioId;
+                               } else {
+                                       return -EINVAL;
+                               }
+                               break;
+                       default:
+                               DRM_ERROR("unknown voltage object table\n");
+                               return -EINVAL;
+                       }
+                       break;
+               default:
+                       DRM_ERROR("unknown voltage object table\n");
+                       return -EINVAL;
+               }
+
+       }
+       return 0;
+}
+
 bool
 amdgpu_atombios_is_voltage_gpio(struct amdgpu_device *adev,
                                u8 voltage_type, u8 voltage_mode)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
index 8c2e696..ec4f941 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
@@ -206,5 +206,19 @@ void amdgpu_atombios_scratch_regs_save(struct 
amdgpu_device *adev);
 void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev);

 void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
-
+int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
+                            u16 voltage_id, u16 *voltage);
+int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device 
*adev,
+                                                     u16 *voltage,
+                                                     u16 leakage_idx);
+void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev,
+                                         u16 *vddc, u16 *vddci, u16 *mvdd);
+int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
+                                      u8 clock_type,
+                                      u32 clock,
+                                      bool strobe_mode,
+                                      struct atom_clock_dividers *dividers);
+int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev,
+                             u8 voltage_type,
+                             u8 *svd_gpio_id, u8 *svc_gpio_id);
 #endif
diff --git a/drivers/gpu/drm/amd/include/atombios.h 
b/drivers/gpu/drm/amd/include/atombios.h
index 32f3e34..b84201b 100644
--- a/drivers/gpu/drm/amd/include/atombios.h
+++ b/drivers/gpu/drm/amd/include/atombios.h
@@ -494,6 +494,7 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3
   union
   {
     ATOM_COMPUTE_CLOCK_FREQ  ulClock;         //Input Parameter
+    ULONG ulClockParams;                      //ULONG access for BE
     ATOM_S_MPLL_FB_DIVIDER   ulFbDiv;         //Output Parameter
   };
   UCHAR   ucRefDiv;                           //Output Parameter
@@ -526,6 +527,7 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5
   union
   {
     ATOM_COMPUTE_CLOCK_FREQ  ulClock;         //Input Parameter
+    ULONG ulClockParams;                      //ULONG access for BE
     ATOM_S_MPLL_FB_DIVIDER   ulFbDiv;         //Output Parameter
   };
   UCHAR   ucRefDiv;                           //Output Parameter
-- 
2.5.5

Reply via email to