提交 0bf0ea43 编写于 作者: L Linus Torvalds

Merge tag 'drm-fixes-for-v4.7-rc5' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "This is the drm fixes tree for 4.7-rc5.

  It's a bit larger than normal, due to fixes for production AMD Polaris
  GPUs.  We only merged support for these in 4.7-rc1 so it would be good
  if we got all the fixes into final.  The changes don't hit any other
  hardware.

  Other than the amdgpu Polaris changes:

   - A single fix for atomic modesetting WARN
   - Nouveau fix for when fbdev is disabled
   - i915 fixes for FBC on Haswell and displayport regression
   - Exynos fix for a display panel regression and some other minor changes
   - Atmel fixes for scaling and OF graph interaction
   - Allwiinner build, warning and probing fixes
   - AMD GPU non-polaris fix for num_rbs and some minor fixes

  Also I've just moved house, and my new place is Internet challenged
  due to incompetent incumbent ISPs, hopefully sorted out in a couple of
  weeks, so I might not be too responsive over the next while.  It also
  helps Daniel is on holidays for those couple of weeks as well"

* tag 'drm-fixes-for-v4.7-rc5' of git://people.freedesktop.org/~airlied/linux: (38 commits)
  drm/atomic: Make drm_atomic_legacy_backoff reset crtc->acquire_ctx
  drm/nouveau: fix for disabled fbdev emulation
  drm/i915/fbc: Disable on HSW by default for now
  drm/i915: Revert DisplayPort fast link training feature
  drm/amd/powerplay: enable clock stretch feature for polaris
  drm/amdgpu/gfx8: update golden setting for polaris10
  drm/amd/powerplay: enable avfs feature for polaris
  drm/amdgpu/atombios: add avfs struct for Polaris10/11
  drm/amd/powerplay: add avfs related define for polaris
  drm/amd/powrplay: enable stutter_mode for polaris.
  drm/amd/powerplay: disable UVD SMU handshake for MCLK.
  drm/amd/powerplay: initialize variables which were missed.
  drm/amd/powerplay: enable PowerContainment feature for polaris10/11.
  drm/amd/powerplay: need to notify system bios pcie device ready
  drm/amd/powerplay: fix bug that function parameter was incorect.
  drm/amd/powerplay: fix logic error.
  drm: atmel-hlcdc: Fix OF graph parsing
  drm: atmel-hlcdc: actually disable scaling when no scaling is required
  drm/amdgpu: initialize amdgpu_cgs_acpi_eval_object result value
  drm/amdgpu: precedence bug in amdgpu_device_init()
  ...
