freescale R10 ipu lib 分析 - ipu_ic.c

 45 void _ipu_vdi_set_top_field_man(bool top_field_0)
 46 {
 47     uint32_t reg;
 48
 49     reg = __raw_readl(VDI_C);
 50     if (top_field_0)
 51         reg &= ~VDI_C_TOP_FIELD_MAN_1;
 52     else
 53         reg |= VDI_C_TOP_FIELD_MAN_1;
 54     __raw_writel(reg, VDI_C);
 55 }

 

50~54 VDI top field manual, 设置0,1 field哪一个是top field

 

 57 void _ipu_vdi_set_motion(ipu_motion_sel motion_sel)
 58 {  
 59     uint32_t reg;
 60    
 61     reg = __raw_readl(VDI_C);
 62     reg &= ~(VDI_C_MOT_SEL_FULL | VDI_C_MOT_SEL_MED | VDI_C_MOT_SEL_LOW);
 63     if (motion_sel == HIGH_MOTION)
 64         reg |= VDI_C_MOT_SEL_FULL;
 65     else if (motion_sel == MED_MOTION)
 66         reg |= VDI_C_MOT_SEL_MED;
 67     else
 68         reg |= VDI_C_MOT_SEL_LOW;
 69
 70     __raw_writel(reg, VDI_C);
 71 }  

设置VDI 对动态图像的矫正方式,因为top bottom field在有些sensor上是不同时间点拍摄的,那么对于运动拍摄的top bottom field并不是对齐的,VDI的de-interlaced比dma channel scan-order要做更复杂的处理。

 

 86 void _ipu_ic_enable_task(ipu_channel_t channel)
 87 {
 88     uint32_t ic_conf;
 89
 90     ic_conf = __raw_readl(IC_CONF);
 91     switch (channel) {
 92     case CSI_PRP_VF_MEM:
 93     case MEM_PRP_VF_MEM:
 94         ic_conf |= IC_CONF_PRPVF_EN;
 95         break;
 96     case MEM_VDI_PRP_VF_MEM:
 97         ic_conf |= IC_CONF_PRPVF_EN;
 98         break;
 99     case MEM_ROT_VF_MEM:
100         ic_conf |= IC_CONF_PRPVF_ROT_EN;
101         break;
102     case CSI_PRP_ENC_MEM:
103     case MEM_PRP_ENC_MEM:
104         ic_conf |= IC_CONF_PRPENC_EN;
105         break;
106     case MEM_ROT_ENC_MEM:
107         ic_conf |= IC_CONF_PRPENC_ROT_EN;
108         break;
109     case MEM_PP_MEM:
110         ic_conf |= IC_CONF_PP_EN;
111         break;
112     case MEM_ROT_PP_MEM:
113         ic_conf |= IC_CONF_PP_ROT_EN;
114         break;
115     default:
116         break;
117     }
118     __raw_writel(ic_conf, IC_CONF);
119 }

 

 

