Android(安卓)S5PV210 fimc驱动分析 - fimc_regs.c
:fimc_regs.c是fimc框架操作camera 硬件的接口,fimc框架把所有硬件相关的操作都放在这个文件中
[html] view plain copy print ?- 100intfimc_hwset_camera_source(structfimc_control*ctrl)
- 101{
- 102structs3c_platform_camera*cam=ctrl->cam;
- 103u32cfg=0;
- 104
- 105/*fornow,wesupportonlyITU6018bitmode*/
- 106cfg|=S3C_CISRCFMT_ITU601_8BIT;
- 107cfg|=cam->order422;
- 108
- 109if(cam->type==CAM_TYPE_ITU)
- 110cfg|=cam->fmt;
- 111
- 112cfg|=S3C_CISRCFMT_SOURCEHSIZE(cam->width);
- 113cfg|=S3C_CISRCFMT_SOURCEVSIZE(cam->height);
- 114
- 115writel(cfg,ctrl->regs+S3C_CISRCFMT);
- 116
- 117return0;
- 118}
100 int fimc_hwset_camera_source(struct fimc_control *ctrl) 101 { 102 struct s3c_platform_camera *cam = ctrl->cam; 103 u32 cfg = 0; 104 105 /* for now, we support only ITU601 8 bit mode */ 106 cfg |= S3C_CISRCFMT_ITU601_8BIT; 107 cfg |= cam->order422; 108 109 if (cam->type == CAM_TYPE_ITU) 110 cfg |= cam->fmt; 111 112 cfg |= S3C_CISRCFMT_SOURCEHSIZE(cam->width); 113 cfg |= S3C_CISRCFMT_SOURCEVSIZE(cam->height); 114 115 writel(cfg, ctrl->regs + S3C_CISRCFMT); 116 117 return 0; 118 }S3C_CISRCFMT: Camera Source Format,FIMC1 FIMC2 FIMC3各对应一个
106 设置external 摄像头支持的模式,一般来讲 AD转换芯片都是支持BT656
107 cam->order422,这里的cam代表的就是一个外部摄像头,cam->order422是在arch/arm/mach-s5pv210/mach-xxx.c中定义的,标识了external camera 像素的Y C R分量的排列方式,对于BT656来是,选择CAM_ORDER422_8BIT_YCBYCR
109 因为cam->fmt也是设置 ITU模式的,所以和106行代码是冗余的,不知作者为什么这样写
112 ~ 113 设置source水平和垂直像素数目,source可以是 camera或者FIFO input
- 159intfimc_hwset_output_area_size(structfimc_control*ctrl,u32size)
- 160{
- 161u32cfg=0;
- 162
- 163cfg=S3C_CITAREA_TARGET_AREA(size);
- 164
- 165writel(cfg,ctrl->regs+S3C_CITAREA);
- 166
- 167return0;
- 168}
159 int fimc_hwset_output_area_size(struct fimc_control *ctrl, u32 size) 160 { 161 u32 cfg = 0; 162 163 cfg = S3C_CITAREA_TARGET_AREA(size); 164 165 writel(cfg, ctrl->regs + S3C_CITAREA); 166 167 return 0; 168 }CITAREA: output DMA target area register
设置output DMA的target大小,这个值并不是buffer空间的大小,而是输出图像的H_size * V_size
- 170voidfimc_wait_disable_capture(structfimc_control*ctrl)
- 171{
- 172unsignedlongtimeo=jiffies+20;/*timeoutof100ms*/
- 173u32cfg;
- 174
- 175if(!ctrl||!ctrl->cap||
- 176ctrl->cap->fmt.colorspace==V4L2_COLORSPACE_JPEG)
- 177return;
- 178
- 179while(time_before(jiffies,timeo)){
- 180cfg=readl(ctrl->regs+S3C_CISTATUS);
- 181
- 182if(0==(cfg&S3C_CISTATUS_IMGCPTEN))
- 183break;
- 184
- 185msleep(10);
- 186}
- 187
- 188dev_dbg(ctrl->dev,"IMGCPTEN:Waittime=%dms\n",
- 189jiffies_to_msecs(jiffies-timeo+20));
- 190
- 191return;
- 192}
170 void fimc_wait_disable_capture(struct fimc_control *ctrl) 171 { 172 unsigned long timeo = jiffies + 20; /* timeout of 100 ms */ 173 u32 cfg; 174 175 if (!ctrl || !ctrl->cap || 176 ctrl->cap->fmt.colorspace == V4L2_COLORSPACE_JPEG) 177 return; 178 179 while (time_before(jiffies, timeo)) { 180 cfg = readl(ctrl->regs + S3C_CISTATUS); 181 182 if (0 == (cfg & S3C_CISTATUS_IMGCPTEN)) 183 break; 184 185 msleep(10); 186 } 187 188 dev_dbg(ctrl->dev, "IMGCPTEN: Wait time = %d ms\n", 189 jiffies_to_msecs(jiffies - timeo + 20)); 190 191 return; 192 }
在disable capture后,可以调用这个函数,来保证disable capture操作完成
S3C_CISTATUS_IMGCPTEN 标识是否image capture enable的状态
- 194intfimc_hwset_image_effect(structfimc_control*ctrl)
- 195{
- 196u32cfg=0;
- 197
- 198if(ctrl->fe.ie_on){
- 199if(ctrl->fe.ie_after_sc)
- 200cfg|=S3C_CIIMGEFF_IE_SC_AFTER;
- 201
- 202cfg|=S3C_CIIMGEFF_FIN(ctrl->fe.fin);
- 203
- 204if(ctrl->fe.fin==FIMC_EFFECT_FIN_ARBITRARY_CBCR)
- 205cfg|=S3C_CIIMGEFF_PAT_CB(ctrl->fe.pat_cb)|
- 206S3C_CIIMGEFF_PAT_CR(ctrl->fe.pat_cr);
- 207
- 208cfg|=S3C_CIIMGEFF_IE_ENABLE;
- 209}
- 210
- 211writel(cfg,ctrl->regs+S3C_CIIMGEFF);
- 212
- 213return0;
- 214}
194 int fimc_hwset_image_effect(struct fimc_control *ctrl) 195 { 196 u32 cfg = 0; 197 198 if (ctrl->fe.ie_on) { 199 if (ctrl->fe.ie_after_sc) 200 cfg |= S3C_CIIMGEFF_IE_SC_AFTER; 201 202 cfg |= S3C_CIIMGEFF_FIN(ctrl->fe.fin); 203 204 if (ctrl->fe.fin == FIMC_EFFECT_FIN_ARBITRARY_CBCR) 205 cfg |= S3C_CIIMGEFF_PAT_CB(ctrl->fe.pat_cb) | 206 S3C_CIIMGEFF_PAT_CR(ctrl->fe.pat_cr); 207 208 cfg |= S3C_CIIMGEFF_IE_ENABLE; 209 } 210 211 writel(cfg, ctrl->regs + S3C_CIIMGEFF); 212 213 return 0; 214 }
FIMC控制器支持图片特效处理,因此fimc的V4L2 s_ctl接口提供了特效控制
CIIMGEFF寄存器控制图片的特效,具体的特效说明,参看s5pv210 datasheet
- 267intfimc_hwset_reset(structfimc_control*ctrl)
- 268{
- 269u32cfg=0;
- 270
- 271cfg=readl(ctrl->regs+S3C_CISRCFMT);
- 272cfg|=S3C_CISRCFMT_ITU601_8BIT;
- 273writel(cfg,ctrl->regs+S3C_CISRCFMT);
- 274
- 275/*s/wreset*/
- 276cfg=readl(ctrl->regs+S3C_CIGCTRL);
- 277cfg|=(S3C_CIGCTRL_SWRST);
- 278writel(cfg,ctrl->regs+S3C_CIGCTRL);
- 279mdelay(1);
- 280
- 281cfg=readl(ctrl->regs+S3C_CIGCTRL);
- 282cfg&=~S3C_CIGCTRL_SWRST;
- 283writel(cfg,ctrl->regs+S3C_CIGCTRL);
- 284
- 285/*incaseofITU656,CISRCFMT[31]shouldbe0*/
- 286if((ctrl->cap!=NULL)&&(ctrl->cam->fmt==ITU_656_YCBCR422_8BIT)){
- 287cfg=readl(ctrl->regs+S3C_CISRCFMT);
- 288cfg&=~S3C_CISRCFMT_ITU601_8BIT;
- 289writel(cfg,ctrl->regs+S3C_CISRCFMT);
- 290}
- 291
- 292fimc_reset_cfg(ctrl);
- 293
- 294return0;
- 295}
267 int fimc_hwset_reset(struct fimc_control *ctrl)268 {269 u32 cfg = 0;270 271 cfg = readl(ctrl->regs + S3C_CISRCFMT);272 cfg |= S3C_CISRCFMT_ITU601_8BIT;273 writel(cfg, ctrl->regs + S3C_CISRCFMT);274 275 /* s/w reset */276 cfg = readl(ctrl->regs + S3C_CIGCTRL);277 cfg |= (S3C_CIGCTRL_SWRST);278 writel(cfg, ctrl->regs + S3C_CIGCTRL);279 mdelay(1);280 281 cfg = readl(ctrl->regs + S3C_CIGCTRL);282 cfg &= ~S3C_CIGCTRL_SWRST;283 writel(cfg, ctrl->regs + S3C_CIGCTRL);284 285 /* in case of ITU656, CISRCFMT[31] should be 0 */286 if ((ctrl->cap != NULL) && (ctrl->cam->fmt == ITU_656_YCBCR422_8BIT)) {287 cfg = readl(ctrl->regs + S3C_CISRCFMT);288 cfg &= ~S3C_CISRCFMT_ITU601_8BIT;289 writel(cfg, ctrl->regs + S3C_CISRCFMT);290 }291 292 fimc_reset_cfg(ctrl);293 294 return 0;295 }
FIMC软件复位过程:
S5PV210 datasheet推荐使用如下初始化序列
对于ITU601: ITU601_656n置1 -> SwRst置1 -> SwRst置0
对于ITU656: ITU601_656n置1 -> SwRst置1 -> SwRst置0 -> ITU601_656置0
- 335intfimc_hwset_camera_offset(structfimc_control*ctrl)
- 336{
- 337structs3c_platform_camera*cam=ctrl->cam;
- 338structv4l2_rect*rect=&cam->window;
- 339u32cfg,h1,h2,v1,v2;
- 340
- 341if(!cam){
- 342fimc_err("%s:noactivecamera\n",__func__);
- 343return-ENODEV;
- 344}
- 345
- 346h1=rect->left;
- 347h2=cam->width-rect->width-rect->left;
- 348v1=rect->top;
- 349v2=cam->height-rect->height-rect->top;
- 350
- 351cfg=readl(ctrl->regs+S3C_CIWDOFST);
- 352cfg&=~(S3C_CIWDOFST_WINHOROFST_MASK|S3C_CIWDOFST_WINVEROFST_MASK);
- 353cfg|=S3C_CIWDOFST_WINHOROFST(h1);
- 354cfg|=S3C_CIWDOFST_WINVEROFST(v1);
- 355cfg|=S3C_CIWDOFST_WINOFSEN;
- 356writel(cfg,ctrl->regs+S3C_CIWDOFST);
- 357
- 358cfg=0;
- 359cfg|=S3C_CIWDOFST2_WINHOROFST2(h2);
- 360cfg|=S3C_CIWDOFST2_WINVEROFST2(v2);
- 361writel(cfg,ctrl->regs+S3C_CIWDOFST2);
- 362
- 363return0;
- 364}
335 int fimc_hwset_camera_offset(struct fimc_control *ctrl)336 {337 struct s3c_platform_camera *cam = ctrl->cam;338 struct v4l2_rect *rect = &cam->window;339 u32 cfg, h1, h2, v1, v2;340 341 if (!cam) {342 fimc_err("%s: no active camera\n", __func__);343 return -ENODEV;344 }345 346 h1 = rect->left;347 h2 = cam->width - rect->width - rect->left;348 v1 = rect->top;349 v2 = cam->height - rect->height - rect->top;350 351 cfg = readl(ctrl->regs + S3C_CIWDOFST);352 cfg &= ~(S3C_CIWDOFST_WINHOROFST_MASK | S3C_CIWDOFST_WINVEROFST_MASK);353 cfg |= S3C_CIWDOFST_WINHOROFST(h1);354 cfg |= S3C_CIWDOFST_WINVEROFST(v1);355 cfg |= S3C_CIWDOFST_WINOFSEN;356 writel(cfg, ctrl->regs + S3C_CIWDOFST);357 358 cfg = 0;359 cfg |= S3C_CIWDOFST2_WINHOROFST2(h2);360 cfg |= S3C_CIWDOFST2_WINVEROFST2(v2);361 writel(cfg, ctrl->regs + S3C_CIWDOFST2);362 363 return 0;364 }
h1: Window Horizon Offset, v1: Window Vertical Offset
h2: Window Horizon Offset2, v2: Window Vertical Offset2
下面这个图很明了的解释了这几个坐标概念
h1, h2, v1, v2这四个坐标就定义了crop的范围,上图右边部分就是crop结果
- 366intfimc_hwset_camera_polarity(structfimc_control*ctrl)
- 367{
- 368structs3c_platform_camera*cam=ctrl->cam;
- 369u32cfg;
- 370
- 371if(!cam){
- 372fimc_err("%s:noactivecamera\n",__func__);
- 373return-ENODEV;
- 374}
- 375
- 376cfg=readl(ctrl->regs+S3C_CIGCTRL);
- 377
- 378cfg&=~(S3C_CIGCTRL_INVPOLPCLK|S3C_CIGCTRL_INVPOLVSYNC|
- 379S3C_CIGCTRL_INVPOLHREF|S3C_CIGCTRL_INVPOLHSYNC);
- 380
- 381if(cam->inv_pclk)
- 382cfg|=S3C_CIGCTRL_INVPOLPCLK;
- 383
- 384if(cam->inv_vsync)
- 385cfg|=S3C_CIGCTRL_INVPOLVSYNC;
- 386
- 387if(cam->inv_href)
- 388cfg|=S3C_CIGCTRL_INVPOLHREF;
- 389
- 390if(cam->inv_hsync)
- 391cfg|=S3C_CIGCTRL_INVPOLHSYNC;
- 392
- 393writel(cfg,ctrl->regs+S3C_CIGCTRL);
- 394
- 395return0;
- 396}
366 int fimc_hwset_camera_polarity(struct fimc_control *ctrl) 367 { 368 struct s3c_platform_camera *cam = ctrl->cam; 369 u32 cfg; 370 371 if (!cam) { 372 fimc_err("%s: no active camera\n", __func__); 373 return -ENODEV; 374 } 375 376 cfg = readl(ctrl->regs + S3C_CIGCTRL); 377 378 cfg &= ~(S3C_CIGCTRL_INVPOLPCLK | S3C_CIGCTRL_INVPOLVSYNC | 379 S3C_CIGCTRL_INVPOLHREF | S3C_CIGCTRL_INVPOLHSYNC); 380 381 if (cam->inv_pclk) 382 cfg |= S3C_CIGCTRL_INVPOLPCLK; 383 384 if (cam->inv_vsync) 385 cfg |= S3C_CIGCTRL_INVPOLVSYNC; 386 387 if (cam->inv_href) 388 cfg |= S3C_CIGCTRL_INVPOLHREF; 389 390 if (cam->inv_hsync) 391 cfg |= S3C_CIGCTRL_INVPOLHSYNC; 392 393 writel(cfg, ctrl->regs + S3C_CIGCTRL); 394 395 return 0; 396 }
camera sensor输出到fimc控制器的几个信号: pixclk, href(hsync), vsync。 sensor可能会设置这几个信号的极性,因此FIMC控制器端也需要和这个信号的极性匹配
具体配置需要参考sensor的输出,一般情况下无极性翻转。
对于BT656信号来说,只需要考虑pixclk的极性。
- 434intfimc43_hwset_camera_type(structfimc_control*ctrl)
- 435{
- 436structs3c_platform_camera*cam=ctrl->cam;
- 437u32cfg;
- 438
- 439if(!cam){
- 440fimc_err("%s:noactivecamera\n",__func__);
- 441return-ENODEV;
- 442}
- 443
- 444cfg=readl(ctrl->regs+S3C_CIGCTRL);
- 445cfg&=~(S3C_CIGCTRL_TESTPATTERN_MASK|S3C_CIGCTRL_SELCAM_ITU_MASK|
- 446S3C_CIGCTRL_SELCAM_MIPI_MASK|S3C_CIGCTRL_SELCAM_FIMC_MASK|
- 447S3C_CIGCTRL_SELWB_CAMIF_MASK);
- 448
- 449/*Interfaceselection*/
- 450if(cam->id==CAMERA_WB){
- 451cfg|=S3C_CIGCTRL_SELWB_CAMIF_WRITEBACK;
- 452}elseif(cam->type==CAM_TYPE_MIPI){
- 453cfg|=S3C_CIGCTRL_SELCAM_FIMC_MIPI;
- 454
- 455/*C110/V210SupportonlyMIPIAsupport*/
- 456cfg|=S3C_CIGCTRL_SELCAM_MIPI_A;
- 457
- 458/*FIXME:TemporaryMIPICSISData32bitaligned*/
- 459if(ctrl->cap->fmt.pixelformat==V4L2_PIX_FMT_JPEG)
- 460writel((MIPI_USER_DEF_PACKET_1|(0x1<<8)),
- 461ctrl->regs+S3C_CSIIMGFMT);
- 462else
- 463writel(cam->fmt|(0x1<<8),
- 464ctrl->regs+S3C_CSIIMGFMT);
- 465}elseif(cam->type==CAM_TYPE_ITU){
- 466if(cam->id==CAMERA_PAR_A)
- 467cfg|=S3C_CIGCTRL_SELCAM_ITU_A;
- 468else
- 469cfg|=S3C_CIGCTRL_SELCAM_ITU_B;
- 470/*switchtoITUinterface*/
- 471cfg|=S3C_CIGCTRL_SELCAM_FIMC_ITU;
- 472}else{
- 473fimc_err("%s:invalidcamerabustypeselected\n",__func__);
- 474return-EINVAL;
- 475}
- 476
- 477writel(cfg,ctrl->regs+S3C_CIGCTRL);
- 478
- 479return0;
- 480}
434 int fimc43_hwset_camera_type(struct fimc_control *ctrl) 435 { 436 struct s3c_platform_camera *cam = ctrl->cam; 437 u32 cfg; 438 439 if (!cam) { 440 fimc_err("%s: no active camera\n", __func__); 441 return -ENODEV; 442 } 443 444 cfg = readl(ctrl->regs + S3C_CIGCTRL); 445 cfg &= ~(S3C_CIGCTRL_TESTPATTERN_MASK | S3C_CIGCTRL_SELCAM_ITU_MASK | 446 S3C_CIGCTRL_SELCAM_MIPI_MASK | S3C_CIGCTRL_SELCAM_FIMC_MASK | 447 S3C_CIGCTRL_SELWB_CAMIF_MASK); 448 449 /* Interface selection */ 450 if (cam->id == CAMERA_WB) { 451 cfg |= S3C_CIGCTRL_SELWB_CAMIF_WRITEBACK; 452 } else if (cam->type == CAM_TYPE_MIPI) { 453 cfg |= S3C_CIGCTRL_SELCAM_FIMC_MIPI; 454 455 /* C110/V210 Support only MIPI A support */ 456 cfg |= S3C_CIGCTRL_SELCAM_MIPI_A; 457 458 /* FIXME: Temporary MIPI CSIS Data 32 bit aligned */ 459 if (ctrl->cap->fmt.pixelformat == V4L2_PIX_FMT_JPEG) 460 writel((MIPI_USER_DEF_PACKET_1 | (0x1 << 8)), 461 ctrl->regs + S3C_CSIIMGFMT); 462 else 463 writel(cam->fmt | (0x1 << 8), 464 ctrl->regs + S3C_CSIIMGFMT); 465 } else if (cam->type == CAM_TYPE_ITU) { 466 if (cam->id == CAMERA_PAR_A) 467 cfg |= S3C_CIGCTRL_SELCAM_ITU_A; 468 else 469 cfg |= S3C_CIGCTRL_SELCAM_ITU_B; 470 /* switch to ITU interface */ 471 cfg |= S3C_CIGCTRL_SELCAM_FIMC_ITU; 472 } else { 473 fimc_err("%s: invalid camera bus type selected\n", __func__); 474 return -EINVAL; 475 } 476 477 writel(cfg, ctrl->regs + S3C_CIGCTRL); 478 479 return 0; 480 }
FIMC提供了三个物理camera接口:
两个ITU类型的:Camera A(GPE0_0 --- GPE1_4)和Camera B(GPJ0_0 --- GPJ1_4),
一个MIPI类型的: Camera C
465 ~ 469 选择使用哪个物理camera接口,这个需要查看原理图来预设cam->id。
- 522intfimc_hwset_jpeg_mode(structfimc_control*ctrl,boolenable)
- 523{
- 524u32cfg;
- 525cfg=readl(ctrl->regs+S3C_CIGCTRL);
- 526
- 527if(enable)
- 528cfg|=S3C_CIGCTRL_CAM_JPEG;
- 529else
- 530cfg&=~S3C_CIGCTRL_CAM_JPEG;
- 531
- 532writel(cfg,ctrl->regs+S3C_CIGCTRL);
- 533
- 534return0;
- 535}
522 int fimc_hwset_jpeg_mode(struct fimc_control *ctrl, bool enable) 523 { 524 u32 cfg; 525 cfg = readl(ctrl->regs + S3C_CIGCTRL); 526 527 if (enable) 528 cfg |= S3C_CIGCTRL_CAM_JPEG; 529 else 530 cfg &= ~S3C_CIGCTRL_CAM_JPEG; 531 532 writel(cfg, ctrl->regs + S3C_CIGCTRL); 533 534 return 0; 535 }对于ITU601输入如果输入数据是8bit jpeg格式(压缩格式),那么就要设置JPEG标志位,这时FIMC会忽略scaler和转换。
对于BT656来说只能是YUYV格式
- 537intfimc_hwset_output_size(structfimc_control*ctrl,intwidth,intheight)
- 538{
- 539u32cfg=readl(ctrl->regs+S3C_CITRGFMT);
- 540
- 541printk(KERN_ERR"%s:width(%d),height(%d)\n",__func__,width,height);
- 542
- 543cfg&=~(S3C_CITRGFMT_TARGETH_MASK|S3C_CITRGFMT_TARGETV_MASK);
- 544
- 545cfg|=S3C_CITRGFMT_TARGETHSIZE(width);
- 546cfg|=S3C_CITRGFMT_TARGETVSIZE(height);
- 547
- 548writel(cfg,ctrl->regs+S3C_CITRGFMT);
- 549
- 550return0;
- 551}
537 int fimc_hwset_output_size(struct fimc_control *ctrl, int width, int height) 538 { 539 u32 cfg = readl(ctrl->regs + S3C_CITRGFMT); 540 541 printk(KERN_ERR "%s: width(%d), height(%d)\n", __func__, width, height); 542 543 cfg &= ~(S3C_CITRGFMT_TARGETH_MASK | S3C_CITRGFMT_TARGETV_MASK); 544 545 cfg |= S3C_CITRGFMT_TARGETHSIZE(width); 546 cfg |= S3C_CITRGFMT_TARGETVSIZE(height); 547 548 writel(cfg, ctrl->regs + S3C_CITRGFMT); 549 550 return 0; 551 }
545 ~ 546 是FIMC输出图像的width和height size, 他们不应该大于camera source height size和 source width size,当然这并不意味着FIMC的scaler没有放大功能,FIMC的scaler有放大功能
,但是放大后的尺寸不能超过source Hsize和souce Vsize
- 553intfimc_hwset_output_colorspace(structfimc_control*ctrl,u32pixelformat)
- 554{
- 555structs3c_platform_fimc*pdata=to_fimc_plat(ctrl->dev);
- 556u32cfg;
- 557
- 558if(pdata->hw_ver!=0x40){
- 559if(pixelformat==V4L2_PIX_FMT_YUV444){
- 560cfg=readl(ctrl->regs+S3C_CIEXTEN);
- 561cfg|=S3C_CIEXTEN_YUV444_OUT;
- 562writel(cfg,ctrl->regs+S3C_CIEXTEN);
- 563
- 564return0;
- 565}else{
- 566cfg=readl(ctrl->regs+S3C_CIEXTEN);
- 567cfg&=~S3C_CIEXTEN_YUV444_OUT;
- 568writel(cfg,ctrl->regs+S3C_CIEXTEN);
- 569}
- 570}
- 571
- 572cfg=readl(ctrl->regs+S3C_CITRGFMT);
- 573cfg&=~S3C_CITRGFMT_OUTFORMAT_MASK;
- 574
- 575switch(pixelformat){
- 576caseV4L2_PIX_FMT_JPEG:
- 577break;
- 578caseV4L2_PIX_FMT_RGB565:/*fallthrough*/
- 579caseV4L2_PIX_FMT_RGB32:
- 580cfg|=S3C_CITRGFMT_OUTFORMAT_RGB;
- 581break;
- 582
- 583caseV4L2_PIX_FMT_YUYV:/*fallthrough*/
- 584caseV4L2_PIX_FMT_UYVY:/*fallthrough*/
- 585caseV4L2_PIX_FMT_VYUY:/*fallthrough*/
- 586caseV4L2_PIX_FMT_YVYU:
- 587cfg|=S3C_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
- 588break;
- 589
- 590caseV4L2_PIX_FMT_NV16:/*fallthrough*/
- 591caseV4L2_PIX_FMT_NV61:/*fallthrough*/
- 592caseV4L2_PIX_FMT_YUV422P:
- 593cfg|=S3C_CITRGFMT_OUTFORMAT_YCBCR422;
- 594break;
- 595
- 596caseV4L2_PIX_FMT_YUV420:/*fallthrough*/
- 597caseV4L2_PIX_FMT_NV12:/*fallthrough*/
- 598caseV4L2_PIX_FMT_NV12T:/*fallthrough*/
- 599caseV4L2_PIX_FMT_NV21:
- 600cfg|=S3C_CITRGFMT_OUTFORMAT_YCBCR420;
- 601break;
- 602
- 603default:
- 604fimc_err("%s:invalidpixelformat\n",__func__);
- 605break;
- 606}
- 607
- 608writel(cfg,ctrl->regs+S3C_CITRGFMT);
- 609
- 610return0;
- 611}
553 int fimc_hwset_output_colorspace(struct fimc_control *ctrl, u32 pixelformat) 554 { 555 struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev); 556 u32 cfg; 557 558 if (pdata->hw_ver != 0x40) { 559 if (pixelformat == V4L2_PIX_FMT_YUV444) { 560 cfg = readl(ctrl->regs + S3C_CIEXTEN); 561 cfg |= S3C_CIEXTEN_YUV444_OUT; 562 writel(cfg, ctrl->regs + S3C_CIEXTEN); 563 564 return 0; 565 } else { 566 cfg = readl(ctrl->regs + S3C_CIEXTEN); 567 cfg &= ~S3C_CIEXTEN_YUV444_OUT; 568 writel(cfg, ctrl->regs + S3C_CIEXTEN); 569 } 570 } 571 572 cfg = readl(ctrl->regs + S3C_CITRGFMT); 573 cfg &= ~S3C_CITRGFMT_OUTFORMAT_MASK; 574 575 switch (pixelformat) { 576 case V4L2_PIX_FMT_JPEG: 577 break; 578 case V4L2_PIX_FMT_RGB565: /* fall through */ 579 case V4L2_PIX_FMT_RGB32: 580 cfg |= S3C_CITRGFMT_OUTFORMAT_RGB; 581 break; 582 583 case V4L2_PIX_FMT_YUYV: /* fall through */ 584 case V4L2_PIX_FMT_UYVY: /* fall through */ 585 case V4L2_PIX_FMT_VYUY: /* fall through */ 586 case V4L2_PIX_FMT_YVYU: 587 cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE; 588 break; 589 590 case V4L2_PIX_FMT_NV16: /* fall through */ 591 case V4L2_PIX_FMT_NV61: /* fall through */ 592 case V4L2_PIX_FMT_YUV422P: 593 cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422; 594 break; 595 596 case V4L2_PIX_FMT_YUV420: /* fall through */ 597 case V4L2_PIX_FMT_NV12: /* fall through */ 598 case V4L2_PIX_FMT_NV12T: /* fall through */ 599 case V4L2_PIX_FMT_NV21: 600 cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR420; 601 break; 602 603 default: 604 fimc_err("%s: invalid pixel format\n", __func__); 605 break; 606 } 607 608 writel(cfg, ctrl->regs + S3C_CITRGFMT); 609 610 return 0; 611 }
设置FIMC的输出颜色格式,FIMC支持颜色空间转换,应用程序或测试程序可以通过S_FMT ioctl指定希望的输出颜色格式
- 615intfimc_hwset_output_rot_flip(structfimc_control*ctrl,u32rot,u32flip)
- 616{
- 617u32cfg,val;
- 618
- 619cfg=readl(ctrl->regs+S3C_CITRGFMT);
- 620cfg&=~S3C_CITRGFMT_FLIP_MASK;
- 621cfg&=~S3C_CITRGFMT_OUTROT90_CLOCKWISE;
- 622
- 623val=fimc_mapping_rot_flip(rot,flip);
- 624
- 625if(val&FIMC_ROT)
- 626cfg|=S3C_CITRGFMT_OUTROT90_CLOCKWISE;
- 627
- 628if(val&FIMC_XFLIP)
- 629cfg|=S3C_CITRGFMT_FLIP_X_MIRROR;
- 630
- 631if(val&FIMC_YFLIP)
- 632cfg|=S3C_CITRGFMT_FLIP_Y_MIRROR;
- 633
- 634writel(cfg,ctrl->regs+S3C_CITRGFMT);
- 635
- 636return0;
- 637}
615 int fimc_hwset_output_rot_flip(struct fimc_control *ctrl, u32 rot, u32 flip) 616 { 617 u32 cfg, val; 618 619 cfg = readl(ctrl->regs + S3C_CITRGFMT); 620 cfg &= ~S3C_CITRGFMT_FLIP_MASK; 621 cfg &= ~S3C_CITRGFMT_OUTROT90_CLOCKWISE; 622 623 val = fimc_mapping_rot_flip(rot, flip); 624 625 if (val & FIMC_ROT) 626 cfg |= S3C_CITRGFMT_OUTROT90_CLOCKWISE; 627 628 if (val & FIMC_XFLIP) 629 cfg |= S3C_CITRGFMT_FLIP_X_MIRROR; 630 631 if (val & FIMC_YFLIP) 632 cfg |= S3C_CITRGFMT_FLIP_Y_MIRROR; 633 634 writel(cfg, ctrl->regs + S3C_CITRGFMT); 635 636 return 0; 637 }
FIMC控制器支持图片的翻转,应用层可以通过s_ctrl ioctl来设置翻转
- 690intfimc_hwset_output_address(structfimc_control*ctrl,
- 691structfimc_buf_set*bs,intid)
- 692{
- 693printk(KERN_ERR"%s:FIMC_ADDR_Y=0x%x,FIMC_ADDR_CB=0x%x,FIMC_ADDR_CR=0x%x\n",
- 694__func__,bs->base[FIMC_ADDR_Y],bs->base[FIMC_ADDR_CB],
- 695bs->base[FIMC_ADDR_CR]);
- 696writel(bs->base[FIMC_ADDR_Y],ctrl->regs+S3C_CIOYSA(id));
- 697writel(bs->base[FIMC_ADDR_CB],ctrl->regs+S3C_CIOCBSA(id));
- 698writel(bs->base[FIMC_ADDR_CR],ctrl->regs+S3C_CIOCRSA(id));
- 699
- 700return0;
- 701}
690 int fimc_hwset_output_address(struct fimc_control *ctrl,691 struct fimc_buf_set *bs, int id)692 {693 printk(KERN_ERR "%s: FIMC_ADDR_Y=0x%x, FIMC_ADDR_CB=0x%x, FIMC_ADDR_CR=0x%x\n",694 __func__, bs->base[FIMC_ADDR_Y], bs->base[FIMC_ADDR_CB],695 bs->base[FIMC_ADDR_CR]);696 writel(bs->base[FIMC_ADDR_Y], ctrl->regs + S3C_CIOYSA(id));697 writel(bs->base[FIMC_ADDR_CB], ctrl->regs + S3C_CIOCBSA(id));698 writel(bs->base[FIMC_ADDR_CR], ctrl->regs + S3C_CIOCRSA(id));699 700 return 0;701 }
设置输出DMA地址,这里需要注意某些情况下,DMA物理地址需要一定的对齐方式,如果赋给FIMC的DMA地址没有满足需要的对齐方式,FIMC驱动并不会报错,而是把输出数据写入到指定地址后符合对齐方式的地址,这样就导致DMA地址前面一部分没有有效数据写入,而后面地址写入的数据又发生了错位。
举个例子,比如DMA要求4K对齐,你赋值的地址为0x40000800,那么FIMC会越过2K字节从0x40001000开始写数据,而且会越过你假定的那个DMA buffer边界,写入不可知的区域(这个我纯属猜测)
FIMC既支持packed格式的输出,此时仅需要设置FIMC_ADDR_Y;也支持planer格式的输出,此时还需要设置FIMC_ADDR_CB和FIMC_ADDR_CR
- 703intfimc_hwset_output_yuv(structfimc_control*ctrl,u32pixelformat)
- 704{
- 705u32cfg;
- 706
- 707cfg=readl(ctrl->regs+S3C_CIOCTRL);
- 708cfg&=~(S3C_CIOCTRL_ORDER2P_MASK|S3C_CIOCTRL_ORDER422_MASK|
- 709S3C_CIOCTRL_YCBCR_PLANE_MASK);
- 710
- 711switch(pixelformat){
- 712/*1planeformats*/
- 713caseV4L2_PIX_FMT_YUYV:
- 714cfg|=S3C_CIOCTRL_ORDER422_YCBYCR;
- 715break;
- 716
- 717caseV4L2_PIX_FMT_UYVY:
- 718cfg|=S3C_CIOCTRL_ORDER422_CBYCRY;
- 719break;
- 720
- 721caseV4L2_PIX_FMT_VYUY:
- 722cfg|=S3C_CIOCTRL_ORDER422_CRYCBY;
- 723break;
- 724
- 725caseV4L2_PIX_FMT_YVYU:
- 726cfg|=S3C_CIOCTRL_ORDER422_YCRYCB;
- 727break;
- 728
- 729/*2planeformats*/
- 730caseV4L2_PIX_FMT_NV12:/*fallthrough*/
- 731caseV4L2_PIX_FMT_NV12T:/*fallthrough*/
- 732caseV4L2_PIX_FMT_NV16:
- 733cfg|=S3C_CIOCTRL_ORDER2P_LSB_CBCR;
- 734cfg|=S3C_CIOCTRL_YCBCR_2PLANE;
- 735break;
- 736
- 737caseV4L2_PIX_FMT_NV21:/*fallthrough*/
- 738caseV4L2_PIX_FMT_NV61:
- 739cfg|=S3C_CIOCTRL_ORDER2P_LSB_CRCB;
- 740cfg|=S3C_CIOCTRL_YCBCR_2PLANE;
- 741break;
- 742
- 743/*3planeformats*/
- 744caseV4L2_PIX_FMT_YUV422P:/*fallthrough*/
- 745caseV4L2_PIX_FMT_YUV420:
- 746cfg|=S3C_CIOCTRL_YCBCR_3PLANE;
- 747break;
- 748}
- 749
- 750writel(cfg,ctrl->regs+S3C_CIOCTRL);
- 751
- 752return0;
- 753}
703 int fimc_hwset_output_yuv(struct fimc_control *ctrl, u32 pixelformat) 704 { 705 u32 cfg; 706 707 cfg = readl(ctrl->regs + S3C_CIOCTRL); 708 cfg &= ~(S3C_CIOCTRL_ORDER2P_MASK | S3C_CIOCTRL_ORDER422_MASK | 709 S3C_CIOCTRL_YCBCR_PLANE_MASK); 710 711 switch (pixelformat) { 712 /* 1 plane formats */ 713 case V4L2_PIX_FMT_YUYV: 714 cfg |= S3C_CIOCTRL_ORDER422_YCBYCR; 715 break; 716 717 case V4L2_PIX_FMT_UYVY: 718 cfg |= S3C_CIOCTRL_ORDER422_CBYCRY; 719 break; 720 721 case V4L2_PIX_FMT_VYUY: 722 cfg |= S3C_CIOCTRL_ORDER422_CRYCBY; 723 break; 724 725 case V4L2_PIX_FMT_YVYU: 726 cfg |= S3C_CIOCTRL_ORDER422_YCRYCB; 727 break; 728 729 /* 2 plane formats */ 730 case V4L2_PIX_FMT_NV12: /* fall through */ 731 case V4L2_PIX_FMT_NV12T: /* fall through */ 732 case V4L2_PIX_FMT_NV16: 733 cfg |= S3C_CIOCTRL_ORDER2P_LSB_CBCR; 734 cfg |= S3C_CIOCTRL_YCBCR_2PLANE; 735 break; 736 737 case V4L2_PIX_FMT_NV21: /* fall through */ 738 case V4L2_PIX_FMT_NV61: 739 cfg |= S3C_CIOCTRL_ORDER2P_LSB_CRCB; 740 cfg |= S3C_CIOCTRL_YCBCR_2PLANE; 741 break; 742 743 /* 3 plane formats */ 744 case V4L2_PIX_FMT_YUV422P: /* fall through */ 745 case V4L2_PIX_FMT_YUV420: 746 cfg |= S3C_CIOCTRL_YCBCR_3PLANE; 747 break; 748 } 749 750 writel(cfg, ctrl->regs + S3C_CIOCTRL); 751 752 return 0; 753 }
YUV有很多种格式,可以分为两大类: 打包格式(packed)和平面格式(planer),打包格式是YUV分量放在一个数组中,相邻的几个分量组成一个像素的。而后者使用两个或者三个分量数组,两个分量数组是将Y和UV分量分开,三个分量数组则是将YUV分量放在不同的数组中
- 755intfimc_hwset_output_scan(structfimc_control*ctrl,
- 756structv4l2_pix_format*fmt)
- 757{
- 758structs3c_platform_fimc*pdata=to_fimc_plat(ctrl->dev);
- 759u32cfg;
- 760
- 761/*nothingtodo:FIMC40notsupportedinterlacedandweaveoutput*/
- 762if(pdata->hw_ver==0x40)
- 763return0;
- 764
- 765cfg=readl(ctrl->regs+S3C_CISCCTRL);
- 766cfg&=~S3C_CISCCTRL_SCAN_MASK;
- 767
- 768if(fmt->field==V4L2_FIELD_INTERLACED||
- 769fmt->field==V4L2_FIELD_INTERLACED_TB){
- 770cfg|=S3C_CISCCTRL_INTERLACE;
- 771printk(KERN_ERR"%s:setS3C_CISCCTRL_INTERLACE\n",__func__);
- 772}
- 773else
- 774cfg|=S3C_CISCCTRL_PROGRESSIVE;
- 775
- 776writel(cfg,ctrl->regs+S3C_CISCCTRL);
- 777
- 778cfg=readl(ctrl->regs+S3C_CIOCTRL);
- 779cfg&=~S3C_CIOCTRL_WEAVE_MASK;
- 780
- 781if((ctrl->cap)&&(fmt->field==V4L2_FIELD_INTERLACED_TB))
- 782cfg|=S3C_CIOCTRL_WEAVE_OUT;
- 783
- 784writel(cfg,ctrl->regs+S3C_CIOCTRL);
- 785
- 786return0;
- 787}
755 int fimc_hwset_output_scan(struct fimc_control *ctrl, 756 struct v4l2_pix_format *fmt) 757 { 758 struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev); 759 u32 cfg; 760 761 /* nothing to do: FIMC40 not supported interlaced and weave output */ 762 if (pdata->hw_ver == 0x40) 763 return 0; 764 765 cfg = readl(ctrl->regs + S3C_CISCCTRL); 766 cfg &= ~S3C_CISCCTRL_SCAN_MASK; 767 768 if (fmt->field == V4L2_FIELD_INTERLACED || 769 fmt->field == V4L2_FIELD_INTERLACED_TB) { 770 cfg |= S3C_CISCCTRL_INTERLACE; 771 printk(KERN_ERR "%s: set S3C_CISCCTRL_INTERLACE\n", __func__); 772 } 773 else 774 cfg |= S3C_CISCCTRL_PROGRESSIVE; 775 776 writel(cfg, ctrl->regs + S3C_CISCCTRL); 777 778 cfg = readl(ctrl->regs + S3C_CIOCTRL); 779 cfg &= ~S3C_CIOCTRL_WEAVE_MASK; 780 781 if ((ctrl->cap) && (fmt->field == V4L2_FIELD_INTERLACED_TB)) 782 cfg |= S3C_CIOCTRL_WEAVE_OUT; 783 784 writel(cfg, ctrl->regs + S3C_CIOCTRL); 785 786 return 0; 787 }
776 根据输出field格式来设定FIMC的扫描方式,
设置为S3C_CISCCTRL_INTERLACE, 如果输入为progressive,则输出半帧数据;如果输入为interlace,输出仅为1/4帧,在s5pv210的datasheet中也注明了这种情况下输入不能为interlace
设置为S3C_CISCCTRL_PROGRESSIVE,如果输入为interlace,则输出半帧数据; 如果输入是progressive,则输出是整帧数据。
781 ~ 782 先了解下V4L2_FIELD_INTERLACED_TB和 V4L2_FIELD_INTERLACED的区别, 设置这个标志后,even field(top field) 被输出而odd field被忽略掉
具体原因我开始猜测了:把even field和odd field交织在一起是会产生毛刺的,所以有时会仅取一场 even field和 odd field之一来代表一帧数据。
这里我比较奇怪的是为什么没有处理V4L2_FIELD_INTERLACED_BT
- 789intfimc_hwset_input_rot(structfimc_control*ctrl,u32rot,u32flip)
- 790{
- 791u32cfg,val;
- 792
- 793cfg=readl(ctrl->regs+S3C_CITRGFMT);
- 794cfg&=~S3C_CITRGFMT_INROT90_CLOCKWISE;
- 795
- 796val=fimc_mapping_rot_flip(rot,flip);
- 797
- 798if(val&FIMC_ROT)
- 799cfg|=S3C_CITRGFMT_INROT90_CLOCKWISE;
- 800
- 801writel(cfg,ctrl->regs+S3C_CITRGFMT);
- 802
- 803return0;
- 804}
789 int fimc_hwset_input_rot(struct fimc_control *ctrl, u32 rot, u32 flip) 790 { 791 u32 cfg, val; 792 793 cfg = readl(ctrl->regs + S3C_CITRGFMT); 794 cfg &= ~S3C_CITRGFMT_INROT90_CLOCKWISE; 795 796 val = fimc_mapping_rot_flip(rot, flip); 797 798 if (val & FIMC_ROT) 799 cfg |= S3C_CITRGFMT_INROT90_CLOCKWISE; 800 801 writel(cfg, ctrl->regs + S3C_CITRGFMT); 802 803 return 0; 804 }
796 调用fimc_mapping_rot_flip把 for flip映射为寄存器参数值,但是由于FIMC的input仅仅支持90 degree clockwise rotate,所以算出来的 flip值实际上没有用的,而且FIMC子系统并没有真正调用这个函数,就是一摆设
- 838intfimc43_hwset_scaler(structfimc_control*ctrl,structfimc_scaler*sc)
- 839{
- 840u32cfg=readl(ctrl->regs+S3C_CISCCTRL);
- 841u32cfg_ext=readl(ctrl->regs+S3C_CIEXTEN);
- 842
- 843cfg&=~(S3C_CISCCTRL_SCALERBYPASS|
- 844S3C_CISCCTRL_SCALEUP_H|S3C_CISCCTRL_SCALEUP_V|
- 845S3C_CISCCTRL_MAIN_V_RATIO_MASK|
- 846S3C_CISCCTRL_MAIN_H_RATIO_MASK|
- 847S3C_CISCCTRL_CSCR2Y_WIDE|
- 848S3C_CISCCTRL_CSCY2R_WIDE);
- 849
- 850#ifdefCONFIG_VIDEO_FIMC_RANGE_WIDE
- 851cfg|=(S3C_CISCCTRL_CSCR2Y_WIDE|S3C_CISCCTRL_CSCY2R_WIDE);
- 852#endif
- 853
- 854if(sc->bypass)
- 855cfg|=S3C_CISCCTRL_SCALERBYPASS;
- 856
- 857if(sc->scaleup_h)
- 858cfg|=S3C_CISCCTRL_SCALEUP_H;
- 859
- 860if(sc->scaleup_v)
- 861cfg|=S3C_CISCCTRL_SCALEUP_V;
- 862
- 863cfg|=S3C_CISCCTRL_MAINHORRATIO(sc->main_hratio);
- 864cfg|=S3C_CISCCTRL_MAINVERRATIO(sc->main_vratio);
- 865
- 866writel(cfg,ctrl->regs+S3C_CISCCTRL);
- 867
- 868cfg_ext&=~S3C_CIEXTEN_MAINHORRATIO_EXT_MASK;
- 869cfg_ext&=~S3C_CIEXTEN_MAINVERRATIO_EXT_MASK;
- 870
- 871cfg_ext|=S3C_CIEXTEN_MAINHORRATIO_EXT(sc->main_hratio);
- 872cfg_ext|=S3C_CIEXTEN_MAINVERRATIO_EXT(sc->main_vratio);
- 873
- 874writel(cfg_ext,ctrl->regs+S3C_CIEXTEN);
- 875
- 876return0;
- 877}
838 int fimc43_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc) 839 { 840 u32 cfg = readl(ctrl->regs + S3C_CISCCTRL); 841 u32 cfg_ext = readl(ctrl->regs + S3C_CIEXTEN); 842 843 cfg &= ~(S3C_CISCCTRL_SCALERBYPASS | 844 S3C_CISCCTRL_SCALEUP_H | S3C_CISCCTRL_SCALEUP_V | 845 S3C_CISCCTRL_MAIN_V_RATIO_MASK | 846 S3C_CISCCTRL_MAIN_H_RATIO_MASK | 847 S3C_CISCCTRL_CSCR2Y_WIDE | 848 S3C_CISCCTRL_CSCY2R_WIDE); 849 850 #ifdef CONFIG_VIDEO_FIMC_RANGE_WIDE 851 cfg |= (S3C_CISCCTRL_CSCR2Y_WIDE | S3C_CISCCTRL_CSCY2R_WIDE); 852 #endif 853 854 if (sc->bypass) 855 cfg |= S3C_CISCCTRL_SCALERBYPASS; 856 857 if (sc->scaleup_h) 858 cfg |= S3C_CISCCTRL_SCALEUP_H; 859 860 if (sc->scaleup_v) 861 cfg |= S3C_CISCCTRL_SCALEUP_V; 862 863 cfg |= S3C_CISCCTRL_MAINHORRATIO(sc->main_hratio); 864 cfg |= S3C_CISCCTRL_MAINVERRATIO(sc->main_vratio); 865 866 writel(cfg, ctrl->regs + S3C_CISCCTRL); 867 868 cfg_ext &= ~S3C_CIEXTEN_MAINHORRATIO_EXT_MASK; 869 cfg_ext &= ~S3C_CIEXTEN_MAINVERRATIO_EXT_MASK; 870 871 cfg_ext |= S3C_CIEXTEN_MAINHORRATIO_EXT(sc->main_hratio); 872 cfg_ext |= S3C_CIEXTEN_MAINVERRATIO_EXT(sc->main_vratio); 873 874 writel(cfg_ext, ctrl->regs + S3C_CIEXTEN); 875 876 return 0; 877 }
854 FIMC仅仅在camera input 格式为JPEG时 设置sc->bypass为1, 这是因为在这种情况下图片的尺寸可能大于scaler能处理的最大尺寸
scaler是我认为比较难理解的地方,有很多莫名秒的变量,无用的变量,按我现在得出的结论,scaler部分三星开发人员写了很多垃圾代码,在作者还没撸清的前提下,我就不分析了。
- 1085intfimc_hwset_output_rgb(structfimc_control*ctrl,u32pixelformat)
- 1086{
- 1087u32cfg=readl(ctrl->regs+S3C_CISCCTRL);
- 1088cfg&=~S3C_CISCCTRL_OUTRGB_FMT_RGB_MASK;
- 1089
- 1090if(pixelformat==V4L2_PIX_FMT_RGB32)
- 1091cfg|=S3C_CISCCTRL_OUTRGB_FMT_RGB888;
- 1092elseif(pixelformat==V4L2_PIX_FMT_RGB565)
- 1093cfg|=S3C_CISCCTRL_OUTRGB_FMT_RGB565;
- 1094
- 1095writel(cfg,ctrl->regs+S3C_CISCCTRL);
- 1096
- 1097return0;
- 1098}
1085 int fimc_hwset_output_rgb(struct fimc_control *ctrl, u32 pixelformat)1086 {1087 u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);1088 cfg &= ~S3C_CISCCTRL_OUTRGB_FMT_RGB_MASK;10891090 if (pixelformat == V4L2_PIX_FMT_RGB32)1091 cfg |= S3C_CISCCTRL_OUTRGB_FMT_RGB888;1092 else if (pixelformat == V4L2_PIX_FMT_RGB565)1093 cfg |= S3C_CISCCTRL_OUTRGB_FMT_RGB565;10941095 writel(cfg, ctrl->regs + S3C_CISCCTRL);10961097 return 0;1098 }
设置output DMA RGB格式,FIMC硬件支持RGB565, RGB888和RGB666,因为V4L2没有RGB666的说法, 所以代码并不支持RGB666。
火大,看什么代码都不顺眼,为什么三桑要把output DMA RGB格式的设置放到Main-scaler control寄存器,就不能和ouput DMA YUV设置寄存器放一块
- 1100intfimc_hwset_ext_rgb(structfimc_control*ctrl,intenable)
- 1101{
- 1102u32cfg=readl(ctrl->regs+S3C_CISCCTRL);
- 1103cfg&=~S3C_CISCCTRL_EXTRGB_EXTENSION;
- 1104
- 1105if(enable)
- 1106cfg|=S3C_CISCCTRL_EXTRGB_EXTENSION;
- 1107
- 1108writel(cfg,ctrl->regs+S3C_CISCCTRL);
- 1109
- 1110return0;
- 1111}
1100 int fimc_hwset_ext_rgb(struct fimc_control *ctrl, int enable)1101 {1102 u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);1103 cfg &= ~S3C_CISCCTRL_EXTRGB_EXTENSION;1104 1105 if (enable)1106 cfg |= S3C_CISCCTRL_EXTRGB_EXTENSION;1107 1108 writel(cfg, ctrl->regs + S3C_CISCCTRL);1109 1110 return 0;1111 }
RGB565/RGB666 转换为 RGB888的方式,FIMC控制器支持两种转换
1. normal模式,简单的末位填充00, 000
2. extension模式,量化补偿方式,S5PV210 FIMC控制器的做法是用原始数据高位补充新数据的低位
- 1731intfimc_hwset_output_addr_style(structfimc_control*ctrl,u32pixelformat)
- 1732{
- 1733u32cfg=readl(ctrl->regs+S3C_CIDMAPARAM);
- 1734cfg&=~S3C_CIDMAPARAM_W_MODE_MASK;
- 1735
- 1736if(pixelformat==V4L2_PIX_FMT_NV12T)
- 1737cfg|=S3C_CIDMAPARAM_W_MODE_64X32;
- 1738else
- 1739cfg|=S3C_CIDMAPARAM_W_MODE_LINEAR;
- 1740
- 1741writel(cfg,ctrl->regs+S3C_CIDMAPARAM);
- 1742
- 1743return0;
- 1744}
1731 int fimc_hwset_output_addr_style(struct fimc_control *ctrl, u32 pixelformat)1732 {1733 u32 cfg = readl(ctrl->regs + S3C_CIDMAPARAM);1734 cfg &= ~S3C_CIDMAPARAM_W_MODE_MASK;17351736 if (pixelformat == V4L2_PIX_FMT_NV12T)1737 cfg |= S3C_CIDMAPARAM_W_MODE_64X32;1738 else1739 cfg |= S3C_CIDMAPARAM_W_MODE_LINEAR;17401741 writel(cfg, ctrl->regs + S3C_CIDMAPARAM);17421743 return 0;1744 }
先唠叨一下V4L2_PIX_FMT_NV12T格式,NV12T后面这个T就是Tile的缩写,NV12T就是tile版本的NV12格式,NV12T的图块包含 64 × 32 pixels.
和tile对应的就是linear,所以我们可以称V4L2_PIX_FMT_NV12为linear的NV12。
再看代码就简单了
更多相关文章
- Android原生音量控制实例详解
- Android(安卓)之 设置EditText最大可输入字符
- GridView添加网格线
- android 检测外接键盘并设置输入法布局
- Android(安卓)LBS系列01 使用Location Manager
- Android(安卓)MediaRecorder录制视频提示start failed的解决办法
- Android绘图系列(五)——绘制文本
- Android(安卓)使用NDK (JNI)简单解压7z压缩文件
- Android(安卓)TextView 设置多种颜色