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

drm/amd/display: Add ABM driver implementation

[Why]
Moving ABM from DMCU to DMCUB.

[How]
Add ABM driver files and implementation.

Signed-off-by: Wyatt Wood <wyatt.wood@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Wyatt Wood and committed by
Alex Deucher
16012806 46484870

+514 -23
+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 32 + dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o dmub_psr.o dmub_abm.o 33 33 34 34 AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) 35 35
+1
drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
··· 447 447 .set_backlight_level_pwm = dce_abm_set_backlight_level_pwm, 448 448 .get_current_backlight = dce_abm_get_current_backlight, 449 449 .get_target_backlight = dce_abm_get_target_backlight, 450 + .load_abm_config = NULL, 450 451 .set_abm_immediate_disable = dce_abm_immediate_disable 451 452 }; 452 453
+417
drivers/gpu/drm/amd/display/dc/dce/dmub_abm.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/inc/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 + #include "atom.h" 37 + 38 + #define TO_DMUB_ABM(abm)\ 39 + container_of(abm, struct dce_abm, base) 40 + 41 + #define REG(reg) \ 42 + (dce_abm->regs->reg) 43 + 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 + static bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst) 54 + { 55 + union dmub_rb_cmd cmd; 56 + struct dc_context *dc = abm->ctx; 57 + uint32_t ramping_boundary = 0xFFFF; 58 + 59 + cmd.abm_set_pipe.header.type = DMUB_CMD__ABM; 60 + cmd.abm_set_pipe.header.sub_type = DMUB_CMD__ABM_SET_PIPE; 61 + cmd.abm_set_pipe.abm_set_pipe_data.otg_inst = otg_inst; 62 + cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary; 63 + cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data); 64 + 65 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.abm_set_pipe.header); 66 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 67 + dc_dmub_srv_wait_idle(dc->dmub_srv); 68 + 69 + return true; 70 + } 71 + 72 + static unsigned int calculate_16_bit_backlight_from_pwm(struct dce_abm *dce_abm) 73 + { 74 + uint64_t current_backlight; 75 + uint32_t round_result; 76 + uint32_t bl_period, bl_int_count; 77 + uint32_t bl_pwm, fractional_duty_cycle_en; 78 + uint32_t bl_period_mask, bl_pwm_mask; 79 + 80 + REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period); 81 + REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, &bl_int_count); 82 + 83 + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &bl_pwm); 84 + REG_GET(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, &fractional_duty_cycle_en); 85 + 86 + if (bl_int_count == 0) 87 + bl_int_count = 16; 88 + 89 + bl_period_mask = (1 << bl_int_count) - 1; 90 + bl_period &= bl_period_mask; 91 + 92 + bl_pwm_mask = bl_period_mask << (16 - bl_int_count); 93 + 94 + if (fractional_duty_cycle_en == 0) 95 + bl_pwm &= bl_pwm_mask; 96 + else 97 + bl_pwm &= 0xFFFF; 98 + 99 + current_backlight = (uint64_t)bl_pwm << (1 + bl_int_count); 100 + 101 + if (bl_period == 0) 102 + bl_period = 0xFFFF; 103 + 104 + current_backlight = div_u64(current_backlight, bl_period); 105 + current_backlight = (current_backlight + 1) >> 1; 106 + 107 + current_backlight = (uint64_t)(current_backlight) * bl_period; 108 + 109 + round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); 110 + 111 + round_result = (round_result >> (bl_int_count-1)) & 1; 112 + 113 + current_backlight >>= bl_int_count; 114 + current_backlight += round_result; 115 + 116 + return (uint32_t)(current_backlight); 117 + } 118 + 119 + static void dmcub_set_backlight_level( 120 + struct dce_abm *dce_abm, 121 + uint32_t backlight_pwm_u16_16, 122 + uint32_t frame_ramp, 123 + uint32_t otg_inst) 124 + { 125 + union dmub_rb_cmd cmd; 126 + struct dc_context *dc = dce_abm->base.ctx; 127 + unsigned int backlight_8_bit = 0; 128 + uint32_t s2; 129 + 130 + if (backlight_pwm_u16_16 & 0x10000) 131 + // Check for max backlight condition 132 + backlight_8_bit = 0xFF; 133 + else 134 + // Take MSB of fractional part since backlight is not max 135 + backlight_8_bit = (backlight_pwm_u16_16 >> 8) & 0xFF; 136 + 137 + dmub_abm_set_pipe(&dce_abm->base, otg_inst); 138 + 139 + if (otg_inst == 0) 140 + frame_ramp = 0; 141 + 142 + cmd.abm_set_backlight.header.type = DMUB_CMD__ABM; 143 + cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT; 144 + cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp; 145 + cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data); 146 + 147 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.abm_set_backlight.header); 148 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 149 + dc_dmub_srv_wait_idle(dc->dmub_srv); 150 + 151 + // Update requested backlight level 152 + s2 = REG_READ(BIOS_SCRATCH_2); 153 + 154 + s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; 155 + backlight_8_bit &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >> 156 + ATOM_S2_CURRENT_BL_LEVEL_SHIFT); 157 + s2 |= (backlight_8_bit << ATOM_S2_CURRENT_BL_LEVEL_SHIFT); 158 + 159 + REG_WRITE(BIOS_SCRATCH_2, s2); 160 + } 161 + 162 + static void dmub_abm_init(struct abm *abm) 163 + { 164 + struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 165 + unsigned int backlight = calculate_16_bit_backlight_from_pwm(dce_abm); 166 + 167 + REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103); 168 + REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101); 169 + REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x103); 170 + REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x101); 171 + REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x101); 172 + 173 + REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0, 174 + ABM1_HG_NUM_OF_BINS_SEL, 0, 175 + ABM1_HG_VMAX_SEL, 1, 176 + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0); 177 + 178 + REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0, 179 + ABM1_IPCSC_COEFF_SEL_R, 2, 180 + ABM1_IPCSC_COEFF_SEL_G, 4, 181 + ABM1_IPCSC_COEFF_SEL_B, 2); 182 + 183 + REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL, 184 + BL1_PWM_CURRENT_ABM_LEVEL, backlight); 185 + 186 + REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL, 187 + BL1_PWM_TARGET_ABM_LEVEL, backlight); 188 + 189 + REG_UPDATE(BL1_PWM_USER_LEVEL, 190 + BL1_PWM_USER_LEVEL, backlight); 191 + 192 + REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, 193 + ABM1_LS_MIN_PIXEL_VALUE_THRES, 0, 194 + ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000); 195 + 196 + REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0, 197 + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1, 198 + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1, 199 + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); 200 + } 201 + 202 + static unsigned int dmub_abm_get_current_backlight(struct abm *abm) 203 + { 204 + struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 205 + unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL); 206 + 207 + /* return backlight in hardware format which is unsigned 17 bits, with 208 + * 1 bit integer and 16 bit fractional 209 + */ 210 + return backlight; 211 + } 212 + 213 + static unsigned int dmub_abm_get_target_backlight(struct abm *abm) 214 + { 215 + struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 216 + unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL); 217 + 218 + /* return backlight in hardware format which is unsigned 17 bits, with 219 + * 1 bit integer and 16 bit fractional 220 + */ 221 + return backlight; 222 + } 223 + 224 + static bool dmub_abm_set_level(struct abm *abm, uint32_t level) 225 + { 226 + union dmub_rb_cmd cmd; 227 + struct dc_context *dc = abm->ctx; 228 + 229 + cmd.abm_set_level.header.type = DMUB_CMD__ABM; 230 + cmd.abm_set_level.header.sub_type = DMUB_CMD__ABM_SET_LEVEL; 231 + cmd.abm_set_level.abm_set_level_data.level = level; 232 + cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data); 233 + 234 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.abm_set_level.header); 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 + static bool dmub_abm_immediate_disable(struct abm *abm) 242 + { 243 + struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 244 + 245 + dmub_abm_set_pipe(abm, DISABLE_ABM_IMMEDIATELY); 246 + 247 + abm->stored_backlight_registers.BL_PWM_CNTL = 248 + REG_READ(BL_PWM_CNTL); 249 + abm->stored_backlight_registers.BL_PWM_CNTL2 = 250 + REG_READ(BL_PWM_CNTL2); 251 + abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 252 + REG_READ(BL_PWM_PERIOD_CNTL); 253 + 254 + REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, 255 + &abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); 256 + 257 + return true; 258 + } 259 + 260 + static bool dmub_abm_init_backlight(struct abm *abm) 261 + { 262 + struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 263 + uint32_t value; 264 + 265 + /* It must not be 0, so we have to restore them 266 + * Bios bug w/a - period resets to zero, 267 + * restoring to cache values which is always correct 268 + */ 269 + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); 270 + 271 + if (value == 0 || value == 1) { 272 + if (abm->stored_backlight_registers.BL_PWM_CNTL != 0) { 273 + REG_WRITE(BL_PWM_CNTL, 274 + abm->stored_backlight_registers.BL_PWM_CNTL); 275 + REG_WRITE(BL_PWM_CNTL2, 276 + abm->stored_backlight_registers.BL_PWM_CNTL2); 277 + REG_WRITE(BL_PWM_PERIOD_CNTL, 278 + abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL); 279 + REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, 280 + BL_PWM_REF_DIV, 281 + abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); 282 + } else { 283 + /* TODO: Note: This should not really happen since VBIOS 284 + * should have initialized PWM registers on boot. 285 + */ 286 + REG_WRITE(BL_PWM_CNTL, 0xC000FA00); 287 + REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); 288 + } 289 + } else { 290 + abm->stored_backlight_registers.BL_PWM_CNTL = 291 + REG_READ(BL_PWM_CNTL); 292 + abm->stored_backlight_registers.BL_PWM_CNTL2 = 293 + REG_READ(BL_PWM_CNTL2); 294 + abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 295 + REG_READ(BL_PWM_PERIOD_CNTL); 296 + 297 + REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, 298 + &abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); 299 + } 300 + 301 + // Have driver take backlight control 302 + // TakeBacklightControl(true) 303 + value = REG_READ(BIOS_SCRATCH_2); 304 + value |= ATOM_S2_VRI_BRIGHT_ENABLE; 305 + REG_WRITE(BIOS_SCRATCH_2, value); 306 + 307 + // Enable the backlight output 308 + REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); 309 + 310 + // Unlock group 2 backlight registers 311 + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, 312 + BL_PWM_GRP1_REG_LOCK, 0); 313 + 314 + return true; 315 + } 316 + 317 + static bool dmub_abm_set_backlight_level_pwm( 318 + struct abm *abm, 319 + unsigned int backlight_pwm_u16_16, 320 + unsigned int frame_ramp, 321 + unsigned int otg_inst, 322 + bool use_smooth_brightness) 323 + { 324 + struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 325 + 326 + dmcub_set_backlight_level(dce_abm, 327 + backlight_pwm_u16_16, 328 + frame_ramp, 329 + otg_inst); 330 + 331 + return true; 332 + } 333 + 334 + static void dmub_abm_enable_fractional_pwm(struct dc_context *dc) 335 + { 336 + union dmub_rb_cmd cmd; 337 + uint32_t fractional_pwm = (dc->dc->config.disable_fractional_pwm == false) ? 1 : 0; 338 + 339 + cmd.abm_set_pwm_frac.header.type = DMUB_CMD__ABM; 340 + cmd.abm_set_pwm_frac.header.sub_type = DMUB_CMD__ABM_SET_PWM_FRAC; 341 + cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.fractional_pwm = fractional_pwm; 342 + cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data); 343 + 344 + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.abm_set_pwm_frac.header); 345 + dc_dmub_srv_cmd_execute(dc->dmub_srv); 346 + dc_dmub_srv_wait_idle(dc->dmub_srv); 347 + } 348 + 349 + static bool dmub_abm_load_config(struct abm *abm, 350 + unsigned int start_offset, 351 + const char *src, 352 + unsigned int bytes) 353 + { 354 + return true; 355 + } 356 + 357 + static const struct abm_funcs abm_funcs = { 358 + .abm_init = dmub_abm_init, 359 + .set_abm_level = dmub_abm_set_level, 360 + .init_backlight = dmub_abm_init_backlight, 361 + .set_pipe = dmub_abm_set_pipe, 362 + .set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm, 363 + .get_current_backlight = dmub_abm_get_current_backlight, 364 + .get_target_backlight = dmub_abm_get_target_backlight, 365 + .set_abm_immediate_disable = dmub_abm_immediate_disable, 366 + .load_abm_config = dmub_abm_load_config, 367 + }; 368 + 369 + static void dmub_abm_construct( 370 + struct dce_abm *abm_dce, 371 + struct dc_context *ctx, 372 + const struct dce_abm_registers *regs, 373 + const struct dce_abm_shift *abm_shift, 374 + const struct dce_abm_mask *abm_mask) 375 + { 376 + struct abm *base = &abm_dce->base; 377 + 378 + base->ctx = ctx; 379 + base->funcs = &abm_funcs; 380 + base->stored_backlight_registers.BL_PWM_CNTL = 0; 381 + base->stored_backlight_registers.BL_PWM_CNTL2 = 0; 382 + base->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 0; 383 + base->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = 0; 384 + base->dmcu_is_running = false; 385 + 386 + abm_dce->regs = regs; 387 + abm_dce->abm_shift = abm_shift; 388 + abm_dce->abm_mask = abm_mask; 389 + 390 + dmub_abm_enable_fractional_pwm(ctx); 391 + } 392 + 393 + struct abm *dmub_abm_create( 394 + struct dc_context *ctx, 395 + const struct dce_abm_registers *regs, 396 + const struct dce_abm_shift *abm_shift, 397 + const struct dce_abm_mask *abm_mask) 398 + { 399 + struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL); 400 + 401 + if (abm_dce == NULL) { 402 + BREAK_TO_DEBUGGER(); 403 + return NULL; 404 + } 405 + 406 + dmub_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask); 407 + 408 + return &abm_dce->base; 409 + } 410 + 411 + void dmub_abm_destroy(struct abm **abm) 412 + { 413 + struct dce_abm *abm_dce = TO_DMUB_ABM(*abm); 414 + 415 + kfree(abm_dce); 416 + *abm = NULL; 417 + }
+40
drivers/gpu/drm/amd/display/dc/dce/dmub_abm.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_H__ 27 + #define __DMUB_ABM_H__ 28 + 29 + #include "abm.h" 30 + #include "dce_abm.h" 31 + 32 + struct abm *dmub_abm_create( 33 + struct dc_context *ctx, 34 + const struct dce_abm_registers *regs, 35 + const struct dce_abm_shift *abm_shift, 36 + const struct dce_abm_mask *abm_mask); 37 + 38 + void dmub_abm_destroy(struct abm **abm); 39 + 40 + #endif
+24 -17
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
··· 85 85 #include "vm_helper.h" 86 86 #include "dcn20/dcn20_vmid.h" 87 87 #include "dce/dmub_psr.h" 88 + #include "dce/dmub_abm.h" 88 89 89 90 #define SOC_BOUNDING_BOX_VALID false 90 91 #define DC_LOGGER_INIT(logger) ··· 992 991 pool->base.dp_clock_source = NULL; 993 992 } 994 993 995 - 996 - if (pool->base.abm != NULL) 997 - dce_abm_destroy(&pool->base.abm); 994 + if (pool->base.abm != NULL) { 995 + if (pool->base.abm->ctx->dc->debug.disable_dmcu) 996 + dmub_abm_destroy(&pool->base.abm); 997 + else 998 + dce_abm_destroy(&pool->base.abm); 999 + } 998 1000 999 1001 if (pool->base.dmcu != NULL) 1000 1002 dce_dmcu_destroy(&pool->base.dmcu); ··· 1846 1842 goto create_fail; 1847 1843 } 1848 1844 1849 - pool->base.dmcu = dcn21_dmcu_create(ctx, 1850 - &dmcu_regs, 1851 - &dmcu_shift, 1852 - &dmcu_mask); 1853 - if (pool->base.dmcu == NULL) { 1854 - dm_error("DC: failed to create dmcu!\n"); 1855 - BREAK_TO_DEBUGGER(); 1856 - goto create_fail; 1845 + if (!dc->debug.disable_dmcu) { 1846 + pool->base.dmcu = dcn21_dmcu_create(ctx, 1847 + &dmcu_regs, 1848 + &dmcu_shift, 1849 + &dmcu_mask); 1850 + if (pool->base.dmcu == NULL) { 1851 + dm_error("DC: failed to create dmcu!\n"); 1852 + BREAK_TO_DEBUGGER(); 1853 + goto create_fail; 1854 + } 1857 1855 } 1858 1856 1859 1857 if (dc->debug.disable_dmcu) { ··· 1868 1862 } 1869 1863 } 1870 1864 1871 - pool->base.abm = dce_abm_create(ctx, 1865 + if (dc->debug.disable_dmcu) 1866 + pool->base.abm = dmub_abm_create(ctx, 1872 1867 &abm_regs, 1873 1868 &abm_shift, 1874 1869 &abm_mask); 1875 - if (pool->base.abm == NULL) { 1876 - dm_error("DC: failed to create abm!\n"); 1877 - BREAK_TO_DEBUGGER(); 1878 - goto create_fail; 1879 - } 1870 + else 1871 + pool->base.abm = dce_abm_create(ctx, 1872 + &abm_regs, 1873 + &abm_shift, 1874 + &abm_mask); 1880 1875 1881 1876 pool->base.pp_smu = dcn21_pp_smu_create(ctx); 1882 1877
+4
drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
··· 60 60 61 61 unsigned int (*get_current_backlight)(struct abm *abm); 62 62 unsigned int (*get_target_backlight)(struct abm *abm); 63 + bool (*load_abm_config)(struct abm *abm, 64 + unsigned int start_offset, 65 + const char *src, 66 + unsigned int bytes); 63 67 }; 64 68 65 69 #endif
+11
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
··· 303 303 struct dmub_cmd_abm_set_pwm_frac_data abm_set_pwm_frac_data; 304 304 }; 305 305 306 + struct dmub_cmd_abm_init_config_data { 307 + union dmub_addr src; 308 + uint16_t bytes; 309 + }; 310 + 311 + struct dmub_rb_cmd_abm_init_config { 312 + struct dmub_cmd_header header; 313 + struct dmub_cmd_abm_init_config_data abm_init_config_data; 314 + }; 315 + 306 316 union dmub_rb_cmd { 307 317 struct dmub_rb_cmd_read_modify_write read_modify_write; 308 318 struct dmub_rb_cmd_reg_field_update_sequence reg_field_update_seq; ··· 334 324 struct dmub_rb_cmd_abm_set_level abm_set_level; 335 325 struct dmub_rb_cmd_abm_set_ambient_level abm_set_ambient_level; 336 326 struct dmub_rb_cmd_abm_set_pwm_frac abm_set_pwm_frac; 327 + struct dmub_rb_cmd_abm_init_config abm_init_config; 337 328 }; 338 329 339 330 #pragma pack(pop)
+16 -5
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
··· 24 24 25 25 #include "power_helpers.h" 26 26 #include "dc/inc/hw/dmcu.h" 27 + #include "dc/inc/hw/abm.h" 28 + #include "dc.h" 29 + #include "core_types.h" 27 30 28 31 #define DIV_ROUNDUP(a, b) (((a)+((b)/2))/(b)) 29 32 ··· 656 653 { 657 654 unsigned char ram_table[IRAM_SIZE]; 658 655 bool result = false; 656 + struct abm *abm = dmcu->ctx->dc->res_pool->abm; 659 657 660 - if (dmcu == NULL) 658 + if (dmcu == NULL && abm == NULL) 661 659 return false; 662 660 663 - if (!dmcu->funcs->is_dmcu_initialized(dmcu)) 661 + if (dmcu && !dmcu->funcs->is_dmcu_initialized(dmcu)) 664 662 return true; 665 663 666 664 memset(&ram_table, 0, sizeof(ram_table)); 667 665 668 - if (dmcu->dmcu_version.abm_version == 0x24) { 666 + // In the case where abm is implemented on dmcub, 667 + // dmcu object will be null. 668 + // ABM 2.4 and up are implemented on dmcub 669 + if (dmcu == NULL) { 669 670 fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params); 670 - result = dmcu->funcs->load_iram( 671 - dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2); 671 + result = abm->funcs->load_abm_config( 672 + abm, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2); 673 + } else if (dmcu->dmcu_version.abm_version == 0x24) { 674 + fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params); 675 + result = dmcu->funcs->load_iram( 676 + dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2); 672 677 } else if (dmcu->dmcu_version.abm_version == 0x23) { 673 678 fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params); 674 679