210 void _ipu_ic_init_prpvf(ipu_channel_params_t *params, bool src_is_csi)
211 {
212     uint32_t reg, ic_conf;
213     uint32_t downsizeCoeff, resizeCoeff;
214     ipu_color_space_t in_fmt, out_fmt;
215
216     /* Setup vertical resizing */
217     _calc_resize_coeffs(params->mem_prp_vf_mem.in_height,
218                 params->mem_prp_vf_mem.out_height,
219                 &resizeCoeff, &downsizeCoeff);
220     reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
221
222     /* Setup horizontal resizing */
223     /* Upadeted for IC split case */
224     if (!(params->mem_prp_vf_mem.outh_resize_ratio)) {
225         _calc_resize_coeffs(params->mem_prp_vf_mem.in_width,
226                 params->mem_prp_vf_mem.out_width,
227                 &resizeCoeff, &downsizeCoeff);
228         reg |= (downsizeCoeff << 14) | resizeCoeff;
229     } else
230         reg |= params->mem_prp_vf_mem.outh_resize_ratio;
231
232     __raw_writel(reg, IC_PRP_VF_RSC);
233
234     ic_conf = __raw_readl(IC_CONF);
235
236     /* Setup color space conversion */
237     in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_pixel_fmt);
238     out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
239     if (in_fmt == RGB) {
240         if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
241             /* Enable RGB->YCBCR CSC1 */
242             _init_csc(IC_TASK_VIEWFINDER, RGB, out_fmt, 1);
243             ic_conf |= IC_CONF_PRPVF_CSC1;
244         }
245     }
246     if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
247         if (out_fmt == RGB) {
248             /* Enable YCBCR->RGB CSC1 */
249             _init_csc(IC_TASK_VIEWFINDER, YCbCr, RGB, 1);
250             ic_conf |= IC_CONF_PRPVF_CSC1;
251         } else {
252             /* TODO: Support YUV<->YCbCr conversion? */
253         }
254     }
255
256     if (params->mem_prp_vf_mem.graphics_combine_en) {
257         ic_conf |= IC_CONF_PRPVF_CMB;
258
259         if (!(ic_conf & IC_CONF_PRPVF_CSC1)) {
260             /* need transparent CSC1 conversion */
261             _init_csc(IC_TASK_VIEWFINDER, RGB, RGB, 1);
262             ic_conf |= IC_CONF_PRPVF_CSC1;  /* Enable RGB->RGB CSC */
263         }
264         in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_g_pixel_fmt);
265         out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
266         if (in_fmt == RGB) {
267             if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
268                 /* Enable RGB->YCBCR CSC2 */
269                 _init_csc(IC_TASK_VIEWFINDER, RGB, out_fmt, 2);
270                 ic_conf |= IC_CONF_PRPVF_CSC2;
271             }
272         }
273         if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
274             if (out_fmt == RGB) {
275                 /* Enable YCBCR->RGB CSC2 */
276                 _init_csc(IC_TASK_VIEWFINDER, YCbCr, RGB, 2);
277                 ic_conf |= IC_CONF_PRPVF_CSC2;
278             } else {
279                 /* TODO: Support YUV<->YCbCr conversion? */
280             }
281         }
282
283         if (params->mem_prp_vf_mem.global_alpha_en) {
284             ic_conf |= IC_CONF_IC_GLB_LOC_A;
285             reg = __raw_readl(IC_CMBP_1);
286             reg &= ~(0xff);
287             reg |= params->mem_prp_vf_mem.alpha;
288             __raw_writel(reg, IC_CMBP_1);
289         } else
290             ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
291
292         if (params->mem_prp_vf_mem.key_color_en) {
293             ic_conf |= IC_CONF_KEY_COLOR_EN;
294             __raw_writel(params->mem_prp_vf_mem.key_color,
295                     IC_CMBP_2);
296         } else
297             ic_conf &= ~IC_CONF_KEY_COLOR_EN;
298     } else {
299         ic_conf &= ~IC_CONF_PRPVF_CMB;
300     }
301
302     if (src_is_csi)
303         ic_conf &= ~IC_CONF_RWS_EN;
304     else
305         ic_conf |= IC_CONF_RWS_EN;
306
307     __raw_writel(ic_conf, IC_CONF);
308 }

 

行217~232计算缩放因子

行237~254 判断输入和输出pixel format, 使能颜色空间转换

行242 根据输入输出pixel format设置颜色转换寄存器的值,

 

302~305 IC_CONF_RWS_EN: Raw sensro enable, 指明是否一个raw sensor attached, 实在没明白为什么src_is_csi=false就意味着

raw sensor attached。

 

