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(CM_CONTROL, CM_BYPASS_EN, 0);
422 }
423 
424 static void ippn10_full_bypass(struct input_pixel_processor *ipp)
425 {
426 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
427 
428 	/* Input pixel format: ARGB8888 */
429 	REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0,
430 			CNVC_SURFACE_PIXEL_FORMAT, 0x8);
431 
432 	/* Zero expansion */
433 	REG_SET_3(FORMAT_CONTROL, 0,
434 			CNVC_BYPASS, 0,
435 			ALPHA_EN, 0,
436 			FORMAT_EXPANSION_MODE, 0);
437 
438 	/* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */
439 	REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1);
440 
441 	/* Setting degamma bypass for now */
442 	REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0);
443 	REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0);
444 }
445 
446 static void ippn10_set_degamma(
447 		struct input_pixel_processor *ipp,
448 		enum ipp_degamma_mode mode)
449 {
450 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
451 	ippn10_enable_cm_block(ipp);
452 
453 	switch (mode) {
454 	case IPP_DEGAMMA_MODE_BYPASS:
455 		/* Setting de gamma bypass for now */
456 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0);
457 		break;
458 	case IPP_DEGAMMA_MODE_HW_sRGB:
459 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1);
460 		break;
461 	case IPP_DEGAMMA_MODE_HW_xvYCC:
462 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2);
463 			break;
464 	default:
465 		BREAK_TO_DEBUGGER();
466 		break;
467 	}
468 }
469 
470 static bool ippn10_cursor_program_control(
471 		struct dcn10_ipp *ippn10,
472 		bool pixel_data_invert,
473 		enum dc_cursor_color_format color_format)
474 {
475 	if (REG(CURSOR_SETTINS))
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 	else
482 		REG_SET_2(CURSOR_SETTINGS, 0,
483 				/* no shift of the cursor HDL schedule */
484 				CURSOR0_DST_Y_OFFSET, 0,
485 				 /* used to shift the cursor chunk request deadline */
486 				CURSOR0_CHUNK_HDL_ADJUST, 3);
487 
488 	REG_UPDATE_2(CURSOR0_CONTROL,
489 			CUR0_MODE, color_format,
490 			CUR0_EXPANSION_MODE, 0);
491 
492 	if (color_format == CURSOR_MODE_MONO) {
493 		/* todo: clarify what to program these to */
494 		REG_UPDATE(CURSOR0_COLOR0,
495 				CUR0_COLOR0, 0x00000000);
496 		REG_UPDATE(CURSOR0_COLOR1,
497 				CUR0_COLOR1, 0xFFFFFFFF);
498 	}
499 
500 	/* TODO: Fixed vs float */
501 
502 	REG_UPDATE_3(FORMAT_CONTROL,
503 				CNVC_BYPASS, 0,
504 				ALPHA_EN, 1,
505 				FORMAT_EXPANSION_MODE, 0);
506 
507 	return true;
508 }
509 
510 enum cursor_pitch {
511 	CURSOR_PITCH_64_PIXELS = 0,
512 	CURSOR_PITCH_128_PIXELS,
513 	CURSOR_PITCH_256_PIXELS
514 };
515 
516 enum cursor_lines_per_chunk {
517 	CURSOR_LINE_PER_CHUNK_2 = 1,
518 	CURSOR_LINE_PER_CHUNK_4,
519 	CURSOR_LINE_PER_CHUNK_8,
520 	CURSOR_LINE_PER_CHUNK_16
521 };
522 
523 static enum cursor_pitch ippn10_get_cursor_pitch(
524 		unsigned int pitch)
525 {
526 	enum cursor_pitch hw_pitch;
527 
528 	switch (pitch) {
529 	case 64:
530 		hw_pitch = CURSOR_PITCH_64_PIXELS;
531 		break;
532 	case 128:
533 		hw_pitch = CURSOR_PITCH_128_PIXELS;
534 		break;
535 	case 256:
536 		hw_pitch = CURSOR_PITCH_256_PIXELS;
537 		break;
538 	default:
539 		DC_ERR("Invalid cursor pitch of %d. "
540 				"Only 64/128/256 is supported on DCN.\n", pitch);
541 		hw_pitch = CURSOR_PITCH_64_PIXELS;
542 		break;
543 	}
544 	return hw_pitch;
545 }
546 
547 static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk(
548 		unsigned int cur_width,
549 		enum dc_cursor_color_format format)
550 {
551 	enum cursor_lines_per_chunk line_per_chunk;
552 
553 	if (format == CURSOR_MODE_MONO)
554 		/* impl B. expansion in CUR Buffer reader */
555 		line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
556 	else if (cur_width <= 32)
557 		line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
558 	else if (cur_width <= 64)
559 		line_per_chunk = CURSOR_LINE_PER_CHUNK_8;
560 	else if (cur_width <= 128)
561 		line_per_chunk = CURSOR_LINE_PER_CHUNK_4;
562 	else
563 		line_per_chunk = CURSOR_LINE_PER_CHUNK_2;
564 
565 	return line_per_chunk;
566 }
567 
568 static void ippn10_cursor_set_attributes(
569 		struct input_pixel_processor *ipp,
570 		const struct dc_cursor_attributes *attr)
571 {
572 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
573 	enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch);
574 	enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk(
575 			attr->width, attr->color_format);
576 
577 	ippn10->curs_attr = *attr;
578 
579 	REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH,
580 			CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part);
581 	REG_UPDATE(CURSOR_SURFACE_ADDRESS,
582 			CURSOR_SURFACE_ADDRESS, attr->address.low_part);
583 
584 	REG_UPDATE_2(CURSOR_SIZE,
585 			CURSOR_WIDTH, attr->width,
586 			CURSOR_HEIGHT, attr->height);
587 
588 	REG_UPDATE_3(CURSOR_CONTROL,
589 			CURSOR_MODE, attr->color_format,
590 			CURSOR_PITCH, hw_pitch,
591 			CURSOR_LINES_PER_CHUNK, lpc);
592 
593 	ippn10_cursor_program_control(ippn10,
594 			attr->attribute_flags.bits.INVERT_PIXEL_DATA,
595 			attr->color_format);
596 }
597 
598 static void ippn10_cursor_set_position(
599 		struct input_pixel_processor *ipp,
600 		const struct dc_cursor_position *pos,
601 		const struct dc_cursor_mi_param *param)
602 {
603 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
604 	int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start;
605 	uint32_t cur_en = pos->enable ? 1 : 0;
606 	uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
607 
608 	/*
609 	 * Guard aganst cursor_set_position() from being called with invalid
610 	 * attributes
611 	 *
612 	 * TODO: Look at combining cursor_set_position() and
613 	 * cursor_set_attributes() into cursor_update()
614 	 */
615 	if (ippn10->curs_attr.address.quad_part == 0)
616 		return;
617 
618 	dst_x_offset *= param->ref_clk_khz;
619 	dst_x_offset /= param->pixel_clk_khz;
620 
621 	ASSERT(param->h_scale_ratio.value);
622 
623 	if (param->h_scale_ratio.value)
624 		dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div(
625 				dal_fixed31_32_from_int(dst_x_offset),
626 				param->h_scale_ratio));
627 
628 	if (src_x_offset >= (int)param->viewport_width)
629 		cur_en = 0;  /* not visible beyond right edge*/
630 
631 	if (src_x_offset + (int)ippn10->curs_attr.width < 0)
632 		cur_en = 0;  /* not visible beyond left edge*/
633 
634 	if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
635 		ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr);
636 	REG_UPDATE(CURSOR_CONTROL,
637 			CURSOR_ENABLE, cur_en);
638 	REG_UPDATE(CURSOR0_CONTROL,
639 			CUR0_ENABLE, cur_en);
640 
641 	REG_SET_2(CURSOR_POSITION, 0,
642 			CURSOR_X_POSITION, pos->x,
643 			CURSOR_Y_POSITION, pos->y);
644 
645 	REG_SET_2(CURSOR_HOT_SPOT, 0,
646 			CURSOR_HOT_SPOT_X, pos->x_hotspot,
647 			CURSOR_HOT_SPOT_Y, pos->y_hotspot);
648 
649 	REG_SET(CURSOR_DST_OFFSET, 0,
650 			CURSOR_DST_X_OFFSET, dst_x_offset);
651 	/* TODO Handle surface pixel formats other than 4:4:4 */
652 }
653 
654 enum pixel_format_description {
655 	PIXEL_FORMAT_FIXED = 0,
656 	PIXEL_FORMAT_FIXED16,
657 	PIXEL_FORMAT_FLOAT
658 
659 };
660 
661 static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\
662 						enum pixel_format_description *fmt)
663 {
664 
665 	if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F ||
666 		input_format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F)
667 		*fmt = PIXEL_FORMAT_FLOAT;
668 	else if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
669 		*fmt = PIXEL_FORMAT_FIXED16;
670 	else
671 		*fmt = PIXEL_FORMAT_FIXED;
672 }
673 
674 static void ippn10_set_degamma_format_float(struct input_pixel_processor *ipp,
675 		bool is_float)
676 {
677 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
678 
679 	if (is_float) {
680 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3);
681 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 1);
682 	} else {
683 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 2);
684 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 0);
685 	}
686 }
687 
688 
689 static void ippn10_cnv_setup (
690 		struct input_pixel_processor *ipp,
691 		enum surface_pixel_format input_format,
692 		enum expansion_mode mode,
693 		enum ipp_output_format cnv_out_format)
694 {
695 	uint32_t pixel_format;
696 	uint32_t alpha_en;
697 	enum pixel_format_description fmt ;
698 	enum dc_color_space color_space;
699 	enum dcn10_input_csc_select select;
700 	bool is_float;
701 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
702 	bool force_disable_cursor = false;
703 
704 	ippn10_setup_format_flags(input_format, &fmt);
705 	alpha_en = 1;
706 	pixel_format = 0;
707 	color_space = COLOR_SPACE_SRGB;
708 	select = INPUT_CSC_SELECT_BYPASS;
709 	is_float = false;
710 
711 	switch (fmt) {
712 	case PIXEL_FORMAT_FIXED:
713 	case PIXEL_FORMAT_FIXED16:
714 	/*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/
715 		REG_SET_3(FORMAT_CONTROL, 0,
716 			CNVC_BYPASS, 0,
717 			FORMAT_EXPANSION_MODE, mode,
718 			OUTPUT_FP, 0);
719 		break;
720 	case PIXEL_FORMAT_FLOAT:
721 		REG_SET_3(FORMAT_CONTROL, 0,
722 			CNVC_BYPASS, 0,
723 			FORMAT_EXPANSION_MODE, mode,
724 			OUTPUT_FP, 1);
725 		is_float = true;
726 		break;
727 	default:
728 
729 		break;
730 	}
731 
732 	ippn10_set_degamma_format_float(ipp, is_float);
733 
734 	switch (input_format) {
735 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
736 		pixel_format = 1;
737 		break;
738 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
739 		pixel_format = 3;
740 		alpha_en = 0;
741 		break;
742 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
743 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
744 		pixel_format = 8;
745 		break;
746 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
747 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
748 		pixel_format = 10;
749 		break;
750 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
751 		force_disable_cursor = false;
752 		pixel_format = 65;
753 		color_space = COLOR_SPACE_YCBCR709;
754 		select = INPUT_CSC_SELECT_ICSC;
755 		break;
756 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
757 		force_disable_cursor = true;
758 		pixel_format = 64;
759 		color_space = COLOR_SPACE_YCBCR709;
760 		select = INPUT_CSC_SELECT_ICSC;
761 		break;
762 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
763 		force_disable_cursor = true;
764 		pixel_format = 67;
765 		color_space = COLOR_SPACE_YCBCR709;
766 		select = INPUT_CSC_SELECT_ICSC;
767 		break;
768 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
769 		force_disable_cursor = true;
770 		pixel_format = 66;
771 		color_space = COLOR_SPACE_YCBCR709;
772 		select = INPUT_CSC_SELECT_ICSC;
773 		break;
774 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
775 		pixel_format = 22;
776 		break;
777 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
778 		pixel_format = 24;
779 		break;
780 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
781 		pixel_format = 25;
782 		break;
783 	default:
784 		break;
785 	}
786 	REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0,
787 			CNVC_SURFACE_PIXEL_FORMAT, pixel_format);
788 	REG_UPDATE(FORMAT_CONTROL, ALPHA_EN, alpha_en);
789 
790 	ippn10_program_input_csc(ipp, color_space, select);
791 
792 	if (force_disable_cursor) {
793 		REG_UPDATE(CURSOR_CONTROL,
794 				CURSOR_ENABLE, 0);
795 		REG_UPDATE(CURSOR0_CONTROL,
796 				CUR0_ENABLE, 0);
797 	}
798 }
799 
800 
801 static bool ippn10_degamma_ram_inuse(struct input_pixel_processor *ipp,
802 							bool *ram_a_inuse)
803 {
804 	bool ret = false;
805 	uint32_t status_reg = 0;
806 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
807 
808 	REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
809 			&status_reg);
810 
811 	if (status_reg == 9) {
812 		*ram_a_inuse = true;
813 		ret = true;
814 	} else if (status_reg == 10) {
815 		*ram_a_inuse = false;
816 		ret = true;
817 	}
818 	return ret;
819 }
820 
821 static bool ippn10_ingamma_ram_inuse(struct input_pixel_processor *ipp,
822 							bool *ram_a_inuse)
823 {
824 	bool in_use = false;
825 	uint32_t status_reg = 0;
826 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
827 
828 	REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
829 				&status_reg);
830 
831 	// 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB
832 	if (status_reg == 1 || status_reg == 3 || status_reg == 4) {
833 		*ram_a_inuse = true;
834 		in_use = true;
835 	// 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB
836 	} else if (status_reg == 2 || status_reg == 5 || status_reg == 6) {
837 		*ram_a_inuse = false;
838 		in_use = true;
839 	}
840 	return in_use;
841 }
842 
843 static void ippn10_degamma_ram_select(struct input_pixel_processor *ipp,
844 							bool use_ram_a)
845 {
846 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
847 
848 	if (use_ram_a)
849 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3);
850 	else
851 		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 4);
852 
853 }
854 
855 static void ippn10_set_degamma_pwl(struct input_pixel_processor *ipp,
856 								 const struct pwl_params *params)
857 {
858 	bool is_ram_a = true;
859 
860 	ippn10_power_on_degamma_lut(ipp, true);
861 	ippn10_enable_cm_block(ipp);
862 	ippn10_degamma_ram_inuse(ipp, &is_ram_a);
863 	if (is_ram_a == true)
864 		ippn10_program_degamma_lutb_settings(ipp, params);
865 	else
866 		ippn10_program_degamma_luta_settings(ipp, params);
867 
868 	ippn10_program_degamma_lut(ipp, params->rgb_resulted,
869 							params->hw_points_num, !is_ram_a);
870 	ippn10_degamma_ram_select(ipp, !is_ram_a);
871 }
872 
873 /*
874  * Input gamma LUT currently supports 256 values only. This means input color
875  * can have a maximum of 8 bits per channel (= 256 possible values) in order to
876  * have a one-to-one mapping with the LUT. Truncation will occur with color
877  * values greater than 8 bits.
878  *
879  * In the future, this function should support additional input gamma methods,
880  * such as piecewise linear mapping, and input gamma bypass.
881  */
882 static void ippn10_program_input_lut(
883 		struct input_pixel_processor *ipp,
884 		const struct dc_gamma *gamma)
885 {
886 	int i;
887 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
888 	bool rama_occupied = false;
889 	uint32_t ram_num;
890 	// Power on LUT memory.
891 	REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1);
892 	ippn10_enable_cm_block(ipp);
893 	// Determine whether to use RAM A or RAM B
894 	ippn10_ingamma_ram_inuse(ipp, &rama_occupied);
895 	if (!rama_occupied)
896 		REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0);
897 	else
898 		REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1);
899 	// RW mode is 256-entry LUT
900 	REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0);
901 	// IGAM Input format should be 8 bits per channel.
902 	REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0);
903 	// Do not mask any R,G,B values
904 	REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7);
905 	// LUT-256, unsigned, integer, new u0.12 format
906 	REG_UPDATE_3(
907 		CM_IGAM_CONTROL,
908 		CM_IGAM_LUT_FORMAT_R, 3,
909 		CM_IGAM_LUT_FORMAT_G, 3,
910 		CM_IGAM_LUT_FORMAT_B, 3);
911 	// Start at index 0 of IGAM LUT
912 	REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0);
913 	for (i = 0; i < INPUT_LUT_ENTRIES; i++) {
914 		REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
915 					gamma->red[i]);
916 		REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
917 					gamma->green[i]);
918 		REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
919 					gamma->blue[i]);
920 	}
921 	// Power off LUT memory
922 	REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0);
923 	// Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB
924 	REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2);
925 	REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num);
926 }
927 
928 /*****************************************/
929 /* Constructor, Destructor               */
930 /*****************************************/
931 
932 static void dcn10_ipp_destroy(struct input_pixel_processor **ipp)
933 {
934 	dm_free(TO_DCN10_IPP(*ipp));
935 	*ipp = NULL;
936 }
937 
938 static const struct ipp_funcs dcn10_ipp_funcs = {
939 	.ipp_cursor_set_attributes	= ippn10_cursor_set_attributes,
940 	.ipp_cursor_set_position	= ippn10_cursor_set_position,
941 	.ipp_set_degamma		= ippn10_set_degamma,
942 	.ipp_program_input_lut		= ippn10_program_input_lut,
943 	.ipp_full_bypass		= ippn10_full_bypass,
944 	.ipp_setup			= ippn10_cnv_setup,
945 	.ipp_program_degamma_pwl	= ippn10_set_degamma_pwl,
946 	.ipp_destroy			= dcn10_ipp_destroy
947 };
948 
949 void dcn10_ipp_construct(
950 	struct dcn10_ipp *ippn10,
951 	struct dc_context *ctx,
952 	int inst,
953 	const struct dcn10_ipp_registers *regs,
954 	const struct dcn10_ipp_shift *ipp_shift,
955 	const struct dcn10_ipp_mask *ipp_mask)
956 {
957 	ippn10->base.ctx = ctx;
958 	ippn10->base.inst = inst;
959 	ippn10->base.funcs = &dcn10_ipp_funcs;
960 
961 	ippn10->regs = regs;
962 	ippn10->ipp_shift = ipp_shift;
963 	ippn10->ipp_mask = ipp_mask;
964 }
965 
966