GNU Linux-libre 4.19.211-gnu1
[releases.git] / drivers / gpu / drm / amd / display / dc / dce110 / dce110_opp_regamma_v.c
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, 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
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 }