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 void dmub_abm_enable_fractional_pwm(struct dc_context *dc)
261 {
262 	union dmub_rb_cmd cmd;
263 	uint32_t fractional_pwm = (dc->dc->config.disable_fractional_pwm == false) ? 1 : 0;
264 
265 	cmd.abm_set_pwm_frac.header.type = DMUB_CMD__ABM;
266 	cmd.abm_set_pwm_frac.header.sub_type = DMUB_CMD__ABM_SET_PWM_FRAC;
267 	cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.fractional_pwm = fractional_pwm;
268 	cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data);
269 
270 	dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.abm_set_pwm_frac.header);
271 	dc_dmub_srv_cmd_execute(dc->dmub_srv);
272 	dc_dmub_srv_wait_idle(dc->dmub_srv);
273 }
274 
275 static bool dmub_abm_init_backlight(struct abm *abm)
276 {
277 	struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
278 	uint32_t value;
279 
280 	dmub_abm_enable_fractional_pwm(abm->ctx);
281 
282 	/* It must not be 0, so we have to restore them
283 	 * Bios bug w/a - period resets to zero,
284 	 * restoring to cache values which is always correct
285 	 */
286 	REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value);
287 
288 	if (value == 0 || value == 1) {
289 		if (abm->stored_backlight_registers.BL_PWM_CNTL != 0) {
290 			REG_WRITE(BL_PWM_CNTL,
291 				abm->stored_backlight_registers.BL_PWM_CNTL);
292 			REG_WRITE(BL_PWM_CNTL2,
293 				abm->stored_backlight_registers.BL_PWM_CNTL2);
294 			REG_WRITE(BL_PWM_PERIOD_CNTL,
295 				abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL);
296 			REG_UPDATE(LVTMA_PWRSEQ_REF_DIV,
297 				BL_PWM_REF_DIV,
298 				abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
299 		} else {
300 			/* TODO: Note: This should not really happen since VBIOS
301 			 * should have initialized PWM registers on boot.
302 			 */
303 			REG_WRITE(BL_PWM_CNTL, 0xC000FA00);
304 			REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0);
305 		}
306 	} else {
307 		abm->stored_backlight_registers.BL_PWM_CNTL =
308 				REG_READ(BL_PWM_CNTL);
309 		abm->stored_backlight_registers.BL_PWM_CNTL2 =
310 				REG_READ(BL_PWM_CNTL2);
311 		abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL =
312 				REG_READ(BL_PWM_PERIOD_CNTL);
313 
314 		REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV,
315 				&abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
316 	}
317 
318 	// Have driver take backlight control
319 	// TakeBacklightControl(true)
320 	value = REG_READ(BIOS_SCRATCH_2);
321 	value |= ATOM_S2_VRI_BRIGHT_ENABLE;
322 	REG_WRITE(BIOS_SCRATCH_2, value);
323 
324 	// Enable the backlight output
325 	REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1);
326 
327 	// Unlock group 2 backlight registers
328 	REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
329 			BL_PWM_GRP1_REG_LOCK, 0);
330 
331 	return true;
332 }
333 
334 static bool dmub_abm_set_backlight_level_pwm(
335 		struct abm *abm,
336 		unsigned int backlight_pwm_u16_16,
337 		unsigned int frame_ramp,
338 		unsigned int otg_inst,
339 		bool use_smooth_brightness)
340 {
341 	struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
342 
343 	dmcub_set_backlight_level(dce_abm,
344 			backlight_pwm_u16_16,
345 			frame_ramp,
346 			otg_inst);
347 
348 	return true;
349 }
350 
351 static bool dmub_abm_init_config(struct abm *abm,
352 	const char *src,
353 	unsigned int bytes)
354 {
355 	union dmub_rb_cmd cmd;
356 	struct dc_context *dc = abm->ctx;
357 
358 	// TODO: Optimize by only reading back final 4 bytes
359 	dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb);
360 
361 	// Copy iramtable into cw7
362 	memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)src, bytes);
363 
364 	// Fw will copy from cw7 to fw_state
365 	cmd.abm_init_config.header.type = DMUB_CMD__ABM;
366 	cmd.abm_init_config.header.sub_type = DMUB_CMD__ABM_INIT_CONFIG;
367 	cmd.abm_init_config.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr;
368 	cmd.abm_init_config.abm_init_config_data.bytes = bytes;
369 	cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data);
370 
371 	dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.abm_init_config.header);
372 	dc_dmub_srv_cmd_execute(dc->dmub_srv);
373 	dc_dmub_srv_wait_idle(dc->dmub_srv);
374 
375 	return true;
376 }
377 
378 static const struct abm_funcs abm_funcs = {
379 	.abm_init = dmub_abm_init,
380 	.set_abm_level = dmub_abm_set_level,
381 	.init_backlight = dmub_abm_init_backlight,
382 	.set_pipe = dmub_abm_set_pipe,
383 	.set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm,
384 	.get_current_backlight = dmub_abm_get_current_backlight,
385 	.get_target_backlight = dmub_abm_get_target_backlight,
386 	.set_abm_immediate_disable = dmub_abm_immediate_disable,
387 	.init_abm_config = dmub_abm_init_config,
388 };
389 
390 static void dmub_abm_construct(
391 	struct dce_abm *abm_dce,
392 	struct dc_context *ctx,
393 	const struct dce_abm_registers *regs,
394 	const struct dce_abm_shift *abm_shift,
395 	const struct dce_abm_mask *abm_mask)
396 {
397 	struct abm *base = &abm_dce->base;
398 
399 	base->ctx = ctx;
400 	base->funcs = &abm_funcs;
401 	base->stored_backlight_registers.BL_PWM_CNTL = 0;
402 	base->stored_backlight_registers.BL_PWM_CNTL2 = 0;
403 	base->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 0;
404 	base->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = 0;
405 	base->dmcu_is_running = false;
406 
407 	abm_dce->regs = regs;
408 	abm_dce->abm_shift = abm_shift;
409 	abm_dce->abm_mask = abm_mask;
410 }
411 
412 struct abm *dmub_abm_create(
413 	struct dc_context *ctx,
414 	const struct dce_abm_registers *regs,
415 	const struct dce_abm_shift *abm_shift,
416 	const struct dce_abm_mask *abm_mask)
417 {
418 	struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL);
419 
420 	if (abm_dce == NULL) {
421 		BREAK_TO_DEBUGGER();
422 		return NULL;
423 	}
424 
425 	dmub_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask);
426 
427 	return &abm_dce->base;
428 }
429 
430 void dmub_abm_destroy(struct abm **abm)
431 {
432 	struct dce_abm *abm_dce = TO_DMUB_ABM(*abm);
433 
434 	kfree(abm_dce);
435 	*abm = NULL;
436 }
437