分类:Android嵌入式LinuxSamsung S5PV210 1031人阅读 评论(2) 收藏 举报 cam struct c output interface image

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

[html] view plain copy
  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,CAM_ORDER422_8BIT_YCRYCB, CAM_ORDER422_8BIT_CBYCRY, CAM_ORDER422_8BIT_CRYCBY之一,具体选择哪一个,要根据sensor datasheet中BT656输出 Y U V分量的顺序决定。

109 因为cam->fmt也是设置 ITU模式的,所以和106行代码是冗余的,不知作者为什么这样写

112 ~ 113 设置source水平和垂直像素数目,source可以是 camera或者FIFO input


[html] view plain copy
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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 权限明细
  3. Android之LinearLayout(线性布局)
  4. Android学习之ProgressDialog
  5. List 去除一些默认设置
  6. Android(安卓)Permission denied 错误(附Android权限大全)
  7. 设置ProgressBar的颜色
  8. Android例子—设置Activity全屏的三种方法
  9. Android(安卓)UI学习 - TableLayout

随机推荐

  1. Android(安卓)Widget 小部件(四---完结)
  2. 安卓屏幕适配
  3. Android(安卓)手写和笔锋研究资料
  4. android 修改系统显示u盘的名称
  5. android canvas drawText 使用说明
  6. android:Handler MessageQueue Looper分析
  7. android http通信——HttpURLConntection
  8. Android两种播放声音的方式
  9. Android(安卓)tab 背景及字体颜色设置
  10. android 更新sdk ip