Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
drm/amd/display: Enable copying of bounding box data from VBIOS DMUB
Browse files Browse the repository at this point in the history
Allocate some memory, send the address in chunks to dmub, and finally
ask it to copy the bounding box data into the newly allocated memory.

Signed-off-by: Aurabindo Pillai <[email protected]>
Acked-by: Harry Wentland <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
  • Loading branch information
Aurabindo Pillai authored and alexdeucher committed May 29, 2024
1 parent c75bfd1 commit 234e945
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 24 deletions.
121 changes: 121 additions & 0 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1627,6 +1627,117 @@ static void retrieve_dmi_info(struct amdgpu_display_manager *dm)
}
}

void*
dm_allocate_gpu_mem(
struct amdgpu_device *adev,
enum dc_gpu_mem_alloc_type type,
size_t size,
long long *addr)
{
struct dal_allocation *da;
u32 domain = (type == DC_MEM_ALLOC_TYPE_GART) ?
AMDGPU_GEM_DOMAIN_GTT : AMDGPU_GEM_DOMAIN_VRAM;
int ret;

da = kzalloc(sizeof(struct dal_allocation), GFP_KERNEL);
if (!da)
return NULL;

ret = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
domain, &da->bo,
&da->gpu_addr, &da->cpu_ptr);

*addr = da->gpu_addr;

if (ret) {
kfree(da);
return NULL;
}

/* add da to list in dm */
list_add(&da->list, &adev->dm.da_list);

return da->cpu_ptr;
}

static enum dmub_status
dm_dmub_send_vbios_gpint_command(struct amdgpu_device *adev,
enum dmub_gpint_command command_code,
uint16_t param,
uint32_t timeout_us)
{
union dmub_gpint_data_register reg, test;
uint32_t i;

/* Assume that VBIOS DMUB is ready to take commands */

reg.bits.status = 1;
reg.bits.command_code = command_code;
reg.bits.param = param;

cgs_write_register(adev->dm.cgs_device, 0x34c0 + 0x01f8, reg.all);

for (i = 0; i < timeout_us; ++i) {
udelay(1);

/* Check if our GPINT got acked */
reg.bits.status = 0;
test = (union dmub_gpint_data_register)
cgs_read_register(adev->dm.cgs_device, 0x34c0 + 0x01f8);

if (test.all == reg.all)
return DMUB_STATUS_OK;
}

return DMUB_STATUS_TIMEOUT;
}

static struct dml2_soc_bb *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev)
{
struct dml2_soc_bb *bb;
long long addr;
int i = 0;
uint16_t chunk;
enum dmub_gpint_command send_addrs[] = {
DMUB_GPINT__SET_BB_ADDR_WORD0,
DMUB_GPINT__SET_BB_ADDR_WORD1,
DMUB_GPINT__SET_BB_ADDR_WORD2,
DMUB_GPINT__SET_BB_ADDR_WORD3,
};
enum dmub_status ret;

switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(4, 0, 1):
break;
default:
return NULL;
}

bb = dm_allocate_gpu_mem(adev,
DC_MEM_ALLOC_TYPE_GART,
sizeof(struct dml2_soc_bb),
&addr);
if (!bb)
return NULL;

for (i = 0; i < 4; i++) {
/* Extract 16-bit chunk */
chunk = ((uint64_t) addr >> (i * 16)) & 0xFFFF;
/* Send the chunk */
ret = dm_dmub_send_vbios_gpint_command(adev, send_addrs[i], chunk, 30000);
if (ret != DMUB_STATUS_OK)
/* No need to free bb here since it shall be done unconditionally <elsewhere> */
return NULL;
}

/* Now ask DMUB to copy the bb */
ret = dm_dmub_send_vbios_gpint_command(adev, DMUB_GPINT__BB_COPY, 1, 200000);
if (ret != DMUB_STATUS_OK)
return NULL;

return bb;
}

static int amdgpu_dm_init(struct amdgpu_device *adev)
{
struct dc_init_data init_data;
Expand Down Expand Up @@ -1748,6 +1859,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)

retrieve_dmi_info(&adev->dm);

