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

drm/amd/display: Refactor ABM feature

[Why]
Refactor ABM feature and implement inbox command for DMUB.

[How]
Implement the ioctl to send inbox command to DMUB.

Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Leon Huang <Leon.Huang1@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Leon Huang and committed by
Alex Deucher
b8fe5637 0c1f0331

+457 -177
+1 -1
drivers/gpu/drm/amd/display/dc/dce/Makefile
··· 29 29 DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ 30 30 dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ 31 31 dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \ 32 - dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o dmub_psr.o dmub_abm.o dce_panel_cntl.o \ 32 + dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o dmub_psr.o dmub_abm.o dmub_abm_lcd.o dce_panel_cntl.o \ 33 33 dmub_hw_lock_mgr.o dmub_outbox.o 34 34 35 35 AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE))
+118 -176
drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
··· 24 24 */ 25 25 26 26 #include "dmub_abm.h" 27 - #include "dce_abm.h" 27 + #include "dmub_abm_lcd.h" 28 28 #include "dc.h" 29 - #include "dc_dmub_srv.h" 30 - #include "dmub/dmub_srv.h" 31 29 #include "core_types.h" 32 - #include "dm_services.h" 33 - #include "reg_helper.h" 34 - #include "fixed31_32.h" 35 - 36 - #include "atom.h" 37 30 38 31 #define TO_DMUB_ABM(abm)\ 39 32 container_of(abm, struct dce_abm, base) 40 33 41 - #define REG(reg) \ 42 - (dce_abm->regs->reg) 34 + #define ABM_FEATURE_NO_SUPPORT 0 35 + #define ABM_LCD_SUPPORT 1 43 36 44 - #undef FN 45 - #define FN(reg_name, field_name) \ 46 - dce_abm->abm_shift->field_name, dce_abm->abm_mask->field_name 47 - 48 - #define CTX \ 49 - dce_abm->base.ctx 50 - 51 - #define DISABLE_ABM_IMMEDIATELY 255 52 - 53 - 54 - 55 - static void dmub_abm_enable_fractional_pwm(struct dc_context *dc) 37 + static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst) 56 38 { 57 - union dmub_rb_cmd cmd; 58 - uint32_t fractional_pwm = (dc->dc->config.disable_fractional_pwm == false) ? 1 : 0; 59 - uint32_t edp_id_count = dc->dc_edp_id_count; 60 - int i; 61 - uint8_t panel_mask = 0; 62 - 63 - for (i = 0; i < edp_id_count; i++) 64 - panel_mask |= 0x01 << i; 65 - 66 - memset(&cmd, 0, sizeof(cmd)); 67 - cmd.abm_set_pwm_frac.header.type = DMUB_CMD__ABM; 68 - cmd.abm_set_pwm_frac.header.sub_type = DMUB_CMD__ABM_SET_PWM_FRAC; 69 - cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.fractional_pwm = fractional_pwm; 70 - cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; 71 - cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.panel_mask = panel_mask; 72 - cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data); 73 - 74 - dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 75 - dc_dmub_srv_cmd_execute(dc->dmub_srv); 76 - dc_dmub_srv_wait_idle(dc->dmub_srv); 77 - } 78 - 79 - static void dmub_abm_init(struct abm *abm, uint32_t backlight) 80 - { 81 - struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 82 - 83 - REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x3); 84 - REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x1); 85 - REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x3); 86 - REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x1); 87 - REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x1); 88 - 89 - REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0, 90 - ABM1_HG_NUM_OF_BINS_SEL, 0, 91 - ABM1_HG_VMAX_SEL, 1, 92 - ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0); 93 - 94 - REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0, 95 - ABM1_IPCSC_COEFF_SEL_R, 2, 96 - ABM1_IPCSC_COEFF_SEL_G, 4, 97 - ABM1_IPCSC_COEFF_SEL_B, 2); 98 - 99 - REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL, 100 - BL1_PWM_CURRENT_ABM_LEVEL, backlight); 101 - 102 - REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL, 103 - BL1_PWM_TARGET_ABM_LEVEL, backlight); 104 - 105 - REG_UPDATE(BL1_PWM_USER_LEVEL, 106 - BL1_PWM_USER_LEVEL, backlight); 107 - 108 - REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, 109 - ABM1_LS_MIN_PIXEL_VALUE_THRES, 0, 110 - ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000); 111 - 112 - REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0, 113 - ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1, 114 - ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1, 115 - ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); 116 - 117 - dmub_abm_enable_fractional_pwm(abm->ctx); 118 - } 119 - 120 - static unsigned int dmub_abm_get_current_backlight(struct abm *abm) 121 - { 122 - struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 123 - unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL); 124 - 125 - /* return backlight in hardware format which is unsigned 17 bits, with 126 - * 1 bit integer and 16 bit fractional 127 - */ 128 - return backlight; 129 - } 130 - 131 - static unsigned int dmub_abm_get_target_backlight(struct abm *abm) 132 - { 133 - struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 134 - unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL); 135 - 136 - /* return backlight in hardware format which is unsigned 17 bits, with 137 - * 1 bit integer and 16 bit fractional 138 - */ 139 - return backlight; 140 - } 141 - 142 - static bool dmub_abm_set_level(struct abm *abm, uint32_t level) 143 - { 144 - union dmub_rb_cmd cmd; 145 39 struct dc_context *dc = abm->ctx; 146 40 struct dc_link *edp_links[MAX_NUM_EDP]; 147 41 int i; 148 42 int edp_num; 149 - uint8_t panel_mask = 0; 43 + unsigned int ret = ABM_FEATURE_NO_SUPPORT; 150 44 151 45 dc_get_edp_links(dc->dc, edp_links, &edp_num); 152 46 153 47 for (i = 0; i < edp_num; i++) { 154 - if (edp_links[i]->link_status.link_active) 155 - panel_mask |= (0x01 << i); 48 + if (panel_inst == i) 49 + break; 156 50 } 157 51 158 - memset(&cmd, 0, sizeof(cmd)); 159 - cmd.abm_set_level.header.type = DMUB_CMD__ABM; 160 - cmd.abm_set_level.header.sub_type = DMUB_CMD__ABM_SET_LEVEL; 161 - cmd.abm_set_level.abm_set_level_data.level = level; 162 - cmd.abm_set_level.abm_set_level_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; 163 - cmd.abm_set_level.abm_set_level_data.panel_mask = panel_mask; 164 - cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data); 52 + if (i < edp_num) { 53 + ret = ABM_LCD_SUPPORT; 54 + } 165 55 166 - dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 167 - dc_dmub_srv_cmd_execute(dc->dmub_srv); 168 - dc_dmub_srv_wait_idle(dc->dmub_srv); 169 - 170 - return true; 56 + return ret; 171 57 } 172 58 173 - static bool dmub_abm_init_config(struct abm *abm, 59 + static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight) 60 + { 61 + dmub_abm_init(abm, backlight); 62 + } 63 + 64 + static unsigned int dmub_abm_get_current_backlight_ex(struct abm *abm) 65 + { 66 + return dmub_abm_get_current_backlight(abm); 67 + } 68 + 69 + static unsigned int dmub_abm_get_target_backlight_ex(struct abm *abm) 70 + { 71 + return dmub_abm_get_target_backlight(abm); 72 + } 73 + 74 + static bool dmub_abm_set_level_ex(struct abm *abm, uint32_t level) 75 + { 76 + bool ret = false; 77 + unsigned int feature_support, i; 78 + uint8_t panel_mask0 = 0; 79 + 80 + for (i = 0; i < MAX_NUM_EDP; i++) { 81 + feature_support = abm_feature_support(abm, i); 82 + 83 + if (feature_support == ABM_LCD_SUPPORT) 84 + panel_mask0 |= (0x01 << i); 85 + } 86 + 87 + if (panel_mask0) 88 + ret = dmub_abm_set_level(abm, level, panel_mask0); 89 + 90 + return ret; 91 + } 92 + 93 + static bool dmub_abm_init_config_ex(struct abm *abm, 174 94 const char *src, 175 95 unsigned int bytes, 176 96 unsigned int inst) 177 97 { 178 - union dmub_rb_cmd cmd; 179 - struct dc_context *dc = abm->ctx; 180 - uint8_t panel_mask = 0x01 << inst; 98 + unsigned int feature_support; 181 99 182 - // TODO: Optimize by only reading back final 4 bytes 183 - dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb); 100 + feature_support = abm_feature_support(abm, inst); 184 101 185 - // Copy iramtable into cw7 186 - memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)src, bytes); 187 - 188 - memset(&cmd, 0, sizeof(cmd)); 189 - // Fw will copy from cw7 to fw_state 190 - cmd.abm_init_config.header.type = DMUB_CMD__ABM; 191 - cmd.abm_init_config.header.sub_type = DMUB_CMD__ABM_INIT_CONFIG; 192 - cmd.abm_init_config.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr; 193 - cmd.abm_init_config.abm_init_config_data.bytes = bytes; 194 - cmd.abm_init_config.abm_init_config_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; 195 - cmd.abm_init_config.abm_init_config_data.panel_mask = panel_mask; 196 - 197 - cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data); 198 - 199 - dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 200 - dc_dmub_srv_cmd_execute(dc->dmub_srv); 201 - dc_dmub_srv_wait_idle(dc->dmub_srv); 102 + if (feature_support == ABM_LCD_SUPPORT) 103 + dmub_abm_init_config(abm, src, bytes, inst); 202 104 203 105 return true; 204 106 } 205 107 206 - static bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst) 108 + static bool dmub_abm_set_pause_ex(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst) 207 109 { 208 - union dmub_rb_cmd cmd; 209 - struct dc_context *dc = abm->ctx; 210 - uint8_t panel_mask = 0x01 << panel_inst; 110 + bool ret = false; 111 + unsigned int feature_support; 211 112 212 - memset(&cmd, 0, sizeof(cmd)); 213 - cmd.abm_pause.header.type = DMUB_CMD__ABM; 214 - cmd.abm_pause.header.sub_type = DMUB_CMD__ABM_PAUSE; 215 - cmd.abm_pause.abm_pause_data.enable = pause; 216 - cmd.abm_pause.abm_pause_data.panel_mask = panel_mask; 217 - cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_pause_data); 113 + feature_support = abm_feature_support(abm, panel_inst); 218 114 219 - dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 220 - dc_dmub_srv_cmd_execute(dc->dmub_srv); 221 - dc_dmub_srv_wait_idle(dc->dmub_srv); 115 + if (feature_support == ABM_LCD_SUPPORT) 116 + ret = dmub_abm_set_pause(abm, pause, panel_inst, stream_inst); 222 117 223 - return true; 118 + return ret; 119 + } 120 + 121 + static bool dmub_abm_set_pipe_ex(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst) 122 + { 123 + bool ret = false; 124 + unsigned int feature_support; 125 + 126 + feature_support = abm_feature_support(abm, panel_inst); 127 + 128 + if (feature_support == ABM_LCD_SUPPORT) 129 + ret = dmub_abm_set_pipe(abm, otg_inst, option, panel_inst); 130 + 131 + return ret; 132 + } 133 + 134 + static bool dmub_abm_set_event_ex(struct abm *abm, unsigned int full_screen, unsigned int video_mode, 135 + unsigned int hdr_mode, unsigned int panel_inst) 136 + { 137 + bool ret = false; 138 + unsigned int feature_support; 139 + 140 + feature_support = abm_feature_support(abm, panel_inst); 141 + 142 + return ret; 143 + } 144 + 145 + static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm, 146 + unsigned int backlight_pwm_u16_16, 147 + unsigned int frame_ramp, 148 + unsigned int controller_id, 149 + unsigned int panel_inst) 150 + { 151 + bool ret = false; 152 + unsigned int feature_support; 153 + 154 + feature_support = abm_feature_support(abm, panel_inst); 155 + 156 + if (feature_support == ABM_LCD_SUPPORT) 157 + ret = dmub_abm_set_backlight_level(abm, backlight_pwm_u16_16, frame_ramp, panel_inst); 158 + 159 + return ret; 224 160 } 225 161 226 162 static const struct abm_funcs abm_funcs = { 227 - .abm_init = dmub_abm_init, 228 - .set_abm_level = dmub_abm_set_level, 229 - .get_current_backlight = dmub_abm_get_current_backlight, 230 - .get_target_backlight = dmub_abm_get_target_backlight, 231 - .init_abm_config = dmub_abm_init_config, 232 - .set_abm_pause = dmub_abm_set_pause, 163 + .abm_init = dmub_abm_init_ex, 164 + .set_abm_level = dmub_abm_set_level_ex, 165 + .get_current_backlight = dmub_abm_get_current_backlight_ex, 166 + .get_target_backlight = dmub_abm_get_target_backlight_ex, 167 + .init_abm_config = dmub_abm_init_config_ex, 168 + .set_abm_pause = dmub_abm_set_pause_ex, 169 + .set_pipe_ex = dmub_abm_set_pipe_ex, 170 + .set_abm_event = dmub_abm_set_event_ex, 171 + .set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm_ex, 233 172 }; 234 173 235 174 static void dmub_abm_construct( ··· 195 256 const struct dce_abm_shift *abm_shift, 196 257 const struct dce_abm_mask *abm_mask) 197 258 { 198 - struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL); 259 + if (ctx->dc->caps.dmcub_support) { 260 + struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL); 199 261 200 - if (abm_dce == NULL) { 201 - BREAK_TO_DEBUGGER(); 202 - return NULL; 262 + if (abm_dce == NULL) { 263 + BREAK_TO_DEBUGGER(); 264 + return NULL; 265 + } 266 + 267 + dmub_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask); 268 + 269 + return &abm_dce->base; 203 270 } 204 - 205 - dmub_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask); 206 - 207 - return &abm_dce->base; 271 + return NULL; 208 272 } 209 273 210 274 void dmub_abm_destroy(struct abm **abm)
+286
drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
··· 1 + /* 2 + * Copyright 2019 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #include "dmub_abm.h" 27 + #include "dce_abm.h" 28 + #include "dc.h" 29 + #include "dc_dmub_srv.h" 30 + #include "dmub/dmub_srv.h" 31 + #include "core_types.h" 32 + #include "dm_services.h" 33 + #include "reg_helper.h" 34 + #include "fixed31_32.h" 35 + 36 + #ifdef _WIN32 37 + #include "atombios.h" 38 + #else 39 + #include "atom.h" 40 + #endif 41 + 42 + #define TO_DMUB_ABM(abm)\ 43 + container_of(abm, struct dce_abm, base) 44 + 45 + #define REG(reg) \ 46 + (dce_abm->regs->reg) 47 + 48 + #undef FN 49 + #define FN(reg_name, field_name) \ 50 + dce_abm->abm_shift->field_name, dce_abm->abm_mask->field_name 51 + 52 + #define CTX \ 53 + dce_abm->base.ctx 54 + 55 + #define DISABLE_ABM_IMMEDIATELY 255 56 + 57 + 58 + 59 + static void dmub_abm_enable_fractional_pwm(struct dc_context *dc) 60 + { 61 + union dmub_rb_cmd cmd; 62 + uint32_t fractional_pwm = (dc->dc->config.disable_fractional_pwm == false) ? 1 : 0; 63 + uint32_t edp_id_count = dc->dc_edp_id_count; 64 + int i; 65 + uint8_t panel_mask = 0; 66 + 67 + for (i = 0; i < edp_id_count; i++) 68 + panel_mask |= 0x01 << i; 69 + 70 + memset(&cmd, 0, sizeof(cmd)); 71 + cmd.abm_set_pwm_frac.header.type = DMUB_CMD__ABM; 72 + cmd.abm_set_pwm_frac.header.sub_type = DMUB_CMD__ABM_SET_PWM_FRAC; 73 + cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.fractional_pwm = fractional_pwm; 74 + cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; 75 + cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.panel_mask = panel_mask; 76 + cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data); 77 + 78 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 79 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 80 + dc_dmub_srv_wait_idle(dc->dmub_srv); 81 + } 82 + 83 + void dmub_abm_init(struct abm *abm, uint32_t backlight) 84 + { 85 + struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 86 + 87 + REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x3); 88 + REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x1); 89 + REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x3); 90 + REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x1); 91 + REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x1); 92 + 93 + REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0, 94 + ABM1_HG_NUM_OF_BINS_SEL, 0, 95 + ABM1_HG_VMAX_SEL, 1, 96 + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0); 97 + 98 + REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0, 99 + ABM1_IPCSC_COEFF_SEL_R, 2, 100 + ABM1_IPCSC_COEFF_SEL_G, 4, 101 + ABM1_IPCSC_COEFF_SEL_B, 2); 102 + 103 + REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL, 104 + BL1_PWM_CURRENT_ABM_LEVEL, backlight); 105 + 106 + REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL, 107 + BL1_PWM_TARGET_ABM_LEVEL, backlight); 108 + 109 + REG_UPDATE(BL1_PWM_USER_LEVEL, 110 + BL1_PWM_USER_LEVEL, backlight); 111 + 112 + REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, 113 + ABM1_LS_MIN_PIXEL_VALUE_THRES, 0, 114 + ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000); 115 + 116 + REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0, 117 + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1, 118 + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1, 119 + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); 120 + 121 + dmub_abm_enable_fractional_pwm(abm->ctx); 122 + } 123 + 124 + unsigned int dmub_abm_get_current_backlight(struct abm *abm) 125 + { 126 + struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 127 + unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL); 128 + 129 + /* return backlight in hardware format which is unsigned 17 bits, with 130 + * 1 bit integer and 16 bit fractional 131 + */ 132 + return backlight; 133 + } 134 + 135 + unsigned int dmub_abm_get_target_backlight(struct abm *abm) 136 + { 137 + struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 138 + unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL); 139 + 140 + /* return backlight in hardware format which is unsigned 17 bits, with 141 + * 1 bit integer and 16 bit fractional 142 + */ 143 + return backlight; 144 + } 145 + 146 + bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask) 147 + { 148 + union dmub_rb_cmd cmd; 149 + struct dc_context *dc = abm->ctx; 150 + 151 + memset(&cmd, 0, sizeof(cmd)); 152 + cmd.abm_set_level.header.type = DMUB_CMD__ABM; 153 + cmd.abm_set_level.header.sub_type = DMUB_CMD__ABM_SET_LEVEL; 154 + cmd.abm_set_level.abm_set_level_data.level = level; 155 + cmd.abm_set_level.abm_set_level_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; 156 + cmd.abm_set_level.abm_set_level_data.panel_mask = panel_mask; 157 + cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data); 158 + 159 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 160 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 161 + dc_dmub_srv_wait_idle(dc->dmub_srv); 162 + 163 + return true; 164 + } 165 + 166 + #ifndef TRIM_AMBIENT_GAMMA 167 + void dmub_abm_set_ambient_level(struct abm *abm, unsigned int ambient_lux, uint8_t panel_mask) 168 + { 169 + union dmub_rb_cmd cmd; 170 + struct dc_context *dc = abm->ctx; 171 + 172 + if (ambient_lux > 0xFFFF) 173 + ambient_lux = 0xFFFF; 174 + 175 + memset(&cmd, 0, sizeof(cmd)); 176 + cmd.abm_set_ambient_level.header.type = DMUB_CMD__ABM; 177 + cmd.abm_set_ambient_level.header.sub_type = DMUB_CMD__ABM_SET_AMBIENT_LEVEL; 178 + cmd.abm_set_ambient_level.abm_set_ambient_level_data.ambient_lux = ambient_lux; 179 + cmd.abm_set_ambient_level.abm_set_ambient_level_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; 180 + cmd.abm_set_ambient_level.abm_set_ambient_level_data.panel_mask = panel_mask; 181 + cmd.abm_set_ambient_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_ambient_level_data); 182 + 183 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 184 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 185 + dc_dmub_srv_wait_idle(dc->dmub_srv); 186 + } 187 + #endif 188 + 189 + void dmub_abm_init_config(struct abm *abm, 190 + const char *src, 191 + unsigned int bytes, 192 + unsigned int inst) 193 + { 194 + union dmub_rb_cmd cmd; 195 + struct dc_context *dc = abm->ctx; 196 + uint8_t panel_mask = 0x01 << inst; 197 + 198 + // TODO: Optimize by only reading back final 4 bytes 199 + dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb); 200 + 201 + // Copy iramtable into cw7 202 + memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)src, bytes); 203 + 204 + memset(&cmd, 0, sizeof(cmd)); 205 + // Fw will copy from cw7 to fw_state 206 + cmd.abm_init_config.header.type = DMUB_CMD__ABM; 207 + cmd.abm_init_config.header.sub_type = DMUB_CMD__ABM_INIT_CONFIG; 208 + cmd.abm_init_config.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr; 209 + cmd.abm_init_config.abm_init_config_data.bytes = bytes; 210 + cmd.abm_init_config.abm_init_config_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; 211 + cmd.abm_init_config.abm_init_config_data.panel_mask = panel_mask; 212 + 213 + cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data); 214 + 215 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 216 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 217 + dc_dmub_srv_wait_idle(dc->dmub_srv); 218 + 219 + } 220 + 221 + bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst) 222 + { 223 + union dmub_rb_cmd cmd; 224 + struct dc_context *dc = abm->ctx; 225 + uint8_t panel_mask = 0x01 << panel_inst; 226 + 227 + memset(&cmd, 0, sizeof(cmd)); 228 + cmd.abm_pause.header.type = DMUB_CMD__ABM; 229 + cmd.abm_pause.header.sub_type = DMUB_CMD__ABM_PAUSE; 230 + cmd.abm_pause.abm_pause_data.enable = pause; 231 + cmd.abm_pause.abm_pause_data.panel_mask = panel_mask; 232 + cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_pause_data); 233 + 234 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 235 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 236 + dc_dmub_srv_wait_idle(dc->dmub_srv); 237 + 238 + return true; 239 + } 240 + 241 + bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst) 242 + { 243 + union dmub_rb_cmd cmd; 244 + struct dc_context *dc = abm->ctx; 245 + uint32_t ramping_boundary = 0xFFFF; 246 + 247 + memset(&cmd, 0, sizeof(cmd)); 248 + cmd.abm_set_pipe.header.type = DMUB_CMD__ABM; 249 + cmd.abm_set_pipe.header.sub_type = DMUB_CMD__ABM_SET_PIPE; 250 + cmd.abm_set_pipe.abm_set_pipe_data.otg_inst = otg_inst; 251 + cmd.abm_set_pipe.abm_set_pipe_data.set_pipe_option = option; 252 + cmd.abm_set_pipe.abm_set_pipe_data.panel_inst = panel_inst; 253 + cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary; 254 + cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data); 255 + 256 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 257 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 258 + dc_dmub_srv_wait_idle(dc->dmub_srv); 259 + 260 + return true; 261 + } 262 + 263 + bool dmub_abm_set_backlight_level(struct abm *abm, 264 + unsigned int backlight_pwm_u16_16, 265 + unsigned int frame_ramp, 266 + unsigned int panel_inst) 267 + { 268 + union dmub_rb_cmd cmd; 269 + struct dc_context *dc = abm->ctx; 270 + 271 + memset(&cmd, 0, sizeof(cmd)); 272 + cmd.abm_set_backlight.header.type = DMUB_CMD__ABM; 273 + cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT; 274 + cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp; 275 + cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_pwm_u16_16; 276 + cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; 277 + cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst); 278 + cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data); 279 + 280 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); 281 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 282 + dc_dmub_srv_wait_idle(dc->dmub_srv); 283 + 284 + return true; 285 + } 286 +
+46
drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.h
··· 1 + /* 2 + * Copyright 2019 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef __DMUB_ABM_LCD_H__ 27 + #define __DMUB_ABM_LCD_H__ 28 + 29 + #include "abm.h" 30 + 31 + void dmub_abm_init(struct abm *abm, uint32_t backlight); 32 + bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask); 33 + unsigned int dmub_abm_get_current_backlight(struct abm *abm); 34 + unsigned int dmub_abm_get_target_backlight(struct abm *abm); 35 + void dmub_abm_init_config(struct abm *abm, 36 + const char *src, 37 + unsigned int bytes, 38 + unsigned int inst); 39 + 40 + bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst); 41 + bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst); 42 + bool dmub_abm_set_backlight_level(struct abm *abm, 43 + unsigned int backlight_pwm_u16_16, 44 + unsigned int frame_ramp, 45 + unsigned int panel_inst); 46 + #endif
+6
drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
··· 55 55 unsigned int bytes, 56 56 unsigned int inst); 57 57 bool (*set_abm_pause)(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int otg_inst); 58 + bool (*set_pipe_ex)(struct abm *abm, 59 + unsigned int otg_inst, 60 + unsigned int option, 61 + unsigned int panel_inst); 62 + bool (*set_abm_event)(struct abm *abm, unsigned int full_screen, unsigned int video_mode, 63 + unsigned int hdr_mode, unsigned int panel_inst); 58 64 }; 59 65 60 66 #endif