Commit d9a07577 authored by Jun Lei's avatar Jun Lei Committed by Alex Deucher

drm/amd/display: add oem i2c implemenation in dc

[why]
Need it for some OEM I2C devices in Nv10

[how]
Link up code to parse OEM table and expose DC interface
to access the pins
Signed-off-by: default avatarJun Lei <Jun.Lei@amd.com>
Reviewed-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ae8cf977
...@@ -294,11 +294,21 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, ...@@ -294,11 +294,21 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
struct atom_display_object_path_v2 *object; struct atom_display_object_path_v2 *object;
struct atom_common_record_header *header; struct atom_common_record_header *header;
struct atom_i2c_record *record; struct atom_i2c_record *record;
struct atom_i2c_record dummy_record = {0};
struct bios_parser *bp = BP_FROM_DCB(dcb); struct bios_parser *bp = BP_FROM_DCB(dcb);
if (!info) if (!info)
return BP_RESULT_BADINPUT; return BP_RESULT_BADINPUT;
if (id.type == OBJECT_TYPE_GENERIC) {
dummy_record.i2c_id = id.id;
if (get_gpio_i2c_info(bp, &dummy_record, info) == BP_RESULT_OK)
return BP_RESULT_OK;
else
return BP_RESULT_NORECORD;
}
object = get_bios_object(bp, id); object = get_bios_object(bp, id);
if (!object) if (!object)
...@@ -341,6 +351,7 @@ static enum bp_result get_gpio_i2c_info( ...@@ -341,6 +351,7 @@ static enum bp_result get_gpio_i2c_info(
struct atom_gpio_pin_lut_v2_1 *header; struct atom_gpio_pin_lut_v2_1 *header;
uint32_t count = 0; uint32_t count = 0;
unsigned int table_index = 0; unsigned int table_index = 0;
bool find_valid = false;
if (!info) if (!info)
return BP_RESULT_BADINPUT; return BP_RESULT_BADINPUT;
...@@ -368,33 +379,28 @@ static enum bp_result get_gpio_i2c_info( ...@@ -368,33 +379,28 @@ static enum bp_result get_gpio_i2c_info(
- sizeof(struct atom_common_table_header)) - sizeof(struct atom_common_table_header))
/ sizeof(struct atom_gpio_pin_assignment); / sizeof(struct atom_gpio_pin_assignment);
table_index = record->i2c_id & I2C_HW_LANE_MUX; for (table_index = 0; table_index < count; table_index++) {
if (((record->i2c_id & I2C_HW_CAP) == (
if (count < table_index) { header->gpio_pin[table_index].gpio_id &
bool find_valid = false; I2C_HW_CAP)) &&
((record->i2c_id & I2C_HW_ENGINE_ID_MASK) ==
for (table_index = 0; table_index < count; table_index++) { (header->gpio_pin[table_index].gpio_id &
if (((record->i2c_id & I2C_HW_CAP) == ( I2C_HW_ENGINE_ID_MASK)) &&
header->gpio_pin[table_index].gpio_id & ((record->i2c_id & I2C_HW_LANE_MUX) ==
I2C_HW_CAP)) && (header->gpio_pin[table_index].gpio_id &
((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == I2C_HW_LANE_MUX))) {
(header->gpio_pin[table_index].gpio_id & /* still valid */
I2C_HW_ENGINE_ID_MASK)) && find_valid = true;
((record->i2c_id & I2C_HW_LANE_MUX) == break;
(header->gpio_pin[table_index].gpio_id &
I2C_HW_LANE_MUX))) {
/* still valid */
find_valid = true;
break;
}
} }
/* If we don't find the entry that we are looking for then
* we will return BP_Result_BadBiosTable.
*/
if (find_valid == false)
return BP_RESULT_BADBIOSTABLE;
} }
/* If we don't find the entry that we are looking for then
* we will return BP_Result_BadBiosTable.
*/
if (find_valid == false)
return BP_RESULT_BADBIOSTABLE;
/* get the GPIO_I2C_INFO */ /* get the GPIO_I2C_INFO */
info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false; info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false;
info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX; info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
...@@ -1205,6 +1211,8 @@ static enum bp_result get_firmware_info_v3_1( ...@@ -1205,6 +1211,8 @@ static enum bp_result get_firmware_info_v3_1(
bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10; bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
} }
info->oem_i2c_present = false;
return BP_RESULT_OK; return BP_RESULT_OK;
} }
...@@ -1283,6 +1291,13 @@ static enum bp_result get_firmware_info_v3_2( ...@@ -1283,6 +1291,13 @@ static enum bp_result get_firmware_info_v3_2(
bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10; bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10;
} }
if (firmware_info->board_i2c_feature_id == 0x2) {
info->oem_i2c_present = true;
info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
} else {
info->oem_i2c_present = false;
}
return BP_RESULT_OK; return BP_RESULT_OK;
} }
......
...@@ -2502,6 +2502,17 @@ bool dc_submit_i2c( ...@@ -2502,6 +2502,17 @@ bool dc_submit_i2c(
cmd); cmd);
} }
bool dc_submit_i2c_oem(
struct dc *dc,
struct i2c_command *cmd)
{
struct ddc_service *ddc = dc->res_pool->oem_device;
return dce_i2c_submit_command(
dc->res_pool,
ddc->ddc_pin,
cmd);
}
static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink) static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink)
{ {
if (dc_link->sink_count >= MAX_SINKS_PER_LINK) { if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
......
...@@ -206,7 +206,10 @@ static void construct( ...@@ -206,7 +206,10 @@ static void construct(
ddc_service->ddc_pin = NULL; ddc_service->ddc_pin = NULL;
} else { } else {
hw_info.ddc_channel = i2c_info.i2c_line; hw_info.ddc_channel = i2c_info.i2c_line;
hw_info.hw_supported = i2c_info.i2c_hw_assist; if (ddc_service->link != NULL)
hw_info.hw_supported = i2c_info.i2c_hw_assist;
else
hw_info.hw_supported = false;
ddc_service->ddc_pin = dal_gpio_create_ddc( ddc_service->ddc_pin = dal_gpio_create_ddc(
gpio_service, gpio_service,
......
...@@ -305,6 +305,10 @@ bool dc_submit_i2c( ...@@ -305,6 +305,10 @@ bool dc_submit_i2c(
uint32_t link_index, uint32_t link_index,
struct i2c_command *cmd); struct i2c_command *cmd);
bool dc_submit_i2c_oem(
struct dc *dc,
struct i2c_command *cmd);
uint32_t dc_bandwidth_in_kbps_from_timing( uint32_t dc_bandwidth_in_kbps_from_timing(
const struct dc_crtc_timing *timing); const struct dc_crtc_timing *timing);
#endif /* DC_LINK_H_ */ #endif /* DC_LINK_H_ */
...@@ -31,7 +31,7 @@ bool dce_i2c_submit_command( ...@@ -31,7 +31,7 @@ bool dce_i2c_submit_command(
struct i2c_command *cmd) struct i2c_command *cmd)
{ {
struct dce_i2c_hw *dce_i2c_hw; struct dce_i2c_hw *dce_i2c_hw;
struct dce_i2c_sw *dce_i2c_sw; struct dce_i2c_sw dce_i2c_sw = {0};
if (!ddc) { if (!ddc) {
BREAK_TO_DEBUGGER(); BREAK_TO_DEBUGGER();
...@@ -43,18 +43,15 @@ bool dce_i2c_submit_command( ...@@ -43,18 +43,15 @@ bool dce_i2c_submit_command(
return false; return false;
} }
/* The software engine is only available on dce8 */ dce_i2c_hw = acquire_i2c_hw_engine(pool, ddc);
dce_i2c_sw = dce_i2c_acquire_i2c_sw_engine(pool, ddc);
if (!dce_i2c_sw) {
dce_i2c_hw = acquire_i2c_hw_engine(pool, ddc);
if (!dce_i2c_hw)
return false;
if (dce_i2c_hw)
return dce_i2c_submit_command_hw(pool, ddc, cmd, dce_i2c_hw); return dce_i2c_submit_command_hw(pool, ddc, cmd, dce_i2c_hw);
}
return dce_i2c_submit_command_sw(pool, ddc, cmd, dce_i2c_sw); dce_i2c_sw.ctx = ddc->ctx;
if (dce_i2c_engine_acquire_sw(&dce_i2c_sw, ddc)) {
return dce_i2c_submit_command_sw(pool, ddc, cmd, &dce_i2c_sw);
}
return false;
} }
...@@ -73,31 +73,6 @@ static void release_engine_dce_sw( ...@@ -73,31 +73,6 @@ static void release_engine_dce_sw(
dce_i2c_sw->ddc = NULL; dce_i2c_sw->ddc = NULL;
} }
static bool get_hw_supported_ddc_line(
struct ddc *ddc,
enum gpio_ddc_line *line)
{
enum gpio_ddc_line line_found;
*line = GPIO_DDC_LINE_UNKNOWN;
if (!ddc) {
BREAK_TO_DEBUGGER();
return false;
}
if (!ddc->hw_info.hw_supported)
return false;
line_found = dal_ddc_get_line(ddc);
if (line_found >= GPIO_DDC_LINE_COUNT)
return false;
*line = line_found;
return true;
}
static bool wait_for_scl_high_sw( static bool wait_for_scl_high_sw(
struct dc_context *ctx, struct dc_context *ctx,
struct ddc *ddc, struct ddc *ddc,
...@@ -524,21 +499,3 @@ bool dce_i2c_submit_command_sw( ...@@ -524,21 +499,3 @@ bool dce_i2c_submit_command_sw(
return result; return result;
} }
struct dce_i2c_sw *dce_i2c_acquire_i2c_sw_engine(
struct resource_pool *pool,
struct ddc *ddc)
{
enum gpio_ddc_line line;
struct dce_i2c_sw *engine = NULL;
if (get_hw_supported_ddc_line(ddc, &line))
engine = pool->sw_i2cs[line];
if (!engine)
return NULL;
if (!dce_i2c_engine_acquire_sw(engine, ddc))
return NULL;
return engine;
}
...@@ -49,9 +49,9 @@ bool dce_i2c_submit_command_sw( ...@@ -49,9 +49,9 @@ bool dce_i2c_submit_command_sw(
struct i2c_command *cmd, struct i2c_command *cmd,
struct dce_i2c_sw *dce_i2c_sw); struct dce_i2c_sw *dce_i2c_sw);
struct dce_i2c_sw *dce_i2c_acquire_i2c_sw_engine( bool dce_i2c_engine_acquire_sw(
struct resource_pool *pool, struct dce_i2c_sw *dce_i2c_sw,
struct ddc *ddc); struct ddc *ddc_handle);
#endif #endif
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#include "dml/display_mode_vba.h" #include "dml/display_mode_vba.h"
#include "dcn20_dccg.h" #include "dcn20_dccg.h"
#include "dcn20_vmid.h" #include "dcn20_vmid.h"
#include "dc_link_ddc.h"
#include "navi10_ip_offset.h" #include "navi10_ip_offset.h"
...@@ -1346,6 +1347,8 @@ static void destruct(struct dcn20_resource_pool *pool) ...@@ -1346,6 +1347,8 @@ static void destruct(struct dcn20_resource_pool *pool)
if (pool->base.pp_smu != NULL) if (pool->base.pp_smu != NULL)
dcn20_pp_smu_destroy(&pool->base.pp_smu); dcn20_pp_smu_destroy(&pool->base.pp_smu);
if (pool->base.oem_device != NULL)
dal_ddc_service_destroy(&pool->base.oem_device);
} }
struct hubp *dcn20_hubp_create( struct hubp *dcn20_hubp_create(
...@@ -3391,6 +3394,7 @@ static bool construct( ...@@ -3391,6 +3394,7 @@ static bool construct(
int i; int i;
struct dc_context *ctx = dc->ctx; struct dc_context *ctx = dc->ctx;
struct irq_service_init_data init_data; struct irq_service_init_data init_data;
struct ddc_service_init_data ddc_init_data;
struct _vcs_dpi_soc_bounding_box_st *loaded_bb = struct _vcs_dpi_soc_bounding_box_st *loaded_bb =
get_asic_rev_soc_bb(ctx->asic_id.hw_internal_rev); get_asic_rev_soc_bb(ctx->asic_id.hw_internal_rev);
struct _vcs_dpi_ip_params_st *loaded_ip = struct _vcs_dpi_ip_params_st *loaded_ip =
...@@ -3686,6 +3690,17 @@ static bool construct( ...@@ -3686,6 +3690,17 @@ static bool construct(
dc->cap_funcs = cap_funcs; dc->cap_funcs = cap_funcs;
if (dc->ctx->dc_bios->fw_info.oem_i2c_present) {
ddc_init_data.ctx = dc->ctx;
ddc_init_data.link = NULL;
ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id;
ddc_init_data.id.enum_id = 0;
ddc_init_data.id.type = OBJECT_TYPE_GENERIC;
pool->base.oem_device = dal_ddc_service_create(&ddc_init_data);
} else {
pool->base.oem_device = NULL;
}
return true; return true;
create_fail: create_fail:
......
...@@ -110,6 +110,12 @@ static const struct ddc_registers ddc_data_regs_dcn[] = { ...@@ -110,6 +110,12 @@ static const struct ddc_registers ddc_data_regs_dcn[] = {
ddc_data_regs_dcn2(4), ddc_data_regs_dcn2(4),
ddc_data_regs_dcn2(5), ddc_data_regs_dcn2(5),
ddc_data_regs_dcn2(6), ddc_data_regs_dcn2(6),
{
DDC_GPIO_VGA_REG_LIST(DATA),
.ddc_setup = 0,
.phy_aux_cntl = 0,
.dc_gpio_aux_ctrl_5 = 0
}
}; };
static const struct ddc_registers ddc_clk_regs_dcn[] = { static const struct ddc_registers ddc_clk_regs_dcn[] = {
...@@ -119,6 +125,12 @@ static const struct ddc_registers ddc_clk_regs_dcn[] = { ...@@ -119,6 +125,12 @@ static const struct ddc_registers ddc_clk_regs_dcn[] = {
ddc_clk_regs_dcn2(4), ddc_clk_regs_dcn2(4),
ddc_clk_regs_dcn2(5), ddc_clk_regs_dcn2(5),
ddc_clk_regs_dcn2(6), ddc_clk_regs_dcn2(6),
{
DDC_GPIO_VGA_REG_LIST(CLK),
.ddc_setup = 0,
.phy_aux_cntl = 0,
.dc_gpio_aux_ctrl_5 = 0
}
}; };
static const struct ddc_sh_mask ddc_shift[] = { static const struct ddc_sh_mask ddc_shift[] = {
......
...@@ -229,6 +229,8 @@ struct resource_pool { ...@@ -229,6 +229,8 @@ struct resource_pool {
const struct resource_funcs *funcs; const struct resource_funcs *funcs;
const struct resource_caps *res_cap; const struct resource_caps *res_cap;
struct ddc_service *oem_device;
}; };
struct dcn_fe_bandwidth { struct dcn_fe_bandwidth {
......
...@@ -178,7 +178,8 @@ struct dc_firmware_info { ...@@ -178,7 +178,8 @@ struct dc_firmware_info {
uint32_t default_engine_clk; /* in KHz */ uint32_t default_engine_clk; /* in KHz */
uint32_t dp_phy_ref_clk; /* in KHz - DCE12 only */ uint32_t dp_phy_ref_clk; /* in KHz - DCE12 only */
uint32_t i2c_engine_ref_clk; /* in KHz - DCE12 only */ uint32_t i2c_engine_ref_clk; /* in KHz - DCE12 only */
bool oem_i2c_present;
uint8_t oem_i2c_obj_id;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment