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()
  ...
This commit is contained in:
Linus Torvalds 2016-06-23 21:35:12 -07:00
commit 0bf0ea431f
40 changed files with 598 additions and 256 deletions

View File

@ -909,7 +909,7 @@ static int amdgpu_cgs_acpi_eval_object(struct cgs_device *cgs_device,
struct cgs_acpi_method_argument *argument = NULL;
uint32_t i, count;
acpi_status status;
int result;
int result = 0;
uint32_t func_no = 0xFFFFFFFF;
handle = ACPI_HANDLE(&adev->pdev->dev);

View File

@ -1535,7 +1535,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
/* Post card if necessary */
if (!amdgpu_card_posted(adev) ||
(adev->virtualization.is_virtual &&
!adev->virtualization.caps & AMDGPU_VIRT_CAPS_SRIOV_EN)) {
!(adev->virtualization.caps & AMDGPU_VIRT_CAPS_SRIOV_EN))) {
if (!adev->bios) {
dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n");
return -EINVAL;

View 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.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._pad = 0;
dev_info.ids_flags = 0;

View File

@ -270,30 +270,28 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private;
enum amd_pm_state_type state = 0;
long idx;
unsigned long idx;
int ret;
if (strlen(buf) == 1)
adev->pp_force_state_enabled = false;
else {
ret = kstrtol(buf, 0, &idx);
else if (adev->pp_enabled) {
struct pp_states_info data;
if (ret) {
ret = kstrtoul(buf, 0, &idx);
if (ret || idx >= ARRAY_SIZE(data.states)) {
count = -EINVAL;
goto fail;
}
if (adev->pp_enabled) {
struct pp_states_info data;
amdgpu_dpm_get_pp_num_states(adev, &data);
state = data.states[idx];
/* only set user selected power states */
if (state != POWER_STATE_TYPE_INTERNAL_BOOT &&
state != POWER_STATE_TYPE_DEFAULT) {
amdgpu_dpm_dispatch_task(adev,
AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
adev->pp_force_state_enabled = true;
}
amdgpu_dpm_get_pp_num_states(adev, &data);
state = data.states[idx];
/* only set user selected power states */
if (state != POWER_STATE_TYPE_INTERNAL_BOOT &&
state != POWER_STATE_TYPE_DEFAULT) {
amdgpu_dpm_dispatch_task(adev,
AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
adev->pp_force_state_enabled = true;
}
}
fail:

View File

@ -297,7 +297,8 @@ static const u32 polaris11_golden_common_all[] =
static const u32 golden_settings_polaris10_a11[] =
{
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,
mmDB_DEBUG2, 0xf00fffff, 0x00000400,
mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,

View File

@ -5538,6 +5538,78 @@ typedef struct _ATOM_ASIC_PROFILING_INFO_V3_5
ULONG ulReserved[12];
}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{
ULONG ulMaxSclkFreq;

View File

@ -633,6 +633,8 @@ static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
data->vddci_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,
VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
data->voltage_control = FIJI_VOLTAGE_CONTROL_BY_SVID2;

View File

@ -306,10 +306,14 @@ int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr,
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->store_cc6_data == NULL)
if (display_config == NULL)
return -EINVAL;
hwmgr->display_config = *display_config;
if (hwmgr->hwmgr_func->store_cc6_data == NULL)
return -EINVAL;
/* to do pass other display configuration in furture */
if (hwmgr->hwmgr_func->store_cc6_data)

View File

@ -1296,7 +1296,6 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
}
mem_level->MclkFrequency = clock;
mem_level->StutterEnable = 0;
mem_level->EnabledForThrottle = 1;
mem_level->EnabledForActivity = 0;
mem_level->UpHyst = 0;
@ -1304,7 +1303,6 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
mem_level->VoltageDownHyst = 0;
mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
mem_level->StutterEnable = false;
mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
data->display_timing.num_existing_displays = info.display_count;
@ -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
* 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);
data->smc_state_table.MemoryDpmLevelCount =
@ -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)
{
uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks,
volt_with_cks, value;
uint16_t clock_freq_u16;
uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min;
struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2,
volt_offset = 0;
uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0;
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
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)
* if the part is SS or FF. if RO >= 1660MHz, part is FF.
*/
efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
ixSMU_EFUSE_0 + (146 * 4));
efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
ixSMU_EFUSE_0 + (148 * 4));
ixSMU_EFUSE_0 + (67 * 4));
efuse &= 0xFF000000;
efuse = efuse >> 24;
efuse2 &= 0xF;
if (efuse2 == 1)
ro = (2300 - 1350) * efuse / 255 + 1350;
else
ro = (2500 - 1000) * efuse / 255 + 1000;
if (hwmgr->chip_id == CHIP_POLARIS10) {
min = 1000;
max = 2300;
} else {
min = 1100;
max = 2100;
}
if (ro >= 1660)
type = 0;
else
type = 1;
/* Populate Stretch amount */
data->smc_state_table.ClockStretcherAmount = stretch_amount;
ro = efuse * (max -min)/255 + min;
/* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
for (i = 0; i < sclk_table->count; i++) {
data->smc_state_table.Sclk_CKS_masterEn0_7 |=
sclk_table->entries[i].cks_enable << i;
volt_without_cks = (uint32_t)((14041 *
(sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 /
(4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000)));
volt_with_cks = (uint32_t)((13946 *
(sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 /
(3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000)));
volt_without_cks = (uint32_t)(((ro - 40) * 1000 - 2753594 - sclk_table->entries[i].clk/100 * 136418 /1000) / \
(sclk_table->entries[i].clk/100 * 1132925 /10000 - 242418)/100);
volt_with_cks = (uint32_t)((ro * 1000 -2396351 - sclk_table->entries[i].clk/100 * 329021/1000) / \
(sclk_table->entries[i].clk/10000 * 649434 /1000 - 18005)/10);
if (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);
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 */
if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
stretch_amount2 = 0;
@ -1835,69 +1818,6 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
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 &= 0xFFFFFFFE;
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,
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
*
@ -2056,6 +2060,10 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
"Failed to populate Clock Stretcher Data Table!",
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->GraphicsVoltageChangeEnable = 1;
table->GraphicsThermThrottleEnable = 1;
@ -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)
{
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 */
if (!data->sclk_dpm_key_disabled)
@ -2262,6 +2273,12 @@ static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
/* enable MCLK dpm */
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(
(0 == smum_send_msg_to_smc(hwmgr->smumgr,
@ -2269,7 +2286,6 @@ static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
"Failed to enable MCLK DPM during DPM Start Function!",
return -1);
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);
@ -2606,6 +2622,7 @@ int polaris10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_FanSpeedInTableIsRPM);
if (hwmgr->chip_id == CHIP_POLARIS11)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SPLLShutdownSupport);
@ -2938,6 +2955,11 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
data->vddci_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,
VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
data->voltage_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2;
@ -2962,6 +2984,10 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
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_init_dpm_defaults(hwmgr);

