Original article: http://blog.csdn.net/kickxxx/archive/2011/06/22/6560455.aspx
Ipu_capture.c
47 int32_t
48 ipu_csi_init_interface (uint16_t width, uint16_t height, uint32_t pixel_fmt,
49 ipu_csi_signal_0000_t pai_param)
50 {
51 uint32_t DATA = 0;
52 uint32_t CSI = pai_param.csi;
53 unsigned long lock_flags;
54
55/* Set sens_data_format bits (8, 9 and 10)
56 RGB or yuv444 is 0 which is current value in data so not set
57 explicitly
58 this is also the default value if attempts are made to set it
59 something invalid .*/
60 switch (pixel_fmt ){
61 case ipu_pix_fmt_yuyv:
62 pai_param.data_fmt = csi_sens_conf_data_fmt_yuv422_yuyv;
63 break;
64 case ipu_pix_fmt_uyvy:
65 pai_param.data_fmt = csi_sens_conf_data_fmt_yuv422_uyvy;
66 break;
67 case ipu_pix_fmt_rgb24:
68 case ipu_pix_fmt_bgr24:
69 pai_param.data_fmt = csi_sens_conf_data_fmt_rgb_yuv444;
70 break;
71 case ipu_pix_fmt_generic:
72 pai_param.data_fmt = csi_sens_conf_data_fmt_bayer;
73 break;
74 case ipu_pix_fmt_rgb565:
75 pai_param.data_fmt = csi_sens_conf_data_fmt_rgb565;
76 break;
77 case ipu_pix_fmt_rgb555:
78 pai_param.data_fmt = csi_sens_conf_data_fmt_rgb555;
79 break;
80 default:
81 return-einval;
82}
83
84/* set the csi_sens_conf register remaining fields */
85 data | = pai_param.data_width <csi_sens_conf_data_width_shift |
86 pai_param.data_fmt <csi_sens_conf_data_fmt_shift |
87 pai_param.data_pol <csi_sens_conf_data_pol_shift |
88 pai_param.vsync_pol <csi_sens_conf_vsync_pol_shift |
89 pai_param.hsync_pol <csi_sens_conf_hsync_pol_shift |
90 pai_param.pixclk_pol <csi_sens_conf_pix_clk_pol_shift |
91 pai_param.ext_vsync <csi_sens_conf_ext_vsync_shift |
92 pai_param.clk_mode <csi_sens_conf_sens_prtcl_shift |
93 pai_param.pack_tight <csi_sens_conf_pack_tight_shift |
94 pai_param.force_eof <csi_sens_conf_force_eof_shift |
95 pai_param.data_en_pol <csi_sens_conf_data_en_pol_shift;
96
97 If (g_ipu_clk_enabled = false ){
98 stop_dvfs_per ();
99 g_ipu_clk_enabled = true;
100 clk_enable (g_ipu_clk );
101}
102
103 spin_lock_irqsave (& ipu_lock, lock_flags );
104
105 _ raw_writel (data, csi_sens_conf (CSI ));
106
107/* setup sensor frame size */
108 _ raw_writel (width-1) | (height-1) <16, csi_sens_frm_size (CSI ));
109
110/* Set ccir registers */
111 If (pai_param.clk_mode = ipu_csi_clk_mode_ccir656_progressive ){
112 _ raw_writel (0x40030, csi_ccir_code_1 (CSI ));
113 _ raw_writel (0xff0000, csi_ccir_code_3 (CSI ));
114} else if (pai_param.clk_mode = ipu_csi_clk_mode_ccir656_interlaced ){
115 If (width = 720 & Height = 625 ){
116/* pal case */
117 /*
118 * field0blankend = 0x6, field0blankstart = 0x2,
119 * field0activeend = 0x4, field0activestart = 0
120 */
121 _ raw_writel (0x40596, csi_ccir_code_1 (CSI ));
122 /*
123 * field1blankend = 0x7, field1blankstart = 0x3,
124 * field1activeend = 0x5, field1activestart = 0x1
125 */
126 _ raw_writel (0xd07df, csi_ccir_code_2 (CSI ));
127 _ raw_writel (0xff0000, csi_ccir_code_3 (CSI ));
128} else if (width = 720 & Height = 525 ){
129/* NTSC case */
130 /*
131 * field0blankend = 0x7, field0blankstart = 0x3,
132 * field0activeend = 0x5, field0activestart = 0x1
133 */
134 _ raw_writel (0xd07df, csi_ccir_code_1 (CSI ));
135 /*
136 * field1blankend = 0x6, field1blankstart = 0x2,
137 * field1activeend = 0x4, field1activestart = 0
138 */
139 _ raw_writel (0x40596, csi_ccir_code_2 (CSI ));
140 _ raw_writel (0xff0000, csi_ccir_code_3 (CSI ));
141} else {
142 spin_unlock_irqrestore (& ipu_lock, lock_flags );
143 dev_err (g_ipu_dev, "unsupported ccir656 interlaced"
144 "video mode/N ");
145 return-einval;
146}
147 _ ipu_csi_ccir_err_detection_enable (CSI );
148} else if (pai_param.clk_mode =
149 ipu_csi_clk_mode_ccir1120_progressive_ddr) |
150 (pai_param.clk_mode =
151 ipu_csi_clk_mode_ccir1120_progressive_sdr) |
152 (pai_param.clk_mode =
153 ipu_csi_clk_mode_ccir1120_interlaced_ddr) |
154 (pai_param.clk_mode =
155 ipu_csi_clk_mode_ccir1120_interlaced_sdr )){
156 _ raw_writel (0x40030, csi_ccir_code_1 (CSI ));
157 _ raw_writel (0xff0000, csi_ccir_code_3 (CSI ));
158 _ ipu_csi_ccir_err_detection_enable (CSI );
159} else if (pai_param.clk_mode = ipu_csi_clk_mode_gated_clk) |
160 (pai_param.clk_mode = ipu_csi_clk_mode_nongated_clk )){
161 _ ipu_csi_ccir_err_detection_disable (CSI );
162}
163
164 dev_dbg (g_ipu_dev, "csi_sens_conf = 0x % 08x/N ",
165 _ raw_readl (csi_sens_conf (CSI )));
166 dev_dbg (g_ipu_dev, "csi_act_frm_size = 0x % 08x/N ",
167 _ raw_readl (csi_act_frm_size (CSI )));
168
169 spin_unlock_irqrestore (& ipu_lock, lock_flags );
170
171 return 0;
172}
173 export_symbol (ipu_csi_init_interface );
This function is called when the CSI register is initialized on an open device or vidioc_s_parm.
The parameter @ height @ width is the sensor's frame raw size, and the raw size corresponds to the active size. For example, the pal Camera Raw size is 720x625, the active size is 720x576.
Parameter @ pixel_fmt: CSI input pixel format
@ Cfg_param: defines parameters related to the CSI interface. These parameters are determined by the specific camera chip and peripheral circuit.
Data_fmt: CSI input pixel format
Ext_vsync: whether an external vsync signal exists
Clock_mode: For bt656 input, it should be ipu_csi_clk_mode_ccir656_interlaced
55 ~ 82 convert pixel format to the internal representation of the CSI register
84 ~ 96 convert the external parameter to the value of the csi_sens_conf register
108 raw size is written here. For details, refer to the definition of csi_sens_frm_size in MX51.
110 ~ 162 set the CCIR register and the time reference signals (frame start, frame end etc.) of bt656. The first three bytes are fixed. This register defines the mode of the fourth byte. Time reference signals is determined by v h f. I have not analyzed how to map it.
For the definition of v h f, see the definition of bt656. f = 0 indicates an even number of fields, F = 1 indicates an odd number of fields, and V = 0 indicates that the behavior is active video, V = 1 indicates that the row is not active video; h = 0 indicates the SAV signal, and H = 1 indicates the EAV signal.
As to why the pal NTSC settings are reversed, I finally thought of a possibility that the Field Sequence of the PAL and NTSC is different, so I reversed it here, therefore, the capture or preview you obtain must be processed according to the input standard.
(Save it first, then)
276 void ipu_csi_set_window_size (uint32_t width, uint32_t height, uint32_t CSI)
277 {
278 unsigned long lock_flags;
279
280 if (g_ipu_clk_enabled = false ){
281 stop_dvfs_per ();
282 g_ipu_clk_enabled = true;
283 clk_enable (g_ipu_clk );
284}
285
286 spin_lock_irqsave (& ipu_lock, lock_flags );
287
288 _ raw_writel (width-1) | (height-1) <16, csi_act_frm_size (CSI ));
289
290 spin_unlock_irqrestore (& ipu_lock, lock_flags );
291}
292 export_symbol (ipu_csi_set_window_size );
301 void ipu_csi_set_window_pos (uint32_t left, uint32_t top, uint32_t CSI)
302 {
303 uint32_t temp;
304 unsigned long lock_flags;
305
306 If (g_ipu_clk_enabled = false ){
307 stop_dvfs_per ();
308 g_ipu_clk_enabled = true;
309 clk_enable (g_ipu_clk );
310}
311
312 spin_lock_irqsave (& ipu_lock, lock_flags );
313
314 temp = _ raw_readl (csi_out_frm_ctrl (CSI ));
315 temp & = ~ (Csi_hsc_mask | csi_vsc_mask );
316 temp | = (top <csi_vsc_shift) | (left <csi_hsc_shift ));
317 _ raw_writel (temp, csi_out_frm_ctrl (CSI ));
318
319 spin_unlock_irqrestore (& ipu_lock, lock_flags );
320}
321 export_symbol (ipu_csi_set_window_pos );
There is nothing to say about these two functions, but csi_act_frm_size and csi_out_frm_ctrl are very important. Here I can only guess, because I didn't try this function.
Csi_act_frm_size and csi_out_frm_ctrl define crop rectangle. Do you still remember vidioc_s_crop? This IOCTL will eventually call ipu_csi_set_window_size and ipu_csi_set_window_pos. It is equivalent to opening a scenario box in the maximum active window of the CSI. Capture and overlay only use the pixels in the context box. If there is time to come back to verify this problem.
329 void _ ipu_csi_horizontal_downsize_enable (uint32_t CSI)
330 {
331 uint32_t temp;
332 unsigned long lock_flags;
333
334 if (g_ipu_clk_enabled = false ){
335 stop_dvfs_per ();
336 g_ipu_clk_enabled = true;
337 clk_enable (g_ipu_clk );
338}
339
340 spin_lock_irqsave (& ipu_lock, lock_flags );
341
342 temp = _ raw_readl (csi_out_frm_ctrl (CSI ));
343 temp | = csi_hori_downsize_en;
344 _ raw_writel (temp, csi_out_frm_ctrl (CSI ));
345
346 spin_unlock_irqrestore (& ipu_lock, lock_flags );
347}
381 void _ ipu_csi_vertical_downsize_enable (uint32_t CSI)
382 {
383 uint32_t temp;
384 unsigned long lock_flags;
385
386 if (g_ipu_clk_enabled = false ){
387 stop_dvfs_per ();
388 g_ipu_clk_enabled = true;
389 clk_enable (g_ipu_clk );
390}
391
392 spin_lock_irqsave (& ipu_lock, lock_flags );
393
394 temp = _ raw_readl (csi_out_frm_ctrl (CSI ));
395 temp | = csi_vert_downsize_en;
396 _ raw_writel (temp, csi_out_frm_ctrl (CSI ));
397
398 spin_unlock_irqrestore (& ipu_lock, lock_flags );
399}
The role of csi_vert_downsize_en csi_hori_downsize_en should be tried later.
824 int _ ipu_csi_init (ipu_channel_t channel, uint32_t CSI)
825 {
826 uint32_t csi_sens_conf, csi_dest;
827 int retval = 0;
828
829 switch (Channel ){
830 case csi_mem0:
831 case csi_mem1:
832 case csi_mem2:
833 case csi_mem3:
834 csi_dest = csi_data_dest_idmac;
835 break;
836 case csi_prp_enc_mem:
837 case csi_prp_vf_mem:
838 csi_dest = csi_data_dest_ic;
839 break;
Default 840:
841 retval =-einval;
842 goto err;
843}
844
845 csi_sens_conf = _ raw_readl (csi_sens_conf (CSI ));
846 csi_sens_conf & = ~ Csi_sens_conf_data_dest_mask;
847 _ raw_writel (csi_sens_conf | (csi_dest <
848 csi_sens_conf_data_dest_shift), csi_sens_conf (CSI ));
849 err:
850 return retval;
851}
Depending on the channel, set the destination of the CSI data. You can set data_dest to determine the direction of the CSI sensor data. IC, smfc, ISP