1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "dce_abm.h"
27#include "dm_services.h"
28#include "reg_helper.h"
29#include "fixed32_32.h"
30#include "dc.h"
31
32#include "atom.h"
33
34
35#define TO_DCE_ABM(abm)\
36 container_of(abm, struct dce_abm, base)
37
38#define REG(reg) \
39 (abm_dce->regs->reg)
40
41#undef FN
42#define FN(reg_name, field_name) \
43 abm_dce->abm_shift->field_name, abm_dce->abm_mask->field_name
44
45#define CTX \
46 abm_dce->base.ctx
47
48#define MCP_ABM_LEVEL_SET 0x65
49#define MCP_ABM_PIPE_SET 0x66
50#define MCP_BL_SET 0x67
51
52#define MCP_DISABLE_ABM_IMMEDIATELY 255
53
54struct abm_backlight_registers {
55 unsigned int BL_PWM_CNTL;
56 unsigned int BL_PWM_CNTL2;
57 unsigned int BL_PWM_PERIOD_CNTL;
58 unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV;
59};
60
61
62static struct abm_backlight_registers stored_backlight_registers = {0};
63
64
65static unsigned int get_current_backlight_16_bit(struct dce_abm *abm_dce)
66{
67 uint64_t current_backlight;
68 uint32_t round_result;
69 uint32_t pwm_period_cntl, bl_period, bl_int_count;
70 uint32_t bl_pwm_cntl, bl_pwm, fractional_duty_cycle_en;
71 uint32_t bl_period_mask, bl_pwm_mask;
72
73 pwm_period_cntl = REG_READ(BL_PWM_PERIOD_CNTL);
74 REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period);
75 REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, &bl_int_count);
76
77 bl_pwm_cntl = REG_READ(BL_PWM_CNTL);
78 REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, (uint32_t *)(&bl_pwm));
79 REG_GET(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, &fractional_duty_cycle_en);
80
81 if (bl_int_count == 0)
82 bl_int_count = 16;
83
84 bl_period_mask = (1 << bl_int_count) - 1;
85 bl_period &= bl_period_mask;
86
87 bl_pwm_mask = bl_period_mask << (16 - bl_int_count);
88
89 if (fractional_duty_cycle_en == 0)
90 bl_pwm &= bl_pwm_mask;
91 else
92 bl_pwm &= 0xFFFF;
93
94 current_backlight = bl_pwm << (1 + bl_int_count);
95
96 if (bl_period == 0)
97 bl_period = 0xFFFF;
98
99 current_backlight = div_u64(current_backlight, bl_period);
100 current_backlight = (current_backlight + 1) >> 1;
101
102 current_backlight = (uint64_t)(current_backlight) * bl_period;
103
104 round_result = (uint32_t)(current_backlight & 0xFFFFFFFF);
105
106 round_result = (round_result >> (bl_int_count-1)) & 1;
107
108 current_backlight >>= bl_int_count;
109 current_backlight += round_result;
110
111 return (uint32_t)(current_backlight);
112}
113
114static void driver_set_backlight_level(struct dce_abm *abm_dce, uint32_t level)
115{
116 uint32_t backlight_24bit;
117 uint32_t backlight_17bit;
118 uint32_t backlight_16bit;
119 uint32_t masked_pwm_period;
120 uint8_t rounding_bit;
121 uint8_t bit_count;
122 uint64_t active_duty_cycle;
123 uint32_t pwm_period_bitcnt;
124
125
126
127
128
129
130
131
132
133
134 backlight_24bit = level * 0x10101;
135
136
137
138
139
140 rounding_bit = (backlight_24bit >> 7) & 1;
141
142
143
144
145 backlight_17bit = (backlight_24bit >> 8) + rounding_bit;
146
147
148
149
150
151
152
153
154 REG_GET_2(BL_PWM_PERIOD_CNTL,
155 BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt,
156 BL_PWM_PERIOD, &masked_pwm_period);
157
158 if (pwm_period_bitcnt == 0)
159 bit_count = 16;
160 else
161 bit_count = pwm_period_bitcnt;
162
163
164 masked_pwm_period = masked_pwm_period & ((1 << bit_count) - 1);
165
166
167
168
169
170 active_duty_cycle = backlight_17bit * masked_pwm_period;
171
172
173
174
175
176 backlight_16bit = active_duty_cycle >> bit_count;
177 backlight_16bit &= 0xFFFF;
178 backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1;
179
180
181
182
183
184
185
186 REG_UPDATE_2(BL_PWM_GRP1_REG_LOCK,
187 BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1,
188 BL_PWM_GRP1_REG_LOCK, 1);
189
190
191 REG_UPDATE(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, backlight_16bit);
192
193
194 REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
195 BL_PWM_GRP1_REG_LOCK, 0);
196
197
198 REG_WAIT(BL_PWM_GRP1_REG_LOCK,
199 BL_PWM_GRP1_REG_UPDATE_PENDING, 0,
200 1, 10000);
201}
202
203static void dmcu_set_backlight_level(
204 struct dce_abm *abm_dce,
205 uint32_t level,
206 uint32_t frame_ramp,
207 uint32_t controller_id)
208{
209 unsigned int backlight_16_bit = (level * 0x10101) >> 8;
210 unsigned int backlight_17_bit = backlight_16_bit +
211 (((backlight_16_bit & 0x80) >> 7) & 1);
212 uint32_t rampingBoundary = 0xFFFF;
213 uint32_t s2;
214
215
216 REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary);
217
218
219 REG_UPDATE_2(MASTER_COMM_CMD_REG,
220 MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET,
221 MASTER_COMM_CMD_REG_BYTE1, controller_id);
222
223
224 REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
225
226
227 REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT,
228 0, 1, 80000);
229
230
231 REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17_bit);
232
233
234 if (controller_id == 0)
235 frame_ramp = 0;
236 REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp);
237
238
239 REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET);
240
241
242 REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
243
244
245 s2 = REG_READ(BIOS_SCRATCH_2);
246
247 s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
248 level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >>
249 ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
250 s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
251
252 REG_WRITE(BIOS_SCRATCH_2, s2);
253}
254
255static void dce_abm_init(struct abm *abm)
256{
257 struct dce_abm *abm_dce = TO_DCE_ABM(abm);
258 unsigned int backlight = get_current_backlight_16_bit(abm_dce);
259
260 REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103);
261 REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101);
262 REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x103);
263 REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x101);
264 REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x101);
265
266 REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0,
267 ABM1_HG_NUM_OF_BINS_SEL, 0,
268 ABM1_HG_VMAX_SEL, 1,
269 ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0);
270
271 REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0,
272 ABM1_IPCSC_COEFF_SEL_R, 2,
273 ABM1_IPCSC_COEFF_SEL_G, 4,
274 ABM1_IPCSC_COEFF_SEL_B, 2);
275
276 REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL,
277 BL1_PWM_CURRENT_ABM_LEVEL, backlight);
278
279 REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL,
280 BL1_PWM_TARGET_ABM_LEVEL, backlight);
281
282 REG_UPDATE(BL1_PWM_USER_LEVEL,
283 BL1_PWM_USER_LEVEL, backlight);
284
285 REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
286 ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
287 ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000);
288
289 REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0,
290 ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1,
291 ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1,
292 ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1);
293}
294
295static unsigned int dce_abm_get_current_backlight_8_bit(struct abm *abm)
296{
297 struct dce_abm *abm_dce = TO_DCE_ABM(abm);
298 unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
299
300 return (backlight >> 8);
301}
302
303static bool dce_abm_set_level(struct abm *abm, uint32_t level)
304{
305 struct dce_abm *abm_dce = TO_DCE_ABM(abm);
306
307 REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
308 1, 80000);
309
310
311 REG_UPDATE_2(MASTER_COMM_CMD_REG,
312 MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET,
313 MASTER_COMM_CMD_REG_BYTE2, level);
314
315
316 REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
317
318 return true;
319}
320
321static bool dce_abm_immediate_disable(struct abm *abm)
322{
323 struct dce_abm *abm_dce = TO_DCE_ABM(abm);
324
325 REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
326 1, 80000);
327
328
329 REG_UPDATE_2(MASTER_COMM_CMD_REG,
330 MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET,
331 MASTER_COMM_CMD_REG_BYTE2, MCP_DISABLE_ABM_IMMEDIATELY);
332
333
334 REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
335
336 return true;
337}
338
339static bool dce_abm_init_backlight(struct abm *abm)
340{
341 struct dce_abm *abm_dce = TO_DCE_ABM(abm);
342 uint32_t value;
343
344
345
346
347
348 REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value);
349 if (value == 0 || value == 1) {
350 if (stored_backlight_registers.BL_PWM_CNTL != 0) {
351 REG_WRITE(BL_PWM_CNTL,
352 stored_backlight_registers.BL_PWM_CNTL);
353 REG_WRITE(BL_PWM_CNTL2,
354 stored_backlight_registers.BL_PWM_CNTL2);
355 REG_WRITE(BL_PWM_PERIOD_CNTL,
356 stored_backlight_registers.BL_PWM_PERIOD_CNTL);
357 REG_UPDATE(LVTMA_PWRSEQ_REF_DIV,
358 BL_PWM_REF_DIV,
359 stored_backlight_registers.
360 LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
361 } else {
362
363
364
365 REG_WRITE(BL_PWM_CNTL, 0xC000FA00);
366 REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0);
367 }
368 } else {
369 stored_backlight_registers.BL_PWM_CNTL =
370 REG_READ(BL_PWM_CNTL);
371 stored_backlight_registers.BL_PWM_CNTL2 =
372 REG_READ(BL_PWM_CNTL2);
373 stored_backlight_registers.BL_PWM_PERIOD_CNTL =
374 REG_READ(BL_PWM_PERIOD_CNTL);
375
376 REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV,
377 &stored_backlight_registers.
378 LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
379 }
380
381
382
383
384 value = REG_READ(BIOS_SCRATCH_2);
385 value |= ATOM_S2_VRI_BRIGHT_ENABLE;
386 REG_WRITE(BIOS_SCRATCH_2, value);
387
388
389 REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1);
390
391
392 REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
393 BL_PWM_GRP1_REG_LOCK, 0);
394
395 return true;
396}
397
398static bool is_dmcu_initialized(struct abm *abm)
399{
400 struct dce_abm *abm_dce = TO_DCE_ABM(abm);
401 unsigned int dmcu_uc_reset;
402
403 REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset);
404
405 return !dmcu_uc_reset;
406}
407
408static bool dce_abm_set_backlight_level(
409 struct abm *abm,
410 unsigned int backlight_level,
411 unsigned int frame_ramp,
412 unsigned int controller_id)
413{
414 struct dce_abm *abm_dce = TO_DCE_ABM(abm);
415
416 dm_logger_write(abm->ctx->logger, LOG_BACKLIGHT,
417 "New Backlight level: %d (0x%X)\n",
418 backlight_level, backlight_level);
419
420
421 if (is_dmcu_initialized(abm))
422 dmcu_set_backlight_level(abm_dce,
423 backlight_level,
424 frame_ramp,
425 controller_id);
426 else
427 driver_set_backlight_level(abm_dce, backlight_level);
428
429 return true;
430}
431
432static const struct abm_funcs dce_funcs = {
433 .abm_init = dce_abm_init,
434 .set_abm_level = dce_abm_set_level,
435 .init_backlight = dce_abm_init_backlight,
436 .set_backlight_level = dce_abm_set_backlight_level,
437 .get_current_backlight_8_bit = dce_abm_get_current_backlight_8_bit,
438 .set_abm_immediate_disable = dce_abm_immediate_disable,
439 .is_dmcu_initialized = is_dmcu_initialized
440};
441
442static void dce_abm_construct(
443 struct dce_abm *abm_dce,
444 struct dc_context *ctx,
445 const struct dce_abm_registers *regs,
446 const struct dce_abm_shift *abm_shift,
447 const struct dce_abm_mask *abm_mask)
448{
449 struct abm *base = &abm_dce->base;
450
451 base->ctx = ctx;
452 base->funcs = &dce_funcs;
453
454 abm_dce->regs = regs;
455 abm_dce->abm_shift = abm_shift;
456 abm_dce->abm_mask = abm_mask;
457}
458
459struct abm *dce_abm_create(
460 struct dc_context *ctx,
461 const struct dce_abm_registers *regs,
462 const struct dce_abm_shift *abm_shift,
463 const struct dce_abm_mask *abm_mask)
464{
465 struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL);
466
467 if (abm_dce == NULL) {
468 BREAK_TO_DEBUGGER();
469 return NULL;
470 }
471
472 dce_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask);
473
474 abm_dce->base.funcs = &dce_funcs;
475
476 return &abm_dce->base;
477}
478
479void dce_abm_destroy(struct abm **abm)
480{
481 struct dce_abm *abm_dce = TO_DCE_ABM(*abm);
482
483 kfree(abm_dce);
484 *abm = NULL;
485}
486