2019独角兽企业重金招聘Python工程师标准>>>

本文系转载,供自己查阅。非本人作品。
转载自:http://blog.csdn.net/dahailinan/article/details/7780154

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

[html] view plain copy print ?
  1. 100 int fimc_hwset_camera_source(struct fimc_control *ctrl)
  2. 101 {
  3. 102     struct s3c_platform_camera *cam = ctrl->cam;
  4. 103     u32 cfg = 0;
  5. 104
  6. 105     /* for now, we support only ITU601 8 bit mode */
  7. 106     cfg |= S3C_CISRCFMT_ITU601_8BIT;
  8. 107     cfg |= cam->order422;
  9. 108
  10. 109     if (cam->type == CAM_TYPE_ITU)
  11. 110         cfg |= cam->fmt;
  12. 111
  13. 112     cfg |= S3C_CISRCFMT_SOURCEHSIZE(cam->width);
  14. 113     cfg |= S3C_CISRCFMT_SOURCEVSIZE(cam->height);
  15. 114
  16. 115     writel(cfg, ctrl->regs + S3C_CISRCFMT);
  17. 116
  18. 117     return 0;
  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. 159 int fimc_hwset_output_area_size(struct fimc_control *ctrl, u32 size)
  2. 160 {
  3. 161     u32 cfg = 0;
  4. 162
  5. 163     cfg = S3C_CITAREA_TARGET_AREA(size);
  6. 164
  7. 165     writel(cfg, ctrl->regs + S3C_CITAREA);
  8. 166
  9. 167     return 0;
  10. 168 }

CITAREA: output DMA target area register

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

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

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

S3C_CISTATUS_IMGCPTEN 标识是否image capture enable的状态

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

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

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

[html] view plain copy print ?
  1. 267 int fimc_hwset_reset(struct fimc_control *ctrl)
  2. 268 {
  3. 269     u32 cfg = 0;
  4. 270
  5. 271     cfg = readl(ctrl->regs + S3C_CISRCFMT);
  6. 272     cfg |= S3C_CISRCFMT_ITU601_8BIT;
  7. 273     writel(cfg, ctrl->regs + S3C_CISRCFMT);
  8. 274
  9. 275     /* s/w reset */
  10. 276     cfg = readl(ctrl->regs + S3C_CIGCTRL);
  11. 277     cfg |= (S3C_CIGCTRL_SWRST);
  12. 278     writel(cfg, ctrl->regs + S3C_CIGCTRL);
  13. 279     mdelay(1);
  14. 280
  15. 281     cfg = readl(ctrl->regs + S3C_CIGCTRL);
  16. 282     cfg &= ~S3C_CIGCTRL_SWRST;
  17. 283     writel(cfg, ctrl->regs + S3C_CIGCTRL);
  18. 284
  19. 285     /* in case of ITU656, CISRCFMT[31] should be 0 */
  20. 286     if ((ctrl->cap != NULL) && (ctrl->cam->fmt == ITU_656_YCBCR422_8BIT)) {
  21. 287         cfg = readl(ctrl->regs + S3C_CISRCFMT);
  22. 288         cfg &= ~S3C_CISRCFMT_ITU601_8BIT;
  23. 289         writel(cfg, ctrl->regs + S3C_CISRCFMT);
  24. 290     }
  25. 291
  26. 292     fimc_reset_cfg(ctrl);
  27. 293
  28. 294     return 0;
  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. 335 int fimc_hwset_camera_offset(struct fimc_control *ctrl)
  2. 336 {
  3. 337     struct s3c_platform_camera *cam = ctrl->cam;
  4. 338     struct v4l2_rect *rect = &cam->window;
  5. 339     u32 cfg, h1, h2, v1, v2;
  6. 340
  7. 341     if (!cam) {
  8. 342         fimc_err("%s: no active camera\n", __func__);
  9. 343         return -ENODEV;
  10. 344     }
  11. 345
  12. 346     h1 = rect->left;
  13. 347     h2 = cam->width - rect->width - rect->left;
  14. 348     v1 = rect->top;
  15. 349     v2 = cam->height - rect->height - rect->top;
  16. 350
  17. 351     cfg = readl(ctrl->regs + S3C_CIWDOFST);
  18. 352     cfg &= ~(S3C_CIWDOFST_WINHOROFST_MASK | S3C_CIWDOFST_WINVEROFST_MASK);
  19. 353     cfg |= S3C_CIWDOFST_WINHOROFST(h1);
  20. 354     cfg |= S3C_CIWDOFST_WINVEROFST(v1);
  21. 355     cfg |= S3C_CIWDOFST_WINOFSEN;
  22. 356     writel(cfg, ctrl->regs + S3C_CIWDOFST);
  23. 357
  24. 358     cfg = 0;
  25. 359     cfg |= S3C_CIWDOFST2_WINHOROFST2(h2);
  26. 360     cfg |= S3C_CIWDOFST2_WINVEROFST2(v2);
  27. 361     writel(cfg, ctrl->regs + S3C_CIWDOFST2);
  28. 362
  29. 363     return 0;
  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. 366 int fimc_hwset_camera_polarity(struct fimc_control *ctrl)
  2. 367 {
  3. 368     struct s3c_platform_camera *cam = ctrl->cam;
  4. 369     u32 cfg;
  5. 370
  6. 371     if (!cam) {
  7. 372         fimc_err("%s: no active camera\n", __func__);
  8. 373         return -ENODEV;
  9. 374     }
  10. 375
  11. 376     cfg = readl(ctrl->regs + S3C_CIGCTRL);
  12. 377
  13. 378     cfg &= ~(S3C_CIGCTRL_INVPOLPCLK | S3C_CIGCTRL_INVPOLVSYNC |
  14. 379          S3C_CIGCTRL_INVPOLHREF | S3C_CIGCTRL_INVPOLHSYNC);
  15. 380
  16. 381     if (cam->inv_pclk)
  17. 382         cfg |= S3C_CIGCTRL_INVPOLPCLK;
  18. 383
  19. 384     if (cam->inv_vsync)
  20. 385         cfg |= S3C_CIGCTRL_INVPOLVSYNC;
  21. 386
  22. 387     if (cam->inv_href)
  23. 388         cfg |= S3C_CIGCTRL_INVPOLHREF;
  24. 389
  25. 390     if (cam->inv_hsync)
  26. 391         cfg |= S3C_CIGCTRL_INVPOLHSYNC;
  27. 392
  28. 393     writel(cfg, ctrl->regs + S3C_CIGCTRL);
  29. 394
  30. 395     return 0;
  31. 396 }

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

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

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

[html] view plain copy print ?
  1. 434 int fimc43_hwset_camera_type(struct fimc_control *ctrl)
  2. 435 {
  3. 436     struct s3c_platform_camera *cam = ctrl->cam;
  4. 437     u32 cfg;
  5. 438
  6. 439     if (!cam) {
  7. 440         fimc_err("%s: no active camera\n", __func__);
  8. 441         return -ENODEV;
  9. 442     }
  10. 443
  11. 444     cfg = readl(ctrl->regs + S3C_CIGCTRL);
  12. 445     cfg &= ~(S3C_CIGCTRL_TESTPATTERN_MASK | S3C_CIGCTRL_SELCAM_ITU_MASK |
  13. 446         S3C_CIGCTRL_SELCAM_MIPI_MASK | S3C_CIGCTRL_SELCAM_FIMC_MASK |
  14. 447         S3C_CIGCTRL_SELWB_CAMIF_MASK);
  15. 448
  16. 449     /* Interface selection */
  17. 450     if (cam->id == CAMERA_WB) {
  18. 451         cfg |= S3C_CIGCTRL_SELWB_CAMIF_WRITEBACK;
  19. 452     } else if (cam->type == CAM_TYPE_MIPI) {
  20. 453         cfg |= S3C_CIGCTRL_SELCAM_FIMC_MIPI;
  21. 454
  22. 455         /* C110/V210 Support only MIPI A support */
  23. 456         cfg |= S3C_CIGCTRL_SELCAM_MIPI_A;
  24. 457
  25. 458         /* FIXME: Temporary MIPI CSIS Data 32 bit aligned */
  26. 459         if (ctrl->cap->fmt.pixelformat == V4L2_PIX_FMT_JPEG)
  27. 460             writel((MIPI_USER_DEF_PACKET_1 | (0x1 << 8)),
  28. 461                     ctrl->regs + S3C_CSIIMGFMT);
  29. 462         else
  30. 463             writel(cam->fmt | (0x1 << 8),
  31. 464                     ctrl->regs + S3C_CSIIMGFMT);
  32. 465     } else if (cam->type == CAM_TYPE_ITU) {
  33. 466         if (cam->id == CAMERA_PAR_A)
  34. 467             cfg |= S3C_CIGCTRL_SELCAM_ITU_A;
  35. 468         else
  36. 469             cfg |= S3C_CIGCTRL_SELCAM_ITU_B;
  37. 470         /* switch to ITU interface */
  38. 471         cfg |= S3C_CIGCTRL_SELCAM_FIMC_ITU;
  39. 472     } else {
  40. 473         fimc_err("%s: invalid camera bus type selected\n", __func__);
  41. 474         return -EINVAL;
  42. 475     }
  43. 476
  44. 477     writel(cfg, ctrl->regs + S3C_CIGCTRL);
  45. 478
  46. 479     return 0;
  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. 522 int fimc_hwset_jpeg_mode(struct fimc_control *ctrl, bool enable)
  2. 523 {
  3. 524     u32 cfg;
  4. 525     cfg = readl(ctrl->regs + S3C_CIGCTRL);
  5. 526
  6. 527     if (enable)
  7. 528         cfg |= S3C_CIGCTRL_CAM_JPEG;
  8. 529     else
  9. 530         cfg &= ~S3C_CIGCTRL_CAM_JPEG;
  10. 531
  11. 532     writel(cfg, ctrl->regs + S3C_CIGCTRL);
  12. 533
  13. 534     return 0;
  14. 535 }

对于ITU601输入如果输入数据是8bit jpeg格式(压缩格式),那么就要设置JPEG标志位,这时FIMC会忽略scaler和转换。

对于BT656来说只能是YUYV格式

[html] view plain copy print ?
  1. 537 int fimc_hwset_output_size(struct fimc_control *ctrl, int width, int height)
  2. 538 {
  3. 539     u32 cfg = readl(ctrl->regs + S3C_CITRGFMT);
  4. 540
  5. 541     printk(KERN_ERR "%s: width(%d), height(%d)\n", __func__, width, height);
  6. 542
  7. 543     cfg &= ~(S3C_CITRGFMT_TARGETH_MASK | S3C_CITRGFMT_TARGETV_MASK);
  8. 544
  9. 545     cfg |= S3C_CITRGFMT_TARGETHSIZE(width);
  10. 546     cfg |= S3C_CITRGFMT_TARGETVSIZE(height);
  11. 547
  12. 548     writel(cfg, ctrl->regs + S3C_CITRGFMT);
  13. 549
  14. 550     return 0;
  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. 553 int fimc_hwset_output_colorspace(struct fimc_control *ctrl, u32 pixelformat)
  2. 554 {
  3. 555     struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
  4. 556     u32 cfg;
  5. 557
  6. 558     if (pdata->hw_ver != 0x40) {
  7. 559         if (pixelformat == V4L2_PIX_FMT_YUV444) {
  8. 560             cfg = readl(ctrl->regs + S3C_CIEXTEN);
  9. 561             cfg |= S3C_CIEXTEN_YUV444_OUT;
  10. 562             writel(cfg, ctrl->regs + S3C_CIEXTEN);
  11. 563
  12. 564             return 0;
  13. 565         } else {
  14. 566             cfg = readl(ctrl->regs + S3C_CIEXTEN);
  15. 567             cfg &= ~S3C_CIEXTEN_YUV444_OUT;
  16. 568             writel(cfg, ctrl->regs + S3C_CIEXTEN);
  17. 569         }
  18. 570     }
  19. 571
  20. 572     cfg = readl(ctrl->regs + S3C_CITRGFMT);
  21. 573     cfg &= ~S3C_CITRGFMT_OUTFORMAT_MASK;
  22. 574
  23. 575     switch (pixelformat) {
  24. 576     case V4L2_PIX_FMT_JPEG:
  25. 577         break;
  26. 578     case V4L2_PIX_FMT_RGB565: /* fall through */
  27. 579     case V4L2_PIX_FMT_RGB32:
  28. 580         cfg |= S3C_CITRGFMT_OUTFORMAT_RGB;
  29. 581         break;
  30. 582
  31. 583     case V4L2_PIX_FMT_YUYV:     /* fall through */
  32. 584     case V4L2_PIX_FMT_UYVY:     /* fall through */
  33. 585     case V4L2_PIX_FMT_VYUY:     /* fall through */
  34. 586     case V4L2_PIX_FMT_YVYU:
  35. 587         cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
  36. 588         break;
  37. 589
  38. 590     case V4L2_PIX_FMT_NV16:     /* fall through */
  39. 591     case V4L2_PIX_FMT_NV61:     /* fall through */
  40. 592     case V4L2_PIX_FMT_YUV422P:
  41. 593         cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422;
  42. 594         break;
  43. 595
  44. 596     case V4L2_PIX_FMT_YUV420:   /* fall through */
  45. 597     case V4L2_PIX_FMT_NV12:     /* fall through */
  46. 598     case V4L2_PIX_FMT_NV12T:    /* fall through */
  47. 599     case V4L2_PIX_FMT_NV21:
  48. 600         cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR420;
  49. 601         break;
  50. 602
  51. 603     default:
  52. 604         fimc_err("%s: invalid pixel format\n", __func__);
  53. 605         break;
  54. 606     }
  55. 607
  56. 608     writel(cfg, ctrl->regs + S3C_CITRGFMT);
  57. 609
  58. 610     return 0;
  59. 611 }

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

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

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

[html] view plain copy print ?
  1. 690 int fimc_hwset_output_address(struct fimc_control *ctrl,
  2. 691                   struct fimc_buf_set *bs, int id)
  3. 692 {
  4. 693     printk(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. 695             bs->base[FIMC_ADDR_CR]);
  7. 696     writel(bs->base[FIMC_ADDR_Y], ctrl->regs + S3C_CIOYSA(id));
  8. 697     writel(bs->base[FIMC_ADDR_CB], ctrl->regs + S3C_CIOCBSA(id));
  9. 698     writel(bs->base[FIMC_ADDR_CR], ctrl->regs + S3C_CIOCRSA(id));
  10. 699
  11. 700     return 0;
  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. 703 int fimc_hwset_output_yuv(struct fimc_control *ctrl, u32 pixelformat)
  2. 704 {
  3. 705     u32 cfg;
  4. 706
  5. 707     cfg = readl(ctrl->regs + S3C_CIOCTRL);
  6. 708     cfg &= ~(S3C_CIOCTRL_ORDER2P_MASK | S3C_CIOCTRL_ORDER422_MASK |
  7. 709         S3C_CIOCTRL_YCBCR_PLANE_MASK);
  8. 710
  9. 711     switch (pixelformat) {
  10. 712     /* 1 plane formats */
  11. 713     case V4L2_PIX_FMT_YUYV:
  12. 714         cfg |= S3C_CIOCTRL_ORDER422_YCBYCR;
  13. 715         break;
  14. 716
  15. 717     case V4L2_PIX_FMT_UYVY:
  16. 718         cfg |= S3C_CIOCTRL_ORDER422_CBYCRY;
  17. 719         break;
  18. 720
  19. 721     case V4L2_PIX_FMT_VYUY:
  20. 722         cfg |= S3C_CIOCTRL_ORDER422_CRYCBY;
  21. 723         break;
  22. 724
  23. 725     case V4L2_PIX_FMT_YVYU:
  24. 726         cfg |= S3C_CIOCTRL_ORDER422_YCRYCB;
  25. 727         break;
  26. 728
  27. 729     /* 2 plane formats */
  28. 730     case V4L2_PIX_FMT_NV12:     /* fall through */
  29. 731     case V4L2_PIX_FMT_NV12T:    /* fall through */
  30. 732     case V4L2_PIX_FMT_NV16:
  31. 733         cfg |= S3C_CIOCTRL_ORDER2P_LSB_CBCR;
  32. 734         cfg |= S3C_CIOCTRL_YCBCR_2PLANE;
  33. 735         break;
  34. 736
  35. 737     case V4L2_PIX_FMT_NV21:     /* fall through */
  36. 738     case V4L2_PIX_FMT_NV61:
  37. 739         cfg |= S3C_CIOCTRL_ORDER2P_LSB_CRCB;
  38. 740         cfg |= S3C_CIOCTRL_YCBCR_2PLANE;
  39. 741         break;
  40. 742
  41. 743     /* 3 plane formats */
  42. 744     case V4L2_PIX_FMT_YUV422P:  /* fall through */
  43. 745     case V4L2_PIX_FMT_YUV420:
  44. 746         cfg |= S3C_CIOCTRL_YCBCR_3PLANE;
  45. 747         break;
  46. 748     }
  47. 749
  48. 750     writel(cfg, ctrl->regs + S3C_CIOCTRL);
  49. 751
  50. 752     return 0;
  51. 753 }

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

[html] view plain copy print ?
  1. 755 int fimc_hwset_output_scan(struct fimc_control *ctrl,
  2. 756                struct v4l2_pix_format *fmt)
  3. 757 {
  4. 758     struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
  5. 759     u32 cfg;
  6. 760
  7. 761     /* nothing to do: FIMC40 not supported interlaced and weave output */
  8. 762     if (pdata->hw_ver == 0x40)
  9. 763         return 0;
  10. 764
  11. 765     cfg = readl(ctrl->regs + S3C_CISCCTRL);
  12. 766     cfg &= ~S3C_CISCCTRL_SCAN_MASK;
  13. 767
  14. 768     if (fmt->field == V4L2_FIELD_INTERLACED ||
  15. 769         fmt->field == V4L2_FIELD_INTERLACED_TB) {
  16. 770         cfg |= S3C_CISCCTRL_INTERLACE;
  17. 771         printk(KERN_ERR "%s: set S3C_CISCCTRL_INTERLACE\n", __func__);
  18. 772     }
  19. 773     else
  20. 774         cfg |= S3C_CISCCTRL_PROGRESSIVE;
  21. 775
  22. 776     writel(cfg, ctrl->regs + S3C_CISCCTRL);
  23. 777
  24. 778     cfg = readl(ctrl->regs + S3C_CIOCTRL);
  25. 779     cfg &= ~S3C_CIOCTRL_WEAVE_MASK;
  26. 780
  27. 781     if ((ctrl->cap) && (fmt->field == V4L2_FIELD_INTERLACED_TB))
  28. 782         cfg |= S3C_CIOCTRL_WEAVE_OUT;
  29. 783
  30. 784     writel(cfg, ctrl->regs + S3C_CIOCTRL);
  31. 785
  32. 786     return 0;
  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. 789 int fimc_hwset_input_rot(struct fimc_control *ctrl, u32 rot, u32 flip)
  2. 790 {
  3. 791     u32 cfg, val;
  4. 792
  5. 793     cfg = readl(ctrl->regs + S3C_CITRGFMT);
  6. 794     cfg &= ~S3C_CITRGFMT_INROT90_CLOCKWISE;
  7. 795
  8. 796     val = fimc_mapping_rot_flip(rot, flip);
  9. 797
  10. 798     if (val & FIMC_ROT)
  11. 799         cfg |= S3C_CITRGFMT_INROT90_CLOCKWISE;
  12. 800
  13. 801     writel(cfg, ctrl->regs + S3C_CITRGFMT);
  14. 802
  15. 803     return 0;
  16. 804 }

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

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

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

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

[html] view plain copy print ?
  1. 1085 int fimc_hwset_output_rgb(struct fimc_control *ctrl, u32 pixelformat)
  2. 1086 {
  3. 1087     u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
  4. 1088     cfg &= ~S3C_CISCCTRL_OUTRGB_FMT_RGB_MASK;
  5. 1089
  6. 1090     if (pixelformat == V4L2_PIX_FMT_RGB32)
  7. 1091         cfg |= S3C_CISCCTRL_OUTRGB_FMT_RGB888;
  8. 1092     else if (pixelformat == V4L2_PIX_FMT_RGB565)
  9. 1093         cfg |= S3C_CISCCTRL_OUTRGB_FMT_RGB565;
  10. 1094
  11. 1095     writel(cfg, ctrl->regs + S3C_CISCCTRL);
  12. 1096
  13. 1097     return 0;
  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. 1100 int fimc_hwset_ext_rgb(struct fimc_control *ctrl, int enable)
  2. 1101 {
  3. 1102     u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
  4. 1103     cfg &= ~S3C_CISCCTRL_EXTRGB_EXTENSION;
  5. 1104
  6. 1105     if (enable)
  7. 1106         cfg |= S3C_CISCCTRL_EXTRGB_EXTENSION;
  8. 1107
  9. 1108     writel(cfg, ctrl->regs + S3C_CISCCTRL);
  10. 1109
  11. 1110     return 0;
  12. 1111 }

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

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

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

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

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

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

再看代码就简单了

转载于:https://my.oschina.net/u/1425390/blog/186450

【转载】Android S5PV210 fimc驱动分析 - fimc_regs.c相关推荐

  1. 【SemiDrive源码分析】【MailBox核间通信】46 - Android侧 RPMSG_IPCC_RPC驱动分析(下) 之 RPMSG_IPCC_RPC驱动初始化、数据收发流程分析

    [SemiDrive源码分析][MailBox核间通信]46 - Android侧 RPMSG_IPCC_RPC驱动分析(下) 之 RPMSG_IPCC_RPC驱动初始化.数据收发流程分析 三. rp ...

  2. 【SemiDrive源码分析】【MailBox核间通信】45 - Android侧 RPMSG_IPCC_RPC驱动分析(上) 之 RPMSG设备 与 RPMSG驱动 匹配过程分析

    [SemiDrive源码分析][MailBox核间通信]45 - Android侧 RPMSG_IPCC_RPC驱动分析(上) 之 RPMSG设备 与 RPMSG驱动 匹配过程分析 一. IPCC_R ...

  3. Android S5PV210 camera驱动(tw9912)小结

    之前没接触过三星的开发板,更不了解S5PV210,TW9912这款AD芯片也是第一次接触,三星FAE又不给力(其实是没有),调试camera过程中,一会怀疑TW9912配置不对,一会怀疑三星FIMC驱 ...

  4. S5PV210 camera 驱动分析(android)

    一.Camera 工作原理介绍 1. 结构 . 一般来说,camera 主要是由 lens 和 sensor IC 两部分组成,其中有的 sensor IC 集成 了 DSP,有的没有集成,但也需要外 ...

  5. (转载)Linux usbtouchscreen驱动分析

    在Linux内核中自带USB触摸屏驱动,以linux-2.6.33.3\drivers\input\touchscreen.c为例,进行解析: 1.驱动加载: static int __init us ...

  6. 高通 android平台LCD驱动分析

    目前手机芯片厂家提供的源码里包含整个LCD驱动框架,一般厂家会定义一个xxx_fb.c的源文件,注册一个平台设备和平台驱动,在驱动的probe函数中来调用register_framebuffer(), ...

  7. android 3d城市源码,[转载]android Gallery3D源码分析

    一.布局 gallery3d的界面生成和普通的应用程序不一样.普通程序一般一个界面就是一个activity,布局用xml或代码都可以实现,界面切换是activity的切换方式:而gallery3d没有 ...

  8. android 副屏驱动_高通 android平台LCD驱动分析

    目前手机芯片厂家提供的源码里包含整个LCD驱动框架,一般厂家会定义一个xxx_fb.c的源文件,注册一个平台设备和平台驱动,在驱动的probe函数中来调用register_framebuffer(), ...

  9. S5PV210 ADC驱动分析

    我这里用的是mini210开发板,在其内核源码中,采用了Linux设备驱动模型中的platform虚拟总线来管理ADC设备.首先看S5PV210提供的ADC驱动接口.在plat-samsung/dev ...

  10. android电池(五):电池 充电IC(PM2301)驱动分析篇

    android电池(五):电池 充电IC(PM2301)驱动分析篇 关键词:android 电池  电量计  PL2301任务初始化宏 power_supply 中断线程化 平台信息: 内核:linu ...

最新文章

  1. 阿里云accessKey如何创建?~ 2015.08.25
  2. openstack简易汉化
  3. MetaSploit攻击实例讲解------攻击445端口漏洞(kali linux 2016.2(rolling))(详细)
  4. CSS 七层叠层顺序(stacking level)
  5. python学习笔记(一)基本数据类型
  6. 2020年母婴消费洞察报告
  7. 序号47指标横向展示.xlsx_电力监控系统安全防护规定Akey310参数指标
  8. CSS揭秘(四)视觉效果
  9. paip.python3 的类使用跟python2 的不同之处
  10. 读书笔记系列2:《More Effective C++》
  11. 地图比例尺与空间分辨率之间的关系_分辨率与比例尺
  12. 测试覆盖:语句覆盖 判定覆盖(即分支覆盖) 条件覆盖 判定-条件覆盖 条件组合覆盖 路径覆盖
  13. 使用SHC命令工具加密Shell脚本
  14. Anaconda||install报错:CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://mirrors.tuna.tsinghu
  15. python_视频中语音识别转出文本
  16. file html5 样式,CSS小技巧之自定义个性的file表单样式
  17. 【源码好又多】springboot后台框架
  18. 遥感监测草原产草量的方法
  19. python做游戏辅助用到的库
  20. java在天猫获取图片_怎么获取天猫商品主图图片?

热门文章

  1. 关于apache httpd.conf脚本的理解
  2. 笔者带你剖析轻量级Sharding中间件——Kratos1.x
  3. EL表达式结合页面JSTL使用 迭代显示表格
  4. 80X86 汇编指令符号大全
  5. 系统架构师学习笔记_第十一章(下)_连载
  6. MySql Odbc等驱动下载地址分享下
  7. python中filter、map、reduce的区别
  8. 错误 C2280 Union : 尝试引用已删除的函数 以及 警告 C4624 “Grade”: 已将析构函数隐式定义为“已删除”的一种解决方法...
  9. 使用Struts2和jQuery EasyUI实现简单CRUD系统(五)——jsp,json,EasyUI的结合
  10. ArcEngine中打开各种数据源(WorkSpace)的连接(转)