对ipu_init_channel的理解
2016-05-2617:11:40
(一)
对于每个channel,它的信息都保存在ipu_channel_params_t结构体联合中,在ipu_init_channel函数中,会根据传入的这个ipu_channel_params_t结构体联合中channel所对应的参数来初始化channel。
对于每一个channel,首先要理解这个channel在ipu中所使用到的模块及数据的流通方向。然后使用到哪一个模块的话,需要增加这个模块的引用计数。之后就是设置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)然后这个channel在ipu内部的流程是通过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中获取到的数据map到IDMACchannel中。
4)指定csi设备的数据流向,通过_ipu_csi_init函数。这个函数中数据的目的地址只有IDMAC和IC两项。通过操作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)这个channel在ipu内部的流程是: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,它需要使用到IC的rotate和viewfinder功能,就需要通过_ipu_ic_init_rotate_vf函数来设置了。