Common IPU API implementation,主要是为MXC V4L2和ipu device驱动提供IPU channel控制函数
110 static inline int _ipu_is_ic_chan(uint32_t dma_chan)
111 {
112 return ((dma_chan >= 11) && (dma_chan <= 22) && (dma_chan != 17) && (dma_chan != 18));
113 }
126 static inline int _ipu_is_irt_chan(uint32_t dma_chan)
127 {
128 return ((dma_chan >= 45) && (dma_chan <= 50));
129 }
channel 45-47 Bmem->IRT, channel 48-50 IRT->Bmem
136 static inline int _ipu_is_smfc_chan(uint32_t dma_chan)
137 {
138 return ((dma_chan >= 0) && (dma_chan <= 3));
139 }
DMA channel 是一个smfc channel,参看MX51 datasheet 42.4.2.1可知,0, 1, 2, 3通过smfc到达mem
这几个通道从CSI获取capture的数据 不做处理然后存储在mem中。(我现在疑惑的是channel本身有interlaced功能,这个算不算处理)
事实上是可以用这个channel进行de-interlaced的, 当然这种de-interlaced只是简单的de-interlaced方式,对于某些情况下(top bottom field拍摄时间点相差较大)的运动景象,可能不适应,我现在好奇的是VDI怎么解决运动景象de-interlaced问题的
461 int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params)
462 {
463 int ret = 0;
464 uint32_t ipu_conf;
465 uint32_t reg;
466 unsigned long lock_flags;
467
468 dev_dbg(g_ipu_dev, "init channel = %d/n", IPU_CHAN_ID(channel));
469
470 /* re-enable error interrupts every time a channel is initialized */
471 __raw_writel(0xFFFFFFFF, IPU_INT_CTRL(5));
472 __raw_writel(0xFFFFFFFF, IPU_INT_CTRL(6));
473 __raw_writel(0xFFFFFFFF, IPU_INT_CTRL(9));
474 __raw_writel(0xFFFFFFFF, IPU_INT_CTRL(10));
475
476 if (g_ipu_clk_enabled == false) {
477 stop_dvfs_per();
478 g_ipu_clk_enabled = true;
479 clk_enable(g_ipu_clk);
480 }
481
482 spin_lock_irqsave(&ipu_lock, lock_flags);
483
484 if (g_channel_init_mask & (1L << IPU_CHAN_ID(channel))) {
485 dev_err(g_ipu_dev, "Warning: channel already initialized %d/n",
486 IPU_CHAN_ID(channel));
487 }
488
489 ipu_conf = __raw_readl(IPU_CONF);
490
491 switch (channel) {
492 case CSI_MEM0:
493 case CSI_MEM1:
494 case CSI_MEM2:
495 case CSI_MEM3:
496 if (params->csi_mem.csi > 1) {
497 ret = -EINVAL;
498 goto err;
499 }
500
501 if (params->csi_mem.interlaced)
502 g_chan_is_interlaced[channel_2_dma(channel,
503 IPU_OUTPUT_BUFFER)] = true;
504 else
505 g_chan_is_interlaced[channel_2_dma(channel,
506 IPU_OUTPUT_BUFFER)] = false;
507
508 ipu_smfc_use_count++;
509 g_ipu_csi_channel[params->csi_mem.csi] = channel;
510
511 /*SMFC setting*/
512 if (params->csi_mem.mipi_en) {
513 ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
514 params->csi_mem.csi));
515 _ipu_smfc_init(channel, params->csi_mem.mipi_id,
516 params->csi_mem.csi);
517 } else {
518 ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
519 params->csi_mem.csi));
520 _ipu_smfc_init(channel, 0, params->csi_mem.csi);
521 }
522
523 /*CSI data (include compander) dest*/
524 _ipu_csi_init(channel, params->csi_mem.csi);
525 break;
501 caller应该根据sensor传入的数据格式设置csi_mem, 如果数据是隔行的,那么设置一个g_chan_is_interlaced,这个标志会在完为为这个channel调用 _ipu_ch_param_set_interlaced_scan.
524 调用_ipu_csi_init来设置CSI数据的流向,在当前的场景下, CSI数据通过SMFC流向IMDAC
526 case CSI_PRP_ENC_MEM:
527 if (params->csi_prp_enc_mem.csi > 1) {
528 ret = -EINVAL;
529 goto err;
530 }
531 if (using_ic_dirct_ch == MEM_VDI_PRP_VF_MEM) {
532 ret = -EINVAL;
533 goto err;
534 }
535 using_ic_dirct_ch = CSI_PRP_ENC_MEM;
536
537 ipu_ic_use_count++;
538 g_ipu_csi_channel[params->csi_prp_enc_mem.csi] = channel;
539
540 /*Without SMFC, CSI only support parallel data source*/
541 ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
542 params->csi_prp_enc_mem.csi));
543
544 /*CSI0/1 feed into IC*/
545 ipu_conf &= ~IPU_CONF_IC_INPUT;
546 if (params->csi_prp_enc_mem.csi)
547 ipu_conf |= IPU_CONF_CSI_SEL;
548 else
549 ipu_conf &= ~IPU_CONF_CSI_SEL;
550
551 /*PRP skip buffer in memory, only valid when RWS_EN is true*/
552 reg = __raw_readl(IPU_FS_PROC_FLOW1);
553 __raw_writel(reg & ~FS_ENC_IN_VALID, IPU_FS_PROC_FLOW1);
554
555 /*CSI data (include compander) dest*/
556 _ipu_csi_init(channel, params->csi_prp_enc_mem.csi);
557 _ipu_ic_init_prpenc(params, true);
558 break;
540~542 设置数据源为parallel
544~549 设置IPU_CONF的CSI select bit, this bit select manually between 2 CSIs, 仅当IC_INPUT bit 清除时有效
行553 暂时不知道干嘛的
行556 设置CSI sensor的数据流向
行557 设置resize寄存器IC_CONF_ENC_RSC, 设置CSC(color space convert) 寄存器, 设置...