xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/display/dc/dce110/amdgpu_dce110_opp_regamma_v.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
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