4.0 ipu_soc,ipu_channel_t ,ipu_channel_params_t结构体详解

来源:互联网 发布:康佳电视软件下载 编辑:程序博客网 时间:2024/06/05 19:31

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 channelbool thrd_chan_en[24]; //对应的channel是否使能了third channelbool chan_is_interlaced[52];  //对应的channel中的数据是否是隔行的,每个channel对应其中的一位,每一位是一个bool类型的值uint32_t channel_init_mask;   //这是一个32位的数,其中每一位代表一个channel号,如果初始化一个channel的话,就将这个channel对应的位置1uint32_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只有两个diint 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]; intvdoa_en;  //是否使能VDOAstruct 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或1uint32_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参数赋值。


0 0
原创粉丝点击