Merge tag 'linux-watchdog-5.11-rc1' of git://www.linux-watchdog.org/linux-watchdog
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / dcn30 / dcn30_dwb_cm.c
1 /*
2  * Copyright 2020 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 "reg_helper.h"
27 #include "fixed31_32.h"
28 #include "resource.h"
29 #include "basics/conversion.h"
30 #include "dwb.h"
31 #include "dcn30_dwb.h"
32 #include "dcn30_cm_common.h"
33 #include "dcn10/dcn10_cm_common.h"
34
35
36 #define REG(reg)\
37         dwbc30->dwbc_regs->reg
38
39 #define CTX \
40         dwbc30->base.ctx
41
42 #undef FN
43 #define FN(reg_name, field_name) \
44         dwbc30->dwbc_shift->field_name, dwbc30->dwbc_mask->field_name
45
46 #define TO_DCN30_DWBC(dwbc_base) \
47         container_of(dwbc_base, struct dcn30_dwbc, base)
48
49 static void dwb3_get_reg_field_ogam(struct dcn30_dwbc *dwbc30,
50         struct dcn3_xfer_func_reg *reg)
51 {
52         reg->shifts.exp_region0_lut_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
53         reg->masks.exp_region0_lut_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
54         reg->shifts.exp_region0_num_segments = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
55         reg->masks.exp_region0_num_segments = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
56         reg->shifts.exp_region1_lut_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
57         reg->masks.exp_region1_lut_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
58         reg->shifts.exp_region1_num_segments = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
59         reg->masks.exp_region1_num_segments = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
60
61         reg->shifts.field_region_end = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_END_B;
62         reg->masks.field_region_end = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_B;
63         reg->shifts.field_region_end_slope = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
64         reg->masks.field_region_end_slope = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
65         reg->shifts.field_region_end_base = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_END_BASE_B;
66         reg->masks.field_region_end_base = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_BASE_B;
67         reg->shifts.field_region_linear_slope = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
68         reg->masks.field_region_linear_slope = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
69         reg->masks.field_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_OFFSET_B;
70         reg->shifts.field_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_OFFSET_B;
71         reg->shifts.exp_region_start = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_B;
72         reg->masks.exp_region_start = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_B;
73         reg->shifts.exp_resion_start_segment = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
74         reg->masks.exp_resion_start_segment = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
75 }
76
77 /*program dwb ogam RAM A*/
78 static void dwb3_program_ogam_luta_settings(
79         struct dcn30_dwbc *dwbc30,
80         const struct pwl_params *params)
81 {
82         struct dcn3_xfer_func_reg gam_regs;
83
84         dwb3_get_reg_field_ogam(dwbc30, &gam_regs);
85
86         gam_regs.start_cntl_b = REG(DWB_OGAM_RAMA_START_CNTL_B);
87         gam_regs.start_cntl_g = REG(DWB_OGAM_RAMA_START_CNTL_G);
88         gam_regs.start_cntl_r = REG(DWB_OGAM_RAMA_START_CNTL_R);
89         gam_regs.start_base_cntl_b = REG(DWB_OGAM_RAMA_START_BASE_CNTL_B);
90         gam_regs.start_base_cntl_g = REG(DWB_OGAM_RAMA_START_BASE_CNTL_G);
91         gam_regs.start_base_cntl_r = REG(DWB_OGAM_RAMA_START_BASE_CNTL_R);
92         gam_regs.start_slope_cntl_b = REG(DWB_OGAM_RAMA_START_SLOPE_CNTL_B);
93         gam_regs.start_slope_cntl_g = REG(DWB_OGAM_RAMA_START_SLOPE_CNTL_G);
94         gam_regs.start_slope_cntl_r = REG(DWB_OGAM_RAMA_START_SLOPE_CNTL_R);
95         gam_regs.start_end_cntl1_b = REG(DWB_OGAM_RAMA_END_CNTL1_B);
96         gam_regs.start_end_cntl2_b = REG(DWB_OGAM_RAMA_END_CNTL2_B);
97         gam_regs.start_end_cntl1_g = REG(DWB_OGAM_RAMA_END_CNTL1_G);
98         gam_regs.start_end_cntl2_g = REG(DWB_OGAM_RAMA_END_CNTL2_G);
99         gam_regs.start_end_cntl1_r = REG(DWB_OGAM_RAMA_END_CNTL1_R);
100         gam_regs.start_end_cntl2_r = REG(DWB_OGAM_RAMA_END_CNTL2_R);
101         gam_regs.offset_b = REG(DWB_OGAM_RAMA_OFFSET_B);
102         gam_regs.offset_g = REG(DWB_OGAM_RAMA_OFFSET_G);
103         gam_regs.offset_r = REG(DWB_OGAM_RAMA_OFFSET_R);
104         gam_regs.region_start = REG(DWB_OGAM_RAMA_REGION_0_1);
105         gam_regs.region_end = REG(DWB_OGAM_RAMA_REGION_32_33);
106         /*todo*/
107         cm_helper_program_gamcor_xfer_func(dwbc30->base.ctx, params, &gam_regs);
108 }
109
110 /*program dwb ogam RAM B*/
111 static void dwb3_program_ogam_lutb_settings(
112         struct dcn30_dwbc *dwbc30,
113         const struct pwl_params *params)
114 {
115         struct dcn3_xfer_func_reg gam_regs;
116
117         dwb3_get_reg_field_ogam(dwbc30, &gam_regs);
118
119         gam_regs.start_cntl_b = REG(DWB_OGAM_RAMB_START_CNTL_B);
120         gam_regs.start_cntl_g = REG(DWB_OGAM_RAMB_START_CNTL_G);
121         gam_regs.start_cntl_r = REG(DWB_OGAM_RAMB_START_CNTL_R);
122         gam_regs.start_base_cntl_b = REG(DWB_OGAM_RAMB_START_BASE_CNTL_B);
123         gam_regs.start_base_cntl_g = REG(DWB_OGAM_RAMB_START_BASE_CNTL_G);
124         gam_regs.start_base_cntl_r = REG(DWB_OGAM_RAMB_START_BASE_CNTL_R);
125         gam_regs.start_slope_cntl_b = REG(DWB_OGAM_RAMB_START_SLOPE_CNTL_B);
126         gam_regs.start_slope_cntl_g = REG(DWB_OGAM_RAMB_START_SLOPE_CNTL_G);
127         gam_regs.start_slope_cntl_r = REG(DWB_OGAM_RAMB_START_SLOPE_CNTL_R);
128         gam_regs.start_end_cntl1_b = REG(DWB_OGAM_RAMB_END_CNTL1_B);
129         gam_regs.start_end_cntl2_b = REG(DWB_OGAM_RAMB_END_CNTL2_B);
130         gam_regs.start_end_cntl1_g = REG(DWB_OGAM_RAMB_END_CNTL1_G);
131         gam_regs.start_end_cntl2_g = REG(DWB_OGAM_RAMB_END_CNTL2_G);
132         gam_regs.start_end_cntl1_r = REG(DWB_OGAM_RAMB_END_CNTL1_R);
133         gam_regs.start_end_cntl2_r = REG(DWB_OGAM_RAMB_END_CNTL2_R);
134         gam_regs.offset_b = REG(DWB_OGAM_RAMB_OFFSET_B);
135         gam_regs.offset_g = REG(DWB_OGAM_RAMB_OFFSET_G);
136         gam_regs.offset_r = REG(DWB_OGAM_RAMB_OFFSET_R);
137         gam_regs.region_start = REG(DWB_OGAM_RAMB_REGION_0_1);
138         gam_regs.region_end = REG(DWB_OGAM_RAMB_REGION_32_33);
139
140         cm_helper_program_gamcor_xfer_func(dwbc30->base.ctx, params, &gam_regs);
141 }
142
143 static enum dc_lut_mode dwb3_get_ogam_current(
144         struct dcn30_dwbc *dwbc30)
145 {
146         enum dc_lut_mode mode;
147         uint32_t state_mode;
148         uint32_t ram_select;
149
150         REG_GET(DWB_OGAM_CONTROL,
151                 DWB_OGAM_MODE, &state_mode);
152         REG_GET(DWB_OGAM_CONTROL,
153                 DWB_OGAM_SELECT, &ram_select);
154
155         if (state_mode == 0) {
156                 mode = LUT_BYPASS;
157         } else if (state_mode == 2) {
158                 if (ram_select == 0)
159                         mode = LUT_RAM_A;
160                 else
161                         mode = LUT_RAM_B;
162         } else {
163                 // Reserved value
164                 mode = LUT_BYPASS;
165                 BREAK_TO_DEBUGGER();
166                 return mode;
167         }
168         return mode;
169 }
170
171 static void dwb3_configure_ogam_lut(
172         struct dcn30_dwbc *dwbc30,
173         bool is_ram_a)
174 {
175         REG_UPDATE(DWB_OGAM_LUT_CONTROL,
176                 DWB_OGAM_LUT_READ_COLOR_SEL, 7);
177         REG_UPDATE(DWB_OGAM_CONTROL,
178                 DWB_OGAM_SELECT, is_ram_a == true ? 0 : 1);
179         REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0);
180 }
181
182 static void dwb3_program_ogam_pwl(struct dcn30_dwbc *dwbc30,
183         const struct pwl_result_data *rgb,
184         uint32_t num)
185 {
186         uint32_t i;
187
188     // triple base implementation
189         for (i = 0; i < num/2; i++) {
190                 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].red_reg);
191                 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].green_reg);
192                 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].blue_reg);
193                 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].red_reg);
194                 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].green_reg);
195                 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].blue_reg);
196                 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].red_reg);
197                 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].green_reg);
198                 REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].blue_reg);
199         }
200 }
201
202 static bool dwb3_program_ogam_lut(
203         struct dcn30_dwbc *dwbc30,
204         const struct pwl_params *params)
205 {
206         enum dc_lut_mode current_mode;
207         enum dc_lut_mode next_mode;
208
209         if (params == NULL) {
210                 REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 0);
211                 return false;
212         }
213
214         current_mode = dwb3_get_ogam_current(dwbc30);
215         if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
216                 next_mode = LUT_RAM_B;
217         else
218                 next_mode = LUT_RAM_A;
219
220         dwb3_configure_ogam_lut(dwbc30, next_mode == LUT_RAM_A ? true : false);
221
222         if (next_mode == LUT_RAM_A)
223                 dwb3_program_ogam_luta_settings(dwbc30, params);
224         else
225                 dwb3_program_ogam_lutb_settings(dwbc30, params);
226
227         dwb3_program_ogam_pwl(
228                 dwbc30, params->rgb_resulted, params->hw_points_num);
229
230         REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 2);
231         REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_SELECT, next_mode == LUT_RAM_A ? 0 : 1);
232
233         return true;
234 }
235
236 bool dwb3_ogam_set_input_transfer_func(
237         struct dwbc *dwbc,
238         const struct dc_transfer_func *in_transfer_func_dwb_ogam)
239 {
240         struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
241         bool result = false;
242         struct pwl_params *dwb_ogam_lut = NULL;
243
244         if (in_transfer_func_dwb_ogam == NULL)
245                 return result;
246
247         dwb_ogam_lut = kzalloc(sizeof(*dwb_ogam_lut), GFP_KERNEL);
248
249         if (dwb_ogam_lut) {
250                 cm_helper_translate_curve_to_hw_format(
251                         in_transfer_func_dwb_ogam,
252                         dwb_ogam_lut, false);
253
254                 result = dwb3_program_ogam_lut(
255                         dwbc30,
256                         dwb_ogam_lut);
257                 kfree(dwb_ogam_lut);
258                 dwb_ogam_lut = NULL;
259         }
260
261         return result;
262 }
263
264 static void dwb3_program_gamut_remap(
265                 struct dwbc *dwbc,
266                 const uint16_t *regval,
267                 enum cm_gamut_coef_format coef_format,
268                 enum cm_gamut_remap_select select)
269 {
270         struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
271
272         struct color_matrices_reg gam_regs;
273
274         REG_UPDATE(DWB_GAMUT_REMAP_COEF_FORMAT, DWB_GAMUT_REMAP_COEF_FORMAT, coef_format);
275
276         if (regval == NULL || select == CM_GAMUT_REMAP_MODE_BYPASS) {
277                 REG_SET(DWB_GAMUT_REMAP_MODE, 0,
278                                 DWB_GAMUT_REMAP_MODE, 0);
279                 return;
280         }
281
282         switch (select) {
283         case CM_GAMUT_REMAP_MODE_RAMA_COEFF:
284                 gam_regs.csc_c11_c12 = REG(DWB_GAMUT_REMAPA_C11_C12);
285                 gam_regs.csc_c33_c34 = REG(DWB_GAMUT_REMAPA_C33_C34);
286
287                 cm_helper_program_color_matrices(
288                                 dwbc30->base.ctx,
289                                 regval,
290                                 &gam_regs);
291                 break;
292         case CM_GAMUT_REMAP_MODE_RAMB_COEFF:
293                 gam_regs.csc_c11_c12 = REG(DWB_GAMUT_REMAPB_C11_C12);
294                 gam_regs.csc_c33_c34 = REG(DWB_GAMUT_REMAPB_C33_C34);
295
296                 cm_helper_program_color_matrices(
297                                 dwbc30->base.ctx,
298                                 regval,
299                                 &gam_regs);
300                 break;
301         case CM_GAMUT_REMAP_MODE_RESERVED:
302                 /* should never happen, bug */
303                 BREAK_TO_DEBUGGER();
304                 return;
305         default:
306                 break;
307         }
308
309         REG_SET(DWB_GAMUT_REMAP_MODE, 0,
310                         DWB_GAMUT_REMAP_MODE, select);
311
312 }
313
314 void dwb3_set_gamut_remap(
315         struct dwbc *dwbc,
316         const struct dc_dwb_params *params)
317 {
318         struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
319         struct cm_grph_csc_adjustment adjust = params->csc_params;
320         int i = 0;
321
322         if (adjust.gamut_adjust_type != CM_GAMUT_ADJUST_TYPE_SW) {
323                 /* Bypass if type is bypass or hw */
324                 dwb3_program_gamut_remap(dwbc, NULL, adjust.gamut_coef_format, CM_GAMUT_REMAP_MODE_BYPASS);
325         } else {
326                 struct fixed31_32 arr_matrix[12];
327                 uint16_t arr_reg_val[12];
328                 unsigned int current_mode;
329
330                 for (i = 0; i < 12; i++)
331                         arr_matrix[i] = adjust.temperature_matrix[i];
332
333                 convert_float_matrix(arr_reg_val, arr_matrix, 12);
334
335                 REG_GET(DWB_GAMUT_REMAP_MODE, DWB_GAMUT_REMAP_MODE_CURRENT, &current_mode);
336
337                 if (current_mode == CM_GAMUT_REMAP_MODE_RAMA_COEFF) {
338                         dwb3_program_gamut_remap(dwbc, arr_reg_val,
339                                         adjust.gamut_coef_format, CM_GAMUT_REMAP_MODE_RAMB_COEFF);
340                 } else {
341                         dwb3_program_gamut_remap(dwbc, arr_reg_val,
342                                         adjust.gamut_coef_format, CM_GAMUT_REMAP_MODE_RAMA_COEFF);
343                 }
344         }
345 }
346
347 void dwb3_program_hdr_mult(
348         struct dwbc *dwbc,
349         const struct dc_dwb_params *params)
350 {
351         struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
352
353         REG_UPDATE(DWB_HDR_MULT_COEF, DWB_HDR_MULT_COEF, params->hdr_mult);
354 }