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 
power_on_lut(struct transform * xfm,bool power_on,bool inputgamma,bool regamma)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 
set_bypass_input_gamma(struct dce_transform * xfm_dce)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 
configure_regamma_mode(struct dce_transform * xfm_dce,uint32_t mode)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  */
regamma_config_regions_and_segments(struct dce_transform * xfm_dce,const struct pwl_params * params)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 
program_pwl(struct dce_transform * xfm_dce,const struct pwl_params * params)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 
dce110_opp_program_regamma_pwl_v(struct transform * xfm,const struct pwl_params * params)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, true, false, true);
506 
507 	/* Program PWL */
508 	program_pwl(xfm_dce, params);
509 
510 	/* program regamma config */
511 	configure_regamma_mode(xfm_dce, 1);
512 
513 	/* Power return to auto back */
514 	power_on_lut(xfm, false, false, true);
515 }
516 
dce110_opp_power_on_regamma_lut_v(struct transform * xfm,bool power_on)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 
dce110_opp_set_regamma_mode_v(struct transform * xfm,enum opp_regamma mode)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