[PATCH v2] drm/amdgpu: Read vram width from integrated system info table
Harry Wentland
harry.wentland at amd.com
Mon Apr 3 15:29:14 UTC 2017
On 2017-04-03 11:20 AM, Kai Wasserbäch wrote:
> Dear Harry,
> Harry Wentland wrote on 03.04.2017 17:01:
>> On KB, KV, CZ we should read the vram width from integrated system
>> table, if we can. The NOOFCHAN in MC_SHARED_CHMAP is not accurate.
>>
>> With this change we can enable two 4k displays on CZ again. This use
>> case was broken sometime in January when we started looking at
>> vram_width for bandwidth calculations instead of hardcoding this value.
>>
>> v2:
>> Return 0 if integrated system info table is not available.
>>
>> Tested-by: Roman Li <roman.li at amd.com>
>> Signed-off-by: Harry Wentland <harry.wentland at amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 29 ++++++++++
>> drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | 2 +
>> drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 87 +++++++++++++++-------------
>> drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 87 +++++++++++++++-------------
>> 4 files changed, 123 insertions(+), 82 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
>> index f52b1bf3d3d9..ad4329922f79 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
>> @@ -754,6 +754,35 @@ union igp_info {
>> struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_9 info_9;
>> };
>>
>> +/*
>> + * Return vram width from integrated system info table, if available,
>> + * or 0 if not.
>> + */
>> +int amdgpu_atombios_get_vram_width(struct amdgpu_device *adev)
>> +{
>> + struct amdgpu_mode_info *mode_info = &adev->mode_info;
>> + int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
>> + u16 data_offset, size;
>> + union igp_info *igp_info;
>> + u8 frev, crev;
>> +
>> + /* get any igp specific overrides */
>> + if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size,
>> + &frev, &crev, &data_offset)) {
>> + igp_info = (union igp_info *)
>> + (mode_info->atom_context->bios + data_offset);
>> + switch (crev) {
>> + case 8:
>> + case 9:
>> + return igp_info->info_8.ucUMAChannelNumber * 64;
>> + default:
>> + return 0;
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> static void amdgpu_atombios_get_igp_ss_overrides(struct amdgpu_device *adev,
>> struct amdgpu_atom_ss *ss,
>> int id)
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
>> index 4e0f488487f3..38d0fe32e5cd 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
>> @@ -148,6 +148,8 @@ int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev);
>>
>> int amdgpu_atombios_get_gfx_info(struct amdgpu_device *adev);
>>
>> +int amdgpu_atombios_get_vram_width(struct amdgpu_device *adev);
>> +
>> bool amdgpu_atombios_get_asic_ss_info(struct amdgpu_device *adev,
>> struct amdgpu_atom_ss *ss,
>> int id, u32 clock);
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
>> index 0c0a6015cca5..78643a1baa5c 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
>> @@ -37,6 +37,8 @@
>> #include "oss/oss_2_0_d.h"
>> #include "oss/oss_2_0_sh_mask.h"
>>
>> +#include "amdgpu_atombios.h"
>> +
>> static void gmc_v7_0_set_gart_funcs(struct amdgpu_device *adev);
>> static void gmc_v7_0_set_irq_funcs(struct amdgpu_device *adev);
>> static int gmc_v7_0_wait_for_idle(void *handle);
>> @@ -325,48 +327,51 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
>> */
>> static int gmc_v7_0_mc_init(struct amdgpu_device *adev)
>> {
>> - u32 tmp;
>> - int chansize, numchan;
>> -
>> - /* Get VRAM informations */
>> - tmp = RREG32(mmMC_ARB_RAMCFG);
>> - if (REG_GET_FIELD(tmp, MC_ARB_RAMCFG, CHANSIZE)) {
>> - chansize = 64;
>> - } else {
>> - chansize = 32;
>> - }
>> - tmp = RREG32(mmMC_SHARED_CHMAP);
>> - switch (REG_GET_FIELD(tmp, MC_SHARED_CHMAP, NOOFCHAN)) {
>> - case 0:
>> - default:
>> - numchan = 1;
>> - break;
>> - case 1:
>> - numchan = 2;
>> - break;
>> - case 2:
>> - numchan = 4;
>> - break;
>> - case 3:
>> - numchan = 8;
>> - break;
>> - case 4:
>> - numchan = 3;
>> - break;
>> - case 5:
>> - numchan = 6;
>> - break;
>> - case 6:
>> - numchan = 10;
>> - break;
>> - case 7:
>> - numchan = 12;
>> - break;
>> - case 8:
>> - numchan = 16;
>> - break;
>> + adev->mc.vram_width = amdgpu_atombios_get_vram_width(adev);
>> + if (!adev->mc.vram_width) {
>> + u32 tmp;
>> + int chansize, numchan;
>> +
>> + /* Get VRAM informations */
>> + tmp = RREG32(mmMC_ARB_RAMCFG);
>> + if (REG_GET_FIELD(tmp, MC_ARB_RAMCFG, CHANSIZE)) {
>> + chansize = 64;
>> + } else {
>> + chansize = 32;
>> + }
>> + tmp = RREG32(mmMC_SHARED_CHMAP);
>> + switch (REG_GET_FIELD(tmp, MC_SHARED_CHMAP, NOOFCHAN)) {
>> + case 0:
>> + default:
>> + numchan = 1;
>> + break;
>> + case 1:
>> + numchan = 2;
>> + break;
>> + case 2:
>> + numchan = 4;
>> + break;
>> + case 3:
>> + numchan = 8;
>> + break;
>> + case 4:
>> + numchan = 3;
>> + break;
>> + case 5:
>> + numchan = 6;
>> + break;
>> + case 6:
>> + numchan = 10;
>> + break;
>> + case 7:
>> + numchan = 12;
>> + break;
>> + case 8:
>> + numchan = 16;
>> + break;
>> + }
>> + adev->mc.vram_width = numchan * chansize;
>> }
>> - adev->mc.vram_width = numchan * chansize;
>> /* Could aper size report 0 ? */
>> adev->mc.aper_base = pci_resource_start(adev->pdev, 0);
>> adev->mc.aper_size = pci_resource_len(adev->pdev, 0);
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
>> index d19d1c5e2847..42b2f357a799 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
>> @@ -38,6 +38,8 @@
>> #include "vid.h"
>> #include "vi.h"
>>
>> +#include "amdgpu_atombios.h"
>> +
>>
>> static void gmc_v8_0_set_gart_funcs(struct amdgpu_device *adev);
>> static void gmc_v8_0_set_irq_funcs(struct amdgpu_device *adev);
>> @@ -487,48 +489,51 @@ static void gmc_v8_0_mc_program(struct amdgpu_device *adev)
>> */
>> static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
>> {
>> - u32 tmp;
>> - int chansize, numchan;
>> -
>> - /* Get VRAM informations */
>> - tmp = RREG32(mmMC_ARB_RAMCFG);
>> - if (REG_GET_FIELD(tmp, MC_ARB_RAMCFG, CHANSIZE)) {
>> - chansize = 64;
>> - } else {
>> - chansize = 32;
>> - }
>> - tmp = RREG32(mmMC_SHARED_CHMAP);
>> - switch (REG_GET_FIELD(tmp, MC_SHARED_CHMAP, NOOFCHAN)) {
>> - case 0:
>> - default:
>> - numchan = 1;
>> - break;
>> - case 1:
>> - numchan = 2;
>> - break;
>> - case 2:
>> - numchan = 4;
>> - break;
>> - case 3:
>> - numchan = 8;
>> - break;
>> - case 4:
>> - numchan = 3;
>> - break;
>> - case 5:
>> - numchan = 6;
>> - break;
>> - case 6:
>> - numchan = 10;
>> - break;
>> - case 7:
>> - numchan = 12;
>> - break;
>> - case 8:
>> - numchan = 16;
>> - break;
>> + adev->mc.vram_width = amdgpu_atombios_get_vram_width(adev);
>> + if (!adev->mc.vram_width) {
>> + u32 tmp;
>> + int chansize, numchan;
>> +
>> + /* Get VRAM informations */
>> + tmp = RREG32(mmMC_ARB_RAMCFG);
>> + if (REG_GET_FIELD(tmp, MC_ARB_RAMCFG, CHANSIZE)) {
>> + chansize = 64;
>> + } else {
>> + chansize = 32;
>> + }
>> + tmp = RREG32(mmMC_SHARED_CHMAP);
>> + switch (REG_GET_FIELD(tmp, MC_SHARED_CHMAP, NOOFCHAN)) {
>> + case 0:
>> + default:
>> + numchan = 1;
>> + break;
>> + case 1:
>> + numchan = 2;
>> + break;
>> + case 2:
>> + numchan = 4;
>> + break;
>> + case 3:
>> + numchan = 8;
>> + break;
>> + case 4:
>> + numchan = 3;
>> + break;
>> + case 5:
>> + numchan = 6;
>> + break;
>> + case 6:
>> + numchan = 10;
>> + break;
>> + case 7:
>> + numchan = 12;
>> + break;
>> + case 8:
>> + numchan = 16;
>> + break;
>> + }
>> + adev->mc.vram_width = numchan * chansize;
>
> I might miss something subtle here, but after reading this a couple of times,
> I've convinced myself this is exactly the same switch statement as in
> gmc_v7_0_mc_init() above, right? If so: why not move that part to common code as
> well?
>
My patch isn't adding (or removing) any duplication, just wrapping the
whole thing in a call to atombios.
I'd rather not change the design of the GMC component with this patch.
It could very well have been a design decisions to have this
duplication, in part because of the register access. mmMC_ARB_RAMCFG
could be defined differently for v7 and v8. The different defines are
pulled in through different register header includes, gmc_7_1_d.h vs
gmc/gmc_8_1_d.h.
Harry
> Cheers,
> Kai
>
>
>> }
>> - adev->mc.vram_width = numchan * chansize;
>> /* Could aper size report 0 ? */
>> adev->mc.aper_base = pci_resource_start(adev->pdev, 0);
>> adev->mc.aper_size = pci_resource_len(adev->pdev, 0);
>
>
More information about the amd-gfx
mailing list