...@@ -909,7 +909,7 @@ static int amdgpu_cgs_acpi_eval_object(struct cgs_device *cgs_device, ...@@ -909,7 +909,7 @@ static int amdgpu_cgs_acpi_eval_object(struct cgs_device *cgs_device,
struct cgs_acpi_method_argument *argument = NULL; struct cgs_acpi_method_argument *argument = NULL;
uint32_t i, count; uint32_t i, count;
acpi_status status; acpi_status status;
int result; int result = 0;
uint32_t func_no = 0xFFFFFFFF; uint32_t func_no = 0xFFFFFFFF;
handle = ACPI_HANDLE(&adev->pdev->dev); handle = ACPI_HANDLE(&adev->pdev->dev);
......
...@@ -1535,7 +1535,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, ...@@ -1535,7 +1535,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
/* Post card if necessary */ /* Post card if necessary */
if (!amdgpu_card_posted(adev) || if (!amdgpu_card_posted(adev) ||
(adev->virtualization.is_virtual && (adev->virtualization.is_virtual &&
!adev->virtualization.caps & AMDGPU_VIRT_CAPS_SRIOV_EN)) { !(adev->virtualization.caps & AMDGPU_VIRT_CAPS_SRIOV_EN))) {
if (!adev->bios) { if (!adev->bios) {
dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n"); dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n");
return -EINVAL; return -EINVAL;
......
...@@ -447,7 +447,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file ...@@ -447,7 +447,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
dev_info.max_memory_clock = adev->pm.default_mclk * 10; dev_info.max_memory_clock = adev->pm.default_mclk * 10;
} }
dev_info.enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask; dev_info.enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask;
dev_info.num_rb_pipes = adev->gfx.config.num_rbs; dev_info.num_rb_pipes = adev->gfx.config.max_backends_per_se *
adev->gfx.config.max_shader_engines;
dev_info.num_hw_gfx_contexts = adev->gfx.config.max_hw_contexts; dev_info.num_hw_gfx_contexts = adev->gfx.config.max_hw_contexts;
dev_info._pad = 0; dev_info._pad = 0;
dev_info.ids_flags = 0; dev_info.ids_flags = 0;
......
...@@ -270,21 +270,20 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, ...@@ -270,21 +270,20 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev); struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private; struct amdgpu_device *adev = ddev->dev_private;
enum amd_pm_state_type state = 0; enum amd_pm_state_type state = 0;
long idx; unsigned long idx;
int ret; int ret;
if (strlen(buf) == 1) if (strlen(buf) == 1)
adev->pp_force_state_enabled = false; adev->pp_force_state_enabled = false;
else { else if (adev->pp_enabled) {
ret = kstrtol(buf, 0, &idx); struct pp_states_info data;
if (ret) { ret = kstrtoul(buf, 0, &idx);
if (ret || idx >= ARRAY_SIZE(data.states)) {
count = -EINVAL; count = -EINVAL;
goto fail; goto fail;
} }
if (adev->pp_enabled) {
struct pp_states_info data;
amdgpu_dpm_get_pp_num_states(adev, &data); amdgpu_dpm_get_pp_num_states(adev, &data);
state = data.states[idx]; state = data.states[idx];
/* only set user selected power states */ /* only set user selected power states */
...@@ -295,7 +294,6 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, ...@@ -295,7 +294,6 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev,
adev->pp_force_state_enabled = true; adev->pp_force_state_enabled = true;
} }
} }
}
fail: fail:
return count; return count;
} }
......
...@@ -297,7 +297,8 @@ static const u32 polaris11_golden_common_all[] = ...@@ -297,7 +297,8 @@ static const u32 polaris11_golden_common_all[] =
static const u32 golden_settings_polaris10_a11[] = static const u32 golden_settings_polaris10_a11[] =
{ {
mmATC_MISC_CG, 0x000c0fc0, 0x000c0200, mmATC_MISC_CG, 0x000c0fc0, 0x000c0200,
mmCB_HW_CONTROL, 0xfffdf3cf, 0x00006208, mmCB_HW_CONTROL, 0xfffdf3cf, 0x00007208,
mmCB_HW_CONTROL_2, 0, 0x0f000000,
mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040, mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040,
mmDB_DEBUG2, 0xf00fffff, 0x00000400, mmDB_DEBUG2, 0xf00fffff, 0x00000400,
mmPA_SC_ENHANCE, 0xffffffff, 0x20000001, mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
......
...@@ -5538,6 +5538,78 @@ typedef struct _ATOM_ASIC_PROFILING_INFO_V3_5 ...@@ -5538,6 +5538,78 @@ typedef struct _ATOM_ASIC_PROFILING_INFO_V3_5
ULONG ulReserved[12]; ULONG ulReserved[12];
}ATOM_ASIC_PROFILING_INFO_V3_5; }ATOM_ASIC_PROFILING_INFO_V3_5;
/* for Polars10/11 AVFS parameters */
typedef struct _ATOM_ASIC_PROFILING_INFO_V3_6
{
ATOM_COMMON_TABLE_HEADER asHeader;
ULONG ulMaxVddc;
ULONG ulMinVddc;
USHORT usLkgEuseIndex;
UCHAR ucLkgEfuseBitLSB;
UCHAR ucLkgEfuseLength;
ULONG ulLkgEncodeLn_MaxDivMin;
ULONG ulLkgEncodeMax;
ULONG ulLkgEncodeMin;
EFUSE_LINEAR_FUNC_PARAM sRoFuse;
ULONG ulEvvDefaultVddc;
ULONG ulEvvNoCalcVddc;
ULONG ulSpeed_Model;
ULONG ulSM_A0;
ULONG ulSM_A1;
ULONG ulSM_A2;
ULONG ulSM_A3;
ULONG ulSM_A4;
ULONG ulSM_A5;
ULONG ulSM_A6;
ULONG ulSM_A7;
UCHAR ucSM_A0_sign;
UCHAR ucSM_A1_sign;
UCHAR ucSM_A2_sign;
UCHAR ucSM_A3_sign;
UCHAR ucSM_A4_sign;
UCHAR ucSM_A5_sign;
UCHAR ucSM_A6_sign;
UCHAR ucSM_A7_sign;
ULONG ulMargin_RO_a;
ULONG ulMargin_RO_b;
ULONG ulMargin_RO_c;
ULONG ulMargin_fixed;
ULONG ulMargin_Fmax_mean;
ULONG ulMargin_plat_mean;
ULONG ulMargin_Fmax_sigma;
ULONG ulMargin_plat_sigma;
ULONG ulMargin_DC_sigma;
ULONG ulLoadLineSlop;
ULONG ulaTDClimitPerDPM[8];
ULONG ulaNoCalcVddcPerDPM[8];
ULONG ulAVFS_meanNsigma_Acontant0;
ULONG ulAVFS_meanNsigma_Acontant1;
ULONG ulAVFS_meanNsigma_Acontant2;
USHORT usAVFS_meanNsigma_DC_tol_sigma;
USHORT usAVFS_meanNsigma_Platform_mean;
USHORT usAVFS_meanNsigma_Platform_sigma;
ULONG ulGB_VDROOP_TABLE_CKSOFF_a0;
ULONG ulGB_VDROOP_TABLE_CKSOFF_a1;
ULONG ulGB_VDROOP_TABLE_CKSOFF_a2;
ULONG ulGB_VDROOP_TABLE_CKSON_a0;
ULONG ulGB_VDROOP_TABLE_CKSON_a1;
ULONG ulGB_VDROOP_TABLE_CKSON_a2;
ULONG ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
USHORT usAVFSGB_FUSE_TABLE_CKSOFF_m2;
ULONG ulAVFSGB_FUSE_TABLE_CKSOFF_b;
ULONG ulAVFSGB_FUSE_TABLE_CKSON_m1;
USHORT usAVFSGB_FUSE_TABLE_CKSON_m2;
ULONG ulAVFSGB_FUSE_TABLE_CKSON_b;
USHORT usMaxVoltage_0_25mv;
UCHAR ucEnableGB_VDROOP_TABLE_CKSOFF;
UCHAR ucEnableGB_VDROOP_TABLE_CKSON;
UCHAR ucEnableGB_FUSE_TABLE_CKSOFF;
UCHAR ucEnableGB_FUSE_TABLE_CKSON;
USHORT usPSM_Age_ComFactor;
UCHAR ucEnableApplyAVFS_CKS_OFF_Voltage;
UCHAR ucReserved;
}ATOM_ASIC_PROFILING_INFO_V3_6;
typedef struct _ATOM_SCLK_FCW_RANGE_ENTRY_V1{ typedef struct _ATOM_SCLK_FCW_RANGE_ENTRY_V1{
ULONG ulMaxSclkFreq; ULONG ulMaxSclkFreq;
......
...@@ -633,6 +633,8 @@ static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr) ...@@ -633,6 +633,8 @@ static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
data->vddci_control = FIJI_VOLTAGE_CONTROL_NONE; data->vddci_control = FIJI_VOLTAGE_CONTROL_NONE;
data->mvdd_control = FIJI_VOLTAGE_CONTROL_NONE; data->mvdd_control = FIJI_VOLTAGE_CONTROL_NONE;
data->force_pcie_gen = PP_PCIEGenInvalid;
if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
data->voltage_control = FIJI_VOLTAGE_CONTROL_BY_SVID2; data->voltage_control = FIJI_VOLTAGE_CONTROL_BY_SVID2;
......
...@@ -306,10 +306,14 @@ int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, ...@@ -306,10 +306,14 @@ int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr,
{ {
PHM_FUNC_CHECK(hwmgr); PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->store_cc6_data == NULL) if (display_config == NULL)
return -EINVAL; return -EINVAL;
hwmgr->display_config = *display_config; hwmgr->display_config = *display_config;
if (hwmgr->hwmgr_func->store_cc6_data == NULL)
return -EINVAL;
/* to do pass other display configuration in furture */ /* to do pass other display configuration in furture */
if (hwmgr->hwmgr_func->store_cc6_data) if (hwmgr->hwmgr_func->store_cc6_data)
......
...@@ -1296,7 +1296,6 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, ...@@ -1296,7 +1296,6 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
} }
mem_level->MclkFrequency = clock; mem_level->MclkFrequency = clock;
mem_level->StutterEnable = 0;
mem_level->EnabledForThrottle = 1; mem_level->EnabledForThrottle = 1;
mem_level->EnabledForActivity = 0; mem_level->EnabledForActivity = 0;
mem_level->UpHyst = 0; mem_level->UpHyst = 0;
...@@ -1304,7 +1303,6 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, ...@@ -1304,7 +1303,6 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
mem_level->VoltageDownHyst = 0; mem_level->VoltageDownHyst = 0;
mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target; mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
mem_level->StutterEnable = false; mem_level->StutterEnable = false;
mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
data->display_timing.num_existing_displays = info.display_count; data->display_timing.num_existing_displays = info.display_count;
...@@ -1363,7 +1361,7 @@ static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) ...@@ -1363,7 +1361,7 @@ static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
* a higher state by default such that we are not effected by * a higher state by default such that we are not effected by
* up threshold or and MCLK DPM latency. * up threshold or and MCLK DPM latency.
*/ */
levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target; levels[0].ActivityLevel = 0x1f;
CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel);
data->smc_state_table.MemoryDpmLevelCount = data->smc_state_table.MemoryDpmLevelCount =
...@@ -1761,12 +1759,9 @@ static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) ...@@ -1761,12 +1759,9 @@ static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr)
static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
{ {
uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min;
volt_with_cks, value;
uint16_t clock_freq_u16;
struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0;
volt_offset = 0;
struct phm_ppt_v1_information *table_info = struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable); (struct phm_ppt_v1_information *)(hwmgr->pptable);
struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
...@@ -1778,50 +1773,38 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) ...@@ -1778,50 +1773,38 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
* if the part is SS or FF. if RO >= 1660MHz, part is FF. * if the part is SS or FF. if RO >= 1660MHz, part is FF.
*/ */
efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
ixSMU_EFUSE_0 + (146 * 4)); ixSMU_EFUSE_0 + (67 * 4));
efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
ixSMU_EFUSE_0 + (148 * 4));
efuse &= 0xFF000000; efuse &= 0xFF000000;
efuse = efuse >> 24; efuse = efuse >> 24;
efuse2 &= 0xF;
if (efuse2 == 1)
ro = (2300 - 1350) * efuse / 255 + 1350;
else
ro = (2500 - 1000) * efuse / 255 + 1000;
if (ro >= 1660) if (hwmgr->chip_id == CHIP_POLARIS10) {
type = 0; min = 1000;
else max = 2300;
type = 1; } else {
min = 1100;
max = 2100;
}
/* Populate Stretch amount */ ro = efuse * (max -min)/255 + min;
data->smc_state_table.ClockStretcherAmount = stretch_amount;
/* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
for (i = 0; i < sclk_table->count; i++) { for (i = 0; i < sclk_table->count; i++) {
data->smc_state_table.Sclk_CKS_masterEn0_7 |= data->smc_state_table.Sclk_CKS_masterEn0_7 |=
sclk_table->entries[i].cks_enable << i; sclk_table->entries[i].cks_enable << i;
volt_without_cks = (uint32_t)((14041 *
(sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / volt_without_cks = (uint32_t)(((ro - 40) * 1000 - 2753594 - sclk_table->entries[i].clk/100 * 136418 /1000) / \
(4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); (sclk_table->entries[i].clk/100 * 1132925 /10000 - 242418)/100);
volt_with_cks = (uint32_t)((13946 *
(sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / volt_with_cks = (uint32_t)((ro * 1000 -2396351 - sclk_table->entries[i].clk/100 * 329021/1000) / \
(3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); (sclk_table->entries[i].clk/10000 * 649434 /1000 - 18005)/10);
if (volt_without_cks >= volt_with_cks) if (volt_without_cks >= volt_with_cks)
volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks +
sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); sclk_table->entries[i].cks_voffset) * 100 / 625) + 1);
data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; data->smc_state_table.Sclk_voltageOffset[i] = volt_offset;
} }
PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
STRETCH_ENABLE, 0x0);
PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
masterReset, 0x1);
/* PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, staticEnable, 0x1); */
PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
masterReset, 0x0);
/* Populate CKS Lookup Table */ /* Populate CKS Lookup Table */
if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
stretch_amount2 = 0; stretch_amount2 = 0;
...@@ -1835,69 +1818,6 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) ...@@ -1835,69 +1818,6 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
return -EINVAL); return -EINVAL);
} }
value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
ixPWR_CKS_CNTL);
value &= 0xFFC2FF87;
data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq =
polaris10_clock_stretcher_lookup_table[stretch_amount2][0];
data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq =
polaris10_clock_stretcher_lookup_table[stretch_amount2][1];
clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(data->smc_state_table.
GraphicsLevel[data->smc_state_table.GraphicsDpmLevelCount - 1].SclkSetting.SclkFrequency) / 100);
if (polaris10_clock_stretcher_lookup_table[stretch_amount2][0] < clock_freq_u16
&& polaris10_clock_stretcher_lookup_table[stretch_amount2][1] > clock_freq_u16) {
/* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
value |= (polaris10_clock_stretcher_lookup_table[stretch_amount2][3]) << 16;
/* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
value |= (polaris10_clock_stretcher_lookup_table[stretch_amount2][2]) << 18;
/* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
value |= (polaris10_clock_stretch_amount_conversion
[polaris10_clock_stretcher_lookup_table[stretch_amount2][3]]
[stretch_amount]) << 3;
}
CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq);
CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq);
data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting =
polaris10_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F;
data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |=
(polaris10_clock_stretcher_lookup_table[stretch_amount2][3]) << 7;
cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
ixPWR_CKS_CNTL, value);
/* Populate DDT Lookup Table */
for (i = 0; i < 4; i++) {
/* Assign the minimum and maximum VID stored
* in the last row of Clock Stretcher Voltage Table.
*/
data->smc_state_table.ClockStretcherDataTable.ClockStretcherDataTableEntry[i].minVID =
(uint8_t) polaris10_clock_stretcher_ddt_table[type][i][2];
data->smc_state_table.ClockStretcherDataTable.ClockStretcherDataTableEntry[i].maxVID =
(uint8_t) polaris10_clock_stretcher_ddt_table[type][i][3];
/* Loop through each SCLK and check the frequency
* to see if it lies within the frequency for clock stretcher.
*/
for (j = 0; j < data->smc_state_table.GraphicsDpmLevelCount; j++) {
cks_setting = 0;
clock_freq = PP_SMC_TO_HOST_UL(
data->smc_state_table.GraphicsLevel[j].SclkSetting.SclkFrequency);
/* Check the allowed frequency against the sclk level[j].
* Sclk's endianness has already been converted,
* and it's in 10Khz unit,
* as opposed to Data table, which is in Mhz unit.
*/
if (clock_freq >= (polaris10_clock_stretcher_ddt_table[type][i][0]) * 100) {
cks_setting |= 0x2;
if (clock_freq < (polaris10_clock_stretcher_ddt_table[type][i][1]) * 100)
cks_setting |= 0x1;
}
data->smc_state_table.ClockStretcherDataTable.ClockStretcherDataTableEntry[i].setting
|= cks_setting << (j * 2);
}
CONVERT_FROM_HOST_TO_SMC_US(
data->smc_state_table.ClockStretcherDataTable.ClockStretcherDataTableEntry[i].setting);
}
value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL);
value &= 0xFFFFFFFE; value &= 0xFFFFFFFE;
cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value);
...@@ -1956,6 +1876,90 @@ static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, ...@@ -1956,6 +1876,90 @@ static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr,
return 0; return 0;
} }
int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
{
struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
SMU74_Discrete_DpmTable *table = &(data->smc_state_table);
int result = 0;
struct pp_atom_ctrl__avfs_parameters avfs_params = {0};
AVFS_meanNsigma_t AVFS_meanNsigma = { {0} };
AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} };
uint32_t tmp, i;
struct pp_smumgr *smumgr = hwmgr->smumgr;
struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)hwmgr->pptable;
struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
table_info->vdd_dep_on_sclk;
if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
return result;
result = atomctrl_get_avfs_information(hwmgr, &avfs_params);
if (0 == result) {
table->BTCGB_VDROOP_TABLE[0].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0);
table->BTCGB_VDROOP_TABLE[0].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1);
table->BTCGB_VDROOP_TABLE[0].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2);
table->BTCGB_VDROOP_TABLE[1].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0);
table->BTCGB_VDROOP_TABLE[1].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1);
table->BTCGB_VDROOP_TABLE[1].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2);
table->AVFSGB_VDROOP_TABLE[0].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1);
table->AVFSGB_VDROOP_TABLE[0].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2);
table->AVFSGB_VDROOP_TABLE[0].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b);
table->AVFSGB_VDROOP_TABLE[0].m1_shift = 24;
table->AVFSGB_VDROOP_TABLE[0].m2_shift = 12;
table->AVFSGB_VDROOP_TABLE[1].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1);
table->AVFSGB_VDROOP_TABLE[1].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2);
table->AVFSGB_VDROOP_TABLE[1].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b);
table->AVFSGB_VDROOP_TABLE[1].m1_shift = 24;
table->AVFSGB_VDROOP_TABLE[1].m2_shift = 12;
table->MaxVoltage = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv);
AVFS_meanNsigma.Aconstant[0] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0);
AVFS_meanNsigma.Aconstant[1] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1);
AVFS_meanNsigma.Aconstant[2] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2);
AVFS_meanNsigma.DC_tol_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma);
AVFS_meanNsigma.Platform_mean = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean);
AVFS_meanNsigma.PSM_Age_CompFactor = PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor);
AVFS_meanNsigma.Platform_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma);
for (i = 0; i < NUM_VFT_COLUMNS; i++) {
AVFS_meanNsigma.Static_Voltage_Offset[i] = (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625);
AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100);
}
result = polaris10_read_smc_sram_dword(smumgr,
SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma),
&tmp, data->sram_end);
polaris10_copy_bytes_to_smc(smumgr,
tmp,
(uint8_t *)&AVFS_meanNsigma,
sizeof(AVFS_meanNsigma_t),
data->sram_end);
result = polaris10_read_smc_sram_dword(smumgr,
SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable),
&tmp, data->sram_end);
polaris10_copy_bytes_to_smc(smumgr,
tmp,
(uint8_t *)&AVFS_SclkOffset,
sizeof(AVFS_Sclk_Offset_t),
data->sram_end);
data->avfs_vdroop_override_setting = (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) |
(avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) |
(avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) |
(avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT);
data->apply_avfs_cks_off_voltage = (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false;
}
return result;
}
/** /**
* Initializes the SMC table and uploads it * Initializes the SMC table and uploads it
* *
...@@ -2056,6 +2060,10 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) ...@@ -2056,6 +2060,10 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
"Failed to populate Clock Stretcher Data Table!", "Failed to populate Clock Stretcher Data Table!",
return result); return result);
} }
result = polaris10_populate_avfs_parameters(hwmgr);
PP_ASSERT_WITH_CODE(0 == result, "Failed to populate AVFS Parameters!", return result;);
table->CurrSclkPllRange = 0xff; table->CurrSclkPllRange = 0xff;
table->GraphicsVoltageChangeEnable = 1; table->GraphicsVoltageChangeEnable = 1;
table->GraphicsThermThrottleEnable = 1; table->GraphicsThermThrottleEnable = 1;
...@@ -2252,6 +2260,9 @@ static int polaris10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) ...@@ -2252,6 +2260,9 @@ static int polaris10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
{ {
struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
uint32_t soft_register_value = 0;
uint32_t handshake_disables_offset = data->soft_regs_start
+ offsetof(SMU74_SoftRegisters, HandshakeDisables);
/* enable SCLK dpm */ /* enable SCLK dpm */
if (!data->sclk_dpm_key_disabled) if (!data->sclk_dpm_key_disabled)
...@@ -2262,6 +2273,12 @@ static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) ...@@ -2262,6 +2273,12 @@ static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
/* enable MCLK dpm */ /* enable MCLK dpm */
if (0 == data->mclk_dpm_key_disabled) { if (0 == data->mclk_dpm_key_disabled) {
/* Disable UVD - SMU handshake for MCLK. */
soft_register_value = cgs_read_ind_register(hwmgr->device,
CGS_IND_REG__SMC, handshake_disables_offset);
soft_register_value |= SMU7_UVD_MCLK_HANDSHAKE_DISABLE;
cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
handshake_disables_offset, soft_register_value);
PP_ASSERT_WITH_CODE( PP_ASSERT_WITH_CODE(
(0 == smum_send_msg_to_smc(hwmgr->smumgr, (0 == smum_send_msg_to_smc(hwmgr->smumgr,
...@@ -2269,7 +2286,6 @@ static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) ...@@ -2269,7 +2286,6 @@ static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
"Failed to enable MCLK DPM during DPM Start Function!", "Failed to enable MCLK DPM during DPM Start Function!",
return -1); return -1);
PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1); PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1);
cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5);
...@@ -2606,6 +2622,7 @@ int polaris10_set_features_platform_caps(struct pp_hwmgr *hwmgr) ...@@ -2606,6 +2622,7 @@ int polaris10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
phm_cap_set(hwmgr->platform_descriptor.platformCaps, phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_FanSpeedInTableIsRPM); PHM_PlatformCaps_FanSpeedInTableIsRPM);
if (hwmgr->chip_id == CHIP_POLARIS11) if (hwmgr->chip_id == CHIP_POLARIS11)
phm_cap_set(hwmgr->platform_descriptor.platformCaps, phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SPLLShutdownSupport); PHM_PlatformCaps_SPLLShutdownSupport);
...@@ -2938,6 +2955,11 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) ...@@ -2938,6 +2955,11 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
data->vddci_control = POLARIS10_VOLTAGE_CONTROL_NONE; data->vddci_control = POLARIS10_VOLTAGE_CONTROL_NONE;
data->mvdd_control = POLARIS10_VOLTAGE_CONTROL_NONE; data->mvdd_control = POLARIS10_VOLTAGE_CONTROL_NONE;
data->enable_tdc_limit_feature = true;
data->enable_pkg_pwr_tracking_feature = true;
data->force_pcie_gen = PP_PCIEGenInvalid;
data->mclk_stutter_mode_threshold = 40000;
if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
data->voltage_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2; data->voltage_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2;
...@@ -2962,6 +2984,10 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) ...@@ -2962,6 +2984,10 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
data->vddci_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2; data->vddci_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2;
} }
if (table_info->cac_dtp_table->usClockStretchAmount != 0)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ClockStretcher);
polaris10_set_features_platform_caps(hwmgr); polaris10_set_features_platform_caps(hwmgr);
polaris10_init_dpm_defaults(hwmgr); polaris10_init_dpm_defaults(hwmgr);
......
...@@ -312,6 +312,9 @@ struct polaris10_hwmgr { ...@@ -312,6 +312,9 @@ struct polaris10_hwmgr {
/* soft pptable for re-uploading into smu */ /* soft pptable for re-uploading into smu */
void *soft_pp_table; void *soft_pp_table;
uint32_t avfs_vdroop_override_setting;
bool apply_avfs_cks_off_voltage;
}; };
/* To convert to Q8.8 format for firmware */ /* To convert to Q8.8 format for firmware */
......
...@@ -625,10 +625,14 @@ static int tf_polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr, ...@@ -625,10 +625,14 @@ static int tf_polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr,
int ret; int ret;
struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr); struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr);
struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
if (smu_data->avfs.avfs_btc_status != AVFS_BTC_ENABLEAVFS) if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
return 0; return 0;
ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting);
ret = (smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs) == 0) ? ret = (smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs) == 0) ?
0 : -1; 0 : -1;
......
...@@ -44,6 +44,20 @@ bool acpi_atcs_functions_supported(void *device, uint32_t index) ...@@ -44,6 +44,20 @@ bool acpi_atcs_functions_supported(void *device, uint32_t index)
return result == 0 ? (output_buf.function_bits & (1 << (index - 1))) != 0 : false; return result == 0 ? (output_buf.function_bits & (1 << (index - 1))) != 0 : false;
} }
bool acpi_atcs_notify_pcie_device_ready(void *device)
{
int32_t temp_buffer = 1;
return cgs_call_acpi_method(device, CGS_ACPI_METHOD_ATCS,
ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION,
&temp_buffer,
NULL,
0,
sizeof(temp_buffer),
0);
}
int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise) int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
{ {
struct atcs_pref_req_input atcs_input; struct atcs_pref_req_input atcs_input;
...@@ -52,7 +66,7 @@ int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise) ...@@ -52,7 +66,7 @@ int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
int result; int result;
struct cgs_system_info info = {0}; struct cgs_system_info info = {0};
if (!acpi_atcs_functions_supported(device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST)) if( 0 != acpi_atcs_notify_pcie_device_ready(device))
return -EINVAL; return -EINVAL;
info.size = sizeof(struct cgs_system_info); info.size = sizeof(struct cgs_system_info);
...@@ -77,7 +91,7 @@ int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise) ...@@ -77,7 +91,7 @@ int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST,
&atcs_input, &atcs_input,
&atcs_output, &atcs_output,
0, 1,
sizeof(atcs_input), sizeof(atcs_input),
sizeof(atcs_output)); sizeof(atcs_output));
if (result != 0) if (result != 0)
......
...@@ -1302,3 +1302,46 @@ int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctr ...@@ -1302,3 +1302,46 @@ int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctr
return 0; return 0;
} }
int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param)
{
ATOM_ASIC_PROFILING_INFO_V3_6 *profile = NULL;
if (param == NULL)
return -EINVAL;
profile = (ATOM_ASIC_PROFILING_INFO_V3_6 *)
cgs_atom_get_data_table(hwmgr->device,
GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo),
NULL, NULL, NULL);
if (!profile)
return -1;
param->ulAVFS_meanNsigma_Acontant0 = profile->ulAVFS_meanNsigma_Acontant0;
param->ulAVFS_meanNsigma_Acontant1 = profile->ulAVFS_meanNsigma_Acontant1;
param->ulAVFS_meanNsigma_Acontant2 = profile->ulAVFS_meanNsigma_Acontant2;
param->usAVFS_meanNsigma_DC_tol_sigma = profile->usAVFS_meanNsigma_DC_tol_sigma;
param->usAVFS_meanNsigma_Platform_mean = profile->usAVFS_meanNsigma_Platform_mean;
param->usAVFS_meanNsigma_Platform_sigma = profile->usAVFS_meanNsigma_Platform_sigma;
param->ulGB_VDROOP_TABLE_CKSOFF_a0 = profile->ulGB_VDROOP_TABLE_CKSOFF_a0;
param->ulGB_VDROOP_TABLE_CKSOFF_a1 = profile->ulGB_VDROOP_TABLE_CKSOFF_a1;
param->ulGB_VDROOP_TABLE_CKSOFF_a2 = profile->ulGB_VDROOP_TABLE_CKSOFF_a2;
param->ulGB_VDROOP_TABLE_CKSON_a0 = profile->ulGB_VDROOP_TABLE_CKSON_a0;
param->ulGB_VDROOP_TABLE_CKSON_a1 = profile->ulGB_VDROOP_TABLE_CKSON_a1;
param->ulGB_VDROOP_TABLE_CKSON_a2 = profile->ulGB_VDROOP_TABLE_CKSON_a2;
param->ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = profile->ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
param->usAVFSGB_FUSE_TABLE_CKSOFF_m2 = profile->usAVFSGB_FUSE_TABLE_CKSOFF_m2;
param->ulAVFSGB_FUSE_TABLE_CKSOFF_b = profile->ulAVFSGB_FUSE_TABLE_CKSOFF_b;
param->ulAVFSGB_FUSE_TABLE_CKSON_m1 = profile->ulAVFSGB_FUSE_TABLE_CKSON_m1;
param->usAVFSGB_FUSE_TABLE_CKSON_m2 = profile->usAVFSGB_FUSE_TABLE_CKSON_m2;
param->ulAVFSGB_FUSE_TABLE_CKSON_b = profile->ulAVFSGB_FUSE_TABLE_CKSON_b;
param->usMaxVoltage_0_25mv = profile->usMaxVoltage_0_25mv;
param->ucEnableGB_VDROOP_TABLE_CKSOFF = profile->ucEnableGB_VDROOP_TABLE_CKSOFF;
param->ucEnableGB_VDROOP_TABLE_CKSON = profile->ucEnableGB_VDROOP_TABLE_CKSON;
param->ucEnableGB_FUSE_TABLE_CKSOFF = profile->ucEnableGB_FUSE_TABLE_CKSOFF;
param->ucEnableGB_FUSE_TABLE_CKSON = profile->ucEnableGB_FUSE_TABLE_CKSON;
param->usPSM_Age_ComFactor = profile->usPSM_Age_ComFactor;
param->ucEnableApplyAVFS_CKS_OFF_Voltage = profile->ucEnableApplyAVFS_CKS_OFF_Voltage;
return 0;
}
...@@ -250,6 +250,35 @@ struct pp_atomctrl_gpio_pin_assignment { ...@@ -250,6 +250,35 @@ struct pp_atomctrl_gpio_pin_assignment {
}; };
typedef struct pp_atomctrl_gpio_pin_assignment pp_atomctrl_gpio_pin_assignment; typedef struct pp_atomctrl_gpio_pin_assignment pp_atomctrl_gpio_pin_assignment;
struct pp_atom_ctrl__avfs_parameters {
uint32_t ulAVFS_meanNsigma_Acontant0;
uint32_t ulAVFS_meanNsigma_Acontant1;
uint32_t ulAVFS_meanNsigma_Acontant2;
uint16_t usAVFS_meanNsigma_DC_tol_sigma;
uint16_t usAVFS_meanNsigma_Platform_mean;
uint16_t usAVFS_meanNsigma_Platform_sigma;
uint32_t ulGB_VDROOP_TABLE_CKSOFF_a0;
uint32_t ulGB_VDROOP_TABLE_CKSOFF_a1;
uint32_t ulGB_VDROOP_TABLE_CKSOFF_a2;
uint32_t ulGB_VDROOP_TABLE_CKSON_a0;
uint32_t ulGB_VDROOP_TABLE_CKSON_a1;
uint32_t ulGB_VDROOP_TABLE_CKSON_a2;
uint32_t ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
uint16_t usAVFSGB_FUSE_TABLE_CKSOFF_m2;
uint32_t ulAVFSGB_FUSE_TABLE_CKSOFF_b;
uint32_t ulAVFSGB_FUSE_TABLE_CKSON_m1;
uint16_t usAVFSGB_FUSE_TABLE_CKSON_m2;
uint32_t ulAVFSGB_FUSE_TABLE_CKSON_b;
uint16_t usMaxVoltage_0_25mv;
uint8_t ucEnableGB_VDROOP_TABLE_CKSOFF;
uint8_t ucEnableGB_VDROOP_TABLE_CKSON;
uint8_t ucEnableGB_FUSE_TABLE_CKSOFF;
uint8_t ucEnableGB_FUSE_TABLE_CKSON;
uint16_t usPSM_Age_ComFactor;
uint8_t ucEnableApplyAVFS_CKS_OFF_Voltage;
uint8_t ucReserved;
};
extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment); extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment);
extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage); extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage);
extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr); extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr);
...@@ -278,5 +307,8 @@ extern int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clo ...@@ -278,5 +307,8 @@ extern int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clo
extern int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type, extern int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage); uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage);
extern int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table); extern int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table);
extern int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param);
#endif #endif
...@@ -4489,6 +4489,7 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr) ...@@ -4489,6 +4489,7 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_NONE; data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_NONE;
data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_NONE; data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_NONE;
data->mvdd_control = TONGA_VOLTAGE_CONTROL_NONE; data->mvdd_control = TONGA_VOLTAGE_CONTROL_NONE;
data->force_pcie_gen = PP_PCIEGenInvalid;
if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) { VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#pragma pack(push, 1) #pragma pack(push, 1)
#define PPSMC_MSG_SetGBDroopSettings ((uint16_t) 0x305)
#define PPSMC_SWSTATE_FLAG_DC 0x01 #define PPSMC_SWSTATE_FLAG_DC 0x01
#define PPSMC_SWSTATE_FLAG_UVD 0x02 #define PPSMC_SWSTATE_FLAG_UVD 0x02
......
...@@ -26,3 +26,4 @@ extern bool acpi_atcs_functions_supported(void *device, ...@@ -26,3 +26,4 @@ extern bool acpi_atcs_functions_supported(void *device,
extern int acpi_pcie_perf_request(void *device, extern int acpi_pcie_perf_request(void *device,
uint8_t perf_req, uint8_t perf_req,
bool advertise); bool advertise);
extern bool acpi_atcs_notify_pcie_device_ready(void *device);
...@@ -34,6 +34,30 @@ ...@@ -34,6 +34,30 @@
#define SMU__NUM_LCLK_DPM_LEVELS 8 #define SMU__NUM_LCLK_DPM_LEVELS 8
#define SMU__NUM_PCIE_DPM_LEVELS 8 #define SMU__NUM_PCIE_DPM_LEVELS 8
#define EXP_M1 35
#define EXP_M2 92821
#define EXP_B 66629747
#define EXP_M1_1 365
#define EXP_M2_1 658700
#define EXP_B_1 305506134
#define EXP_M1_2 189
#define EXP_M2_2 379692
#define EXP_B_2 194609469
#define EXP_M1_3 99
#define EXP_M2_3 217915
#define EXP_B_3 122255994
#define EXP_M1_4 51
#define EXP_M2_4 122643
#define EXP_B_4 74893384
#define EXP_M1_5 423
#define EXP_M2_5 1103326
#define EXP_B_5 728122621
enum SID_OPTION { enum SID_OPTION {
SID_OPTION_HI, SID_OPTION_HI,
SID_OPTION_LO, SID_OPTION_LO,
...@@ -548,20 +572,20 @@ struct SMU74_Firmware_Header { ...@@ -548,20 +572,20 @@ struct SMU74_Firmware_Header {
uint32_t CacConfigTable; uint32_t CacConfigTable;
uint32_t CacStatusTable; uint32_t CacStatusTable;
uint32_t mcRegisterTable; uint32_t mcRegisterTable;
uint32_t mcArbDramTimingTable; uint32_t mcArbDramTimingTable;
uint32_t PmFuseTable; uint32_t PmFuseTable;
uint32_t Globals; uint32_t Globals;
uint32_t ClockStretcherTable; uint32_t ClockStretcherTable;
uint32_t VftTable; uint32_t VftTable;
uint32_t Reserved[21]; uint32_t Reserved1;
uint32_t AvfsTable;
uint32_t AvfsCksOffGbvTable;
uint32_t AvfsMeanNSigma;
uint32_t AvfsSclkOffsetTable;
uint32_t Reserved[16];
uint32_t Signature; uint32_t Signature;
}; };
...@@ -701,8 +725,6 @@ VR Config info is contained in dpmTable.VRConfig */ ...@@ -701,8 +725,6 @@ VR Config info is contained in dpmTable.VRConfig */
struct SMU_ClockStretcherDataTableEntry { struct SMU_ClockStretcherDataTableEntry {
uint8_t minVID; uint8_t minVID;
uint8_t maxVID; uint8_t maxVID;
uint16_t setting; uint16_t setting;
}; };
typedef struct SMU_ClockStretcherDataTableEntry SMU_ClockStretcherDataTableEntry; typedef struct SMU_ClockStretcherDataTableEntry SMU_ClockStretcherDataTableEntry;
...@@ -769,6 +791,43 @@ struct VFT_TABLE_t { ...@@ -769,6 +791,43 @@ struct VFT_TABLE_t {
typedef struct VFT_TABLE_t VFT_TABLE_t; typedef struct VFT_TABLE_t VFT_TABLE_t;
/* Total margin, root mean square of Fmax + DC + Platform */
struct AVFS_Margin_t {
VFT_CELL_t Cell[NUM_VFT_COLUMNS];
};
typedef struct AVFS_Margin_t AVFS_Margin_t;
#define BTCGB_VDROOP_TABLE_MAX_ENTRIES 2
#define AVFSGB_VDROOP_TABLE_MAX_ENTRIES 2
struct GB_VDROOP_TABLE_t {
int32_t a0;
int32_t a1;
int32_t a2;
uint32_t spare;
};
typedef struct GB_VDROOP_TABLE_t GB_VDROOP_TABLE_t;
struct AVFS_CksOff_Gbv_t {
VFT_CELL_t Cell[NUM_VFT_COLUMNS];
};
typedef struct AVFS_CksOff_Gbv_t AVFS_CksOff_Gbv_t;
struct AVFS_meanNsigma_t {
uint32_t Aconstant[3];
uint16_t DC_tol_sigma;
uint16_t Platform_mean;
uint16_t Platform_sigma;
uint16_t PSM_Age_CompFactor;
uint8_t Static_Voltage_Offset[NUM_VFT_COLUMNS];
};
typedef struct AVFS_meanNsigma_t AVFS_meanNsigma_t;
struct AVFS_Sclk_Offset_t {
uint16_t Sclk_Offset[8];
};
typedef struct AVFS_Sclk_Offset_t AVFS_Sclk_Offset_t;
#endif #endif
...@@ -223,6 +223,16 @@ struct SMU74_Discrete_StateInfo { ...@@ -223,6 +223,16 @@ struct SMU74_Discrete_StateInfo {
typedef struct SMU74_Discrete_StateInfo SMU74_Discrete_StateInfo; typedef struct SMU74_Discrete_StateInfo SMU74_Discrete_StateInfo;
struct SMU_QuadraticCoeffs {
int32_t m1;
uint32_t b;
int16_t m2;
uint8_t m1_shift;
uint8_t m2_shift;
};
typedef struct SMU_QuadraticCoeffs SMU_QuadraticCoeffs;
struct SMU74_Discrete_DpmTable { struct SMU74_Discrete_DpmTable {
SMU74_PIDController GraphicsPIDController; SMU74_PIDController GraphicsPIDController;
...@@ -258,7 +268,14 @@ struct SMU74_Discrete_DpmTable { ...@@ -258,7 +268,14 @@ struct SMU74_Discrete_DpmTable {
uint8_t ThermOutPolarity; uint8_t ThermOutPolarity;
uint8_t ThermOutMode; uint8_t ThermOutMode;
uint8_t BootPhases; uint8_t BootPhases;
uint32_t Reserved[4];
uint8_t VRHotLevel;
uint8_t Reserved1[3];
uint16_t FanStartTemperature;
uint16_t FanStopTemperature;
uint16_t MaxVoltage;
uint16_t Reserved2;
uint32_t Reserved[1];
SMU74_Discrete_GraphicsLevel GraphicsLevel[SMU74_MAX_LEVELS_GRAPHICS]; SMU74_Discrete_GraphicsLevel GraphicsLevel[SMU74_MAX_LEVELS_GRAPHICS];
SMU74_Discrete_MemoryLevel MemoryACPILevel; SMU74_Discrete_MemoryLevel MemoryACPILevel;
...@@ -347,6 +364,8 @@ struct SMU74_Discrete_DpmTable { ...@@ -347,6 +364,8 @@ struct SMU74_Discrete_DpmTable {
uint32_t CurrSclkPllRange; uint32_t CurrSclkPllRange;
sclkFcwRange_t SclkFcwRangeTable[NUM_SCLK_RANGE]; sclkFcwRange_t SclkFcwRangeTable[NUM_SCLK_RANGE];
GB_VDROOP_TABLE_t BTCGB_VDROOP_TABLE[BTCGB_VDROOP_TABLE_MAX_ENTRIES];
SMU_QuadraticCoeffs AVFSGB_VDROOP_TABLE[AVFSGB_VDROOP_TABLE_MAX_ENTRIES];
}; };
typedef struct SMU74_Discrete_DpmTable SMU74_Discrete_DpmTable; typedef struct SMU74_Discrete_DpmTable SMU74_Discrete_DpmTable;
...@@ -550,16 +569,6 @@ struct SMU7_AcpiScoreboard { ...@@ -550,16 +569,6 @@ struct SMU7_AcpiScoreboard {
typedef struct SMU7_AcpiScoreboard SMU7_AcpiScoreboard; typedef struct SMU7_AcpiScoreboard SMU7_AcpiScoreboard;
struct SMU_QuadraticCoeffs {
int32_t m1;
uint32_t b;
int16_t m2;
uint8_t m1_shift;
uint8_t m2_shift;
};
typedef struct SMU_QuadraticCoeffs SMU_QuadraticCoeffs;
struct SMU74_Discrete_PmFuses { struct SMU74_Discrete_PmFuses {
uint8_t BapmVddCVidHiSidd[8]; uint8_t BapmVddCVidHiSidd[8];
uint8_t BapmVddCVidLoSidd[8]; uint8_t BapmVddCVidLoSidd[8];
...@@ -821,6 +830,17 @@ typedef struct SMU7_GfxCuPgScoreboard SMU7_GfxCuPgScoreboard; ...@@ -821,6 +830,17 @@ typedef struct SMU7_GfxCuPgScoreboard SMU7_GfxCuPgScoreboard;
#define DB_PCC_SHIFT 26 #define DB_PCC_SHIFT 26
#define DB_EDC_SHIFT 27 #define DB_EDC_SHIFT 27
#define BTCGB0_Vdroop_Enable_MASK 0x1
#define BTCGB1_Vdroop_Enable_MASK 0x2
#define AVFSGB0_Vdroop_Enable_MASK 0x4
#define AVFSGB1_Vdroop_Enable_MASK 0x8
#define BTCGB0_Vdroop_Enable_SHIFT 0
#define BTCGB1_Vdroop_Enable_SHIFT 1
#define AVFSGB0_Vdroop_Enable_SHIFT 2
#define AVFSGB1_Vdroop_Enable_SHIFT 3
#pragma pack(pop) #pragma pack(pop)
......
...@@ -52,19 +52,18 @@ ...@@ -52,19 +52,18 @@
static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = { static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = {
/* Min pcie DeepSleep Activity CgSpll CgSpll CcPwr CcPwr Sclk Enabled Enabled Voltage Power */ /* Min pcie DeepSleep Activity CgSpll CgSpll CcPwr CcPwr Sclk Enabled Enabled Voltage Power */
/* Voltage, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, DynRm, DynRm1 Did, Padding,ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */ /* Voltage, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, DynRm, DynRm1 Did, Padding,ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */
{ 0x3c0fd047, 0x00, 0x03, 0x1e00, 0x00200410, 0x87020000, 0, 0, 0x16, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x30750000, 0, 0, 0, 0, 0, 0, 0 } }, { 0x100ea446, 0x00, 0x03, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x30750000, 0x3000, 0, 0x2600, 0, 0, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } },
{ 0xa00fd047, 0x01, 0x04, 0x1e00, 0x00800510, 0x87020000, 0, 0, 0x16, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x409c0000, 0, 0, 0, 0, 0, 0, 0 } }, { 0x400ea446, 0x01, 0x04, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x409c0000, 0x2000, 0, 0x1e00, 1, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } },
{ 0x0410d047, 0x01, 0x00, 0x1e00, 0x00600410, 0x87020000, 0, 0, 0x0e, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x50c30000, 0, 0, 0, 0, 0, 0, 0 } }, { 0x740ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x50c30000, 0x2800, 0, 0x2000, 1, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } },
{ 0x6810d047, 0x01, 0x00, 0x1e00, 0x00800410, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x60ea0000, 0, 0, 0, 0, 0, 0, 0 } }, { 0xa40ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x60ea0000, 0x3000, 0, 0x2600, 1, 1, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } },
{ 0xcc10d047, 0x01, 0x00, 0x1e00, 0x00e00410, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0xe8fd0000, 0, 0, 0, 0, 0, 0, 0 } }, { 0xd80ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x70110100, 0x3800, 0, 0x2c00, 1, 1, 0x0004, 0x1203, 0xffff, 0x3600, 0xc9e2, 0x2e00 } },
{ 0x3011d047, 0x01, 0x00, 0x1e00, 0x00400510, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x70110100, 0, 0, 0, 0, 0, 0, 0 } }, { 0x3c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x80380100, 0x2000, 0, 0x1e00, 2, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } },
{ 0x9411d047, 0x01, 0x00, 0x1e00, 0x00a00510, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0xf8240100, 0, 0, 0, 0, 0, 0, 0 } }, { 0x6c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x905f0100, 0x2400, 0, 0x1e00, 2, 1, 0x0004, 0x8901, 0xffff, 0x2300, 0x314c, 0x1d00 } },
{ 0xf811d047, 0x01, 0x00, 0x1e00, 0x00000610, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x80380100, 0, 0, 0, 0, 0, 0, 0 } } { 0xa00fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0xa0860100, 0x2800, 0, 0x2000, 2, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } }
}; };
static const SMU74_Discrete_MemoryLevel avfs_memory_level_polaris10 = static const SMU74_Discrete_MemoryLevel avfs_memory_level_polaris10 =
{0x50140000, 0x50140000, 0x00320000, 0x00, 0x00, {0x100ea446, 0, 0x30750000, 0x01, 0x01, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x1f00, 0x00, 0x00};
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00};
/** /**
* Set the address for reading/writing the SMC SRAM space. * Set the address for reading/writing the SMC SRAM space.
...@@ -219,6 +218,18 @@ bool polaris10_is_smc_ram_running(struct pp_smumgr *smumgr) ...@@ -219,6 +218,18 @@ bool polaris10_is_smc_ram_running(struct pp_smumgr *smumgr)
&& (0x20100 <= cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMC_PC_C))); && (0x20100 <= cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMC_PC_C)));
} }
static bool polaris10_is_hw_avfs_present(struct pp_smumgr *smumgr)
{
uint32_t efuse;
efuse = cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMU_EFUSE_0 + (49*4));
efuse &= 0x00000001;
if (efuse)
return true;
return false;
}
/** /**
* Send a message to the SMC, and wait for its response. * Send a message to the SMC, and wait for its response.
* *
...@@ -228,21 +239,27 @@ bool polaris10_is_smc_ram_running(struct pp_smumgr *smumgr) ...@@ -228,21 +239,27 @@ bool polaris10_is_smc_ram_running(struct pp_smumgr *smumgr)
*/ */
int polaris10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) int polaris10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
{ {
int ret;
if (!polaris10_is_smc_ram_running(smumgr)) if (!polaris10_is_smc_ram_running(smumgr))
return -1; return -1;
SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP);
printk("Failed to send Previous Message.\n");
if (ret != 1)
printk("\n failed to send pre message %x ret is %d \n", msg, ret);
cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg); cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP);
printk("Failed to send Message.\n");
if (ret != 1)
printk("\n failed to send message %x ret is %d \n", msg, ret);
return 0; return 0;
} }
...@@ -953,6 +970,11 @@ static int polaris10_smu_init(struct pp_smumgr *smumgr) ...@@ -953,6 +970,11 @@ static int polaris10_smu_init(struct pp_smumgr *smumgr)
(cgs_handle_t)smu_data->smu_buffer.handle); (cgs_handle_t)smu_data->smu_buffer.handle);
return -1;); return -1;);
if (polaris10_is_hw_avfs_present(smumgr))
smu_data->avfs.avfs_btc_status = AVFS_BTC_BOOT;
else
smu_data->avfs.avfs_btc_status = AVFS_BTC_NOTSUPPORTED;
return 0; return 0;
} }
......
...@@ -266,20 +266,22 @@ int atmel_hlcdc_create_outputs(struct drm_device *dev) ...@@ -266,20 +266,22 @@ int atmel_hlcdc_create_outputs(struct drm_device *dev)
if (!ret) if (!ret)
ret = atmel_hlcdc_check_endpoint(dev, &ep); ret = atmel_hlcdc_check_endpoint(dev, &ep);
if (ret) {
of_node_put(ep_np); of_node_put(ep_np);
if (ret)
return ret; return ret;
} }
}
for_each_endpoint_of_node(dev->dev->of_node, ep_np) { for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
ret = of_graph_parse_endpoint(ep_np, &ep); ret = of_graph_parse_endpoint(ep_np, &ep);
if (!ret) if (!ret)
ret = atmel_hlcdc_attach_endpoint(dev, &ep); ret = atmel_hlcdc_attach_endpoint(dev, &ep);
if (ret) {
of_node_put(ep_np); of_node_put(ep_np);
if (ret)
return ret; return ret;
} }
}
return 0; return 0;
} }
...@@ -339,6 +339,8 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane, ...@@ -339,6 +339,8 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff, atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff,
factor_reg); factor_reg);
} else {
atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff, 0);
} }
} }
......
...@@ -1296,14 +1296,39 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes); ...@@ -1296,14 +1296,39 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes);
*/ */
void drm_atomic_legacy_backoff(struct drm_atomic_state *state) void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
{ {
struct drm_device *dev = state->dev;
unsigned crtc_mask = 0;
struct drm_crtc *crtc;
int ret; int ret;
bool global = false;
drm_for_each_crtc(crtc, dev) {
if (crtc->acquire_ctx != state->acquire_ctx)
continue;
crtc_mask |= drm_crtc_mask(crtc);
crtc->acquire_ctx = NULL;
}
if (WARN_ON(dev->mode_config.acquire_ctx == state->acquire_ctx)) {
global = true;
dev->mode_config.acquire_ctx = NULL;
}
retry: retry:
drm_modeset_backoff(state->acquire_ctx); drm_modeset_backoff(state->acquire_ctx);
ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx); ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx);
if (ret) if (ret)
goto retry; goto retry;
drm_for_each_crtc(crtc, dev)
if (drm_crtc_mask(crtc) & crtc_mask)
crtc->acquire_ctx = state->acquire_ctx;
if (global)
dev->mode_config.acquire_ctx = state->acquire_ctx;
} }
EXPORT_SYMBOL(drm_atomic_legacy_backoff); EXPORT_SYMBOL(drm_atomic_legacy_backoff);
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "exynos_drm_plane.h" #include "exynos_drm_plane.h"
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_fb.h" #include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_iommu.h" #include "exynos_drm_iommu.h"
/* /*
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
struct exynos_dp_device { struct exynos_dp_device {
struct drm_encoder encoder; struct drm_encoder encoder;
struct drm_connector connector; struct drm_connector *connector;
struct drm_bridge *ptn_bridge; struct drm_bridge *ptn_bridge;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct device *dev; struct device *dev;
...@@ -70,7 +70,7 @@ static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data) ...@@ -70,7 +70,7 @@ static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data)
static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data) static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data)
{ {
struct exynos_dp_device *dp = to_dp(plat_data); struct exynos_dp_device *dp = to_dp(plat_data);
struct drm_connector *connector = &dp->connector; struct drm_connector *connector = dp->connector;
struct drm_display_mode *mode; struct drm_display_mode *mode;
int num_modes = 0; int num_modes = 0;
...@@ -103,6 +103,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data, ...@@ -103,6 +103,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
int ret; int ret;
drm_connector_register(connector); drm_connector_register(connector);
dp->connector = connector;
/* Pre-empt DP connector creation if there's a bridge */ /* Pre-empt DP connector creation if there's a bridge */
if (dp->ptn_bridge) { if (dp->ptn_bridge) {
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_fbdev.h"
static LIST_HEAD(exynos_drm_subdrv_list); static LIST_HEAD(exynos_drm_subdrv_list);
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_fb.h" #include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h" #include "exynos_drm_plane.h"
#include "exynos_drm_iommu.h" #include "exynos_drm_iommu.h"
...@@ -120,7 +119,6 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = { ...@@ -120,7 +119,6 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = {
.timing_base = 0x0, .timing_base = 0x0,
.has_clksel = 1, .has_clksel = 1,
.has_limited_fmt = 1, .has_limited_fmt = 1,
.has_hw_trigger = 1,
}; };
static struct fimd_driver_data exynos3_fimd_driver_data = { static struct fimd_driver_data exynos3_fimd_driver_data = {
...@@ -171,14 +169,11 @@ static struct fimd_driver_data exynos5420_fimd_driver_data = { ...@@ -171,14 +169,11 @@ static struct fimd_driver_data exynos5420_fimd_driver_data = {
.lcdblk_vt_shift = 24, .lcdblk_vt_shift = 24,
.lcdblk_bypass_shift = 15, .lcdblk_bypass_shift = 15,
.lcdblk_mic_bypass_shift = 11, .lcdblk_mic_bypass_shift = 11,
.trg_type = I80_HW_TRG,
.has_shadowcon = 1, .has_shadowcon = 1,
.has_vidoutcon = 1, .has_vidoutcon = 1,
.has_vtsel = 1, .has_vtsel = 1,
.has_mic_bypass = 1, .has_mic_bypass = 1,
.has_dp_clk = 1, .has_dp_clk = 1,
.has_hw_trigger = 1,
.has_trigger_per_te = 1,
}; };
struct fimd_context { struct fimd_context {
......
...@@ -48,13 +48,13 @@ ...@@ -48,13 +48,13 @@
/* registers for base address */ /* registers for base address */
#define G2D_SRC_BASE_ADDR 0x0304 #define G2D_SRC_BASE_ADDR 0x0304
#define G2D_SRC_STRIDE_REG 0x0308 #define G2D_SRC_STRIDE 0x0308
#define G2D_SRC_COLOR_MODE 0x030C #define G2D_SRC_COLOR_MODE 0x030C
#define G2D_SRC_LEFT_TOP 0x0310 #define G2D_SRC_LEFT_TOP 0x0310
#define G2D_SRC_RIGHT_BOTTOM 0x0314 #define G2D_SRC_RIGHT_BOTTOM 0x0314
#define G2D_SRC_PLANE2_BASE_ADDR 0x0318 #define G2D_SRC_PLANE2_BASE_ADDR 0x0318
#define G2D_DST_BASE_ADDR 0x0404 #define G2D_DST_BASE_ADDR 0x0404
#define G2D_DST_STRIDE_REG 0x0408 #define G2D_DST_STRIDE 0x0408
#define G2D_DST_COLOR_MODE 0x040C #define G2D_DST_COLOR_MODE 0x040C
#define G2D_DST_LEFT_TOP 0x0410 #define G2D_DST_LEFT_TOP 0x0410
#define G2D_DST_RIGHT_BOTTOM 0x0414 #define G2D_DST_RIGHT_BOTTOM 0x0414
...@@ -563,7 +563,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset) ...@@ -563,7 +563,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
switch (reg_offset) { switch (reg_offset) {
case G2D_SRC_BASE_ADDR: case G2D_SRC_BASE_ADDR:
case G2D_SRC_STRIDE_REG: case G2D_SRC_STRIDE:
case G2D_SRC_COLOR_MODE: case G2D_SRC_COLOR_MODE:
case G2D_SRC_LEFT_TOP: case G2D_SRC_LEFT_TOP:
case G2D_SRC_RIGHT_BOTTOM: case G2D_SRC_RIGHT_BOTTOM:
...@@ -573,7 +573,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset) ...@@ -573,7 +573,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
reg_type = REG_TYPE_SRC_PLANE2; reg_type = REG_TYPE_SRC_PLANE2;
break; break;
case G2D_DST_BASE_ADDR: case G2D_DST_BASE_ADDR:
case G2D_DST_STRIDE_REG: case G2D_DST_STRIDE:
case G2D_DST_COLOR_MODE: case G2D_DST_COLOR_MODE:
case G2D_DST_LEFT_TOP: case G2D_DST_LEFT_TOP:
case G2D_DST_RIGHT_BOTTOM: case G2D_DST_RIGHT_BOTTOM:
...@@ -968,8 +968,8 @@ static int g2d_check_reg_offset(struct device *dev, ...@@ -968,8 +968,8 @@ static int g2d_check_reg_offset(struct device *dev,
} else } else
buf_info->types[reg_type] = BUF_TYPE_GEM; buf_info->types[reg_type] = BUF_TYPE_GEM;
break; break;
case G2D_SRC_STRIDE_REG: case G2D_SRC_STRIDE:
case G2D_DST_STRIDE_REG: case G2D_DST_STRIDE:
if (for_addr) if (for_addr)
goto err; goto err;
......
...@@ -242,7 +242,7 @@ exynos_drm_plane_check_size(const struct exynos_drm_plane_config *config, ...@@ -242,7 +242,7 @@ exynos_drm_plane_check_size(const struct exynos_drm_plane_config *config,
state->v_ratio == (1 << 15)) state->v_ratio == (1 << 15))
height_ok = true; height_ok = true;
if (width_ok & height_ok) if (width_ok && height_ok)
return 0; return 0;
DRM_DEBUG_KMS("scaling mode is not supported"); DRM_DEBUG_KMS("scaling mode is not supported");
......
...@@ -4977,9 +4977,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) ...@@ -4977,9 +4977,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
intel_display_power_get(dev_priv, power_domain); intel_display_power_get(dev_priv, power_domain);
if (long_hpd) { if (long_hpd) {
/* indicate that we need to restart link training */
intel_dp->train_set_valid = false;
intel_dp_long_pulse(intel_dp->attached_connector); intel_dp_long_pulse(intel_dp->attached_connector);
if (intel_dp->is_mst) if (intel_dp->is_mst)
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
......
...@@ -85,7 +85,6 @@ static bool ...@@ -85,7 +85,6 @@ static bool
intel_dp_reset_link_train(struct intel_dp *intel_dp, intel_dp_reset_link_train(struct intel_dp *intel_dp,
uint8_t dp_train_pat) uint8_t dp_train_pat)
{ {
if (!intel_dp->train_set_valid)
memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set)); memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
intel_dp_set_signal_levels(intel_dp); intel_dp_set_signal_levels(intel_dp);
return intel_dp_set_link_train(intel_dp, dp_train_pat); return intel_dp_set_link_train(intel_dp, dp_train_pat);
...@@ -161,23 +160,6 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) ...@@ -161,23 +160,6 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
break; break;
} }
/*
* if we used previously trained voltage and pre-emphasis values
* and we don't get clock recovery, reset link training values
*/
if (intel_dp->train_set_valid) {
DRM_DEBUG_KMS("clock recovery not ok, reset");
/* clear the flag as we are not reusing train set */
intel_dp->train_set_valid = false;
if (!intel_dp_reset_link_train(intel_dp,
DP_TRAINING_PATTERN_1 |
DP_LINK_SCRAMBLING_DISABLE)) {
DRM_ERROR("failed to enable link training\n");
return;
}
continue;
}
/* Check to see if we've tried the max voltage */ /* Check to see if we've tried the max voltage */
for (i = 0; i < intel_dp->lane_count; i++) for (i = 0; i < intel_dp->lane_count; i++)
if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
...@@ -284,7 +266,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) ...@@ -284,7 +266,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
/* Make sure clock is still ok */ /* Make sure clock is still ok */
if (!drm_dp_clock_recovery_ok(link_status, if (!drm_dp_clock_recovery_ok(link_status,
intel_dp->lane_count)) { intel_dp->lane_count)) {
intel_dp->train_set_valid = false;
intel_dp_link_training_clock_recovery(intel_dp); intel_dp_link_training_clock_recovery(intel_dp);
intel_dp_set_link_train(intel_dp, intel_dp_set_link_train(intel_dp,
training_pattern | training_pattern |
...@@ -301,7 +282,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) ...@@ -301,7 +282,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
/* Try 5 times, then try clock recovery if that fails */ /* Try 5 times, then try clock recovery if that fails */
if (tries > 5) { if (tries > 5) {
intel_dp->train_set_valid = false;
intel_dp_link_training_clock_recovery(intel_dp); intel_dp_link_training_clock_recovery(intel_dp);
intel_dp_set_link_train(intel_dp, intel_dp_set_link_train(intel_dp,
training_pattern | training_pattern |
...@@ -322,10 +302,8 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) ...@@ -322,10 +302,8 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
intel_dp_set_idle_link_train(intel_dp); intel_dp_set_idle_link_train(intel_dp);
if (channel_eq) { if (channel_eq)
intel_dp->train_set_valid = true;
DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
}
} }
void intel_dp_stop_link_train(struct intel_dp *intel_dp) void intel_dp_stop_link_train(struct intel_dp *intel_dp)
......
...@@ -863,8 +863,6 @@ struct intel_dp { ...@@ -863,8 +863,6 @@ struct intel_dp {
/* This is called before a link training is starterd */ /* This is called before a link training is starterd */
void (*prepare_link_retrain)(struct intel_dp *intel_dp); void (*prepare_link_retrain)(struct intel_dp *intel_dp);
bool train_set_valid;
/* Displayport compliance testing */ /* Displayport compliance testing */
unsigned long compliance_test_type; unsigned long compliance_test_type;
unsigned long compliance_test_data; unsigned long compliance_test_data;
......
...@@ -824,8 +824,7 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc) ...@@ -824,8 +824,7 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc)
{ {
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc *fbc = &dev_priv->fbc;
bool enable_by_default = IS_HASWELL(dev_priv) || bool enable_by_default = IS_BROADWELL(dev_priv);
IS_BROADWELL(dev_priv);
if (intel_vgpu_active(dev_priv->dev)) { if (intel_vgpu_active(dev_priv->dev)) {
fbc->no_fbc_reason = "VGPU is active"; fbc->no_fbc_reason = "VGPU is active";
......
...@@ -552,6 +552,7 @@ nouveau_fbcon_init(struct drm_device *dev) ...@@ -552,6 +552,7 @@ nouveau_fbcon_init(struct drm_device *dev)
if (ret) if (ret)
goto fini; goto fini;
if (fbcon->helper.fbdev)
fbcon->helper.fbdev->pixmap.buf_align = 4; fbcon->helper.fbdev->pixmap.buf_align = 4;
return 0; return 0;
......
config DRM_SUN4I config DRM_SUN4I
tristate "DRM Support for Allwinner A10 Display Engine" tristate "DRM Support for Allwinner A10 Display Engine"
depends on DRM && ARM depends on DRM && ARM && COMMON_CLK
depends on ARCH_SUNXI || COMPILE_TEST depends on ARCH_SUNXI || COMPILE_TEST
select DRM_GEM_CMA_HELPER select DRM_GEM_CMA_HELPER
select DRM_KMS_HELPER select DRM_KMS_HELPER
......
...@@ -190,7 +190,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, ...@@ -190,7 +190,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
/* Get the physical address of the buffer in memory */ /* Get the physical address of the buffer in memory */
gem = drm_fb_cma_get_gem_obj(fb, 0); gem = drm_fb_cma_get_gem_obj(fb, 0);
DRM_DEBUG_DRIVER("Using GEM @ 0x%x\n", gem->paddr); DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
/* Compute the start of the displayed memory */ /* Compute the start of the displayed memory */
bpp = drm_format_plane_cpp(fb->pixel_format, 0); bpp = drm_format_plane_cpp(fb->pixel_format, 0);
...@@ -198,7 +198,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, ...@@ -198,7 +198,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
paddr += (state->src_x >> 16) * bpp; paddr += (state->src_x >> 16) * bpp;
paddr += (state->src_y >> 16) * fb->pitches[0]; paddr += (state->src_y >> 16) * fb->pitches[0];
DRM_DEBUG_DRIVER("Setting buffer address to 0x%x\n", paddr); DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
/* Write the 32 lower bits of the address (in bits) */ /* Write the 32 lower bits of the address (in bits) */
lo_paddr = paddr << 3; lo_paddr = paddr << 3;
......
...@@ -72,14 +72,40 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw, ...@@ -72,14 +72,40 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate, static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate) unsigned long *parent_rate)
{ {
return *parent_rate / DIV_ROUND_CLOSEST(*parent_rate, rate); unsigned long best_parent = 0;
u8 best_div = 1;
int i;
for (i = 6; i < 127; i++) {
unsigned long ideal = rate * i;
unsigned long rounded;
rounded = clk_hw_round_rate(clk_hw_get_parent(hw),
ideal);
if (rounded == ideal) {
best_parent = rounded;
best_div = i;
goto out;
}
if ((rounded < ideal) && (rounded > best_parent)) {
best_parent = rounded;
best_div = i;
}
}
out:
*parent_rate = best_parent;
return best_parent / best_div;
} }
static int sun4i_dclk_set_rate(struct clk_hw *hw, unsigned long rate, static int sun4i_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct sun4i_dclk *dclk = hw_to_dclk(hw); struct sun4i_dclk *dclk = hw_to_dclk(hw);
int div = DIV_ROUND_CLOSEST(parent_rate, rate); u8 div = parent_rate / rate;
return regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG, return regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG,
GENMASK(6, 0), div); GENMASK(6, 0), div);
...@@ -127,10 +153,14 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon) ...@@ -127,10 +153,14 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
const char *clk_name, *parent_name; const char *clk_name, *parent_name;
struct clk_init_data init; struct clk_init_data init;
struct sun4i_dclk *dclk; struct sun4i_dclk *dclk;
int ret;
parent_name = __clk_get_name(tcon->sclk0); parent_name = __clk_get_name(tcon->sclk0);
of_property_read_string_index(dev->of_node, "clock-output-names", 0, ret = of_property_read_string_index(dev->of_node,
"clock-output-names", 0,
&clk_name); &clk_name);
if (ret)
return ret;
dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL); dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
if (!dclk) if (!dclk)
...@@ -140,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon) ...@@ -140,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
init.ops = &sun4i_dclk_ops; init.ops = &sun4i_dclk_ops;
init.parent_names = &parent_name; init.parent_names = &parent_name;
init.num_parents = 1; init.num_parents = 1;
init.flags = CLK_SET_RATE_PARENT;
dclk->regmap = tcon->regs; dclk->regmap = tcon->regs;
dclk->hw.init = &init; dclk->hw.init = &init;
......
...@@ -24,34 +24,6 @@ ...@@ -24,34 +24,6 @@
#include "sun4i_layer.h" #include "sun4i_layer.h"
#include "sun4i_tcon.h" #include "sun4i_tcon.h"
static int sun4i_drv_connector_plug_all(struct drm_device *drm)
{
struct drm_connector *connector, *failed;
int ret;
mutex_lock(&drm->mode_config.mutex);
list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
ret = drm_connector_register(connector);
if (ret) {
failed = connector;
goto err;
}
}
mutex_unlock(&drm->mode_config.mutex);
return 0;
err:
list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
if (failed == connector)
break;
drm_connector_unregister(connector);
}
mutex_unlock(&drm->mode_config.mutex);
return ret;
}
static int sun4i_drv_enable_vblank(struct drm_device *drm, unsigned int pipe) static int sun4i_drv_enable_vblank(struct drm_device *drm, unsigned int pipe)
{ {
struct sun4i_drv *drv = drm->dev_private; struct sun4i_drv *drv = drm->dev_private;
...@@ -125,6 +97,22 @@ static struct drm_driver sun4i_drv_driver = { ...@@ -125,6 +97,22 @@ static struct drm_driver sun4i_drv_driver = {
.disable_vblank = sun4i_drv_disable_vblank, .disable_vblank = sun4i_drv_disable_vblank,
}; };
static void sun4i_remove_framebuffers(void)
{
struct apertures_struct *ap;
ap = alloc_apertures(1);
if (!ap)
return;
/* The framebuffer can be located anywhere in RAM */
ap->ranges[0].base = 0;
ap->ranges[0].size = ~0;
remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false);
kfree(ap);
}
static int sun4i_drv_bind(struct device *dev) static int sun4i_drv_bind(struct device *dev)
{ {
struct drm_device *drm; struct drm_device *drm;
...@@ -172,6 +160,9 @@ static int sun4i_drv_bind(struct device *dev) ...@@ -172,6 +160,9 @@ static int sun4i_drv_bind(struct device *dev)
} }
drm->irq_enabled = true; drm->irq_enabled = true;
/* Remove early framebuffers (ie. simplefb) */
sun4i_remove_framebuffers();
/* Create our framebuffer */ /* Create our framebuffer */
drv->fbdev = sun4i_framebuffer_init(drm); drv->fbdev = sun4i_framebuffer_init(drm);
if (IS_ERR(drv->fbdev)) { if (IS_ERR(drv->fbdev)) {
...@@ -187,7 +178,7 @@ static int sun4i_drv_bind(struct device *dev) ...@@ -187,7 +178,7 @@ static int sun4i_drv_bind(struct device *dev)
if (ret) if (ret)
goto free_drm; goto free_drm;
ret = sun4i_drv_connector_plug_all(drm); ret = drm_connector_register_all(drm);
if (ret) if (ret)
goto unregister_drm; goto unregister_drm;
...@@ -204,6 +195,7 @@ static void sun4i_drv_unbind(struct device *dev) ...@@ -204,6 +195,7 @@ static void sun4i_drv_unbind(struct device *dev)
{ {
struct drm_device *drm = dev_get_drvdata(dev); struct drm_device *drm = dev_get_drvdata(dev);
drm_connector_unregister_all(drm);
drm_dev_unregister(drm); drm_dev_unregister(drm);
drm_kms_helper_poll_fini(drm); drm_kms_helper_poll_fini(drm);
sun4i_framebuffer_free(drm); sun4i_framebuffer_free(drm);
......
...@@ -54,8 +54,13 @@ static int sun4i_rgb_get_modes(struct drm_connector *connector) ...@@ -54,8 +54,13 @@ static int sun4i_rgb_get_modes(struct drm_connector *connector)
static int sun4i_rgb_mode_valid(struct drm_connector *connector, static int sun4i_rgb_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector);
struct sun4i_drv *drv = rgb->drv;
struct sun4i_tcon *tcon = drv->tcon;
u32 hsync = mode->hsync_end - mode->hsync_start; u32 hsync = mode->hsync_end - mode->hsync_start;
u32 vsync = mode->vsync_end - mode->vsync_start; u32 vsync = mode->vsync_end - mode->vsync_start;
unsigned long rate = mode->clock * 1000;
long rounded_rate;
DRM_DEBUG_DRIVER("Validating modes...\n"); DRM_DEBUG_DRIVER("Validating modes...\n");
...@@ -87,6 +92,15 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector, ...@@ -87,6 +92,15 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector,
DRM_DEBUG_DRIVER("Vertical parameters OK\n"); DRM_DEBUG_DRIVER("Vertical parameters OK\n");
rounded_rate = clk_round_rate(tcon->dclk, rate);
if (rounded_rate < rate)
return MODE_CLOCK_LOW;
if (rounded_rate > rate)
return MODE_CLOCK_HIGH;
DRM_DEBUG_DRIVER("Clock rate OK\n");
return MODE_OK; return MODE_OK;
} }
...@@ -203,7 +217,7 @@ int sun4i_rgb_init(struct drm_device *drm) ...@@ -203,7 +217,7 @@ int sun4i_rgb_init(struct drm_device *drm)
int ret; int ret;
/* If we don't have a panel, there's no point in going on */ /* If we don't have a panel, there's no point in going on */
if (!tcon->panel) if (IS_ERR(tcon->panel))
return -ENODEV; return -ENODEV;
rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL); rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL);
......
...@@ -425,11 +425,11 @@ static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node) ...@@ -425,11 +425,11 @@ static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
remote = of_graph_get_remote_port_parent(end_node); remote = of_graph_get_remote_port_parent(end_node);
if (!remote) { if (!remote) {
DRM_DEBUG_DRIVER("Enable to parse remote node\n"); DRM_DEBUG_DRIVER("Unable to parse remote node\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
return of_drm_find_panel(remote); return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
} }
static int sun4i_tcon_bind(struct device *dev, struct device *master, static int sun4i_tcon_bind(struct device *dev, struct device *master,
...@@ -490,7 +490,11 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, ...@@ -490,7 +490,11 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
return 0; return 0;
} }
return sun4i_rgb_init(drm); ret = sun4i_rgb_init(drm);
if (ret < 0)
goto err_free_clocks;
return 0;
err_free_clocks: err_free_clocks:
sun4i_tcon_free_clocks(tcon); sun4i_tcon_free_clocks(tcon);
...@@ -522,11 +526,12 @@ static int sun4i_tcon_probe(struct platform_device *pdev) ...@@ -522,11 +526,12 @@ static int sun4i_tcon_probe(struct platform_device *pdev)
* Defer the probe. * Defer the probe.
*/ */
panel = sun4i_tcon_find_panel(node); panel = sun4i_tcon_find_panel(node);
if (IS_ERR(panel)) {
/* /*
* If we don't have a panel endpoint, just go on * If we don't have a panel endpoint, just go on
*/ */
if (PTR_ERR(panel) != -ENODEV) if (PTR_ERR(panel) == -EPROBE_DEFER) {
DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册