649 static void _init_csc(uint8_t ic_task, ipu_color_space_t in_format,
650               ipu_color_space_t out_format, int csc_index)
651 {
652
653 /*     Y = R *  .299 + G *  .587 + B *  .114;
654        U = R * -.169 + G * -.332 + B *  .500 + 128.;
655        V = R *  .500 + G * -.419 + B * -.0813 + 128.;*/
656     static const uint32_t rgb2ycbcr_coeff[4][3] = {
657         {0x004D, 0x0096, 0x001D},
658         {0x01D5, 0x01AB, 0x0080},
659         {0x0080, 0x0195, 0x01EB},
660         {0x0000, 0x0200, 0x0200},   /* A0, A1, A2 */
661     };
662
663     /* transparent RGB->RGB matrix for combining
664      */
665     static const uint32_t rgb2rgb_coeff[4][3] = {
666         {0x0080, 0x0000, 0x0000},
667         {0x0000, 0x0080, 0x0000},
668         {0x0000, 0x0000, 0x0080},
669         {0x0000, 0x0000, 0x0000},   /* A0, A1, A2 */
670     };
671
672 /*     R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
673        G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
674        B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128); */
675     static const uint32_t ycbcr2rgb_coeff[4][3] = {
676         {149, 0, 204},
677         {149, 462, 408},
678         {149, 255, 0},
679         {8192 - 446, 266, 8192 - 554},  /* A0, A1, A2 */
680     };
681
682     uint32_t param;
683     uint32_t *base = NULL;
684
685     if (ic_task == IC_TASK_ENCODER) {
686         base = ipu_tpmem_base + 0x2008 / 4;
687     } else if (ic_task == IC_TASK_VIEWFINDER) {
688         if (csc_index == 1)
689             base = ipu_tpmem_base + 0x4028 / 4;
690         else
691             base = ipu_tpmem_base + 0x4040 / 4;
692     } else if (ic_task == IC_TASK_POST_PROCESSOR) {
693         if (csc_index == 1)
694             base = ipu_tpmem_base + 0x6060 / 4;
695         else
696             base = ipu_tpmem_base + 0x6078 / 4;
697     } else {
698         BUG();
699     }
700
701     if ((in_format == YCbCr) && (out_format == RGB)) {
702         /* Init CSC (YCbCr->RGB) */
703         param = (ycbcr2rgb_coeff[3][0] << 27) |
704             (ycbcr2rgb_coeff[0][0] << 18) |
705             (ycbcr2rgb_coeff[1][1] << 9) | ycbcr2rgb_coeff[2][2];
706         __raw_writel(param, base++);
707         /* scale = 2, sat = 0 */
708         param = (ycbcr2rgb_coeff[3][0] >> 5) | (2L << (40 - 32));
709         __raw_writel(param, base++);
710
711         param = (ycbcr2rgb_coeff[3][1] << 27) |
712             (ycbcr2rgb_coeff[0][1] << 18) |
713             (ycbcr2rgb_coeff[1][0] << 9) | ycbcr2rgb_coeff[2][0];
714         __raw_writel(param, base++);
715         param = (ycbcr2rgb_coeff[3][1] >> 5);
716         __raw_writel(param, base++);
717
718         param = (ycbcr2rgb_coeff[3][2] << 27) |
719             (ycbcr2rgb_coeff[0][2] << 18) |
720             (ycbcr2rgb_coeff[1][2] << 9) | ycbcr2rgb_coeff[2][1];
721         __raw_writel(param, base++);
722         param = (ycbcr2rgb_coeff[3][2] >> 5);
723         __raw_writel(param, base++);
724     } else if ((in_format == RGB) && (out_format == YCbCr)) {
725         /* Init CSC (RGB->YCbCr) */
726         param = (rgb2ycbcr_coeff[3][0] << 27) |
727             (rgb2ycbcr_coeff[0][0] << 18) |
728             (rgb2ycbcr_coeff[1][1] << 9) | rgb2ycbcr_coeff[2][2];
729         __raw_writel(param, base++);
730         /* scale = 1, sat = 0 */
731         param = (rgb2ycbcr_coeff[3][0] >> 5) | (1UL << 8);
732         __raw_writel(param, base++);
733
734         param = (rgb2ycbcr_coeff[3][1] << 27) |
735             (rgb2ycbcr_coeff[0][1] << 18) |
736             (rgb2ycbcr_coeff[1][0] << 9) | rgb2ycbcr_coeff[2][0];
737         __raw_writel(param, base++);
738         param = (rgb2ycbcr_coeff[3][1] >> 5);
739         __raw_writel(param, base++);
740
741         param = (rgb2ycbcr_coeff[3][2] << 27) |
742             (rgb2ycbcr_coeff[0][2] << 18) |
743             (rgb2ycbcr_coeff[1][2] << 9) | rgb2ycbcr_coeff[2][1];
744         __raw_writel(param, base++);
745         param = (rgb2ycbcr_coeff[3][2] >> 5);
746         __raw_writel(param, base++);
747     } else if ((in_format == RGB) && (out_format == RGB)) {
748         /* Init CSC */
749         param =
750             (rgb2rgb_coeff[3][0] << 27) | (rgb2rgb_coeff[0][0] << 18) |
751             (rgb2rgb_coeff[1][1] << 9) | rgb2rgb_coeff[2][2];
752         __raw_writel(param, base++);
753         /* scale = 2, sat = 0 */
754         param = (rgb2rgb_coeff[3][0] >> 5) | (2UL << 8);
755         __raw_writel(param, base++);
756
757         param =
758             (rgb2rgb_coeff[3][1] << 27) | (rgb2rgb_coeff[0][1] << 18) |
759             (rgb2rgb_coeff[1][0] << 9) | rgb2rgb_coeff[2][0];
760         __raw_writel(param, base++);
761         param = (rgb2rgb_coeff[3][1] >> 5);
762         __raw_writel(param, base++);
763
764         param =
765             (rgb2rgb_coeff[3][2] << 27) | (rgb2rgb_coeff[0][2] << 18) |
766             (rgb2rgb_coeff[1][2] << 9) | rgb2rgb_coeff[2][1];
767         __raw_writel(param, base++);
768         param = (rgb2rgb_coeff[3][2] >> 5);
769         __raw_writel(param, base++);
770     } else {
771         dev_err(g_ipu_dev, "Unsupported color space conversion/n");
772     }
773 }
774

