:fimc_regs.c是fimc框架操作camera 硬件的接口,fimc框架把所有硬件相关的操作都放在这个文件中

[html] view plain copy print ?
  1. 100intfimc_hwset_camera_source(structfimc_control*ctrl)
  2. 101{
  3. 102structs3c_platform_camera*cam=ctrl->cam;
  4. 103u32cfg=0;
  5. 104
  6. 105/*fornow,wesupportonlyITU6018bitmode*/
  7. 106cfg|=S3C_CISRCFMT_ITU601_8BIT;
  8. 107cfg|=cam->order422;
  9. 108
  10. 109if(cam->type==CAM_TYPE_ITU)
  11. 110cfg|=cam->fmt;
  12. 111
  13. 112cfg|=S3C_CISRCFMT_SOURCEHSIZE(cam->width);
  14. 113cfg|=S3C_CISRCFMT_SOURCEVSIZE(cam->height);
  15. 114
  16. 115writel(cfg,ctrl->regs+S3C_CISRCFMT);
  17. 116
  18. 117return0;
  19. 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


[html] view plain copy print ?
  1. 159intfimc_hwset_output_area_size(structfimc_control*ctrl,u32size)
  2. 160{
  3. 161u32cfg=0;
  4. 162
  5. 163cfg=S3C_CITAREA_TARGET_AREA(size);
  6. 164
  7. 165writel(cfg,ctrl->regs+S3C_CITAREA);
  8. 166
  9. 167return0;
  10. 168}
CITAREA: output DMA target area register

设置output DMA的target大小,这个值并不是buffer空间的大小,而是输出图像的H_size * V_size


[html] view plain copy print ?
  1. 170voidfimc_wait_disable_capture(structfimc_control*ctrl)
  2. 171{
  3. 172unsignedlongtimeo=jiffies+20;/*timeoutof100ms*/
  4. 173u32cfg;
  5. 174
  6. 175if(!ctrl||!ctrl->cap||
  7. 176ctrl->cap->fmt.colorspace==V4L2_COLORSPACE_JPEG)
  8. 177return;
  9. 178
  10. 179while(time_before(jiffies,timeo)){
  11. 180cfg=readl(ctrl->regs+S3C_CISTATUS);
  12. 181
  13. 182if(0==(cfg&S3C_CISTATUS_IMGCPTEN))
  14. 183break;
  15. 184
  16. 185msleep(10);
  17. 186}
  18. 187
  19. 188dev_dbg(ctrl->dev,"IMGCPTEN:Waittime=%dms\n",
  20. 189jiffies_to_msecs(jiffies-timeo+20));
  21. 190
  22. 191return;
  23. 192}

在disable capture后,可以调用这个函数,来保证disable capture操作完成

S3C_CISTATUS_IMGCPTEN 标识是否image capture enable的状态


[html] view plain copy print ?
  1. 194intfimc_hwset_image_effect(structfimc_control*ctrl)
  2. 195{
  3. 196u32cfg=0;
  4. 197
  5. 198if(ctrl->fe.ie_on){
  6. 199if(ctrl->fe.ie_after_sc)
  7. 200cfg|=S3C_CIIMGEFF_IE_SC_AFTER;
  8. 201
  9. 202cfg|=S3C_CIIMGEFF_FIN(ctrl->fe.fin);
  10. 203
  11. 204if(ctrl->fe.fin==FIMC_EFFECT_FIN_ARBITRARY_CBCR)
  12. 205cfg|=S3C_CIIMGEFF_PAT_CB(ctrl->fe.pat_cb)|
  13. 206S3C_CIIMGEFF_PAT_CR(ctrl->fe.pat_cr);
  14. 207
  15. 208cfg|=S3C_CIIMGEFF_IE_ENABLE;
  16. 209}
  17. 210
  18. 211writel(cfg,ctrl->regs+S3C_CIIMGEFF);
  19. 212
  20. 213return0;
  21. 214}

FIMC控制器支持图片特效处理,因此fimc的V4L2 s_ctl接口提供了特效控制

CIIMGEFF寄存器控制图片的特效,具体的特效说明,参看s5pv210 datasheet


[html] view plain copy print ?
  1. 267intfimc_hwset_reset(structfimc_control*ctrl)
  2. 268{
  3. 269u32cfg=0;
  4. 270
  5. 271cfg=readl(ctrl->regs+S3C_CISRCFMT);
  6. 272cfg|=S3C_CISRCFMT_ITU601_8BIT;
  7. 273writel(cfg,ctrl->regs+S3C_CISRCFMT);
  8. 274
  9. 275/*s/wreset*/
  10. 276cfg=readl(ctrl->regs+S3C_CIGCTRL);
  11. 277cfg|=(S3C_CIGCTRL_SWRST);
  12. 278writel(cfg,ctrl->regs+S3C_CIGCTRL);
  13. 279mdelay(1);
  14. 280
  15. 281cfg=readl(ctrl->regs+S3C_CIGCTRL);
  16. 282cfg&=~S3C_CIGCTRL_SWRST;
  17. 283writel(cfg,ctrl->regs+S3C_CIGCTRL);
  18. 284
  19. 285/*incaseofITU656,CISRCFMT[31]shouldbe0*/
  20. 286if((ctrl->cap!=NULL)&&(ctrl->cam->fmt==ITU_656_YCBCR422_8BIT)){
  21. 287cfg=readl(ctrl->regs+S3C_CISRCFMT);
  22. 288cfg&=~S3C_CISRCFMT_ITU601_8BIT;
  23. 289writel(cfg,ctrl->regs+S3C_CISRCFMT);
  24. 290}
  25. 291
  26. 292fimc_reset_cfg(ctrl);
  27. 293
  28. 294return0;
  29. 295}

FIMC软件复位过程:

S5PV210 datasheet推荐使用如下初始化序列

对于ITU601: ITU601_656n置1 -> SwRst置1 -> SwRst置0

对于ITU656: ITU601_656n置1 -> SwRst置1 -> SwRst置0 -> ITU601_656置0


[html] view plain copy print ?
  1. 335intfimc_hwset_camera_offset(structfimc_control*ctrl)
  2. 336{
  3. 337structs3c_platform_camera*cam=ctrl->cam;
  4. 338structv4l2_rect*rect=&cam->window;
  5. 339u32cfg,h1,h2,v1,v2;
  6. 340
  7. 341if(!cam){
  8. 342fimc_err("%s:noactivecamera\n",__func__);
  9. 343return-ENODEV;
  10. 344}
  11. 345
  12. 346h1=rect->left;
  13. 347h2=cam->width-rect->width-rect->left;
  14. 348v1=rect->top;
  15. 349v2=cam->height-rect->height-rect->top;
  16. 350
  17. 351cfg=readl(ctrl->regs+S3C_CIWDOFST);
  18. 352cfg&=~(S3C_CIWDOFST_WINHOROFST_MASK|S3C_CIWDOFST_WINVEROFST_MASK);
  19. 353cfg|=S3C_CIWDOFST_WINHOROFST(h1);
  20. 354cfg|=S3C_CIWDOFST_WINVEROFST(v1);
  21. 355cfg|=S3C_CIWDOFST_WINOFSEN;
  22. 356writel(cfg,ctrl->regs+S3C_CIWDOFST);
  23. 357
  24. 358cfg=0;
  25. 359cfg|=S3C_CIWDOFST2_WINHOROFST2(h2);
  26. 360cfg|=S3C_CIWDOFST2_WINVEROFST2(v2);
  27. 361writel(cfg,ctrl->regs+S3C_CIWDOFST2);
  28. 362
  29. 363return0;
  30. 364}

h1: Window Horizon Offset, v1: Window Vertical Offset

h2: Window Horizon Offset2, v2: Window Vertical Offset2

下面这个图很明了的解释了这几个坐标概念


h1, h2, v1, v2这四个坐标就定义了crop的范围,上图右边部分就是crop结果


[html] view plain copy print ?
  1. 366intfimc_hwset_camera_polarity(structfimc_control*ctrl)
  2. 367{
  3. 368structs3c_platform_camera*cam=ctrl->cam;
  4. 369u32cfg;
  5. 370
  6. 371if(!cam){
  7. 372fimc_err("%s:noactivecamera\n",__func__);
  8. 373return-ENODEV;
  9. 374}
  10. 375
  11. 376cfg=readl(ctrl->regs+S3C_CIGCTRL);
  12. 377
  13. 378cfg&=~(S3C_CIGCTRL_INVPOLPCLK|S3C_CIGCTRL_INVPOLVSYNC|
  14. 379S3C_CIGCTRL_INVPOLHREF|S3C_CIGCTRL_INVPOLHSYNC);
  15. 380
  16. 381if(cam->inv_pclk)
  17. 382cfg|=S3C_CIGCTRL_INVPOLPCLK;
  18. 383
  19. 384if(cam->inv_vsync)
  20. 385cfg|=S3C_CIGCTRL_INVPOLVSYNC;
  21. 386
  22. 387if(cam->inv_href)
  23. 388cfg|=S3C_CIGCTRL_INVPOLHREF;
  24. 389
  25. 390if(cam->inv_hsync)
  26. 391cfg|=S3C_CIGCTRL_INVPOLHSYNC;
  27. 392
  28. 393writel(cfg,ctrl->regs+S3C_CIGCTRL);
  29. 394
  30. 395return0;
  31. 396}

camera sensor输出到fimc控制器的几个信号: pixclk, href(hsync), vsync。 sensor可能会设置这几个信号的极性,因此FIMC控制器端也需要和这个信号的极性匹配

具体配置需要参考sensor的输出,一般情况下无极性翻转。

对于BT656信号来说,只需要考虑pixclk的极性。


[html] view plain copy print ?
  1. 434intfimc43_hwset_camera_type(structfimc_control*ctrl)
  2. 435{
  3. 436structs3c_platform_camera*cam=ctrl->cam;
  4. 437u32cfg;
  5. 438
  6. 439if(!cam){
  7. 440fimc_err("%s:noactivecamera\n",__func__);
  8. 441return-ENODEV;
  9. 442}
  10. 443
  11. 444cfg=readl(ctrl->regs+S3C_CIGCTRL);
  12. 445cfg&=~(S3C_CIGCTRL_TESTPATTERN_MASK|S3C_CIGCTRL_SELCAM_ITU_MASK|
  13. 446S3C_CIGCTRL_SELCAM_MIPI_MASK|S3C_CIGCTRL_SELCAM_FIMC_MASK|
  14. 447S3C_CIGCTRL_SELWB_CAMIF_MASK);
  15. 448
  16. 449/*Interfaceselection*/
  17. 450if(cam->id==CAMERA_WB){
  18. 451cfg|=S3C_CIGCTRL_SELWB_CAMIF_WRITEBACK;
  19. 452}elseif(cam->type==CAM_TYPE_MIPI){
  20. 453cfg|=S3C_CIGCTRL_SELCAM_FIMC_MIPI;
  21. 454
  22. 455/*C110/V210SupportonlyMIPIAsupport*/
  23. 456cfg|=S3C_CIGCTRL_SELCAM_MIPI_A;
  24. 457
  25. 458/*FIXME:TemporaryMIPICSISData32bitaligned*/
  26. 459if(ctrl->cap->fmt.pixelformat==V4L2_PIX_FMT_JPEG)
  27. 460writel((MIPI_USER_DEF_PACKET_1|(0x1<<8)),
  28. 461ctrl->regs+S3C_CSIIMGFMT);
  29. 462else
  30. 463writel(cam->fmt|(0x1<<8),
  31. 464ctrl->regs+S3C_CSIIMGFMT);
  32. 465}elseif(cam->type==CAM_TYPE_ITU){
  33. 466if(cam->id==CAMERA_PAR_A)
  34. 467cfg|=S3C_CIGCTRL_SELCAM_ITU_A;
  35. 468else
  36. 469cfg|=S3C_CIGCTRL_SELCAM_ITU_B;
  37. 470/*switchtoITUinterface*/
  38. 471cfg|=S3C_CIGCTRL_SELCAM_FIMC_ITU;
  39. 472}else{
  40. 473fimc_err("%s:invalidcamerabustypeselected\n",__func__);
  41. 474return-EINVAL;
  42. 475}
  43. 476
  44. 477writel(cfg,ctrl->regs+S3C_CIGCTRL);
  45. 478
  46. 479return0;
  47. 480}


FIMC提供了三个物理camera接口:

两个ITU类型的:Camera A(GPE0_0 --- GPE1_4)和Camera B(GPJ0_0 --- GPJ1_4),

一个MIPI类型的: Camera C

465 ~ 469 选择使用哪个物理camera接口,这个需要查看原理图来预设cam->id。


[html] view plain copy print ?
  1. 522intfimc_hwset_jpeg_mode(structfimc_control*ctrl,boolenable)
  2. 523{
  3. 524u32cfg;
  4. 525cfg=readl(ctrl->regs+S3C_CIGCTRL);
  5. 526
  6. 527if(enable)
  7. 528cfg|=S3C_CIGCTRL_CAM_JPEG;
  8. 529else
  9. 530cfg&=~S3C_CIGCTRL_CAM_JPEG;
  10. 531
  11. 532writel(cfg,ctrl->regs+S3C_CIGCTRL);
  12. 533
  13. 534return0;
  14. 535}
对于ITU601输入如果输入数据是8bit jpeg格式(压缩格式),那么就要设置JPEG标志位,这时FIMC会忽略scaler和转换。

对于BT656来说只能是YUYV格式


[html] view plain copy print ?
  1. 537intfimc_hwset_output_size(structfimc_control*ctrl,intwidth,intheight)
  2. 538{
  3. 539u32cfg=readl(ctrl->regs+S3C_CITRGFMT);
  4. 540
  5. 541printk(KERN_ERR"%s:width(%d),height(%d)\n",__func__,width,height);
  6. 542
  7. 543cfg&=~(S3C_CITRGFMT_TARGETH_MASK|S3C_CITRGFMT_TARGETV_MASK);
  8. 544
  9. 545cfg|=S3C_CITRGFMT_TARGETHSIZE(width);
  10. 546cfg|=S3C_CITRGFMT_TARGETVSIZE(height);
  11. 547
  12. 548writel(cfg,ctrl->regs+S3C_CITRGFMT);
  13. 549
  14. 550return0;
  15. 551}

545 ~ 546 是FIMC输出图像的width和height size, 他们不应该大于camera source height size和 source width size,当然这并不意味着FIMC的scaler没有放大功能,FIMC的scaler有放大功能

,但是放大后的尺寸不能超过source Hsize和souce Vsize


[html] view plain copy print ?
  1. 553intfimc_hwset_output_colorspace(structfimc_control*ctrl,u32pixelformat)
  2. 554{
  3. 555structs3c_platform_fimc*pdata=to_fimc_plat(ctrl->dev);
  4. 556u32cfg;
  5. 557
  6. 558if(pdata->hw_ver!=0x40){
  7. 559if(pixelformat==V4L2_PIX_FMT_YUV444){
  8. 560cfg=readl(ctrl->regs+S3C_CIEXTEN);
  9. 561cfg|=S3C_CIEXTEN_YUV444_OUT;
  10. 562writel(cfg,ctrl->regs+S3C_CIEXTEN);
  11. 563
  12. 564return0;
  13. 565}else{
  14. 566cfg=readl(ctrl->regs+S3C_CIEXTEN);
  15. 567cfg&=~S3C_CIEXTEN_YUV444_OUT;
  16. 568writel(cfg,ctrl->regs+S3C_CIEXTEN);
  17. 569}
  18. 570}
  19. 571
  20. 572cfg=readl(ctrl->regs+S3C_CITRGFMT);
  21. 573cfg&=~S3C_CITRGFMT_OUTFORMAT_MASK;
  22. 574
  23. 575switch(pixelformat){
  24. 576caseV4L2_PIX_FMT_JPEG:
  25. 577break;
  26. 578caseV4L2_PIX_FMT_RGB565:/*fallthrough*/
  27. 579caseV4L2_PIX_FMT_RGB32:
  28. 580cfg|=S3C_CITRGFMT_OUTFORMAT_RGB;
  29. 581break;
  30. 582
  31. 583caseV4L2_PIX_FMT_YUYV:/*fallthrough*/
  32. 584caseV4L2_PIX_FMT_UYVY:/*fallthrough*/
  33. 585caseV4L2_PIX_FMT_VYUY:/*fallthrough*/
  34. 586caseV4L2_PIX_FMT_YVYU:
  35. 587cfg|=S3C_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
  36. 588break;
  37. 589
  38. 590caseV4L2_PIX_FMT_NV16:/*fallthrough*/
  39. 591caseV4L2_PIX_FMT_NV61:/*fallthrough*/
  40. 592caseV4L2_PIX_FMT_YUV422P:
  41. 593cfg|=S3C_CITRGFMT_OUTFORMAT_YCBCR422;
  42. 594break;
  43. 595
  44. 596caseV4L2_PIX_FMT_YUV420:/*fallthrough*/
  45. 597caseV4L2_PIX_FMT_NV12:/*fallthrough*/
  46. 598caseV4L2_PIX_FMT_NV12T:/*fallthrough*/
  47. 599caseV4L2_PIX_FMT_NV21:
  48. 600cfg|=S3C_CITRGFMT_OUTFORMAT_YCBCR420;
  49. 601break;
  50. 602
  51. 603default:
  52. 604fimc_err("%s:invalidpixelformat\n",__func__);
  53. 605break;
  54. 606}
  55. 607
  56. 608writel(cfg,ctrl->regs+S3C_CITRGFMT);
  57. 609
  58. 610return0;
  59. 611}

设置FIMC的输出颜色格式,FIMC支持颜色空间转换,应用程序或测试程序可以通过S_FMT ioctl指定希望的输出颜色格式


[html] view plain copy print ?
  1. 615intfimc_hwset_output_rot_flip(structfimc_control*ctrl,u32rot,u32flip)
  2. 616{
  3. 617u32cfg,val;
  4. 618
  5. 619cfg=readl(ctrl->regs+S3C_CITRGFMT);
  6. 620cfg&=~S3C_CITRGFMT_FLIP_MASK;
  7. 621cfg&=~S3C_CITRGFMT_OUTROT90_CLOCKWISE;
  8. 622
  9. 623val=fimc_mapping_rot_flip(rot,flip);
  10. 624
  11. 625if(val&FIMC_ROT)
  12. 626cfg|=S3C_CITRGFMT_OUTROT90_CLOCKWISE;
  13. 627
  14. 628if(val&FIMC_XFLIP)
  15. 629cfg|=S3C_CITRGFMT_FLIP_X_MIRROR;
  16. 630
  17. 631if(val&FIMC_YFLIP)
  18. 632cfg|=S3C_CITRGFMT_FLIP_Y_MIRROR;
  19. 633
  20. 634writel(cfg,ctrl->regs+S3C_CITRGFMT);
  21. 635
  22. 636return0;
  23. 637}


FIMC控制器支持图片的翻转,应用层可以通过s_ctrl ioctl来设置翻转


[html] view plain copy print ?
  1. 690intfimc_hwset_output_address(structfimc_control*ctrl,
  2. 691structfimc_buf_set*bs,intid)
  3. 692{
  4. 693printk(KERN_ERR"%s:FIMC_ADDR_Y=0x%x,FIMC_ADDR_CB=0x%x,FIMC_ADDR_CR=0x%x\n",
  5. 694__func__,bs->base[FIMC_ADDR_Y],bs->base[FIMC_ADDR_CB],
  6. 695bs->base[FIMC_ADDR_CR]);
  7. 696writel(bs->base[FIMC_ADDR_Y],ctrl->regs+S3C_CIOYSA(id));
  8. 697writel(bs->base[FIMC_ADDR_CB],ctrl->regs+S3C_CIOCBSA(id));
  9. 698writel(bs->base[FIMC_ADDR_CR],ctrl->regs+S3C_CIOCRSA(id));
  10. 699
  11. 700return0;
  12. 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


[html] view plain copy print ?
  1. 703intfimc_hwset_output_yuv(structfimc_control*ctrl,u32pixelformat)
  2. 704{
  3. 705u32cfg;
  4. 706
  5. 707cfg=readl(ctrl->regs+S3C_CIOCTRL);
  6. 708cfg&=~(S3C_CIOCTRL_ORDER2P_MASK|S3C_CIOCTRL_ORDER422_MASK|
  7. 709S3C_CIOCTRL_YCBCR_PLANE_MASK);
  8. 710
  9. 711switch(pixelformat){
  10. 712/*1planeformats*/
  11. 713caseV4L2_PIX_FMT_YUYV:
  12. 714cfg|=S3C_CIOCTRL_ORDER422_YCBYCR;
  13. 715break;
  14. 716
  15. 717caseV4L2_PIX_FMT_UYVY:
  16. 718cfg|=S3C_CIOCTRL_ORDER422_CBYCRY;
  17. 719break;
  18. 720
  19. 721caseV4L2_PIX_FMT_VYUY:
  20. 722cfg|=S3C_CIOCTRL_ORDER422_CRYCBY;
  21. 723break;
  22. 724
  23. 725caseV4L2_PIX_FMT_YVYU:
  24. 726cfg|=S3C_CIOCTRL_ORDER422_YCRYCB;
  25. 727break;
  26. 728
  27. 729/*2planeformats*/
  28. 730caseV4L2_PIX_FMT_NV12:/*fallthrough*/
  29. 731caseV4L2_PIX_FMT_NV12T:/*fallthrough*/
  30. 732caseV4L2_PIX_FMT_NV16:
  31. 733cfg|=S3C_CIOCTRL_ORDER2P_LSB_CBCR;
  32. 734cfg|=S3C_CIOCTRL_YCBCR_2PLANE;
  33. 735break;
  34. 736
  35. 737caseV4L2_PIX_FMT_NV21:/*fallthrough*/
  36. 738caseV4L2_PIX_FMT_NV61:
  37. 739cfg|=S3C_CIOCTRL_ORDER2P_LSB_CRCB;
  38. 740cfg|=S3C_CIOCTRL_YCBCR_2PLANE;
  39. 741break;
  40. 742
  41. 743/*3planeformats*/
  42. 744caseV4L2_PIX_FMT_YUV422P:/*fallthrough*/
  43. 745caseV4L2_PIX_FMT_YUV420:
  44. 746cfg|=S3C_CIOCTRL_YCBCR_3PLANE;
  45. 747break;
  46. 748}
  47. 749
  48. 750writel(cfg,ctrl->regs+S3C_CIOCTRL);
  49. 751
  50. 752return0;
  51. 753}

YUV有很多种格式,可以分为两大类: 打包格式(packed)和平面格式(planer),打包格式是YUV分量放在一个数组中,相邻的几个分量组成一个像素的。而后者使用两个或者三个分量数组,两个分量数组是将Y和UV分量分开,三个分量数组则是将YUV分量放在不同的数组中


[html] view plain copy print ?
  1. 755intfimc_hwset_output_scan(structfimc_control*ctrl,
  2. 756structv4l2_pix_format*fmt)
  3. 757{
  4. 758structs3c_platform_fimc*pdata=to_fimc_plat(ctrl->dev);
  5. 759u32cfg;
  6. 760
  7. 761/*nothingtodo:FIMC40notsupportedinterlacedandweaveoutput*/
  8. 762if(pdata->hw_ver==0x40)
  9. 763return0;
  10. 764
  11. 765cfg=readl(ctrl->regs+S3C_CISCCTRL);
  12. 766cfg&=~S3C_CISCCTRL_SCAN_MASK;
  13. 767
  14. 768if(fmt->field==V4L2_FIELD_INTERLACED||
  15. 769fmt->field==V4L2_FIELD_INTERLACED_TB){
  16. 770cfg|=S3C_CISCCTRL_INTERLACE;
  17. 771printk(KERN_ERR"%s:setS3C_CISCCTRL_INTERLACE\n",__func__);
  18. 772}
  19. 773else
  20. 774cfg|=S3C_CISCCTRL_PROGRESSIVE;
  21. 775
  22. 776writel(cfg,ctrl->regs+S3C_CISCCTRL);
  23. 777
  24. 778cfg=readl(ctrl->regs+S3C_CIOCTRL);
  25. 779cfg&=~S3C_CIOCTRL_WEAVE_MASK;
  26. 780
  27. 781if((ctrl->cap)&&(fmt->field==V4L2_FIELD_INTERLACED_TB))
  28. 782cfg|=S3C_CIOCTRL_WEAVE_OUT;
  29. 783
  30. 784writel(cfg,ctrl->regs+S3C_CIOCTRL);
  31. 785
  32. 786return0;
  33. 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


[html] view plain copy print ?
  1. 789intfimc_hwset_input_rot(structfimc_control*ctrl,u32rot,u32flip)
  2. 790{
  3. 791u32cfg,val;
  4. 792
  5. 793cfg=readl(ctrl->regs+S3C_CITRGFMT);
  6. 794cfg&=~S3C_CITRGFMT_INROT90_CLOCKWISE;
  7. 795
  8. 796val=fimc_mapping_rot_flip(rot,flip);
  9. 797
  10. 798if(val&FIMC_ROT)
  11. 799cfg|=S3C_CITRGFMT_INROT90_CLOCKWISE;
  12. 800
  13. 801writel(cfg,ctrl->regs+S3C_CITRGFMT);
  14. 802
  15. 803return0;
  16. 804}

796 调用fimc_mapping_rot_flip把 for flip映射为寄存器参数值,但是由于FIMC的input仅仅支持90 degree clockwise rotate,所以算出来的 flip值实际上没有用的,而且FIMC子系统并没有真正调用这个函数,就是一摆设


[html] view plain copy print ?
  1. 838intfimc43_hwset_scaler(structfimc_control*ctrl,structfimc_scaler*sc)
  2. 839{
  3. 840u32cfg=readl(ctrl->regs+S3C_CISCCTRL);
  4. 841u32cfg_ext=readl(ctrl->regs+S3C_CIEXTEN);
  5. 842
  6. 843cfg&=~(S3C_CISCCTRL_SCALERBYPASS|
  7. 844S3C_CISCCTRL_SCALEUP_H|S3C_CISCCTRL_SCALEUP_V|
  8. 845S3C_CISCCTRL_MAIN_V_RATIO_MASK|
  9. 846S3C_CISCCTRL_MAIN_H_RATIO_MASK|
  10. 847S3C_CISCCTRL_CSCR2Y_WIDE|
  11. 848S3C_CISCCTRL_CSCY2R_WIDE);
  12. 849
  13. 850#ifdefCONFIG_VIDEO_FIMC_RANGE_WIDE
  14. 851cfg|=(S3C_CISCCTRL_CSCR2Y_WIDE|S3C_CISCCTRL_CSCY2R_WIDE);
  15. 852#endif
  16. 853
  17. 854if(sc->bypass)
  18. 855cfg|=S3C_CISCCTRL_SCALERBYPASS;
  19. 856
  20. 857if(sc->scaleup_h)
  21. 858cfg|=S3C_CISCCTRL_SCALEUP_H;
  22. 859
  23. 860if(sc->scaleup_v)
  24. 861cfg|=S3C_CISCCTRL_SCALEUP_V;
  25. 862
  26. 863cfg|=S3C_CISCCTRL_MAINHORRATIO(sc->main_hratio);
  27. 864cfg|=S3C_CISCCTRL_MAINVERRATIO(sc->main_vratio);
  28. 865
  29. 866writel(cfg,ctrl->regs+S3C_CISCCTRL);
  30. 867
  31. 868cfg_ext&=~S3C_CIEXTEN_MAINHORRATIO_EXT_MASK;
  32. 869cfg_ext&=~S3C_CIEXTEN_MAINVERRATIO_EXT_MASK;
  33. 870
  34. 871cfg_ext|=S3C_CIEXTEN_MAINHORRATIO_EXT(sc->main_hratio);
  35. 872cfg_ext|=S3C_CIEXTEN_MAINVERRATIO_EXT(sc->main_vratio);
  36. 873
  37. 874writel(cfg_ext,ctrl->regs+S3C_CIEXTEN);
  38. 875
  39. 876return0;
  40. 877}

854 FIMC仅仅在camera input 格式为JPEG时 设置sc->bypass为1, 这是因为在这种情况下图片的尺寸可能大于scaler能处理的最大尺寸

scaler是我认为比较难理解的地方,有很多莫名秒的变量,无用的变量,按我现在得出的结论,scaler部分三星开发人员写了很多垃圾代码,在作者还没撸清的前提下,我就不分析了。


[html] view plain copy print ?
  1. 1085intfimc_hwset_output_rgb(structfimc_control*ctrl,u32pixelformat)
  2. 1086{
  3. 1087u32cfg=readl(ctrl->regs+S3C_CISCCTRL);
  4. 1088cfg&=~S3C_CISCCTRL_OUTRGB_FMT_RGB_MASK;
  5. 1089
  6. 1090if(pixelformat==V4L2_PIX_FMT_RGB32)
  7. 1091cfg|=S3C_CISCCTRL_OUTRGB_FMT_RGB888;
  8. 1092elseif(pixelformat==V4L2_PIX_FMT_RGB565)
  9. 1093cfg|=S3C_CISCCTRL_OUTRGB_FMT_RGB565;
  10. 1094
  11. 1095writel(cfg,ctrl->regs+S3C_CISCCTRL);
  12. 1096
  13. 1097return0;
  14. 1098}

设置output DMA RGB格式,FIMC硬件支持RGB565, RGB888和RGB666,因为V4L2没有RGB666的说法, 所以代码并不支持RGB666。

火大,看什么代码都不顺眼,为什么三桑要把output DMA RGB格式的设置放到Main-scaler control寄存器,就不能和ouput DMA YUV设置寄存器放一块

[html] view plain copy print ?
  1. 1100intfimc_hwset_ext_rgb(structfimc_control*ctrl,intenable)
  2. 1101{
  3. 1102u32cfg=readl(ctrl->regs+S3C_CISCCTRL);
  4. 1103cfg&=~S3C_CISCCTRL_EXTRGB_EXTENSION;
  5. 1104
  6. 1105if(enable)
  7. 1106cfg|=S3C_CISCCTRL_EXTRGB_EXTENSION;
  8. 1107
  9. 1108writel(cfg,ctrl->regs+S3C_CISCCTRL);
  10. 1109
  11. 1110return0;
  12. 1111}

RGB565/RGB666 转换为 RGB888的方式,FIMC控制器支持两种转换

1. normal模式,简单的末位填充00, 000

2. extension模式,量化补偿方式,S5PV210 FIMC控制器的做法是用原始数据高位补充新数据的低位


[html] view plain copy print ?
  1. 1731intfimc_hwset_output_addr_style(structfimc_control*ctrl,u32pixelformat)
  2. 1732{
  3. 1733u32cfg=readl(ctrl->regs+S3C_CIDMAPARAM);
  4. 1734cfg&=~S3C_CIDMAPARAM_W_MODE_MASK;
  5. 1735
  6. 1736if(pixelformat==V4L2_PIX_FMT_NV12T)
  7. 1737cfg|=S3C_CIDMAPARAM_W_MODE_64X32;
  8. 1738else
  9. 1739cfg|=S3C_CIDMAPARAM_W_MODE_LINEAR;
  10. 1740
  11. 1741writel(cfg,ctrl->regs+S3C_CIDMAPARAM);
  12. 1742
  13. 1743return0;
  14. 1744}


先唠叨一下V4L2_PIX_FMT_NV12T格式,NV12T后面这个T就是Tile的缩写,NV12T就是tile版本的NV12格式,NV12T的图块包含 64 × 32 pixels.

和tile对应的就是linear,所以我们可以称V4L2_PIX_FMT_NV12为linear的NV12。

再看代码就简单了

更多相关文章

  1. Android原生音量控制实例详解
  2. Android(安卓)之 设置EditText最大可输入字符
  3. GridView添加网格线
  4. android 检测外接键盘并设置输入法布局
  5. Android(安卓)LBS系列01 使用Location Manager
  6. Android(安卓)MediaRecorder录制视频提示start failed的解决办法
  7. Android绘图系列(五)——绘制文本
  8. Android(安卓)使用NDK (JNI)简单解压7z压缩文件
  9. Android(安卓)TextView 设置多种颜色

随机推荐

  1. Rootzwiki 采访 CM 创始人 Steve Kondik
  2. Android(安卓)系统基础
  3. Android用户界面设计:基本按钮
  4. 一个Android登陆/注册XML布局文件代码
  5. Android(安卓)res/raw文件以及raw与res/a
  6. Pro Android(安卓)4 第六章 构建用户界面
  7. Android组开发规范-参考95%参考阿里
  8. 在android屏幕上 上 下 左 右 四个方向移
  9. Android(安卓)P 图形显示系统(九) Android
  10. 想抢先体验Android操作系统的魅力吗?那就