View File

@ -312,6 +312,9 @@ struct polaris10_hwmgr {
/* soft pptable for re-uploading into smu */
void *soft_pp_table;
uint32_t avfs_vdroop_override_setting;
bool apply_avfs_cks_off_voltage;
};
/* To convert to Q8.8 format for firmware */

View File

@ -625,10 +625,14 @@ static int tf_polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr,
int ret;
struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr);
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;
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) ?
0 : -1;

View File

@ -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;
}
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)
{
struct atcs_pref_req_input atcs_input;
@ -52,7 +66,7 @@ int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
int result;
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;
info.size = sizeof(struct cgs_system_info);
@ -77,7 +91,7 @@ int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST,
&atcs_input,
&atcs_output,
0,
1,
sizeof(atcs_input),
sizeof(atcs_output));
if (result != 0)

View File

@ -1302,3 +1302,46 @@ int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctr
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;
}

View File

@ -250,6 +250,35 @@ struct 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 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);
@ -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,
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_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param);
#endif

View File

@ -4489,6 +4489,7 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_NONE;
data->vdd_gfx_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,
VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {

View File

@ -27,6 +27,7 @@
#pragma pack(push, 1)
#define PPSMC_MSG_SetGBDroopSettings ((uint16_t) 0x305)
#define PPSMC_SWSTATE_FLAG_DC 0x01
#define PPSMC_SWSTATE_FLAG_UVD 0x02

View File

@ -26,3 +26,4 @@ extern bool acpi_atcs_functions_supported(void *device,
extern int acpi_pcie_perf_request(void *device,
uint8_t perf_req,
bool advertise);
extern bool acpi_atcs_notify_pcie_device_ready(void *device);

View File

@ -34,6 +34,30 @@
#define SMU__NUM_LCLK_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 {
SID_OPTION_HI,
SID_OPTION_LO,
@ -548,20 +572,20 @@ struct SMU74_Firmware_Header {
uint32_t CacConfigTable;
uint32_t CacStatusTable;
uint32_t mcRegisterTable;
uint32_t mcArbDramTimingTable;
uint32_t PmFuseTable;
uint32_t Globals;
uint32_t ClockStretcherTable;
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;
};
@ -701,8 +725,6 @@ VR Config info is contained in dpmTable.VRConfig */
struct SMU_ClockStretcherDataTableEntry {
uint8_t minVID;
uint8_t maxVID;
uint16_t setting;
};
typedef struct SMU_ClockStretcherDataTableEntry SMU_ClockStretcherDataTableEntry;
@ -769,6 +791,43 @@ struct 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

View File

@ -223,6 +223,16 @@ struct 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 {
SMU74_PIDController GraphicsPIDController;
@ -258,7 +268,14 @@ struct SMU74_Discrete_DpmTable {
uint8_t ThermOutPolarity;
uint8_t ThermOutMode;
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_MemoryLevel MemoryACPILevel;
@ -347,6 +364,8 @@ struct SMU74_Discrete_DpmTable {
uint32_t CurrSclkPllRange;
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;
@ -550,16 +569,6 @@ struct 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 {
uint8_t BapmVddCVidHiSidd[8];
uint8_t BapmVddCVidLoSidd[8];
@ -821,6 +830,17 @@ typedef struct SMU7_GfxCuPgScoreboard SMU7_GfxCuPgScoreboard;
#define DB_PCC_SHIFT 26
#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)

View File

@ -52,19 +52,18 @@
static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = {
/* 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 */
{ 0x3c0fd047, 0x00, 0x03, 0x1e00, 0x00200410, 0x87020000, 0, 0, 0x16, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x30750000, 0, 0, 0, 0, 0, 0, 0 } },
{ 0xa00fd047, 0x01, 0x04, 0x1e00, 0x00800510, 0x87020000, 0, 0, 0x16, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x409c0000, 0, 0, 0, 0, 0, 0, 0 } },
{ 0x0410d047, 0x01, 0x00, 0x1e00, 0x00600410, 0x87020000, 0, 0, 0x0e, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x50c30000, 0, 0, 0, 0, 0, 0, 0 } },
{ 0x6810d047, 0x01, 0x00, 0x1e00, 0x00800410, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x60ea0000, 0, 0, 0, 0, 0, 0, 0 } },
{ 0xcc10d047, 0x01, 0x00, 0x1e00, 0x00e00410, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0xe8fd0000, 0, 0, 0, 0, 0, 0, 0 } },
{ 0x3011d047, 0x01, 0x00, 0x1e00, 0x00400510, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x70110100, 0, 0, 0, 0, 0, 0, 0 } },
{ 0x9411d047, 0x01, 0x00, 0x1e00, 0x00a00510, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0xf8240100, 0, 0, 0, 0, 0, 0, 0 } },
{ 0xf811d047, 0x01, 0x00, 0x1e00, 0x00000610, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x80380100, 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 } },
{ 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 } },
{ 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 } },
{ 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 } },
{ 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 } },
{ 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 } },
{ 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 } },
{ 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 =
{0x50140000, 0x50140000, 0x00320000, 0x00, 0x00,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00};
{0x100ea446, 0, 0x30750000, 0x01, 0x01, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x1f00, 0x00, 0x00};
/**
* Set the address for reading/writing the SMC SRAM space.
@ -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)));
}
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.
*
@ -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 ret;
if (!polaris10_is_smc_ram_running(smumgr))
return -1;
SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP))
printk("Failed to send Previous Message.\n");
ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP);
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);
SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP))
printk("Failed to send Message.\n");
ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP);
if (ret != 1)
printk("\n failed to send message %x ret is %d \n", msg, ret);
return 0;
}
@ -953,6 +970,11 @@ static int polaris10_smu_init(struct pp_smumgr *smumgr)
(cgs_handle_t)smu_data->smu_buffer.handle);
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;
}

View File

@ -266,9 +266,10 @@ int atmel_hlcdc_create_outputs(struct drm_device *dev)
if (!ret)
ret = atmel_hlcdc_check_endpoint(dev, &ep);
of_node_put(ep_np);
if (ret)
if (ret) {
of_node_put(ep_np);
return ret;
}
}
for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
@ -276,9 +277,10 @@ int atmel_hlcdc_create_outputs(struct drm_device *dev)
if (!ret)
ret = atmel_hlcdc_attach_endpoint(dev, &ep);
of_node_put(ep_np);
if (ret)
if (ret) {
of_node_put(ep_np);
return ret;
}
}
return 0;

View File

@ -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,
factor_reg);
} else {
atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff, 0);
}
}

View File

@ -1296,14 +1296,39 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes);
*/
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;
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:
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)
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);

