1 | /* |
2 | * Copyright 2012-15 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 "dm_services.h" |
27 | |
28 | /* include DCE11 register header files */ |
29 | #include "dce/dce_11_0_d.h" |
30 | #include "dce/dce_11_0_sh_mask.h" |
31 | |
32 | #include "dce110_transform_v.h" |
33 | |
34 | static void power_on_lut(struct transform *xfm, |
35 | bool power_on, bool inputgamma, bool regamma) |
36 | { |
37 | uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); |
38 | int i; |
39 | |
40 | if (power_on) { |
41 | if (inputgamma) |
42 | set_reg_field_value( |
43 | value, |
44 | 1, |
45 | DCFEV_MEM_PWR_CTRL, |
46 | COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); |
47 | if (regamma) |
48 | set_reg_field_value( |
49 | value, |
50 | 1, |
51 | DCFEV_MEM_PWR_CTRL, |
52 | COL_MAN_GAMMA_CORR_MEM_PWR_DIS); |
53 | } else { |
54 | if (inputgamma) |
55 | set_reg_field_value( |
56 | value, |
57 | 0, |
58 | DCFEV_MEM_PWR_CTRL, |
59 | COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); |
60 | if (regamma) |
61 | set_reg_field_value( |
62 | value, |
63 | 0, |
64 | DCFEV_MEM_PWR_CTRL, |
65 | COL_MAN_GAMMA_CORR_MEM_PWR_DIS); |
66 | } |
67 | |
68 | dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value); |
69 | |
70 | for (i = 0; i < 3; i++) { |
71 | value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); |
72 | if (get_reg_field_value(value, |
73 | DCFEV_MEM_PWR_CTRL, |
74 | COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) && |
75 | get_reg_field_value(value, |
76 | DCFEV_MEM_PWR_CTRL, |
77 | COL_MAN_GAMMA_CORR_MEM_PWR_DIS)) |
78 | break; |
79 | |
80 | udelay(2); |
81 | } |
82 | } |
83 | |
84 | static void set_bypass_input_gamma(struct dce_transform *xfm_dce) |
85 | { |
86 | uint32_t value; |
87 | |
88 | value = dm_read_reg(xfm_dce->base.ctx, |
89 | mmCOL_MAN_INPUT_GAMMA_CONTROL1); |
90 | |
91 | set_reg_field_value( |
92 | value, |
93 | 0, |
94 | COL_MAN_INPUT_GAMMA_CONTROL1, |
95 | INPUT_GAMMA_MODE); |
96 | |
97 | dm_write_reg(xfm_dce->base.ctx, |
98 | mmCOL_MAN_INPUT_GAMMA_CONTROL1, value); |
99 | } |
100 | |
101 | static void configure_regamma_mode(struct dce_transform *xfm_dce, uint32_t mode) |
102 | { |
103 | uint32_t value = 0; |
104 | |
105 | set_reg_field_value( |
106 | value, |
107 | mode, |
108 | GAMMA_CORR_CONTROL, |
109 | GAMMA_CORR_MODE); |
110 | |
111 | dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CONTROL, 0); |
112 | } |
113 | |
114 | /* |
115 | ***************************************************************************** |
116 | * Function: regamma_config_regions_and_segments |
117 | * |
118 | * build regamma curve by using predefined hw points |
119 | * uses interface parameters ,like EDID coeff. |
120 | * |
121 | * @param : parameters interface parameters |
122 | * @return void |
123 | * |
124 | * @note |
125 | * |
126 | * @see |
127 | * |
128 | ***************************************************************************** |
129 | */ |
130 | static void regamma_config_regions_and_segments( |
131 | struct dce_transform *xfm_dce, const struct pwl_params *params) |
132 | { |
133 | const struct gamma_curve *curve; |
134 | uint32_t value = 0; |
135 | |
136 | { |
137 | set_reg_field_value( |
138 | value, |
139 | params->arr_points[0].custom_float_x, |
140 | GAMMA_CORR_CNTLA_START_CNTL, |
141 | GAMMA_CORR_CNTLA_EXP_REGION_START); |
142 | |
143 | set_reg_field_value( |
144 | value, |
145 | 0, |
146 | GAMMA_CORR_CNTLA_START_CNTL, |
147 | GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT); |
148 | |
149 | dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL, |
150 | value); |
151 | } |
152 | { |
153 | value = 0; |
154 | set_reg_field_value( |
155 | value, |
156 | params->arr_points[0].custom_float_slope, |
157 | GAMMA_CORR_CNTLA_SLOPE_CNTL, |
158 | GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE); |
159 | |
160 | dm_write_reg(xfm_dce->base.ctx, |
161 | mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value); |
162 | } |
163 | { |
164 | value = 0; |
165 | set_reg_field_value( |
166 | value, |
167 | params->arr_points[1].custom_float_x, |
168 | GAMMA_CORR_CNTLA_END_CNTL1, |
169 | GAMMA_CORR_CNTLA_EXP_REGION_END); |
170 | |
171 | dm_write_reg(xfm_dce->base.ctx, |
172 | mmGAMMA_CORR_CNTLA_END_CNTL1, value); |
173 | } |
174 | { |
175 | value = 0; |
176 | set_reg_field_value( |
177 | value, |
178 | params->arr_points[1].custom_float_slope, |
179 | GAMMA_CORR_CNTLA_END_CNTL2, |
180 | GAMMA_CORR_CNTLA_EXP_REGION_END_BASE); |
181 | |
182 | set_reg_field_value( |
183 | value, |
184 | params->arr_points[1].custom_float_y, |
185 | GAMMA_CORR_CNTLA_END_CNTL2, |
186 | GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE); |
187 | |
188 | dm_write_reg(xfm_dce->base.ctx, |
189 | mmGAMMA_CORR_CNTLA_END_CNTL2, value); |
190 | } |
191 | |
192 | curve = params->arr_curve_points; |
193 | |
194 | { |
195 | value = 0; |
196 | set_reg_field_value( |
197 | value, |
198 | curve[0].offset, |
199 | GAMMA_CORR_CNTLA_REGION_0_1, |
200 | GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET); |
201 | |
202 | set_reg_field_value( |
203 | value, |
204 | curve[0].segments_num, |
205 | GAMMA_CORR_CNTLA_REGION_0_1, |
206 | GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS); |
207 | |
208 | set_reg_field_value( |
209 | value, |
210 | curve[1].offset, |
211 | GAMMA_CORR_CNTLA_REGION_0_1, |
212 | GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET); |
213 | |
214 | set_reg_field_value( |
215 | value, |
216 | curve[1].segments_num, |
217 | GAMMA_CORR_CNTLA_REGION_0_1, |
218 | GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS); |
219 | |
220 | dm_write_reg( |
221 | xfm_dce->base.ctx, |
222 | mmGAMMA_CORR_CNTLA_REGION_0_1, |
223 | value); |
224 | } |
225 | |
226 | curve += 2; |
227 | { |
228 | value = 0; |
229 | set_reg_field_value( |
230 | value, |
231 | curve[0].offset, |
232 | GAMMA_CORR_CNTLA_REGION_2_3, |
233 | GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET); |
234 | |
235 | set_reg_field_value( |
236 | value, |
237 | curve[0].segments_num, |
238 | GAMMA_CORR_CNTLA_REGION_2_3, |
239 | GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS); |
240 | |
241 | set_reg_field_value( |
242 | value, |
243 | curve[1].offset, |
244 | GAMMA_CORR_CNTLA_REGION_2_3, |
245 | GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET); |
246 | |
247 | set_reg_field_value( |
248 | value, |
249 | curve[1].segments_num, |
250 | GAMMA_CORR_CNTLA_REGION_2_3, |
251 | GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS); |
252 | |
253 | dm_write_reg(xfm_dce->base.ctx, |
254 | mmGAMMA_CORR_CNTLA_REGION_2_3, |
255 | value); |
256 | } |
257 | |
258 | curve += 2; |
259 | { |
260 | value = 0; |
261 | set_reg_field_value( |
262 | value, |
263 | curve[0].offset, |
264 | GAMMA_CORR_CNTLA_REGION_4_5, |
265 | GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET); |
266 | |
267 | set_reg_field_value( |
268 | value, |
269 | curve[0].segments_num, |
270 | GAMMA_CORR_CNTLA_REGION_4_5, |
271 | GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS); |
272 | |
273 | set_reg_field_value( |
274 | value, |
275 | curve[1].offset, |
276 | GAMMA_CORR_CNTLA_REGION_4_5, |
277 | GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET); |
278 | |
279 | set_reg_field_value( |
280 | value, |
281 | curve[1].segments_num, |
282 | GAMMA_CORR_CNTLA_REGION_4_5, |
283 | GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS); |
284 | |
285 | dm_write_reg(xfm_dce->base.ctx, |
286 | mmGAMMA_CORR_CNTLA_REGION_4_5, |
287 | value); |
288 | } |
289 | |
290 | curve += 2; |
291 | { |
292 | value = 0; |
293 | set_reg_field_value( |
294 | value, |
295 | curve[0].offset, |
296 | GAMMA_CORR_CNTLA_REGION_6_7, |
297 | GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET); |
298 | |
299 | set_reg_field_value( |
300 | value, |
301 | curve[0].segments_num, |
302 | GAMMA_CORR_CNTLA_REGION_6_7, |
303 | GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS); |
304 | |
305 | set_reg_field_value( |
306 | value, |
307 | curve[1].offset, |
308 | GAMMA_CORR_CNTLA_REGION_6_7, |
309 | GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET); |
310 | |
311 | set_reg_field_value( |
312 | value, |
313 | curve[1].segments_num, |
314 | GAMMA_CORR_CNTLA_REGION_6_7, |
315 | GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS); |
316 | |
317 | dm_write_reg(xfm_dce->base.ctx, |
318 | mmGAMMA_CORR_CNTLA_REGION_6_7, |
319 | value); |
320 | } |
321 | |
322 | curve += 2; |
323 | { |
324 | value = 0; |
325 | set_reg_field_value( |
326 | value, |
327 | curve[0].offset, |
328 | GAMMA_CORR_CNTLA_REGION_8_9, |
329 | GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET); |
330 | |
331 | set_reg_field_value( |
332 | value, |
333 | curve[0].segments_num, |
334 | GAMMA_CORR_CNTLA_REGION_8_9, |
335 | GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS); |
336 | |
337 | set_reg_field_value( |
338 | value, |
339 | curve[1].offset, |
340 | GAMMA_CORR_CNTLA_REGION_8_9, |
341 | GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET); |
342 | |
343 | set_reg_field_value( |
344 | value, |
345 | curve[1].segments_num, |
346 | GAMMA_CORR_CNTLA_REGION_8_9, |
347 | GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS); |
348 | |
349 | dm_write_reg(xfm_dce->base.ctx, |
350 | mmGAMMA_CORR_CNTLA_REGION_8_9, |
351 | value); |
352 | } |
353 | |
354 | curve += 2; |
355 | { |
356 | value = 0; |
357 | set_reg_field_value( |
358 | value, |
359 | curve[0].offset, |
360 | GAMMA_CORR_CNTLA_REGION_10_11, |
361 | GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET); |
362 | |
363 | set_reg_field_value( |
364 | value, |
365 | curve[0].segments_num, |
366 | GAMMA_CORR_CNTLA_REGION_10_11, |
367 | GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS); |
368 | |
369 | set_reg_field_value( |
370 | value, |
371 | curve[1].offset, |
372 | GAMMA_CORR_CNTLA_REGION_10_11, |
373 | GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET); |
374 | |
375 | set_reg_field_value( |
376 | value, |
377 | curve[1].segments_num, |
378 | GAMMA_CORR_CNTLA_REGION_10_11, |
379 | GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS); |
380 | |
381 | dm_write_reg(xfm_dce->base.ctx, |
382 | mmGAMMA_CORR_CNTLA_REGION_10_11, |
383 | value); |
384 | } |
385 | |
386 | curve += 2; |
387 | { |
388 | value = 0; |
389 | set_reg_field_value( |
390 | value, |
391 | curve[0].offset, |
392 | GAMMA_CORR_CNTLA_REGION_12_13, |
393 | GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET); |
394 | |
395 | set_reg_field_value( |
396 | value, |
397 | curve[0].segments_num, |
398 | GAMMA_CORR_CNTLA_REGION_12_13, |
399 | GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS); |
400 | |
401 | set_reg_field_value( |
402 | value, |
403 | curve[1].offset, |
404 | GAMMA_CORR_CNTLA_REGION_12_13, |
405 | GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET); |
406 | |
407 | set_reg_field_value( |
408 | value, |
409 | curve[1].segments_num, |
410 | GAMMA_CORR_CNTLA_REGION_12_13, |
411 | GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS); |
412 | |
413 | dm_write_reg(xfm_dce->base.ctx, |
414 | mmGAMMA_CORR_CNTLA_REGION_12_13, |
415 | value); |
416 | } |
417 | |
418 | curve += 2; |
419 | { |
420 | value = 0; |
421 | set_reg_field_value( |
422 | value, |
423 | curve[0].offset, |
424 | GAMMA_CORR_CNTLA_REGION_14_15, |
425 | GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET); |
426 | |
427 | set_reg_field_value( |
428 | value, |
429 | curve[0].segments_num, |
430 | GAMMA_CORR_CNTLA_REGION_14_15, |
431 | GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS); |
432 | |
433 | set_reg_field_value( |
434 | value, |
435 | curve[1].offset, |
436 | GAMMA_CORR_CNTLA_REGION_14_15, |
437 | GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET); |
438 | |
439 | set_reg_field_value( |
440 | value, |
441 | curve[1].segments_num, |
442 | GAMMA_CORR_CNTLA_REGION_14_15, |
443 | GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS); |
444 | |
445 | dm_write_reg(xfm_dce->base.ctx, |
446 | mmGAMMA_CORR_CNTLA_REGION_14_15, |
447 | value); |
448 | } |
449 | } |
450 | |
451 | static void program_pwl(struct dce_transform *xfm_dce, |
452 | const struct pwl_params *params) |
453 | { |
454 | uint32_t value = 0; |
455 | |
456 | set_reg_field_value( |
457 | value, |
458 | 7, |
459 | GAMMA_CORR_LUT_WRITE_EN_MASK, |
460 | GAMMA_CORR_LUT_WRITE_EN_MASK); |
461 | |
462 | dm_write_reg(xfm_dce->base.ctx, |
463 | mmGAMMA_CORR_LUT_WRITE_EN_MASK, value); |
464 | |
465 | dm_write_reg(xfm_dce->base.ctx, |
466 | mmGAMMA_CORR_LUT_INDEX, 0); |
467 | |
468 | /* Program REGAMMA_LUT_DATA */ |
469 | { |
470 | const uint32_t addr = mmGAMMA_CORR_LUT_DATA; |
471 | uint32_t i = 0; |
472 | const struct pwl_result_data *rgb = |
473 | params->rgb_resulted; |
474 | |
475 | while (i != params->hw_points_num) { |
476 | dm_write_reg(xfm_dce->base.ctx, addr, rgb->red_reg); |
477 | dm_write_reg(xfm_dce->base.ctx, addr, rgb->green_reg); |
478 | dm_write_reg(xfm_dce->base.ctx, addr, rgb->blue_reg); |
479 | |
480 | dm_write_reg(xfm_dce->base.ctx, addr, |
481 | rgb->delta_red_reg); |
482 | dm_write_reg(xfm_dce->base.ctx, addr, |
483 | rgb->delta_green_reg); |
484 | dm_write_reg(xfm_dce->base.ctx, addr, |
485 | rgb->delta_blue_reg); |
486 | |
487 | ++rgb; |
488 | ++i; |
489 | } |
490 | } |
491 | } |
492 | |
493 | void dce110_opp_program_regamma_pwl_v( |
494 | struct transform *xfm, |
495 | const struct pwl_params *params) |
496 | { |
497 | struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); |
498 | |
499 | /* Setup regions */ |
500 | regamma_config_regions_and_segments(xfm_dce, params); |
501 | |
502 | set_bypass_input_gamma(xfm_dce); |
503 | |
504 | /* Power on gamma LUT memory */ |
505 | power_on_lut(xfm, power_on: true, inputgamma: false, regamma: true); |
506 | |
507 | /* Program PWL */ |
508 | program_pwl(xfm_dce, params); |
509 | |
510 | /* program regamma config */ |
511 | configure_regamma_mode(xfm_dce, mode: 1); |
512 | |
513 | /* Power return to auto back */ |
514 | power_on_lut(xfm, power_on: false, inputgamma: false, regamma: true); |
515 | } |
516 | |
517 | void dce110_opp_power_on_regamma_lut_v( |
518 | struct transform *xfm, |
519 | bool power_on) |
520 | { |
521 | uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); |
522 | |
523 | set_reg_field_value( |
524 | value, |
525 | 0, |
526 | DCFEV_MEM_PWR_CTRL, |
527 | COL_MAN_GAMMA_CORR_MEM_PWR_FORCE); |
528 | |
529 | set_reg_field_value( |
530 | value, |
531 | power_on, |
532 | DCFEV_MEM_PWR_CTRL, |
533 | COL_MAN_GAMMA_CORR_MEM_PWR_DIS); |
534 | |
535 | set_reg_field_value( |
536 | value, |
537 | 0, |
538 | DCFEV_MEM_PWR_CTRL, |
539 | COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE); |
540 | |
541 | set_reg_field_value( |
542 | value, |
543 | power_on, |
544 | DCFEV_MEM_PWR_CTRL, |
545 | COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); |
546 | |
547 | dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value); |
548 | } |
549 | |
550 | void dce110_opp_set_regamma_mode_v( |
551 | struct transform *xfm, |
552 | enum opp_regamma mode) |
553 | { |
554 | // TODO: need to implement the function |
555 | } |
556 | |