这个函数设置 IPM(IC task parameter memory) 颜色转换寄存器,参见42.4.6.6

 

775 static bool _calc_resize_coeffs(uint32_t inSize, uint32_t outSize,
776                 uint32_t *resizeCoeff,
777                 uint32_t *downsizeCoeff)
778 {
779     uint32_t tempSize;
780     uint32_t tempDownsize;
781
782     /* Input size cannot be more than 4096 */
783     /* Output size cannot be more than 1024 */
784     if ((inSize > 4096) || (outSize > 1024))
785         return false;
786
787     /* Cannot downsize more than 8:1 */
788     if ((outSize << 3) < inSize)
789         return false;
790
791     /* Compute downsizing coefficient */
792     /* Output of downsizing unit cannot be more than 1024 */
793     tempDownsize = 0;
794     tempSize = inSize;
795     while (((tempSize > 1024) || (tempSize >= outSize * 2)) &&
796            (tempDownsize < 2)) {
797         tempSize >>= 1;
798         tempDownsize++;
799     }
800     *downsizeCoeff = tempDownsize;
801
802     /* compute resizing coefficient using the following equation:
803        resizeCoeff = M*(SI -1)/(SO - 1)
804        where M = 2^13, SI - input size, SO - output size    */
805     *resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
806     if (*resizeCoeff >= 16384L) {
807         dev_err(g_ipu_dev, "Warning! Overflow on resize coeff./n");
808         *resizeCoeff = 0x3FFF;
809     }
810
811     dev_dbg(g_ipu_dev, "resizing from %u -> %u pixels, "
812         "downsize=%u, resize=%u.%lu (reg=%u)/n", inSize, outSize,
813         *downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
814         ((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
815
816     return true;
817 }
这个函数计算resize 因子

输出两个值downsizeCoeff和resizeCoff,resize由这两个值共同组成,downsizeCoff是倍数部分,resizeCoff是小数部分

 

 

你可能感兴趣的:(freescale R10 ipu lib 分析 - ipu_ic.c)