Merge tag 'wberr-v4.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_atomfirmware.c
index 4bdda56fcceea36b8229d74ac3b76fe706919a77..f9ffe8ef0cd60a85ae4180f66727f791e8679622 100644 (file)
@@ -66,41 +66,6 @@ void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev)
        }
 }
 
-void amdgpu_atomfirmware_scratch_regs_save(struct amdgpu_device *adev)
-{
-       int i;
-
-       for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++)
-               adev->bios_scratch[i] = RREG32(adev->bios_scratch_reg_offset + i);
-}
-
-void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev)
-{
-       int i;
-
-       /*
-        * VBIOS will check ASIC_INIT_COMPLETE bit to decide if
-        * execute ASIC_Init posting via driver
-        */
-       adev->bios_scratch[7] &= ~ATOM_S7_ASIC_INIT_COMPLETE_MASK;
-
-       for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++)
-               WREG32(adev->bios_scratch_reg_offset + i, adev->bios_scratch[i]);
-}
-
-void amdgpu_atomfirmware_scratch_regs_engine_hung(struct amdgpu_device *adev,
-                                                 bool hung)
-{
-       u32 tmp = RREG32(adev->bios_scratch_reg_offset + 3);
-
-       if (hung)
-               tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
-       else
-               tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
-
-       WREG32(adev->bios_scratch_reg_offset + 3, tmp);
-}
-
 int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)
 {
        struct atom_context *ctx = adev->mode_info.atom_context;
@@ -130,3 +95,129 @@ int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)
        ctx->scratch_size_bytes = usage_bytes;
        return 0;
 }
+
+union igp_info {
+       struct atom_integrated_system_info_v1_11 v11;
+};
+
+/*
+ * Return vram width from integrated system info table, if available,
+ * or 0 if not.
+ */
+int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev)
+{
+       struct amdgpu_mode_info *mode_info = &adev->mode_info;
+       int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+                                               integratedsysteminfo);
+       u16 data_offset, size;
+       union igp_info *igp_info;
+       u8 frev, crev;
+
+       /* get any igp specific overrides */
+       if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size,
+                                  &frev, &crev, &data_offset)) {
+               igp_info = (union igp_info *)
+                       (mode_info->atom_context->bios + data_offset);
+               switch (crev) {
+               case 11:
+                       return igp_info->v11.umachannelnumber * 64;
+               default:
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
+union firmware_info {
+       struct atom_firmware_info_v3_1 v31;
+};
+
+union smu_info {
+       struct atom_smu_info_v3_1 v31;
+};
+
+union umc_info {
+       struct atom_umc_info_v3_1 v31;
+};
+
+int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev)
+{
+       struct amdgpu_mode_info *mode_info = &adev->mode_info;
+       struct amdgpu_pll *spll = &adev->clock.spll;
+       struct amdgpu_pll *mpll = &adev->clock.mpll;
+       uint8_t frev, crev;
+       uint16_t data_offset;
+       int ret = -EINVAL, index;
+
+       index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+                                           firmwareinfo);
+       if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               union firmware_info *firmware_info =
+                       (union firmware_info *)(mode_info->atom_context->bios +
+                                               data_offset);
+
+               adev->clock.default_sclk =
+                       le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz);
+               adev->clock.default_mclk =
+                       le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz);
+
+               adev->pm.current_sclk = adev->clock.default_sclk;
+               adev->pm.current_mclk = adev->clock.default_mclk;
+
+               /* not technically a clock, but... */
+               adev->mode_info.firmware_flags =
+                       le32_to_cpu(firmware_info->v31.firmware_capability);
+
+               ret = 0;
+       }
+
+       index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+                                           smu_info);
+       if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               union smu_info *smu_info =
+                       (union smu_info *)(mode_info->atom_context->bios +
+                                          data_offset);
+
+               /* system clock */
+               spll->reference_freq = le32_to_cpu(smu_info->v31.core_refclk_10khz);
+
+               spll->reference_div = 0;
+               spll->min_post_div = 1;
+               spll->max_post_div = 1;
+               spll->min_ref_div = 2;
+               spll->max_ref_div = 0xff;
+               spll->min_feedback_div = 4;
+               spll->max_feedback_div = 0xff;
+               spll->best_vco = 0;
+
+               ret = 0;
+       }
+
+       index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+                                           umc_info);
+       if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               union umc_info *umc_info =
+                       (union umc_info *)(mode_info->atom_context->bios +
+                                          data_offset);
+
+               /* memory clock */
+               mpll->reference_freq = le32_to_cpu(umc_info->v31.mem_refclk_10khz);
+
+               mpll->reference_div = 0;
+               mpll->min_post_div = 1;
+               mpll->max_post_div = 1;
+               mpll->min_ref_div = 2;
+               mpll->max_ref_div = 0xff;
+               mpll->min_feedback_div = 4;
+               mpll->max_feedback_div = 0xff;
+               mpll->best_vco = 0;
+
+               ret = 0;
+       }
+
+       return ret;
+}