NXP

4.0 ipu_soc,ipu_channel_t ,ipu_channel_params_t结构体

2019-07-12 13:27发布

1.ipu_soc结构体: struct ipu_soc { unsigned int id; //ipu的ID号 unsigned int devtype; //ipu的一些信息,包含cm,ic等模块的地址偏移值 bool online; //表示这个ipu是否正在使用中 /*clk*/ struct clk *ipu_clk; struct clk *di_clk[2]; struct clk *di_clk_sel[2]; struct clk *pixel_clk[2]; bool pixel_clk_en[2]; struct clk *pixel_clk_sel[2]; struct clk *csi_clk[2]; struct clk *prg_clk; /*irq*/ int irq_sync; int irq_err; struct ipu_irq_node irq_list[IPU_IRQ_COUNT]; //在request_irq函数中会根据传入的irq号在这个数组中选择对应的下标,来存取有关这个irq的 //信息如irq服务函数,名字,flags等参数。 /*reg*/ /* ipu内部模块经过ioremap后的地址 */ void __iomem *cm_reg; void __iomem *idmac_reg; void __iomem *dp_reg; void __iomem *ic_reg; void __iomem *dc_reg; void __iomem *dc_tmpl_reg; void __iomem *dmfc_reg; void __iomem *di_reg[2]; void __iomem *smfc_reg; void __iomem *csi_reg[2]; void __iomem *cpmem_base; void __iomem *tpmem_base; void __iomem *vdi_reg; struct device *dev; ipu_channel_t csi_channel[2]; //每个ipu有两个csi设备,将此时csi设备对应的channel根据csi号保存在这个csi_channel[]数组中 ipu_channel_t using_ic_dirct_ch; //表示那个channel直接使用IC设备 unsigned char dc_di_assignment[10]; bool sec_chan_en[24]; //对应的channel是否使能了second channel bool thrd_chan_en[24]; //对应的channel是否使能了third channel bool chan_is_interlaced[52]; //对应的channel中的数据是否是隔行的,每个channel对应其中的一位,每一位是一个bool类型的值 uint32_t channel_init_mask; //这是一个32位的数,其中每一位代表一个channel号,如果初始化一个channel的话,就将这个channel对应的位置1 uint32_t channel_enable_mask; //每一位对应一个channel号,如果使能了一个channel 的话,就将这个channel对应的位置1,与上面那个channel_init_mask类似。 /*use count*/ /* 下面几个是IPU内部模块的引用计数 */ int dc_use_count; //dc引用计数 int dp_use_count; //dp引用计数 int dmfc_use_count; //dmfc引用计数 int smfc_use_count; //smfc引用计数 int ic_use_count; //ic引用计数 int rot_use_count; //rot引用计数 int vdi_use_count; //vdi引用计数 int di_use_count[2]; //di引用计数,每个ipu只有两个di int csi_use_count[2]; //csi引用计数,每个ipu只有两个csi struct mutex mutex_lock; spinlock_t int_reg_spin_lock; spinlock_t rdy_reg_spin_lock; int dmfc_size_28; int dmfc_size_29; int dmfc_size_24; int dmfc_size_27; int dmfc_size_23; enum csc_type_t fg_csc_type; enum csc_type_t bg_csc_type; bool color_key_4rgb; bool dc_swap; struct completion dc_comp; struct completion csi_comp; struct rot_mem { void *vaddr; dma_addr_t paddr; int size; } rot_dma[2]; int vdoa_en; //是否使能VDOA struct task_struct *thread[2]; //两个内核线程 /* * Bypass reset to avoid display channel being * stopped by probe since it may starts to work * in bootloader. */ bool bypass_reset; /* 这个值是从dts文件中获得的bypass_reset,因为在开发板启动过程中,需要使能屏幕来显示,所以显示通道可能已经在bootloader中开启了, * 在这里设置这个值,使得显示通道在probe函数中不会关闭,也就是这个参数的含义(旁路)。*/ /* AXI protocol id */ unsigned int ch0123_axi; unsigned int ch23_axi; unsigned int ch27_axi; unsigned int ch28_axi; unsigned int normal_axi; /* 不同的channel可能会对应不同的 AXI protocol,在ipu_probe函数中对这些值进行了赋值,在ipu_platform_type结构体中指定的。 */ bool smfc_idmac_12bit_3planar_bs_fixup; /* workaround little stripes */ };

2.ipu_channel_t枚举: typedef enum { CHAN_NONE = -1, MEM_ROT_ENC_MEM = _MAKE_CHAN(1, 45, NO_DMA, NO_DMA, 48), MEM_ROT_VF_MEM = _MAKE_CHAN(2, 46, NO_DMA, NO_DMA, 49), MEM_ROT_PP_MEM = _MAKE_CHAN(3, 47, NO_DMA, NO_DMA, 50), MEM_PRP_ENC_MEM = _MAKE_CHAN(4, 12, 14, 17, 20), MEM_PRP_VF_MEM = _MAKE_CHAN(5, 12, 14, 17, 21), MEM_PP_MEM = _MAKE_CHAN(6, 11, 15, 18, 22), MEM_DC_SYNC = _MAKE_CHAN(7, 28, NO_DMA, NO_DMA, NO_DMA), MEM_DC_ASYNC = _MAKE_CHAN(8, 41, NO_DMA, NO_DMA, NO_DMA), MEM_BG_SYNC = _MAKE_CHAN(9, 23, NO_DMA, 51, NO_DMA), MEM_FG_SYNC = _MAKE_CHAN(10, 27, NO_DMA, 31, NO_DMA), MEM_BG_ASYNC0 = _MAKE_CHAN(11, 24, NO_DMA, 52, NO_DMA), MEM_FG_ASYNC0 = _MAKE_CHAN(12, 29, NO_DMA, 33, NO_DMA), MEM_BG_ASYNC1 = _MAKE_ALT_CHAN(MEM_BG_ASYNC0), MEM_FG_ASYNC1 = _MAKE_ALT_CHAN(MEM_FG_ASYNC0), DIRECT_ASYNC0 = _MAKE_CHAN(13, NO_DMA, NO_DMA, NO_DMA, NO_DMA), DIRECT_ASYNC1 = _MAKE_CHAN(14, NO_DMA, NO_DMA, NO_DMA, NO_DMA), CSI_MEM0 = _MAKE_CHAN(15, NO_DMA, NO_DMA, NO_DMA, 0), CSI_MEM1 = _MAKE_CHAN(16, NO_DMA, NO_DMA, NO_DMA, 1), CSI_MEM2 = _MAKE_CHAN(17, NO_DMA, NO_DMA, NO_DMA, 2), CSI_MEM3 = _MAKE_CHAN(18, NO_DMA, NO_DMA, NO_DMA, 3), CSI_MEM = CSI_MEM0, CSI_PRP_ENC_MEM = _MAKE_CHAN(19, NO_DMA, NO_DMA, NO_DMA, 20), CSI_PRP_VF_MEM = _MAKE_CHAN(20, NO_DMA, NO_DMA, NO_DMA, 21), /* for vdi mem->vdi->ic->mem , add graphics plane and alpha*/ MEM_VDI_PRP_VF_MEM_P = _MAKE_CHAN(21, 8, 14, 17, 21), MEM_VDI_PRP_VF_MEM = _MAKE_CHAN(22, 9, 14, 17, 21), MEM_VDI_PRP_VF_MEM_N = _MAKE_CHAN(23, 10, 14, 17, 21), /* for vdi mem->vdi->mem */ MEM_VDI_MEM_P = _MAKE_CHAN(24, 8, NO_DMA, NO_DMA, 5), MEM_VDI_MEM = _MAKE_CHAN(25, 9, NO_DMA, NO_DMA, 5), MEM_VDI_MEM_N = _MAKE_CHAN(26, 10, NO_DMA, NO_DMA, 5), /* fake channel for vdoa to link with IPU */ MEM_VDOA_MEM = _MAKE_CHAN(27, NO_DMA, NO_DMA, NO_DMA, NO_DMA), MEM_PP_ADC = CHAN_NONE, ADC_SYS2 = CHAN_NONE, } ipu_channel_t; 再来看看这个_MAKE_CHAN宏: #define _MAKE_CHAN(num, v_in, g_in, a_in, out) ((num << 24) | (v_in << 18) | (g_in << 12) | (a_in << 6) | out) #define NO_DMA 0x3F 从这里就可以看出来,ipu_channel_t只是根据5个值左移形成的一个数字。 那么想要从channel中获取它的ID号怎么办?只需要将它右移24位即可,就能得到,就是下面一个宏: #define IPU_CHAN_ID(ch) (ch >> 24) 再来看看channel_2_dma函数: static inline uint32_t channel_2_dma(ipu_channel_t ch, ipu_buffer_t type) { return ((uint32_t) ch >> (6 * type)) & 0x3F; }; 这个函数能够根据不同的type类型从channel里面提取出所使用的dmachannel typedef enum { IPU_OUTPUT_BUFFER = 0, /*!< Buffer for output from IPU */ IPU_ALPHA_IN_BUFFER = 1, /*!< Buffer for input to IPU */ IPU_GRAPH_IN_BUFFER = 2, /*!< Buffer for input to IPU */ IPU_VIDEO_IN_BUFFER = 3, /*!< Buffer for input to IPU */ IPU_INPUT_BUFFER = IPU_VIDEO_IN_BUFFER, IPU_SEC_INPUT_BUFFER = IPU_GRAPH_IN_BUFFER, } ipu_buffer_t; 同时根据_MAKE_CHAN宏中几个变量的名字,就能够理解ipu_channel_t中各个位的含义: 05位:输出dmachannel 611位:alpha通道号 1217位:graph通道号 1823位:video输入dmachannel 24~ :channel的序列号

3. ipu_channel_params_t联合: typedef union { struct { uint32_t csi; //csi设备号,0或1 uint32_t mipi_id; //mipi ID号 uint32_t mipi_vc; //mipi虚拟通道号 bool mipi_en; //是否使能mipi接口 bool interlaced; //数据是否是隔行的 } csi_mem; struct { uint32_t in_width; //输入数据的宽度 uint32_t in_height; //输入数据的高度 uint32_t in_pixel_fmt; //输入数据的像素格式 uint32_t out_width; //输出数据的宽度 uint32_t out_height; //输出数据的高度 uint32_t out_pixel_fmt; //输出数据的像素格式 uint32_t outh_resize_ratio; //输出水平方向上重定义大小系数 uint32_t outv_resize_ratio; //输出垂直方向上重定义大小系数 uint32_t csi; //csi 设备号 uint32_t mipi_id; //mipi ID号 uint32_t mipi_vc; //mipi 虚拟通道号 bool mipi_en; //是否是能mipi接口 } csi_prp_enc_mem; struct { uint32_t in_width; uint32_t in_height; uint32_t in_pixel_fmt; uint32_t out_width; uint32_t out_height; uint32_t out_pixel_fmt; uint32_t outh_resize_ratio; uint32_t outv_resize_ratio; } mem_prp_enc_mem; struct { uint32_t in_width; uint32_t in_height; uint32_t in_pixel_fmt; uint32_t out_width; uint32_t out_height; uint32_t out_pixel_fmt; } mem_rot_enc_mem; struct { uint32_t in_width; uint32_t in_height; uint32_t in_pixel_fmt; uint32_t out_width; uint32_t out_height; uint32_t out_pixel_fmt; uint32_t outh_resize_ratio; uint32_t outv_resize_ratio; bool graphics_combine_en; bool global_alpha_en; bool key_color_en; uint32_t in_g_pixel_fmt; uint8_t alpha; uint32_t key_color; bool alpha_chan_en; ipu_motion_sel motion_sel; enum v4l2_field field_fmt; uint32_t csi; uint32_t mipi_id; uint32_t mipi_vc; bool mipi_en; } csi_prp_vf_mem; struct { uint32_t in_width; uint32_t in_height; uint32_t in_pixel_fmt; uint32_t out_width; uint32_t out_height; uint32_t out_pixel_fmt; bool graphics_combine_en; bool global_alpha_en; bool key_color_en; display_port_t disp; uint32_t out_left; uint32_t out_top; } csi_prp_vf_adc; struct { uint32_t in_width; //输入宽度 uint32_t in_height; //输入高度 uint32_t in_pixel_fmt; //输入像素格式 uint32_t out_width; //输出宽度 uint32_t out_height; //输出高度 uint32_t out_pixel_fmt; //输出像素格式 uint32_t outh_resize_ratio; //输出水平方向上重定义大小的比例 uint32_t outv_resize_ratio; //输出垂直方向上重定义大小的比例 bool graphics_combine_en; //是否使能second channel的标志位 bool global_alpha_en; //是否使能third channel的标志位 bool key_color_en; uint32_t in_g_pixel_fmt; uint8_t alpha; uint32_t key_color; bool alpha_chan_en; ipu_motion_sel motion_sel; enum v4l2_field field_fmt; } mem_prp_vf_mem; struct { uint32_t temp; } mem_prp_vf_adc; struct { uint32_t temp; } mem_rot_vf_mem; struct { uint32_t in_width; uint32_t in_height; uint32_t in_pixel_fmt; uint32_t out_width; uint32_t out_height; uint32_t out_pixel_fmt; uint32_t outh_resize_ratio; uint32_t outv_resize_ratio; bool graphics_combine_en; bool global_alpha_en; bool key_color_en; uint32_t in_g_pixel_fmt; uint8_t alpha; uint32_t key_color; bool alpha_chan_en; } mem_pp_mem; struct { uint32_t temp; } mem_rot_mem; struct { uint32_t in_width; uint32_t in_height; uint32_t in_pixel_fmt; uint32_t out_width; uint32_t out_height; uint32_t out_pixel_fmt; bool graphics_combine_en; bool global_alpha_en; bool key_color_en; display_port_t disp; uint32_t out_left; uint32_t out_top; } mem_pp_adc; struct { uint32_t di; bool interlaced; //数据是否是隔行的 uint32_t in_pixel_fmt; uint32_t out_pixel_fmt; } mem_dc_sync; struct { uint32_t temp; } mem_sdc_fg; struct { uint32_t di; bool interlaced; //数据是否是隔行的 uint32_t in_pixel_fmt; uint32_t out_pixel_fmt; bool alpha_chan_en; } mem_dp_bg_sync; struct { uint32_t temp; } mem_sdc_bg; struct { uint32_t di; bool interlaced; //数据是否是隔行的 uint32_t in_pixel_fmt; uint32_t out_pixel_fmt; bool alpha_chan_en; } mem_dp_fg_sync; struct { uint32_t di; } direct_async; struct { display_port_t disp; mcu_mode_t ch_mode; uint32_t out_left; uint32_t out_top; } adc_sys1; struct { display_port_t disp; mcu_mode_t ch_mode; uint32_t out_left; uint32_t out_top; } adc_sys2; } ipu_channel_params_t;
这个ipu_channel_params_t这个联合,在这个联合中对于每一种channel都有一个对应的结构体类型来保存channel的参数。如果想要获取哪一个channel的信息,就从这个联合中的对应channel里面找即可。同时,在initchannel的时候,也是通过对这个联合里面对应的channel参数赋值。