View File

@ -31,7 +31,6 @@
#include "exynos_drm_plane.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_iommu.h"
/*

View File

@ -34,7 +34,7 @@
struct exynos_dp_device {
struct drm_encoder encoder;
struct drm_connector connector;
struct drm_connector *connector;
struct drm_bridge *ptn_bridge;
struct drm_device *drm_dev;
struct device *dev;
@ -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)
{
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;
int num_modes = 0;
@ -103,6 +103,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
int ret;
drm_connector_register(connector);
dp->connector = connector;
/* Pre-empt DP connector creation if there's a bridge */
if (dp->ptn_bridge) {

View File

@ -15,7 +15,6 @@
#include <drm/drmP.h>
#include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h"
#include "exynos_drm_fbdev.h"
static LIST_HEAD(exynos_drm_subdrv_list);

View File

@ -30,7 +30,6 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_iommu.h"
@ -120,7 +119,6 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = {
.timing_base = 0x0,
.has_clksel = 1,
.has_limited_fmt = 1,
.has_hw_trigger = 1,
};
static struct fimd_driver_data exynos3_fimd_driver_data = {
@ -171,14 +169,11 @@ static struct fimd_driver_data exynos5420_fimd_driver_data = {
.lcdblk_vt_shift = 24,
.lcdblk_bypass_shift = 15,
.lcdblk_mic_bypass_shift = 11,
.trg_type = I80_HW_TRG,
.has_shadowcon = 1,
.has_vidoutcon = 1,
.has_vtsel = 1,
.has_mic_bypass = 1,
.has_dp_clk = 1,
.has_hw_trigger = 1,
.has_trigger_per_te = 1,
};
struct fimd_context {

View File

@ -48,13 +48,13 @@
/* registers for base address */
#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_LEFT_TOP 0x0310
#define G2D_SRC_RIGHT_BOTTOM 0x0314
#define G2D_SRC_PLANE2_BASE_ADDR 0x0318
#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_LEFT_TOP 0x0410
#define G2D_DST_RIGHT_BOTTOM 0x0414
@ -563,7 +563,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
switch (reg_offset) {
case G2D_SRC_BASE_ADDR:
case G2D_SRC_STRIDE_REG:
case G2D_SRC_STRIDE:
case G2D_SRC_COLOR_MODE:
case G2D_SRC_LEFT_TOP:
case G2D_SRC_RIGHT_BOTTOM:
@ -573,7 +573,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
reg_type = REG_TYPE_SRC_PLANE2;
break;
case G2D_DST_BASE_ADDR:
case G2D_DST_STRIDE_REG:
case G2D_DST_STRIDE:
case G2D_DST_COLOR_MODE:
case G2D_DST_LEFT_TOP:
case G2D_DST_RIGHT_BOTTOM:
@ -968,8 +968,8 @@ static int g2d_check_reg_offset(struct device *dev,
} else
buf_info->types[reg_type] = BUF_TYPE_GEM;
break;
case G2D_SRC_STRIDE_REG:
case G2D_DST_STRIDE_REG:
case G2D_SRC_STRIDE:
case G2D_DST_STRIDE:
if (for_addr)
goto err;

View File

@ -242,7 +242,7 @@ exynos_drm_plane_check_size(const struct exynos_drm_plane_config *config,
state->v_ratio == (1 << 15))
height_ok = true;
if (width_ok & height_ok)
if (width_ok && height_ok)
return 0;
DRM_DEBUG_KMS("scaling mode is not supported");

View File

@ -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);
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);
if (intel_dp->is_mst)
ret = IRQ_HANDLED;

View File

@ -85,8 +85,7 @@ static bool
intel_dp_reset_link_train(struct intel_dp *intel_dp,
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);
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)
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 */
for (i = 0; i < intel_dp->lane_count; i++)
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)
/* Make sure clock is still ok */
if (!drm_dp_clock_recovery_ok(link_status,
intel_dp->lane_count)) {
intel_dp->train_set_valid = false;
intel_dp_link_training_clock_recovery(intel_dp);
intel_dp_set_link_train(intel_dp,
training_pattern |
@ -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 */
if (tries > 5) {
intel_dp->train_set_valid = false;
intel_dp_link_training_clock_recovery(intel_dp);
intel_dp_set_link_train(intel_dp,
training_pattern |
@ -322,10 +302,8 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
intel_dp_set_idle_link_train(intel_dp);
if (channel_eq) {
intel_dp->train_set_valid = true;
if (channel_eq)
DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
}
}
void intel_dp_stop_link_train(struct intel_dp *intel_dp)

View File

@ -863,8 +863,6 @@ struct intel_dp {
/* This is called before a link training is starterd */
void (*prepare_link_retrain)(struct intel_dp *intel_dp);
bool train_set_valid;
/* Displayport compliance testing */
unsigned long compliance_test_type;
unsigned long compliance_test_data;

View File

@ -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 intel_fbc *fbc = &dev_priv->fbc;
bool enable_by_default = IS_HASWELL(dev_priv) ||
IS_BROADWELL(dev_priv);
bool enable_by_default = IS_BROADWELL(dev_priv);
if (intel_vgpu_active(dev_priv->dev)) {
fbc->no_fbc_reason = "VGPU is active";

View File

@ -552,7 +552,8 @@ nouveau_fbcon_init(struct drm_device *dev)
if (ret)
goto fini;
fbcon->helper.fbdev->pixmap.buf_align = 4;
if (fbcon->helper.fbdev)
fbcon->helper.fbdev->pixmap.buf_align = 4;
return 0;
fini:

View File

@ -1,6 +1,6 @@
config DRM_SUN4I
tristate "DRM Support for Allwinner A10 Display Engine"
depends on DRM && ARM
depends on DRM && ARM && COMMON_CLK
depends on ARCH_SUNXI || COMPILE_TEST
select DRM_GEM_CMA_HELPER
select DRM_KMS_HELPER

View File

@ -190,7 +190,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
/* Get the physical address of the buffer in memory */
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 */
bpp = drm_format_plane_cpp(fb->pixel_format, 0);
@ -198,7 +198,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
paddr += (state->src_x >> 16) * bpp;
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) */
lo_paddr = paddr << 3;

View File

@ -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,
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,
unsigned long parent_rate)
{
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,
GENMASK(6, 0), div);
@ -127,10 +153,14 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
const char *clk_name, *parent_name;
struct clk_init_data init;
struct sun4i_dclk *dclk;
int ret;
parent_name = __clk_get_name(tcon->sclk0);
of_property_read_string_index(dev->of_node, "clock-output-names", 0,
&clk_name);
ret = of_property_read_string_index(dev->of_node,
"clock-output-names", 0,
&clk_name);
if (ret)
return ret;
dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
if (!dclk)
@ -140,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
init.ops = &sun4i_dclk_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = CLK_SET_RATE_PARENT;
dclk->regmap = tcon->regs;
dclk->hw.init = &init;

View File

@ -24,34 +24,6 @@
#include "sun4i_layer.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)
{
struct sun4i_drv *drv = drm->dev_private;
@ -125,6 +97,22 @@ static struct drm_driver sun4i_drv_driver = {
.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)
{
struct drm_device *drm;
@ -172,6 +160,9 @@ static int sun4i_drv_bind(struct device *dev)
}
drm->irq_enabled = true;
/* Remove early framebuffers (ie. simplefb) */
sun4i_remove_framebuffers();
/* Create our framebuffer */
drv->fbdev = sun4i_framebuffer_init(drm);
if (IS_ERR(drv->fbdev)) {
@ -187,7 +178,7 @@ static int sun4i_drv_bind(struct device *dev)
if (ret)
goto free_drm;
ret = sun4i_drv_connector_plug_all(drm);
ret = drm_connector_register_all(drm);
if (ret)
goto unregister_drm;
@ -204,6 +195,7 @@ static void sun4i_drv_unbind(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
drm_connector_unregister_all(drm);
drm_dev_unregister(drm);
drm_kms_helper_poll_fini(drm);
sun4i_framebuffer_free(drm);

View File

@ -54,8 +54,13 @@ static int sun4i_rgb_get_modes(struct drm_connector *connector)
static int sun4i_rgb_mode_valid(struct drm_connector *connector,
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 vsync = mode->vsync_end - mode->vsync_start;
unsigned long rate = mode->clock * 1000;
long rounded_rate;
DRM_DEBUG_DRIVER("Validating modes...\n");
@ -87,6 +92,15 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector,
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;
}
@ -203,7 +217,7 @@ int sun4i_rgb_init(struct drm_device *drm)
int ret;
/* If we don't have a panel, there's no point in going on */
if (!tcon->panel)
if (IS_ERR(tcon->panel))
return -ENODEV;
rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL);

View File

@ -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);
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 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,
@ -490,7 +490,11 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
return 0;
}
return sun4i_rgb_init(drm);
ret = sun4i_rgb_init(drm);
if (ret < 0)
goto err_free_clocks;
return 0;
err_free_clocks:
sun4i_tcon_free_clocks(tcon);
@ -522,12 +526,13 @@ static int sun4i_tcon_probe(struct platform_device *pdev)
* Defer the probe.
*/
panel = sun4i_tcon_find_panel(node);
if (IS_ERR(panel)) {
/*
* If we don't have a panel endpoint, just go on
*/
if (PTR_ERR(panel) != -ENODEV)
return -EPROBE_DEFER;
/*
* If we don't have a panel endpoint, just go on
*/
if (PTR_ERR(panel) == -EPROBE_DEFER) {
DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
return -EPROBE_DEFER;
}
return component_add(&pdev->dev, &sun4i_tcon_ops);