Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Jun Lei and committed by
Alex Deucher
d9a07577 ae8cf977

+100 -83
+39 -24
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
··· 294 294 struct atom_display_object_path_v2 *object; 295 295 struct atom_common_record_header *header; 296 296 struct atom_i2c_record *record; 297 + struct atom_i2c_record dummy_record = {0}; 297 298 struct bios_parser *bp = BP_FROM_DCB(dcb); 298 299 299 300 if (!info) 300 301 return BP_RESULT_BADINPUT; 302 + 303 + if (id.type == OBJECT_TYPE_GENERIC) { 304 + dummy_record.i2c_id = id.id; 305 + 306 + if (get_gpio_i2c_info(bp, &dummy_record, info) == BP_RESULT_OK) 307 + return BP_RESULT_OK; 308 + else 309 + return BP_RESULT_NORECORD; 310 + } 301 311 302 312 object = get_bios_object(bp, id); 303 313 ··· 351 341 struct atom_gpio_pin_lut_v2_1 *header; 352 342 uint32_t count = 0; 353 343 unsigned int table_index = 0; 344 + bool find_valid = false; 354 345 355 346 if (!info) 356 347 return BP_RESULT_BADINPUT; ··· 379 368 - sizeof(struct atom_common_table_header)) 380 369 / sizeof(struct atom_gpio_pin_assignment); 381 370 382 - table_index = record->i2c_id & I2C_HW_LANE_MUX; 383 - 384 - if (count < table_index) { 385 - bool find_valid = false; 386 - 387 - for (table_index = 0; table_index < count; table_index++) { 388 - if (((record->i2c_id & I2C_HW_CAP) == ( 389 - header->gpio_pin[table_index].gpio_id & 390 - I2C_HW_CAP)) && 391 - ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == 392 - (header->gpio_pin[table_index].gpio_id & 393 - I2C_HW_ENGINE_ID_MASK)) && 394 - ((record->i2c_id & I2C_HW_LANE_MUX) == 395 - (header->gpio_pin[table_index].gpio_id & 396 - I2C_HW_LANE_MUX))) { 397 - /* still valid */ 398 - find_valid = true; 399 - break; 400 - } 371 + for (table_index = 0; table_index < count; table_index++) { 372 + if (((record->i2c_id & I2C_HW_CAP) == ( 373 + header->gpio_pin[table_index].gpio_id & 374 + I2C_HW_CAP)) && 375 + ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == 376 + (header->gpio_pin[table_index].gpio_id & 377 + I2C_HW_ENGINE_ID_MASK)) && 378 + ((record->i2c_id & I2C_HW_LANE_MUX) == 379 + (header->gpio_pin[table_index].gpio_id & 380 + I2C_HW_LANE_MUX))) { 381 + /* still valid */ 382 + find_valid = true; 383 + break; 401 384 } 402 - /* If we don't find the entry that we are looking for then 403 - * we will return BP_Result_BadBiosTable. 404 - */ 405 - if (find_valid == false) 406 - return BP_RESULT_BADBIOSTABLE; 407 385 } 386 + 387 + /* If we don't find the entry that we are looking for then 388 + * we will return BP_Result_BadBiosTable. 389 + */ 390 + if (find_valid == false) 391 + return BP_RESULT_BADBIOSTABLE; 408 392 409 393 /* get the GPIO_I2C_INFO */ 410 394 info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false; ··· 1211 1205 bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10; 1212 1206 } 1213 1207 1208 + info->oem_i2c_present = false; 1209 + 1214 1210 return BP_RESULT_OK; 1215 1211 } 1216 1212 ··· 1289 1281 else if (revision.minor == 3) 1290 1282 info->smu_gpu_pll_output_freq = 1291 1283 bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10; 1284 + } 1285 + 1286 + if (firmware_info->board_i2c_feature_id == 0x2) { 1287 + info->oem_i2c_present = true; 1288 + info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id; 1289 + } else { 1290 + info->oem_i2c_present = false; 1292 1291 } 1293 1292 1294 1293 return BP_RESULT_OK;
+11
drivers/gpu/drm/amd/display/dc/core/dc.c
··· 2502 2502 cmd); 2503 2503 } 2504 2504 2505 + bool dc_submit_i2c_oem( 2506 + struct dc *dc, 2507 + struct i2c_command *cmd) 2508 + { 2509 + struct ddc_service *ddc = dc->res_pool->oem_device; 2510 + return dce_i2c_submit_command( 2511 + dc->res_pool, 2512 + ddc->ddc_pin, 2513 + cmd); 2514 + } 2515 + 2505 2516 static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink) 2506 2517 { 2507 2518 if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
+4
drivers/gpu/drm/amd/display/dc/dc_link.h
··· 305 305 uint32_t link_index, 306 306 struct i2c_command *cmd); 307 307 308 + bool dc_submit_i2c_oem( 309 + struct dc *dc, 310 + struct i2c_command *cmd); 311 + 308 312 uint32_t dc_bandwidth_in_kbps_from_timing( 309 313 const struct dc_crtc_timing *timing); 310 314 #endif /* DC_LINK_H_ */
+8 -11
drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c
··· 31 31 struct i2c_command *cmd) 32 32 { 33 33 struct dce_i2c_hw *dce_i2c_hw; 34 - struct dce_i2c_sw *dce_i2c_sw; 34 + struct dce_i2c_sw dce_i2c_sw = {0}; 35 35 36 36 if (!ddc) { 37 37 BREAK_TO_DEBUGGER(); ··· 43 43 return false; 44 44 } 45 45 46 - /* The software engine is only available on dce8 */ 47 - dce_i2c_sw = dce_i2c_acquire_i2c_sw_engine(pool, ddc); 46 + dce_i2c_hw = acquire_i2c_hw_engine(pool, ddc); 48 47 49 - if (!dce_i2c_sw) { 50 - dce_i2c_hw = acquire_i2c_hw_engine(pool, ddc); 51 - 52 - if (!dce_i2c_hw) 53 - return false; 54 - 48 + if (dce_i2c_hw) 55 49 return dce_i2c_submit_command_hw(pool, ddc, cmd, dce_i2c_hw); 50 + 51 + dce_i2c_sw.ctx = ddc->ctx; 52 + if (dce_i2c_engine_acquire_sw(&dce_i2c_sw, ddc)) { 53 + return dce_i2c_submit_command_sw(pool, ddc, cmd, &dce_i2c_sw); 56 54 } 57 55 58 - return dce_i2c_submit_command_sw(pool, ddc, cmd, dce_i2c_sw); 59 - 56 + return false; 60 57 }
-43
drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c
··· 73 73 dce_i2c_sw->ddc = NULL; 74 74 } 75 75 76 - static bool get_hw_supported_ddc_line( 77 - struct ddc *ddc, 78 - enum gpio_ddc_line *line) 79 - { 80 - enum gpio_ddc_line line_found; 81 - 82 - *line = GPIO_DDC_LINE_UNKNOWN; 83 - 84 - if (!ddc) { 85 - BREAK_TO_DEBUGGER(); 86 - return false; 87 - } 88 - 89 - if (!ddc->hw_info.hw_supported) 90 - return false; 91 - 92 - line_found = dal_ddc_get_line(ddc); 93 - 94 - if (line_found >= GPIO_DDC_LINE_COUNT) 95 - return false; 96 - 97 - *line = line_found; 98 - 99 - return true; 100 - } 101 76 static bool wait_for_scl_high_sw( 102 77 struct dc_context *ctx, 103 78 struct ddc *ddc, ··· 498 523 release_engine_dce_sw(pool, dce_i2c_sw); 499 524 500 525 return result; 501 - } 502 - struct dce_i2c_sw *dce_i2c_acquire_i2c_sw_engine( 503 - struct resource_pool *pool, 504 - struct ddc *ddc) 505 - { 506 - enum gpio_ddc_line line; 507 - struct dce_i2c_sw *engine = NULL; 508 - 509 - if (get_hw_supported_ddc_line(ddc, &line)) 510 - engine = pool->sw_i2cs[line]; 511 - 512 - if (!engine) 513 - return NULL; 514 - 515 - if (!dce_i2c_engine_acquire_sw(engine, ddc)) 516 - return NULL; 517 - 518 - return engine; 519 526 }
+3 -3
drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.h
··· 49 49 struct i2c_command *cmd, 50 50 struct dce_i2c_sw *dce_i2c_sw); 51 51 52 - struct dce_i2c_sw *dce_i2c_acquire_i2c_sw_engine( 53 - struct resource_pool *pool, 54 - struct ddc *ddc); 52 + bool dce_i2c_engine_acquire_sw( 53 + struct dce_i2c_sw *dce_i2c_sw, 54 + struct ddc *ddc_handle); 55 55 56 56 #endif 57 57
+15
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
··· 59 59 #include "dml/display_mode_vba.h" 60 60 #include "dcn20_dccg.h" 61 61 #include "dcn20_vmid.h" 62 + #include "dc_link_ddc.h" 62 63 63 64 #include "navi10_ip_offset.h" 64 65 ··· 1347 1346 if (pool->base.pp_smu != NULL) 1348 1347 dcn20_pp_smu_destroy(&pool->base.pp_smu); 1349 1348 1349 + if (pool->base.oem_device != NULL) 1350 + dal_ddc_service_destroy(&pool->base.oem_device); 1350 1351 } 1351 1352 1352 1353 struct hubp *dcn20_hubp_create( ··· 3394 3391 int i; 3395 3392 struct dc_context *ctx = dc->ctx; 3396 3393 struct irq_service_init_data init_data; 3394 + struct ddc_service_init_data ddc_init_data; 3397 3395 struct _vcs_dpi_soc_bounding_box_st *loaded_bb = 3398 3396 get_asic_rev_soc_bb(ctx->asic_id.hw_internal_rev); 3399 3397 struct _vcs_dpi_ip_params_st *loaded_ip = ··· 3689 3685 dc->caps.planes[i] = plane_cap; 3690 3686 3691 3687 dc->cap_funcs = cap_funcs; 3688 + 3689 + if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { 3690 + ddc_init_data.ctx = dc->ctx; 3691 + ddc_init_data.link = NULL; 3692 + ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; 3693 + ddc_init_data.id.enum_id = 0; 3694 + ddc_init_data.id.type = OBJECT_TYPE_GENERIC; 3695 + pool->base.oem_device = dal_ddc_service_create(&ddc_init_data); 3696 + } else { 3697 + pool->base.oem_device = NULL; 3698 + } 3692 3699 3693 3700 return true; 3694 3701
+12
drivers/gpu/drm/amd/display/dc/gpio/dcn20/hw_factory_dcn20.c
··· 110 110 ddc_data_regs_dcn2(4), 111 111 ddc_data_regs_dcn2(5), 112 112 ddc_data_regs_dcn2(6), 113 + { 114 + DDC_GPIO_VGA_REG_LIST(DATA), 115 + .ddc_setup = 0, 116 + .phy_aux_cntl = 0, 117 + .dc_gpio_aux_ctrl_5 = 0 118 + } 113 119 }; 114 120 115 121 static const struct ddc_registers ddc_clk_regs_dcn[] = { ··· 125 119 ddc_clk_regs_dcn2(4), 126 120 ddc_clk_regs_dcn2(5), 127 121 ddc_clk_regs_dcn2(6), 122 + { 123 + DDC_GPIO_VGA_REG_LIST(CLK), 124 + .ddc_setup = 0, 125 + .phy_aux_cntl = 0, 126 + .dc_gpio_aux_ctrl_5 = 0 127 + } 128 128 }; 129 129 130 130 static const struct ddc_sh_mask ddc_shift[] = {
+2
drivers/gpu/drm/amd/display/dc/inc/core_types.h
··· 229 229 230 230 const struct resource_funcs *funcs; 231 231 const struct resource_caps *res_cap; 232 + 233 + struct ddc_service *oem_device; 232 234 }; 233 235 234 236 struct dcn_fe_bandwidth {
+2 -1
drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h
··· 178 178 uint32_t default_engine_clk; /* in KHz */ 179 179 uint32_t dp_phy_ref_clk; /* in KHz - DCE12 only */ 180 180 uint32_t i2c_engine_ref_clk; /* in KHz - DCE12 only */ 181 - 181 + bool oem_i2c_present; 182 + uint8_t oem_i2c_obj_id; 182 183 183 184 }; 184 185