]>
Commit | Line | Data |
---|---|---|
5e7773a2 AK |
1 | /* |
2 | * Copyright 2012-16 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 "dce_abm.h" | |
27 | #include "dm_services.h" | |
28 | #include "reg_helper.h" | |
eb0e5154 | 29 | #include "fixed31_32.h" |
5e7773a2 AK |
30 | #include "dc.h" |
31 | ||
6728b30c AK |
32 | #include "atom.h" |
33 | ||
34 | ||
5e7773a2 AK |
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 | ||
1296423b BL |
45 | #define DC_LOGGER \ |
46 | abm->ctx->logger | |
5e7773a2 AK |
47 | #define CTX \ |
48 | abm_dce->base.ctx | |
49 | ||
50 | #define MCP_ABM_LEVEL_SET 0x65 | |
6728b30c AK |
51 | #define MCP_ABM_PIPE_SET 0x66 |
52 | #define MCP_BL_SET 0x67 | |
53 | ||
aa7397df AZ |
54 | #define MCP_DISABLE_ABM_IMMEDIATELY 255 |
55 | ||
5e7773a2 | 56 | |
262485a5 | 57 | static unsigned int calculate_16_bit_backlight_from_pwm(struct dce_abm *abm_dce) |
5e7773a2 AK |
58 | { |
59 | uint64_t current_backlight; | |
60 | uint32_t round_result; | |
61 | uint32_t pwm_period_cntl, bl_period, bl_int_count; | |
62 | uint32_t bl_pwm_cntl, bl_pwm, fractional_duty_cycle_en; | |
63 | uint32_t bl_period_mask, bl_pwm_mask; | |
64 | ||
65 | pwm_period_cntl = REG_READ(BL_PWM_PERIOD_CNTL); | |
66 | REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period); | |
67 | REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, &bl_int_count); | |
68 | ||
69 | bl_pwm_cntl = REG_READ(BL_PWM_CNTL); | |
70 | REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, (uint32_t *)(&bl_pwm)); | |
71 | REG_GET(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, &fractional_duty_cycle_en); | |
72 | ||
73 | if (bl_int_count == 0) | |
74 | bl_int_count = 16; | |
75 | ||
76 | bl_period_mask = (1 << bl_int_count) - 1; | |
77 | bl_period &= bl_period_mask; | |
78 | ||
79 | bl_pwm_mask = bl_period_mask << (16 - bl_int_count); | |
80 | ||
81 | if (fractional_duty_cycle_en == 0) | |
82 | bl_pwm &= bl_pwm_mask; | |
83 | else | |
84 | bl_pwm &= 0xFFFF; | |
85 | ||
86 | current_backlight = bl_pwm << (1 + bl_int_count); | |
87 | ||
88 | if (bl_period == 0) | |
89 | bl_period = 0xFFFF; | |
90 | ||
ca709397 | 91 | current_backlight = div_u64(current_backlight, bl_period); |
5e7773a2 AK |
92 | current_backlight = (current_backlight + 1) >> 1; |
93 | ||
94 | current_backlight = (uint64_t)(current_backlight) * bl_period; | |
95 | ||
96 | round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); | |
97 | ||
98 | round_result = (round_result >> (bl_int_count-1)) & 1; | |
99 | ||
100 | current_backlight >>= bl_int_count; | |
101 | current_backlight += round_result; | |
102 | ||
103 | return (uint32_t)(current_backlight); | |
104 | } | |
105 | ||
262485a5 AK |
106 | static void driver_set_backlight_level(struct dce_abm *abm_dce, |
107 | uint32_t backlight_pwm_u16_16) | |
6728b30c | 108 | { |
6728b30c AK |
109 | uint32_t backlight_16bit; |
110 | uint32_t masked_pwm_period; | |
6728b30c AK |
111 | uint8_t bit_count; |
112 | uint64_t active_duty_cycle; | |
113 | uint32_t pwm_period_bitcnt; | |
114 | ||
115 | /* | |
262485a5 | 116 | * 1. Find 16 bit backlight active duty cycle, where 0 <= backlight |
6728b30c AK |
117 | * active duty cycle <= backlight period |
118 | */ | |
119 | ||
262485a5 | 120 | /* 1.1 Apply bitmask for backlight period value based on value of BITCNT |
6728b30c AK |
121 | */ |
122 | REG_GET_2(BL_PWM_PERIOD_CNTL, | |
123 | BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt, | |
124 | BL_PWM_PERIOD, &masked_pwm_period); | |
125 | ||
126 | if (pwm_period_bitcnt == 0) | |
127 | bit_count = 16; | |
128 | else | |
129 | bit_count = pwm_period_bitcnt; | |
130 | ||
131 | /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ | |
132 | masked_pwm_period = masked_pwm_period & ((1 << bit_count) - 1); | |
133 | ||
262485a5 | 134 | /* 1.2 Calculate integer active duty cycle required upper 16 bits |
6728b30c AK |
135 | * contain integer component, lower 16 bits contain fractional component |
136 | * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 | |
137 | */ | |
262485a5 | 138 | active_duty_cycle = backlight_pwm_u16_16 * masked_pwm_period; |
6728b30c | 139 | |
262485a5 | 140 | /* 1.3 Calculate 16 bit active duty cycle from integer and fractional |
6728b30c AK |
141 | * components shift by bitCount then mask 16 bits and add rounding bit |
142 | * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 | |
143 | */ | |
144 | backlight_16bit = active_duty_cycle >> bit_count; | |
145 | backlight_16bit &= 0xFFFF; | |
146 | backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; | |
147 | ||
148 | /* | |
262485a5 | 149 | * 2. Program register with updated value |
6728b30c AK |
150 | */ |
151 | ||
262485a5 | 152 | /* 2.1 Lock group 2 backlight registers */ |
6728b30c AK |
153 | |
154 | REG_UPDATE_2(BL_PWM_GRP1_REG_LOCK, | |
155 | BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1, | |
156 | BL_PWM_GRP1_REG_LOCK, 1); | |
157 | ||
262485a5 | 158 | // 2.2 Write new active duty cycle |
6728b30c AK |
159 | REG_UPDATE(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, backlight_16bit); |
160 | ||
262485a5 | 161 | /* 2.3 Unlock group 2 backlight registers */ |
6728b30c AK |
162 | REG_UPDATE(BL_PWM_GRP1_REG_LOCK, |
163 | BL_PWM_GRP1_REG_LOCK, 0); | |
164 | ||
262485a5 | 165 | /* 3 Wait for pending bit to be cleared */ |
8a5d8245 TC |
166 | REG_WAIT(BL_PWM_GRP1_REG_LOCK, |
167 | BL_PWM_GRP1_REG_UPDATE_PENDING, 0, | |
168 | 1, 10000); | |
6728b30c AK |
169 | } |
170 | ||
171 | static void dmcu_set_backlight_level( | |
172 | struct dce_abm *abm_dce, | |
262485a5 | 173 | uint32_t backlight_pwm_u16_16, |
6728b30c AK |
174 | uint32_t frame_ramp, |
175 | uint32_t controller_id) | |
176 | { | |
262485a5 | 177 | unsigned int backlight_8_bit = 0; |
6728b30c AK |
178 | uint32_t rampingBoundary = 0xFFFF; |
179 | uint32_t s2; | |
180 | ||
262485a5 AK |
181 | if (backlight_pwm_u16_16 & 0x10000) |
182 | // Check for max backlight condition | |
183 | backlight_8_bit = 0xFF; | |
184 | else | |
185 | // Take MSB of fractional part since backlight is not max | |
186 | backlight_8_bit = (backlight_pwm_u16_16 >> 8) & 0xFF; | |
187 | ||
6728b30c AK |
188 | /* set ramping boundary */ |
189 | REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary); | |
190 | ||
191 | /* setDMCUParam_Pipe */ | |
192 | REG_UPDATE_2(MASTER_COMM_CMD_REG, | |
193 | MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET, | |
194 | MASTER_COMM_CMD_REG_BYTE1, controller_id); | |
195 | ||
196 | /* notifyDMCUMsg */ | |
197 | REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); | |
198 | ||
199 | /* waitDMCUReadyForCmd */ | |
200 | REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, | |
8a5d8245 | 201 | 0, 1, 80000); |
6728b30c AK |
202 | |
203 | /* setDMCUParam_BL */ | |
262485a5 | 204 | REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_pwm_u16_16); |
6728b30c AK |
205 | |
206 | /* write ramp */ | |
207 | if (controller_id == 0) | |
208 | frame_ramp = 0; | |
209 | REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp); | |
210 | ||
211 | /* setDMCUParam_Cmd */ | |
212 | REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET); | |
213 | ||
214 | /* notifyDMCUMsg */ | |
215 | REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); | |
216 | ||
217 | /* UpdateRequestedBacklightLevel */ | |
218 | s2 = REG_READ(BIOS_SCRATCH_2); | |
219 | ||
220 | s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; | |
262485a5 | 221 | backlight_8_bit &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >> |
6728b30c | 222 | ATOM_S2_CURRENT_BL_LEVEL_SHIFT); |
262485a5 | 223 | s2 |= (backlight_8_bit << ATOM_S2_CURRENT_BL_LEVEL_SHIFT); |
6728b30c AK |
224 | |
225 | REG_WRITE(BIOS_SCRATCH_2, s2); | |
226 | } | |
227 | ||
228 | static void dce_abm_init(struct abm *abm) | |
5e7773a2 AK |
229 | { |
230 | struct dce_abm *abm_dce = TO_DCE_ABM(abm); | |
262485a5 | 231 | unsigned int backlight = calculate_16_bit_backlight_from_pwm(abm_dce); |
5e7773a2 AK |
232 | |
233 | REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103); | |
234 | REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101); | |
235 | REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x103); | |
236 | REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x101); | |
237 | REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x101); | |
238 | ||
239 | REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0, | |
240 | ABM1_HG_NUM_OF_BINS_SEL, 0, | |
241 | ABM1_HG_VMAX_SEL, 1, | |
242 | ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0); | |
243 | ||
244 | REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0, | |
245 | ABM1_IPCSC_COEFF_SEL_R, 2, | |
246 | ABM1_IPCSC_COEFF_SEL_G, 4, | |
247 | ABM1_IPCSC_COEFF_SEL_B, 2); | |
248 | ||
249 | REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL, | |
250 | BL1_PWM_CURRENT_ABM_LEVEL, backlight); | |
251 | ||
252 | REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL, | |
253 | BL1_PWM_TARGET_ABM_LEVEL, backlight); | |
254 | ||
255 | REG_UPDATE(BL1_PWM_USER_LEVEL, | |
256 | BL1_PWM_USER_LEVEL, backlight); | |
257 | ||
258 | REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, | |
259 | ABM1_LS_MIN_PIXEL_VALUE_THRES, 0, | |
260 | ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000); | |
261 | ||
262 | REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0, | |
263 | ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1, | |
264 | ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1, | |
265 | ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); | |
266 | } | |
267 | ||
262485a5 | 268 | static unsigned int dce_abm_get_current_backlight(struct abm *abm) |
fe626734 AK |
269 | { |
270 | struct dce_abm *abm_dce = TO_DCE_ABM(abm); | |
271 | unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL); | |
272 | ||
262485a5 AK |
273 | /* return backlight in hardware format which is unsigned 17 bits, with |
274 | * 1 bit integer and 16 bit fractional | |
275 | */ | |
276 | return backlight; | |
fe626734 AK |
277 | } |
278 | ||
ba45df4c AK |
279 | static unsigned int dce_abm_get_target_backlight(struct abm *abm) |
280 | { | |
281 | struct dce_abm *abm_dce = TO_DCE_ABM(abm); | |
282 | unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL); | |
283 | ||
284 | /* return backlight in hardware format which is unsigned 17 bits, with | |
285 | * 1 bit integer and 16 bit fractional | |
286 | */ | |
287 | return backlight; | |
288 | } | |
289 | ||
6728b30c | 290 | static bool dce_abm_set_level(struct abm *abm, uint32_t level) |
5e7773a2 AK |
291 | { |
292 | struct dce_abm *abm_dce = TO_DCE_ABM(abm); | |
5e7773a2 | 293 | |
6728b30c | 294 | REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, |
8a5d8245 | 295 | 1, 80000); |
5e7773a2 AK |
296 | |
297 | /* setDMCUParam_ABMLevel */ | |
298 | REG_UPDATE_2(MASTER_COMM_CMD_REG, | |
299 | MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, | |
300 | MASTER_COMM_CMD_REG_BYTE2, level); | |
301 | ||
302 | /* notifyDMCUMsg */ | |
303 | REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); | |
304 | ||
305 | return true; | |
306 | } | |
307 | ||
aa7397df AZ |
308 | static bool dce_abm_immediate_disable(struct abm *abm) |
309 | { | |
310 | struct dce_abm *abm_dce = TO_DCE_ABM(abm); | |
311 | ||
312 | REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, | |
8a5d8245 | 313 | 1, 80000); |
aa7397df AZ |
314 | |
315 | /* setDMCUParam_ABMLevel */ | |
316 | REG_UPDATE_2(MASTER_COMM_CMD_REG, | |
22d7663f PH |
317 | MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET, |
318 | MASTER_COMM_CMD_REG_BYTE1, MCP_DISABLE_ABM_IMMEDIATELY); | |
aa7397df AZ |
319 | |
320 | /* notifyDMCUMsg */ | |
321 | REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); | |
322 | ||
c3b1c061 CL |
323 | abm->stored_backlight_registers.BL_PWM_CNTL = |
324 | REG_READ(BL_PWM_CNTL); | |
325 | abm->stored_backlight_registers.BL_PWM_CNTL2 = | |
326 | REG_READ(BL_PWM_CNTL2); | |
327 | abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL = | |
328 | REG_READ(BL_PWM_PERIOD_CNTL); | |
329 | ||
330 | REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, | |
331 | &abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); | |
aa7397df AZ |
332 | return true; |
333 | } | |
334 | ||
6728b30c AK |
335 | static bool dce_abm_init_backlight(struct abm *abm) |
336 | { | |
337 | struct dce_abm *abm_dce = TO_DCE_ABM(abm); | |
338 | uint32_t value; | |
339 | ||
340 | /* It must not be 0, so we have to restore them | |
341 | * Bios bug w/a - period resets to zero, | |
342 | * restoring to cache values which is always correct | |
343 | */ | |
344 | REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); | |
345 | if (value == 0 || value == 1) { | |
404dfe1c | 346 | if (abm->stored_backlight_registers.BL_PWM_CNTL != 0) { |
6728b30c | 347 | REG_WRITE(BL_PWM_CNTL, |
404dfe1c | 348 | abm->stored_backlight_registers.BL_PWM_CNTL); |
6728b30c | 349 | REG_WRITE(BL_PWM_CNTL2, |
404dfe1c | 350 | abm->stored_backlight_registers.BL_PWM_CNTL2); |
6728b30c | 351 | REG_WRITE(BL_PWM_PERIOD_CNTL, |
404dfe1c | 352 | abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL); |
6728b30c AK |
353 | REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, |
354 | BL_PWM_REF_DIV, | |
404dfe1c | 355 | abm->stored_backlight_registers. |
6728b30c AK |
356 | LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); |
357 | } else { | |
358 | /* TODO: Note: This should not really happen since VBIOS | |
359 | * should have initialized PWM registers on boot. | |
360 | */ | |
361 | REG_WRITE(BL_PWM_CNTL, 0xC000FA00); | |
362 | REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); | |
363 | } | |
364 | } else { | |
404dfe1c | 365 | abm->stored_backlight_registers.BL_PWM_CNTL = |
6728b30c | 366 | REG_READ(BL_PWM_CNTL); |
404dfe1c | 367 | abm->stored_backlight_registers.BL_PWM_CNTL2 = |
6728b30c | 368 | REG_READ(BL_PWM_CNTL2); |
404dfe1c | 369 | abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL = |
6728b30c AK |
370 | REG_READ(BL_PWM_PERIOD_CNTL); |
371 | ||
372 | REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, | |
404dfe1c | 373 | &abm->stored_backlight_registers. |
6728b30c AK |
374 | LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); |
375 | } | |
376 | ||
377 | /* Have driver take backlight control | |
378 | * TakeBacklightControl(true) | |
379 | */ | |
380 | value = REG_READ(BIOS_SCRATCH_2); | |
381 | value |= ATOM_S2_VRI_BRIGHT_ENABLE; | |
382 | REG_WRITE(BIOS_SCRATCH_2, value); | |
383 | ||
384 | /* Enable the backlight output */ | |
385 | REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); | |
386 | ||
387 | /* Unlock group 2 backlight registers */ | |
388 | REG_UPDATE(BL_PWM_GRP1_REG_LOCK, | |
389 | BL_PWM_GRP1_REG_LOCK, 0); | |
390 | ||
391 | return true; | |
392 | } | |
393 | ||
262485a5 | 394 | static bool dce_abm_set_backlight_level_pwm( |
6728b30c | 395 | struct abm *abm, |
262485a5 | 396 | unsigned int backlight_pwm_u16_16, |
6728b30c | 397 | unsigned int frame_ramp, |
23bfb331 AK |
398 | unsigned int controller_id, |
399 | bool use_smooth_brightness) | |
6728b30c AK |
400 | { |
401 | struct dce_abm *abm_dce = TO_DCE_ABM(abm); | |
6728b30c | 402 | |
1296423b | 403 | DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", |
262485a5 | 404 | backlight_pwm_u16_16, backlight_pwm_u16_16); |
6728b30c | 405 | |
6728b30c | 406 | /* If DMCU is in reset state, DMCU is uninitialized */ |
23bfb331 | 407 | if (use_smooth_brightness) |
6728b30c | 408 | dmcu_set_backlight_level(abm_dce, |
262485a5 | 409 | backlight_pwm_u16_16, |
6728b30c AK |
410 | frame_ramp, |
411 | controller_id); | |
15a27de2 | 412 | else |
262485a5 | 413 | driver_set_backlight_level(abm_dce, backlight_pwm_u16_16); |
6728b30c AK |
414 | |
415 | return true; | |
416 | } | |
417 | ||
5e7773a2 AK |
418 | static const struct abm_funcs dce_funcs = { |
419 | .abm_init = dce_abm_init, | |
420 | .set_abm_level = dce_abm_set_level, | |
6728b30c | 421 | .init_backlight = dce_abm_init_backlight, |
262485a5 AK |
422 | .set_backlight_level_pwm = dce_abm_set_backlight_level_pwm, |
423 | .get_current_backlight = dce_abm_get_current_backlight, | |
ba45df4c | 424 | .get_target_backlight = dce_abm_get_target_backlight, |
23bfb331 | 425 | .set_abm_immediate_disable = dce_abm_immediate_disable |
5e7773a2 AK |
426 | }; |
427 | ||
428 | static void dce_abm_construct( | |
429 | struct dce_abm *abm_dce, | |
430 | struct dc_context *ctx, | |
431 | const struct dce_abm_registers *regs, | |
432 | const struct dce_abm_shift *abm_shift, | |
433 | const struct dce_abm_mask *abm_mask) | |
434 | { | |
435 | struct abm *base = &abm_dce->base; | |
436 | ||
437 | base->ctx = ctx; | |
438 | base->funcs = &dce_funcs; | |
404dfe1c AK |
439 | base->stored_backlight_registers.BL_PWM_CNTL = 0; |
440 | base->stored_backlight_registers.BL_PWM_CNTL2 = 0; | |
441 | base->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 0; | |
442 | base->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = 0; | |
5e7773a2 AK |
443 | |
444 | abm_dce->regs = regs; | |
445 | abm_dce->abm_shift = abm_shift; | |
446 | abm_dce->abm_mask = abm_mask; | |
447 | } | |
448 | ||
449 | struct abm *dce_abm_create( | |
450 | struct dc_context *ctx, | |
451 | const struct dce_abm_registers *regs, | |
452 | const struct dce_abm_shift *abm_shift, | |
453 | const struct dce_abm_mask *abm_mask) | |
454 | { | |
2004f45e | 455 | struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL); |
5e7773a2 AK |
456 | |
457 | if (abm_dce == NULL) { | |
458 | BREAK_TO_DEBUGGER(); | |
459 | return NULL; | |
460 | } | |
461 | ||
462 | dce_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask); | |
463 | ||
464 | abm_dce->base.funcs = &dce_funcs; | |
465 | ||
466 | return &abm_dce->base; | |
467 | } | |
468 | ||
469 | void dce_abm_destroy(struct abm **abm) | |
470 | { | |
471 | struct dce_abm *abm_dce = TO_DCE_ABM(*abm); | |
472 | ||
2004f45e | 473 | kfree(abm_dce); |
5e7773a2 AK |
474 | *abm = NULL; |
475 | } |