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