NXP

对ipu_init_channel的理解

2019-07-12 13:48发布

ipu_init_channel的理解 2016-05-2617:11:40 (一) 对于每个channel,它的信息都保存在ipu_channel_params_t结构体联合中,在ipu_init_channel函数中,会根据传入的这个ipu_channel_params_t结构体联合channel所对应的参数来初始化channel
对于每一个channel,首先要理解这个channelipu中所使用到的模块及数据的流通方向。然后使用到哪一个模块的话,需要增加这个模块的引用计数。之后就是设置ipu_conf寄存器,这个寄存器是这里的关键。 设置完寄存器以后,就需要设置channel所使用到的ipu内部的模块,因为想使用哪一个模块的话,肯定需要先初始化以后才能使用。

(二) 比如对于CSI_MEMxchannel来说,首先需要知道这个channel所对应的channel参数在哪里? 就是ipu_channel_params_t联合中的csi_mem结构体,如下所示: struct{ uint32_tcsi; //csi设备id uint32_tmipi_id; uint32_tmipi_vc; boolmipi_en; //是否是mipi设备 boolinterlaced; //数据是否隔行 }csi_mem;
1)首先根据csi_mem.interlaced来选择将ipu->chan_is_interlaced[]数组中置位true还是false
2)然后这个channelipu内部的流程是通过csi--->smfc--->mem,它使用到了smfc模块,将smfc的引用计数增加1,同时,对于csi设备来说,在ipu_soc结构体中有一个csi_channel[2]的数组,将对应csi_mem结构体中csi设备号的那一项的channel填充进去,如下: ipu->csi_channel[params->csi_mem.csi]= channel;
3)之后,就是根据params->csi_mem.mipi_en来选择是否使用mipi,我们先假设不使用。 那么就需要设置ipu_conf寄存器的28或者29位,这一位表示csi设备的数据是普通的数据还是mipi数据。 然后就需要设置smfc模块,通过使用_ipu_smfc_init函数。_ipu_smfc_init(ipu,channel, 0,params->csi_mem.csi);来填充SMFC_MAP寄存器来设置将从csi中获取到的数据mapIDMACchannel中。
4)指定csi设备的数据流向,通过_ipu_csi_init函数。这个函数中数据的目的地址只有IDMACIC两项。通过操作CSI_SENS_CONF寄存器来设置目的地址。

(三) 对于CSI_PRP_ENC_MEMchannel 这个channel所对应的channel参数在ipu_channel_params_t联合中的csi_prp_enc_mem结构体 struct{ uint32_tin_width; //输入数据的宽度 uint32_tin_height; //输入数据的高度 uint32_tin_pixel_fmt; //输入数据的像素格式 uint32_tout_width; //输出数据的宽度 uint32_tout_height; //输出数据的高度 uint32_tout_pixel_fmt; //输出数据的像素格式 uint32_touth_resize_ratio; //输出水平方向上缩放比例系数 uint32_toutv_resize_ratio; //输出垂直方向上缩放比例系数 uint32_tcsi; //csi设备号0或者1 uint32_tmipi_id; uint32_tmipi_vc; boolmipi_en; //是否使能mipi }csi_prp_enc_mem;
1)首先设置ipu->using_ic_dirct_ch,这个参数再理解一下
2)这个channelipu内部的流程是:csi--->ic--->mem,它使用到了ic模块,所以将ic的引用计数加1,同样使用了csi设备,就需要填充ipu_soc结构体中的ipu->csi_channel[]数组,将对应的csi设备所使用的channel填进去。
3)与上一个channel中类似,如果channel使用到csi设备的话,就需要设置ipu_conf中的28或者29位,用以确定csi设备中的数据类型是普通的还是mipi类型的。
4)之后对于这个channel,还需要设置ipu_conf寄存器的31位,这一位表示输入IC模块的数据来源是哪一个csi设备,为0表示来源于csi0,1表示来源于csi1.
5)然后就是通过_ipu_csi_init函数来指定数据的目的地址是IDMAC
6)对比上一个channel,上一个channel使用了smfc,就需要设置smfc。而这一个设备使用了IC,所以肯定需要设置IC模块。通过_ipu_ic_init_prpenc函数来初始化IC为预处理数据。

(四) 对于CSI_PRP_VF_MEMchannel 这个channel所对应的channel参数在ipu_channel_params_t联合中的csi_prp_vf_mem结构体 struct{ uint32_tin_width; uint32_tin_height; uint32_tin_pixel_fmt; uint32_tout_width; uint32_tout_height; uint32_tout_pixel_fmt; uint32_touth_resize_ratio; uint32_toutv_resize_ratio; boolgraphics_combine_en; boolglobal_alpha_en; boolkey_color_en; uint32_tin_g_pixel_fmt; uint8_talpha; uint32_tkey_color; boolalpha_chan_en; ipu_motion_selmotion_sel; enumv4l2_field field_fmt; uint32_tcsi; uint32_tmipi_id; uint32_tmipi_vc; boolmipi_en; }csi_prp_vf_mem;
这个CSI_PRP_VF_MEMchannel于上面CSI_PRP_ENC_MEMchannel对比来看,他们是相似的,只是channel的参数有些差异。他们在ipu内部的流程都是:csi--->ic--->mem 所以首先是设置ipu->using_ic_dirct_ch这一项,然后增加ic的引用计数,使用了csi设备,就制定ipu->csi_channel[]数组中csi号所对应的channel 然后设置ipu_conf寄存器中的28或者29位,来确定csi接口处的设备是普通的还是mipi的。然后设置ipu_conf寄存器的31位,来告诉ic模块,数据来源是csi0还是csi1 之后就是通过_ipu_csi_init函数来设置数据的目的地址,通过_ipu_ic_init_prpvf函数来将ic初始化为预处理viewfinder模式。

从上面几个例子可以看出来基本都是这几个流程。
上面几个函数都使用到了CSI设备,所以都使用了_ipu_csi_init函数来指定数据的目的地址。对于有些channel没有使用CSI设备,肯定就不用使用_ipu_csi_init这个函数了。
比如对于MEM_VDI_MEMchannel,它使用到VDI模块,只需要通过_ipu_vdi_init函数来设置即可。 比如MEM_ROT_VF_MEMchannel,它需要使用到ICrotateviewfinder功能,就需要通过_ipu_ic_init_rotate_vf函数来设置了。