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 "dcn30_mpc.h" |
28 | #include "dcn30_cm_common.h" |
29 | #include "basics/conversion.h" |
30 | #include "dcn10/dcn10_cm_common.h" |
31 | #include "dc.h" |
32 | |
33 | #define REG(reg)\ |
34 | mpc30->mpc_regs->reg |
35 | |
36 | #define CTX \ |
37 | mpc30->base.ctx |
38 | |
39 | #undef FN |
40 | #define FN(reg_name, field_name) \ |
41 | mpc30->mpc_shift->field_name, mpc30->mpc_mask->field_name |
42 | |
43 | |
44 | #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) |
45 | |
46 | |
47 | bool mpc3_is_dwb_idle( |
48 | struct mpc *mpc, |
49 | int dwb_id) |
50 | { |
51 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
52 | unsigned int status; |
53 | |
54 | REG_GET(DWB_MUX[dwb_id], MPC_DWB0_MUX_STATUS, &status); |
55 | |
56 | if (status == 0xf) |
57 | return true; |
58 | else |
59 | return false; |
60 | } |
61 | |
62 | void mpc3_set_dwb_mux( |
63 | struct mpc *mpc, |
64 | int dwb_id, |
65 | int mpcc_id) |
66 | { |
67 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
68 | |
69 | REG_SET(DWB_MUX[dwb_id], 0, |
70 | MPC_DWB0_MUX, mpcc_id); |
71 | } |
72 | |
73 | void mpc3_disable_dwb_mux( |
74 | struct mpc *mpc, |
75 | int dwb_id) |
76 | { |
77 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
78 | |
79 | REG_SET(DWB_MUX[dwb_id], 0, |
80 | MPC_DWB0_MUX, 0xf); |
81 | } |
82 | |
83 | void mpc3_set_out_rate_control( |
84 | struct mpc *mpc, |
85 | int opp_id, |
86 | bool enable, |
87 | bool rate_2x_mode, |
88 | struct mpc_dwb_flow_control *flow_control) |
89 | { |
90 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
91 | |
92 | REG_UPDATE_2(MUX[opp_id], |
93 | MPC_OUT_RATE_CONTROL_DISABLE, !enable, |
94 | MPC_OUT_RATE_CONTROL, rate_2x_mode); |
95 | |
96 | if (flow_control) |
97 | REG_UPDATE_2(MUX[opp_id], |
98 | MPC_OUT_FLOW_CONTROL_MODE, flow_control->flow_ctrl_mode, |
99 | MPC_OUT_FLOW_CONTROL_COUNT, flow_control->flow_ctrl_cnt1); |
100 | } |
101 | |
102 | enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id) |
103 | { |
104 | /*Contrary to DCN2 and DCN1 wherein a single status register field holds this info; |
105 | *in DCN3/3AG, we need to read two separate fields to retrieve the same info |
106 | */ |
107 | enum dc_lut_mode mode; |
108 | uint32_t state_mode; |
109 | uint32_t state_ram_lut_in_use; |
110 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
111 | |
112 | REG_GET_2(MPCC_OGAM_CONTROL[mpcc_id], MPCC_OGAM_MODE_CURRENT, &state_mode, |
113 | MPCC_OGAM_SELECT_CURRENT, &state_ram_lut_in_use); |
114 | |
115 | switch (state_mode) { |
116 | case 0: |
117 | mode = LUT_BYPASS; |
118 | break; |
119 | case 2: |
120 | switch (state_ram_lut_in_use) { |
121 | case 0: |
122 | mode = LUT_RAM_A; |
123 | break; |
124 | case 1: |
125 | mode = LUT_RAM_B; |
126 | break; |
127 | default: |
128 | mode = LUT_BYPASS; |
129 | break; |
130 | } |
131 | break; |
132 | default: |
133 | mode = LUT_BYPASS; |
134 | break; |
135 | } |
136 | |
137 | return mode; |
138 | } |
139 | |
140 | void mpc3_power_on_ogam_lut( |
141 | struct mpc *mpc, int mpcc_id, |
142 | bool power_on) |
143 | { |
144 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
145 | |
146 | /* |
147 | * Powering on: force memory active so the LUT can be updated. |
148 | * Powering off: allow entering memory low power mode |
149 | * |
150 | * Memory low power mode is controlled during MPC OGAM LUT init. |
151 | */ |
152 | REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], |
153 | MPCC_OGAM_MEM_PWR_DIS, power_on != 0); |
154 | |
155 | /* Wait for memory to be powered on - we won't be able to write to it otherwise. */ |
156 | if (power_on) |
157 | REG_WAIT(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_STATE, 0, 10, 10); |
158 | } |
159 | |
160 | static void mpc3_configure_ogam_lut( |
161 | struct mpc *mpc, int mpcc_id, |
162 | bool is_ram_a) |
163 | { |
164 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
165 | |
166 | REG_UPDATE_2(MPCC_OGAM_LUT_CONTROL[mpcc_id], |
167 | MPCC_OGAM_LUT_WRITE_COLOR_MASK, 7, |
168 | MPCC_OGAM_LUT_HOST_SEL, is_ram_a == true ? 0:1); |
169 | |
170 | REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0); |
171 | } |
172 | |
173 | static void mpc3_ogam_get_reg_field( |
174 | struct mpc *mpc, |
175 | struct dcn3_xfer_func_reg *reg) |
176 | { |
177 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
178 | |
179 | reg->shifts.field_region_start_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B; |
180 | reg->masks.field_region_start_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B; |
181 | reg->shifts.field_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_OFFSET_B; |
182 | reg->masks.field_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_OFFSET_B; |
183 | |
184 | reg->shifts.exp_region0_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET; |
185 | reg->masks.exp_region0_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET; |
186 | reg->shifts.exp_region0_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; |
187 | reg->masks.exp_region0_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; |
188 | reg->shifts.exp_region1_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET; |
189 | reg->masks.exp_region1_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET; |
190 | reg->shifts.exp_region1_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; |
191 | reg->masks.exp_region1_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; |
192 | |
193 | reg->shifts.field_region_end = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_B; |
194 | reg->masks.field_region_end = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_B; |
195 | reg->shifts.field_region_end_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B; |
196 | reg->masks.field_region_end_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B; |
197 | reg->shifts.field_region_end_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B; |
198 | reg->masks.field_region_end_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B; |
199 | reg->shifts.field_region_linear_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B; |
200 | reg->masks.field_region_linear_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B; |
201 | reg->shifts.exp_region_start = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_B; |
202 | reg->masks.exp_region_start = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_B; |
203 | reg->shifts.exp_resion_start_segment = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B; |
204 | reg->masks.exp_resion_start_segment = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B; |
205 | } |
206 | |
207 | static void mpc3_program_luta(struct mpc *mpc, int mpcc_id, |
208 | const struct pwl_params *params) |
209 | { |
210 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
211 | struct dcn3_xfer_func_reg gam_regs; |
212 | |
213 | mpc3_ogam_get_reg_field(mpc, reg: &gam_regs); |
214 | |
215 | gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMA_START_CNTL_B[mpcc_id]); |
216 | gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMA_START_CNTL_G[mpcc_id]); |
217 | gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMA_START_CNTL_R[mpcc_id]); |
218 | gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_B[mpcc_id]); |
219 | gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_G[mpcc_id]); |
220 | gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_R[mpcc_id]); |
221 | gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMA_END_CNTL1_B[mpcc_id]); |
222 | gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMA_END_CNTL2_B[mpcc_id]); |
223 | gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMA_END_CNTL1_G[mpcc_id]); |
224 | gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMA_END_CNTL2_G[mpcc_id]); |
225 | gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMA_END_CNTL1_R[mpcc_id]); |
226 | gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMA_END_CNTL2_R[mpcc_id]); |
227 | gam_regs.region_start = REG(MPCC_OGAM_RAMA_REGION_0_1[mpcc_id]); |
228 | gam_regs.region_end = REG(MPCC_OGAM_RAMA_REGION_32_33[mpcc_id]); |
229 | //New registers in DCN3AG/DCN OGAM block |
230 | gam_regs.offset_b = REG(MPCC_OGAM_RAMA_OFFSET_B[mpcc_id]); |
231 | gam_regs.offset_g = REG(MPCC_OGAM_RAMA_OFFSET_G[mpcc_id]); |
232 | gam_regs.offset_r = REG(MPCC_OGAM_RAMA_OFFSET_R[mpcc_id]); |
233 | gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_B[mpcc_id]); |
234 | gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_G[mpcc_id]); |
235 | gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_R[mpcc_id]); |
236 | |
237 | cm_helper_program_gamcor_xfer_func(ctx: mpc30->base.ctx, params, reg: &gam_regs); |
238 | } |
239 | |
240 | static void mpc3_program_lutb(struct mpc *mpc, int mpcc_id, |
241 | const struct pwl_params *params) |
242 | { |
243 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
244 | struct dcn3_xfer_func_reg gam_regs; |
245 | |
246 | mpc3_ogam_get_reg_field(mpc, reg: &gam_regs); |
247 | |
248 | gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMB_START_CNTL_B[mpcc_id]); |
249 | gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMB_START_CNTL_G[mpcc_id]); |
250 | gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMB_START_CNTL_R[mpcc_id]); |
251 | gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_B[mpcc_id]); |
252 | gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_G[mpcc_id]); |
253 | gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_R[mpcc_id]); |
254 | gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMB_END_CNTL1_B[mpcc_id]); |
255 | gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMB_END_CNTL2_B[mpcc_id]); |
256 | gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMB_END_CNTL1_G[mpcc_id]); |
257 | gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMB_END_CNTL2_G[mpcc_id]); |
258 | gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMB_END_CNTL1_R[mpcc_id]); |
259 | gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMB_END_CNTL2_R[mpcc_id]); |
260 | gam_regs.region_start = REG(MPCC_OGAM_RAMB_REGION_0_1[mpcc_id]); |
261 | gam_regs.region_end = REG(MPCC_OGAM_RAMB_REGION_32_33[mpcc_id]); |
262 | //New registers in DCN3AG/DCN OGAM block |
263 | gam_regs.offset_b = REG(MPCC_OGAM_RAMB_OFFSET_B[mpcc_id]); |
264 | gam_regs.offset_g = REG(MPCC_OGAM_RAMB_OFFSET_G[mpcc_id]); |
265 | gam_regs.offset_r = REG(MPCC_OGAM_RAMB_OFFSET_R[mpcc_id]); |
266 | gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_B[mpcc_id]); |
267 | gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_G[mpcc_id]); |
268 | gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_R[mpcc_id]); |
269 | |
270 | cm_helper_program_gamcor_xfer_func(ctx: mpc30->base.ctx, params, reg: &gam_regs); |
271 | } |
272 | |
273 | |
274 | static void mpc3_program_ogam_pwl( |
275 | struct mpc *mpc, int mpcc_id, |
276 | const struct pwl_result_data *rgb, |
277 | uint32_t num) |
278 | { |
279 | uint32_t i; |
280 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
281 | |
282 | if (is_rgb_equal(rgb, num)) { |
283 | for (i = 0 ; i < num; i++) |
284 | REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg); |
285 | } else { |
286 | |
287 | REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id], |
288 | MPCC_OGAM_LUT_WRITE_COLOR_MASK, 4); |
289 | |
290 | for (i = 0 ; i < num; i++) |
291 | REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg); |
292 | |
293 | REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0); |
294 | |
295 | REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id], |
296 | MPCC_OGAM_LUT_WRITE_COLOR_MASK, 2); |
297 | |
298 | for (i = 0 ; i < num; i++) |
299 | REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].green_reg); |
300 | |
301 | REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0); |
302 | |
303 | REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id], |
304 | MPCC_OGAM_LUT_WRITE_COLOR_MASK, 1); |
305 | |
306 | for (i = 0 ; i < num; i++) |
307 | REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].blue_reg); |
308 | |
309 | } |
310 | |
311 | } |
312 | |
313 | void mpc3_set_output_gamma( |
314 | struct mpc *mpc, |
315 | int mpcc_id, |
316 | const struct pwl_params *params) |
317 | { |
318 | enum dc_lut_mode current_mode; |
319 | enum dc_lut_mode next_mode; |
320 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
321 | |
322 | if (mpc->ctx->dc->debug.cm_in_bypass) { |
323 | REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE, 0); |
324 | return; |
325 | } |
326 | |
327 | if (params == NULL) { //disable OGAM |
328 | REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 0); |
329 | return; |
330 | } |
331 | //enable OGAM |
332 | REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 2); |
333 | |
334 | current_mode = mpc3_get_ogam_current(mpc, mpcc_id); |
335 | if (current_mode == LUT_BYPASS) |
336 | next_mode = LUT_RAM_A; |
337 | else if (current_mode == LUT_RAM_A) |
338 | next_mode = LUT_RAM_B; |
339 | else |
340 | next_mode = LUT_RAM_A; |
341 | |
342 | mpc3_power_on_ogam_lut(mpc, mpcc_id, power_on: true); |
343 | mpc3_configure_ogam_lut(mpc, mpcc_id, is_ram_a: next_mode == LUT_RAM_A); |
344 | |
345 | if (next_mode == LUT_RAM_A) |
346 | mpc3_program_luta(mpc, mpcc_id, params); |
347 | else |
348 | mpc3_program_lutb(mpc, mpcc_id, params); |
349 | |
350 | mpc3_program_ogam_pwl( |
351 | mpc, mpcc_id, rgb: params->rgb_resulted, num: params->hw_points_num); |
352 | |
353 | /*we need to program 2 fields here as apposed to 1*/ |
354 | REG_UPDATE(MPCC_OGAM_CONTROL[mpcc_id], |
355 | MPCC_OGAM_SELECT, next_mode == LUT_RAM_A ? 0:1); |
356 | |
357 | if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) |
358 | mpc3_power_on_ogam_lut(mpc, mpcc_id, power_on: false); |
359 | } |
360 | |
361 | void mpc3_set_denorm( |
362 | struct mpc *mpc, |
363 | int opp_id, |
364 | enum dc_color_depth output_depth) |
365 | { |
366 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
367 | /* De-normalize Fixed U1.13 color data to different target bit depths. 0 is bypass*/ |
368 | int denorm_mode = 0; |
369 | |
370 | switch (output_depth) { |
371 | case COLOR_DEPTH_666: |
372 | denorm_mode = 1; |
373 | break; |
374 | case COLOR_DEPTH_888: |
375 | denorm_mode = 2; |
376 | break; |
377 | case COLOR_DEPTH_999: |
378 | denorm_mode = 3; |
379 | break; |
380 | case COLOR_DEPTH_101010: |
381 | denorm_mode = 4; |
382 | break; |
383 | case COLOR_DEPTH_111111: |
384 | denorm_mode = 5; |
385 | break; |
386 | case COLOR_DEPTH_121212: |
387 | denorm_mode = 6; |
388 | break; |
389 | case COLOR_DEPTH_141414: |
390 | case COLOR_DEPTH_161616: |
391 | default: |
392 | /* not valid used case! */ |
393 | break; |
394 | } |
395 | |
396 | REG_UPDATE(DENORM_CONTROL[opp_id], |
397 | MPC_OUT_DENORM_MODE, denorm_mode); |
398 | } |
399 | |
400 | void mpc3_set_denorm_clamp( |
401 | struct mpc *mpc, |
402 | int opp_id, |
403 | struct mpc_denorm_clamp denorm_clamp) |
404 | { |
405 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
406 | |
407 | /*program min and max clamp values for the pixel components*/ |
408 | REG_UPDATE_2(DENORM_CONTROL[opp_id], |
409 | MPC_OUT_DENORM_CLAMP_MAX_R_CR, denorm_clamp.clamp_max_r_cr, |
410 | MPC_OUT_DENORM_CLAMP_MIN_R_CR, denorm_clamp.clamp_min_r_cr); |
411 | REG_UPDATE_2(DENORM_CLAMP_G_Y[opp_id], |
412 | MPC_OUT_DENORM_CLAMP_MAX_G_Y, denorm_clamp.clamp_max_g_y, |
413 | MPC_OUT_DENORM_CLAMP_MIN_G_Y, denorm_clamp.clamp_min_g_y); |
414 | REG_UPDATE_2(DENORM_CLAMP_B_CB[opp_id], |
415 | MPC_OUT_DENORM_CLAMP_MAX_B_CB, denorm_clamp.clamp_max_b_cb, |
416 | MPC_OUT_DENORM_CLAMP_MIN_B_CB, denorm_clamp.clamp_min_b_cb); |
417 | } |
418 | |
419 | static enum dc_lut_mode mpc3_get_shaper_current(struct mpc *mpc, uint32_t rmu_idx) |
420 | { |
421 | enum dc_lut_mode mode; |
422 | uint32_t state_mode; |
423 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
424 | |
425 | REG_GET(SHAPER_CONTROL[rmu_idx], MPC_RMU_SHAPER_LUT_MODE_CURRENT, &state_mode); |
426 | |
427 | switch (state_mode) { |
428 | case 0: |
429 | mode = LUT_BYPASS; |
430 | break; |
431 | case 1: |
432 | mode = LUT_RAM_A; |
433 | break; |
434 | case 2: |
435 | mode = LUT_RAM_B; |
436 | break; |
437 | default: |
438 | mode = LUT_BYPASS; |
439 | break; |
440 | } |
441 | |
442 | return mode; |
443 | } |
444 | |
445 | static void mpc3_configure_shaper_lut( |
446 | struct mpc *mpc, |
447 | bool is_ram_a, |
448 | uint32_t rmu_idx) |
449 | { |
450 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
451 | |
452 | REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx], |
453 | MPC_RMU_SHAPER_LUT_WRITE_EN_MASK, 7); |
454 | REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx], |
455 | MPC_RMU_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1); |
456 | REG_SET(SHAPER_LUT_INDEX[rmu_idx], 0, MPC_RMU_SHAPER_LUT_INDEX, 0); |
457 | } |
458 | |
459 | static void mpc3_program_shaper_luta_settings( |
460 | struct mpc *mpc, |
461 | const struct pwl_params *params, |
462 | uint32_t rmu_idx) |
463 | { |
464 | const struct gamma_curve *curve; |
465 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
466 | |
467 | REG_SET_2(SHAPER_RAMA_START_CNTL_B[rmu_idx], 0, |
468 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x, |
469 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); |
470 | REG_SET_2(SHAPER_RAMA_START_CNTL_G[rmu_idx], 0, |
471 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x, |
472 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); |
473 | REG_SET_2(SHAPER_RAMA_START_CNTL_R[rmu_idx], 0, |
474 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x, |
475 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); |
476 | |
477 | REG_SET_2(SHAPER_RAMA_END_CNTL_B[rmu_idx], 0, |
478 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x, |
479 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y); |
480 | REG_SET_2(SHAPER_RAMA_END_CNTL_G[rmu_idx], 0, |
481 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x, |
482 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y); |
483 | REG_SET_2(SHAPER_RAMA_END_CNTL_R[rmu_idx], 0, |
484 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x, |
485 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y); |
486 | |
487 | curve = params->arr_curve_points; |
488 | REG_SET_4(SHAPER_RAMA_REGION_0_1[rmu_idx], 0, |
489 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
490 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
491 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
492 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
493 | |
494 | curve += 2; |
495 | REG_SET_4(SHAPER_RAMA_REGION_2_3[rmu_idx], 0, |
496 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
497 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
498 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
499 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
500 | |
501 | curve += 2; |
502 | REG_SET_4(SHAPER_RAMA_REGION_4_5[rmu_idx], 0, |
503 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
504 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
505 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
506 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
507 | |
508 | curve += 2; |
509 | REG_SET_4(SHAPER_RAMA_REGION_6_7[rmu_idx], 0, |
510 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
511 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
512 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
513 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
514 | |
515 | curve += 2; |
516 | REG_SET_4(SHAPER_RAMA_REGION_8_9[rmu_idx], 0, |
517 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
518 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
519 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
520 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
521 | |
522 | curve += 2; |
523 | REG_SET_4(SHAPER_RAMA_REGION_10_11[rmu_idx], 0, |
524 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
525 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
526 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
527 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
528 | |
529 | curve += 2; |
530 | REG_SET_4(SHAPER_RAMA_REGION_12_13[rmu_idx], 0, |
531 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
532 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
533 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
534 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
535 | |
536 | curve += 2; |
537 | REG_SET_4(SHAPER_RAMA_REGION_14_15[rmu_idx], 0, |
538 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
539 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
540 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
541 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
542 | |
543 | |
544 | curve += 2; |
545 | REG_SET_4(SHAPER_RAMA_REGION_16_17[rmu_idx], 0, |
546 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
547 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
548 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
549 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
550 | |
551 | curve += 2; |
552 | REG_SET_4(SHAPER_RAMA_REGION_18_19[rmu_idx], 0, |
553 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
554 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
555 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
556 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
557 | |
558 | curve += 2; |
559 | REG_SET_4(SHAPER_RAMA_REGION_20_21[rmu_idx], 0, |
560 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
561 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
562 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
563 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
564 | |
565 | curve += 2; |
566 | REG_SET_4(SHAPER_RAMA_REGION_22_23[rmu_idx], 0, |
567 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
568 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
569 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
570 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
571 | |
572 | curve += 2; |
573 | REG_SET_4(SHAPER_RAMA_REGION_24_25[rmu_idx], 0, |
574 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
575 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
576 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
577 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
578 | |
579 | curve += 2; |
580 | REG_SET_4(SHAPER_RAMA_REGION_26_27[rmu_idx], 0, |
581 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
582 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
583 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
584 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
585 | |
586 | curve += 2; |
587 | REG_SET_4(SHAPER_RAMA_REGION_28_29[rmu_idx], 0, |
588 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
589 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
590 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
591 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
592 | |
593 | curve += 2; |
594 | REG_SET_4(SHAPER_RAMA_REGION_30_31[rmu_idx], 0, |
595 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
596 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
597 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
598 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
599 | |
600 | curve += 2; |
601 | REG_SET_4(SHAPER_RAMA_REGION_32_33[rmu_idx], 0, |
602 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
603 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
604 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
605 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
606 | } |
607 | |
608 | static void mpc3_program_shaper_lutb_settings( |
609 | struct mpc *mpc, |
610 | const struct pwl_params *params, |
611 | uint32_t rmu_idx) |
612 | { |
613 | const struct gamma_curve *curve; |
614 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
615 | |
616 | REG_SET_2(SHAPER_RAMB_START_CNTL_B[rmu_idx], 0, |
617 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x, |
618 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); |
619 | REG_SET_2(SHAPER_RAMB_START_CNTL_G[rmu_idx], 0, |
620 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x, |
621 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); |
622 | REG_SET_2(SHAPER_RAMB_START_CNTL_R[rmu_idx], 0, |
623 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x, |
624 | MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); |
625 | |
626 | REG_SET_2(SHAPER_RAMB_END_CNTL_B[rmu_idx], 0, |
627 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x, |
628 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y); |
629 | REG_SET_2(SHAPER_RAMB_END_CNTL_G[rmu_idx], 0, |
630 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x, |
631 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y); |
632 | REG_SET_2(SHAPER_RAMB_END_CNTL_R[rmu_idx], 0, |
633 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x, |
634 | MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y); |
635 | |
636 | curve = params->arr_curve_points; |
637 | REG_SET_4(SHAPER_RAMB_REGION_0_1[rmu_idx], 0, |
638 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
639 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
640 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
641 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
642 | |
643 | curve += 2; |
644 | REG_SET_4(SHAPER_RAMB_REGION_2_3[rmu_idx], 0, |
645 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
646 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
647 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
648 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
649 | |
650 | |
651 | curve += 2; |
652 | REG_SET_4(SHAPER_RAMB_REGION_4_5[rmu_idx], 0, |
653 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
654 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
655 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
656 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
657 | |
658 | curve += 2; |
659 | REG_SET_4(SHAPER_RAMB_REGION_6_7[rmu_idx], 0, |
660 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
661 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
662 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
663 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
664 | |
665 | curve += 2; |
666 | REG_SET_4(SHAPER_RAMB_REGION_8_9[rmu_idx], 0, |
667 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
668 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
669 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
670 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
671 | |
672 | curve += 2; |
673 | REG_SET_4(SHAPER_RAMB_REGION_10_11[rmu_idx], 0, |
674 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
675 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
676 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
677 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
678 | |
679 | curve += 2; |
680 | REG_SET_4(SHAPER_RAMB_REGION_12_13[rmu_idx], 0, |
681 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
682 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
683 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
684 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
685 | |
686 | curve += 2; |
687 | REG_SET_4(SHAPER_RAMB_REGION_14_15[rmu_idx], 0, |
688 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
689 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
690 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
691 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
692 | |
693 | |
694 | curve += 2; |
695 | REG_SET_4(SHAPER_RAMB_REGION_16_17[rmu_idx], 0, |
696 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
697 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
698 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
699 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
700 | |
701 | curve += 2; |
702 | REG_SET_4(SHAPER_RAMB_REGION_18_19[rmu_idx], 0, |
703 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
704 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
705 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
706 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
707 | |
708 | curve += 2; |
709 | REG_SET_4(SHAPER_RAMB_REGION_20_21[rmu_idx], 0, |
710 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
711 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
712 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
713 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
714 | |
715 | curve += 2; |
716 | REG_SET_4(SHAPER_RAMB_REGION_22_23[rmu_idx], 0, |
717 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
718 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
719 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
720 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
721 | |
722 | curve += 2; |
723 | REG_SET_4(SHAPER_RAMB_REGION_24_25[rmu_idx], 0, |
724 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
725 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
726 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
727 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
728 | |
729 | curve += 2; |
730 | REG_SET_4(SHAPER_RAMB_REGION_26_27[rmu_idx], 0, |
731 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
732 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
733 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
734 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
735 | |
736 | curve += 2; |
737 | REG_SET_4(SHAPER_RAMB_REGION_28_29[rmu_idx], 0, |
738 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
739 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
740 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
741 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
742 | |
743 | curve += 2; |
744 | REG_SET_4(SHAPER_RAMB_REGION_30_31[rmu_idx], 0, |
745 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
746 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
747 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
748 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
749 | |
750 | curve += 2; |
751 | REG_SET_4(SHAPER_RAMB_REGION_32_33[rmu_idx], 0, |
752 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, |
753 | MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, |
754 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, |
755 | MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); |
756 | } |
757 | |
758 | |
759 | static void mpc3_program_shaper_lut( |
760 | struct mpc *mpc, |
761 | const struct pwl_result_data *rgb, |
762 | uint32_t num, |
763 | uint32_t rmu_idx) |
764 | { |
765 | uint32_t i, red, green, blue; |
766 | uint32_t red_delta, green_delta, blue_delta; |
767 | uint32_t red_value, green_value, blue_value; |
768 | |
769 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
770 | |
771 | for (i = 0 ; i < num; i++) { |
772 | |
773 | red = rgb[i].red_reg; |
774 | green = rgb[i].green_reg; |
775 | blue = rgb[i].blue_reg; |
776 | |
777 | red_delta = rgb[i].delta_red_reg; |
778 | green_delta = rgb[i].delta_green_reg; |
779 | blue_delta = rgb[i].delta_blue_reg; |
780 | |
781 | red_value = ((red_delta & 0x3ff) << 14) | (red & 0x3fff); |
782 | green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff); |
783 | blue_value = ((blue_delta & 0x3ff) << 14) | (blue & 0x3fff); |
784 | |
785 | REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, red_value); |
786 | REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, green_value); |
787 | REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, blue_value); |
788 | } |
789 | |
790 | } |
791 | |
792 | static void mpc3_power_on_shaper_3dlut( |
793 | struct mpc *mpc, |
794 | uint32_t rmu_idx, |
795 | bool power_on) |
796 | { |
797 | uint32_t power_status_shaper = 2; |
798 | uint32_t power_status_3dlut = 2; |
799 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
800 | int max_retries = 10; |
801 | |
802 | if (rmu_idx == 0) { |
803 | REG_SET(MPC_RMU_MEM_PWR_CTRL, 0, |
804 | MPC_RMU0_MEM_PWR_DIS, power_on == true ? 1:0); |
805 | /* wait for memory to fully power up */ |
806 | if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) { |
807 | REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, 0, 1, max_retries); |
808 | REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, 0, 1, max_retries); |
809 | } |
810 | |
811 | /*read status is not mandatory, it is just for debugging*/ |
812 | REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, &power_status_shaper); |
813 | REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, &power_status_3dlut); |
814 | } else if (rmu_idx == 1) { |
815 | REG_SET(MPC_RMU_MEM_PWR_CTRL, 0, |
816 | MPC_RMU1_MEM_PWR_DIS, power_on == true ? 1:0); |
817 | if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) { |
818 | REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, 0, 1, max_retries); |
819 | REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, 0, 1, max_retries); |
820 | } |
821 | |
822 | REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, &power_status_shaper); |
823 | REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, &power_status_3dlut); |
824 | } |
825 | /*TODO Add rmu_idx == 2 for SIENNA_CICHLID */ |
826 | if (power_status_shaper != 0 && power_on == true) |
827 | BREAK_TO_DEBUGGER(); |
828 | |
829 | if (power_status_3dlut != 0 && power_on == true) |
830 | BREAK_TO_DEBUGGER(); |
831 | } |
832 | |
833 | |
834 | |
835 | bool mpc3_program_shaper( |
836 | struct mpc *mpc, |
837 | const struct pwl_params *params, |
838 | uint32_t rmu_idx) |
839 | { |
840 | enum dc_lut_mode current_mode; |
841 | enum dc_lut_mode next_mode; |
842 | |
843 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
844 | |
845 | if (params == NULL) { |
846 | REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, 0); |
847 | return false; |
848 | } |
849 | |
850 | if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) |
851 | mpc3_power_on_shaper_3dlut(mpc, rmu_idx, power_on: true); |
852 | |
853 | current_mode = mpc3_get_shaper_current(mpc, rmu_idx); |
854 | |
855 | if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A) |
856 | next_mode = LUT_RAM_B; |
857 | else |
858 | next_mode = LUT_RAM_A; |
859 | |
860 | mpc3_configure_shaper_lut(mpc, is_ram_a: next_mode == LUT_RAM_A, rmu_idx); |
861 | |
862 | if (next_mode == LUT_RAM_A) |
863 | mpc3_program_shaper_luta_settings(mpc, params, rmu_idx); |
864 | else |
865 | mpc3_program_shaper_lutb_settings(mpc, params, rmu_idx); |
866 | |
867 | mpc3_program_shaper_lut( |
868 | mpc, rgb: params->rgb_resulted, num: params->hw_points_num, rmu_idx); |
869 | |
870 | REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2); |
871 | mpc3_power_on_shaper_3dlut(mpc, rmu_idx, power_on: false); |
872 | |
873 | return true; |
874 | } |
875 | |
876 | static void mpc3_set_3dlut_mode( |
877 | struct mpc *mpc, |
878 | enum dc_lut_mode mode, |
879 | bool is_color_channel_12bits, |
880 | bool is_lut_size17x17x17, |
881 | uint32_t rmu_idx) |
882 | { |
883 | uint32_t lut_mode; |
884 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
885 | |
886 | if (mode == LUT_BYPASS) |
887 | lut_mode = 0; |
888 | else if (mode == LUT_RAM_A) |
889 | lut_mode = 1; |
890 | else |
891 | lut_mode = 2; |
892 | |
893 | REG_UPDATE_2(RMU_3DLUT_MODE[rmu_idx], |
894 | MPC_RMU_3DLUT_MODE, lut_mode, |
895 | MPC_RMU_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1); |
896 | } |
897 | |
898 | static enum dc_lut_mode get3dlut_config( |
899 | struct mpc *mpc, |
900 | bool *is_17x17x17, |
901 | bool *is_12bits_color_channel, |
902 | int rmu_idx) |
903 | { |
904 | uint32_t i_mode, i_enable_10bits, lut_size; |
905 | enum dc_lut_mode mode; |
906 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
907 | |
908 | REG_GET(RMU_3DLUT_MODE[rmu_idx], |
909 | MPC_RMU_3DLUT_MODE_CURRENT, &i_mode); |
910 | |
911 | REG_GET(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx], |
912 | MPC_RMU_3DLUT_30BIT_EN, &i_enable_10bits); |
913 | |
914 | switch (i_mode) { |
915 | case 0: |
916 | mode = LUT_BYPASS; |
917 | break; |
918 | case 1: |
919 | mode = LUT_RAM_A; |
920 | break; |
921 | case 2: |
922 | mode = LUT_RAM_B; |
923 | break; |
924 | default: |
925 | mode = LUT_BYPASS; |
926 | break; |
927 | } |
928 | if (i_enable_10bits > 0) |
929 | *is_12bits_color_channel = false; |
930 | else |
931 | *is_12bits_color_channel = true; |
932 | |
933 | REG_GET(RMU_3DLUT_MODE[rmu_idx], MPC_RMU_3DLUT_SIZE, &lut_size); |
934 | |
935 | if (lut_size == 0) |
936 | *is_17x17x17 = true; |
937 | else |
938 | *is_17x17x17 = false; |
939 | |
940 | return mode; |
941 | } |
942 | |
943 | static void mpc3_select_3dlut_ram( |
944 | struct mpc *mpc, |
945 | enum dc_lut_mode mode, |
946 | bool is_color_channel_12bits, |
947 | uint32_t rmu_idx) |
948 | { |
949 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
950 | |
951 | REG_UPDATE_2(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx], |
952 | MPC_RMU_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1, |
953 | MPC_RMU_3DLUT_30BIT_EN, is_color_channel_12bits == true ? 0:1); |
954 | } |
955 | |
956 | static void mpc3_select_3dlut_ram_mask( |
957 | struct mpc *mpc, |
958 | uint32_t ram_selection_mask, |
959 | uint32_t rmu_idx) |
960 | { |
961 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
962 | |
963 | REG_UPDATE(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx], MPC_RMU_3DLUT_WRITE_EN_MASK, |
964 | ram_selection_mask); |
965 | REG_SET(RMU_3DLUT_INDEX[rmu_idx], 0, MPC_RMU_3DLUT_INDEX, 0); |
966 | } |
967 | |
968 | static void mpc3_set3dlut_ram12( |
969 | struct mpc *mpc, |
970 | const struct dc_rgb *lut, |
971 | uint32_t entries, |
972 | uint32_t rmu_idx) |
973 | { |
974 | uint32_t i, red, green, blue, red1, green1, blue1; |
975 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
976 | |
977 | for (i = 0 ; i < entries; i += 2) { |
978 | red = lut[i].red<<4; |
979 | green = lut[i].green<<4; |
980 | blue = lut[i].blue<<4; |
981 | red1 = lut[i+1].red<<4; |
982 | green1 = lut[i+1].green<<4; |
983 | blue1 = lut[i+1].blue<<4; |
984 | |
985 | REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0, |
986 | MPC_RMU_3DLUT_DATA0, red, |
987 | MPC_RMU_3DLUT_DATA1, red1); |
988 | |
989 | REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0, |
990 | MPC_RMU_3DLUT_DATA0, green, |
991 | MPC_RMU_3DLUT_DATA1, green1); |
992 | |
993 | REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0, |
994 | MPC_RMU_3DLUT_DATA0, blue, |
995 | MPC_RMU_3DLUT_DATA1, blue1); |
996 | } |
997 | } |
998 | |
999 | static void mpc3_set3dlut_ram10( |
1000 | struct mpc *mpc, |
1001 | const struct dc_rgb *lut, |
1002 | uint32_t entries, |
1003 | uint32_t rmu_idx) |
1004 | { |
1005 | uint32_t i, red, green, blue, value; |
1006 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
1007 | |
1008 | for (i = 0; i < entries; i++) { |
1009 | red = lut[i].red; |
1010 | green = lut[i].green; |
1011 | blue = lut[i].blue; |
1012 | //should we shift red 22bit and green 12? ask Nvenko |
1013 | value = (red<<20) | (green<<10) | blue; |
1014 | |
1015 | REG_SET(RMU_3DLUT_DATA_30BIT[rmu_idx], 0, MPC_RMU_3DLUT_DATA_30BIT, value); |
1016 | } |
1017 | |
1018 | } |
1019 | |
1020 | |
1021 | void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst) |
1022 | { |
1023 | mpcc->mpcc_id = mpcc_inst; |
1024 | mpcc->dpp_id = 0xf; |
1025 | mpcc->mpcc_bot = NULL; |
1026 | mpcc->blnd_cfg.overlap_only = false; |
1027 | mpcc->blnd_cfg.global_alpha = 0xff; |
1028 | mpcc->blnd_cfg.global_gain = 0xff; |
1029 | mpcc->blnd_cfg.background_color_bpc = 4; |
1030 | mpcc->blnd_cfg.bottom_gain_mode = 0; |
1031 | mpcc->blnd_cfg.top_gain = 0x1f000; |
1032 | mpcc->blnd_cfg.bottom_inside_gain = 0x1f000; |
1033 | mpcc->blnd_cfg.bottom_outside_gain = 0x1f000; |
1034 | mpcc->sm_cfg.enable = false; |
1035 | mpcc->shared_bottom = false; |
1036 | } |
1037 | |
1038 | static void program_gamut_remap( |
1039 | struct dcn30_mpc *mpc30, |
1040 | int mpcc_id, |
1041 | const uint16_t *regval, |
1042 | int select) |
1043 | { |
1044 | uint16_t selection = 0; |
1045 | struct color_matrices_reg gam_regs; |
1046 | |
1047 | if (regval == NULL || select == GAMUT_REMAP_BYPASS) { |
1048 | REG_SET(MPCC_GAMUT_REMAP_MODE[mpcc_id], 0, |
1049 | MPCC_GAMUT_REMAP_MODE, GAMUT_REMAP_BYPASS); |
1050 | return; |
1051 | } |
1052 | switch (select) { |
1053 | case GAMUT_REMAP_COEFF: |
1054 | selection = 1; |
1055 | break; |
1056 | /*this corresponds to GAMUT_REMAP coefficients set B |
1057 | * we don't have common coefficient sets in dcn3ag/dcn3 |
1058 | */ |
1059 | case GAMUT_REMAP_COMA_COEFF: |
1060 | selection = 2; |
1061 | break; |
1062 | default: |
1063 | break; |
1064 | } |
1065 | |
1066 | gam_regs.shifts.csc_c11 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C11_A; |
1067 | gam_regs.masks.csc_c11 = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C11_A; |
1068 | gam_regs.shifts.csc_c12 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C12_A; |
1069 | gam_regs.masks.csc_c12 = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C12_A; |
1070 | |
1071 | |
1072 | if (select == GAMUT_REMAP_COEFF) { |
1073 | gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_A[mpcc_id]); |
1074 | gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_A[mpcc_id]); |
1075 | |
1076 | cm_helper_program_color_matrices( |
1077 | ctx: mpc30->base.ctx, |
1078 | regval, |
1079 | reg: &gam_regs); |
1080 | |
1081 | } else if (select == GAMUT_REMAP_COMA_COEFF) { |
1082 | |
1083 | gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_B[mpcc_id]); |
1084 | gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_B[mpcc_id]); |
1085 | |
1086 | cm_helper_program_color_matrices( |
1087 | ctx: mpc30->base.ctx, |
1088 | regval, |
1089 | reg: &gam_regs); |
1090 | |
1091 | } |
1092 | //select coefficient set to use |
1093 | REG_SET(MPCC_GAMUT_REMAP_MODE[mpcc_id], 0, |
1094 | MPCC_GAMUT_REMAP_MODE, selection); |
1095 | } |
1096 | |
1097 | void mpc3_set_gamut_remap( |
1098 | struct mpc *mpc, |
1099 | int mpcc_id, |
1100 | const struct mpc_grph_gamut_adjustment *adjust) |
1101 | { |
1102 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
1103 | int i = 0; |
1104 | int gamut_mode; |
1105 | |
1106 | if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) |
1107 | program_gamut_remap(mpc30, mpcc_id, NULL, select: GAMUT_REMAP_BYPASS); |
1108 | else { |
1109 | struct fixed31_32 arr_matrix[12]; |
1110 | uint16_t arr_reg_val[12]; |
1111 | |
1112 | for (i = 0; i < 12; i++) |
1113 | arr_matrix[i] = adjust->temperature_matrix[i]; |
1114 | |
1115 | convert_float_matrix( |
1116 | matrix: arr_reg_val, flt: arr_matrix, buffer_size: 12); |
1117 | |
1118 | //current coefficient set in use |
1119 | REG_GET(MPCC_GAMUT_REMAP_MODE[mpcc_id], MPCC_GAMUT_REMAP_MODE_CURRENT, &gamut_mode); |
1120 | |
1121 | if (gamut_mode == 0) |
1122 | gamut_mode = 1; //use coefficient set A |
1123 | else if (gamut_mode == 1) |
1124 | gamut_mode = 2; |
1125 | else |
1126 | gamut_mode = 1; |
1127 | |
1128 | program_gamut_remap(mpc30, mpcc_id, regval: arr_reg_val, select: gamut_mode); |
1129 | } |
1130 | } |
1131 | |
1132 | bool mpc3_program_3dlut( |
1133 | struct mpc *mpc, |
1134 | const struct tetrahedral_params *params, |
1135 | int rmu_idx) |
1136 | { |
1137 | enum dc_lut_mode mode; |
1138 | bool is_17x17x17; |
1139 | bool is_12bits_color_channel; |
1140 | const struct dc_rgb *lut0; |
1141 | const struct dc_rgb *lut1; |
1142 | const struct dc_rgb *lut2; |
1143 | const struct dc_rgb *lut3; |
1144 | int lut_size0; |
1145 | int lut_size; |
1146 | |
1147 | if (params == NULL) { |
1148 | mpc3_set_3dlut_mode(mpc, mode: LUT_BYPASS, is_color_channel_12bits: false, is_lut_size17x17x17: false, rmu_idx); |
1149 | return false; |
1150 | } |
1151 | mpc3_power_on_shaper_3dlut(mpc, rmu_idx, power_on: true); |
1152 | |
1153 | mode = get3dlut_config(mpc, is_17x17x17: &is_17x17x17, is_12bits_color_channel: &is_12bits_color_channel, rmu_idx); |
1154 | |
1155 | if (mode == LUT_BYPASS || mode == LUT_RAM_B) |
1156 | mode = LUT_RAM_A; |
1157 | else |
1158 | mode = LUT_RAM_B; |
1159 | |
1160 | is_17x17x17 = !params->use_tetrahedral_9; |
1161 | is_12bits_color_channel = params->use_12bits; |
1162 | if (is_17x17x17) { |
1163 | lut0 = params->tetrahedral_17.lut0; |
1164 | lut1 = params->tetrahedral_17.lut1; |
1165 | lut2 = params->tetrahedral_17.lut2; |
1166 | lut3 = params->tetrahedral_17.lut3; |
1167 | lut_size0 = sizeof(params->tetrahedral_17.lut0)/ |
1168 | sizeof(params->tetrahedral_17.lut0[0]); |
1169 | lut_size = sizeof(params->tetrahedral_17.lut1)/ |
1170 | sizeof(params->tetrahedral_17.lut1[0]); |
1171 | } else { |
1172 | lut0 = params->tetrahedral_9.lut0; |
1173 | lut1 = params->tetrahedral_9.lut1; |
1174 | lut2 = params->tetrahedral_9.lut2; |
1175 | lut3 = params->tetrahedral_9.lut3; |
1176 | lut_size0 = sizeof(params->tetrahedral_9.lut0)/ |
1177 | sizeof(params->tetrahedral_9.lut0[0]); |
1178 | lut_size = sizeof(params->tetrahedral_9.lut1)/ |
1179 | sizeof(params->tetrahedral_9.lut1[0]); |
1180 | } |
1181 | |
1182 | mpc3_select_3dlut_ram(mpc, mode, |
1183 | is_color_channel_12bits: is_12bits_color_channel, rmu_idx); |
1184 | mpc3_select_3dlut_ram_mask(mpc, ram_selection_mask: 0x1, rmu_idx); |
1185 | if (is_12bits_color_channel) |
1186 | mpc3_set3dlut_ram12(mpc, lut: lut0, entries: lut_size0, rmu_idx); |
1187 | else |
1188 | mpc3_set3dlut_ram10(mpc, lut: lut0, entries: lut_size0, rmu_idx); |
1189 | |
1190 | mpc3_select_3dlut_ram_mask(mpc, ram_selection_mask: 0x2, rmu_idx); |
1191 | if (is_12bits_color_channel) |
1192 | mpc3_set3dlut_ram12(mpc, lut: lut1, entries: lut_size, rmu_idx); |
1193 | else |
1194 | mpc3_set3dlut_ram10(mpc, lut: lut1, entries: lut_size, rmu_idx); |
1195 | |
1196 | mpc3_select_3dlut_ram_mask(mpc, ram_selection_mask: 0x4, rmu_idx); |
1197 | if (is_12bits_color_channel) |
1198 | mpc3_set3dlut_ram12(mpc, lut: lut2, entries: lut_size, rmu_idx); |
1199 | else |
1200 | mpc3_set3dlut_ram10(mpc, lut: lut2, entries: lut_size, rmu_idx); |
1201 | |
1202 | mpc3_select_3dlut_ram_mask(mpc, ram_selection_mask: 0x8, rmu_idx); |
1203 | if (is_12bits_color_channel) |
1204 | mpc3_set3dlut_ram12(mpc, lut: lut3, entries: lut_size, rmu_idx); |
1205 | else |
1206 | mpc3_set3dlut_ram10(mpc, lut: lut3, entries: lut_size, rmu_idx); |
1207 | |
1208 | mpc3_set_3dlut_mode(mpc, mode, is_color_channel_12bits: is_12bits_color_channel, |
1209 | is_lut_size17x17x17: is_17x17x17, rmu_idx); |
1210 | |
1211 | if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) |
1212 | mpc3_power_on_shaper_3dlut(mpc, rmu_idx, power_on: false); |
1213 | |
1214 | return true; |
1215 | } |
1216 | |
1217 | void mpc3_set_output_csc( |
1218 | struct mpc *mpc, |
1219 | int opp_id, |
1220 | const uint16_t *regval, |
1221 | enum mpc_output_csc_mode ocsc_mode) |
1222 | { |
1223 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
1224 | struct color_matrices_reg ocsc_regs; |
1225 | |
1226 | REG_WRITE(MPC_OUT_CSC_COEF_FORMAT, 0); |
1227 | |
1228 | REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode); |
1229 | |
1230 | if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE) |
1231 | return; |
1232 | |
1233 | if (regval == NULL) { |
1234 | BREAK_TO_DEBUGGER(); |
1235 | return; |
1236 | } |
1237 | |
1238 | ocsc_regs.shifts.csc_c11 = mpc30->mpc_shift->MPC_OCSC_C11_A; |
1239 | ocsc_regs.masks.csc_c11 = mpc30->mpc_mask->MPC_OCSC_C11_A; |
1240 | ocsc_regs.shifts.csc_c12 = mpc30->mpc_shift->MPC_OCSC_C12_A; |
1241 | ocsc_regs.masks.csc_c12 = mpc30->mpc_mask->MPC_OCSC_C12_A; |
1242 | |
1243 | if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) { |
1244 | ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]); |
1245 | ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]); |
1246 | } else { |
1247 | ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]); |
1248 | ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]); |
1249 | } |
1250 | cm_helper_program_color_matrices( |
1251 | ctx: mpc30->base.ctx, |
1252 | regval, |
1253 | reg: &ocsc_regs); |
1254 | } |
1255 | |
1256 | void mpc3_set_ocsc_default( |
1257 | struct mpc *mpc, |
1258 | int opp_id, |
1259 | enum dc_color_space color_space, |
1260 | enum mpc_output_csc_mode ocsc_mode) |
1261 | { |
1262 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
1263 | uint32_t arr_size; |
1264 | struct color_matrices_reg ocsc_regs; |
1265 | const uint16_t *regval = NULL; |
1266 | |
1267 | REG_WRITE(MPC_OUT_CSC_COEF_FORMAT, 0); |
1268 | |
1269 | REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode); |
1270 | if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE) |
1271 | return; |
1272 | |
1273 | regval = find_color_matrix(color_space, array_size: &arr_size); |
1274 | |
1275 | if (regval == NULL) { |
1276 | BREAK_TO_DEBUGGER(); |
1277 | return; |
1278 | } |
1279 | |
1280 | ocsc_regs.shifts.csc_c11 = mpc30->mpc_shift->MPC_OCSC_C11_A; |
1281 | ocsc_regs.masks.csc_c11 = mpc30->mpc_mask->MPC_OCSC_C11_A; |
1282 | ocsc_regs.shifts.csc_c12 = mpc30->mpc_shift->MPC_OCSC_C12_A; |
1283 | ocsc_regs.masks.csc_c12 = mpc30->mpc_mask->MPC_OCSC_C12_A; |
1284 | |
1285 | |
1286 | if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) { |
1287 | ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]); |
1288 | ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]); |
1289 | } else { |
1290 | ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]); |
1291 | ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]); |
1292 | } |
1293 | |
1294 | cm_helper_program_color_matrices( |
1295 | ctx: mpc30->base.ctx, |
1296 | regval, |
1297 | reg: &ocsc_regs); |
1298 | } |
1299 | |
1300 | void mpc3_set_rmu_mux( |
1301 | struct mpc *mpc, |
1302 | int rmu_idx, |
1303 | int value) |
1304 | { |
1305 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
1306 | |
1307 | if (rmu_idx == 0) |
1308 | REG_UPDATE(MPC_RMU_CONTROL, MPC_RMU0_MUX, value); |
1309 | else if (rmu_idx == 1) |
1310 | REG_UPDATE(MPC_RMU_CONTROL, MPC_RMU1_MUX, value); |
1311 | |
1312 | } |
1313 | |
1314 | uint32_t mpc3_get_rmu_mux_status( |
1315 | struct mpc *mpc, |
1316 | int rmu_idx) |
1317 | { |
1318 | uint32_t status = 0xf; |
1319 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
1320 | |
1321 | if (rmu_idx == 0) |
1322 | REG_GET(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, &status); |
1323 | else if (rmu_idx == 1) |
1324 | REG_GET(MPC_RMU_CONTROL, MPC_RMU1_MUX_STATUS, &status); |
1325 | |
1326 | return status; |
1327 | } |
1328 | |
1329 | uint32_t mpcc3_acquire_rmu(struct mpc *mpc, int mpcc_id, int rmu_idx) |
1330 | { |
1331 | uint32_t rmu_status; |
1332 | |
1333 | //determine if this mpcc is already multiplexed to an RMU unit |
1334 | rmu_status = mpc3_get_rmu_mux_status(mpc, rmu_idx); |
1335 | if (rmu_status == mpcc_id) |
1336 | //return rmu_idx of pre_acquired rmu unit |
1337 | return rmu_idx; |
1338 | |
1339 | if (rmu_status == 0xf) {//rmu unit is disabled |
1340 | mpc3_set_rmu_mux(mpc, rmu_idx, value: mpcc_id); |
1341 | return rmu_idx; |
1342 | } |
1343 | |
1344 | //no vacant RMU units or invalid parameters acquire_post_bldn_3dlut |
1345 | return -1; |
1346 | } |
1347 | |
1348 | static int mpcc3_release_rmu(struct mpc *mpc, int mpcc_id) |
1349 | { |
1350 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
1351 | int rmu_idx; |
1352 | uint32_t rmu_status; |
1353 | int released_rmu = -1; |
1354 | |
1355 | for (rmu_idx = 0; rmu_idx < mpc30->num_rmu; rmu_idx++) { |
1356 | rmu_status = mpc3_get_rmu_mux_status(mpc, rmu_idx); |
1357 | if (rmu_status == mpcc_id) { |
1358 | mpc3_set_rmu_mux(mpc, rmu_idx, value: 0xf); |
1359 | released_rmu = rmu_idx; |
1360 | break; |
1361 | } |
1362 | } |
1363 | return released_rmu; |
1364 | |
1365 | } |
1366 | |
1367 | static void mpc3_set_mpc_mem_lp_mode(struct mpc *mpc) |
1368 | { |
1369 | struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); |
1370 | int mpcc_id; |
1371 | |
1372 | if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) { |
1373 | if (mpc30->mpc_mask->MPC_RMU0_MEM_LOW_PWR_MODE && mpc30->mpc_mask->MPC_RMU1_MEM_LOW_PWR_MODE) { |
1374 | REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_LOW_PWR_MODE, 3); |
1375 | REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_LOW_PWR_MODE, 3); |
1376 | } |
1377 | |
1378 | if (mpc30->mpc_mask->MPCC_OGAM_MEM_LOW_PWR_MODE) { |
1379 | for (mpcc_id = 0; mpcc_id < mpc30->num_mpcc; mpcc_id++) |
1380 | REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_LOW_PWR_MODE, 3); |
1381 | } |
1382 | } |
1383 | } |
1384 | |
1385 | static const struct mpc_funcs dcn30_mpc_funcs = { |
1386 | .read_mpcc_state = mpc1_read_mpcc_state, |
1387 | .insert_plane = mpc1_insert_plane, |
1388 | .remove_mpcc = mpc1_remove_mpcc, |
1389 | .mpc_init = mpc1_mpc_init, |
1390 | .mpc_init_single_inst = mpc1_mpc_init_single_inst, |
1391 | .update_blending = mpc2_update_blending, |
1392 | .cursor_lock = mpc1_cursor_lock, |
1393 | .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp, |
1394 | .wait_for_idle = mpc2_assert_idle_mpcc, |
1395 | .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect, |
1396 | .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw, |
1397 | .set_denorm = mpc3_set_denorm, |
1398 | .set_denorm_clamp = mpc3_set_denorm_clamp, |
1399 | .set_output_csc = mpc3_set_output_csc, |
1400 | .set_ocsc_default = mpc3_set_ocsc_default, |
1401 | .set_output_gamma = mpc3_set_output_gamma, |
1402 | .insert_plane_to_secondary = NULL, |
1403 | .remove_mpcc_from_secondary = NULL, |
1404 | .set_dwb_mux = mpc3_set_dwb_mux, |
1405 | .disable_dwb_mux = mpc3_disable_dwb_mux, |
1406 | .is_dwb_idle = mpc3_is_dwb_idle, |
1407 | .set_out_rate_control = mpc3_set_out_rate_control, |
1408 | .set_gamut_remap = mpc3_set_gamut_remap, |
1409 | .program_shaper = mpc3_program_shaper, |
1410 | .acquire_rmu = mpcc3_acquire_rmu, |
1411 | .program_3dlut = mpc3_program_3dlut, |
1412 | .release_rmu = mpcc3_release_rmu, |
1413 | .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut, |
1414 | .get_mpc_out_mux = mpc1_get_mpc_out_mux, |
1415 | .set_bg_color = mpc1_set_bg_color, |
1416 | .set_mpc_mem_lp_mode = mpc3_set_mpc_mem_lp_mode, |
1417 | }; |
1418 | |
1419 | void dcn30_mpc_construct(struct dcn30_mpc *mpc30, |
1420 | struct dc_context *ctx, |
1421 | const struct dcn30_mpc_registers *mpc_regs, |
1422 | const struct dcn30_mpc_shift *mpc_shift, |
1423 | const struct dcn30_mpc_mask *mpc_mask, |
1424 | int num_mpcc, |
1425 | int num_rmu) |
1426 | { |
1427 | int i; |
1428 | |
1429 | mpc30->base.ctx = ctx; |
1430 | |
1431 | mpc30->base.funcs = &dcn30_mpc_funcs; |
1432 | |
1433 | mpc30->mpc_regs = mpc_regs; |
1434 | mpc30->mpc_shift = mpc_shift; |
1435 | mpc30->mpc_mask = mpc_mask; |
1436 | |
1437 | mpc30->mpcc_in_use_mask = 0; |
1438 | mpc30->num_mpcc = num_mpcc; |
1439 | mpc30->num_rmu = num_rmu; |
1440 | |
1441 | for (i = 0; i < MAX_MPCC; i++) |
1442 | mpc3_init_mpcc(mpcc: &mpc30->base.mpcc_array[i], mpcc_inst: i); |
1443 | } |
1444 | |
1445 | |