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