if (adev->dm.bb_from_dmub)
init_data.bb_from_dmub = adev->dm.bb_from_dmub;
else
init_data.bb_from_dmub = NULL;

/* Display Core create. */
adev->dm.dc = dc_create(&init_data);

Expand Down Expand Up @@ -2305,6 +2421,8 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
return -EINVAL;
}

adev->dm.bb_from_dmub = dm_dmub_get_vbios_bounding_box(adev);

return 0;
}

Expand Down Expand Up @@ -2334,6 +2452,9 @@ static int dm_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;

kfree(adev->dm.bb_from_dmub);
adev->dm.bb_from_dmub = NULL;

kfree(adev->dm.dmub_fb_info);
adev->dm.dmub_fb_info = NULL;

Expand Down
10 changes: 10 additions & 0 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,11 @@ struct amdgpu_display_manager {
* Guards access to DPIA AUX
*/
struct mutex dpia_aux_lock;

/*
* Bounding box data read from dmub during early initialization for DCN4+
*/
struct dml2_soc_bb *bb_from_dmub;
};

enum dsc_clock_force_state {
Expand Down Expand Up @@ -964,4 +969,9 @@ amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,

int convert_dc_color_depth_into_bpc(enum dc_color_depth display_color_depth);
struct idle_workqueue *idle_create_workqueue(struct amdgpu_device *adev);

void *dm_allocate_gpu_mem(struct amdgpu_device *adev,
enum dc_gpu_mem_alloc_type type,
size_t size,
long long *addr);
#endif /* __AMDGPU_DM_H__ */
24 changes: 1 addition & 23 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,30 +1045,8 @@ void *dm_helpers_allocate_gpu_mem(
long long *addr)
{
struct amdgpu_device *adev = ctx->driver_context;
struct dal_allocation *da;
u32 domain = (type == DC_MEM_ALLOC_TYPE_GART) ?
AMDGPU_GEM_DOMAIN_GTT : AMDGPU_GEM_DOMAIN_VRAM;
int ret;

da = kzalloc(sizeof(struct dal_allocation), GFP_KERNEL);
if (!da)
return NULL;

ret = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
domain, &da->bo,
&da->gpu_addr, &da->cpu_ptr);

*addr = da->gpu_addr;

if (ret) {
kfree(da);
return NULL;
}

/* add da to list in dm */
list_add(&da->list, &adev->dm.da_list);

return da->cpu_ptr;
return dm_allocate_gpu_mem(adev, type, size, addr);
}

void dm_helpers_free_gpu_mem(
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/amd/display/dc/core/dc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,11 @@ static bool dc_construct(struct dc *dc,

dc->dcn_ip = dcn_ip;

if (init_params->bb_from_dmub)
dc->dml2_options.bb_from_dmub = init_params->bb_from_dmub;
else
dc->dml2_options.bb_from_dmub = NULL;

if (!dc_construct_ctx(dc, init_params)) {
dm_error("%s: failed to create ctx\n", __func__);
goto fail;
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/amd/display/dc/dc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,8 @@ struct dchub_init_data {
bool dchub_info_valid;
};

struct dml2_soc_bb;

struct dc_init_data {
struct hw_asic_id asic_id;
void *driver; /* ctx */
Expand Down Expand Up @@ -1099,6 +1101,7 @@ struct dc_init_data {
uint32_t *dcn_reg_offsets;
uint32_t *nbio_reg_offsets;
uint32_t *clk_reg_offsets;
struct dml2_soc_bb *bb_from_dmub;
};

struct dc_callback_init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ static void dml21_init_socbb_params(struct dml2_initialize_instance_in_out *dml_
break;
case DCN_VERSION_4_01:
default:
soc_bb = &dml2_socbb_dcn401;
if (config->bb_from_dmub)
soc_bb = config->bb_from_dmub;
else
soc_bb = &dml2_socbb_dcn401;

qos_params = &dml_dcn401_soc_qos_params;
}

Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ struct dml2_configuration_options {

bool use_clock_dc_limits;
bool gpuvm_enable;
struct dml2_soc_bb *bb_from_dmub;
};

/*
Expand Down

0 comments on commit 234e945

Please sign in to comment.