/* Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved. */ #include "dmub_abm.h" #include "dmub_abm_cacp.h" #include "dce_abm.h" #include "dc.h" #include "dc_dmub_srv.h" #include "dmub/dmub_srv.h" #include "core_types.h" #define CACP_LEVEL_NUM 4 void dmub_cacp_init(struct abm *abm, const char *src, unsigned int bytes, unsigned int panel_inst) { union dmub_rb_cmd cmd; struct dc_context *dc = abm->ctx; uint8_t panel_mask = 0x01 << panel_inst; struct dc_link *edp_links[MAX_NUM_EDP]; unsigned int i, edp_num; // TODO: Optimize by only reading back final 4 bytes dmub_srv_flush_buffer_mem(dc->dmub_srv->dmub, &dc->dmub_srv->dmub->scratch_mem_fb); // Copy iramtable into cw7 memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)src, bytes); memset(&cmd, 0, sizeof(cmd)); // Fw will copy from cw7 to fw_state cmd.cacp_init_config.header.type = DMUB_CMD__CACP; cmd.cacp_init_config.header.sub_type = DMUB_CMD__CACP_INIT_CONFIG; cmd.cacp_init_config.cacp_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr; cmd.cacp_init_config.cacp_init_config_data.bytes = (uint16_t)bytes; cmd.cacp_init_config.cacp_init_config_data.panel_mask = panel_mask; cmd.cacp_init_config.cacp_init_config_data.visual_confirm = (dc->dc->debug.visual_confirm == VISUAL_CONFIRM_ABM) ? true : false; cmd.cacp_init_config.header.payload_bytes = sizeof(struct dmub_cmd_cacp_init_config_data); dc_get_edp_links(dc->dc, edp_links, &edp_num); for (i = 0; i < edp_num; i++) { if (panel_inst == i) break; } if (i < edp_num) { cmd.cacp_init_config.cacp_init_config_data.strscl_valid = (uint8_t)edp_links[panel_inst]->panel_config.cacp.strscl_valid; cmd.cacp_init_config.cacp_init_config_data.mode = edp_links[panel_inst]->panel_config.cacp.cacp_control_mode ? DMUB_CMD_CACP_CONTROL_MODE_1 : DMUB_CMD_CACP_CONTROL_MODE_0; for (int j = 0; j < CACP_LEVEL_NUM; j++) { cmd.cacp_init_config.cacp_init_config_data.strscl_sdr[j] = (uint8_t)edp_links[panel_inst]->panel_config.cacp.strscl_sdr[j]; cmd.cacp_init_config.cacp_init_config_data.strscl_hdr[j] = (uint8_t)edp_links[panel_inst]->panel_config.cacp.strscl_hdr[j]; } } dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); } bool dmub_cacp_set_level(struct abm *abm, unsigned int abm_level, unsigned char panel_mask) { union dmub_rb_cmd cmd; struct dc_context *dc = abm->ctx; memset(&cmd, 0, sizeof(cmd)); cmd.cacp_set_level.header.type = DMUB_CMD__CACP; cmd.cacp_set_level.header.sub_type = DMUB_CMD__CACP_SET_LEVEL; cmd.cacp_set_level.cacp_set_level_data.level = abm_level; cmd.cacp_set_level.cacp_set_level_data.version = DMUB_CMD_CACP_CONTROL_VERSION_1; cmd.cacp_set_level.cacp_set_level_data.panel_mask = panel_mask; cmd.cacp_set_level.header.payload_bytes = sizeof(struct dmub_cmd_cacp_set_level_data); dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); return true; } bool dmub_cacp_set_pipe(struct abm *abm, unsigned int otg_inst, unsigned int pipe_option, unsigned int panel_inst, unsigned int pwrseq_inst) { union dmub_rb_cmd cmd; struct dc_context *dc = abm->ctx; memset(&cmd, 0, sizeof(cmd)); cmd.cacp_set_pipe.header.type = DMUB_CMD__CACP; cmd.cacp_set_pipe.header.sub_type = DMUB_CMD__CACP_SET_PIPE; cmd.cacp_set_pipe.cacp_set_pipe_data.otg_inst = (uint8_t)otg_inst; cmd.cacp_set_pipe.cacp_set_pipe_data.panel_inst = (uint8_t)panel_inst; cmd.cacp_set_pipe.cacp_set_pipe_data.set_pipe_option = (uint8_t)pipe_option; cmd.cacp_set_pipe.cacp_set_pipe_data.pwrseq_inst = (uint8_t)pwrseq_inst; cmd.cacp_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_cacp_set_pipe_data); dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); return true; } bool dmub_cacp_set_event(struct abm *abm, unsigned int full_screen, unsigned int trans_info, unsigned int hdr_mode, unsigned int scaling_enable, unsigned int panel_inst) { union dmub_rb_cmd cmd; struct dc_context *dc = abm->ctx; memset(&cmd, 0, sizeof(cmd)); cmd.cacp_set_event.header.type = DMUB_CMD__CACP; cmd.cacp_set_event.header.sub_type = DMUB_CMD__CACP_SET_EVENT; //TODO: cmd.cacp_set_event.cacp_set_event_data.full_screen_mode = (uint8_t)full_screen; cmd.cacp_set_event.cacp_set_event_data.trans_info = trans_info; cmd.cacp_set_event.cacp_set_event_data.hdr_mode = (uint8_t)hdr_mode; cmd.cacp_set_event.cacp_set_event_data.vb_scaling_enable = (uint8_t)scaling_enable; cmd.cacp_set_event.cacp_set_event_data.panel_mask = (1<ctx; memset(&cmd, 0, sizeof(cmd)); cmd.cacp_pause.header.type = DMUB_CMD__CACP; cmd.cacp_pause.header.sub_type = DMUB_CMD__CACP_PAUSE; cmd.cacp_pause.cacp_pause_data.panel_mask = (1<ctx; memset(&cmd, 0, sizeof(cmd)); cmd.cacp_set_backlight.header.type = DMUB_CMD__CACP; cmd.cacp_set_backlight.header.sub_type = DMUB_CMD__CACP_SET_BACKLIGHT; cmd.cacp_set_backlight.cacp_set_backlight_data.frame_ramp = frame_ramp; cmd.cacp_set_backlight.cacp_set_backlight_data.backlight_user_level = backlight_pwm_u16_16; cmd.cacp_set_backlight.cacp_set_backlight_data.version = DMUB_CMD_CACP_CONTROL_VERSION_1; cmd.cacp_set_backlight.cacp_set_backlight_data.panel_mask = (0x01 << panel_inst); cmd.cacp_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_cacp_set_backlight_data); dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); return true; } void dmub_cacp_enable_fractional_pwm(struct abm *abm, uint8_t panel_mask) { union dmub_rb_cmd cmd; struct dc_context *dc = abm->ctx; uint32_t fractional_pwm = (dc->dc->config.disable_fractional_pwm == false) ? 1 : 0; memset(&cmd, 0, sizeof(cmd)); cmd.cacp_set_pwm_frac.header.type = DMUB_CMD__CACP; cmd.cacp_set_pwm_frac.header.sub_type = DMUB_CMD__CACP_SET_PWM_FRAC; cmd.cacp_set_pwm_frac.cacp_set_pwm_frac_data.fractional_pwm = fractional_pwm; cmd.cacp_set_pwm_frac.cacp_set_pwm_frac_data.version = DMUB_CMD_CACP_CONTROL_VERSION_1; cmd.cacp_set_pwm_frac.cacp_set_pwm_frac_data.panel_mask = panel_mask; cmd.cacp_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_cacp_set_pwm_frac_data); dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); } bool dmub_cacp_get_histogram( struct dc_context *dc, unsigned int panel_inst, unsigned int *histogram, enum dmub_abm_histogram_type histogram_type, unsigned int size) { union dmub_rb_cmd cmd; dmub_srv_flush_buffer_mem(dc->dmub_srv->dmub, &dc->dmub_srv->dmub->scratch_mem_fb); memset(&cmd, 0, sizeof(cmd)); cmd.cacp_get_histogram.header.type = DMUB_CMD__CACP; cmd.cacp_get_histogram.header.sub_type = DMUB_CMD__CACP_GET_HISTOGRAM; cmd.cacp_get_histogram.dest.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr; cmd.cacp_get_histogram.bytes = (uint16_t)size; cmd.cacp_get_histogram.panel_inst = (uint8_t)panel_inst; cmd.cacp_get_histogram.histogram_type = histogram_type; cmd.cacp_get_histogram.header.payload_bytes = sizeof(struct dmub_rb_cmd_cacp_get_histogram); dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); memcpy((void *)histogram, dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, size); return true; }