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