1 //==========================================================================
5 // common functions definitions for IPU modules operation
7 //==========================================================================
8 //#####DESCRIPTIONBEGIN####
10 // Author(s): Ray Sun <Yanfei.Sun@freescale.com>
11 // Create Date: 2008-07-31
13 //####DESCRIPTIONEND####
15 //==========================================================================
18 #include <cyg/io/ipu_common.h>
19 #include <cyg/io/xec_dls.h>
21 extern struct xec_dls_params xecDlsParams;
23 void ipu_ic_enable(int ic_enable, int irt_enable)
25 ipu_write_field(IPU_IPU_CONF__IC_EN, ic_enable);
26 ipu_write_field(IPU_IPU_CONF__IRT_EN, irt_enable);
30 * this function is used to config the rotation/resizing task perform by the Image Converter
32 void ipu_ic_task_config(ipu_task_params_t task_params)
34 int resCoff, downsCoff;
36 switch (task_params.taskType) {
38 ipu_write_field(IPU_IC_CONF__PRPENC_EN, 0);
39 ipu_write_field(IPU_IC_CONF__RWS_EN, 1);
40 ipu_write_field(IPU_IPU_FS_PROC_FLOW1__ENC_IN_VALID, 1);
41 ipu_write_field(IPU_IC_IDMAC_1__CB0_BURST_16, 1); // set to 16bps
42 ipu_write_field(IPU_IC_IDMAC_1__CB6_BURST_16, 1);
43 ipu_write_field(IPU_IC_CONF__PRPENC_EN, 1);
44 ipu_write_field(IPU_IC_CONF__PRPENC_ROT_EN, task_params.rotEnable);
45 /* set rotation task */
46 if (task_params.rotEnable) {
47 ipu_write_field(IPU_IC_IDMAC_1__T1_FLIP_LR, task_params.rotInfo.HorizFlip);
48 ipu_write_field(IPU_IC_IDMAC_1__T1_FLIP_UD, task_params.rotInfo.VertFlip);
49 ipu_write_field(IPU_IC_IDMAC_1__T1_ROT, task_params.rotInfo.rotation);
51 /* set resizing task */
52 if (task_params.resEnable) {
53 ipu_write_field(IPU_IC_IDMAC_2__T1_FR_HEIGHT, task_params.resInfo.outHeight - 1);
54 ipu_write_field(IPU_IC_IDMAC_3__T1_FR_WIDTH, task_params.resInfo.outWidth - 1);
56 ipu_ic_calc_resize_coeffs(task_params.resInfo.inWidth, task_params.resInfo.outWidth,
57 &resCoff, &downsCoff);
58 ipu_write_field(IPU_IC_PRP_ENC_RSC__PRPENC_DS_R_H, downsCoff);
59 ipu_write_field(IPU_IC_PRP_ENC_RSC__PRPENC_RS_R_H, resCoff);
60 ipu_ic_calc_resize_coeffs(task_params.resInfo.inHeight, task_params.resInfo.outHeight,
61 &resCoff, &downsCoff);
63 ipu_write_field(IPU_IC_PRP_ENC_RSC__PRPENC_DS_R_V, downsCoff);
64 ipu_write_field(IPU_IC_PRP_ENC_RSC__PRPENC_RS_R_V, resCoff);
66 ipu_write_field(IPU_IC_CONF__PRPENC_EN, 1);
70 ipu_write_field(IPU_IC_CONF__PRPVF_EN, 0);
71 ipu_write_field(IPU_IC_CONF__RWS_EN, 1);
72 ipu_write_field(IPU_IPU_FS_PROC_FLOW1__VF_IN_VALID, 1);
73 ipu_write_field(IPU_IC_IDMAC_1__CB1_BURST_16, 1); // set to 16bps
74 ipu_write_field(IPU_IC_IDMAC_1__CB6_BURST_16, 1);
75 ipu_write_field(IPU_IC_CONF__PRPVF_EN, 1);
76 ipu_write_field(IPU_IC_CONF__PRPVF_ROT_EN, task_params.rotEnable);
78 if (task_params.rotEnable) {
79 ipu_write_field(IPU_IC_IDMAC_1__T2_FLIP_LR, task_params.rotInfo.HorizFlip);
80 ipu_write_field(IPU_IC_IDMAC_1__T2_FLIP_UD, task_params.rotInfo.VertFlip);
81 ipu_write_field(IPU_IC_IDMAC_1__T2_ROT, task_params.rotInfo.rotation);
84 if (task_params.resEnable) {
85 ipu_write_field(IPU_IC_IDMAC_2__T2_FR_HEIGHT, task_params.resInfo.outHeight - 1);
86 ipu_write_field(IPU_IC_IDMAC_3__T2_FR_WIDTH, task_params.resInfo.outWidth - 1);
88 ipu_ic_calc_resize_coeffs(task_params.resInfo.inWidth, task_params.resInfo.outWidth,
89 &resCoff, &downsCoff);
90 ipu_write_field(IPU_IC_PRP_VF_RSC__PRPVF_DS_R_H, downsCoff);
91 ipu_write_field(IPU_IC_PRP_VF_RSC__PRPVF_RS_R_H, resCoff);
92 ipu_ic_calc_resize_coeffs(task_params.resInfo.inHeight, task_params.resInfo.outHeight,
93 &resCoff, &downsCoff);
94 ipu_write_field(IPU_IC_PRP_VF_RSC__PRPVF_DS_R_V, downsCoff);
95 ipu_write_field(IPU_IC_PRP_VF_RSC__PRPVF_RS_R_V, resCoff);
97 ipu_write_field(IPU_IC_CONF__PRPVF_EN, 1);
101 ipu_write_field(IPU_IC_CONF__PP_EN, 0);
102 ipu_write_field(IPU_IC_IDMAC_1__CB2_BURST_16, 1); // set to 16bps
103 ipu_write_field(IPU_IC_IDMAC_1__CB5_BURST_16, 1);
104 ipu_write_field(IPU_IC_CONF__PP_EN, 1);
105 ipu_write_field(IPU_IC_CONF__PP_ROT_EN, task_params.rotEnable);
107 if (task_params.rotEnable) {
108 ipu_write_field(IPU_IC_IDMAC_1__T3_FLIP_LR, task_params.rotInfo.HorizFlip);
109 ipu_write_field(IPU_IC_IDMAC_1__T3_FLIP_UD, task_params.rotInfo.VertFlip);
110 ipu_write_field(IPU_IC_IDMAC_1__T3_ROT, task_params.rotInfo.rotation);
113 if (task_params.resEnable) {
114 ipu_write_field(IPU_IC_IDMAC_2__T3_FR_HEIGHT, task_params.resInfo.outHeight - 1);
115 ipu_write_field(IPU_IC_IDMAC_3__T3_FR_WIDTH, task_params.resInfo.outWidth - 1);
117 ipu_ic_calc_resize_coeffs(task_params.resInfo.inWidth, task_params.resInfo.outWidth,
118 &resCoff, &downsCoff);
120 ipu_write_field(IPU_IC_PP_RSC__PP_DS_R_H, downsCoff);
121 ipu_write_field(IPU_IC_PP_RSC__PP_RS_R_H, resCoff);
122 ipu_ic_calc_resize_coeffs(task_params.resInfo.inHeight, task_params.resInfo.outHeight,
123 &resCoff, &downsCoff);
125 ipu_write_field(IPU_IC_PP_RSC__PP_DS_R_V, downsCoff);
126 ipu_write_field(IPU_IC_PP_RSC__PP_RS_R_V, resCoff); // FROM (1536/2 -1)->479 *8192 = 13117
128 ipu_write_field(IPU_IC_CONF__PP_EN, 1);
131 ERRDP("Task type is wrong, IC task configuration failed\n");
136 * this function is used to calculate the params for resizing
138 void ipu_ic_calc_resize_coeffs(unsigned int in_size, unsigned int out_size,
139 unsigned int *resize_coeff, unsigned int *downsize_coeff)
141 unsigned int tempSize;
142 unsigned int tempDownsize;
144 /* Cannot downsize more than 8:1 */
145 if ((out_size << 3) < in_size)
148 /* compute downsizing coefficient */
151 while ((tempSize >= out_size * 2) && (tempDownsize < 2)) {
155 *downsize_coeff = tempDownsize;
157 /* compute resizing coefficient using the following equation:
158 resizeCoeff = M*(SI -1)/(SO - 1)
159 where M = 2^13, SI - input size, SO - output size */
160 *resize_coeff = (8192L * (tempSize - 1)) / (out_size - 1);
161 if (*resize_coeff >= 16384L) {
162 ERRDP("Overflow on resize coeff.\n");
163 *resize_coeff = 0x3FFF;
168 * this function is used to set the resizing parameters
170 int ipu_ic_config_resize_rate(char *task_type, unsigned int res_vert, unsigned int down_vert,
171 unsigned int res_horiz, unsigned int down_horiz)
174 val = (down_vert << 30) | (res_vert << 16) | (down_horiz << 14) | (res_horiz);
176 if (!strcmp(task_type, "PPTASK")) {
177 DP("Post Processing Task!\n");
178 writel(val, IPU_CTRL_BASE_ADDR + IPU_IC_PP_RSC__ADDR);
179 } else if (!strcmp(task_type, "VFTASK")) {
180 DP("View Finder Task!\n");
181 writel(val, IPU_CTRL_BASE_ADDR + IPU_IC_PRP_VF_RSC__ADDR);
182 } else if (!strcmp(task_type, "PrPTASK")) {
183 DP("Pre Processing Task!\n");
184 writel(val, IPU_CTRL_BASE_ADDR + IPU_IC_PRP_ENC_RSC__ADDR);
186 ERRDP("Task type is not defined!\n");
193 * this function is used to calculate the output size for IC resizing task
195 void ipu_ic_calc_vout_size(ipu_res_info_t * info, display_device_t disp_device, int rotation,
196 int full_screen_enable)
198 float coffHeight, coffWidth;
200 /* if rotation is enabled, swap the width and height */
202 coffWidth = (float)(disp_device.height) / info->inWidth;
203 coffHeight = (float)(disp_device.width) / info->inHeight;
205 coffWidth = (float)(disp_device.width) / info->inWidth;
206 coffHeight = (float)(disp_device.height) / info->inHeight;
208 /* the resizing ratio should be the same in both width and height */
209 if (coffWidth >= coffHeight) {
210 info->outWidth = info->inWidth * coffHeight;
211 info->outHeight = info->inHeight * coffHeight;
213 info->outWidth = info->inWidth * coffWidth;
214 info->outHeight = info->inHeight * coffWidth;
217 if (full_screen_enable) {
219 info->outWidth = disp_device.height;
220 info->outHeight = disp_device.width;
223 info->outWidth = disp_device.width;
224 info->outHeight = disp_device.height;
228 /* the output of IPU resizing is up to 1024*1024 */
229 info->xSplitParts = info->outWidth / 1024 + 1;
230 info->ySplitParts = info->outHeight / 1024 + 1;
232 /* the image in block mode, which is 8*8 size */
233 info->outHeight -= info->outHeight % 8;
234 info->outWidth -= info->outWidth % 8;
239 * this function is used to config the combination task in the IC
240 * local alpha with per-pixel or from separate buffer can be used
241 * global alpha can be used also.
243 int ipu_ic_combine_config(ic_comb_params_t comb_params)
245 switch (comb_params.taskType) {
247 ipu_write_field(IPU_IC_IDMAC_1__CB3_BURST_16, 1); // set to 16bps
248 if (comb_params.alpha < 0) {
249 ipu_write_field(IPU_IC_CONF__IC_GLB_LOC_A, 0); // local alpha with per-pixel
250 } else if (comb_params.alpha < 0x100) {
251 ipu_write_field(IPU_IC_CONF__IC_GLB_LOC_A, 1); // global alpha enabled
252 ipu_write_field(IPU_IC_CMBP_1__IC_PRPVF_ALPHA_V, comb_params.alpha); // global alpha value
254 ipu_write_field(IPU_IC_CONF__IC_GLB_LOC_A, 0); // local alpha from separate buffer
256 ipu_write_field(IPU_IC_CONF__PRPVF_CMB,
257 (comb_params.alpha == 0) ? 0 : 1);
258 ipu_write_field(IPU_IC_CONF__PRPVF_EN, 1);
261 ipu_write_field(IPU_IC_IDMAC_1__CB4_BURST_16, 1); // set to 16bps
262 if (comb_params.alpha < 0) {
263 ipu_write_field(IPU_IC_CONF__IC_GLB_LOC_A, 0); // local alpha with per-pixel
264 } else if (comb_params.alpha < 0x100) {
265 ipu_write_field(IPU_IC_CONF__IC_GLB_LOC_A, 1); // global alpha enabled
266 ipu_write_field(IPU_IC_CMBP_1__IC_PP_ALPHA_V, comb_params.alpha); // global alpha
268 ipu_write_field(IPU_IC_CONF__IC_GLB_LOC_A, 0); // local alpha in sepatate buffer
270 ipu_write_field(IPU_IC_CONF__PP_CMB,
271 (comb_params.alpha == 0) ? 0 : 1);
272 ipu_write_field(IPU_IC_CONF__PP_EN, 1);
275 ERRDP("Task Type is wrong!!\n");
282 * this function is used to config the color space conversion task in the IC
284 extern int xecDlsEnable;
285 int ipu_ic_csc_config(int csc_set_index, ic_csc_params_t csc_params)
288 CYG_ADDRESS tpmBaseAddr = IPU_CTRL_BASE_ADDR + 0x1F060000;
291 if (csc_set_index != 1 && csc_set_index != 2) {
292 ERRDP("Wrong index input for IC CSC!!\n");
295 /*Y = R * .299 + G * .587 + B * .114;
296 U = R * -.169 + G * -.332 + B * .500 + 128.;
297 V = R * .500 + G * -.419 + B * -.0813 + 128.; */
298 unsigned int rgb2ycbcr_coeff[4][3] = {
299 { 0x004D, 0x0096, 0x001D },
300 { 0x01D5, 0x01AB, 0x0080 },
301 { 0x0080, 0x0195, 0x01EB },
302 { 0x0000, 0x0200, 0x0200 }, /* A0, A1, A2 */
305 /* transparent RGB->RGB matrix for combining
307 unsigned int rgb2rgb_coeff[4][3] = {
308 { 0x0080, 0x0000, 0x0000 },
309 { 0x0000, 0x0080, 0x0000 },
310 { 0x0000, 0x0000, 0x0080 },
311 { 0x0000, 0x0000, 0x0000 }, /* A0, A1, A2 */
315 R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
316 G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
317 B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128);
319 unsigned int ycbcr2rgb_coeff[4][3] = {
321 { 0x95, 0x1CE, 0x198 },
323 { 0x1E42, 0x10A, 0x1DD6 }, // A0, A1, A2
327 R = (1.164 * alpha * (Y - 16)) + (1.596 * (Cr - 128));
328 G = (1.164 * alpha * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
329 B = (1.164 * alpha * (Y - 16)) + (2.017 * (Cb - 128);
332 /* compensation of y_coeff */
333 ycbcr2rgb_coeff[0][0] = ycbcr2rgb_coeff[0][0] * xecDlsParams.curAlpha/100;
334 ycbcr2rgb_coeff[1][0] = ycbcr2rgb_coeff[1][0] * xecDlsParams.curAlpha/100;
335 ycbcr2rgb_coeff[2][0] = ycbcr2rgb_coeff[2][0] * xecDlsParams.curAlpha/100;
337 /* compensation of constant coeff */
338 ycbcr2rgb_coeff[3][0] -= (1.164 * 16 * 0x2 * (xecDlsParams.curAlpha - 100)/100);
339 ycbcr2rgb_coeff[3][1] -= (1.164 * 16 * 0x2 * (xecDlsParams.curAlpha - 100)/100);
340 ycbcr2rgb_coeff[3][2] -= (1.164 * 16 * 0x2 * (xecDlsParams.curAlpha - 100)/100);
342 DP("alpha %d \n", xecDlsParams.curAlpha);
345 if (csc_set_index == 1) {
346 if (csc_params.taskType == PrP_ENC_TASK) {
347 base = tpmBaseAddr + 0x2008;
348 } else if (csc_params.taskType == PrP_VF_TASK) {
349 base = tpmBaseAddr + 0x4028;
350 } else if (csc_params.taskType == PP_TASK) {
351 base = tpmBaseAddr + 0x6060;
353 ERRDP("Wrong task type for IC CSC1 input!!\n");
357 if (csc_params.taskType == PrP_VF_TASK) {
358 base = tpmBaseAddr + 0x4040;
359 } else if (csc_params.taskType == PP_TASK) {
360 base = tpmBaseAddr + 0x6078;
362 ERRDP("Wrong task type for IC CSC2 input!!\n");
367 if ((csc_params.inFormat == YCbCr) && (csc_params.outFormat == RGB)) {
368 /* Init CSC (YCbCr->RGB) */
369 param = (ycbcr2rgb_coeff[3][0] << 27) |
370 (ycbcr2rgb_coeff[0][0] << 18) | (ycbcr2rgb_coeff[1][1] << 9) | ycbcr2rgb_coeff[2][2];
371 writel(param, base++);
372 /* scale = 2, sat = 0 */
373 param = (ycbcr2rgb_coeff[3][0] >> 5) | (2 << (40 - 32));
374 writel(param, base++);
376 param = (ycbcr2rgb_coeff[3][1] << 27) |
377 (ycbcr2rgb_coeff[0][1] << 18) | (ycbcr2rgb_coeff[1][0] << 9) | ycbcr2rgb_coeff[2][0];
378 writel(param, base++);
379 param = (ycbcr2rgb_coeff[3][1] >> 5);
380 writel(param, base++);
382 param = (ycbcr2rgb_coeff[3][2] << 27) |
383 (ycbcr2rgb_coeff[0][2] << 18) | (ycbcr2rgb_coeff[1][2] << 9) | ycbcr2rgb_coeff[2][1];
384 writel(param, base++);
385 param = (ycbcr2rgb_coeff[3][2] >> 5);
386 writel(param, base++);
387 } else if ((csc_params.inFormat == RGB) && (csc_params.outFormat == YCbCr)) {
388 /* Init CSC1 (RGB->YCbCr) */
389 param = (rgb2ycbcr_coeff[3][0] << 27) |
390 (rgb2ycbcr_coeff[0][0] << 18) | (rgb2ycbcr_coeff[1][1] << 9) | rgb2ycbcr_coeff[2][2];
391 writel(param, base++);
392 /* scale = 1, sat = 0 */
393 param = (rgb2ycbcr_coeff[3][0] >> 5) | (1UL << 8);
394 writel(param, base++);
396 param = (rgb2ycbcr_coeff[3][1] << 27) |
397 (rgb2ycbcr_coeff[0][1] << 18) | (rgb2ycbcr_coeff[1][0] << 9) | rgb2ycbcr_coeff[2][0];
398 writel(param, base++);
399 param = (rgb2ycbcr_coeff[3][1] >> 5);
400 writel(param, base++);
402 param = (rgb2ycbcr_coeff[3][2] << 27) |
403 (rgb2ycbcr_coeff[0][2] << 18) | (rgb2ycbcr_coeff[1][2] << 9) | rgb2ycbcr_coeff[2][1];
404 writel(param, base++);
405 param = (rgb2ycbcr_coeff[3][2] >> 5);
406 writel(param, base++);
407 } else if ((csc_params.inFormat == RGB) && (csc_params.outFormat == RGB)) {
410 (rgb2rgb_coeff[3][0] << 27) | (rgb2rgb_coeff[0][0] << 18) |
411 (rgb2rgb_coeff[1][1] << 9) | rgb2rgb_coeff[2][2];
412 writel(param, base++);
413 /* scale = 2, sat = 0 */
414 param = (rgb2rgb_coeff[3][0] >> 5) | (2UL << 8);
415 writel(param, base++);
418 (rgb2rgb_coeff[3][1] << 27) | (rgb2rgb_coeff[0][1] << 18) |
419 (rgb2rgb_coeff[1][0] << 9) | rgb2rgb_coeff[2][0];
420 writel(param, base++);
421 param = (rgb2rgb_coeff[3][1] >> 5);
422 writel(param, base++);
425 (rgb2rgb_coeff[3][2] << 27) | (rgb2rgb_coeff[0][2] << 18) |
426 (rgb2rgb_coeff[1][2] << 9) | rgb2rgb_coeff[2][1];
427 writel(param, base++);
428 param = (rgb2rgb_coeff[3][2] >> 5);
429 writel(param, base++);
431 ERRDP("Unkown color space conversion!!\n");
434 if (csc_set_index == 1) {
435 if (csc_params.taskType == PrP_ENC_TASK) {
436 ipu_write_field(IPU_IC_CONF__PRPENC_CSC1, 1);
437 } else if (csc_params.taskType == PrP_VF_TASK) {
438 ipu_write_field(IPU_IC_CONF__PRPVF_CSC1, 1);
439 } else if (csc_params.taskType == PP_TASK) {
440 ipu_write_field(IPU_IC_CONF__PP_CSC1, 1);
442 ERRDP("Wrong Task input!!\n");
446 if (csc_params.taskType == PrP_VF_TASK) {
447 ipu_write_field(IPU_IC_CONF__PRPVF_CSC2, 1);
448 } else if (csc_params.taskType == PP_TASK) {
449 ipu_write_field(IPU_IC_CONF__PP_CSC2, 1);
451 ERRDP("Wrong Task input!!\n");
459 * enable ipu tasks, such as preprocessing/post-processing task
461 int ipu_ic_task_enable(int task_type, int task, int enable)
466 ipu_write_field(IPU_IC_CONF__PRPENC_CSC1, enable);
468 ipu_write_field(IPU_IC_CONF__PRPENC_EN, enable);
470 ERRDP("Task Type is wrong!!\n");
474 ipu_write_field(IPU_IC_CONF__PRPVF_CMB, enable);
475 else if (task == IC_CSC1)
476 ipu_write_field(IPU_IC_CONF__PRPVF_CSC1, enable);
477 else if (task == IC_CSC2)
478 ipu_write_field(IPU_IC_CONF__PRPVF_CSC2, enable);
479 else if (task == IC_PRPVF)
480 ipu_write_field(IPU_IC_CONF__PRPVF_EN, enable);
482 ERRDP("Task Type is wrong!!\n");
486 ipu_write_field(IPU_IC_CONF__PP_CMB, enable);
487 else if (task == IC_CSC1)
488 ipu_write_field(IPU_IC_CONF__PP_CSC1, enable);
489 else if (task == IC_CSC2)
490 ipu_write_field(IPU_IC_CONF__PP_CSC2, enable);
491 else if (task == IC_PP)
492 ipu_write_field(IPU_IC_CONF__PP_EN, enable);
494 ERRDP("Task Type is wrong!!\n");
497 ERRDP("Task Type is wrong!!\n");
504 * this function is used to config the color space conversion task in the DP
506 void ipu_dp_csc_config(int dp, dp_csc_param_t dp_csc_params, bool srm_mode_update)
510 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_CSC_YUV_SAT_MODE_SYNC, 0); //SAT mode is zero
511 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_CSC_GAMUT_SAT_EN_SYNC, 0); //GAMUT en (RGB...)
513 if (dp_csc_params.mode >= 0) {
514 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_CSC_DEF_SYNC, dp_csc_params.mode); //disable CSC
517 coeff = dp_csc_params.coeff;
520 writel(GET_LSB(10, coeff[0][0]) | (GET_LSB(10, coeff[0][1]) << 16),
521 IPU_CTRL_BASE_ADDR + SRM_DP_CSCA_SYNC_0__ADDR + dp * 4);
522 writel(GET_LSB(10, coeff[0][2]) | (GET_LSB(10, coeff[1][0]) << 16),
523 IPU_CTRL_BASE_ADDR + SRM_DP_CSCA_SYNC_1__ADDR + dp * 4);
524 writel(GET_LSB(10, coeff[1][1]) | (GET_LSB(10, coeff[1][2]) << 16),
525 IPU_CTRL_BASE_ADDR + SRM_DP_CSCA_SYNC_2__ADDR + dp * 4);
526 writel(GET_LSB(10, coeff[2][0]) | (GET_LSB(10, coeff[2][1]) << 16),
527 IPU_CTRL_BASE_ADDR + SRM_DP_CSCA_SYNC_3__ADDR + dp * 4);
528 writel(GET_LSB(10, coeff[2][2]) | (GET_LSB(14, coeff[3][0]) << 16) |
529 (coeff[4][0] << 30), IPU_CTRL_BASE_ADDR + SRM_DP_CSC_SYNC_0__ADDR + dp * 4);
530 writel(GET_LSB(14, coeff[3][1]) | (coeff[4][1] << 14) |
531 (GET_LSB(14, coeff[3][2]) << 16) | (coeff[4][2] << 30),
532 IPU_CTRL_BASE_ADDR + SRM_DP_CSC_SYNC_1__ADDR + dp * 4);
534 if (srm_mode_update) {
535 ipu_write_field(IPU_IPU_SRM_PRI2__DP_S_SRM_MODE, 3);
536 ipu_write_field(IPU_IPU_SRM_PRI2__DP_SRM_PRI, 0x0);
541 * this function is used to config the foreground plane for combination in the DP
543 void ipu_dp_fg_config(dp_fg_param_t foreground_params)
545 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_GAMMA_EN_SYNC, 0);
546 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_GAMMA_YUV_EN_SYNC, 0);
548 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_COC_SYNC, foreground_params.cursorEnable);
549 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_GWCKE_SYNC, foreground_params.colorKeyEnable); //color key
550 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_GWAM_SYNC, foreground_params.alphaMode); //1=global alpha,0=local alpha
551 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_GWSEL_SYNC, foreground_params.graphicSelect); //1=graphic is FG,0=graphic is BG
552 ipu_write_field(SRM_DP_COM_CONF_SYNC__DP_FG_EN_SYNC, foreground_params.fgEnable); //1=FG channel enabled,0=FG channel disabled
553 ipu_write_field(SRM_DP_FG_POS_SYNC__DP_FGXP_SYNC, foreground_params.offsetHoriz);
554 ipu_write_field(SRM_DP_FG_POS_SYNC__DP_FGYP_SYNC, foreground_params.offsetVert);
555 ipu_write_field(SRM_DP_GRAPH_WIND_CTRL_SYNC__DP_GWAV_SYNC, foreground_params.opaque); // set the FG opaque
556 ipu_write_field(SRM_DP_GRAPH_WIND_CTRL_SYNC__DP_GWCKR_SYNC, 0xFF);
557 ipu_write_field(SRM_DP_GRAPH_WIND_CTRL_SYNC__DP_GWCKG_SYNC, 0xFF);
558 ipu_write_field(SRM_DP_GRAPH_WIND_CTRL_SYNC__DP_GWCKB_SYNC, 0xFF);
562 * microcode configuration, refer to ipuv3 spec
564 void ipu_dc_microcode_config(dc_microcode_t microcode)
566 unsigned int LowWord = 0;
567 unsigned int HighWord = 0;
568 unsigned int opcode_fixed;
570 if (!strcmp(microcode.opcode, "WROD")) {
571 LowWord = LowWord | microcode.sync;
572 LowWord = LowWord | (microcode.gluelogic << 4);
573 LowWord = LowWord | (microcode.waveform << 11);
574 LowWord = LowWord | (microcode.mapping << 15);
575 LowWord = LowWord | (microcode.operand << 20);
577 HighWord = HighWord | (microcode.operand >> 12);
578 opcode_fixed = 0x18 | (microcode.lf << 1);
579 HighWord = HighWord | (opcode_fixed << 4);
580 HighWord = HighWord | (microcode.stop << 9);
582 ERRDP("Microcode type not supported yet!!\n");
584 writel(LowWord, IPU_CTRL_BASE_ADDR + IPU_MEM_DC_MICROCODE_BASE_ADDR + microcode.addr * 8);
585 writel(HighWord, IPU_CTRL_BASE_ADDR + IPU_MEM_DC_MICROCODE_BASE_ADDR + microcode.addr * 8 + 4);
589 * microcode event configuration, to handle different event
591 void ipu_dc_microcode_event(int channel, char event[8], int priority, int address)
593 int channel_offset = (channel >= 5) ? (0x5C + (channel - 5) * 0x1C) : channel * 0x1C;
595 if (!strcmp(event, "NL")) {
596 ipu_write_field(channel_offset + IPU_DC_RL0_CH_0__COD_NL_START_CHAN_0, address);
597 ipu_write_field(channel_offset + IPU_DC_RL0_CH_0__COD_NL_PRIORITY_CHAN_0, priority);
598 } else if (!strcmp(event, "NF")) {
599 ipu_write_field(channel_offset + IPU_DC_RL0_CH_0__COD_NF_START_CHAN_0, address);
600 ipu_write_field(channel_offset + IPU_DC_RL0_CH_0__COD_NF_PRIORITY_CHAN_0, priority);
601 } else if (!strcmp(event, "NFIELD")) {
602 ipu_write_field(channel_offset + IPU_DC_RL1_CH_0__COD_NFIELD_START_CHAN_0, address);
603 ipu_write_field(channel_offset + IPU_DC_RL1_CH_0__COD_NFIELD_PRIORITY_CHAN_0, priority);
604 } else if (!strcmp(event, "EOF")) {
605 ipu_write_field(channel_offset + IPU_DC_RL1_CH_0__COD_EOF_START_CHAN_0, address);
606 ipu_write_field(channel_offset + IPU_DC_RL1_CH_0__COD_EOF_PRIORITY_CHAN_0, priority);
607 } else if (!strcmp(event, "EOFIELD")) {
608 ipu_write_field(channel_offset + IPU_DC_RL2_CH_0__COD_EOFIELD_START_CHAN_0, address);
609 ipu_write_field(channel_offset + IPU_DC_RL2_CH_0__COD_EOFIELD_PRIORITY_CHAN_0, priority);
610 } else if (!strcmp(event, "EOL")) {
611 ipu_write_field(channel_offset + IPU_DC_RL2_CH_0__COD_EOL_START_CHAN_0, address);
612 ipu_write_field(channel_offset + IPU_DC_RL2_CH_0__COD_EOL_PRIORITY_CHAN_0, priority);
613 } else if (!strcmp(event, "NEW_CHAN")) {
614 ipu_write_field(channel_offset + IPU_DC_RL3_CH_0__COD_NEW_CHAN_START_CHAN_0, address);
615 ipu_write_field(channel_offset + IPU_DC_RL3_CH_0__COD_NEW_CHAN_PRIORITY_CHAN_0, priority);
616 } else if (!strcmp(event, "NEW_ADDR")) {
617 ipu_write_field(channel_offset + IPU_DC_RL3_CH_0__COD_NEW_ADDR_START_CHAN_0, address);
618 ipu_write_field(channel_offset + IPU_DC_RL3_CH_0__COD_NEW_ADDR_PRIORITY_CHAN_0, priority);
619 } else if (!strcmp(event, "NEW_DATA")) {
620 ipu_write_field(channel_offset + IPU_DC_RL4_CH_0__COD_NEW_DATA_START_CHAN_0, address);
621 ipu_write_field(channel_offset + IPU_DC_RL4_CH_0__COD_NEW_DATA_PRIORITY_CHAN_0, priority);
623 ERRDP("Wrong DC microcode\n");
628 * this function is used to perform pack/unpacking for yuv/rgb data
630 int ipu_dc_map(int map, int format)
632 int offset[3], mask[3];
634 if (format == RGB565) {
641 } else if (format == RGB666) {
648 } else if (format == RGB888 || format == YUV888) {
656 ERRDP("Invalid pixel format %d\n", format);
662 /* DC_MAP, should be RGB666 mode */
663 ipu_write_field(IPU_DC_MAP_CONF_16__MD_OFFSET_2, offset[0]);
664 ipu_write_field(IPU_DC_MAP_CONF_16__MD_MASK_2, mask[0]);
665 ipu_write_field(IPU_DC_MAP_CONF_15__MD_OFFSET_1, offset[1]);
666 ipu_write_field(IPU_DC_MAP_CONF_15__MD_MASK_1, mask[1]);
667 ipu_write_field(IPU_DC_MAP_CONF_15__MD_OFFSET_0, offset[2]);
668 ipu_write_field(IPU_DC_MAP_CONF_15__MD_MASK_0, mask[2]);
670 ipu_write_field(IPU_DC_MAP_CONF_0__MAPPING_PNTR_BYTE2_0, 0);
671 ipu_write_field(IPU_DC_MAP_CONF_0__MAPPING_PNTR_BYTE1_0, 2);
672 ipu_write_field(IPU_DC_MAP_CONF_0__MAPPING_PNTR_BYTE0_0, 1);
677 ipu_write_field(IPU_DC_MAP_CONF_18__MD_OFFSET_6, offset[0]);
678 ipu_write_field(IPU_DC_MAP_CONF_18__MD_MASK_6, mask[0]);
679 ipu_write_field(IPU_DC_MAP_CONF_17__MD_OFFSET_5, offset[1]);
680 ipu_write_field(IPU_DC_MAP_CONF_17__MD_MASK_5, mask[1]);
681 ipu_write_field(IPU_DC_MAP_CONF_17__MD_OFFSET_4, offset[2]);
682 ipu_write_field(IPU_DC_MAP_CONF_17__MD_MASK_4, mask[2]);
683 ipu_write_field(IPU_DC_MAP_CONF_0__MAPPING_PNTR_BYTE2_1, 6);
684 ipu_write_field(IPU_DC_MAP_CONF_0__MAPPING_PNTR_BYTE1_1, 5);
685 ipu_write_field(IPU_DC_MAP_CONF_0__MAPPING_PNTR_BYTE0_1, 4);
689 ERRDP("Invalid map value: %d\n", map);
696 * config the display port in the DC
698 int ipu_dc_display_config(int display_port, int type, int increment, int strideline)
700 switch (display_port) {
702 ipu_write_field(IPU_DC_DISP_CONF1_0__DISP_TYP_0, type); /* parallel display without byte enable */
703 ipu_write_field(IPU_DC_DISP_CONF1_0__ADDR_INCREMENT_0, increment);
704 ipu_write_field(IPU_DC_DISP_CONF2_0__SL_0, strideline); //stride line
707 ipu_write_field(IPU_DC_DISP_CONF1_1__DISP_TYP_1, type); /* parallel display without byte enable */
708 ipu_write_field(IPU_DC_DISP_CONF1_1__ADDR_INCREMENT_1, increment);
709 ipu_write_field(IPU_DC_DISP_CONF2_1__SL_1, strideline); //stride line
712 ipu_write_field(IPU_DC_DISP_CONF1_2__DISP_TYP_2, type); /* parallel display without byte enable */
713 ipu_write_field(IPU_DC_DISP_CONF1_2__ADDR_INCREMENT_2, increment);
714 ipu_write_field(IPU_DC_DISP_CONF2_2__SL_2, strideline); //stride line
717 ipu_write_field(IPU_DC_DISP_CONF1_3__DISP_TYP_3, type); /* parallel display without byte enable */
718 ipu_write_field(IPU_DC_DISP_CONF1_3__ADDR_INCREMENT_3, increment);
719 ipu_write_field(IPU_DC_DISP_CONF2_3__SL_3, strideline); //stride line
722 ERRDP("Invalid display port: %d\n", display_port);
729 * config the write channel for display.
730 * different channels linked to different display port
732 int ipu_dc_write_channel_config(int dma_channel, int disp_port, int link_di_index,
733 int field_mode_enable)
735 switch (dma_channel) {
737 ipu_write_field(IPU_DC_WR_CH_CONF_5__PROG_START_TIME_5, 0);
738 ipu_write_field(IPU_DC_WR_CH_CONF_5__CHAN_MASK_DEFAULT_5, 0);
739 ipu_write_field(IPU_DC_WR_CH_CONF_5__PROG_CHAN_TYP_5, 4); // Normal mode without anti-tearing
740 ipu_write_field(IPU_DC_WR_CH_CONF_5__PROG_DISP_ID_5, disp_port);
741 ipu_write_field(IPU_DC_WR_CH_CONF_5__PROG_DI_ID_5, link_di_index);
742 ipu_write_field(IPU_DC_WR_CH_CONF_5__W_SIZE_5, 2); // Component size access to DC set to 24bit
743 ipu_write_field(IPU_DC_WR_CH_ADDR_5__ST_ADDR_5, 0);
744 ipu_write_field(IPU_DC_WR_CH_CONF_5__FIELD_MODE_5, field_mode_enable);
746 ipu_write_field(IPU_DC_GEN__SYNC_PRIORITY_5, 1); // sets the priority of channel #5 to high.
747 ipu_write_field(IPU_DC_GEN__MASK4CHAN_5, 0); // mask channel is associated to the sync flow via DC (without DP)
748 ipu_write_field(IPU_DC_GEN__MASK_EN, 0); // mask channel is disabled
749 ipu_write_field(IPU_DC_GEN__DC_CH5_TYPE, 0); // alternate sync or asyn flow
752 ipu_write_field(IPU_DC_WR_CH_CONF_1__PROG_START_TIME_1, 0);
753 ipu_write_field(IPU_DC_WR_CH_CONF_1__CHAN_MASK_DEFAULT_1, 0);
754 ipu_write_field(IPU_DC_WR_CH_CONF_1__PROG_CHAN_TYP_1, 4); // Normal mode without anti-tearing
755 ipu_write_field(IPU_DC_WR_CH_CONF_1__PROG_DISP_ID_1, disp_port);
756 ipu_write_field(IPU_DC_WR_CH_CONF_1__PROG_DI_ID_1, link_di_index);
757 /* if CH28 is connected to DI0, CH23 must connect to DI1 even if it is not used. */
758 if (link_di_index == 0)
759 ipu_write_field(IPU_DC_WR_CH_CONF_5__PROG_DI_ID_5, 1);
761 ipu_write_field(IPU_DC_WR_CH_CONF_1__W_SIZE_1, 2); // Component size access to DC set to 24bit
762 ipu_write_field(IPU_DC_WR_CH_ADDR_1__ST_ADDR_1, 0); // START ADDRESS OF CHANNEL
763 ipu_write_field(IPU_DC_WR_CH_CONF_1__FIELD_MODE_1, field_mode_enable);
765 ipu_write_field(IPU_DC_GEN__SYNC_PRIORITY_1, 1); //sets the priority of channel #5 to high.
766 ipu_write_field(IPU_DC_GEN__SYNC_1_6, 2); // Channel 1 of the DC handles sync flow
769 ERRDP("Invalid display channel: %d\n", dma_channel);