1 /*
2  * Copyright 2017 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 #include "dcn10_ipp.h"
28 #include "reg_helper.h"
29 
30 #define REG(reg) \
31 	(ippn10->regs->reg)
32 
33 #undef FN
34 #define FN(reg_name, field_name) \
35 	ippn10->ipp_shift->field_name, ippn10->ipp_mask->field_name
36 
37 #define CTX \
38 	ippn10->base.ctx
39 
40 
41 struct dcn10_input_csc_matrix {
42 	enum dc_color_space color_space;
43 	uint32_t regval[12];
44 };
45 
46 static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = {
47 	{COLOR_SPACE_SRGB,
48 		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
49 	{COLOR_SPACE_SRGB_LIMITED,
50 		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
51 	{COLOR_SPACE_YCBCR601,
52 		{0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef,
53 						0, 0x2000, 0x38b4, 0xe3a6} },
54 	{COLOR_SPACE_YCBCR601_LIMITED,
55 		{0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108,
56 						0, 0x2568, 0x40de, 0xdd3a} },
57 	{COLOR_SPACE_YCBCR709,
58 		{0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0,
59 						0x2000, 0x3b61, 0xe24f} },
60 
61 	{COLOR_SPACE_YCBCR709_LIMITED,
62 		{0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0,
63 						0x2568, 0x43ee, 0xdbb2} }
64 };
65 
66 enum dcn10_input_csc_select {
67 	INPUT_CSC_SELECT_BYPASS = 0,
68 	INPUT_CSC_SELECT_ICSC,
69 	INPUT_CSC_SELECT_COMA
70 };
71 
72 static void ippn10_program_input_csc(
73 		struct input_pixel_processor *ipp,
74 		enum dc_color_space color_space,
75 		enum dcn10_input_csc_select select)
76 {
77 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
78 	int i;
79 	int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix);
80 	const uint32_t *regval = NULL;
81 	uint32_t selection = 1;
82 
83 	if (select == INPUT_CSC_SELECT_BYPASS) {
84 		REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0);
85 		return;
86 	}
87 
88 	for (i = 0; i < arr_size; i++)
89 		if (dcn10_input_csc_matrix[i].color_space == color_space) {
90 			regval = dcn10_input_csc_matrix[i].regval;
91 			break;
92 		}
93 
94 	if (regval == NULL) {
95 		BREAK_TO_DEBUGGER();
96 		return;
97 	}
98 
99 	if (select == INPUT_CSC_SELECT_COMA)
100 		selection = 2;
101 	REG_SET(CM_ICSC_CONTROL, 0,
102 			CM_ICSC_MODE, selection);
103 
104 	if (select == INPUT_CSC_SELECT_ICSC) {
105 		/*R*/
106 		REG_SET_2(CM_ICSC_C11_C12, 0,
107 			CM_ICSC_C11, regval[0],
108 			CM_ICSC_C12, regval[1]);
109 		regval += 2;
110 		REG_SET_2(CM_ICSC_C13_C14, 0,
111 			CM_ICSC_C13, regval[0],
112 			CM_ICSC_C14, regval[1]);
113 		/*G*/
114 		regval += 2;
115 		REG_SET_2(CM_ICSC_C21_C22, 0,
116 			CM_ICSC_C21, regval[0],
117 			CM_ICSC_C22, regval[1]);
118 		regval += 2;
119 		REG_SET_2(CM_ICSC_C23_C24, 0,
120 			CM_ICSC_C23, regval[0],
121 			CM_ICSC_C24, regval[1]);
122 		/*B*/
123 		regval += 2;
124 		REG_SET_2(CM_ICSC_C31_C32, 0,
125 			CM_ICSC_C31, regval[0],
126 			CM_ICSC_C32, regval[1]);
127 		regval += 2;
128 		REG_SET_2(CM_ICSC_C33_C34, 0,
129 			CM_ICSC_C33, regval[0],
130 			CM_ICSC_C34, regval[1]);
131 	} else {
132 		/*R*/
133 		REG_SET_2(CM_COMA_C11_C12, 0,
134 			CM_COMA_C11, regval[0],
135 			CM_COMA_C12, regval[1]);
136 		regval += 2;
137 		REG_SET_2(CM_COMA_C13_C14, 0,
138 			CM_COMA_C13, regval[0],
139 			CM_COMA_C14, regval[1]);
140 		/*G*/
141 		regval += 2;
142 		REG_SET_2(CM_COMA_C21_C22, 0,
143 			CM_COMA_C21, regval[0],
144 			CM_COMA_C22, regval[1]);
145 		regval += 2;
146 		REG_SET_2(CM_COMA_C23_C24, 0,
147 			CM_COMA_C23, regval[0],
148 			CM_COMA_C24, regval[1]);
149 		/*B*/
150 		regval += 2;
151 		REG_SET_2(CM_COMA_C31_C32, 0,
152 			CM_COMA_C31, regval[0],
153 			CM_COMA_C32, regval[1]);
154 		regval += 2;
155 		REG_SET_2(CM_COMA_C33_C34, 0,
156 			CM_COMA_C33, regval[0],
157 			CM_COMA_C34, regval[1]);
158 	}
159 }
160 
161 /*program de gamma RAM B*/
162 static void ippn10_program_degamma_lutb_settings(
163 		struct input_pixel_processor *ipp,
164 		const struct pwl_params *params)
165 {
166 	const struct gamma_curve *curve;
167 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
168 
169 	REG_SET_2(CM_DGAM_RAMB_START_CNTL_B, 0,
170 		CM_DGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x,
171 		CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0);
172 
173 	REG_SET_2(CM_DGAM_RAMB_START_CNTL_G, 0,
174 		CM_DGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x,
175 		CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0);
176 
177 	REG_SET_2(CM_DGAM_RAMB_START_CNTL_R, 0,
178 		CM_DGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x,
179 		CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0);
180 
181 	REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_B, 0,
182 		CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope);
183 
184 	REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_G, 0,
185 		CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope);
186 
187 	REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_R, 0,
188 		CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope);
189 
190 	REG_SET(CM_DGAM_RAMB_END_CNTL1_B, 0,
191 		CM_DGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x);
192 
193 	REG_SET_2(CM_DGAM_RAMB_END_CNTL2_B, 0,
194 		CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y,
195 		CM_DGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope);
196 
197 	REG_SET(CM_DGAM_RAMB_END_CNTL1_G, 0,
198 		CM_DGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x);
199 
200 	REG_SET_2(CM_DGAM_RAMB_END_CNTL2_G, 0,
201 		CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y,
202 		CM_DGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope);
203 
204 	REG_SET(CM_DGAM_RAMB_END_CNTL1_R, 0,
205 		CM_DGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x);
206 
207 	REG_SET_2(CM_DGAM_RAMB_END_CNTL2_R, 0,
208 		CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y,
209 		CM_DGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope);
210 
211 	curve = params->arr_curve_points;
212 	REG_SET_4(CM_DGAM_RAMB_REGION_0_1, 0,
213 		CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
214 		CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
215 		CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, 	curve[1].offset,
216 		CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
217 
218 	curve += 2;
219 	REG_SET_4(CM_DGAM_RAMB_REGION_2_3, 0,
220 		CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset,
221 		CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
222 		CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset,
223 		CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
224 
225 	curve += 2;
226 	REG_SET_4(CM_DGAM_RAMB_REGION_4_5, 0,
227 		CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset,
228 		CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
229 		CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset,
230 		CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
231 
232 	curve += 2;
233 	REG_SET_4(CM_DGAM_RAMB_REGION_6_7, 0,
234 		CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset,
235 		CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
236 		CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset,
237 		CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
238 
239 	curve += 2;
240 	REG_SET_4(CM_DGAM_RAMB_REGION_8_9, 0,
241 		CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset,
242 		CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
243 		CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset,
244 		CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
245 
246 	curve += 2;
247 	REG_SET_4(CM_DGAM_RAMB_REGION_10_11, 0,
248 		CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset,
249 		CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
250 		CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset,
251 		CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
252 
253 	curve += 2;
254 	REG_SET_4(CM_DGAM_RAMB_REGION_12_13, 0,
255 		CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset,
256 		CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
257 		CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset,
258 		CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
259 
260 	curve += 2;
261 	REG_SET_4(CM_DGAM_RAMB_REGION_14_15, 0,
262 		CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset,
263 		CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
264 		CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset,
265 		CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
266 }
267 
268 /*program de gamma RAM A*/
269 static void ippn10_program_degamma_luta_settings(
270 		struct input_pixel_processor *ipp,
271 		const struct pwl_params *params)
272 {
273 	const struct gamma_curve *curve;
274 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
275 
276 	REG_SET_2(CM_DGAM_RAMA_START_CNTL_B, 0,
277 		CM_DGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x,
278 		CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0);
279 
280 	REG_SET_2(CM_DGAM_RAMA_START_CNTL_G, 0,
281 		CM_DGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x,
282 		CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0);
283 
284 	REG_SET_2(CM_DGAM_RAMA_START_CNTL_R, 0,
285 		CM_DGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x,
286 		CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0);
287 
288 	REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_B, 0,
289 		CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope);
290 
291 	REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_G, 0,
292 		CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope);
293 
294 	REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_R, 0,
295 		CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope);
296 
297 	REG_SET(CM_DGAM_RAMA_END_CNTL1_B, 0,
298 		CM_DGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x);
299 
300 	REG_SET_2(CM_DGAM_RAMA_END_CNTL2_B, 0,
301 		CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y,
302 		CM_DGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope);
303 
304 	REG_SET(CM_DGAM_RAMA_END_CNTL1_G, 0,
305 		CM_DGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x);
306 
307 	REG_SET_2(CM_DGAM_RAMA_END_CNTL2_G, 0,
308 		CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y,
309 		CM_DGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope);
310 
311 	REG_SET(CM_DGAM_RAMA_END_CNTL1_R, 0,
312 		CM_DGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x);
313 
314 	REG_SET_2(CM_DGAM_RAMA_END_CNTL2_R, 0,
315 		CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y,
316 		CM_DGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope);
317 
318 	curve = params->arr_curve_points;
319 	REG_SET_4(CM_DGAM_RAMA_REGION_0_1, 0,
320 		CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
321 		CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
322 		CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
323 		CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
324 
325 	curve += 2;
326 	REG_SET_4(CM_DGAM_RAMA_REGION_2_3, 0,
327 		CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset,
328 		CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
329 		CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset,
330 		CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
331 
332 	curve += 2;
333 	REG_SET_4(CM_DGAM_RAMA_REGION_4_5, 0,
334 		CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset,
335 		CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
336 		CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset,
337 		CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
338 
339 	curve += 2;
340 	REG_SET_4(CM_DGAM_RAMA_REGION_6_7, 0,
341 		CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset,
342 		CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
343 		CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset,
344 		CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
345 
346 	curve += 2;
347 	REG_SET_4(CM_DGAM_RAMA_REGION_8_9, 0,
348 		CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset,
349 		CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
350 		CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset,
351 		CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
352 
353 	curve += 2;
354 	REG_SET_4(CM_DGAM_RAMA_REGION_10_11, 0,
355 		CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset,
356 		CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
357 		CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset,
358 		CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
359 
360 	curve += 2;
361 	REG_SET_4(CM_DGAM_RAMA_REGION_12_13, 0,
362 		CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset,
363 		CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
364 		CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset,
365 		CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
366 
367 	curve += 2;
368 	REG_SET_4(CM_DGAM_RAMA_REGION_14_15, 0,
369 		CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset,
370 		CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
371 		CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset,
372 		CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
373 }
374 
375 static void ippn10_power_on_degamma_lut(
376 	struct input_pixel_processor *ipp,
377 	bool power_on)
378 {
379 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
380 
381 	REG_SET(CM_MEM_PWR_CTRL, 0,
382 			SHARED_MEM_PWR_DIS, power_on == true ? 0:1);
383 
384 }
385 
386 static void ippn10_program_degamma_lut(
387 		struct input_pixel_processor *ipp,
388 		const struct pwl_result_data *rgb,
389 		uint32_t num,
390 		bool is_ram_a)
391 {
392 	uint32_t i;
393 
394 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
395 	REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0);
396 	REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK,
397 				   CM_DGAM_LUT_WRITE_EN_MASK, 7);
398 	REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL,
399 					is_ram_a == true ? 0:1);
400 
401 	REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0);
402 	for (i = 0 ; i < num; i++) {
403 		REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg);
404 		REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg);
405 		REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg);
406 
407 		REG_SET(CM_DGAM_LUT_DATA, 0,
408 				CM_DGAM_LUT_DATA, rgb[i].delta_red_reg);
409 		REG_SET(CM_DGAM_LUT_DATA, 0,
410 				CM_DGAM_LUT_DATA, rgb[i].delta_green_reg);
411 		REG_SET(CM_DGAM_LUT_DATA, 0,
412 				CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg);
413 	}
414 }
415 
416 static void ippn10_enable_cm_block(
417 		struct input_pixel_processor *ipp)
418 {
419 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
420 
421 	REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1);
422 	REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0);
423 }
424 
425 static void ippn10_full_bypass(struct input_pixel_processor *ipp)
426 {
427 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
428 
429 	/* Input pixel format: ARGB8888 */
430 	REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0,
431 			CNVC_SURFACE_PIXEL_FORMAT, 0x8);
432 
433 	/* Zero expansion */
434 	REG_SET_3(FORMAT_CONTROL, 0,
435 			CNVC_BYPASS, 0,
436 			ALPHA_EN, 0,
437 			FORMAT_EXPANSION_MODE, 0);
438 
439 	/* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */
440 	REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1);
441 
442 	/* Setting degamma bypass for now */
443 	REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0);
444 	REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0);
445 }
446 
447 static void ippn10_set_degamma(
448 		struct input_pixel_processor *ipp,
449 		enum ipp_degamma_mode mode)
450 {
451 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
452 	ippn10_enable_cm_block(ipp);
453 
454 	switch (mode) {
455 	case IPP_DEGAMMA_MODE_BYPASS:
456 		/* Setting de gamma bypass for now */
457 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0);
458 		break;
459 	case IPP_DEGAMMA_MODE_HW_sRGB:
460 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1);
461 		break;
462 	case IPP_DEGAMMA_MODE_HW_xvYCC:
463 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2);
464 			break;
465 	default:
466 		BREAK_TO_DEBUGGER();
467 		break;
468 	}
469 }
470 
471 static bool ippn10_cursor_program_control(
472 		struct dcn10_ipp *ippn10,
473 		bool pixel_data_invert,
474 		enum dc_cursor_color_format color_format)
475 {
476 	REG_SET_2(CURSOR_SETTINS, 0,
477 			/* no shift of the cursor HDL schedule */
478 			CURSOR0_DST_Y_OFFSET, 0,
479 			 /* used to shift the cursor chunk request deadline */
480 			CURSOR0_CHUNK_HDL_ADJUST, 3);
481 
482 	REG_UPDATE_2(CURSOR0_CONTROL,
483 			CUR0_MODE, color_format,
484 			CUR0_EXPANSION_MODE, 0);
485 
486 	if (color_format == CURSOR_MODE_MONO) {
487 		/* todo: clarify what to program these to */
488 		REG_UPDATE(CURSOR0_COLOR0,
489 				CUR0_COLOR0, 0x00000000);
490 		REG_UPDATE(CURSOR0_COLOR1,
491 				CUR0_COLOR1, 0xFFFFFFFF);
492 	}
493 
494 	/* TODO: Fixed vs float */
495 
496 	REG_UPDATE_3(FORMAT_CONTROL,
497 				CNVC_BYPASS, 0,
498 				ALPHA_EN, 1,
499 				FORMAT_EXPANSION_MODE, 0);
500 
501 	return true;
502 }
503 
504 enum cursor_pitch {
505 	CURSOR_PITCH_64_PIXELS = 0,
506 	CURSOR_PITCH_128_PIXELS,
507 	CURSOR_PITCH_256_PIXELS
508 };
509 
510 enum cursor_lines_per_chunk {
511 	CURSOR_LINE_PER_CHUNK_2 = 1,
512 	CURSOR_LINE_PER_CHUNK_4,
513 	CURSOR_LINE_PER_CHUNK_8,
514 	CURSOR_LINE_PER_CHUNK_16
515 };
516 
517 static enum cursor_pitch ippn10_get_cursor_pitch(
518 		unsigned int pitch)
519 {
520 	enum cursor_pitch hw_pitch;
521 
522 	switch (pitch) {
523 	case 64:
524 		hw_pitch = CURSOR_PITCH_64_PIXELS;
525 		break;
526 	case 128:
527 		hw_pitch = CURSOR_PITCH_128_PIXELS;
528 		break;
529 	case 256:
530 		hw_pitch = CURSOR_PITCH_256_PIXELS;
531 		break;
532 	default:
533 		DC_ERR("Invalid cursor pitch of %d. "
534 				"Only 64/128/256 is supported on DCN.\n", pitch);
535 		hw_pitch = CURSOR_PITCH_64_PIXELS;
536 		break;
537 	}
538 	return hw_pitch;
539 }
540 
541 static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk(
542 		unsigned int cur_width,
543 		enum dc_cursor_color_format format)
544 {
545 	enum cursor_lines_per_chunk line_per_chunk;
546 
547 	if (format == CURSOR_MODE_MONO)
548 		/* impl B. expansion in CUR Buffer reader */
549 		line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
550 	else if (cur_width <= 32)
551 		line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
552 	else if (cur_width <= 64)
553 		line_per_chunk = CURSOR_LINE_PER_CHUNK_8;
554 	else if (cur_width <= 128)
555 		line_per_chunk = CURSOR_LINE_PER_CHUNK_4;
556 	else
557 		line_per_chunk = CURSOR_LINE_PER_CHUNK_2;
558 
559 	return line_per_chunk;
560 }
561 
562 static void ippn10_cursor_set_attributes(
563 		struct input_pixel_processor *ipp,
564 		const struct dc_cursor_attributes *attr)
565 {
566 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
567 	enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch);
568 	enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk(
569 			attr->width, attr->color_format);
570 
571 	ippn10->curs_attr = *attr;
572 
573 	REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH,
574 			CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part);
575 	REG_UPDATE(CURSOR_SURFACE_ADDRESS,
576 			CURSOR_SURFACE_ADDRESS, attr->address.low_part);
577 
578 	REG_UPDATE_2(CURSOR_SIZE,
579 			CURSOR_WIDTH, attr->width,
580 			CURSOR_HEIGHT, attr->height);
581 
582 	REG_UPDATE_3(CURSOR_CONTROL,
583 			CURSOR_MODE, attr->color_format,
584 			CURSOR_PITCH, hw_pitch,
585 			CURSOR_LINES_PER_CHUNK, lpc);
586 
587 	ippn10_cursor_program_control(ippn10,
588 			attr->attribute_flags.bits.INVERT_PIXEL_DATA,
589 			attr->color_format);
590 }
591 
592 static void ippn10_cursor_set_position(
593 		struct input_pixel_processor *ipp,
594 		const struct dc_cursor_position *pos,
595 		const struct dc_cursor_mi_param *param)
596 {
597 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
598 	int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start;
599 	uint32_t cur_en = pos->enable ? 1 : 0;
600 	uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
601 
602 	/*
603 	 * Guard aganst cursor_set_position() from being called with invalid
604 	 * attributes
605 	 *
606 	 * TODO: Look at combining cursor_set_position() and
607 	 * cursor_set_attributes() into cursor_update()
608 	 */
609 	if (ippn10->curs_attr.address.quad_part == 0)
610 		return;
611 
612 	dst_x_offset *= param->ref_clk_khz;
613 	dst_x_offset /= param->pixel_clk_khz;
614 
615 	ASSERT(param->h_scale_ratio.value);
616 
617 	if (param->h_scale_ratio.value)
618 		dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div(
619 				dal_fixed31_32_from_int(dst_x_offset),
620 				param->h_scale_ratio));
621 
622 	if (src_x_offset >= (int)param->viewport_width)
623 		cur_en = 0;  /* not visible beyond right edge*/
624 
625 	if (src_x_offset + (int)ippn10->curs_attr.width < 0)
626 		cur_en = 0;  /* not visible beyond left edge*/
627 
628 	if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
629 		ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr);
630 	REG_UPDATE(CURSOR_CONTROL,
631 			CURSOR_ENABLE, cur_en);
632 	REG_UPDATE(CURSOR0_CONTROL,
633 			CUR0_ENABLE, cur_en);
634 
635 	REG_SET_2(CURSOR_POSITION, 0,
636 			CURSOR_X_POSITION, pos->x,
637 			CURSOR_Y_POSITION, pos->y);
638 
639 	REG_SET_2(CURSOR_HOT_SPOT, 0,
640 			CURSOR_HOT_SPOT_X, pos->x_hotspot,
641 			CURSOR_HOT_SPOT_Y, pos->y_hotspot);
642 
643 	REG_SET(CURSOR_DST_OFFSET, 0,
644 			CURSOR_DST_X_OFFSET, dst_x_offset);
645 	/* TODO Handle surface pixel formats other than 4:4:4 */
646 }
647 
648 enum pixel_format_description {
649 	PIXEL_FORMAT_FIXED = 0,
650 	PIXEL_FORMAT_FIXED16,
651 	PIXEL_FORMAT_FLOAT
652 
653 };
654 
655 static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\
656 						enum pixel_format_description *fmt)
657 {
658 
659 	if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F ||
660 		input_format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F)
661 		*fmt = PIXEL_FORMAT_FLOAT;
662 	else if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
663 		*fmt = PIXEL_FORMAT_FIXED16;
664 	else
665 		*fmt = PIXEL_FORMAT_FIXED;
666 }
667 
668 static void ippn10_set_degamma_format_float(struct input_pixel_processor *ipp,
669 		bool is_float)
670 {
671 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
672 
673 	if (is_float) {
674 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3);
675 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 1);
676 	} else {
677 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 2);
678 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 0);
679 	}
680 }
681 
682 
683 static void ippn10_cnv_setup (
684 		struct input_pixel_processor *ipp,
685 		enum surface_pixel_format input_format,
686 		enum expansion_mode mode,
687 		enum ipp_output_format cnv_out_format)
688 {
689 	uint32_t pixel_format;
690 	uint32_t alpha_en;
691 	enum pixel_format_description fmt ;
692 	enum dc_color_space color_space;
693 	enum dcn10_input_csc_select select;
694 	bool is_float;
695 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
696 	bool force_disable_cursor = false;
697 
698 	ippn10_setup_format_flags(input_format, &fmt);
699 	alpha_en = 1;
700 	pixel_format = 0;
701 	color_space = COLOR_SPACE_SRGB;
702 	select = INPUT_CSC_SELECT_BYPASS;
703 	is_float = false;
704 
705 	switch (fmt) {
706 	case PIXEL_FORMAT_FIXED:
707 	case PIXEL_FORMAT_FIXED16:
708 	/*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/
709 		REG_SET_3(FORMAT_CONTROL, 0,
710 			CNVC_BYPASS, 0,
711 			FORMAT_EXPANSION_MODE, mode,
712 			OUTPUT_FP, 0);
713 		break;
714 	case PIXEL_FORMAT_FLOAT:
715 		REG_SET_3(FORMAT_CONTROL, 0,
716 			CNVC_BYPASS, 0,
717 			FORMAT_EXPANSION_MODE, mode,
718 			OUTPUT_FP, 1);
719 		is_float = true;
720 		break;
721 	default:
722 
723 		break;
724 	}
725 
726 	ippn10_set_degamma_format_float(ipp, is_float);
727 
728 	switch (input_format) {
729 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
730 		pixel_format = 1;
731 		break;
732 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
733 		pixel_format = 3;
734 		alpha_en = 0;
735 		break;
736 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
737 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
738 		pixel_format = 8;
739 		break;
740 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
741 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
742 		pixel_format = 10;
743 		break;
744 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
745 		force_disable_cursor = false;
746 		pixel_format = 65;
747 		color_space = COLOR_SPACE_YCBCR709;
748 		select = INPUT_CSC_SELECT_ICSC;
749 		break;
750 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
751 		force_disable_cursor = true;
752 		pixel_format = 64;
753 		color_space = COLOR_SPACE_YCBCR709;
754 		select = INPUT_CSC_SELECT_ICSC;
755 		break;
756 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
757 		force_disable_cursor = true;
758 		pixel_format = 67;
759 		color_space = COLOR_SPACE_YCBCR709;
760 		select = INPUT_CSC_SELECT_ICSC;
761 		break;
762 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
763 		force_disable_cursor = true;
764 		pixel_format = 66;
765 		color_space = COLOR_SPACE_YCBCR709;
766 		select = INPUT_CSC_SELECT_ICSC;
767 		break;
768 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
769 		pixel_format = 22;
770 		break;
771 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
772 		pixel_format = 24;
773 		break;
774 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
775 		pixel_format = 25;
776 		break;
777 	default:
778 		break;
779 	}
780 	REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0,
781 			CNVC_SURFACE_PIXEL_FORMAT, pixel_format);
782 	REG_UPDATE(FORMAT_CONTROL, ALPHA_EN, alpha_en);
783 
784 	ippn10_program_input_csc(ipp, color_space, select);
785 
786 	if (force_disable_cursor) {
787 		REG_UPDATE(CURSOR_CONTROL,
788 				CURSOR_ENABLE, 0);
789 		REG_UPDATE(CURSOR0_CONTROL,
790 				CUR0_ENABLE, 0);
791 	}
792 }
793 
794 
795 static bool ippn10_degamma_ram_inuse(struct input_pixel_processor *ipp,
796 							bool *ram_a_inuse)
797 {
798 	bool ret = false;
799 	uint32_t status_reg = 0;
800 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
801 
802 	REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
803 			&status_reg);
804 
805 	if (status_reg == 9) {
806 		*ram_a_inuse = true;
807 		ret = true;
808 	} else if (status_reg == 10) {
809 		*ram_a_inuse = false;
810 		ret = true;
811 	}
812 	return ret;
813 }
814 
815 static bool ippn10_ingamma_ram_inuse(struct input_pixel_processor *ipp,
816 							bool *ram_a_inuse)
817 {
818 	bool in_use = false;
819 	uint32_t status_reg = 0;
820 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
821 
822 	REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
823 				&status_reg);
824 
825 	// 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB
826 	if (status_reg == 1 || status_reg == 3 || status_reg == 4) {
827 		*ram_a_inuse = true;
828 		in_use = true;
829 	// 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB
830 	} else if (status_reg == 2 || status_reg == 5 || status_reg == 6) {
831 		*ram_a_inuse = false;
832 		in_use = true;
833 	}
834 	return in_use;
835 }
836 
837 static void ippn10_degamma_ram_select(struct input_pixel_processor *ipp,
838 							bool use_ram_a)
839 {
840 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
841 
842 	if (use_ram_a)
843 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3);
844 	else
845 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 4);
846 
847 }
848 
849 static void ippn10_set_degamma_pwl(struct input_pixel_processor *ipp,
850 								 const struct pwl_params *params)
851 {
852 	bool is_ram_a = true;
853 
854 	ippn10_power_on_degamma_lut(ipp, true);
855 	ippn10_enable_cm_block(ipp);
856 	ippn10_degamma_ram_inuse(ipp, &is_ram_a);
857 	if (is_ram_a == true)
858 		ippn10_program_degamma_lutb_settings(ipp, params);
859 	else
860 		ippn10_program_degamma_luta_settings(ipp, params);
861 
862 	ippn10_program_degamma_lut(ipp, params->rgb_resulted,
863 							params->hw_points_num, !is_ram_a);
864 	ippn10_degamma_ram_select(ipp, !is_ram_a);
865 }
866 
867 /*
868  * Input gamma LUT currently supports 256 values only. This means input color
869  * can have a maximum of 8 bits per channel (= 256 possible values) in order to
870  * have a one-to-one mapping with the LUT. Truncation will occur with color
871  * values greater than 8 bits.
872  *
873  * In the future, this function should support additional input gamma methods,
874  * such as piecewise linear mapping, and input gamma bypass.
875  */
876 static void ippn10_program_input_lut(
877 		struct input_pixel_processor *ipp,
878 		const struct dc_gamma *gamma)
879 {
880 	int i;
881 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
882 	bool rama_occupied = false;
883 	uint32_t ram_num;
884 	// Power on LUT memory.
885 	REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1);
886 	ippn10_enable_cm_block(ipp);
887 	// Determine whether to use RAM A or RAM B
888 	ippn10_ingamma_ram_inuse(ipp, &rama_occupied);
889 	if (!rama_occupied)
890 		REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0);
891 	else
892 		REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1);
893 	// RW mode is 256-entry LUT
894 	REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0);
895 	// IGAM Input format should be 8 bits per channel.
896 	REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0);
897 	// Do not mask any R,G,B values
898 	REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7);
899 	// LUT-256, unsigned, integer, new u0.12 format
900 	REG_UPDATE_3(
901 		CM_IGAM_CONTROL,
902 		CM_IGAM_LUT_FORMAT_R, 3,
903 		CM_IGAM_LUT_FORMAT_G, 3,
904 		CM_IGAM_LUT_FORMAT_B, 3);
905 	// Start at index 0 of IGAM LUT
906 	REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0);
907 	for (i = 0; i < INPUT_LUT_ENTRIES; i++) {
908 		REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
909 					gamma->red[i]);
910 		REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
911 					gamma->green[i]);
912 		REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
913 					gamma->blue[i]);
914 	}
915 	// Power off LUT memory
916 	REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0);
917 	// Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB
918 	REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2);
919 	REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num);
920 }
921 
922 /*****************************************/
923 /* Constructor, Destructor               */
924 /*****************************************/
925 
926 static void dcn10_ipp_destroy(struct input_pixel_processor **ipp)
927 {
928 	dm_free(TO_DCN10_IPP(*ipp));
929 	*ipp = NULL;
930 }
931 
932 static const struct ipp_funcs dcn10_ipp_funcs = {
933 	.ipp_cursor_set_attributes	= ippn10_cursor_set_attributes,
934 	.ipp_cursor_set_position	= ippn10_cursor_set_position,
935 	.ipp_set_degamma		= ippn10_set_degamma,
936 	.ipp_program_input_lut		= ippn10_program_input_lut,
937 	.ipp_full_bypass		= ippn10_full_bypass,
938 	.ipp_setup			= ippn10_cnv_setup,
939 	.ipp_program_degamma_pwl	= ippn10_set_degamma_pwl,
940 	.ipp_destroy			= dcn10_ipp_destroy
941 };
942 
943 void dcn10_ipp_construct(
944 	struct dcn10_ipp *ippn10,
945 	struct dc_context *ctx,
946 	int inst,
947 	const struct dcn10_ipp_registers *regs,
948 	const struct dcn10_ipp_shift *ipp_shift,
949 	const struct dcn10_ipp_mask *ipp_mask)
950 {
951 	ippn10->base.ctx = ctx;
952 	ippn10->base.inst = inst;
953 	ippn10->base.funcs = &dcn10_ipp_funcs;
954 
955 	ippn10->regs = regs;
956 	ippn10->ipp_shift = ipp_shift;
957 	ippn10->ipp_mask = ipp_mask;
958 }
959 
960