Commit 5ddfaaaeeb3996e9a219eaacffc725eef1ecfd28
1 parent
363e746e8e
Exists in
smarc-l5.0.0_1.0.0-ga
and in
2 other branches
MLK-9917 imx6sx: fix csi modules prevent system entering low power mode
The reproduce step: $ echo 8 > /proc/sys/kernel/printk $ echo 1 > /sys/class/graphics/fb0/blank $ ifconfig eth0 down $ ifconfig eth1 down $ cat /sys/kernel/debug/clk/osc/pll2_bus/pll2_pfd2_396m/periph2_pre/periph2/mmdc_podf/clk_rate 396000000 The expected result should be '24000000' and following message. Bus freq set to 24000000 start... Bus freq set to 24000000 done! This patch did the following to fix it. - Move the pm runtime handling into csi v4l2 driver, request high bus frequency when the device opens and release high bus frequency when device closes. - Add new api csisw_reset() to mainly do DMA reflash otherwise potentially meet garbage data when CSI starts to work on imx6sl. Signed-off-by: Robby Cai <r63905@freescale.com> (cherry picked from commit 857a52585c92cad8d851751f859e8e23ea4ae250)
Showing 4 changed files with 124 additions and 61 deletions Inline Diff
drivers/media/platform/mxc/capture/csi_v4l2_capture.c
1 | /* | 1 | /* |
2 | * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved. | 2 | * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | /* | 5 | /* |
6 | * The code contained herein is licensed under the GNU General Public | 6 | * The code contained herein is licensed under the GNU General Public |
7 | * License. You may obtain a copy of the GNU General Public License | 7 | * License. You may obtain a copy of the GNU General Public License |
8 | * Version 2 or later at the following locations: | 8 | * Version 2 or later at the following locations: |
9 | * | 9 | * |
10 | * http://www.opensource.org/licenses/gpl-license.html | 10 | * http://www.opensource.org/licenses/gpl-license.html |
11 | * http://www.gnu.org/copyleft/gpl.html | 11 | * http://www.gnu.org/copyleft/gpl.html |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /*! | 14 | /*! |
15 | * @file drivers/media/video/mxc/capture/csi_v4l2_capture.c | 15 | * @file drivers/media/video/mxc/capture/csi_v4l2_capture.c |
16 | * This file is derived from mxc_v4l2_capture.c | 16 | * This file is derived from mxc_v4l2_capture.c |
17 | * | 17 | * |
18 | * @brief Video For Linux 2 capture driver | 18 | * @brief Video For Linux 2 capture driver |
19 | * | 19 | * |
20 | * @ingroup MXC_V4L2_CAPTURE | 20 | * @ingroup MXC_V4L2_CAPTURE |
21 | */ | 21 | */ |
22 | #include <linux/busfreq-imx6.h> | ||
22 | #include <linux/version.h> | 23 | #include <linux/version.h> |
23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
26 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <linux/ctype.h> | 29 | #include <linux/ctype.h> |
29 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
30 | #include <linux/io.h> | 31 | #include <linux/io.h> |
31 | #include <linux/semaphore.h> | 32 | #include <linux/semaphore.h> |
32 | #include <linux/pagemap.h> | 33 | #include <linux/pagemap.h> |
34 | #include <linux/pm_runtime.h> | ||
33 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
34 | #include <linux/types.h> | 36 | #include <linux/types.h> |
35 | #include <linux/fb.h> | 37 | #include <linux/fb.h> |
36 | #include <linux/mxcfb.h> | 38 | #include <linux/mxcfb.h> |
37 | #include <linux/dma-mapping.h> | 39 | #include <linux/dma-mapping.h> |
38 | #include <media/v4l2-ioctl.h> | 40 | #include <media/v4l2-ioctl.h> |
39 | #include <media/v4l2-int-device.h> | 41 | #include <media/v4l2-int-device.h> |
40 | #include <media/v4l2-chip-ident.h> | 42 | #include <media/v4l2-chip-ident.h> |
41 | #include "mxc_v4l2_capture.h" | 43 | #include "mxc_v4l2_capture.h" |
42 | #include "fsl_csi.h" | 44 | #include "fsl_csi.h" |
43 | 45 | ||
44 | static int video_nr = -1; | 46 | static int video_nr = -1; |
45 | static int req_buf_number; | 47 | static int req_buf_number; |
46 | 48 | ||
47 | static int csi_v4l2_master_attach(struct v4l2_int_device *slave); | 49 | static int csi_v4l2_master_attach(struct v4l2_int_device *slave); |
48 | static void csi_v4l2_master_detach(struct v4l2_int_device *slave); | 50 | static void csi_v4l2_master_detach(struct v4l2_int_device *slave); |
49 | static u8 camera_power(cam_data *cam, bool cameraOn); | 51 | static u8 camera_power(cam_data *cam, bool cameraOn); |
50 | 52 | ||
51 | /*! Information about this driver. */ | 53 | /*! Information about this driver. */ |
52 | static struct v4l2_int_master csi_v4l2_master = { | 54 | static struct v4l2_int_master csi_v4l2_master = { |
53 | .attach = csi_v4l2_master_attach, | 55 | .attach = csi_v4l2_master_attach, |
54 | .detach = csi_v4l2_master_detach, | 56 | .detach = csi_v4l2_master_detach, |
55 | }; | 57 | }; |
56 | 58 | ||
57 | static struct v4l2_queryctrl pxp_controls[] = { | 59 | static struct v4l2_queryctrl pxp_controls[] = { |
58 | { | 60 | { |
59 | .id = V4L2_CID_HFLIP, | 61 | .id = V4L2_CID_HFLIP, |
60 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 62 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
61 | .name = "Horizontal Flip", | 63 | .name = "Horizontal Flip", |
62 | .minimum = 0, | 64 | .minimum = 0, |
63 | .maximum = 1, | 65 | .maximum = 1, |
64 | .step = 1, | 66 | .step = 1, |
65 | .default_value = 0, | 67 | .default_value = 0, |
66 | .flags = 0, | 68 | .flags = 0, |
67 | }, { | 69 | }, { |
68 | .id = V4L2_CID_VFLIP, | 70 | .id = V4L2_CID_VFLIP, |
69 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 71 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
70 | .name = "Vertical Flip", | 72 | .name = "Vertical Flip", |
71 | .minimum = 0, | 73 | .minimum = 0, |
72 | .maximum = 1, | 74 | .maximum = 1, |
73 | .step = 1, | 75 | .step = 1, |
74 | .default_value = 0, | 76 | .default_value = 0, |
75 | .flags = 0, | 77 | .flags = 0, |
76 | }, { | 78 | }, { |
77 | .id = V4L2_CID_PRIVATE_BASE, | 79 | .id = V4L2_CID_PRIVATE_BASE, |
78 | .type = V4L2_CTRL_TYPE_INTEGER, | 80 | .type = V4L2_CTRL_TYPE_INTEGER, |
79 | .name = "Rotation", | 81 | .name = "Rotation", |
80 | .minimum = 0, | 82 | .minimum = 0, |
81 | .maximum = 270, | 83 | .maximum = 270, |
82 | .step = 90, | 84 | .step = 90, |
83 | .default_value = 0, | 85 | .default_value = 0, |
84 | .flags = 0, | 86 | .flags = 0, |
85 | }, | 87 | }, |
86 | }; | 88 | }; |
87 | 89 | ||
88 | /*! List of TV input video formats supported. The video formats is corresponding | 90 | /*! List of TV input video formats supported. The video formats is corresponding |
89 | * to the v4l2_id in video_fmt_t. | 91 | * to the v4l2_id in video_fmt_t. |
90 | * Currently, only PAL and NTSC is supported. Needs to be expanded in the | 92 | * Currently, only PAL and NTSC is supported. Needs to be expanded in the |
91 | * future. | 93 | * future. |
92 | */ | 94 | */ |
93 | typedef enum _video_fmt_idx { | 95 | typedef enum _video_fmt_idx { |
94 | TV_NTSC = 0, /*!< Locked on (M) NTSC video signal. */ | 96 | TV_NTSC = 0, /*!< Locked on (M) NTSC video signal. */ |
95 | TV_PAL, /*!< (B, G, H, I, N)PAL video signal. */ | 97 | TV_PAL, /*!< (B, G, H, I, N)PAL video signal. */ |
96 | TV_NOT_LOCKED, /*!< Not locked on a signal. */ | 98 | TV_NOT_LOCKED, /*!< Not locked on a signal. */ |
97 | } video_fmt_idx; | 99 | } video_fmt_idx; |
98 | 100 | ||
99 | /*! Number of video standards supported (including 'not locked' signal). */ | 101 | /*! Number of video standards supported (including 'not locked' signal). */ |
100 | #define TV_STD_MAX (TV_NOT_LOCKED + 1) | 102 | #define TV_STD_MAX (TV_NOT_LOCKED + 1) |
101 | 103 | ||
102 | /*! Video format structure. */ | 104 | /*! Video format structure. */ |
103 | typedef struct _video_fmt_t { | 105 | typedef struct _video_fmt_t { |
104 | int v4l2_id; /*!< Video for linux ID. */ | 106 | int v4l2_id; /*!< Video for linux ID. */ |
105 | char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */ | 107 | char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */ |
106 | u16 raw_width; /*!< Raw width. */ | 108 | u16 raw_width; /*!< Raw width. */ |
107 | u16 raw_height; /*!< Raw height. */ | 109 | u16 raw_height; /*!< Raw height. */ |
108 | u16 active_width; /*!< Active width. */ | 110 | u16 active_width; /*!< Active width. */ |
109 | u16 active_height; /*!< Active height. */ | 111 | u16 active_height; /*!< Active height. */ |
110 | u16 active_top; /*!< Active top. */ | 112 | u16 active_top; /*!< Active top. */ |
111 | u16 active_left; /*!< Active left. */ | 113 | u16 active_left; /*!< Active left. */ |
112 | } video_fmt_t; | 114 | } video_fmt_t; |
113 | 115 | ||
114 | /*! | 116 | /*! |
115 | * Description of video formats supported. | 117 | * Description of video formats supported. |
116 | * | 118 | * |
117 | * PAL: raw=720x625, active=720x576. | 119 | * PAL: raw=720x625, active=720x576. |
118 | * NTSC: raw=720x525, active=720x480. | 120 | * NTSC: raw=720x525, active=720x480. |
119 | */ | 121 | */ |
120 | static video_fmt_t video_fmts[] = { | 122 | static video_fmt_t video_fmts[] = { |
121 | { /*! NTSC */ | 123 | { /*! NTSC */ |
122 | .v4l2_id = V4L2_STD_NTSC, | 124 | .v4l2_id = V4L2_STD_NTSC, |
123 | .name = "NTSC", | 125 | .name = "NTSC", |
124 | .raw_width = 720, /* SENS_FRM_WIDTH */ | 126 | .raw_width = 720, /* SENS_FRM_WIDTH */ |
125 | .raw_height = 525, /* SENS_FRM_HEIGHT */ | 127 | .raw_height = 525, /* SENS_FRM_HEIGHT */ |
126 | .active_width = 720, /* ACT_FRM_WIDTH */ | 128 | .active_width = 720, /* ACT_FRM_WIDTH */ |
127 | .active_height = 480, /* ACT_FRM_HEIGHT */ | 129 | .active_height = 480, /* ACT_FRM_HEIGHT */ |
128 | .active_top = 0, | 130 | .active_top = 0, |
129 | .active_left = 0, | 131 | .active_left = 0, |
130 | }, | 132 | }, |
131 | { /*! (B, G, H, I, N) PAL */ | 133 | { /*! (B, G, H, I, N) PAL */ |
132 | .v4l2_id = V4L2_STD_PAL, | 134 | .v4l2_id = V4L2_STD_PAL, |
133 | .name = "PAL", | 135 | .name = "PAL", |
134 | .raw_width = 720, | 136 | .raw_width = 720, |
135 | .raw_height = 625, | 137 | .raw_height = 625, |
136 | .active_width = 720, | 138 | .active_width = 720, |
137 | .active_height = 576, | 139 | .active_height = 576, |
138 | .active_top = 0, | 140 | .active_top = 0, |
139 | .active_left = 0, | 141 | .active_left = 0, |
140 | }, | 142 | }, |
141 | { /*! Unlocked standard */ | 143 | { /*! Unlocked standard */ |
142 | .v4l2_id = V4L2_STD_ALL, | 144 | .v4l2_id = V4L2_STD_ALL, |
143 | .name = "Autodetect", | 145 | .name = "Autodetect", |
144 | .raw_width = 720, | 146 | .raw_width = 720, |
145 | .raw_height = 625, | 147 | .raw_height = 625, |
146 | .active_width = 720, | 148 | .active_width = 720, |
147 | .active_height = 576, | 149 | .active_height = 576, |
148 | .active_top = 0, | 150 | .active_top = 0, |
149 | .active_left = 0, | 151 | .active_left = 0, |
150 | }, | 152 | }, |
151 | }; | 153 | }; |
152 | 154 | ||
153 | #define CSI_V4L2_CAPTURE_NUM_INPUTS 2 | 155 | #define CSI_V4L2_CAPTURE_NUM_INPUTS 2 |
154 | static struct v4l2_input csi_capture_inputs[CSI_V4L2_CAPTURE_NUM_INPUTS] = { | 156 | static struct v4l2_input csi_capture_inputs[CSI_V4L2_CAPTURE_NUM_INPUTS] = { |
155 | { | 157 | { |
156 | .index = 0, | 158 | .index = 0, |
157 | .name = "Camera", | 159 | .name = "Camera", |
158 | .type = V4L2_INPUT_TYPE_CAMERA, | 160 | .type = V4L2_INPUT_TYPE_CAMERA, |
159 | .audioset = 0, | 161 | .audioset = 0, |
160 | .tuner = 0, | 162 | .tuner = 0, |
161 | .std = V4L2_STD_UNKNOWN, | 163 | .std = V4L2_STD_UNKNOWN, |
162 | .status = 0, | 164 | .status = 0, |
163 | }, | 165 | }, |
164 | { | 166 | { |
165 | .index = 1, | 167 | .index = 1, |
166 | .name = "Vadc", | 168 | .name = "Vadc", |
167 | .type = V4L2_INPUT_TYPE_CAMERA, | 169 | .type = V4L2_INPUT_TYPE_CAMERA, |
168 | .audioset = 0, | 170 | .audioset = 0, |
169 | .tuner = 0, | 171 | .tuner = 0, |
170 | .std = V4L2_STD_UNKNOWN, | 172 | .std = V4L2_STD_UNKNOWN, |
171 | .status = 0, | 173 | .status = 0, |
172 | }, | 174 | }, |
173 | }; | 175 | }; |
174 | 176 | ||
175 | /*!* Standard index of TV. */ | 177 | /*!* Standard index of TV. */ |
176 | static video_fmt_idx video_index = TV_NOT_LOCKED; | 178 | static video_fmt_idx video_index = TV_NOT_LOCKED; |
177 | 179 | ||
178 | /* Callback function triggered after PxP receives an EOF interrupt */ | 180 | /* Callback function triggered after PxP receives an EOF interrupt */ |
179 | static void pxp_dma_done(void *arg) | 181 | static void pxp_dma_done(void *arg) |
180 | { | 182 | { |
181 | struct pxp_tx_desc *tx_desc = to_tx_desc(arg); | 183 | struct pxp_tx_desc *tx_desc = to_tx_desc(arg); |
182 | struct dma_chan *chan = tx_desc->txd.chan; | 184 | struct dma_chan *chan = tx_desc->txd.chan; |
183 | struct pxp_channel *pxp_chan = to_pxp_channel(chan); | 185 | struct pxp_channel *pxp_chan = to_pxp_channel(chan); |
184 | cam_data *cam = pxp_chan->client; | 186 | cam_data *cam = pxp_chan->client; |
185 | 187 | ||
186 | /* This call will signal wait_for_completion_timeout() */ | 188 | /* This call will signal wait_for_completion_timeout() */ |
187 | complete(&cam->pxp_tx_cmpl); | 189 | complete(&cam->pxp_tx_cmpl); |
188 | } | 190 | } |
189 | 191 | ||
190 | static bool chan_filter(struct dma_chan *chan, void *arg) | 192 | static bool chan_filter(struct dma_chan *chan, void *arg) |
191 | { | 193 | { |
192 | if (imx_dma_is_pxp(chan)) | 194 | if (imx_dma_is_pxp(chan)) |
193 | return true; | 195 | return true; |
194 | else | 196 | else |
195 | return false; | 197 | return false; |
196 | } | 198 | } |
197 | 199 | ||
198 | /* Function to request PXP DMA channel */ | 200 | /* Function to request PXP DMA channel */ |
199 | static int pxp_chan_init(cam_data *cam) | 201 | static int pxp_chan_init(cam_data *cam) |
200 | { | 202 | { |
201 | dma_cap_mask_t mask; | 203 | dma_cap_mask_t mask; |
202 | struct dma_chan *chan; | 204 | struct dma_chan *chan; |
203 | 205 | ||
204 | /* Request a free channel */ | 206 | /* Request a free channel */ |
205 | dma_cap_zero(mask); | 207 | dma_cap_zero(mask); |
206 | dma_cap_set(DMA_SLAVE, mask); | 208 | dma_cap_set(DMA_SLAVE, mask); |
207 | dma_cap_set(DMA_PRIVATE, mask); | 209 | dma_cap_set(DMA_PRIVATE, mask); |
208 | chan = dma_request_channel(mask, chan_filter, NULL); | 210 | chan = dma_request_channel(mask, chan_filter, NULL); |
209 | if (!chan) { | 211 | if (!chan) { |
210 | pr_err("Unsuccessfully request channel!\n"); | 212 | pr_err("Unsuccessfully request channel!\n"); |
211 | return -EBUSY; | 213 | return -EBUSY; |
212 | } | 214 | } |
213 | 215 | ||
214 | cam->pxp_chan = to_pxp_channel(chan); | 216 | cam->pxp_chan = to_pxp_channel(chan); |
215 | cam->pxp_chan->client = cam; | 217 | cam->pxp_chan->client = cam; |
216 | 218 | ||
217 | init_completion(&cam->pxp_tx_cmpl); | 219 | init_completion(&cam->pxp_tx_cmpl); |
218 | 220 | ||
219 | return 0; | 221 | return 0; |
220 | } | 222 | } |
221 | 223 | ||
222 | static int v4l2_fmt_2_pxp_fmt(int fmt) | 224 | static int v4l2_fmt_2_pxp_fmt(int fmt) |
223 | { | 225 | { |
224 | int ret; | 226 | int ret; |
225 | switch (fmt) { | 227 | switch (fmt) { |
226 | case V4L2_PIX_FMT_YUV420: | 228 | case V4L2_PIX_FMT_YUV420: |
227 | ret = PXP_PIX_FMT_YUV420P2; | 229 | ret = PXP_PIX_FMT_YUV420P2; |
228 | break; | 230 | break; |
229 | case V4L2_PIX_FMT_RGB565: | 231 | case V4L2_PIX_FMT_RGB565: |
230 | case V4L2_PIX_FMT_YUYV: | 232 | case V4L2_PIX_FMT_YUYV: |
231 | case V4L2_PIX_FMT_UYVY: | 233 | case V4L2_PIX_FMT_UYVY: |
232 | case V4L2_PIX_FMT_YUV444: | 234 | case V4L2_PIX_FMT_YUV444: |
233 | default: | 235 | default: |
234 | ret = fmt; | 236 | ret = fmt; |
235 | break; | 237 | break; |
236 | } | 238 | } |
237 | return ret; | 239 | return ret; |
238 | } | 240 | } |
239 | /* | 241 | /* |
240 | * Function to call PxP DMA driver and send our new V4L2 buffer | 242 | * Function to call PxP DMA driver and send our new V4L2 buffer |
241 | * through the PxP. | 243 | * through the PxP. |
242 | * Note: This is a blocking call, so upon return the PxP tx should be complete. | 244 | * Note: This is a blocking call, so upon return the PxP tx should be complete. |
243 | */ | 245 | */ |
244 | static int pxp_process_update(cam_data *cam) | 246 | static int pxp_process_update(cam_data *cam) |
245 | { | 247 | { |
246 | dma_cookie_t cookie; | 248 | dma_cookie_t cookie; |
247 | struct scatterlist *sg = cam->sg; | 249 | struct scatterlist *sg = cam->sg; |
248 | struct dma_chan *dma_chan; | 250 | struct dma_chan *dma_chan; |
249 | struct pxp_tx_desc *desc; | 251 | struct pxp_tx_desc *desc; |
250 | struct dma_async_tx_descriptor *txd; | 252 | struct dma_async_tx_descriptor *txd; |
251 | struct pxp_config_data *pxp_conf = &cam->pxp_conf; | 253 | struct pxp_config_data *pxp_conf = &cam->pxp_conf; |
252 | struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; | 254 | struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; |
253 | int i, ret; | 255 | int i, ret; |
254 | int length; | 256 | int length; |
255 | 257 | ||
256 | pr_debug("Starting PxP Send Buffer\n"); | 258 | pr_debug("Starting PxP Send Buffer\n"); |
257 | 259 | ||
258 | /* First, check to see that we have acquired a PxP Channel object */ | 260 | /* First, check to see that we have acquired a PxP Channel object */ |
259 | if (cam->pxp_chan == NULL) { | 261 | if (cam->pxp_chan == NULL) { |
260 | /* | 262 | /* |
261 | * PxP Channel has not yet been created and initialized, | 263 | * PxP Channel has not yet been created and initialized, |
262 | * so let's go ahead and try | 264 | * so let's go ahead and try |
263 | */ | 265 | */ |
264 | ret = pxp_chan_init(cam); | 266 | ret = pxp_chan_init(cam); |
265 | if (ret) { | 267 | if (ret) { |
266 | /* | 268 | /* |
267 | * PxP channel init failed, and we can't use the | 269 | * PxP channel init failed, and we can't use the |
268 | * PxP until the PxP DMA driver has loaded, so we abort | 270 | * PxP until the PxP DMA driver has loaded, so we abort |
269 | */ | 271 | */ |
270 | pr_err("PxP chan init failed\n"); | 272 | pr_err("PxP chan init failed\n"); |
271 | return -ENODEV; | 273 | return -ENODEV; |
272 | } | 274 | } |
273 | } | 275 | } |
274 | 276 | ||
275 | /* | 277 | /* |
276 | * Init completion, so that we can be properly informed of | 278 | * Init completion, so that we can be properly informed of |
277 | * the completion of the PxP task when it is done. | 279 | * the completion of the PxP task when it is done. |
278 | */ | 280 | */ |
279 | init_completion(&cam->pxp_tx_cmpl); | 281 | init_completion(&cam->pxp_tx_cmpl); |
280 | 282 | ||
281 | dma_chan = &cam->pxp_chan->dma_chan; | 283 | dma_chan = &cam->pxp_chan->dma_chan; |
282 | 284 | ||
283 | txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2, | 285 | txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2, |
284 | DMA_TO_DEVICE, | 286 | DMA_TO_DEVICE, |
285 | DMA_PREP_INTERRUPT, | 287 | DMA_PREP_INTERRUPT, |
286 | NULL); | 288 | NULL); |
287 | if (!txd) { | 289 | if (!txd) { |
288 | pr_err("Error preparing a DMA transaction descriptor.\n"); | 290 | pr_err("Error preparing a DMA transaction descriptor.\n"); |
289 | return -EIO; | 291 | return -EIO; |
290 | } | 292 | } |
291 | 293 | ||
292 | txd->callback_param = txd; | 294 | txd->callback_param = txd; |
293 | txd->callback = pxp_dma_done; | 295 | txd->callback = pxp_dma_done; |
294 | 296 | ||
295 | /* | 297 | /* |
296 | * Configure PxP for processing of new v4l2 buf | 298 | * Configure PxP for processing of new v4l2 buf |
297 | */ | 299 | */ |
298 | pxp_conf->s0_param.pixel_fmt = | 300 | pxp_conf->s0_param.pixel_fmt = |
299 | v4l2_fmt_2_pxp_fmt(cam->input_fmt.fmt.pix.pixelformat); | 301 | v4l2_fmt_2_pxp_fmt(cam->input_fmt.fmt.pix.pixelformat); |
300 | pxp_conf->s0_param.color_key = -1; | 302 | pxp_conf->s0_param.color_key = -1; |
301 | pxp_conf->s0_param.color_key_enable = false; | 303 | pxp_conf->s0_param.color_key_enable = false; |
302 | pxp_conf->s0_param.width = cam->input_fmt.fmt.pix.width; | 304 | pxp_conf->s0_param.width = cam->input_fmt.fmt.pix.width; |
303 | pxp_conf->s0_param.height = cam->input_fmt.fmt.pix.height; | 305 | pxp_conf->s0_param.height = cam->input_fmt.fmt.pix.height; |
304 | 306 | ||
305 | pxp_conf->ol_param[0].combine_enable = false; | 307 | pxp_conf->ol_param[0].combine_enable = false; |
306 | 308 | ||
307 | proc_data->srect.top = 0; | 309 | proc_data->srect.top = 0; |
308 | proc_data->srect.left = 0; | 310 | proc_data->srect.left = 0; |
309 | proc_data->srect.width = pxp_conf->s0_param.width; | 311 | proc_data->srect.width = pxp_conf->s0_param.width; |
310 | proc_data->srect.height = pxp_conf->s0_param.height; | 312 | proc_data->srect.height = pxp_conf->s0_param.height; |
311 | 313 | ||
312 | if (cam->crop_current.top != 0) | 314 | if (cam->crop_current.top != 0) |
313 | proc_data->srect.top = cam->crop_current.top; | 315 | proc_data->srect.top = cam->crop_current.top; |
314 | if (cam->crop_current.left != 0) | 316 | if (cam->crop_current.left != 0) |
315 | proc_data->srect.left = cam->crop_current.left; | 317 | proc_data->srect.left = cam->crop_current.left; |
316 | if (cam->crop_current.width != 0) | 318 | if (cam->crop_current.width != 0) |
317 | proc_data->srect.width = cam->crop_current.width; | 319 | proc_data->srect.width = cam->crop_current.width; |
318 | if (cam->crop_current.height != 0) | 320 | if (cam->crop_current.height != 0) |
319 | proc_data->srect.height = cam->crop_current.height; | 321 | proc_data->srect.height = cam->crop_current.height; |
320 | 322 | ||
321 | proc_data->drect.left = 0; | 323 | proc_data->drect.left = 0; |
322 | proc_data->drect.top = 0; | 324 | proc_data->drect.top = 0; |
323 | proc_data->drect.width = cam->v2f.fmt.pix.width; | 325 | proc_data->drect.width = cam->v2f.fmt.pix.width; |
324 | proc_data->drect.height = cam->v2f.fmt.pix.height; | 326 | proc_data->drect.height = cam->v2f.fmt.pix.height; |
325 | 327 | ||
326 | /* Out buffer */ | 328 | /* Out buffer */ |
327 | pxp_conf->out_param.pixel_fmt = v4l2_fmt_2_pxp_fmt(cam->v2f.fmt.pix.pixelformat); | 329 | pxp_conf->out_param.pixel_fmt = v4l2_fmt_2_pxp_fmt(cam->v2f.fmt.pix.pixelformat); |
328 | pxp_conf->out_param.width = proc_data->drect.width; | 330 | pxp_conf->out_param.width = proc_data->drect.width; |
329 | pxp_conf->out_param.height = proc_data->drect.height; | 331 | pxp_conf->out_param.height = proc_data->drect.height; |
330 | 332 | ||
331 | pr_debug("srect l: %d, t: %d, w: %d, h: %d; " | 333 | pr_debug("srect l: %d, t: %d, w: %d, h: %d; " |
332 | "drect l: %d, t: %d, w: %d, h: %d\n", | 334 | "drect l: %d, t: %d, w: %d, h: %d\n", |
333 | proc_data->srect.left, proc_data->srect.top, | 335 | proc_data->srect.left, proc_data->srect.top, |
334 | proc_data->srect.width, proc_data->srect.height, | 336 | proc_data->srect.width, proc_data->srect.height, |
335 | proc_data->drect.left, proc_data->drect.top, | 337 | proc_data->drect.left, proc_data->drect.top, |
336 | proc_data->drect.width, proc_data->drect.height); | 338 | proc_data->drect.width, proc_data->drect.height); |
337 | 339 | ||
338 | if (cam->rotation % 180) | 340 | if (cam->rotation % 180) |
339 | pxp_conf->out_param.stride = pxp_conf->out_param.height; | 341 | pxp_conf->out_param.stride = pxp_conf->out_param.height; |
340 | else | 342 | else |
341 | pxp_conf->out_param.stride = pxp_conf->out_param.width; | 343 | pxp_conf->out_param.stride = pxp_conf->out_param.width; |
342 | 344 | ||
343 | desc = to_tx_desc(txd); | 345 | desc = to_tx_desc(txd); |
344 | length = desc->len; | 346 | length = desc->len; |
345 | for (i = 0; i < length; i++) { | 347 | for (i = 0; i < length; i++) { |
346 | if (i == 0) {/* S0 */ | 348 | if (i == 0) {/* S0 */ |
347 | memcpy(&desc->proc_data, proc_data, | 349 | memcpy(&desc->proc_data, proc_data, |
348 | sizeof(struct pxp_proc_data)); | 350 | sizeof(struct pxp_proc_data)); |
349 | pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]); | 351 | pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]); |
350 | memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param, | 352 | memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param, |
351 | sizeof(struct pxp_layer_param)); | 353 | sizeof(struct pxp_layer_param)); |
352 | } else if (i == 1) {/* output */ | 354 | } else if (i == 1) {/* output */ |
353 | pxp_conf->out_param.paddr = sg_dma_address(&sg[1]); | 355 | pxp_conf->out_param.paddr = sg_dma_address(&sg[1]); |
354 | memcpy(&desc->layer_param.out_param, | 356 | memcpy(&desc->layer_param.out_param, |
355 | &pxp_conf->out_param, | 357 | &pxp_conf->out_param, |
356 | sizeof(struct pxp_layer_param)); | 358 | sizeof(struct pxp_layer_param)); |
357 | } else {/* overlay */ | 359 | } else {/* overlay */ |
358 | memcpy(&desc->layer_param.ol_param, | 360 | memcpy(&desc->layer_param.ol_param, |
359 | &pxp_conf->ol_param, | 361 | &pxp_conf->ol_param, |
360 | sizeof(struct pxp_layer_param)); | 362 | sizeof(struct pxp_layer_param)); |
361 | } | 363 | } |
362 | 364 | ||
363 | desc = desc->next; | 365 | desc = desc->next; |
364 | } | 366 | } |
365 | 367 | ||
366 | /* Submitting our TX starts the PxP processing task */ | 368 | /* Submitting our TX starts the PxP processing task */ |
367 | cookie = txd->tx_submit(txd); | 369 | cookie = txd->tx_submit(txd); |
368 | if (cookie < 0) { | 370 | if (cookie < 0) { |
369 | pr_err("Error sending FB through PxP\n"); | 371 | pr_err("Error sending FB through PxP\n"); |
370 | return -EIO; | 372 | return -EIO; |
371 | } | 373 | } |
372 | 374 | ||
373 | cam->txd = txd; | 375 | cam->txd = txd; |
374 | 376 | ||
375 | /* trigger PxP */ | 377 | /* trigger PxP */ |
376 | dma_async_issue_pending(dma_chan); | 378 | dma_async_issue_pending(dma_chan); |
377 | 379 | ||
378 | return 0; | 380 | return 0; |
379 | } | 381 | } |
380 | 382 | ||
381 | static int pxp_complete_update(cam_data *cam) | 383 | static int pxp_complete_update(cam_data *cam) |
382 | { | 384 | { |
383 | int ret; | 385 | int ret; |
384 | /* | 386 | /* |
385 | * Wait for completion event, which will be set | 387 | * Wait for completion event, which will be set |
386 | * through our TX callback function. | 388 | * through our TX callback function. |
387 | */ | 389 | */ |
388 | ret = wait_for_completion_timeout(&cam->pxp_tx_cmpl, HZ / 10); | 390 | ret = wait_for_completion_timeout(&cam->pxp_tx_cmpl, HZ / 10); |
389 | if (ret <= 0) { | 391 | if (ret <= 0) { |
390 | pr_warning("PxP operation failed due to %s\n", | 392 | pr_warning("PxP operation failed due to %s\n", |
391 | ret < 0 ? "user interrupt" : "timeout"); | 393 | ret < 0 ? "user interrupt" : "timeout"); |
392 | dma_release_channel(&cam->pxp_chan->dma_chan); | 394 | dma_release_channel(&cam->pxp_chan->dma_chan); |
393 | cam->pxp_chan = NULL; | 395 | cam->pxp_chan = NULL; |
394 | return ret ? : -ETIMEDOUT; | 396 | return ret ? : -ETIMEDOUT; |
395 | } | 397 | } |
396 | 398 | ||
397 | dma_release_channel(&cam->pxp_chan->dma_chan); | 399 | dma_release_channel(&cam->pxp_chan->dma_chan); |
398 | cam->pxp_chan = NULL; | 400 | cam->pxp_chan = NULL; |
399 | 401 | ||
400 | pr_debug("TX completed\n"); | 402 | pr_debug("TX completed\n"); |
401 | 403 | ||
402 | return 0; | 404 | return 0; |
403 | } | 405 | } |
404 | 406 | ||
405 | /*! | 407 | /*! |
406 | * Camera V4l2 callback function. | 408 | * Camera V4l2 callback function. |
407 | * | 409 | * |
408 | * @param mask u32 | 410 | * @param mask u32 |
409 | * @param dev void device structure | 411 | * @param dev void device structure |
410 | * | 412 | * |
411 | * @return none | 413 | * @return none |
412 | */ | 414 | */ |
413 | static void camera_callback(u32 mask, void *dev) | 415 | static void camera_callback(u32 mask, void *dev) |
414 | { | 416 | { |
415 | struct mxc_v4l_frame *done_frame; | 417 | struct mxc_v4l_frame *done_frame; |
416 | struct mxc_v4l_frame *ready_frame; | 418 | struct mxc_v4l_frame *ready_frame; |
417 | cam_data *cam; | 419 | cam_data *cam; |
418 | 420 | ||
419 | cam = (cam_data *) dev; | 421 | cam = (cam_data *) dev; |
420 | if (cam == NULL) | 422 | if (cam == NULL) |
421 | return; | 423 | return; |
422 | 424 | ||
423 | spin_lock(&cam->queue_int_lock); | 425 | spin_lock(&cam->queue_int_lock); |
424 | spin_lock(&cam->dqueue_int_lock); | 426 | spin_lock(&cam->dqueue_int_lock); |
425 | if (!list_empty(&cam->working_q)) { | 427 | if (!list_empty(&cam->working_q)) { |
426 | done_frame = list_entry(cam->working_q.next, | 428 | done_frame = list_entry(cam->working_q.next, |
427 | struct mxc_v4l_frame, queue); | 429 | struct mxc_v4l_frame, queue); |
428 | 430 | ||
429 | if (done_frame->csi_buf_num != cam->ping_pong_csi) | 431 | if (done_frame->csi_buf_num != cam->ping_pong_csi) |
430 | goto next; | 432 | goto next; |
431 | 433 | ||
432 | if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { | 434 | if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { |
433 | done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE; | 435 | done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE; |
434 | done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; | 436 | done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; |
435 | 437 | ||
436 | /* Added to the done queue */ | 438 | /* Added to the done queue */ |
437 | list_del(cam->working_q.next); | 439 | list_del(cam->working_q.next); |
438 | list_add_tail(&done_frame->queue, &cam->done_q); | 440 | list_add_tail(&done_frame->queue, &cam->done_q); |
439 | cam->enc_counter++; | 441 | cam->enc_counter++; |
440 | wake_up_interruptible(&cam->enc_queue); | 442 | wake_up_interruptible(&cam->enc_queue); |
441 | } else { | 443 | } else { |
442 | pr_err("ERROR: v4l2 capture: %s: " | 444 | pr_err("ERROR: v4l2 capture: %s: " |
443 | "buffer not queued\n", __func__); | 445 | "buffer not queued\n", __func__); |
444 | } | 446 | } |
445 | } | 447 | } |
446 | 448 | ||
447 | next: | 449 | next: |
448 | if (!list_empty(&cam->ready_q)) { | 450 | if (!list_empty(&cam->ready_q)) { |
449 | ready_frame = list_entry(cam->ready_q.next, | 451 | ready_frame = list_entry(cam->ready_q.next, |
450 | struct mxc_v4l_frame, queue); | 452 | struct mxc_v4l_frame, queue); |
451 | list_del(cam->ready_q.next); | 453 | list_del(cam->ready_q.next); |
452 | list_add_tail(&ready_frame->queue, &cam->working_q); | 454 | list_add_tail(&ready_frame->queue, &cam->working_q); |
453 | 455 | ||
454 | csi_write(cam->csi_soc, ready_frame->paddress, | 456 | csi_write(cam->csi_soc, ready_frame->paddress, |
455 | cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 : | 457 | cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 : |
456 | CSI_CSIDMASA_FB2); | 458 | CSI_CSIDMASA_FB2); |
457 | ready_frame->csi_buf_num = cam->ping_pong_csi; | 459 | ready_frame->csi_buf_num = cam->ping_pong_csi; |
458 | } else { | 460 | } else { |
459 | csi_write(cam->csi_soc, cam->dummy_frame.paddress, | 461 | csi_write(cam->csi_soc, cam->dummy_frame.paddress, |
460 | cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 : | 462 | cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 : |
461 | CSI_CSIDMASA_FB2); | 463 | CSI_CSIDMASA_FB2); |
462 | } | 464 | } |
463 | spin_unlock(&cam->dqueue_int_lock); | 465 | spin_unlock(&cam->dqueue_int_lock); |
464 | spin_unlock(&cam->queue_int_lock); | 466 | spin_unlock(&cam->queue_int_lock); |
465 | 467 | ||
466 | return; | 468 | return; |
467 | } | 469 | } |
468 | 470 | ||
469 | /*! | 471 | /*! |
470 | * Make csi ready for capture image. | 472 | * Make csi ready for capture image. |
471 | * | 473 | * |
472 | * @param cam structure cam_data * | 474 | * @param cam structure cam_data * |
473 | * | 475 | * |
474 | * @return status 0 success | 476 | * @return status 0 success |
475 | */ | 477 | */ |
476 | static int csi_cap_image(cam_data *cam) | 478 | static int csi_cap_image(cam_data *cam) |
477 | { | 479 | { |
478 | unsigned int value; | 480 | unsigned int value; |
479 | 481 | ||
480 | value = csi_read(cam->csi_soc, CSI_CSICR3); | 482 | value = csi_read(cam->csi_soc, CSI_CSICR3); |
481 | csi_write(cam->csi_soc, value | BIT_FRMCNT_RST, CSI_CSICR3); | 483 | csi_write(cam->csi_soc, value | BIT_FRMCNT_RST, CSI_CSICR3); |
482 | value = csi_read(cam->csi_soc, CSI_CSISR); | 484 | value = csi_read(cam->csi_soc, CSI_CSISR); |
483 | csi_write(cam->csi_soc, value, CSI_CSISR); | 485 | csi_write(cam->csi_soc, value, CSI_CSISR); |
484 | 486 | ||
485 | return 0; | 487 | return 0; |
486 | } | 488 | } |
487 | 489 | ||
488 | /*************************************************************************** | 490 | /*************************************************************************** |
489 | * Functions for handling Frame buffers. | 491 | * Functions for handling Frame buffers. |
490 | **************************************************************************/ | 492 | **************************************************************************/ |
491 | 493 | ||
492 | /*! | 494 | /*! |
493 | * Free frame buffers | 495 | * Free frame buffers |
494 | * | 496 | * |
495 | * @param cam Structure cam_data * | 497 | * @param cam Structure cam_data * |
496 | * | 498 | * |
497 | * @return status 0 success. | 499 | * @return status 0 success. |
498 | */ | 500 | */ |
499 | static int csi_free_frame_buf(cam_data *cam) | 501 | static int csi_free_frame_buf(cam_data *cam) |
500 | { | 502 | { |
501 | int i; | 503 | int i; |
502 | 504 | ||
503 | pr_debug("MVC: In %s\n", __func__); | 505 | pr_debug("MVC: In %s\n", __func__); |
504 | 506 | ||
505 | for (i = 0; i < FRAME_NUM; i++) { | 507 | for (i = 0; i < FRAME_NUM; i++) { |
506 | if (cam->frame[i].vaddress != 0) { | 508 | if (cam->frame[i].vaddress != 0) { |
507 | dma_free_coherent(0, cam->frame[i].buffer.length, | 509 | dma_free_coherent(0, cam->frame[i].buffer.length, |
508 | cam->frame[i].vaddress, | 510 | cam->frame[i].vaddress, |
509 | cam->frame[i].paddress); | 511 | cam->frame[i].paddress); |
510 | cam->frame[i].vaddress = 0; | 512 | cam->frame[i].vaddress = 0; |
511 | } | 513 | } |
512 | } | 514 | } |
513 | 515 | ||
514 | if (cam->dummy_frame.vaddress != 0) { | 516 | if (cam->dummy_frame.vaddress != 0) { |
515 | dma_free_coherent(0, cam->dummy_frame.buffer.length, | 517 | dma_free_coherent(0, cam->dummy_frame.buffer.length, |
516 | cam->dummy_frame.vaddress, | 518 | cam->dummy_frame.vaddress, |
517 | cam->dummy_frame.paddress); | 519 | cam->dummy_frame.paddress); |
518 | cam->dummy_frame.vaddress = 0; | 520 | cam->dummy_frame.vaddress = 0; |
519 | } | 521 | } |
520 | 522 | ||
521 | return 0; | 523 | return 0; |
522 | } | 524 | } |
523 | 525 | ||
524 | /*! | 526 | /*! |
525 | * Allocate frame buffers | 527 | * Allocate frame buffers |
526 | * | 528 | * |
527 | * @param cam Structure cam_data * | 529 | * @param cam Structure cam_data * |
528 | * @param count int number of buffer need to allocated | 530 | * @param count int number of buffer need to allocated |
529 | * | 531 | * |
530 | * @return status -0 Successfully allocated a buffer, -ENOBUFS failed. | 532 | * @return status -0 Successfully allocated a buffer, -ENOBUFS failed. |
531 | */ | 533 | */ |
532 | static int csi_allocate_frame_buf(cam_data *cam, int count) | 534 | static int csi_allocate_frame_buf(cam_data *cam, int count) |
533 | { | 535 | { |
534 | int i; | 536 | int i; |
535 | 537 | ||
536 | pr_debug("In MVC:%s- size=%d\n", | 538 | pr_debug("In MVC:%s- size=%d\n", |
537 | __func__, cam->v2f.fmt.pix.sizeimage); | 539 | __func__, cam->v2f.fmt.pix.sizeimage); |
538 | for (i = 0; i < count; i++) { | 540 | for (i = 0; i < count; i++) { |
539 | cam->frame[i].vaddress = dma_alloc_coherent(0, PAGE_ALIGN | 541 | cam->frame[i].vaddress = dma_alloc_coherent(0, PAGE_ALIGN |
540 | (cam->v2f.fmt. | 542 | (cam->v2f.fmt. |
541 | pix.sizeimage), | 543 | pix.sizeimage), |
542 | &cam->frame[i]. | 544 | &cam->frame[i]. |
543 | paddress, | 545 | paddress, |
544 | GFP_DMA | | 546 | GFP_DMA | |
545 | GFP_KERNEL); | 547 | GFP_KERNEL); |
546 | if (cam->frame[i].vaddress == 0) { | 548 | if (cam->frame[i].vaddress == 0) { |
547 | pr_err("ERROR: v4l2 capture: " | 549 | pr_err("ERROR: v4l2 capture: " |
548 | "%s failed.\n", __func__); | 550 | "%s failed.\n", __func__); |
549 | csi_free_frame_buf(cam); | 551 | csi_free_frame_buf(cam); |
550 | return -ENOBUFS; | 552 | return -ENOBUFS; |
551 | } | 553 | } |
552 | cam->frame[i].buffer.index = i; | 554 | cam->frame[i].buffer.index = i; |
553 | cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; | 555 | cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; |
554 | cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 556 | cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
555 | cam->frame[i].buffer.length = cam->v2f.fmt.pix.sizeimage; | 557 | cam->frame[i].buffer.length = cam->v2f.fmt.pix.sizeimage; |
556 | cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP; | 558 | cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP; |
557 | cam->frame[i].buffer.m.offset = cam->frame[i].paddress; | 559 | cam->frame[i].buffer.m.offset = cam->frame[i].paddress; |
558 | cam->frame[i].index = i; | 560 | cam->frame[i].index = i; |
559 | cam->frame[i].csi_buf_num = 0; | 561 | cam->frame[i].csi_buf_num = 0; |
560 | } | 562 | } |
561 | 563 | ||
562 | return 0; | 564 | return 0; |
563 | } | 565 | } |
564 | 566 | ||
565 | /*! | 567 | /*! |
566 | * Free frame buffers status | 568 | * Free frame buffers status |
567 | * | 569 | * |
568 | * @param cam Structure cam_data * | 570 | * @param cam Structure cam_data * |
569 | * | 571 | * |
570 | * @return none | 572 | * @return none |
571 | */ | 573 | */ |
572 | static void csi_free_frames(cam_data *cam) | 574 | static void csi_free_frames(cam_data *cam) |
573 | { | 575 | { |
574 | int i; | 576 | int i; |
575 | 577 | ||
576 | pr_debug("In MVC: %s\n", __func__); | 578 | pr_debug("In MVC: %s\n", __func__); |
577 | 579 | ||
578 | for (i = 0; i < FRAME_NUM; i++) | 580 | for (i = 0; i < FRAME_NUM; i++) |
579 | cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; | 581 | cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; |
580 | 582 | ||
581 | cam->enc_counter = 0; | 583 | cam->enc_counter = 0; |
582 | INIT_LIST_HEAD(&cam->ready_q); | 584 | INIT_LIST_HEAD(&cam->ready_q); |
583 | INIT_LIST_HEAD(&cam->working_q); | 585 | INIT_LIST_HEAD(&cam->working_q); |
584 | INIT_LIST_HEAD(&cam->done_q); | 586 | INIT_LIST_HEAD(&cam->done_q); |
585 | 587 | ||
586 | return; | 588 | return; |
587 | } | 589 | } |
588 | 590 | ||
589 | /*! | 591 | /*! |
590 | * Return the buffer status | 592 | * Return the buffer status |
591 | * | 593 | * |
592 | * @param cam Structure cam_data * | 594 | * @param cam Structure cam_data * |
593 | * @param buf Structure v4l2_buffer * | 595 | * @param buf Structure v4l2_buffer * |
594 | * | 596 | * |
595 | * @return status 0 success, EINVAL failed. | 597 | * @return status 0 success, EINVAL failed. |
596 | */ | 598 | */ |
597 | static int csi_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf) | 599 | static int csi_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf) |
598 | { | 600 | { |
599 | pr_debug("In MVC: %s\n", __func__); | 601 | pr_debug("In MVC: %s\n", __func__); |
600 | 602 | ||
601 | if (buf->index < 0 || buf->index >= FRAME_NUM) { | 603 | if (buf->index < 0 || buf->index >= FRAME_NUM) { |
602 | pr_err("ERROR: v4l2 capture: %s buffers " | 604 | pr_err("ERROR: v4l2 capture: %s buffers " |
603 | "not allocated\n", __func__); | 605 | "not allocated\n", __func__); |
604 | return -EINVAL; | 606 | return -EINVAL; |
605 | } | 607 | } |
606 | 608 | ||
607 | memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf)); | 609 | memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf)); |
608 | 610 | ||
609 | return 0; | 611 | return 0; |
610 | } | 612 | } |
611 | 613 | ||
612 | static int csi_v4l2_release_bufs(cam_data *cam) | 614 | static int csi_v4l2_release_bufs(cam_data *cam) |
613 | { | 615 | { |
614 | pr_debug("In MVC:csi_v4l2_release_bufs\n"); | 616 | pr_debug("In MVC:csi_v4l2_release_bufs\n"); |
615 | return 0; | 617 | return 0; |
616 | } | 618 | } |
617 | 619 | ||
618 | static int csi_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf) | 620 | static int csi_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf) |
619 | { | 621 | { |
620 | pr_debug("In MVC:csi_v4l2_prepare_bufs\n"); | 622 | pr_debug("In MVC:csi_v4l2_prepare_bufs\n"); |
621 | 623 | ||
622 | if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length < | 624 | if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length < |
623 | cam->v2f.fmt.pix.sizeimage) { | 625 | cam->v2f.fmt.pix.sizeimage) { |
624 | pr_err("ERROR: v4l2 capture: csi_v4l2_prepare_bufs buffers " | 626 | pr_err("ERROR: v4l2 capture: csi_v4l2_prepare_bufs buffers " |
625 | "not allocated,index=%d, length=%d\n", buf->index, | 627 | "not allocated,index=%d, length=%d\n", buf->index, |
626 | buf->length); | 628 | buf->length); |
627 | return -EINVAL; | 629 | return -EINVAL; |
628 | } | 630 | } |
629 | 631 | ||
630 | cam->frame[buf->index].buffer.index = buf->index; | 632 | cam->frame[buf->index].buffer.index = buf->index; |
631 | cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED; | 633 | cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED; |
632 | cam->frame[buf->index].buffer.length = buf->length; | 634 | cam->frame[buf->index].buffer.length = buf->length; |
633 | cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress | 635 | cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress |
634 | = buf->m.offset; | 636 | = buf->m.offset; |
635 | cam->frame[buf->index].buffer.type = buf->type; | 637 | cam->frame[buf->index].buffer.type = buf->type; |
636 | cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR; | 638 | cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR; |
637 | cam->frame[buf->index].index = buf->index; | 639 | cam->frame[buf->index].index = buf->index; |
638 | 640 | ||
639 | return 0; | 641 | return 0; |
640 | } | 642 | } |
641 | 643 | ||
642 | /*! | 644 | /*! |
643 | * Indicates whether the palette is supported. | 645 | * Indicates whether the palette is supported. |
644 | * | 646 | * |
645 | * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_UYVY or V4L2_PIX_FMT_YUV420 | 647 | * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_UYVY or V4L2_PIX_FMT_YUV420 |
646 | * | 648 | * |
647 | * @return 0 if failed | 649 | * @return 0 if failed |
648 | */ | 650 | */ |
649 | static inline int valid_mode(u32 palette) | 651 | static inline int valid_mode(u32 palette) |
650 | { | 652 | { |
651 | return (palette == V4L2_PIX_FMT_RGB565) || | 653 | return (palette == V4L2_PIX_FMT_RGB565) || |
652 | (palette == V4L2_PIX_FMT_YUYV) || | 654 | (palette == V4L2_PIX_FMT_YUYV) || |
653 | (palette == V4L2_PIX_FMT_RGB32) || | 655 | (palette == V4L2_PIX_FMT_RGB32) || |
654 | (palette == V4L2_PIX_FMT_UYVY) || | 656 | (palette == V4L2_PIX_FMT_UYVY) || |
655 | (palette == V4L2_PIX_FMT_YUV444) || | 657 | (palette == V4L2_PIX_FMT_YUV444) || |
656 | (palette == V4L2_PIX_FMT_YUV420); | 658 | (palette == V4L2_PIX_FMT_YUV420); |
657 | } | 659 | } |
658 | 660 | ||
659 | /*! | 661 | /*! |
660 | * Start stream I/O | 662 | * Start stream I/O |
661 | * | 663 | * |
662 | * @param cam structure cam_data * | 664 | * @param cam structure cam_data * |
663 | * | 665 | * |
664 | * @return status 0 Success | 666 | * @return status 0 Success |
665 | */ | 667 | */ |
666 | static int csi_streamon(cam_data *cam) | 668 | static int csi_streamon(cam_data *cam) |
667 | { | 669 | { |
668 | struct mxc_v4l_frame *frame; | 670 | struct mxc_v4l_frame *frame; |
669 | unsigned long flags; | 671 | unsigned long flags; |
670 | unsigned long val; | 672 | unsigned long val; |
671 | int timeout, timeout2; | 673 | int timeout, timeout2; |
672 | 674 | ||
673 | pr_debug("In MVC: %s\n", __func__); | 675 | pr_debug("In MVC: %s\n", __func__); |
674 | 676 | ||
675 | if (NULL == cam) { | 677 | if (NULL == cam) { |
676 | pr_err("ERROR: v4l2 capture: %s cam parameter is NULL\n", | 678 | pr_err("ERROR: v4l2 capture: %s cam parameter is NULL\n", |
677 | __func__); | 679 | __func__); |
678 | return -1; | 680 | return -1; |
679 | } | 681 | } |
680 | cam->dummy_frame.vaddress = dma_alloc_coherent(0, | 682 | cam->dummy_frame.vaddress = dma_alloc_coherent(0, |
681 | PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), | 683 | PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), |
682 | &cam->dummy_frame.paddress, | 684 | &cam->dummy_frame.paddress, |
683 | GFP_DMA | GFP_KERNEL); | 685 | GFP_DMA | GFP_KERNEL); |
684 | if (cam->dummy_frame.vaddress == 0) { | 686 | if (cam->dummy_frame.vaddress == 0) { |
685 | pr_err("ERROR: v4l2 capture: Allocate dummy frame " | 687 | pr_err("ERROR: v4l2 capture: Allocate dummy frame " |
686 | "failed.\n"); | 688 | "failed.\n"); |
687 | return -ENOBUFS; | 689 | return -ENOBUFS; |
688 | } | 690 | } |
689 | cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE; | 691 | cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE; |
690 | cam->dummy_frame.buffer.length = cam->v2f.fmt.pix.sizeimage; | 692 | cam->dummy_frame.buffer.length = cam->v2f.fmt.pix.sizeimage; |
691 | cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress; | 693 | cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress; |
692 | 694 | ||
693 | spin_lock_irqsave(&cam->queue_int_lock, flags); | 695 | spin_lock_irqsave(&cam->queue_int_lock, flags); |
694 | /* move the frame from readyq to workingq */ | 696 | /* move the frame from readyq to workingq */ |
695 | if (list_empty(&cam->ready_q)) { | 697 | if (list_empty(&cam->ready_q)) { |
696 | pr_err("ERROR: v4l2 capture: %s: " | 698 | pr_err("ERROR: v4l2 capture: %s: " |
697 | "ready_q queue empty\n", __func__); | 699 | "ready_q queue empty\n", __func__); |
698 | spin_unlock_irqrestore(&cam->queue_int_lock, flags); | 700 | spin_unlock_irqrestore(&cam->queue_int_lock, flags); |
699 | return -1; | 701 | return -1; |
700 | } | 702 | } |
701 | frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); | 703 | frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); |
702 | list_del(cam->ready_q.next); | 704 | list_del(cam->ready_q.next); |
703 | list_add_tail(&frame->queue, &cam->working_q); | 705 | list_add_tail(&frame->queue, &cam->working_q); |
704 | csi_write(cam->csi_soc, frame->paddress, CSI_CSIDMASA_FB1); | 706 | csi_write(cam->csi_soc, frame->paddress, CSI_CSIDMASA_FB1); |
705 | frame->csi_buf_num = 1; | 707 | frame->csi_buf_num = 1; |
706 | 708 | ||
707 | if (list_empty(&cam->ready_q)) { | 709 | if (list_empty(&cam->ready_q)) { |
708 | pr_err("ERROR: v4l2 capture: %s: " | 710 | pr_err("ERROR: v4l2 capture: %s: " |
709 | "ready_q queue empty\n", __func__); | 711 | "ready_q queue empty\n", __func__); |
710 | spin_unlock_irqrestore(&cam->queue_int_lock, flags); | 712 | spin_unlock_irqrestore(&cam->queue_int_lock, flags); |
711 | return -1; | 713 | return -1; |
712 | } | 714 | } |
713 | frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); | 715 | frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); |
714 | list_del(cam->ready_q.next); | 716 | list_del(cam->ready_q.next); |
715 | list_add_tail(&frame->queue, &cam->working_q); | 717 | list_add_tail(&frame->queue, &cam->working_q); |
716 | csi_write(cam->csi_soc, frame->paddress, CSI_CSIDMASA_FB2); | 718 | csi_write(cam->csi_soc, frame->paddress, CSI_CSIDMASA_FB2); |
717 | frame->csi_buf_num = 2; | 719 | frame->csi_buf_num = 2; |
718 | spin_unlock_irqrestore(&cam->queue_int_lock, flags); | 720 | spin_unlock_irqrestore(&cam->queue_int_lock, flags); |
719 | 721 | ||
720 | cam->capture_pid = current->pid; | 722 | cam->capture_pid = current->pid; |
721 | cam->capture_on = true; | 723 | cam->capture_on = true; |
722 | csi_cap_image(cam); | 724 | csi_cap_image(cam); |
723 | 725 | ||
724 | local_irq_save(flags); | 726 | local_irq_save(flags); |
725 | for (timeout = 1000000; timeout > 0; timeout--) { | 727 | for (timeout = 1000000; timeout > 0; timeout--) { |
726 | if (csi_read(cam->csi_soc, CSI_CSISR) & BIT_SOF_INT) { | 728 | if (csi_read(cam->csi_soc, CSI_CSISR) & BIT_SOF_INT) { |
727 | val = csi_read(cam->csi_soc, CSI_CSICR3); | 729 | val = csi_read(cam->csi_soc, CSI_CSICR3); |
728 | csi_write(cam->csi_soc, val | BIT_DMA_REFLASH_RFF, | 730 | csi_write(cam->csi_soc, val | BIT_DMA_REFLASH_RFF, |
729 | CSI_CSICR3); | 731 | CSI_CSICR3); |
730 | /* Wait DMA reflash done */ | 732 | /* Wait DMA reflash done */ |
731 | for (timeout2 = 1000000; timeout2 > 0; timeout2--) { | 733 | for (timeout2 = 1000000; timeout2 > 0; timeout2--) { |
732 | if (csi_read(cam->csi_soc, CSI_CSICR3) & | 734 | if (csi_read(cam->csi_soc, CSI_CSICR3) & |
733 | BIT_DMA_REFLASH_RFF) | 735 | BIT_DMA_REFLASH_RFF) |
734 | cpu_relax(); | 736 | cpu_relax(); |
735 | else | 737 | else |
736 | break; | 738 | break; |
737 | } | 739 | } |
738 | if (timeout2 <= 0) { | 740 | if (timeout2 <= 0) { |
739 | pr_err("timeout when wait for reflash done.\n"); | 741 | pr_err("timeout when wait for reflash done.\n"); |
740 | local_irq_restore(flags); | 742 | local_irq_restore(flags); |
741 | return -ETIME; | 743 | return -ETIME; |
742 | } | 744 | } |
743 | 745 | ||
744 | csi_dmareq_rff_enable(cam->csi_soc); | 746 | csi_dmareq_rff_enable(cam->csi_soc); |
745 | csi_enable_int(cam, 1); | 747 | csi_enable_int(cam, 1); |
746 | csi_enable(cam, 1); | 748 | csi_enable(cam, 1); |
747 | break; | 749 | break; |
748 | } else | 750 | } else |
749 | cpu_relax(); | 751 | cpu_relax(); |
750 | } | 752 | } |
751 | if (timeout <= 0) { | 753 | if (timeout <= 0) { |
752 | pr_err("timeout when wait for SOF\n"); | 754 | pr_err("timeout when wait for SOF\n"); |
753 | local_irq_restore(flags); | 755 | local_irq_restore(flags); |
754 | return -ETIME; | 756 | return -ETIME; |
755 | } | 757 | } |
756 | local_irq_restore(flags); | 758 | local_irq_restore(flags); |
757 | 759 | ||
758 | return 0; | 760 | return 0; |
759 | } | 761 | } |
760 | 762 | ||
761 | /*! | 763 | /*! |
762 | * Stop stream I/O | 764 | * Stop stream I/O |
763 | * | 765 | * |
764 | * @param cam structure cam_data * | 766 | * @param cam structure cam_data * |
765 | * | 767 | * |
766 | * @return status 0 Success | 768 | * @return status 0 Success |
767 | */ | 769 | */ |
768 | static int csi_streamoff(cam_data *cam) | 770 | static int csi_streamoff(cam_data *cam) |
769 | { | 771 | { |
770 | pr_debug("In MVC: %s\n", __func__); | 772 | pr_debug("In MVC: %s\n", __func__); |
771 | 773 | ||
772 | if (cam->capture_on == false) | 774 | if (cam->capture_on == false) |
773 | return 0; | 775 | return 0; |
774 | 776 | ||
775 | csi_dmareq_rff_disable(cam->csi_soc); | 777 | csi_dmareq_rff_disable(cam->csi_soc); |
776 | csi_disable_int(cam); | 778 | csi_disable_int(cam); |
777 | cam->capture_on = false; | 779 | cam->capture_on = false; |
778 | 780 | ||
779 | /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */ | 781 | /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */ |
780 | csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB1); | 782 | csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB1); |
781 | csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB2); | 783 | csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB2); |
782 | 784 | ||
783 | if (strcmp(csi_capture_inputs[cam->current_input].name, | 785 | if (strcmp(csi_capture_inputs[cam->current_input].name, |
784 | "Vadc") == 0) { | 786 | "Vadc") == 0) { |
785 | csi_buf_stride_set(cam, 0); | 787 | csi_buf_stride_set(cam, 0); |
786 | csi_deinterlace_enable(cam, false); | 788 | csi_deinterlace_enable(cam, false); |
787 | csi_tvdec_enable(cam, false); | 789 | csi_tvdec_enable(cam, false); |
788 | } | 790 | } |
789 | csi_enable(cam, 0); | 791 | csi_enable(cam, 0); |
790 | 792 | ||
791 | csi_free_frames(cam); | 793 | csi_free_frames(cam); |
792 | csi_free_frame_buf(cam); | 794 | csi_free_frame_buf(cam); |
793 | 795 | ||
794 | return 0; | 796 | return 0; |
795 | } | 797 | } |
796 | 798 | ||
797 | /*! | 799 | /*! |
798 | * start the viewfinder job | 800 | * start the viewfinder job |
799 | * | 801 | * |
800 | * @param cam structure cam_data * | 802 | * @param cam structure cam_data * |
801 | * | 803 | * |
802 | * @return status 0 Success | 804 | * @return status 0 Success |
803 | */ | 805 | */ |
804 | static int start_preview(cam_data *cam) | 806 | static int start_preview(cam_data *cam) |
805 | { | 807 | { |
806 | unsigned long fb_addr = (unsigned long)cam->v4l2_fb.base; | 808 | unsigned long fb_addr = (unsigned long)cam->v4l2_fb.base; |
807 | 809 | ||
808 | csi_write(cam->csi_soc, fb_addr, CSI_CSIDMASA_FB1); | 810 | csi_write(cam->csi_soc, fb_addr, CSI_CSIDMASA_FB1); |
809 | csi_write(cam->csi_soc, fb_addr, CSI_CSIDMASA_FB2); | 811 | csi_write(cam->csi_soc, fb_addr, CSI_CSIDMASA_FB2); |
810 | csi_write(cam->csi_soc, | 812 | csi_write(cam->csi_soc, |
811 | csi_read(cam->csi_soc, CSI_CSICR3) | BIT_DMA_REFLASH_RFF, | 813 | csi_read(cam->csi_soc, CSI_CSICR3) | BIT_DMA_REFLASH_RFF, |
812 | CSI_CSICR3); | 814 | CSI_CSICR3); |
813 | 815 | ||
814 | csi_enable_int(cam, 0); | 816 | csi_enable_int(cam, 0); |
815 | 817 | ||
816 | return 0; | 818 | return 0; |
817 | } | 819 | } |
818 | 820 | ||
819 | /*! | 821 | /*! |
820 | * shut down the viewfinder job | 822 | * shut down the viewfinder job |
821 | * | 823 | * |
822 | * @param cam structure cam_data * | 824 | * @param cam structure cam_data * |
823 | * | 825 | * |
824 | * @return status 0 Success | 826 | * @return status 0 Success |
825 | */ | 827 | */ |
826 | static int stop_preview(cam_data *cam) | 828 | static int stop_preview(cam_data *cam) |
827 | { | 829 | { |
828 | csi_disable_int(cam); | 830 | csi_disable_int(cam); |
829 | 831 | ||
830 | /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */ | 832 | /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */ |
831 | csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB1); | 833 | csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB1); |
832 | csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB2); | 834 | csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB2); |
833 | csi_write(cam->csi_soc, | 835 | csi_write(cam->csi_soc, |
834 | csi_read(cam->csi_soc, CSI_CSICR3) | BIT_DMA_REFLASH_RFF, | 836 | csi_read(cam->csi_soc, CSI_CSICR3) | BIT_DMA_REFLASH_RFF, |
835 | CSI_CSICR3); | 837 | CSI_CSICR3); |
836 | 838 | ||
837 | return 0; | 839 | return 0; |
838 | } | 840 | } |
839 | 841 | ||
840 | /*************************************************************************** | 842 | /*************************************************************************** |
841 | * VIDIOC Functions. | 843 | * VIDIOC Functions. |
842 | **************************************************************************/ | 844 | **************************************************************************/ |
843 | 845 | ||
844 | /*! | 846 | /*! |
845 | * | 847 | * |
846 | * @param cam structure cam_data * | 848 | * @param cam structure cam_data * |
847 | * | 849 | * |
848 | * @param f structure v4l2_format * | 850 | * @param f structure v4l2_format * |
849 | * | 851 | * |
850 | * @return status 0 success, EINVAL failed | 852 | * @return status 0 success, EINVAL failed |
851 | */ | 853 | */ |
852 | static int csi_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f) | 854 | static int csi_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f) |
853 | { | 855 | { |
854 | int retval = 0; | 856 | int retval = 0; |
855 | 857 | ||
856 | switch (f->type) { | 858 | switch (f->type) { |
857 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 859 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
858 | pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); | 860 | pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); |
859 | f->fmt.pix = cam->v2f.fmt.pix; | 861 | f->fmt.pix = cam->v2f.fmt.pix; |
860 | break; | 862 | break; |
861 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 863 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
862 | pr_debug(" type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); | 864 | pr_debug(" type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); |
863 | f->fmt.win = cam->win; | 865 | f->fmt.win = cam->win; |
864 | break; | 866 | break; |
865 | default: | 867 | default: |
866 | pr_debug(" type is invalid\n"); | 868 | pr_debug(" type is invalid\n"); |
867 | retval = -EINVAL; | 869 | retval = -EINVAL; |
868 | } | 870 | } |
869 | 871 | ||
870 | pr_debug("End of %s: v2f pix widthxheight %d x %d\n", | 872 | pr_debug("End of %s: v2f pix widthxheight %d x %d\n", |
871 | __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); | 873 | __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); |
872 | 874 | ||
873 | return retval; | 875 | return retval; |
874 | } | 876 | } |
875 | 877 | ||
876 | /*! | 878 | /*! |
877 | * V4L2 - csi_v4l2_s_fmt function | 879 | * V4L2 - csi_v4l2_s_fmt function |
878 | * | 880 | * |
879 | * @param cam structure cam_data * | 881 | * @param cam structure cam_data * |
880 | * | 882 | * |
881 | * @param f structure v4l2_format * | 883 | * @param f structure v4l2_format * |
882 | * | 884 | * |
883 | * @return status 0 success, EINVAL failed | 885 | * @return status 0 success, EINVAL failed |
884 | */ | 886 | */ |
885 | static int csi_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f) | 887 | static int csi_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f) |
886 | { | 888 | { |
887 | int retval = 0; | 889 | int retval = 0; |
888 | int size = 0; | 890 | int size = 0; |
889 | int bytesperline = 0; | 891 | int bytesperline = 0; |
890 | int *width, *height; | 892 | int *width, *height; |
891 | 893 | ||
892 | pr_debug("In MVC: %s\n", __func__); | 894 | pr_debug("In MVC: %s\n", __func__); |
893 | 895 | ||
894 | switch (f->type) { | 896 | switch (f->type) { |
895 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 897 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
896 | pr_debug(" type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); | 898 | pr_debug(" type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); |
897 | if (!valid_mode(f->fmt.pix.pixelformat)) { | 899 | if (!valid_mode(f->fmt.pix.pixelformat)) { |
898 | pr_err("ERROR: v4l2 capture: %s: format " | 900 | pr_err("ERROR: v4l2 capture: %s: format " |
899 | "not supported\n", __func__); | 901 | "not supported\n", __func__); |
900 | return -EINVAL; | 902 | return -EINVAL; |
901 | } | 903 | } |
902 | 904 | ||
903 | /* Handle case where size requested is larger than current | 905 | /* Handle case where size requested is larger than current |
904 | * camera setting. */ | 906 | * camera setting. */ |
905 | if ((f->fmt.pix.width > cam->crop_bounds.width) | 907 | if ((f->fmt.pix.width > cam->crop_bounds.width) |
906 | || (f->fmt.pix.height > cam->crop_bounds.height)) { | 908 | || (f->fmt.pix.height > cam->crop_bounds.height)) { |
907 | /* Need the logic here, calling vidioc_s_param if | 909 | /* Need the logic here, calling vidioc_s_param if |
908 | * camera can change. */ | 910 | * camera can change. */ |
909 | pr_debug("csi_v4l2_s_fmt size changed\n"); | 911 | pr_debug("csi_v4l2_s_fmt size changed\n"); |
910 | } | 912 | } |
911 | if (cam->rotation % 180) { | 913 | if (cam->rotation % 180) { |
912 | height = &f->fmt.pix.width; | 914 | height = &f->fmt.pix.width; |
913 | width = &f->fmt.pix.height; | 915 | width = &f->fmt.pix.height; |
914 | } else { | 916 | } else { |
915 | width = &f->fmt.pix.width; | 917 | width = &f->fmt.pix.width; |
916 | height = &f->fmt.pix.height; | 918 | height = &f->fmt.pix.height; |
917 | } | 919 | } |
918 | 920 | ||
919 | if (*width == 0 || *height == 0) { | 921 | if (*width == 0 || *height == 0) { |
920 | pr_err("ERROR: csi v4l2 capture: width or height" | 922 | pr_err("ERROR: csi v4l2 capture: width or height" |
921 | " too small.\n"); | 923 | " too small.\n"); |
922 | return -EINVAL; | 924 | return -EINVAL; |
923 | } | 925 | } |
924 | 926 | ||
925 | if ((cam->crop_bounds.width / *width > 8) || | 927 | if ((cam->crop_bounds.width / *width > 8) || |
926 | ((cam->crop_bounds.width / *width == 8) && | 928 | ((cam->crop_bounds.width / *width == 8) && |
927 | (cam->crop_bounds.width % *width))) { | 929 | (cam->crop_bounds.width % *width))) { |
928 | *width = cam->crop_bounds.width / 8; | 930 | *width = cam->crop_bounds.width / 8; |
929 | if (*width % 8) | 931 | if (*width % 8) |
930 | *width += 8 - *width % 8; | 932 | *width += 8 - *width % 8; |
931 | pr_err("ERROR: v4l2 capture: width exceeds limit " | 933 | pr_err("ERROR: v4l2 capture: width exceeds limit " |
932 | "resize to %d.\n", *width); | 934 | "resize to %d.\n", *width); |
933 | } | 935 | } |
934 | 936 | ||
935 | if ((cam->crop_bounds.height / *height > 8) || | 937 | if ((cam->crop_bounds.height / *height > 8) || |
936 | ((cam->crop_bounds.height / *height == 8) && | 938 | ((cam->crop_bounds.height / *height == 8) && |
937 | (cam->crop_bounds.height % *height))) { | 939 | (cam->crop_bounds.height % *height))) { |
938 | *height = cam->crop_bounds.height / 8; | 940 | *height = cam->crop_bounds.height / 8; |
939 | if (*height % 8) | 941 | if (*height % 8) |
940 | *height += 8 - *height % 8; | 942 | *height += 8 - *height % 8; |
941 | pr_err("ERROR: v4l2 capture: height exceeds limit " | 943 | pr_err("ERROR: v4l2 capture: height exceeds limit " |
942 | "resize to %d.\n", *height); | 944 | "resize to %d.\n", *height); |
943 | } | 945 | } |
944 | 946 | ||
945 | /* disable swap function */ | 947 | /* disable swap function */ |
946 | csi_format_swap16(cam, false); | 948 | csi_format_swap16(cam, false); |
947 | cam->bswapenable = false; | 949 | cam->bswapenable = false; |
948 | 950 | ||
949 | switch (f->fmt.pix.pixelformat) { | 951 | switch (f->fmt.pix.pixelformat) { |
950 | case V4L2_PIX_FMT_RGB32: | 952 | case V4L2_PIX_FMT_RGB32: |
951 | size = f->fmt.pix.width * f->fmt.pix.height * 4; | 953 | size = f->fmt.pix.width * f->fmt.pix.height * 4; |
952 | bytesperline = f->fmt.pix.width * 4; | 954 | bytesperline = f->fmt.pix.width * 4; |
953 | break; | 955 | break; |
954 | case V4L2_PIX_FMT_RGB565: | 956 | case V4L2_PIX_FMT_RGB565: |
955 | size = f->fmt.pix.width * f->fmt.pix.height * 2; | 957 | size = f->fmt.pix.width * f->fmt.pix.height * 2; |
956 | bytesperline = f->fmt.pix.width * 2; | 958 | bytesperline = f->fmt.pix.width * 2; |
957 | break; | 959 | break; |
958 | case V4L2_PIX_FMT_YUV444: | 960 | case V4L2_PIX_FMT_YUV444: |
959 | size = f->fmt.pix.width * f->fmt.pix.height * 4; | 961 | size = f->fmt.pix.width * f->fmt.pix.height * 4; |
960 | bytesperline = f->fmt.pix.width * 4; | 962 | bytesperline = f->fmt.pix.width * 4; |
961 | break; | 963 | break; |
962 | case V4L2_PIX_FMT_UYVY: | 964 | case V4L2_PIX_FMT_UYVY: |
963 | size = f->fmt.pix.width * f->fmt.pix.height * 2; | 965 | size = f->fmt.pix.width * f->fmt.pix.height * 2; |
964 | bytesperline = f->fmt.pix.width * 2; | 966 | bytesperline = f->fmt.pix.width * 2; |
965 | if (cam->input_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) { | 967 | if (cam->input_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) { |
966 | csi_format_swap16(cam, true); | 968 | csi_format_swap16(cam, true); |
967 | cam->bswapenable = true; | 969 | cam->bswapenable = true; |
968 | } | 970 | } |
969 | break; | 971 | break; |
970 | case V4L2_PIX_FMT_YUYV: | 972 | case V4L2_PIX_FMT_YUYV: |
971 | size = f->fmt.pix.width * f->fmt.pix.height * 2; | 973 | size = f->fmt.pix.width * f->fmt.pix.height * 2; |
972 | bytesperline = f->fmt.pix.width * 2; | 974 | bytesperline = f->fmt.pix.width * 2; |
973 | if (cam->input_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) { | 975 | if (cam->input_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) { |
974 | csi_format_swap16(cam, true); | 976 | csi_format_swap16(cam, true); |
975 | cam->bswapenable = true; | 977 | cam->bswapenable = true; |
976 | } | 978 | } |
977 | break; | 979 | break; |
978 | case V4L2_PIX_FMT_YUV420: | 980 | case V4L2_PIX_FMT_YUV420: |
979 | size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; | 981 | size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; |
980 | bytesperline = f->fmt.pix.width; | 982 | bytesperline = f->fmt.pix.width; |
981 | break; | 983 | break; |
982 | case V4L2_PIX_FMT_YUV422P: | 984 | case V4L2_PIX_FMT_YUV422P: |
983 | case V4L2_PIX_FMT_RGB24: | 985 | case V4L2_PIX_FMT_RGB24: |
984 | case V4L2_PIX_FMT_BGR24: | 986 | case V4L2_PIX_FMT_BGR24: |
985 | case V4L2_PIX_FMT_BGR32: | 987 | case V4L2_PIX_FMT_BGR32: |
986 | case V4L2_PIX_FMT_NV12: | 988 | case V4L2_PIX_FMT_NV12: |
987 | default: | 989 | default: |
988 | pr_debug(" case not supported\n"); | 990 | pr_debug(" case not supported\n"); |
989 | break; | 991 | break; |
990 | } | 992 | } |
991 | 993 | ||
992 | if (f->fmt.pix.bytesperline < bytesperline) | 994 | if (f->fmt.pix.bytesperline < bytesperline) |
993 | f->fmt.pix.bytesperline = bytesperline; | 995 | f->fmt.pix.bytesperline = bytesperline; |
994 | else | 996 | else |
995 | bytesperline = f->fmt.pix.bytesperline; | 997 | bytesperline = f->fmt.pix.bytesperline; |
996 | 998 | ||
997 | if (f->fmt.pix.sizeimage < size) | 999 | if (f->fmt.pix.sizeimage < size) |
998 | f->fmt.pix.sizeimage = size; | 1000 | f->fmt.pix.sizeimage = size; |
999 | else | 1001 | else |
1000 | size = f->fmt.pix.sizeimage; | 1002 | size = f->fmt.pix.sizeimage; |
1001 | 1003 | ||
1002 | if (cam->input_fmt.fmt.pix.sizeimage > f->fmt.pix.sizeimage) | 1004 | if (cam->input_fmt.fmt.pix.sizeimage > f->fmt.pix.sizeimage) |
1003 | f->fmt.pix.sizeimage = cam->input_fmt.fmt.pix.sizeimage; | 1005 | f->fmt.pix.sizeimage = cam->input_fmt.fmt.pix.sizeimage; |
1004 | 1006 | ||
1005 | cam->v2f.fmt.pix = f->fmt.pix; | 1007 | cam->v2f.fmt.pix = f->fmt.pix; |
1006 | 1008 | ||
1007 | if (cam->v2f.fmt.pix.priv != 0) { | 1009 | if (cam->v2f.fmt.pix.priv != 0) { |
1008 | if (copy_from_user(&cam->offset, | 1010 | if (copy_from_user(&cam->offset, |
1009 | (void *)cam->v2f.fmt.pix.priv, | 1011 | (void *)cam->v2f.fmt.pix.priv, |
1010 | sizeof(cam->offset))) { | 1012 | sizeof(cam->offset))) { |
1011 | retval = -EFAULT; | 1013 | retval = -EFAULT; |
1012 | break; | 1014 | break; |
1013 | } | 1015 | } |
1014 | } | 1016 | } |
1015 | break; | 1017 | break; |
1016 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 1018 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
1017 | pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); | 1019 | pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); |
1018 | cam->win = f->fmt.win; | 1020 | cam->win = f->fmt.win; |
1019 | 1021 | ||
1020 | break; | 1022 | break; |
1021 | default: | 1023 | default: |
1022 | retval = -EINVAL; | 1024 | retval = -EINVAL; |
1023 | } | 1025 | } |
1024 | 1026 | ||
1025 | pr_debug("End of %s: v2f pix widthxheight %d x %d\n", | 1027 | pr_debug("End of %s: v2f pix widthxheight %d x %d\n", |
1026 | __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); | 1028 | __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); |
1027 | 1029 | ||
1028 | return retval; | 1030 | return retval; |
1029 | } | 1031 | } |
1030 | 1032 | ||
1031 | /*! | 1033 | /*! |
1032 | * V4L2 - csi_v4l2_s_param function | 1034 | * V4L2 - csi_v4l2_s_param function |
1033 | * Allows setting of capturemode and frame rate. | 1035 | * Allows setting of capturemode and frame rate. |
1034 | * | 1036 | * |
1035 | * @param cam structure cam_data * | 1037 | * @param cam structure cam_data * |
1036 | * @param parm structure v4l2_streamparm * | 1038 | * @param parm structure v4l2_streamparm * |
1037 | * | 1039 | * |
1038 | * @return status 0 success, EINVAL failed | 1040 | * @return status 0 success, EINVAL failed |
1039 | */ | 1041 | */ |
1040 | static int csi_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm) | 1042 | static int csi_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm) |
1041 | { | 1043 | { |
1042 | struct v4l2_ifparm ifparm; | 1044 | struct v4l2_ifparm ifparm; |
1043 | struct v4l2_format *f; | 1045 | struct v4l2_format *f; |
1044 | struct v4l2_streamparm currentparm; | 1046 | struct v4l2_streamparm currentparm; |
1045 | int err = 0; | 1047 | int err = 0; |
1046 | int size = 0; | 1048 | int size = 0; |
1047 | 1049 | ||
1048 | pr_debug("In %s\n", __func__); | 1050 | pr_debug("In %s\n", __func__); |
1049 | 1051 | ||
1050 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1052 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1051 | pr_err(KERN_ERR "%s invalid type\n", __func__); | 1053 | pr_err(KERN_ERR "%s invalid type\n", __func__); |
1052 | return -EINVAL; | 1054 | return -EINVAL; |
1053 | } | 1055 | } |
1054 | 1056 | ||
1055 | /* Stop the viewfinder */ | 1057 | /* Stop the viewfinder */ |
1056 | if (cam->overlay_on == true) | 1058 | if (cam->overlay_on == true) |
1057 | stop_preview(cam); | 1059 | stop_preview(cam); |
1058 | 1060 | ||
1059 | currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1061 | currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1060 | 1062 | ||
1061 | /* First check that this device can support the changes requested. */ | 1063 | /* First check that this device can support the changes requested. */ |
1062 | err = vidioc_int_g_parm(cam->sensor, ¤tparm); | 1064 | err = vidioc_int_g_parm(cam->sensor, ¤tparm); |
1063 | if (err) { | 1065 | if (err) { |
1064 | pr_err("%s: vidioc_int_g_parm returned an error %d\n", | 1066 | pr_err("%s: vidioc_int_g_parm returned an error %d\n", |
1065 | __func__, err); | 1067 | __func__, err); |
1066 | goto exit; | 1068 | goto exit; |
1067 | } | 1069 | } |
1068 | 1070 | ||
1069 | pr_debug(" Current capabilities are %x\n", | 1071 | pr_debug(" Current capabilities are %x\n", |
1070 | currentparm.parm.capture.capability); | 1072 | currentparm.parm.capture.capability); |
1071 | pr_debug(" Current capturemode is %d change to %d\n", | 1073 | pr_debug(" Current capturemode is %d change to %d\n", |
1072 | currentparm.parm.capture.capturemode, | 1074 | currentparm.parm.capture.capturemode, |
1073 | parm->parm.capture.capturemode); | 1075 | parm->parm.capture.capturemode); |
1074 | pr_debug(" Current framerate is %d change to %d\n", | 1076 | pr_debug(" Current framerate is %d change to %d\n", |
1075 | currentparm.parm.capture.timeperframe.denominator, | 1077 | currentparm.parm.capture.timeperframe.denominator, |
1076 | parm->parm.capture.timeperframe.denominator); | 1078 | parm->parm.capture.timeperframe.denominator); |
1077 | 1079 | ||
1078 | err = vidioc_int_s_parm(cam->sensor, parm); | 1080 | err = vidioc_int_s_parm(cam->sensor, parm); |
1079 | if (err) { | 1081 | if (err) { |
1080 | pr_err("%s: vidioc_int_s_parm returned an error %d\n", | 1082 | pr_err("%s: vidioc_int_s_parm returned an error %d\n", |
1081 | __func__, err); | 1083 | __func__, err); |
1082 | goto exit; | 1084 | goto exit; |
1083 | } | 1085 | } |
1084 | 1086 | ||
1085 | vidioc_int_g_ifparm(cam->sensor, &ifparm); | 1087 | vidioc_int_g_ifparm(cam->sensor, &ifparm); |
1086 | cam->input_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1088 | cam->input_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1087 | vidioc_int_g_fmt_cap(cam->sensor, &cam->input_fmt); | 1089 | vidioc_int_g_fmt_cap(cam->sensor, &cam->input_fmt); |
1088 | 1090 | ||
1089 | pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n", | 1091 | pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n", |
1090 | cam->input_fmt.fmt.pix.width, cam->input_fmt.fmt.pix.height); | 1092 | cam->input_fmt.fmt.pix.width, cam->input_fmt.fmt.pix.height); |
1091 | 1093 | ||
1092 | f = &cam->input_fmt; | 1094 | f = &cam->input_fmt; |
1093 | switch (f->fmt.pix.pixelformat) { | 1095 | switch (f->fmt.pix.pixelformat) { |
1094 | case V4L2_PIX_FMT_YUV444: | 1096 | case V4L2_PIX_FMT_YUV444: |
1095 | size = f->fmt.pix.width * f->fmt.pix.height * 4; | 1097 | size = f->fmt.pix.width * f->fmt.pix.height * 4; |
1096 | csi_set_32bit_imagpara(cam, | 1098 | csi_set_32bit_imagpara(cam, |
1097 | f->fmt.pix.width, | 1099 | f->fmt.pix.width, |
1098 | f->fmt.pix.height); | 1100 | f->fmt.pix.height); |
1099 | break; | 1101 | break; |
1100 | case V4L2_PIX_FMT_UYVY: | 1102 | case V4L2_PIX_FMT_UYVY: |
1101 | size = f->fmt.pix.width * f->fmt.pix.height * 2; | 1103 | size = f->fmt.pix.width * f->fmt.pix.height * 2; |
1102 | csi_set_16bit_imagpara(cam, | 1104 | csi_set_16bit_imagpara(cam, |
1103 | f->fmt.pix.width, | 1105 | f->fmt.pix.width, |
1104 | f->fmt.pix.height); | 1106 | f->fmt.pix.height); |
1105 | break; | 1107 | break; |
1106 | case V4L2_PIX_FMT_YUYV: | 1108 | case V4L2_PIX_FMT_YUYV: |
1107 | size = f->fmt.pix.width * f->fmt.pix.height * 2; | 1109 | size = f->fmt.pix.width * f->fmt.pix.height * 2; |
1108 | csi_set_16bit_imagpara(cam, | 1110 | csi_set_16bit_imagpara(cam, |
1109 | f->fmt.pix.width, | 1111 | f->fmt.pix.width, |
1110 | f->fmt.pix.height); | 1112 | f->fmt.pix.height); |
1111 | break; | 1113 | break; |
1112 | case V4L2_PIX_FMT_YUV420: | 1114 | case V4L2_PIX_FMT_YUV420: |
1113 | size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; | 1115 | size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; |
1114 | csi_set_12bit_imagpara(cam, | 1116 | csi_set_12bit_imagpara(cam, |
1115 | f->fmt.pix.width, | 1117 | f->fmt.pix.width, |
1116 | f->fmt.pix.height); | 1118 | f->fmt.pix.height); |
1117 | break; | 1119 | break; |
1118 | case V4L2_PIX_FMT_YUV422P: | 1120 | case V4L2_PIX_FMT_YUV422P: |
1119 | case V4L2_PIX_FMT_RGB24: | 1121 | case V4L2_PIX_FMT_RGB24: |
1120 | case V4L2_PIX_FMT_BGR24: | 1122 | case V4L2_PIX_FMT_BGR24: |
1121 | case V4L2_PIX_FMT_BGR32: | 1123 | case V4L2_PIX_FMT_BGR32: |
1122 | case V4L2_PIX_FMT_RGB32: | 1124 | case V4L2_PIX_FMT_RGB32: |
1123 | case V4L2_PIX_FMT_NV12: | 1125 | case V4L2_PIX_FMT_NV12: |
1124 | default: | 1126 | default: |
1125 | pr_debug(" case not supported\n"); | 1127 | pr_debug(" case not supported\n"); |
1126 | return -EINVAL; | 1128 | return -EINVAL; |
1127 | } | 1129 | } |
1128 | f->fmt.pix.sizeimage = size; | 1130 | f->fmt.pix.sizeimage = size; |
1129 | 1131 | ||
1130 | cam->crop_bounds.top = cam->crop_bounds.left = 0; | 1132 | cam->crop_bounds.top = cam->crop_bounds.left = 0; |
1131 | cam->crop_bounds.width = cam->input_fmt.fmt.pix.width; | 1133 | cam->crop_bounds.width = cam->input_fmt.fmt.pix.width; |
1132 | cam->crop_bounds.height = cam->input_fmt.fmt.pix.height; | 1134 | cam->crop_bounds.height = cam->input_fmt.fmt.pix.height; |
1133 | cam->crop_current.width = cam->crop_bounds.width; | 1135 | cam->crop_current.width = cam->crop_bounds.width; |
1134 | cam->crop_current.height = cam->crop_bounds.height; | 1136 | cam->crop_current.height = cam->crop_bounds.height; |
1135 | 1137 | ||
1136 | exit: | 1138 | exit: |
1137 | return err; | 1139 | return err; |
1138 | } | 1140 | } |
1139 | 1141 | ||
1140 | static int pxp_set_cstate(cam_data *cam, struct v4l2_control *vc) | 1142 | static int pxp_set_cstate(cam_data *cam, struct v4l2_control *vc) |
1141 | { | 1143 | { |
1142 | struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; | 1144 | struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; |
1143 | 1145 | ||
1144 | if (vc->id == V4L2_CID_HFLIP) { | 1146 | if (vc->id == V4L2_CID_HFLIP) { |
1145 | proc_data->hflip = vc->value; | 1147 | proc_data->hflip = vc->value; |
1146 | } else if (vc->id == V4L2_CID_VFLIP) { | 1148 | } else if (vc->id == V4L2_CID_VFLIP) { |
1147 | proc_data->vflip = vc->value; | 1149 | proc_data->vflip = vc->value; |
1148 | } else if (vc->id == V4L2_CID_PRIVATE_BASE) { | 1150 | } else if (vc->id == V4L2_CID_PRIVATE_BASE) { |
1149 | if (vc->value % 90) | 1151 | if (vc->value % 90) |
1150 | return -ERANGE; | 1152 | return -ERANGE; |
1151 | proc_data->rotate = vc->value; | 1153 | proc_data->rotate = vc->value; |
1152 | cam->rotation = vc->value; | 1154 | cam->rotation = vc->value; |
1153 | } | 1155 | } |
1154 | 1156 | ||
1155 | return 0; | 1157 | return 0; |
1156 | } | 1158 | } |
1157 | 1159 | ||
1158 | static int pxp_get_cstate(cam_data *cam, struct v4l2_control *vc) | 1160 | static int pxp_get_cstate(cam_data *cam, struct v4l2_control *vc) |
1159 | { | 1161 | { |
1160 | struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; | 1162 | struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; |
1161 | 1163 | ||
1162 | if (vc->id == V4L2_CID_HFLIP) | 1164 | if (vc->id == V4L2_CID_HFLIP) |
1163 | vc->value = proc_data->hflip; | 1165 | vc->value = proc_data->hflip; |
1164 | else if (vc->id == V4L2_CID_VFLIP) | 1166 | else if (vc->id == V4L2_CID_VFLIP) |
1165 | vc->value = proc_data->vflip; | 1167 | vc->value = proc_data->vflip; |
1166 | else if (vc->id == V4L2_CID_PRIVATE_BASE) | 1168 | else if (vc->id == V4L2_CID_PRIVATE_BASE) |
1167 | vc->value = proc_data->rotate; | 1169 | vc->value = proc_data->rotate; |
1168 | 1170 | ||
1169 | return 0; | 1171 | return 0; |
1170 | } | 1172 | } |
1171 | 1173 | ||
1172 | /*! | 1174 | /*! |
1173 | * V4L2 - csi_v4l_s_std function | 1175 | * V4L2 - csi_v4l_s_std function |
1174 | * | 1176 | * |
1175 | * Sets the TV standard to be used. | 1177 | * Sets the TV standard to be used. |
1176 | * | 1178 | * |
1177 | * @param cam structure cam_data * | 1179 | * @param cam structure cam_data * |
1178 | * @param parm structure v4l2_std_id * | 1180 | * @param parm structure v4l2_std_id * |
1179 | * | 1181 | * |
1180 | * @return status 0 success, -EINVAL failed | 1182 | * @return status 0 success, -EINVAL failed |
1181 | */ | 1183 | */ |
1182 | static int csi_v4l_s_std(cam_data *cam, v4l2_std_id e) | 1184 | static int csi_v4l_s_std(cam_data *cam, v4l2_std_id e) |
1183 | { | 1185 | { |
1184 | pr_debug("In csi_v4l2_s_std %Lx\n", e); | 1186 | pr_debug("In csi_v4l2_s_std %Lx\n", e); |
1185 | 1187 | ||
1186 | if (e == V4L2_STD_PAL) { | 1188 | if (e == V4L2_STD_PAL) { |
1187 | pr_debug(" Setting standard to PAL %Lx\n", V4L2_STD_PAL); | 1189 | pr_debug(" Setting standard to PAL %Lx\n", V4L2_STD_PAL); |
1188 | cam->standard.id = V4L2_STD_PAL; | 1190 | cam->standard.id = V4L2_STD_PAL; |
1189 | video_index = TV_PAL; | 1191 | video_index = TV_PAL; |
1190 | } else if (e == V4L2_STD_NTSC) { | 1192 | } else if (e == V4L2_STD_NTSC) { |
1191 | pr_debug(" Setting standard to NTSC %Lx\n", | 1193 | pr_debug(" Setting standard to NTSC %Lx\n", |
1192 | V4L2_STD_NTSC); | 1194 | V4L2_STD_NTSC); |
1193 | /* Get rid of the white dot line in NTSC signal input */ | 1195 | /* Get rid of the white dot line in NTSC signal input */ |
1194 | cam->standard.id = V4L2_STD_NTSC; | 1196 | cam->standard.id = V4L2_STD_NTSC; |
1195 | video_index = TV_NTSC; | 1197 | video_index = TV_NTSC; |
1196 | } else { | 1198 | } else { |
1197 | cam->standard.id = V4L2_STD_ALL; | 1199 | cam->standard.id = V4L2_STD_ALL; |
1198 | video_index = TV_NOT_LOCKED; | 1200 | video_index = TV_NOT_LOCKED; |
1199 | pr_err("ERROR: unrecognized std! %Lx (PAL=%Lx, NTSC=%Lx\n", | 1201 | pr_err("ERROR: unrecognized std! %Lx (PAL=%Lx, NTSC=%Lx\n", |
1200 | e, V4L2_STD_PAL, V4L2_STD_NTSC); | 1202 | e, V4L2_STD_PAL, V4L2_STD_NTSC); |
1201 | } | 1203 | } |
1202 | 1204 | ||
1203 | cam->standard.index = video_index; | 1205 | cam->standard.index = video_index; |
1204 | strcpy(cam->standard.name, video_fmts[video_index].name); | 1206 | strcpy(cam->standard.name, video_fmts[video_index].name); |
1205 | 1207 | ||
1206 | /* Enable csi PAL/NTSC deinterlace mode */ | 1208 | /* Enable csi PAL/NTSC deinterlace mode */ |
1207 | csi_buf_stride_set(cam, video_fmts[video_index].active_width); | 1209 | csi_buf_stride_set(cam, video_fmts[video_index].active_width); |
1208 | csi_deinterlace_mode(cam, cam->standard.id); | 1210 | csi_deinterlace_mode(cam, cam->standard.id); |
1209 | csi_deinterlace_enable(cam, true); | 1211 | csi_deinterlace_enable(cam, true); |
1210 | 1212 | ||
1211 | /* crop will overwrite */ | 1213 | /* crop will overwrite */ |
1212 | cam->crop_bounds.width = video_fmts[video_index].active_width; | 1214 | cam->crop_bounds.width = video_fmts[video_index].active_width; |
1213 | cam->crop_bounds.height = video_fmts[video_index].active_height; | 1215 | cam->crop_bounds.height = video_fmts[video_index].active_height; |
1214 | cam->crop_current.width = video_fmts[video_index].active_width; | 1216 | cam->crop_current.width = video_fmts[video_index].active_width; |
1215 | cam->crop_current.height = video_fmts[video_index].active_height; | 1217 | cam->crop_current.height = video_fmts[video_index].active_height; |
1216 | cam->crop_current.top = video_fmts[video_index].active_top; | 1218 | cam->crop_current.top = video_fmts[video_index].active_top; |
1217 | cam->crop_current.left = video_fmts[video_index].active_left; | 1219 | cam->crop_current.left = video_fmts[video_index].active_left; |
1218 | 1220 | ||
1219 | return 0; | 1221 | return 0; |
1220 | } | 1222 | } |
1221 | 1223 | ||
1222 | /*! | 1224 | /*! |
1223 | * V4L2 - csi_v4l_g_std function | 1225 | * V4L2 - csi_v4l_g_std function |
1224 | * | 1226 | * |
1225 | * Gets the TV standard from the TV input device. | 1227 | * Gets the TV standard from the TV input device. |
1226 | * | 1228 | * |
1227 | * @param cam structure cam_data * | 1229 | * @param cam structure cam_data * |
1228 | * | 1230 | * |
1229 | * @param e structure v4l2_std_id * | 1231 | * @param e structure v4l2_std_id * |
1230 | * | 1232 | * |
1231 | * @return status 0 success, -EINVAL failed | 1233 | * @return status 0 success, -EINVAL failed |
1232 | */ | 1234 | */ |
1233 | static int csi_v4l_g_std(cam_data *cam, v4l2_std_id *e) | 1235 | static int csi_v4l_g_std(cam_data *cam, v4l2_std_id *e) |
1234 | { | 1236 | { |
1235 | struct v4l2_format tv_fmt; | 1237 | struct v4l2_format tv_fmt; |
1236 | 1238 | ||
1237 | pr_debug("In csi_v4l2_g_std, cam->csi %d\n", cam->csi); | 1239 | pr_debug("In csi_v4l2_g_std, cam->csi %d\n", cam->csi); |
1238 | 1240 | ||
1239 | if (cam->device_type == 1) { | 1241 | if (cam->device_type == 1) { |
1240 | /* Use this function to get what the TV-In device detects the | 1242 | /* Use this function to get what the TV-In device detects the |
1241 | * format to be. pixelformat is used to return the std value | 1243 | * format to be. pixelformat is used to return the std value |
1242 | * since the interface has no vidioc_g_std.*/ | 1244 | * since the interface has no vidioc_g_std.*/ |
1243 | tv_fmt.type = V4L2_BUF_TYPE_PRIVATE; | 1245 | tv_fmt.type = V4L2_BUF_TYPE_PRIVATE; |
1244 | vidioc_int_g_fmt_cap(cam->sensor, &tv_fmt); | 1246 | vidioc_int_g_fmt_cap(cam->sensor, &tv_fmt); |
1245 | 1247 | ||
1246 | /* If the TV-in automatically detects the standard, then if it | 1248 | /* If the TV-in automatically detects the standard, then if it |
1247 | * changes, the settings need to change. */ | 1249 | * changes, the settings need to change. */ |
1248 | if (cam->standard_autodetect) { | 1250 | if (cam->standard_autodetect) { |
1249 | if (cam->standard.id != tv_fmt.fmt.pix.pixelformat) { | 1251 | if (cam->standard.id != tv_fmt.fmt.pix.pixelformat) { |
1250 | pr_debug("csi_v4l2_g_std: " | 1252 | pr_debug("csi_v4l2_g_std: " |
1251 | "Changing standard\n"); | 1253 | "Changing standard\n"); |
1252 | csi_v4l_s_std(cam, tv_fmt.fmt.pix.pixelformat); | 1254 | csi_v4l_s_std(cam, tv_fmt.fmt.pix.pixelformat); |
1253 | } | 1255 | } |
1254 | } | 1256 | } |
1255 | 1257 | ||
1256 | *e = tv_fmt.fmt.pix.pixelformat; | 1258 | *e = tv_fmt.fmt.pix.pixelformat; |
1257 | } | 1259 | } |
1258 | 1260 | ||
1259 | return 0; | 1261 | return 0; |
1260 | } | 1262 | } |
1261 | 1263 | ||
1262 | static void csi_input_select(cam_data *cam) | 1264 | static void csi_input_select(cam_data *cam) |
1263 | { | 1265 | { |
1264 | if (strcmp(csi_capture_inputs[cam->current_input].name, "Vadc") == 0) | 1266 | if (strcmp(csi_capture_inputs[cam->current_input].name, "Vadc") == 0) |
1265 | /* Enable csi tvdec */ | 1267 | /* Enable csi tvdec */ |
1266 | csi_tvdec_enable(cam, true); | 1268 | csi_tvdec_enable(cam, true); |
1267 | else | 1269 | else |
1268 | csi_tvdec_enable(cam, false); | 1270 | csi_tvdec_enable(cam, false); |
1269 | } | 1271 | } |
1270 | 1272 | ||
1271 | /*! | 1273 | /*! |
1272 | * Dequeue one V4L capture buffer | 1274 | * Dequeue one V4L capture buffer |
1273 | * | 1275 | * |
1274 | * @param cam structure cam_data * | 1276 | * @param cam structure cam_data * |
1275 | * @param buf structure v4l2_buffer * | 1277 | * @param buf structure v4l2_buffer * |
1276 | * | 1278 | * |
1277 | * @return status 0 success, EINVAL invalid frame number | 1279 | * @return status 0 success, EINVAL invalid frame number |
1278 | * ETIME timeout, ERESTARTSYS interrupted by user | 1280 | * ETIME timeout, ERESTARTSYS interrupted by user |
1279 | */ | 1281 | */ |
1280 | static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) | 1282 | static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) |
1281 | { | 1283 | { |
1282 | int retval = 0; | 1284 | int retval = 0; |
1283 | struct mxc_v4l_frame *frame; | 1285 | struct mxc_v4l_frame *frame; |
1284 | unsigned long lock_flags; | 1286 | unsigned long lock_flags; |
1285 | 1287 | ||
1286 | if (!wait_event_interruptible_timeout(cam->enc_queue, | 1288 | if (!wait_event_interruptible_timeout(cam->enc_queue, |
1287 | cam->enc_counter != 0, 10 * HZ)) { | 1289 | cam->enc_counter != 0, 10 * HZ)) { |
1288 | pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout " | 1290 | pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout " |
1289 | "enc_counter %x\n", cam->enc_counter); | 1291 | "enc_counter %x\n", cam->enc_counter); |
1290 | return -ETIME; | 1292 | return -ETIME; |
1291 | } else if (signal_pending(current)) { | 1293 | } else if (signal_pending(current)) { |
1292 | pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() " | 1294 | pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() " |
1293 | "interrupt received\n"); | 1295 | "interrupt received\n"); |
1294 | return -ERESTARTSYS; | 1296 | return -ERESTARTSYS; |
1295 | } | 1297 | } |
1296 | 1298 | ||
1297 | if (down_interruptible(&cam->busy_lock)) | 1299 | if (down_interruptible(&cam->busy_lock)) |
1298 | return -EBUSY; | 1300 | return -EBUSY; |
1299 | 1301 | ||
1300 | spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags); | 1302 | spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags); |
1301 | 1303 | ||
1302 | if (list_empty(&cam->done_q)) { | 1304 | if (list_empty(&cam->done_q)) { |
1303 | spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); | 1305 | spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); |
1304 | up(&cam->busy_lock); | 1306 | up(&cam->busy_lock); |
1305 | return -EINVAL; | 1307 | return -EINVAL; |
1306 | } | 1308 | } |
1307 | 1309 | ||
1308 | cam->enc_counter--; | 1310 | cam->enc_counter--; |
1309 | 1311 | ||
1310 | frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); | 1312 | frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); |
1311 | list_del(cam->done_q.next); | 1313 | list_del(cam->done_q.next); |
1312 | 1314 | ||
1313 | if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) { | 1315 | if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) { |
1314 | frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE; | 1316 | frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE; |
1315 | } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { | 1317 | } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { |
1316 | pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " | 1318 | pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " |
1317 | "Buffer not filled.\n"); | 1319 | "Buffer not filled.\n"); |
1318 | frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; | 1320 | frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; |
1319 | retval = -EINVAL; | 1321 | retval = -EINVAL; |
1320 | } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) { | 1322 | } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) { |
1321 | pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " | 1323 | pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " |
1322 | "Buffer not queued.\n"); | 1324 | "Buffer not queued.\n"); |
1323 | retval = -EINVAL; | 1325 | retval = -EINVAL; |
1324 | } | 1326 | } |
1325 | 1327 | ||
1326 | spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); | 1328 | spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); |
1327 | 1329 | ||
1328 | buf->bytesused = cam->v2f.fmt.pix.sizeimage; | 1330 | buf->bytesused = cam->v2f.fmt.pix.sizeimage; |
1329 | buf->index = frame->index; | 1331 | buf->index = frame->index; |
1330 | buf->flags = frame->buffer.flags; | 1332 | buf->flags = frame->buffer.flags; |
1331 | buf->m = cam->frame[frame->index].buffer.m; | 1333 | buf->m = cam->frame[frame->index].buffer.m; |
1332 | 1334 | ||
1333 | /* | 1335 | /* |
1334 | * Note: | 1336 | * Note: |
1335 | * If want to do preview on LCD, use PxP CSC to convert from UYVY | 1337 | * If want to do preview on LCD, use PxP CSC to convert from UYVY |
1336 | * to RGB565; but for encoding, usually we don't use RGB format. | 1338 | * to RGB565; but for encoding, usually we don't use RGB format. |
1337 | */ | 1339 | */ |
1338 | if (cam->v2f.fmt.pix.pixelformat != cam->input_fmt.fmt.pix.pixelformat | 1340 | if (cam->v2f.fmt.pix.pixelformat != cam->input_fmt.fmt.pix.pixelformat |
1339 | && !cam->bswapenable) { | 1341 | && !cam->bswapenable) { |
1340 | sg_dma_address(&cam->sg[0]) = buf->m.offset; | 1342 | sg_dma_address(&cam->sg[0]) = buf->m.offset; |
1341 | /* last frame buffer as pxp output buffer */ | 1343 | /* last frame buffer as pxp output buffer */ |
1342 | sg_dma_address(&cam->sg[1]) = | 1344 | sg_dma_address(&cam->sg[1]) = |
1343 | cam->frame[req_buf_number].paddress; | 1345 | cam->frame[req_buf_number].paddress; |
1344 | retval = pxp_process_update(cam); | 1346 | retval = pxp_process_update(cam); |
1345 | if (retval) { | 1347 | if (retval) { |
1346 | pr_err("Unable to submit PxP update task.\n"); | 1348 | pr_err("Unable to submit PxP update task.\n"); |
1347 | return retval; | 1349 | return retval; |
1348 | } | 1350 | } |
1349 | pxp_complete_update(cam); | 1351 | pxp_complete_update(cam); |
1350 | /* Copy data from pxp output buffer to original buffer | 1352 | /* Copy data from pxp output buffer to original buffer |
1351 | * Need optimization */ | 1353 | * Need optimization */ |
1352 | if (cam->frame[buf->index].vaddress) | 1354 | if (cam->frame[buf->index].vaddress) |
1353 | memcpy(cam->frame[buf->index].vaddress, | 1355 | memcpy(cam->frame[buf->index].vaddress, |
1354 | cam->frame[req_buf_number].vaddress, | 1356 | cam->frame[req_buf_number].vaddress, |
1355 | cam->v2f.fmt.pix.sizeimage); | 1357 | cam->v2f.fmt.pix.sizeimage); |
1356 | } | 1358 | } |
1357 | 1359 | ||
1358 | up(&cam->busy_lock); | 1360 | up(&cam->busy_lock); |
1359 | 1361 | ||
1360 | return retval; | 1362 | return retval; |
1361 | } | 1363 | } |
1362 | 1364 | ||
1363 | /*! | 1365 | /*! |
1364 | * V4L interface - open function | 1366 | * V4L interface - open function |
1365 | * | 1367 | * |
1366 | * @param file structure file * | 1368 | * @param file structure file * |
1367 | * | 1369 | * |
1368 | * @return status 0 success, ENODEV invalid device instance, | 1370 | * @return status 0 success, ENODEV invalid device instance, |
1369 | * ENODEV timeout, ERESTARTSYS interrupted by user | 1371 | * ENODEV timeout, ERESTARTSYS interrupted by user |
1370 | */ | 1372 | */ |
1371 | static int csi_v4l_open(struct file *file) | 1373 | static int csi_v4l_open(struct file *file) |
1372 | { | 1374 | { |
1373 | struct v4l2_ifparm ifparm; | 1375 | struct v4l2_ifparm ifparm; |
1374 | struct v4l2_format cam_fmt; | 1376 | struct v4l2_format cam_fmt; |
1375 | struct video_device *dev = video_devdata(file); | 1377 | struct video_device *dev = video_devdata(file); |
1376 | cam_data *cam = video_get_drvdata(dev); | 1378 | cam_data *cam = video_get_drvdata(dev); |
1377 | struct sensor_data *sensor; | 1379 | struct sensor_data *sensor; |
1378 | int err = 0; | 1380 | int err = 0; |
1379 | 1381 | ||
1380 | pr_debug(" device name is %s\n", dev->name); | 1382 | pr_debug(" device name is %s\n", dev->name); |
1381 | 1383 | ||
1382 | if (!cam) { | 1384 | if (!cam) { |
1383 | pr_err("%s: Internal error, cam_data not found!\n", __func__); | 1385 | pr_err("%s: Internal error, cam_data not found!\n", __func__); |
1384 | return -EBADF; | 1386 | return -EBADF; |
1385 | } | 1387 | } |
1386 | 1388 | ||
1387 | if (!cam->sensor) { | 1389 | if (!cam->sensor) { |
1388 | pr_err("%s: Internal error, camera is not found!\n", __func__); | 1390 | pr_err("%s: Internal error, camera is not found!\n", __func__); |
1389 | return -EBADF; | 1391 | return -EBADF; |
1390 | } | 1392 | } |
1391 | 1393 | ||
1392 | sensor = cam->sensor->priv; | 1394 | sensor = cam->sensor->priv; |
1393 | if (!sensor) { | 1395 | if (!sensor) { |
1394 | pr_err("%s: Internal error, sensor_data is not found!\n", __func__); | 1396 | pr_err("%s: Internal error, sensor_data is not found!\n", __func__); |
1395 | return -EBADF; | 1397 | return -EBADF; |
1396 | } | 1398 | } |
1397 | 1399 | ||
1398 | down(&cam->busy_lock); | 1400 | down(&cam->busy_lock); |
1399 | err = 0; | 1401 | err = 0; |
1400 | if (signal_pending(current)) | 1402 | if (signal_pending(current)) |
1401 | goto oops; | 1403 | goto oops; |
1402 | 1404 | ||
1403 | if (cam->open_count++ == 0) { | 1405 | if (cam->open_count++ == 0) { |
1406 | pm_runtime_get_sync(&cam->pdev->dev); | ||
1407 | |||
1404 | wait_event_interruptible(cam->power_queue, | 1408 | wait_event_interruptible(cam->power_queue, |
1405 | cam->low_power == false); | 1409 | cam->low_power == false); |
1406 | 1410 | ||
1407 | cam->enc_counter = 0; | 1411 | cam->enc_counter = 0; |
1408 | INIT_LIST_HEAD(&cam->ready_q); | 1412 | INIT_LIST_HEAD(&cam->ready_q); |
1409 | INIT_LIST_HEAD(&cam->working_q); | 1413 | INIT_LIST_HEAD(&cam->working_q); |
1410 | INIT_LIST_HEAD(&cam->done_q); | 1414 | INIT_LIST_HEAD(&cam->done_q); |
1411 | 1415 | ||
1412 | vidioc_int_g_ifparm(cam->sensor, &ifparm); | 1416 | vidioc_int_g_ifparm(cam->sensor, &ifparm); |
1413 | 1417 | ||
1414 | cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1418 | cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1415 | csi_clk_enable(); | 1419 | csi_clk_enable(); |
1416 | clk_prepare_enable(sensor->sensor_clk); | 1420 | clk_prepare_enable(sensor->sensor_clk); |
1417 | vidioc_int_s_power(cam->sensor, 1); | 1421 | vidioc_int_s_power(cam->sensor, 1); |
1418 | vidioc_int_init(cam->sensor); | 1422 | vidioc_int_init(cam->sensor); |
1419 | vidioc_int_dev_init(cam->sensor); | 1423 | vidioc_int_dev_init(cam->sensor); |
1420 | } | 1424 | } |
1421 | 1425 | ||
1422 | file->private_data = dev; | 1426 | file->private_data = dev; |
1423 | 1427 | ||
1424 | oops: | 1428 | oops: |
1425 | up(&cam->busy_lock); | 1429 | up(&cam->busy_lock); |
1426 | return err; | 1430 | return err; |
1427 | } | 1431 | } |
1428 | 1432 | ||
1429 | /*! | 1433 | /*! |
1430 | * V4L interface - close function | 1434 | * V4L interface - close function |
1431 | * | 1435 | * |
1432 | * @param file struct file * | 1436 | * @param file struct file * |
1433 | * | 1437 | * |
1434 | * @return 0 success | 1438 | * @return 0 success |
1435 | */ | 1439 | */ |
1436 | static int csi_v4l_close(struct file *file) | 1440 | static int csi_v4l_close(struct file *file) |
1437 | { | 1441 | { |
1438 | struct video_device *dev = video_devdata(file); | 1442 | struct video_device *dev = video_devdata(file); |
1439 | int err = 0; | 1443 | int err = 0; |
1440 | cam_data *cam = video_get_drvdata(dev); | 1444 | cam_data *cam = video_get_drvdata(dev); |
1441 | struct sensor_data *sensor; | 1445 | struct sensor_data *sensor; |
1442 | 1446 | ||
1443 | pr_debug("In MVC:%s\n", __func__); | 1447 | pr_debug("In MVC:%s\n", __func__); |
1444 | 1448 | ||
1445 | if (!cam) { | 1449 | if (!cam) { |
1446 | pr_err("%s: Internal error, cam_data not found!\n", __func__); | 1450 | pr_err("%s: Internal error, cam_data not found!\n", __func__); |
1447 | return -EBADF; | 1451 | return -EBADF; |
1448 | } | 1452 | } |
1449 | 1453 | ||
1450 | if (!cam->sensor) { | 1454 | if (!cam->sensor) { |
1451 | pr_err("%s: Internal error, camera is not found!\n", __func__); | 1455 | pr_err("%s: Internal error, camera is not found!\n", __func__); |
1452 | return -EBADF; | 1456 | return -EBADF; |
1453 | } | 1457 | } |
1454 | 1458 | ||
1455 | sensor = cam->sensor->priv; | 1459 | sensor = cam->sensor->priv; |
1456 | if (!sensor) { | 1460 | if (!sensor) { |
1457 | pr_err("%s: Internal error, sensor_data is not found!\n", __func__); | 1461 | pr_err("%s: Internal error, sensor_data is not found!\n", __func__); |
1458 | return -EBADF; | 1462 | return -EBADF; |
1459 | } | 1463 | } |
1460 | 1464 | ||
1461 | /* for the case somebody hit the ctrl C */ | 1465 | /* for the case somebody hit the ctrl C */ |
1462 | if (cam->overlay_pid == current->pid) { | 1466 | if (cam->overlay_pid == current->pid) { |
1463 | err = stop_preview(cam); | 1467 | err = stop_preview(cam); |
1464 | cam->overlay_on = false; | 1468 | cam->overlay_on = false; |
1465 | } | 1469 | } |
1466 | 1470 | ||
1467 | if (--cam->open_count == 0) { | 1471 | if (--cam->open_count == 0) { |
1468 | wait_event_interruptible(cam->power_queue, | 1472 | wait_event_interruptible(cam->power_queue, |
1469 | cam->low_power == false); | 1473 | cam->low_power == false); |
1470 | file->private_data = NULL; | 1474 | file->private_data = NULL; |
1471 | vidioc_int_s_power(cam->sensor, 0); | 1475 | vidioc_int_s_power(cam->sensor, 0); |
1472 | clk_disable_unprepare(sensor->sensor_clk); | 1476 | clk_disable_unprepare(sensor->sensor_clk); |
1477 | |||
1478 | pm_runtime_put_sync_suspend(&cam->pdev->dev); | ||
1473 | } | 1479 | } |
1474 | 1480 | ||
1475 | return err; | 1481 | return err; |
1476 | } | 1482 | } |
1477 | 1483 | ||
1478 | /* | 1484 | /* |
1479 | * V4L interface - read function | 1485 | * V4L interface - read function |
1480 | * | 1486 | * |
1481 | * @param file struct file * | 1487 | * @param file struct file * |
1482 | * @param read buf char * | 1488 | * @param read buf char * |
1483 | * @param count size_t | 1489 | * @param count size_t |
1484 | * @param ppos structure loff_t * | 1490 | * @param ppos structure loff_t * |
1485 | * | 1491 | * |
1486 | * @return bytes read | 1492 | * @return bytes read |
1487 | */ | 1493 | */ |
1488 | static ssize_t csi_v4l_read(struct file *file, char *buf, size_t count, | 1494 | static ssize_t csi_v4l_read(struct file *file, char *buf, size_t count, |
1489 | loff_t *ppos) | 1495 | loff_t *ppos) |
1490 | { | 1496 | { |
1491 | int err = 0; | 1497 | int err = 0; |
1492 | struct video_device *dev = video_devdata(file); | 1498 | struct video_device *dev = video_devdata(file); |
1493 | cam_data *cam = video_get_drvdata(dev); | 1499 | cam_data *cam = video_get_drvdata(dev); |
1494 | 1500 | ||
1495 | if (down_interruptible(&cam->busy_lock)) | 1501 | if (down_interruptible(&cam->busy_lock)) |
1496 | return -EINTR; | 1502 | return -EINTR; |
1497 | 1503 | ||
1498 | /* Stop the viewfinder */ | 1504 | /* Stop the viewfinder */ |
1499 | if (cam->overlay_on == true) | 1505 | if (cam->overlay_on == true) |
1500 | stop_preview(cam); | 1506 | stop_preview(cam); |
1501 | 1507 | ||
1502 | if (cam->still_buf_vaddr == NULL) { | 1508 | if (cam->still_buf_vaddr == NULL) { |
1503 | cam->still_buf_vaddr = dma_alloc_coherent(0, | 1509 | cam->still_buf_vaddr = dma_alloc_coherent(0, |
1504 | PAGE_ALIGN | 1510 | PAGE_ALIGN |
1505 | (cam->v2f.fmt. | 1511 | (cam->v2f.fmt. |
1506 | pix.sizeimage), | 1512 | pix.sizeimage), |
1507 | &cam-> | 1513 | &cam-> |
1508 | still_buf[0], | 1514 | still_buf[0], |
1509 | GFP_DMA | GFP_KERNEL); | 1515 | GFP_DMA | GFP_KERNEL); |
1510 | if (cam->still_buf_vaddr == NULL) { | 1516 | if (cam->still_buf_vaddr == NULL) { |
1511 | pr_err("alloc dma memory failed\n"); | 1517 | pr_err("alloc dma memory failed\n"); |
1512 | return -ENOMEM; | 1518 | return -ENOMEM; |
1513 | } | 1519 | } |
1514 | cam->still_counter = 0; | 1520 | cam->still_counter = 0; |
1515 | csi_write(cam->csi_soc, cam->still_buf[0], CSI_CSIDMASA_FB2); | 1521 | csi_write(cam->csi_soc, cam->still_buf[0], CSI_CSIDMASA_FB2); |
1516 | csi_write(cam->csi_soc, cam->still_buf[0], CSI_CSIDMASA_FB1); | 1522 | csi_write(cam->csi_soc, cam->still_buf[0], CSI_CSIDMASA_FB1); |
1517 | csi_write(cam->csi_soc, | 1523 | csi_write(cam->csi_soc, |
1518 | csi_read(cam->csi_soc, CSI_CSICR3) | | 1524 | csi_read(cam->csi_soc, CSI_CSICR3) | |
1519 | BIT_DMA_REFLASH_RFF, | 1525 | BIT_DMA_REFLASH_RFF, |
1520 | CSI_CSICR3); | 1526 | CSI_CSICR3); |
1521 | csi_write(cam->csi_soc, csi_read(cam->csi_soc, CSI_CSISR), | 1527 | csi_write(cam->csi_soc, csi_read(cam->csi_soc, CSI_CSISR), |
1522 | CSI_CSISR); | 1528 | CSI_CSISR); |
1523 | csi_write(cam->csi_soc, | 1529 | csi_write(cam->csi_soc, |
1524 | csi_read(cam->csi_soc, CSI_CSICR3) | BIT_FRMCNT_RST, | 1530 | csi_read(cam->csi_soc, CSI_CSICR3) | BIT_FRMCNT_RST, |
1525 | CSI_CSICR3); | 1531 | CSI_CSICR3); |
1526 | csi_enable_int(cam, 1); | 1532 | csi_enable_int(cam, 1); |
1527 | csi_enable(cam, 1); | 1533 | csi_enable(cam, 1); |
1528 | } | 1534 | } |
1529 | 1535 | ||
1530 | wait_event_interruptible(cam->still_queue, cam->still_counter); | 1536 | wait_event_interruptible(cam->still_queue, cam->still_counter); |
1531 | csi_disable_int(cam); | 1537 | csi_disable_int(cam); |
1532 | err = copy_to_user(buf, cam->still_buf_vaddr, | 1538 | err = copy_to_user(buf, cam->still_buf_vaddr, |
1533 | cam->v2f.fmt.pix.sizeimage); | 1539 | cam->v2f.fmt.pix.sizeimage); |
1534 | 1540 | ||
1535 | if (cam->still_buf_vaddr != NULL) { | 1541 | if (cam->still_buf_vaddr != NULL) { |
1536 | dma_free_coherent(0, PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), | 1542 | dma_free_coherent(0, PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), |
1537 | cam->still_buf_vaddr, cam->still_buf[0]); | 1543 | cam->still_buf_vaddr, cam->still_buf[0]); |
1538 | cam->still_buf[0] = 0; | 1544 | cam->still_buf[0] = 0; |
1539 | cam->still_buf_vaddr = NULL; | 1545 | cam->still_buf_vaddr = NULL; |
1540 | } | 1546 | } |
1541 | 1547 | ||
1542 | if (cam->overlay_on == true) | 1548 | if (cam->overlay_on == true) |
1543 | start_preview(cam); | 1549 | start_preview(cam); |
1544 | 1550 | ||
1545 | up(&cam->busy_lock); | 1551 | up(&cam->busy_lock); |
1546 | if (err < 0) | 1552 | if (err < 0) |
1547 | return err; | 1553 | return err; |
1548 | 1554 | ||
1549 | return cam->v2f.fmt.pix.sizeimage - err; | 1555 | return cam->v2f.fmt.pix.sizeimage - err; |
1550 | } | 1556 | } |
1551 | 1557 | ||
1552 | /*! | 1558 | /*! |
1553 | * V4L interface - ioctl function | 1559 | * V4L interface - ioctl function |
1554 | * | 1560 | * |
1555 | * @param file struct file* | 1561 | * @param file struct file* |
1556 | * | 1562 | * |
1557 | * @param ioctlnr unsigned int | 1563 | * @param ioctlnr unsigned int |
1558 | * | 1564 | * |
1559 | * @param arg void* | 1565 | * @param arg void* |
1560 | * | 1566 | * |
1561 | * @return 0 success, ENODEV for invalid device instance, | 1567 | * @return 0 success, ENODEV for invalid device instance, |
1562 | * -1 for other errors. | 1568 | * -1 for other errors. |
1563 | */ | 1569 | */ |
1564 | static long csi_v4l_do_ioctl(struct file *file, | 1570 | static long csi_v4l_do_ioctl(struct file *file, |
1565 | unsigned int ioctlnr, void *arg) | 1571 | unsigned int ioctlnr, void *arg) |
1566 | { | 1572 | { |
1567 | struct video_device *dev = video_devdata(file); | 1573 | struct video_device *dev = video_devdata(file); |
1568 | cam_data *cam = video_get_drvdata(dev); | 1574 | cam_data *cam = video_get_drvdata(dev); |
1569 | int retval = 0; | 1575 | int retval = 0; |
1570 | unsigned long lock_flags; | 1576 | unsigned long lock_flags; |
1571 | 1577 | ||
1572 | pr_debug("In MVC: %s, %x\n", __func__, ioctlnr); | 1578 | pr_debug("In MVC: %s, %x\n", __func__, ioctlnr); |
1573 | wait_event_interruptible(cam->power_queue, cam->low_power == false); | 1579 | wait_event_interruptible(cam->power_queue, cam->low_power == false); |
1574 | /* make this _really_ smp-safe */ | 1580 | /* make this _really_ smp-safe */ |
1575 | if (ioctlnr != VIDIOC_DQBUF) | 1581 | if (ioctlnr != VIDIOC_DQBUF) |
1576 | if (down_interruptible(&cam->busy_lock)) | 1582 | if (down_interruptible(&cam->busy_lock)) |
1577 | return -EBUSY; | 1583 | return -EBUSY; |
1578 | 1584 | ||
1579 | switch (ioctlnr) { | 1585 | switch (ioctlnr) { |
1580 | /*! | 1586 | /*! |
1581 | * V4l2 VIDIOC_G_FMT ioctl | 1587 | * V4l2 VIDIOC_G_FMT ioctl |
1582 | */ | 1588 | */ |
1583 | case VIDIOC_G_FMT:{ | 1589 | case VIDIOC_G_FMT:{ |
1584 | struct v4l2_format *gf = arg; | 1590 | struct v4l2_format *gf = arg; |
1585 | pr_debug(" case VIDIOC_G_FMT\n"); | 1591 | pr_debug(" case VIDIOC_G_FMT\n"); |
1586 | retval = csi_v4l2_g_fmt(cam, gf); | 1592 | retval = csi_v4l2_g_fmt(cam, gf); |
1587 | break; | 1593 | break; |
1588 | } | 1594 | } |
1589 | 1595 | ||
1590 | /*! | 1596 | /*! |
1591 | * V4l2 VIDIOC_S_FMT ioctl | 1597 | * V4l2 VIDIOC_S_FMT ioctl |
1592 | */ | 1598 | */ |
1593 | case VIDIOC_S_FMT:{ | 1599 | case VIDIOC_S_FMT:{ |
1594 | struct v4l2_format *sf = arg; | 1600 | struct v4l2_format *sf = arg; |
1595 | pr_debug(" case VIDIOC_S_FMT\n"); | 1601 | pr_debug(" case VIDIOC_S_FMT\n"); |
1596 | retval = csi_v4l2_s_fmt(cam, sf); | 1602 | retval = csi_v4l2_s_fmt(cam, sf); |
1597 | vidioc_int_s_fmt_cap(cam->sensor, sf); | 1603 | vidioc_int_s_fmt_cap(cam->sensor, sf); |
1598 | break; | 1604 | break; |
1599 | } | 1605 | } |
1600 | 1606 | ||
1601 | /*! | 1607 | /*! |
1602 | * V4l2 VIDIOC_OVERLAY ioctl | 1608 | * V4l2 VIDIOC_OVERLAY ioctl |
1603 | */ | 1609 | */ |
1604 | case VIDIOC_OVERLAY:{ | 1610 | case VIDIOC_OVERLAY:{ |
1605 | int *on = arg; | 1611 | int *on = arg; |
1606 | pr_debug(" case VIDIOC_OVERLAY\n"); | 1612 | pr_debug(" case VIDIOC_OVERLAY\n"); |
1607 | if (*on) { | 1613 | if (*on) { |
1608 | cam->overlay_on = true; | 1614 | cam->overlay_on = true; |
1609 | cam->overlay_pid = current->pid; | 1615 | cam->overlay_pid = current->pid; |
1610 | start_preview(cam); | 1616 | start_preview(cam); |
1611 | } | 1617 | } |
1612 | if (!*on) { | 1618 | if (!*on) { |
1613 | stop_preview(cam); | 1619 | stop_preview(cam); |
1614 | cam->overlay_on = false; | 1620 | cam->overlay_on = false; |
1615 | } | 1621 | } |
1616 | break; | 1622 | break; |
1617 | } | 1623 | } |
1618 | 1624 | ||
1619 | /*! | 1625 | /*! |
1620 | * V4l2 VIDIOC_G_FBUF ioctl | 1626 | * V4l2 VIDIOC_G_FBUF ioctl |
1621 | */ | 1627 | */ |
1622 | case VIDIOC_G_FBUF:{ | 1628 | case VIDIOC_G_FBUF:{ |
1623 | struct v4l2_framebuffer *fb = arg; | 1629 | struct v4l2_framebuffer *fb = arg; |
1624 | *fb = cam->v4l2_fb; | 1630 | *fb = cam->v4l2_fb; |
1625 | fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY; | 1631 | fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY; |
1626 | break; | 1632 | break; |
1627 | } | 1633 | } |
1628 | 1634 | ||
1629 | /*! | 1635 | /*! |
1630 | * V4l2 VIDIOC_S_FBUF ioctl | 1636 | * V4l2 VIDIOC_S_FBUF ioctl |
1631 | */ | 1637 | */ |
1632 | case VIDIOC_S_FBUF:{ | 1638 | case VIDIOC_S_FBUF:{ |
1633 | struct v4l2_framebuffer *fb = arg; | 1639 | struct v4l2_framebuffer *fb = arg; |
1634 | cam->v4l2_fb = *fb; | 1640 | cam->v4l2_fb = *fb; |
1635 | break; | 1641 | break; |
1636 | } | 1642 | } |
1637 | 1643 | ||
1638 | case VIDIOC_G_PARM:{ | 1644 | case VIDIOC_G_PARM:{ |
1639 | struct v4l2_streamparm *parm = arg; | 1645 | struct v4l2_streamparm *parm = arg; |
1640 | pr_debug(" case VIDIOC_G_PARM\n"); | 1646 | pr_debug(" case VIDIOC_G_PARM\n"); |
1641 | vidioc_int_g_parm(cam->sensor, parm); | 1647 | vidioc_int_g_parm(cam->sensor, parm); |
1642 | break; | 1648 | break; |
1643 | } | 1649 | } |
1644 | 1650 | ||
1645 | case VIDIOC_S_PARM:{ | 1651 | case VIDIOC_S_PARM:{ |
1646 | struct v4l2_streamparm *parm = arg; | 1652 | struct v4l2_streamparm *parm = arg; |
1647 | pr_debug(" case VIDIOC_S_PARM\n"); | 1653 | pr_debug(" case VIDIOC_S_PARM\n"); |
1648 | retval = csi_v4l2_s_param(cam, parm); | 1654 | retval = csi_v4l2_s_param(cam, parm); |
1649 | break; | 1655 | break; |
1650 | } | 1656 | } |
1651 | 1657 | ||
1652 | case VIDIOC_QUERYCAP:{ | 1658 | case VIDIOC_QUERYCAP:{ |
1653 | struct v4l2_capability *cap = arg; | 1659 | struct v4l2_capability *cap = arg; |
1654 | pr_debug(" case VIDIOC_QUERYCAP\n"); | 1660 | pr_debug(" case VIDIOC_QUERYCAP\n"); |
1655 | strcpy(cap->driver, "csi_v4l2"); | 1661 | strcpy(cap->driver, "csi_v4l2"); |
1656 | cap->version = KERNEL_VERSION(0, 1, 11); | 1662 | cap->version = KERNEL_VERSION(0, 1, 11); |
1657 | cap->capabilities = V4L2_CAP_VIDEO_OVERLAY | | 1663 | cap->capabilities = V4L2_CAP_VIDEO_OVERLAY | |
1658 | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | | 1664 | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | |
1659 | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_READWRITE; | 1665 | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_READWRITE; |
1660 | cap->card[0] = '\0'; | 1666 | cap->card[0] = '\0'; |
1661 | cap->bus_info[0] = '\0'; | 1667 | cap->bus_info[0] = '\0'; |
1662 | break; | 1668 | break; |
1663 | } | 1669 | } |
1664 | 1670 | ||
1665 | case VIDIOC_CROPCAP: | 1671 | case VIDIOC_CROPCAP: |
1666 | { | 1672 | { |
1667 | struct v4l2_cropcap *cap = arg; | 1673 | struct v4l2_cropcap *cap = arg; |
1668 | 1674 | ||
1669 | if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && | 1675 | if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && |
1670 | cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { | 1676 | cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { |
1671 | retval = -EINVAL; | 1677 | retval = -EINVAL; |
1672 | break; | 1678 | break; |
1673 | } | 1679 | } |
1674 | cap->bounds = cam->crop_bounds; | 1680 | cap->bounds = cam->crop_bounds; |
1675 | cap->defrect = cam->crop_defrect; | 1681 | cap->defrect = cam->crop_defrect; |
1676 | break; | 1682 | break; |
1677 | } | 1683 | } |
1678 | case VIDIOC_S_CROP: | 1684 | case VIDIOC_S_CROP: |
1679 | { | 1685 | { |
1680 | struct v4l2_crop *crop = arg; | 1686 | struct v4l2_crop *crop = arg; |
1681 | struct v4l2_rect *b = &cam->crop_bounds; | 1687 | struct v4l2_rect *b = &cam->crop_bounds; |
1682 | 1688 | ||
1683 | pr_debug(" case VIDIOC_S_CROP\n"); | 1689 | pr_debug(" case VIDIOC_S_CROP\n"); |
1684 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1690 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1685 | retval = -EINVAL; | 1691 | retval = -EINVAL; |
1686 | break; | 1692 | break; |
1687 | } | 1693 | } |
1688 | 1694 | ||
1689 | crop->c.top = (crop->c.top < b->top) ? b->top | 1695 | crop->c.top = (crop->c.top < b->top) ? b->top |
1690 | : crop->c.top; | 1696 | : crop->c.top; |
1691 | if (crop->c.top > b->top + b->height) | 1697 | if (crop->c.top > b->top + b->height) |
1692 | crop->c.top = b->top + b->height - 1; | 1698 | crop->c.top = b->top + b->height - 1; |
1693 | if (crop->c.height > b->top + b->height - crop->c.top) | 1699 | if (crop->c.height > b->top + b->height - crop->c.top) |
1694 | crop->c.height = | 1700 | crop->c.height = |
1695 | b->top + b->height - crop->c.top; | 1701 | b->top + b->height - crop->c.top; |
1696 | 1702 | ||
1697 | crop->c.left = (crop->c.left < b->left) ? b->left | 1703 | crop->c.left = (crop->c.left < b->left) ? b->left |
1698 | : crop->c.left; | 1704 | : crop->c.left; |
1699 | if (crop->c.left > b->left + b->width) | 1705 | if (crop->c.left > b->left + b->width) |
1700 | crop->c.left = b->left + b->width - 1; | 1706 | crop->c.left = b->left + b->width - 1; |
1701 | if (crop->c.width > b->left - crop->c.left + b->width) | 1707 | if (crop->c.width > b->left - crop->c.left + b->width) |
1702 | crop->c.width = | 1708 | crop->c.width = |
1703 | b->left - crop->c.left + b->width; | 1709 | b->left - crop->c.left + b->width; |
1704 | 1710 | ||
1705 | crop->c.width -= crop->c.width % 8; | 1711 | crop->c.width -= crop->c.width % 8; |
1706 | crop->c.height -= crop->c.height % 8; | 1712 | crop->c.height -= crop->c.height % 8; |
1707 | 1713 | ||
1708 | cam->crop_current = crop->c; | 1714 | cam->crop_current = crop->c; |
1709 | 1715 | ||
1710 | break; | 1716 | break; |
1711 | } | 1717 | } |
1712 | case VIDIOC_G_CROP: | 1718 | case VIDIOC_G_CROP: |
1713 | { | 1719 | { |
1714 | struct v4l2_crop *crop = arg; | 1720 | struct v4l2_crop *crop = arg; |
1715 | pr_debug(" case VIDIOC_G_CROP\n"); | 1721 | pr_debug(" case VIDIOC_G_CROP\n"); |
1716 | 1722 | ||
1717 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1723 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1718 | retval = -EINVAL; | 1724 | retval = -EINVAL; |
1719 | break; | 1725 | break; |
1720 | } | 1726 | } |
1721 | crop->c = cam->crop_current; | 1727 | crop->c = cam->crop_current; |
1722 | 1728 | ||
1723 | break; | 1729 | break; |
1724 | 1730 | ||
1725 | } | 1731 | } |
1726 | case VIDIOC_REQBUFS: { | 1732 | case VIDIOC_REQBUFS: { |
1727 | struct v4l2_requestbuffers *req = arg; | 1733 | struct v4l2_requestbuffers *req = arg; |
1728 | pr_debug(" case VIDIOC_REQBUFS\n"); | 1734 | pr_debug(" case VIDIOC_REQBUFS\n"); |
1729 | 1735 | ||
1730 | if (req->count > FRAME_NUM) { | 1736 | if (req->count > FRAME_NUM) { |
1731 | pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " | 1737 | pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " |
1732 | "not enough buffers\n"); | 1738 | "not enough buffers\n"); |
1733 | req->count = FRAME_NUM; | 1739 | req->count = FRAME_NUM; |
1734 | } | 1740 | } |
1735 | 1741 | ||
1736 | if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1742 | if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1737 | pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " | 1743 | pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " |
1738 | "wrong buffer type\n"); | 1744 | "wrong buffer type\n"); |
1739 | retval = -EINVAL; | 1745 | retval = -EINVAL; |
1740 | break; | 1746 | break; |
1741 | } | 1747 | } |
1742 | 1748 | ||
1743 | csi_streamoff(cam); | 1749 | csi_streamoff(cam); |
1744 | if (req->memory & V4L2_MEMORY_MMAP) { | 1750 | if (req->memory & V4L2_MEMORY_MMAP) { |
1745 | csi_free_frame_buf(cam); | 1751 | csi_free_frame_buf(cam); |
1746 | retval = csi_allocate_frame_buf(cam, req->count + 1); | 1752 | retval = csi_allocate_frame_buf(cam, req->count + 1); |
1747 | req_buf_number = req->count; | 1753 | req_buf_number = req->count; |
1748 | } | 1754 | } |
1749 | break; | 1755 | break; |
1750 | } | 1756 | } |
1751 | 1757 | ||
1752 | case VIDIOC_QUERYBUF: { | 1758 | case VIDIOC_QUERYBUF: { |
1753 | struct v4l2_buffer *buf = arg; | 1759 | struct v4l2_buffer *buf = arg; |
1754 | int index = buf->index; | 1760 | int index = buf->index; |
1755 | pr_debug(" case VIDIOC_QUERYBUF\n"); | 1761 | pr_debug(" case VIDIOC_QUERYBUF\n"); |
1756 | 1762 | ||
1757 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1763 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1758 | retval = -EINVAL; | 1764 | retval = -EINVAL; |
1759 | break; | 1765 | break; |
1760 | } | 1766 | } |
1761 | 1767 | ||
1762 | if (buf->memory & V4L2_MEMORY_MMAP) { | 1768 | if (buf->memory & V4L2_MEMORY_MMAP) { |
1763 | memset(buf, 0, sizeof(buf)); | 1769 | memset(buf, 0, sizeof(buf)); |
1764 | buf->index = index; | 1770 | buf->index = index; |
1765 | } | 1771 | } |
1766 | 1772 | ||
1767 | down(&cam->param_lock); | 1773 | down(&cam->param_lock); |
1768 | if (buf->memory & V4L2_MEMORY_USERPTR) { | 1774 | if (buf->memory & V4L2_MEMORY_USERPTR) { |
1769 | csi_v4l2_release_bufs(cam); | 1775 | csi_v4l2_release_bufs(cam); |
1770 | retval = csi_v4l2_prepare_bufs(cam, buf); | 1776 | retval = csi_v4l2_prepare_bufs(cam, buf); |
1771 | } | 1777 | } |
1772 | if (buf->memory & V4L2_MEMORY_MMAP) | 1778 | if (buf->memory & V4L2_MEMORY_MMAP) |
1773 | retval = csi_v4l2_buffer_status(cam, buf); | 1779 | retval = csi_v4l2_buffer_status(cam, buf); |
1774 | up(&cam->param_lock); | 1780 | up(&cam->param_lock); |
1775 | break; | 1781 | break; |
1776 | } | 1782 | } |
1777 | 1783 | ||
1778 | case VIDIOC_QBUF: { | 1784 | case VIDIOC_QBUF: { |
1779 | struct v4l2_buffer *buf = arg; | 1785 | struct v4l2_buffer *buf = arg; |
1780 | int index = buf->index; | 1786 | int index = buf->index; |
1781 | pr_debug(" case VIDIOC_QBUF\n"); | 1787 | pr_debug(" case VIDIOC_QBUF\n"); |
1782 | 1788 | ||
1783 | spin_lock_irqsave(&cam->queue_int_lock, lock_flags); | 1789 | spin_lock_irqsave(&cam->queue_int_lock, lock_flags); |
1784 | cam->frame[index].buffer.m.offset = buf->m.offset; | 1790 | cam->frame[index].buffer.m.offset = buf->m.offset; |
1785 | if ((cam->frame[index].buffer.flags & 0x7) == | 1791 | if ((cam->frame[index].buffer.flags & 0x7) == |
1786 | V4L2_BUF_FLAG_MAPPED) { | 1792 | V4L2_BUF_FLAG_MAPPED) { |
1787 | cam->frame[index].buffer.flags |= V4L2_BUF_FLAG_QUEUED; | 1793 | cam->frame[index].buffer.flags |= V4L2_BUF_FLAG_QUEUED; |
1788 | list_add_tail(&cam->frame[index].queue, &cam->ready_q); | 1794 | list_add_tail(&cam->frame[index].queue, &cam->ready_q); |
1789 | } else if (cam->frame[index].buffer.flags & | 1795 | } else if (cam->frame[index].buffer.flags & |
1790 | V4L2_BUF_FLAG_QUEUED) { | 1796 | V4L2_BUF_FLAG_QUEUED) { |
1791 | pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " | 1797 | pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " |
1792 | "buffer already queued\n"); | 1798 | "buffer already queued\n"); |
1793 | retval = -EINVAL; | 1799 | retval = -EINVAL; |
1794 | } else if (cam->frame[index].buffer. | 1800 | } else if (cam->frame[index].buffer. |
1795 | flags & V4L2_BUF_FLAG_DONE) { | 1801 | flags & V4L2_BUF_FLAG_DONE) { |
1796 | pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " | 1802 | pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " |
1797 | "overwrite done buffer.\n"); | 1803 | "overwrite done buffer.\n"); |
1798 | cam->frame[index].buffer.flags &= | 1804 | cam->frame[index].buffer.flags &= |
1799 | ~V4L2_BUF_FLAG_DONE; | 1805 | ~V4L2_BUF_FLAG_DONE; |
1800 | cam->frame[index].buffer.flags |= | 1806 | cam->frame[index].buffer.flags |= |
1801 | V4L2_BUF_FLAG_QUEUED; | 1807 | V4L2_BUF_FLAG_QUEUED; |
1802 | retval = -EINVAL; | 1808 | retval = -EINVAL; |
1803 | } | 1809 | } |
1804 | buf->flags = cam->frame[index].buffer.flags; | 1810 | buf->flags = cam->frame[index].buffer.flags; |
1805 | spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); | 1811 | spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); |
1806 | 1812 | ||
1807 | break; | 1813 | break; |
1808 | } | 1814 | } |
1809 | 1815 | ||
1810 | case VIDIOC_DQBUF: { | 1816 | case VIDIOC_DQBUF: { |
1811 | struct v4l2_buffer *buf = arg; | 1817 | struct v4l2_buffer *buf = arg; |
1812 | pr_debug(" case VIDIOC_DQBUF\n"); | 1818 | pr_debug(" case VIDIOC_DQBUF\n"); |
1813 | 1819 | ||
1814 | retval = csi_v4l_dqueue(cam, buf); | 1820 | retval = csi_v4l_dqueue(cam, buf); |
1815 | 1821 | ||
1816 | break; | 1822 | break; |
1817 | } | 1823 | } |
1818 | 1824 | ||
1819 | case VIDIOC_STREAMON: { | 1825 | case VIDIOC_STREAMON: { |
1820 | pr_debug(" case VIDIOC_STREAMON\n"); | 1826 | pr_debug(" case VIDIOC_STREAMON\n"); |
1821 | retval = csi_streamon(cam); | 1827 | retval = csi_streamon(cam); |
1822 | break; | 1828 | break; |
1823 | } | 1829 | } |
1824 | 1830 | ||
1825 | case VIDIOC_STREAMOFF: { | 1831 | case VIDIOC_STREAMOFF: { |
1826 | pr_debug(" case VIDIOC_STREAMOFF\n"); | 1832 | pr_debug(" case VIDIOC_STREAMOFF\n"); |
1827 | retval = csi_streamoff(cam); | 1833 | retval = csi_streamoff(cam); |
1828 | break; | 1834 | break; |
1829 | } | 1835 | } |
1830 | case VIDIOC_ENUM_FMT: { | 1836 | case VIDIOC_ENUM_FMT: { |
1831 | struct v4l2_fmtdesc *fmt = arg; | 1837 | struct v4l2_fmtdesc *fmt = arg; |
1832 | if (cam->sensor) | 1838 | if (cam->sensor) |
1833 | retval = vidioc_int_enum_fmt_cap(cam->sensor, fmt); | 1839 | retval = vidioc_int_enum_fmt_cap(cam->sensor, fmt); |
1834 | else { | 1840 | else { |
1835 | pr_err("ERROR: v4l2 capture: slave not found!\n"); | 1841 | pr_err("ERROR: v4l2 capture: slave not found!\n"); |
1836 | retval = -ENODEV; | 1842 | retval = -ENODEV; |
1837 | } | 1843 | } |
1838 | break; | 1844 | break; |
1839 | } | 1845 | } |
1840 | case VIDIOC_ENUM_FRAMESIZES: { | 1846 | case VIDIOC_ENUM_FRAMESIZES: { |
1841 | struct v4l2_frmsizeenum *fsize = arg; | 1847 | struct v4l2_frmsizeenum *fsize = arg; |
1842 | if (cam->sensor) | 1848 | if (cam->sensor) |
1843 | retval = vidioc_int_enum_framesizes(cam->sensor, fsize); | 1849 | retval = vidioc_int_enum_framesizes(cam->sensor, fsize); |
1844 | else { | 1850 | else { |
1845 | pr_err("ERROR: v4l2 capture: slave not found!\n"); | 1851 | pr_err("ERROR: v4l2 capture: slave not found!\n"); |
1846 | retval = -ENODEV; | 1852 | retval = -ENODEV; |
1847 | } | 1853 | } |
1848 | break; | 1854 | break; |
1849 | } | 1855 | } |
1850 | case VIDIOC_ENUM_FRAMEINTERVALS: { | 1856 | case VIDIOC_ENUM_FRAMEINTERVALS: { |
1851 | struct v4l2_frmivalenum *fival = arg; | 1857 | struct v4l2_frmivalenum *fival = arg; |
1852 | if (cam->sensor) | 1858 | if (cam->sensor) |
1853 | retval = vidioc_int_enum_frameintervals(cam->sensor, | 1859 | retval = vidioc_int_enum_frameintervals(cam->sensor, |
1854 | fival); | 1860 | fival); |
1855 | else { | 1861 | else { |
1856 | pr_err("ERROR: v4l2 capture: slave not found!\n"); | 1862 | pr_err("ERROR: v4l2 capture: slave not found!\n"); |
1857 | retval = -ENODEV; | 1863 | retval = -ENODEV; |
1858 | } | 1864 | } |
1859 | break; | 1865 | break; |
1860 | } | 1866 | } |
1861 | case VIDIOC_DBG_G_CHIP_IDENT: { | 1867 | case VIDIOC_DBG_G_CHIP_IDENT: { |
1862 | struct v4l2_dbg_chip_ident *p = arg; | 1868 | struct v4l2_dbg_chip_ident *p = arg; |
1863 | p->ident = V4L2_IDENT_NONE; | 1869 | p->ident = V4L2_IDENT_NONE; |
1864 | p->revision = 0; | 1870 | p->revision = 0; |
1865 | if (cam->sensor) | 1871 | if (cam->sensor) |
1866 | retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p); | 1872 | retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p); |
1867 | else { | 1873 | else { |
1868 | pr_err("ERROR: v4l2 capture: slave not found!\n"); | 1874 | pr_err("ERROR: v4l2 capture: slave not found!\n"); |
1869 | retval = -ENODEV; | 1875 | retval = -ENODEV; |
1870 | } | 1876 | } |
1871 | break; | 1877 | break; |
1872 | } | 1878 | } |
1873 | 1879 | ||
1874 | case VIDIOC_S_CTRL: | 1880 | case VIDIOC_S_CTRL: |
1875 | { | 1881 | { |
1876 | struct v4l2_control *vc = arg; | 1882 | struct v4l2_control *vc = arg; |
1877 | int i; | 1883 | int i; |
1878 | 1884 | ||
1879 | for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) | 1885 | for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) |
1880 | if (vc->id == pxp_controls[i].id) { | 1886 | if (vc->id == pxp_controls[i].id) { |
1881 | if (vc->value < pxp_controls[i].minimum || | 1887 | if (vc->value < pxp_controls[i].minimum || |
1882 | vc->value > pxp_controls[i].maximum) { | 1888 | vc->value > pxp_controls[i].maximum) { |
1883 | retval = -ERANGE; | 1889 | retval = -ERANGE; |
1884 | break; | 1890 | break; |
1885 | } | 1891 | } |
1886 | retval = pxp_set_cstate(cam, vc); | 1892 | retval = pxp_set_cstate(cam, vc); |
1887 | break; | 1893 | break; |
1888 | } | 1894 | } |
1889 | 1895 | ||
1890 | if (i >= ARRAY_SIZE(pxp_controls)) | 1896 | if (i >= ARRAY_SIZE(pxp_controls)) |
1891 | retval = -EINVAL; | 1897 | retval = -EINVAL; |
1892 | break; | 1898 | break; |
1893 | 1899 | ||
1894 | } | 1900 | } |
1895 | case VIDIOC_G_CTRL: | 1901 | case VIDIOC_G_CTRL: |
1896 | { | 1902 | { |
1897 | struct v4l2_control *vc = arg; | 1903 | struct v4l2_control *vc = arg; |
1898 | int i; | 1904 | int i; |
1899 | 1905 | ||
1900 | for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) | 1906 | for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) |
1901 | if (vc->id == pxp_controls[i].id) { | 1907 | if (vc->id == pxp_controls[i].id) { |
1902 | retval = pxp_get_cstate(cam, vc); | 1908 | retval = pxp_get_cstate(cam, vc); |
1903 | break; | 1909 | break; |
1904 | } | 1910 | } |
1905 | 1911 | ||
1906 | if (i >= ARRAY_SIZE(pxp_controls)) | 1912 | if (i >= ARRAY_SIZE(pxp_controls)) |
1907 | retval = -EINVAL; | 1913 | retval = -EINVAL; |
1908 | break; | 1914 | break; |
1909 | } | 1915 | } |
1910 | case VIDIOC_QUERYCTRL: | 1916 | case VIDIOC_QUERYCTRL: |
1911 | { | 1917 | { |
1912 | struct v4l2_queryctrl *qc = arg; | 1918 | struct v4l2_queryctrl *qc = arg; |
1913 | int i; | 1919 | int i; |
1914 | 1920 | ||
1915 | for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) | 1921 | for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) |
1916 | if (qc->id && qc->id == pxp_controls[i].id) { | 1922 | if (qc->id && qc->id == pxp_controls[i].id) { |
1917 | memcpy(qc, &(pxp_controls[i]), sizeof(*qc)); | 1923 | memcpy(qc, &(pxp_controls[i]), sizeof(*qc)); |
1918 | break; | 1924 | break; |
1919 | } | 1925 | } |
1920 | 1926 | ||
1921 | if (i >= ARRAY_SIZE(pxp_controls)) | 1927 | if (i >= ARRAY_SIZE(pxp_controls)) |
1922 | retval = -EINVAL; | 1928 | retval = -EINVAL; |
1923 | break; | 1929 | break; |
1924 | } | 1930 | } |
1925 | 1931 | ||
1926 | case VIDIOC_G_STD: { | 1932 | case VIDIOC_G_STD: { |
1927 | v4l2_std_id *e = arg; | 1933 | v4l2_std_id *e = arg; |
1928 | pr_debug(" case VIDIOC_G_STD\n"); | 1934 | pr_debug(" case VIDIOC_G_STD\n"); |
1929 | if (cam->sensor) { | 1935 | if (cam->sensor) { |
1930 | retval = csi_v4l_g_std(cam, e); | 1936 | retval = csi_v4l_g_std(cam, e); |
1931 | } else { | 1937 | } else { |
1932 | pr_err("ERROR: v4l2 capture: slave not found!\n"); | 1938 | pr_err("ERROR: v4l2 capture: slave not found!\n"); |
1933 | retval = -ENODEV; | 1939 | retval = -ENODEV; |
1934 | } | 1940 | } |
1935 | break; | 1941 | break; |
1936 | } | 1942 | } |
1937 | 1943 | ||
1938 | case VIDIOC_S_STD: { | 1944 | case VIDIOC_S_STD: { |
1939 | v4l2_std_id *e = arg; | 1945 | v4l2_std_id *e = arg; |
1940 | pr_debug(" case VIDIOC_S_STD\n"); | 1946 | pr_debug(" case VIDIOC_S_STD\n"); |
1941 | retval = csi_v4l_s_std(cam, *e); | 1947 | retval = csi_v4l_s_std(cam, *e); |
1942 | 1948 | ||
1943 | break; | 1949 | break; |
1944 | } | 1950 | } |
1945 | 1951 | ||
1946 | case VIDIOC_ENUMINPUT: { | 1952 | case VIDIOC_ENUMINPUT: { |
1947 | struct v4l2_input *input = arg; | 1953 | struct v4l2_input *input = arg; |
1948 | pr_debug(" case VIDIOC_ENUMINPUT\n"); | 1954 | pr_debug(" case VIDIOC_ENUMINPUT\n"); |
1949 | if (input->index >= CSI_V4L2_CAPTURE_NUM_INPUTS) { | 1955 | if (input->index >= CSI_V4L2_CAPTURE_NUM_INPUTS) { |
1950 | retval = -EINVAL; | 1956 | retval = -EINVAL; |
1951 | break; | 1957 | break; |
1952 | } | 1958 | } |
1953 | *input = csi_capture_inputs[input->index]; | 1959 | *input = csi_capture_inputs[input->index]; |
1954 | break; | 1960 | break; |
1955 | } | 1961 | } |
1956 | 1962 | ||
1957 | case VIDIOC_G_INPUT: { | 1963 | case VIDIOC_G_INPUT: { |
1958 | int *index = arg; | 1964 | int *index = arg; |
1959 | pr_debug(" case VIDIOC_G_INPUT\n"); | 1965 | pr_debug(" case VIDIOC_G_INPUT\n"); |
1960 | *index = cam->current_input; | 1966 | *index = cam->current_input; |
1961 | break; | 1967 | break; |
1962 | } | 1968 | } |
1963 | 1969 | ||
1964 | case VIDIOC_S_INPUT: { | 1970 | case VIDIOC_S_INPUT: { |
1965 | int *index = arg; | 1971 | int *index = arg; |
1966 | pr_debug(" case VIDIOC_S_INPUT\n"); | 1972 | pr_debug(" case VIDIOC_S_INPUT\n"); |
1967 | if (*index >= CSI_V4L2_CAPTURE_NUM_INPUTS) { | 1973 | if (*index >= CSI_V4L2_CAPTURE_NUM_INPUTS) { |
1968 | retval = -EINVAL; | 1974 | retval = -EINVAL; |
1969 | break; | 1975 | break; |
1970 | } | 1976 | } |
1971 | 1977 | ||
1972 | cam->current_input = *index; | 1978 | cam->current_input = *index; |
1973 | 1979 | ||
1974 | csi_input_select(cam); | 1980 | csi_input_select(cam); |
1975 | break; | 1981 | break; |
1976 | } | 1982 | } |
1977 | case VIDIOC_G_OUTPUT: | 1983 | case VIDIOC_G_OUTPUT: |
1978 | case VIDIOC_S_OUTPUT: | 1984 | case VIDIOC_S_OUTPUT: |
1979 | case VIDIOC_ENUMSTD: | 1985 | case VIDIOC_ENUMSTD: |
1980 | case VIDIOC_TRY_FMT: | 1986 | case VIDIOC_TRY_FMT: |
1981 | case VIDIOC_G_TUNER: | 1987 | case VIDIOC_G_TUNER: |
1982 | case VIDIOC_S_TUNER: | 1988 | case VIDIOC_S_TUNER: |
1983 | case VIDIOC_G_FREQUENCY: | 1989 | case VIDIOC_G_FREQUENCY: |
1984 | case VIDIOC_S_FREQUENCY: | 1990 | case VIDIOC_S_FREQUENCY: |
1985 | case VIDIOC_ENUMOUTPUT: | 1991 | case VIDIOC_ENUMOUTPUT: |
1986 | default: | 1992 | default: |
1987 | pr_debug(" case not supported\n"); | 1993 | pr_debug(" case not supported\n"); |
1988 | retval = -EINVAL; | 1994 | retval = -EINVAL; |
1989 | break; | 1995 | break; |
1990 | } | 1996 | } |
1991 | 1997 | ||
1992 | if (ioctlnr != VIDIOC_DQBUF) | 1998 | if (ioctlnr != VIDIOC_DQBUF) |
1993 | up(&cam->busy_lock); | 1999 | up(&cam->busy_lock); |
1994 | return retval; | 2000 | return retval; |
1995 | } | 2001 | } |
1996 | 2002 | ||
1997 | /* | 2003 | /* |
1998 | * V4L interface - ioctl function | 2004 | * V4L interface - ioctl function |
1999 | * | 2005 | * |
2000 | * @return None | 2006 | * @return None |
2001 | */ | 2007 | */ |
2002 | static long csi_v4l_ioctl(struct file *file, | 2008 | static long csi_v4l_ioctl(struct file *file, |
2003 | unsigned int cmd, unsigned long arg) | 2009 | unsigned int cmd, unsigned long arg) |
2004 | { | 2010 | { |
2005 | return video_usercopy(file, cmd, arg, csi_v4l_do_ioctl); | 2011 | return video_usercopy(file, cmd, arg, csi_v4l_do_ioctl); |
2006 | } | 2012 | } |
2007 | 2013 | ||
2008 | /*! | 2014 | /*! |
2009 | * V4L interface - mmap function | 2015 | * V4L interface - mmap function |
2010 | * | 2016 | * |
2011 | * @param file structure file * | 2017 | * @param file structure file * |
2012 | * | 2018 | * |
2013 | * @param vma structure vm_area_struct * | 2019 | * @param vma structure vm_area_struct * |
2014 | * | 2020 | * |
2015 | * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error | 2021 | * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error |
2016 | */ | 2022 | */ |
2017 | static int csi_mmap(struct file *file, struct vm_area_struct *vma) | 2023 | static int csi_mmap(struct file *file, struct vm_area_struct *vma) |
2018 | { | 2024 | { |
2019 | struct video_device *dev = video_devdata(file); | 2025 | struct video_device *dev = video_devdata(file); |
2020 | unsigned long size; | 2026 | unsigned long size; |
2021 | int res = 0; | 2027 | int res = 0; |
2022 | cam_data *cam = video_get_drvdata(dev); | 2028 | cam_data *cam = video_get_drvdata(dev); |
2023 | 2029 | ||
2024 | pr_debug("%s\n", __func__); | 2030 | pr_debug("%s\n", __func__); |
2025 | pr_debug("\npgoff=0x%lx, start=0x%lx, end=0x%lx\n", | 2031 | pr_debug("\npgoff=0x%lx, start=0x%lx, end=0x%lx\n", |
2026 | vma->vm_pgoff, vma->vm_start, vma->vm_end); | 2032 | vma->vm_pgoff, vma->vm_start, vma->vm_end); |
2027 | 2033 | ||
2028 | /* make this _really_ smp-safe */ | 2034 | /* make this _really_ smp-safe */ |
2029 | if (down_interruptible(&cam->busy_lock)) | 2035 | if (down_interruptible(&cam->busy_lock)) |
2030 | return -EINTR; | 2036 | return -EINTR; |
2031 | 2037 | ||
2032 | size = vma->vm_end - vma->vm_start; | 2038 | size = vma->vm_end - vma->vm_start; |
2033 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | 2039 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); |
2034 | 2040 | ||
2035 | if (remap_pfn_range(vma, vma->vm_start, | 2041 | if (remap_pfn_range(vma, vma->vm_start, |
2036 | vma->vm_pgoff, size, vma->vm_page_prot)) { | 2042 | vma->vm_pgoff, size, vma->vm_page_prot)) { |
2037 | pr_err("ERROR: v4l2 capture: %s : " | 2043 | pr_err("ERROR: v4l2 capture: %s : " |
2038 | "remap_pfn_range failed\n", __func__); | 2044 | "remap_pfn_range failed\n", __func__); |
2039 | res = -ENOBUFS; | 2045 | res = -ENOBUFS; |
2040 | goto csi_mmap_exit; | 2046 | goto csi_mmap_exit; |
2041 | } | 2047 | } |
2042 | 2048 | ||
2043 | vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ | 2049 | vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ |
2044 | 2050 | ||
2045 | csi_mmap_exit: | 2051 | csi_mmap_exit: |
2046 | up(&cam->busy_lock); | 2052 | up(&cam->busy_lock); |
2047 | return res; | 2053 | return res; |
2048 | } | 2054 | } |
2049 | 2055 | ||
2050 | /*! | 2056 | /*! |
2051 | * This structure defines the functions to be called in this driver. | 2057 | * This structure defines the functions to be called in this driver. |
2052 | */ | 2058 | */ |
2053 | static struct v4l2_file_operations csi_v4l_fops = { | 2059 | static struct v4l2_file_operations csi_v4l_fops = { |
2054 | .owner = THIS_MODULE, | 2060 | .owner = THIS_MODULE, |
2055 | .open = csi_v4l_open, | 2061 | .open = csi_v4l_open, |
2056 | .release = csi_v4l_close, | 2062 | .release = csi_v4l_close, |
2057 | .read = csi_v4l_read, | 2063 | .read = csi_v4l_read, |
2058 | .ioctl = csi_v4l_ioctl, | 2064 | .ioctl = csi_v4l_ioctl, |
2059 | .mmap = csi_mmap, | 2065 | .mmap = csi_mmap, |
2060 | }; | 2066 | }; |
2061 | 2067 | ||
2062 | static struct video_device csi_v4l_template = { | 2068 | static struct video_device csi_v4l_template = { |
2063 | .name = "Mx25 Camera", | 2069 | .name = "Mx25 Camera", |
2064 | .fops = &csi_v4l_fops, | 2070 | .fops = &csi_v4l_fops, |
2065 | .release = video_device_release, | 2071 | .release = video_device_release, |
2066 | }; | 2072 | }; |
2067 | 2073 | ||
2068 | /*! | 2074 | /*! |
2069 | * initialize cam_data structure | 2075 | * initialize cam_data structure |
2070 | * | 2076 | * |
2071 | * @param cam structure cam_data * | 2077 | * @param cam structure cam_data * |
2072 | * | 2078 | * |
2073 | * @return status 0 Success | 2079 | * @return status 0 Success |
2074 | */ | 2080 | */ |
2075 | static void init_camera_struct(cam_data *cam, struct platform_device *pdev) | 2081 | static void init_camera_struct(cam_data *cam, struct platform_device *pdev) |
2076 | { | 2082 | { |
2077 | struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; | 2083 | struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; |
2078 | struct device_node *np = pdev->dev.of_node; | 2084 | struct device_node *np = pdev->dev.of_node; |
2079 | int ret = 0; | 2085 | int ret = 0; |
2080 | int csi_id; | 2086 | int csi_id; |
2081 | pr_debug("In MVC: %s\n", __func__); | 2087 | pr_debug("In MVC: %s\n", __func__); |
2082 | 2088 | ||
2083 | ret = of_property_read_u32(np, "csi_id", &csi_id); | 2089 | ret = of_property_read_u32(np, "csi_id", &csi_id); |
2084 | if (ret) { | 2090 | if (ret) { |
2085 | dev_err(&pdev->dev, "csi_id missing or invalid\n"); | 2091 | dev_err(&pdev->dev, "csi_id missing or invalid\n"); |
2086 | return; | 2092 | return; |
2087 | } | 2093 | } |
2088 | 2094 | ||
2089 | proc_data->hflip = 0; | 2095 | proc_data->hflip = 0; |
2090 | proc_data->vflip = 0; | 2096 | proc_data->vflip = 0; |
2091 | proc_data->rotate = 0; | 2097 | proc_data->rotate = 0; |
2092 | proc_data->bgcolor = 0; | 2098 | proc_data->bgcolor = 0; |
2093 | 2099 | ||
2094 | /* Default everything to 0 */ | 2100 | /* Default everything to 0 */ |
2095 | memset(cam, 0, sizeof(cam_data)); | 2101 | memset(cam, 0, sizeof(cam_data)); |
2096 | 2102 | ||
2097 | sema_init(&cam->param_lock, 1); | 2103 | sema_init(&cam->param_lock, 1); |
2098 | sema_init(&cam->busy_lock, 1); | 2104 | sema_init(&cam->busy_lock, 1); |
2099 | 2105 | ||
2100 | /* TODO sanity check */ | 2106 | /* TODO sanity check */ |
2101 | cam->csi_soc = csi_get_soc(csi_id); | 2107 | cam->csi_soc = csi_get_soc(csi_id); |
2102 | 2108 | ||
2103 | cam->video_dev = video_device_alloc(); | 2109 | cam->video_dev = video_device_alloc(); |
2104 | if (cam->video_dev == NULL) | 2110 | if (cam->video_dev == NULL) |
2105 | return; | 2111 | return; |
2106 | 2112 | ||
2107 | *(cam->video_dev) = csi_v4l_template; | 2113 | *(cam->video_dev) = csi_v4l_template; |
2108 | 2114 | ||
2109 | video_set_drvdata(cam->video_dev, cam); | 2115 | video_set_drvdata(cam->video_dev, cam); |
2110 | cam->video_dev->minor = -1; | 2116 | cam->video_dev->minor = -1; |
2111 | 2117 | ||
2112 | init_waitqueue_head(&cam->enc_queue); | 2118 | init_waitqueue_head(&cam->enc_queue); |
2113 | init_waitqueue_head(&cam->still_queue); | 2119 | init_waitqueue_head(&cam->still_queue); |
2114 | 2120 | ||
2115 | cam->streamparm.parm.capture.capturemode = 0; | 2121 | cam->streamparm.parm.capture.capturemode = 0; |
2116 | 2122 | ||
2117 | cam->standard.index = 0; | 2123 | cam->standard.index = 0; |
2118 | cam->standard.id = V4L2_STD_UNKNOWN; | 2124 | cam->standard.id = V4L2_STD_UNKNOWN; |
2119 | cam->standard.frameperiod.denominator = 30; | 2125 | cam->standard.frameperiod.denominator = 30; |
2120 | cam->standard.frameperiod.numerator = 1; | 2126 | cam->standard.frameperiod.numerator = 1; |
2121 | cam->standard.framelines = 480; | 2127 | cam->standard.framelines = 480; |
2122 | cam->standard_autodetect = true; | 2128 | cam->standard_autodetect = true; |
2123 | cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 2129 | cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
2124 | cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod; | 2130 | cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod; |
2125 | cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | 2131 | cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME; |
2126 | cam->overlay_on = false; | 2132 | cam->overlay_on = false; |
2127 | cam->capture_on = false; | 2133 | cam->capture_on = false; |
2128 | cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY; | 2134 | cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY; |
2129 | 2135 | ||
2130 | cam->v2f.fmt.pix.sizeimage = 480 * 640 * 2; | 2136 | cam->v2f.fmt.pix.sizeimage = 480 * 640 * 2; |
2131 | cam->v2f.fmt.pix.bytesperline = 640 * 2; | 2137 | cam->v2f.fmt.pix.bytesperline = 640 * 2; |
2132 | cam->v2f.fmt.pix.width = 640; | 2138 | cam->v2f.fmt.pix.width = 640; |
2133 | cam->v2f.fmt.pix.height = 480; | 2139 | cam->v2f.fmt.pix.height = 480; |
2134 | cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; | 2140 | cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; |
2135 | cam->win.w.width = 160; | 2141 | cam->win.w.width = 160; |
2136 | cam->win.w.height = 160; | 2142 | cam->win.w.height = 160; |
2137 | cam->win.w.left = 0; | 2143 | cam->win.w.left = 0; |
2138 | cam->win.w.top = 0; | 2144 | cam->win.w.top = 0; |
2139 | cam->still_counter = 0; | 2145 | cam->still_counter = 0; |
2140 | /* setup cropping */ | 2146 | /* setup cropping */ |
2141 | cam->crop_bounds.left = 0; | 2147 | cam->crop_bounds.left = 0; |
2142 | cam->crop_bounds.width = 640; | 2148 | cam->crop_bounds.width = 640; |
2143 | cam->crop_bounds.top = 0; | 2149 | cam->crop_bounds.top = 0; |
2144 | cam->crop_bounds.height = 480; | 2150 | cam->crop_bounds.height = 480; |
2145 | cam->crop_current = cam->crop_defrect = cam->crop_bounds; | 2151 | cam->crop_current = cam->crop_defrect = cam->crop_bounds; |
2146 | 2152 | ||
2147 | cam->csi = csi_id; | 2153 | cam->csi = csi_id; |
2148 | cam->enc_callback = camera_callback; | 2154 | cam->enc_callback = camera_callback; |
2149 | csi_start_callback(cam); | 2155 | csi_start_callback(cam); |
2150 | init_waitqueue_head(&cam->power_queue); | 2156 | init_waitqueue_head(&cam->power_queue); |
2151 | spin_lock_init(&cam->queue_int_lock); | 2157 | spin_lock_init(&cam->queue_int_lock); |
2152 | spin_lock_init(&cam->dqueue_int_lock); | 2158 | spin_lock_init(&cam->dqueue_int_lock); |
2153 | 2159 | ||
2154 | cam->self = kmalloc(sizeof(struct v4l2_int_device), GFP_KERNEL); | 2160 | cam->self = kmalloc(sizeof(struct v4l2_int_device), GFP_KERNEL); |
2155 | cam->self->module = THIS_MODULE; | 2161 | cam->self->module = THIS_MODULE; |
2156 | sprintf(cam->self->name, "csi_v4l2_cap%d", cam->csi); | 2162 | sprintf(cam->self->name, "csi_v4l2_cap%d", cam->csi); |
2157 | cam->self->type = v4l2_int_type_master; | 2163 | cam->self->type = v4l2_int_type_master; |
2158 | cam->self->u.master = &csi_v4l2_master; | 2164 | cam->self->u.master = &csi_v4l2_master; |
2165 | |||
2166 | cam->pdev = pdev; | ||
2159 | } | 2167 | } |
2160 | 2168 | ||
2161 | /*! | 2169 | /*! |
2162 | * camera_power function | 2170 | * camera_power function |
2163 | * Turns Sensor power On/Off | 2171 | * Turns Sensor power On/Off |
2164 | * | 2172 | * |
2165 | * @param cam cam data struct | 2173 | * @param cam cam data struct |
2166 | * @param cameraOn true to turn camera on, false to turn off power. | 2174 | * @param cameraOn true to turn camera on, false to turn off power. |
2167 | * | 2175 | * |
2168 | * @return status | 2176 | * @return status |
2169 | */ | 2177 | */ |
2170 | static u8 camera_power(cam_data *cam, bool cameraOn) | 2178 | static u8 camera_power(cam_data *cam, bool cameraOn) |
2171 | { | 2179 | { |
2172 | pr_debug("In MVC: %s on=%d\n", __func__, cameraOn); | 2180 | pr_debug("In MVC: %s on=%d\n", __func__, cameraOn); |
2173 | 2181 | ||
2174 | if (cameraOn == true) { | 2182 | if (cameraOn == true) { |
2175 | vidioc_int_s_power(cam->sensor, 1); | 2183 | vidioc_int_s_power(cam->sensor, 1); |
2176 | } else { | 2184 | } else { |
2177 | vidioc_int_s_power(cam->sensor, 0); | 2185 | vidioc_int_s_power(cam->sensor, 0); |
2178 | } | 2186 | } |
2179 | return 0; | 2187 | return 0; |
2180 | } | 2188 | } |
2181 | 2189 | ||
2182 | static const struct of_device_id imx_csi_v4l2_dt_ids[] = { | 2190 | static const struct of_device_id imx_csi_v4l2_dt_ids[] = { |
2183 | { .compatible = "fsl,imx6sl-csi-v4l2", }, | 2191 | { .compatible = "fsl,imx6sl-csi-v4l2", }, |
2184 | { /* sentinel */ } | 2192 | { /* sentinel */ } |
2185 | }; | 2193 | }; |
2186 | MODULE_DEVICE_TABLE(of, imx_csi_v4l2_dt_ids); | 2194 | MODULE_DEVICE_TABLE(of, imx_csi_v4l2_dt_ids); |
2187 | 2195 | ||
2188 | static int csi_v4l2_probe(struct platform_device *pdev) | 2196 | static int csi_v4l2_probe(struct platform_device *pdev) |
2189 | { | 2197 | { |
2190 | static cam_data *g_cam; | 2198 | static cam_data *g_cam; |
2191 | struct scatterlist *sg; | 2199 | struct scatterlist *sg; |
2192 | u8 err = 0; | 2200 | u8 err = 0; |
2193 | 2201 | ||
2194 | /* Create g_cam and initialize it. */ | 2202 | /* Create g_cam and initialize it. */ |
2195 | g_cam = kmalloc(sizeof(cam_data), GFP_KERNEL); | 2203 | g_cam = kmalloc(sizeof(cam_data), GFP_KERNEL); |
2196 | if (g_cam == NULL) { | 2204 | if (g_cam == NULL) { |
2197 | pr_err("ERROR: v4l2 capture: failed to register camera\n"); | 2205 | pr_err("ERROR: v4l2 capture: failed to register camera\n"); |
2198 | err = -ENOMEM; | 2206 | err = -ENOMEM; |
2199 | goto out; | 2207 | goto out; |
2200 | } | 2208 | } |
2201 | memset(&g_cam->input_fmt, 0, sizeof(g_cam->input_fmt)); | 2209 | memset(&g_cam->input_fmt, 0, sizeof(g_cam->input_fmt)); |
2202 | init_camera_struct(g_cam, pdev); | 2210 | init_camera_struct(g_cam, pdev); |
2203 | platform_set_drvdata(pdev, (void *)g_cam); | 2211 | platform_set_drvdata(pdev, (void *)g_cam); |
2204 | 2212 | ||
2205 | /* Set up the v4l2 device and register it */ | 2213 | /* Set up the v4l2 device and register it */ |
2206 | g_cam->self->priv = g_cam; | 2214 | g_cam->self->priv = g_cam; |
2207 | v4l2_int_device_register(g_cam->self); | 2215 | v4l2_int_device_register(g_cam->self); |
2208 | 2216 | ||
2209 | /* register v4l video device */ | 2217 | /* register v4l video device */ |
2210 | if (video_register_device(g_cam->video_dev, VFL_TYPE_GRABBER, video_nr) | 2218 | if (video_register_device(g_cam->video_dev, VFL_TYPE_GRABBER, video_nr) |
2211 | == -1) { | 2219 | == -1) { |
2212 | kfree(g_cam); | 2220 | kfree(g_cam); |
2213 | g_cam = NULL; | 2221 | g_cam = NULL; |
2214 | pr_err("ERROR: v4l2 capture: video_register_device failed\n"); | 2222 | pr_err("ERROR: v4l2 capture: video_register_device failed\n"); |
2215 | err = -ENODEV; | 2223 | err = -ENODEV; |
2216 | goto out; | 2224 | goto out; |
2217 | } | 2225 | } |
2218 | pr_debug(" Video device registered: %s #%d\n", | 2226 | pr_debug(" Video device registered: %s #%d\n", |
2219 | g_cam->video_dev->name, g_cam->video_dev->minor); | 2227 | g_cam->video_dev->name, g_cam->video_dev->minor); |
2220 | 2228 | ||
2221 | g_cam->pxp_chan = NULL; | 2229 | g_cam->pxp_chan = NULL; |
2222 | /* Initialize Scatter-gather list containing 2 buffer addresses. */ | 2230 | /* Initialize Scatter-gather list containing 2 buffer addresses. */ |
2223 | sg = g_cam->sg; | 2231 | sg = g_cam->sg; |
2224 | sg_init_table(sg, 2); | 2232 | sg_init_table(sg, 2); |
2225 | 2233 | ||
2234 | pm_runtime_enable(&g_cam->pdev->dev); | ||
2226 | out: | 2235 | out: |
2227 | return err; | 2236 | return err; |
2228 | } | 2237 | } |
2229 | 2238 | ||
2230 | static int csi_v4l2_remove(struct platform_device *pdev) | 2239 | static int csi_v4l2_remove(struct platform_device *pdev) |
2231 | { | 2240 | { |
2232 | cam_data *g_cam = platform_get_drvdata(pdev); | 2241 | cam_data *g_cam = platform_get_drvdata(pdev); |
2233 | 2242 | ||
2234 | if (g_cam == NULL) | 2243 | if (g_cam == NULL) |
2235 | return -EINVAL; | 2244 | return -EINVAL; |
2236 | 2245 | ||
2237 | if (g_cam->open_count) { | 2246 | if (g_cam->open_count) { |
2238 | pr_err("ERROR: v4l2 capture:camera open " | 2247 | pr_err("ERROR: v4l2 capture:camera open " |
2239 | "-- setting ops to NULL\n"); | 2248 | "-- setting ops to NULL\n"); |
2240 | } else { | 2249 | } else { |
2241 | pr_info("V4L2 freeing image input device\n"); | 2250 | pr_info("V4L2 freeing image input device\n"); |
2242 | v4l2_int_device_unregister(g_cam->self); | 2251 | v4l2_int_device_unregister(g_cam->self); |
2243 | csi_stop_callback(g_cam); | 2252 | csi_stop_callback(g_cam); |
2244 | video_unregister_device(g_cam->video_dev); | 2253 | video_unregister_device(g_cam->video_dev); |
2245 | platform_set_drvdata(pdev, NULL); | 2254 | platform_set_drvdata(pdev, NULL); |
2255 | pm_runtime_disable(&g_cam->pdev->dev); | ||
2246 | 2256 | ||
2247 | kfree(g_cam); | 2257 | kfree(g_cam); |
2248 | g_cam = NULL; | 2258 | g_cam = NULL; |
2249 | } | 2259 | } |
2250 | 2260 | ||
2251 | return 0; | 2261 | return 0; |
2252 | } | 2262 | } |
2253 | 2263 | ||
2264 | #ifdef CONFIG_PM_RUNTIME | ||
2265 | static int csi_v4l2_runtime_suspend(struct device *dev) | ||
2266 | { | ||
2267 | int ret = 0; | ||
2268 | |||
2269 | release_bus_freq(BUS_FREQ_HIGH); | ||
2270 | dev_dbg(dev, "csi v4l2 busfreq high release.\n"); | ||
2271 | |||
2272 | csi_regulator_disable(); | ||
2273 | |||
2274 | return ret; | ||
2275 | } | ||
2276 | |||
2277 | static int csi_v4l2_runtime_resume(struct device *dev) | ||
2278 | { | ||
2279 | int ret = 0; | ||
2280 | |||
2281 | request_bus_freq(BUS_FREQ_HIGH); | ||
2282 | dev_dbg(dev, "csi v4l2 busfreq high request.\n"); | ||
2283 | |||
2284 | csi_regulator_enable(); | ||
2285 | |||
2286 | return ret; | ||
2287 | } | ||
2288 | #else | ||
2289 | #define mxsfb_runtime_suspend NULL | ||
2290 | #define mxsfb_runtime_resume NULL | ||
2291 | #endif | ||
2292 | |||
2293 | #ifdef CONFIG_PM_SLEEP | ||
2254 | /*! | 2294 | /*! |
2255 | * This function is called to put the sensor in a low power state. | 2295 | * This function is called to put the sensor in a low power state. |
2256 | * Refer to the document driver-model/driver.txt in the kernel source tree | 2296 | * Refer to the document driver-model/driver.txt in the kernel source tree |
2257 | * for more information. | 2297 | * for more information. |
2258 | * | 2298 | * |
2259 | * @param pdev the device structure used to give information on which I2C | 2299 | * @param pdev the device structure used to give information on which I2C |
2260 | * to suspend | 2300 | * to suspend |
2261 | * @param state the power state the device is entering | 2301 | * @param state the power state the device is entering |
2262 | * | 2302 | * |
2263 | * @return The function returns 0 on success and -1 on failure. | 2303 | * @return The function returns 0 on success and -1 on failure. |
2264 | */ | 2304 | */ |
2265 | static int csi_v4l2_suspend(struct platform_device *pdev, pm_message_t state) | 2305 | static int csi_v4l2_suspend(struct device *dev) |
2266 | { | 2306 | { |
2267 | cam_data *cam = platform_get_drvdata(pdev); | 2307 | cam_data *cam = dev_get_drvdata(dev); |
2268 | 2308 | ||
2269 | pr_debug("In MVC: %s\n", __func__); | 2309 | pr_debug("In MVC: %s\n", __func__); |
2270 | 2310 | ||
2271 | if (cam == NULL) | 2311 | if (cam == NULL) |
2272 | return -1; | 2312 | return -1; |
2273 | 2313 | ||
2274 | cam->low_power = true; | 2314 | cam->low_power = true; |
2275 | 2315 | ||
2276 | if (cam->overlay_on == true) | 2316 | if (cam->overlay_on == true) |
2277 | stop_preview(cam); | 2317 | stop_preview(cam); |
2278 | 2318 | ||
2279 | if (cam->capture_on == true || cam->overlay_on == true) | 2319 | if (cam->capture_on == true || cam->overlay_on == true) |
2280 | camera_power(cam, false); | 2320 | camera_power(cam, false); |
2281 | 2321 | ||
2282 | return 0; | 2322 | return 0; |
2283 | } | 2323 | } |
2284 | 2324 | ||
2285 | /*! | 2325 | /*! |
2286 | * This function is called to bring the sensor back from a low power state. | 2326 | * This function is called to bring the sensor back from a low power state. |
2287 | * Refer to the document driver-model/driver.txt in the kernel source tree | 2327 | * Refer to the document driver-model/driver.txt in the kernel source tree |
2288 | * for more information. | 2328 | * for more information. |
2289 | * | 2329 | * |
2290 | * @param pdev the device structure | 2330 | * @param pdev the device structure |
2291 | * | 2331 | * |
2292 | * @return The function returns 0 on success and -1 on failure | 2332 | * @return The function returns 0 on success and -1 on failure |
2293 | */ | 2333 | */ |
2294 | static int csi_v4l2_resume(struct platform_device *pdev) | 2334 | static int csi_v4l2_resume(struct device *dev) |
2295 | { | 2335 | { |
2296 | cam_data *cam = platform_get_drvdata(pdev); | 2336 | cam_data *cam = dev_get_drvdata(dev); |
2297 | 2337 | ||
2298 | pr_debug("In MVC: %s\n", __func__); | 2338 | pr_debug("In MVC: %s\n", __func__); |
2299 | 2339 | ||
2300 | if (cam == NULL) | 2340 | if (cam == NULL) |
2301 | return -1; | 2341 | return -1; |
2302 | 2342 | ||
2303 | cam->low_power = false; | 2343 | cam->low_power = false; |
2304 | wake_up_interruptible(&cam->power_queue); | 2344 | wake_up_interruptible(&cam->power_queue); |
2305 | if (cam->capture_on == true || cam->overlay_on == true) | 2345 | if (cam->capture_on == true || cam->overlay_on == true) |
2306 | camera_power(cam, true); | 2346 | camera_power(cam, true); |
2307 | 2347 | ||
2308 | if (cam->overlay_on == true) | 2348 | if (cam->overlay_on == true) |
2309 | start_preview(cam); | 2349 | start_preview(cam); |
2310 | 2350 | ||
2311 | return 0; | 2351 | return 0; |
2312 | } | 2352 | } |
2353 | #else | ||
2354 | #define csi_v4l2_suspend NULL | ||
2355 | #define csi_v4l2_resume NULL | ||
2356 | #endif | ||
2313 | 2357 | ||
2358 | static const struct dev_pm_ops csi_v4l2_pm_ops = { | ||
2359 | SET_RUNTIME_PM_OPS(csi_v4l2_runtime_suspend, csi_v4l2_runtime_resume, NULL) | ||
2360 | SET_SYSTEM_SLEEP_PM_OPS(csi_v4l2_suspend, csi_v4l2_resume) | ||
2361 | }; | ||
2362 | |||
2314 | /*! | 2363 | /*! |
2315 | * This structure contains pointers to the power management callback functions. | 2364 | * This structure contains pointers to the power management callback functions. |
2316 | */ | 2365 | */ |
2317 | static struct platform_driver csi_v4l2_driver = { | 2366 | static struct platform_driver csi_v4l2_driver = { |
2318 | .driver = { | 2367 | .driver = { |
2319 | .name = "csi_v4l2", | 2368 | .name = "csi_v4l2", |
2320 | .of_match_table = of_match_ptr(imx_csi_v4l2_dt_ids), | 2369 | .of_match_table = of_match_ptr(imx_csi_v4l2_dt_ids), |
2370 | .pm = &csi_v4l2_pm_ops, | ||
2321 | }, | 2371 | }, |
2322 | .probe = csi_v4l2_probe, | 2372 | .probe = csi_v4l2_probe, |
2323 | .remove = csi_v4l2_remove, | 2373 | .remove = csi_v4l2_remove, |
2324 | #ifdef CONFIG_PM | ||
2325 | .suspend = csi_v4l2_suspend, | ||
2326 | .resume = csi_v4l2_resume, | ||
2327 | #endif | ||
2328 | .shutdown = NULL, | 2374 | .shutdown = NULL, |
2329 | }; | 2375 | }; |
2330 | 2376 | ||
2331 | /*! | 2377 | /*! |
2332 | * Initializes the camera driver. | 2378 | * Initializes the camera driver. |
2333 | */ | 2379 | */ |
2334 | static int csi_v4l2_master_attach(struct v4l2_int_device *slave) | 2380 | static int csi_v4l2_master_attach(struct v4l2_int_device *slave) |
2335 | { | 2381 | { |
2336 | cam_data *cam = slave->u.slave->master->priv; | 2382 | cam_data *cam = slave->u.slave->master->priv; |
2337 | struct sensor_data *sdata = slave->priv; | 2383 | struct sensor_data *sdata = slave->priv; |
2338 | struct v4l2_format cam_fmt; | 2384 | struct v4l2_format cam_fmt; |
2339 | 2385 | ||
2340 | pr_debug("In MVC: %s\n", __func__); | 2386 | pr_debug("In MVC: %s\n", __func__); |
2341 | pr_debug(" slave.name = %s\n", slave->name); | 2387 | pr_debug(" slave.name = %s\n", slave->name); |
2342 | pr_debug(" master.name = %s\n", slave->u.slave->master->name); | 2388 | pr_debug(" master.name = %s\n", slave->u.slave->master->name); |
2343 | 2389 | ||
2344 | if (slave == NULL) { | 2390 | if (slave == NULL) { |
2345 | pr_err("ERROR: v4l2 capture: slave parameter not valid.\n"); | 2391 | pr_err("ERROR: v4l2 capture: slave parameter not valid.\n"); |
2346 | return -1; | 2392 | return -1; |
2347 | } | 2393 | } |
2348 | if (sdata->csi != cam->csi) { | 2394 | if (sdata->csi != cam->csi) { |
2349 | pr_debug("%s: csi doesn't match\n", __func__); | 2395 | pr_debug("%s: csi doesn't match\n", __func__); |
2350 | return -1; | 2396 | return -1; |
2351 | } | 2397 | } |
2352 | 2398 | ||
2353 | cam->sensor = slave; | 2399 | cam->sensor = slave; |
2354 | 2400 | ||
2355 | cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 2401 | cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
2356 | vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); | 2402 | vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); |
2357 | 2403 | ||
2358 | /* Used to detect TV in (type 1) vs. camera (type 0) */ | 2404 | /* Used to detect TV in (type 1) vs. camera (type 0) */ |
2359 | cam->device_type = cam_fmt.fmt.pix.priv; | 2405 | cam->device_type = cam_fmt.fmt.pix.priv; |
2360 | 2406 | ||
2361 | cam->crop_bounds.top = cam->crop_bounds.left = 0; | 2407 | cam->crop_bounds.top = cam->crop_bounds.left = 0; |
2362 | cam->crop_bounds.width = cam_fmt.fmt.pix.width; | 2408 | cam->crop_bounds.width = cam_fmt.fmt.pix.width; |
2363 | cam->crop_bounds.height = cam_fmt.fmt.pix.height; | 2409 | cam->crop_bounds.height = cam_fmt.fmt.pix.height; |
2364 | 2410 | ||
2365 | /* This also is the max crop size for this device. */ | 2411 | /* This also is the max crop size for this device. */ |
2366 | cam->crop_defrect.top = cam->crop_defrect.left = 0; | 2412 | cam->crop_defrect.top = cam->crop_defrect.left = 0; |
2367 | cam->crop_defrect.width = cam_fmt.fmt.pix.width; | 2413 | cam->crop_defrect.width = cam_fmt.fmt.pix.width; |
2368 | cam->crop_defrect.height = cam_fmt.fmt.pix.height; | 2414 | cam->crop_defrect.height = cam_fmt.fmt.pix.height; |
2369 | 2415 | ||
2370 | /* At this point, this is also the current image size. */ | 2416 | /* At this point, this is also the current image size. */ |
2371 | cam->crop_current.top = cam->crop_current.left = 0; | 2417 | cam->crop_current.top = cam->crop_current.left = 0; |
2372 | cam->crop_current.width = cam_fmt.fmt.pix.width; | 2418 | cam->crop_current.width = cam_fmt.fmt.pix.width; |
2373 | cam->crop_current.height = cam_fmt.fmt.pix.height; | 2419 | cam->crop_current.height = cam_fmt.fmt.pix.height; |
2374 | 2420 | ||
2375 | pr_debug("End of %s: v2f pix widthxheight %d x %d\n", | 2421 | pr_debug("End of %s: v2f pix widthxheight %d x %d\n", |
2376 | __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); | 2422 | __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); |
2377 | 2423 | ||
2378 | return 0; | 2424 | return 0; |
2379 | } | 2425 | } |
2380 | 2426 | ||
2381 | /*! | 2427 | /*! |
2382 | * Disconnects the camera driver. | 2428 | * Disconnects the camera driver. |
2383 | */ | 2429 | */ |
2384 | static void csi_v4l2_master_detach(struct v4l2_int_device *slave) | 2430 | static void csi_v4l2_master_detach(struct v4l2_int_device *slave) |
2385 | { | 2431 | { |
2386 | pr_debug("In MVC: %s\n", __func__); | 2432 | pr_debug("In MVC: %s\n", __func__); |
2387 | 2433 | ||
2388 | vidioc_int_dev_exit(slave); | 2434 | vidioc_int_dev_exit(slave); |
2389 | } | 2435 | } |
2390 | 2436 | ||
2391 | module_platform_driver(csi_v4l2_driver); | 2437 | module_platform_driver(csi_v4l2_driver); |
2392 | 2438 | ||
2393 | module_param(video_nr, int, 0444); | 2439 | module_param(video_nr, int, 0444); |
2394 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | 2440 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
drivers/media/platform/mxc/capture/fsl_csi.c
1 | /* | 1 | /* |
2 | * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved. | 2 | * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | /* | 5 | /* |
6 | * The code contained herein is licensed under the GNU General Public | 6 | * The code contained herein is licensed under the GNU General Public |
7 | * License. You may obtain a copy of the GNU General Public License | 7 | * License. You may obtain a copy of the GNU General Public License |
8 | * Version 2 or later at the following locations: | 8 | * Version 2 or later at the following locations: |
9 | * | 9 | * |
10 | * http://www.opensource.org/licenses/gpl-license.html | 10 | * http://www.opensource.org/licenses/gpl-license.html |
11 | * http://www.gnu.org/copyleft/gpl.html | 11 | * http://www.gnu.org/copyleft/gpl.html |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /*! | 14 | /*! |
15 | * @file fsl_csi.c, this file is derived from mx27_csi.c | 15 | * @file fsl_csi.c, this file is derived from mx27_csi.c |
16 | * | 16 | * |
17 | * @brief mx25 CMOS Sensor interface functions | 17 | * @brief mx25 CMOS Sensor interface functions |
18 | * | 18 | * |
19 | * @ingroup CSI | 19 | * @ingroup CSI |
20 | */ | 20 | */ |
21 | #include <linux/busfreq-imx6.h> | ||
22 | #include <linux/types.h> | 21 | #include <linux/types.h> |
23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
24 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
25 | #include <linux/pm_runtime.h> | 24 | #include <linux/delay.h> |
26 | #include <linux/device.h> | 25 | #include <linux/device.h> |
27 | #include <linux/err.h> | 26 | #include <linux/err.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
29 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
30 | #include <linux/module.h> | 29 | #include <linux/module.h> |
31 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
32 | #include <linux/of.h> | 31 | #include <linux/of.h> |
33 | #include <linux/regulator/consumer.h> | 32 | #include <linux/regulator/consumer.h> |
34 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
35 | 34 | ||
36 | #include "mxc_v4l2_capture.h" | 35 | #include "mxc_v4l2_capture.h" |
37 | #include "fsl_csi.h" | 36 | #include "fsl_csi.h" |
38 | 37 | ||
39 | #define CSI_MAX_NUM 2 | 38 | #define CSI_MAX_NUM 2 |
40 | struct csi_soc csi_array[CSI_MAX_NUM], *csi; | 39 | struct csi_soc csi_array[CSI_MAX_NUM], *csi; |
41 | 40 | ||
42 | static csi_irq_callback_t g_callback; | 41 | static csi_irq_callback_t g_callback; |
43 | static void *g_callback_data; | 42 | static void *g_callback_data; |
44 | static struct clk *disp_axi_clk; | 43 | static struct clk *disp_axi_clk; |
45 | static struct clk *dcic_clk; | 44 | static struct clk *dcic_clk; |
46 | static struct clk *csi_clk; | 45 | static struct clk *csi_clk; |
47 | struct platform_device *csi_pdev; | 46 | static struct regulator *disp_reg; |
48 | 47 | ||
49 | void csi_clk_enable(void) | 48 | int csi_regulator_enable(void) |
50 | { | 49 | { |
51 | pm_runtime_get_sync(&csi_pdev->dev); | 50 | int ret = 0; |
52 | 51 | ||
52 | if (disp_reg) | ||
53 | ret = regulator_enable(disp_reg); | ||
54 | |||
55 | return ret; | ||
56 | } | ||
57 | EXPORT_SYMBOL(csi_regulator_enable); | ||
58 | |||
59 | void csi_regulator_disable(void) | ||
60 | { | ||
61 | if (disp_reg) | ||
62 | regulator_disable(disp_reg); | ||
63 | } | ||
64 | EXPORT_SYMBOL(csi_regulator_disable); | ||
65 | |||
66 | void csi_clk_enable(void) | ||
67 | { | ||
53 | clk_prepare_enable(disp_axi_clk); | 68 | clk_prepare_enable(disp_axi_clk); |
54 | clk_prepare_enable(dcic_clk); | 69 | clk_prepare_enable(dcic_clk); |
55 | clk_prepare_enable(csi_clk); | 70 | clk_prepare_enable(csi_clk); |
56 | } | 71 | } |
57 | EXPORT_SYMBOL(csi_clk_enable); | 72 | EXPORT_SYMBOL(csi_clk_enable); |
58 | 73 | ||
59 | void csi_clk_disable(void) | 74 | void csi_clk_disable(void) |
60 | { | 75 | { |
61 | clk_disable_unprepare(csi_clk); | 76 | clk_disable_unprepare(csi_clk); |
62 | clk_disable_unprepare(dcic_clk); | 77 | clk_disable_unprepare(dcic_clk); |
63 | clk_disable_unprepare(disp_axi_clk); | 78 | clk_disable_unprepare(disp_axi_clk); |
64 | |||
65 | pm_runtime_put_sync_suspend(&csi_pdev->dev); | ||
66 | } | 79 | } |
67 | EXPORT_SYMBOL(csi_clk_disable); | 80 | EXPORT_SYMBOL(csi_clk_disable); |
68 | 81 | ||
69 | static irqreturn_t csi_irq_handler(int irq, void *data) | 82 | static irqreturn_t csi_irq_handler(int irq, void *data) |
70 | { | 83 | { |
71 | cam_data *cam = (cam_data *) data; | 84 | cam_data *cam = (cam_data *) data; |
72 | struct csi_soc *csi = &csi_array[cam->csi]; | 85 | struct csi_soc *csi = &csi_array[cam->csi]; |
73 | unsigned long status = __raw_readl(csi->regbase + CSI_CSISR); | 86 | unsigned long status = __raw_readl(csi->regbase + CSI_CSISR); |
74 | u32 cr3, cr18; | 87 | u32 cr3, cr18; |
75 | 88 | ||
76 | __raw_writel(status, csi->regbase + CSI_CSISR); | 89 | __raw_writel(status, csi->regbase + CSI_CSISR); |
77 | 90 | ||
78 | if (status & BIT_HRESP_ERR_INT) | 91 | if (status & BIT_HRESP_ERR_INT) |
79 | pr_warning("Hresponse error is detected.\n"); | 92 | pr_warning("Hresponse error is detected.\n"); |
80 | 93 | ||
81 | if (status & BIT_ADDR_CH_ERR_INT) { | 94 | if (status & BIT_ADDR_CH_ERR_INT) { |
82 | /* Disable csi */ | 95 | /* Disable csi */ |
83 | cr18 = __raw_readl(csi->regbase + CSI_CSICR18); | 96 | cr18 = __raw_readl(csi->regbase + CSI_CSICR18); |
84 | cr18 &= ~BIT_CSI_ENABLE; | 97 | cr18 &= ~BIT_CSI_ENABLE; |
85 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); | 98 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); |
86 | 99 | ||
87 | /* DMA reflash */ | 100 | /* DMA reflash */ |
88 | cr3 = __raw_readl(csi->regbase + CSI_CSICR3); | 101 | cr3 = __raw_readl(csi->regbase + CSI_CSICR3); |
89 | cr3 |= BIT_DMA_REFLASH_RFF; | 102 | cr3 |= BIT_DMA_REFLASH_RFF; |
90 | __raw_writel(cr3, csi->regbase + CSI_CSICR3); | 103 | __raw_writel(cr3, csi->regbase + CSI_CSICR3); |
91 | 104 | ||
92 | /* Ensable csi */ | 105 | /* Ensable csi */ |
93 | cr18 |= BIT_CSI_ENABLE; | 106 | cr18 |= BIT_CSI_ENABLE; |
94 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); | 107 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); |
95 | 108 | ||
96 | pr_debug("base address switching Change Err.\n"); | 109 | pr_debug("base address switching Change Err.\n"); |
97 | } | 110 | } |
98 | 111 | ||
99 | if ((status & BIT_DMA_TSF_DONE_FB1) && | 112 | if ((status & BIT_DMA_TSF_DONE_FB1) && |
100 | (status & BIT_DMA_TSF_DONE_FB2)) { | 113 | (status & BIT_DMA_TSF_DONE_FB2)) { |
101 | /* For both FB1 and FB2 interrupter bits set case, | 114 | /* For both FB1 and FB2 interrupter bits set case, |
102 | * CSI DMA is work in one of FB1 and FB2 buffer, | 115 | * CSI DMA is work in one of FB1 and FB2 buffer, |
103 | * but software can not know the state. | 116 | * but software can not know the state. |
104 | * Skip it to avoid base address updated | 117 | * Skip it to avoid base address updated |
105 | * when csi work in field0 and field1 will write to | 118 | * when csi work in field0 and field1 will write to |
106 | * new base address. | 119 | * new base address. |
107 | * PDM TKT230775 */ | 120 | * PDM TKT230775 */ |
108 | pr_debug("Skip two frames\n"); | 121 | pr_debug("Skip two frames\n"); |
109 | } else if (status & BIT_DMA_TSF_DONE_FB1) { | 122 | } else if (status & BIT_DMA_TSF_DONE_FB1) { |
110 | if (cam->capture_on) { | 123 | if (cam->capture_on) { |
111 | spin_lock(&cam->queue_int_lock); | 124 | spin_lock(&cam->queue_int_lock); |
112 | cam->ping_pong_csi = 1; | 125 | cam->ping_pong_csi = 1; |
113 | spin_unlock(&cam->queue_int_lock); | 126 | spin_unlock(&cam->queue_int_lock); |
114 | cam->enc_callback(0, cam); | 127 | cam->enc_callback(0, cam); |
115 | } else { | 128 | } else { |
116 | cam->still_counter++; | 129 | cam->still_counter++; |
117 | wake_up_interruptible(&cam->still_queue); | 130 | wake_up_interruptible(&cam->still_queue); |
118 | } | 131 | } |
119 | } else if (status & BIT_DMA_TSF_DONE_FB2) { | 132 | } else if (status & BIT_DMA_TSF_DONE_FB2) { |
120 | if (cam->capture_on) { | 133 | if (cam->capture_on) { |
121 | spin_lock(&cam->queue_int_lock); | 134 | spin_lock(&cam->queue_int_lock); |
122 | cam->ping_pong_csi = 2; | 135 | cam->ping_pong_csi = 2; |
123 | spin_unlock(&cam->queue_int_lock); | 136 | spin_unlock(&cam->queue_int_lock); |
124 | cam->enc_callback(0, cam); | 137 | cam->enc_callback(0, cam); |
125 | } else { | 138 | } else { |
126 | cam->still_counter++; | 139 | cam->still_counter++; |
127 | wake_up_interruptible(&cam->still_queue); | 140 | wake_up_interruptible(&cam->still_queue); |
128 | } | 141 | } |
129 | } | 142 | } |
130 | 143 | ||
131 | if (g_callback) | 144 | if (g_callback) |
132 | g_callback(g_callback_data, status); | 145 | g_callback(g_callback_data, status); |
133 | 146 | ||
134 | pr_debug("CSI status = 0x%08lX\n", status); | 147 | pr_debug("CSI status = 0x%08lX\n", status); |
135 | 148 | ||
136 | return IRQ_HANDLED; | 149 | return IRQ_HANDLED; |
137 | } | 150 | } |
138 | 151 | ||
139 | static void csihw_reset_frame_count(struct csi_soc *csi) | 152 | static void csihw_reset_frame_count(struct csi_soc *csi) |
140 | { | 153 | { |
141 | __raw_writel(__raw_readl(csi->regbase + CSI_CSICR3) | BIT_FRMCNT_RST, | 154 | __raw_writel(__raw_readl(csi->regbase + CSI_CSICR3) | BIT_FRMCNT_RST, |
142 | csi->regbase + CSI_CSICR3); | 155 | csi->regbase + CSI_CSICR3); |
143 | } | 156 | } |
144 | 157 | ||
145 | static void csihw_reset(struct csi_soc *csi) | 158 | static void csihw_reset(struct csi_soc *csi) |
146 | { | 159 | { |
147 | csihw_reset_frame_count(csi); | 160 | csihw_reset_frame_count(csi); |
148 | __raw_writel(CSICR1_RESET_VAL, csi->regbase + CSI_CSICR1); | 161 | __raw_writel(CSICR1_RESET_VAL, csi->regbase + CSI_CSICR1); |
149 | __raw_writel(CSICR2_RESET_VAL, csi->regbase + CSI_CSICR2); | 162 | __raw_writel(CSICR2_RESET_VAL, csi->regbase + CSI_CSICR2); |
150 | __raw_writel(CSICR3_RESET_VAL, csi->regbase + CSI_CSICR3); | 163 | __raw_writel(CSICR3_RESET_VAL, csi->regbase + CSI_CSICR3); |
151 | } | 164 | } |
152 | 165 | ||
166 | static void csisw_reset(struct csi_soc *csi) | ||
167 | { | ||
168 | int cr1, cr3, cr18, isr; | ||
169 | |||
170 | /* Disable csi */ | ||
171 | cr18 = __raw_readl(csi->regbase + CSI_CSICR18); | ||
172 | cr18 &= ~BIT_CSI_ENABLE; | ||
173 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); | ||
174 | |||
175 | /* Clear RX FIFO */ | ||
176 | cr1 = __raw_readl(csi->regbase + CSI_CSICR1); | ||
177 | __raw_writel(cr1 & ~BIT_FCC, csi->regbase + CSI_CSICR1); | ||
178 | cr1 = __raw_readl(csi->regbase + CSI_CSICR1); | ||
179 | __raw_writel(cr1 | BIT_CLR_RXFIFO, csi->regbase + CSI_CSICR1); | ||
180 | |||
181 | /* DMA reflash */ | ||
182 | cr3 = __raw_readl(csi->regbase + CSI_CSICR3); | ||
183 | cr3 |= BIT_DMA_REFLASH_RFF | BIT_FRMCNT_RST; | ||
184 | __raw_writel(cr3, csi->regbase + CSI_CSICR3); | ||
185 | |||
186 | msleep(2); | ||
187 | |||
188 | cr1 = __raw_readl(csi->regbase + CSI_CSICR1); | ||
189 | __raw_writel(cr1 | BIT_FCC, csi->regbase + CSI_CSICR1); | ||
190 | |||
191 | isr = __raw_readl(csi->regbase + CSI_CSISR); | ||
192 | __raw_writel(isr, csi->regbase + CSI_CSISR); | ||
193 | |||
194 | /* Ensable csi */ | ||
195 | cr18 |= BIT_CSI_ENABLE; | ||
196 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); | ||
197 | } | ||
198 | |||
153 | /*! | 199 | /*! |
154 | * csi_init_interface | 200 | * csi_init_interface |
155 | * Init csi interface | 201 | * Init csi interface |
156 | */ | 202 | */ |
157 | static void csi_init_interface(struct csi_soc *csi) | 203 | static void csi_init_interface(struct csi_soc *csi) |
158 | { | 204 | { |
159 | unsigned int val = 0; | 205 | unsigned int val = 0; |
160 | unsigned int imag_para; | 206 | unsigned int imag_para; |
161 | 207 | ||
162 | val |= BIT_SOF_POL; | 208 | val |= BIT_SOF_POL; |
163 | val |= BIT_REDGE; | 209 | val |= BIT_REDGE; |
164 | val |= BIT_GCLK_MODE; | 210 | val |= BIT_GCLK_MODE; |
165 | val |= BIT_HSYNC_POL; | 211 | val |= BIT_HSYNC_POL; |
166 | val |= BIT_FCC; | 212 | val |= BIT_FCC; |
167 | val |= 1 << SHIFT_MCLKDIV; | 213 | val |= 1 << SHIFT_MCLKDIV; |
168 | val |= BIT_MCLKEN; | 214 | val |= BIT_MCLKEN; |
169 | __raw_writel(val, csi->regbase + CSI_CSICR1); | 215 | __raw_writel(val, csi->regbase + CSI_CSICR1); |
170 | 216 | ||
171 | imag_para = (640 << 16) | 960; | 217 | imag_para = (640 << 16) | 960; |
172 | __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA); | 218 | __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA); |
173 | 219 | ||
174 | val = 0x1010; | 220 | val = 0x1010; |
175 | val |= BIT_DMA_REFLASH_RFF; | 221 | val |= BIT_DMA_REFLASH_RFF; |
176 | __raw_writel(val, csi->regbase + CSI_CSICR3); | 222 | __raw_writel(val, csi->regbase + CSI_CSICR3); |
177 | } | 223 | } |
178 | 224 | ||
179 | void csi_format_swap16(cam_data *cam, bool enable) | 225 | void csi_format_swap16(cam_data *cam, bool enable) |
180 | { | 226 | { |
181 | struct csi_soc *csi = &csi_array[cam->csi]; | 227 | struct csi_soc *csi = &csi_array[cam->csi]; |
182 | unsigned int val; | 228 | unsigned int val; |
183 | 229 | ||
184 | val = __raw_readl(csi->regbase + CSI_CSICR1); | 230 | val = __raw_readl(csi->regbase + CSI_CSICR1); |
185 | if (enable) { | 231 | if (enable) { |
186 | val |= BIT_PACK_DIR; | 232 | val |= BIT_PACK_DIR; |
187 | val |= BIT_SWAP16_EN; | 233 | val |= BIT_SWAP16_EN; |
188 | } else { | 234 | } else { |
189 | val &= ~BIT_PACK_DIR; | 235 | val &= ~BIT_PACK_DIR; |
190 | val &= ~BIT_SWAP16_EN; | 236 | val &= ~BIT_SWAP16_EN; |
191 | } | 237 | } |
192 | 238 | ||
193 | __raw_writel(val, csi->regbase + CSI_CSICR1); | 239 | __raw_writel(val, csi->regbase + CSI_CSICR1); |
194 | } | 240 | } |
195 | EXPORT_SYMBOL(csi_format_swap16); | 241 | EXPORT_SYMBOL(csi_format_swap16); |
196 | 242 | ||
197 | /*! | 243 | /*! |
198 | * csi_read_mclk_flag | 244 | * csi_read_mclk_flag |
199 | * | 245 | * |
200 | * @return gcsi_mclk_source | 246 | * @return gcsi_mclk_source |
201 | */ | 247 | */ |
202 | int csi_read_mclk_flag(void) | 248 | int csi_read_mclk_flag(void) |
203 | { | 249 | { |
204 | return 0; | 250 | return 0; |
205 | } | 251 | } |
206 | EXPORT_SYMBOL(csi_read_mclk_flag); | 252 | EXPORT_SYMBOL(csi_read_mclk_flag); |
207 | 253 | ||
208 | void csi_start_callback(void *data) | 254 | void csi_start_callback(void *data) |
209 | { | 255 | { |
210 | cam_data *cam = (cam_data *) data; | 256 | cam_data *cam = (cam_data *) data; |
211 | 257 | ||
212 | if (request_irq(csi_array[cam->csi].irq_nr, csi_irq_handler, 0, "csi", | 258 | if (request_irq(csi_array[cam->csi].irq_nr, csi_irq_handler, 0, "csi", |
213 | cam) < 0) | 259 | cam) < 0) |
214 | pr_debug("CSI error: irq request fail\n"); | 260 | pr_debug("CSI error: irq request fail\n"); |
215 | 261 | ||
216 | } | 262 | } |
217 | EXPORT_SYMBOL(csi_start_callback); | 263 | EXPORT_SYMBOL(csi_start_callback); |
218 | 264 | ||
219 | void csi_stop_callback(void *data) | 265 | void csi_stop_callback(void *data) |
220 | { | 266 | { |
221 | cam_data *cam = (cam_data *) data; | 267 | cam_data *cam = (cam_data *) data; |
222 | 268 | ||
223 | free_irq(csi_array[cam->csi].irq_nr, cam); | 269 | free_irq(csi_array[cam->csi].irq_nr, cam); |
224 | } | 270 | } |
225 | EXPORT_SYMBOL(csi_stop_callback); | 271 | EXPORT_SYMBOL(csi_stop_callback); |
226 | 272 | ||
227 | void csi_enable_int(cam_data *cam, int arg) | 273 | void csi_enable_int(cam_data *cam, int arg) |
228 | { | 274 | { |
229 | struct csi_soc *csi = &csi_array[cam->csi]; | 275 | struct csi_soc *csi = &csi_array[cam->csi]; |
230 | unsigned long cr1 = __raw_readl(csi->regbase + CSI_CSICR1); | 276 | unsigned long cr1 = __raw_readl(csi->regbase + CSI_CSICR1); |
231 | 277 | ||
232 | cr1 |= BIT_SOF_INTEN; | 278 | cr1 |= BIT_SOF_INTEN; |
233 | if (arg == 1) { | 279 | if (arg == 1) { |
234 | /* still capture needs DMA intterrupt */ | 280 | /* still capture needs DMA intterrupt */ |
235 | cr1 |= BIT_FB1_DMA_DONE_INTEN; | 281 | cr1 |= BIT_FB1_DMA_DONE_INTEN; |
236 | cr1 |= BIT_FB2_DMA_DONE_INTEN; | 282 | cr1 |= BIT_FB2_DMA_DONE_INTEN; |
237 | } | 283 | } |
238 | __raw_writel(cr1, csi->regbase + CSI_CSICR1); | 284 | __raw_writel(cr1, csi->regbase + CSI_CSICR1); |
239 | } | 285 | } |
240 | EXPORT_SYMBOL(csi_enable_int); | 286 | EXPORT_SYMBOL(csi_enable_int); |
241 | 287 | ||
242 | void csi_disable_int(cam_data *cam) | 288 | void csi_disable_int(cam_data *cam) |
243 | { | 289 | { |
244 | struct csi_soc *csi = &csi_array[cam->csi]; | 290 | struct csi_soc *csi = &csi_array[cam->csi]; |
245 | unsigned long cr1 = __raw_readl(csi->regbase + CSI_CSICR1); | 291 | unsigned long cr1 = __raw_readl(csi->regbase + CSI_CSICR1); |
246 | 292 | ||
247 | cr1 &= ~BIT_SOF_INTEN; | 293 | cr1 &= ~BIT_SOF_INTEN; |
248 | cr1 &= ~BIT_FB1_DMA_DONE_INTEN; | 294 | cr1 &= ~BIT_FB1_DMA_DONE_INTEN; |
249 | cr1 &= ~BIT_FB2_DMA_DONE_INTEN; | 295 | cr1 &= ~BIT_FB2_DMA_DONE_INTEN; |
250 | __raw_writel(cr1, csi->regbase + CSI_CSICR1); | 296 | __raw_writel(cr1, csi->regbase + CSI_CSICR1); |
251 | } | 297 | } |
252 | EXPORT_SYMBOL(csi_disable_int); | 298 | EXPORT_SYMBOL(csi_disable_int); |
253 | 299 | ||
254 | void csi_enable(cam_data *cam, int arg) | 300 | void csi_enable(cam_data *cam, int arg) |
255 | { | 301 | { |
256 | struct csi_soc *csi = &csi_array[cam->csi]; | 302 | struct csi_soc *csi = &csi_array[cam->csi]; |
257 | unsigned long cr = __raw_readl(csi->regbase + CSI_CSICR18); | 303 | unsigned long cr = __raw_readl(csi->regbase + CSI_CSICR18); |
258 | 304 | ||
259 | if (arg == 1) | 305 | if (arg == 1) { |
306 | csisw_reset(csi); | ||
260 | cr |= BIT_CSI_ENABLE; | 307 | cr |= BIT_CSI_ENABLE; |
261 | else | 308 | } else |
262 | cr &= ~BIT_CSI_ENABLE; | 309 | cr &= ~BIT_CSI_ENABLE; |
263 | __raw_writel(cr, csi->regbase + CSI_CSICR18); | 310 | __raw_writel(cr, csi->regbase + CSI_CSICR18); |
264 | } | 311 | } |
265 | EXPORT_SYMBOL(csi_enable); | 312 | EXPORT_SYMBOL(csi_enable); |
266 | 313 | ||
267 | void csi_buf_stride_set(cam_data *cam, u32 stride) | 314 | void csi_buf_stride_set(cam_data *cam, u32 stride) |
268 | { | 315 | { |
269 | struct csi_soc *csi = &csi_array[cam->csi]; | 316 | struct csi_soc *csi = &csi_array[cam->csi]; |
270 | 317 | ||
271 | __raw_writel(stride, csi->regbase + CSI_CSIFBUF_PARA); | 318 | __raw_writel(stride, csi->regbase + CSI_CSIFBUF_PARA); |
272 | } | 319 | } |
273 | EXPORT_SYMBOL(csi_buf_stride_set); | 320 | EXPORT_SYMBOL(csi_buf_stride_set); |
274 | 321 | ||
275 | void csi_deinterlace_enable(cam_data *cam, bool enable) | 322 | void csi_deinterlace_enable(cam_data *cam, bool enable) |
276 | { | 323 | { |
277 | struct csi_soc *csi = &csi_array[cam->csi]; | 324 | struct csi_soc *csi = &csi_array[cam->csi]; |
278 | unsigned long cr18 = __raw_readl(csi->regbase + CSI_CSICR18); | 325 | unsigned long cr18 = __raw_readl(csi->regbase + CSI_CSICR18); |
279 | 326 | ||
280 | if (enable == true) | 327 | if (enable == true) |
281 | cr18 |= BIT_DEINTERLACE_EN; | 328 | cr18 |= BIT_DEINTERLACE_EN; |
282 | else | 329 | else |
283 | cr18 &= ~BIT_DEINTERLACE_EN; | 330 | cr18 &= ~BIT_DEINTERLACE_EN; |
284 | 331 | ||
285 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); | 332 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); |
286 | } | 333 | } |
287 | EXPORT_SYMBOL(csi_deinterlace_enable); | 334 | EXPORT_SYMBOL(csi_deinterlace_enable); |
288 | 335 | ||
289 | void csi_deinterlace_mode(cam_data *cam, int mode) | 336 | void csi_deinterlace_mode(cam_data *cam, int mode) |
290 | { | 337 | { |
291 | struct csi_soc *csi = &csi_array[cam->csi]; | 338 | struct csi_soc *csi = &csi_array[cam->csi]; |
292 | unsigned long cr18 = __raw_readl(csi->regbase + CSI_CSICR18); | 339 | unsigned long cr18 = __raw_readl(csi->regbase + CSI_CSICR18); |
293 | 340 | ||
294 | if (mode == V4L2_STD_NTSC) | 341 | if (mode == V4L2_STD_NTSC) |
295 | cr18 |= BIT_NTSC_EN; | 342 | cr18 |= BIT_NTSC_EN; |
296 | else | 343 | else |
297 | cr18 &= ~BIT_NTSC_EN; | 344 | cr18 &= ~BIT_NTSC_EN; |
298 | 345 | ||
299 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); | 346 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); |
300 | } | 347 | } |
301 | EXPORT_SYMBOL(csi_deinterlace_mode); | 348 | EXPORT_SYMBOL(csi_deinterlace_mode); |
302 | 349 | ||
303 | void csi_tvdec_enable(cam_data *cam, bool enable) | 350 | void csi_tvdec_enable(cam_data *cam, bool enable) |
304 | { | 351 | { |
305 | struct csi_soc *csi = &csi_array[cam->csi]; | 352 | struct csi_soc *csi = &csi_array[cam->csi]; |
306 | unsigned long cr18 = __raw_readl(csi->regbase + CSI_CSICR18); | 353 | unsigned long cr18 = __raw_readl(csi->regbase + CSI_CSICR18); |
307 | unsigned long cr1 = __raw_readl(csi->regbase + CSI_CSICR1); | 354 | unsigned long cr1 = __raw_readl(csi->regbase + CSI_CSICR1); |
308 | 355 | ||
309 | if (enable == true) { | 356 | if (enable == true) { |
310 | cr18 |= (BIT_TVDECODER_IN_EN | | 357 | cr18 |= (BIT_TVDECODER_IN_EN | |
311 | BIT_BASEADDR_SWITCH_EN | | 358 | BIT_BASEADDR_SWITCH_EN | |
312 | BIT_BASEADDR_SWITCH_SEL | | 359 | BIT_BASEADDR_SWITCH_SEL | |
313 | BIT_BASEADDR_CHG_ERR_EN); | 360 | BIT_BASEADDR_CHG_ERR_EN); |
314 | cr1 |= BIT_CCIR_MODE; | 361 | cr1 |= BIT_CCIR_MODE; |
315 | cr1 &= ~(BIT_SOF_POL | BIT_REDGE); | 362 | cr1 &= ~(BIT_SOF_POL | BIT_REDGE); |
316 | } else { | 363 | } else { |
317 | cr18 &= ~(BIT_TVDECODER_IN_EN | | 364 | cr18 &= ~(BIT_TVDECODER_IN_EN | |
318 | BIT_BASEADDR_SWITCH_EN | | 365 | BIT_BASEADDR_SWITCH_EN | |
319 | BIT_BASEADDR_SWITCH_SEL | | 366 | BIT_BASEADDR_SWITCH_SEL | |
320 | BIT_BASEADDR_CHG_ERR_EN); | 367 | BIT_BASEADDR_CHG_ERR_EN); |
321 | cr1 &= ~BIT_CCIR_MODE; | 368 | cr1 &= ~BIT_CCIR_MODE; |
322 | cr1 |= BIT_SOF_POL | BIT_REDGE; | 369 | cr1 |= BIT_SOF_POL | BIT_REDGE; |
323 | } | 370 | } |
324 | 371 | ||
325 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); | 372 | __raw_writel(cr18, csi->regbase + CSI_CSICR18); |
326 | __raw_writel(cr1, csi->regbase + CSI_CSICR1); | 373 | __raw_writel(cr1, csi->regbase + CSI_CSICR1); |
327 | } | 374 | } |
328 | EXPORT_SYMBOL(csi_tvdec_enable); | 375 | EXPORT_SYMBOL(csi_tvdec_enable); |
329 | 376 | ||
330 | void csi_set_32bit_imagpara(cam_data *cam, int width, int height) | 377 | void csi_set_32bit_imagpara(cam_data *cam, int width, int height) |
331 | { | 378 | { |
332 | struct csi_soc *csi = &csi_array[cam->csi]; | 379 | struct csi_soc *csi = &csi_array[cam->csi]; |
333 | int imag_para = 0; | 380 | int imag_para = 0; |
334 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); | 381 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); |
335 | 382 | ||
336 | imag_para = (width << 16) | height; | 383 | imag_para = (width << 16) | height; |
337 | __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA); | 384 | __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA); |
338 | 385 | ||
339 | 386 | ||
340 | /* reflash the embeded DMA controller */ | 387 | /* reflash the embeded DMA controller */ |
341 | __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3); | 388 | __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3); |
342 | } | 389 | } |
343 | EXPORT_SYMBOL(csi_set_32bit_imagpara); | 390 | EXPORT_SYMBOL(csi_set_32bit_imagpara); |
344 | 391 | ||
345 | void csi_set_16bit_imagpara(cam_data *cam, int width, int height) | 392 | void csi_set_16bit_imagpara(cam_data *cam, int width, int height) |
346 | { | 393 | { |
347 | struct csi_soc *csi = &csi_array[cam->csi]; | 394 | struct csi_soc *csi = &csi_array[cam->csi]; |
348 | int imag_para = 0; | 395 | int imag_para = 0; |
349 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); | 396 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); |
350 | 397 | ||
351 | imag_para = (width << 16) | (height * 2); | 398 | imag_para = (width << 16) | (height * 2); |
352 | __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA); | 399 | __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA); |
353 | 400 | ||
354 | /* reflash the embeded DMA controller */ | 401 | /* reflash the embeded DMA controller */ |
355 | __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3); | 402 | __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3); |
356 | } | 403 | } |
357 | EXPORT_SYMBOL(csi_set_16bit_imagpara); | 404 | EXPORT_SYMBOL(csi_set_16bit_imagpara); |
358 | 405 | ||
359 | void csi_set_12bit_imagpara(cam_data *cam, int width, int height) | 406 | void csi_set_12bit_imagpara(cam_data *cam, int width, int height) |
360 | { | 407 | { |
361 | struct csi_soc *csi = &csi_array[cam->csi]; | 408 | struct csi_soc *csi = &csi_array[cam->csi]; |
362 | int imag_para = 0; | 409 | int imag_para = 0; |
363 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); | 410 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); |
364 | 411 | ||
365 | imag_para = (width << 16) | (height * 3 / 2); | 412 | imag_para = (width << 16) | (height * 3 / 2); |
366 | __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA); | 413 | __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA); |
367 | 414 | ||
368 | /* reflash the embeded DMA controller */ | 415 | /* reflash the embeded DMA controller */ |
369 | __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3); | 416 | __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3); |
370 | } | 417 | } |
371 | EXPORT_SYMBOL(csi_set_12bit_imagpara); | 418 | EXPORT_SYMBOL(csi_set_12bit_imagpara); |
372 | 419 | ||
373 | void csi_dmareq_rff_enable(struct csi_soc *csi) | 420 | void csi_dmareq_rff_enable(struct csi_soc *csi) |
374 | { | 421 | { |
375 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); | 422 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); |
376 | unsigned long cr2 = __raw_readl(csi->regbase + CSI_CSICR2); | 423 | unsigned long cr2 = __raw_readl(csi->regbase + CSI_CSICR2); |
377 | 424 | ||
378 | /* Burst Type of DMA Transfer from RxFIFO. INCR16 */ | 425 | /* Burst Type of DMA Transfer from RxFIFO. INCR16 */ |
379 | cr2 |= 0xC0000000; | 426 | cr2 |= 0xC0000000; |
380 | 427 | ||
381 | cr3 |= BIT_DMA_REQ_EN_RFF; | 428 | cr3 |= BIT_DMA_REQ_EN_RFF; |
382 | cr3 |= BIT_HRESP_ERR_EN; | 429 | cr3 |= BIT_HRESP_ERR_EN; |
383 | cr3 &= ~BIT_RXFF_LEVEL; | 430 | cr3 &= ~BIT_RXFF_LEVEL; |
384 | cr3 |= 0x2 << 4; | 431 | cr3 |= 0x2 << 4; |
385 | 432 | ||
386 | __raw_writel(cr3, csi->regbase + CSI_CSICR3); | 433 | __raw_writel(cr3, csi->regbase + CSI_CSICR3); |
387 | __raw_writel(cr2, csi->regbase + CSI_CSICR2); | 434 | __raw_writel(cr2, csi->regbase + CSI_CSICR2); |
388 | } | 435 | } |
389 | EXPORT_SYMBOL(csi_dmareq_rff_enable); | 436 | EXPORT_SYMBOL(csi_dmareq_rff_enable); |
390 | 437 | ||
391 | void csi_dmareq_rff_disable(struct csi_soc *csi) | 438 | void csi_dmareq_rff_disable(struct csi_soc *csi) |
392 | { | 439 | { |
393 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); | 440 | unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3); |
394 | 441 | ||
395 | cr3 &= ~BIT_DMA_REQ_EN_RFF; | 442 | cr3 &= ~BIT_DMA_REQ_EN_RFF; |
396 | cr3 &= ~BIT_HRESP_ERR_EN; | 443 | cr3 &= ~BIT_HRESP_ERR_EN; |
397 | __raw_writel(cr3, csi->regbase + CSI_CSICR3); | 444 | __raw_writel(cr3, csi->regbase + CSI_CSICR3); |
398 | } | 445 | } |
399 | EXPORT_SYMBOL(csi_dmareq_rff_disable); | 446 | EXPORT_SYMBOL(csi_dmareq_rff_disable); |
400 | 447 | ||
401 | struct csi_soc *csi_get_soc(int id) | 448 | struct csi_soc *csi_get_soc(int id) |
402 | { | 449 | { |
403 | if (id >= CSI_MAX_NUM) | 450 | if (id >= CSI_MAX_NUM) |
404 | return ERR_PTR(-ENODEV); | 451 | return ERR_PTR(-ENODEV); |
405 | else if (!csi_array[id].online) | 452 | else if (!csi_array[id].online) |
406 | return ERR_PTR(-ENODEV); | 453 | return ERR_PTR(-ENODEV); |
407 | else | 454 | else |
408 | return &(csi_array[id]); | 455 | return &(csi_array[id]); |
409 | } | 456 | } |
410 | EXPORT_SYMBOL_GPL(csi_get_soc); | 457 | EXPORT_SYMBOL_GPL(csi_get_soc); |
411 | 458 | ||
412 | static const struct of_device_id fsl_csi_dt_ids[] = { | 459 | static const struct of_device_id fsl_csi_dt_ids[] = { |
413 | { .compatible = "fsl,imx6sl-csi", }, | 460 | { .compatible = "fsl,imx6sl-csi", }, |
414 | { /* sentinel */ } | 461 | { /* sentinel */ } |
415 | }; | 462 | }; |
416 | MODULE_DEVICE_TABLE(of, fsl_csi_dt_ids); | 463 | MODULE_DEVICE_TABLE(of, fsl_csi_dt_ids); |
417 | 464 | ||
418 | static int csi_probe(struct platform_device *pdev) | 465 | static int csi_probe(struct platform_device *pdev) |
419 | { | 466 | { |
420 | int ret = 0; | 467 | int ret = 0; |
421 | struct resource *res; | 468 | struct resource *res; |
422 | int id; | 469 | int id; |
423 | 470 | ||
424 | csi_pdev = pdev; | ||
425 | |||
426 | id = of_alias_get_id(pdev->dev.of_node, "csi"); | 471 | id = of_alias_get_id(pdev->dev.of_node, "csi"); |
427 | if (id < 0) { | 472 | if (id < 0) { |
428 | dev_dbg(&pdev->dev, "can not get alias id\n"); | 473 | dev_dbg(&pdev->dev, "can not get alias id\n"); |
429 | return id; | 474 | return id; |
430 | } | 475 | } |
431 | 476 | ||
432 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 477 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
433 | if (!res) { | 478 | if (!res) { |
434 | dev_err(&pdev->dev, "No csi irq found.\n"); | 479 | dev_err(&pdev->dev, "No csi irq found.\n"); |
435 | ret = -ENODEV; | 480 | ret = -ENODEV; |
436 | goto err; | 481 | goto err; |
437 | } | 482 | } |
438 | 483 | ||
439 | csi = &csi_array[id]; | 484 | csi = &csi_array[id]; |
440 | csi->irq_nr = res->start; | 485 | csi->irq_nr = res->start; |
441 | csi->online = false; | 486 | csi->online = false; |
442 | 487 | ||
443 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 488 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
444 | if (!res) { | 489 | if (!res) { |
445 | dev_err(&pdev->dev, "No csi base address found.\n"); | 490 | dev_err(&pdev->dev, "No csi base address found.\n"); |
446 | ret = -ENODEV; | 491 | ret = -ENODEV; |
447 | goto err; | 492 | goto err; |
448 | } | 493 | } |
449 | csi->regbase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | 494 | csi->regbase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); |
450 | if (!csi->regbase) { | 495 | if (!csi->regbase) { |
451 | dev_err(&pdev->dev, "ioremap failed with csi base\n"); | 496 | dev_err(&pdev->dev, "ioremap failed with csi base\n"); |
452 | ret = -ENOMEM; | 497 | ret = -ENOMEM; |
453 | goto err; | 498 | goto err; |
454 | } | 499 | } |
455 | 500 | ||
456 | disp_axi_clk = devm_clk_get(&pdev->dev, "disp-axi"); | 501 | disp_axi_clk = devm_clk_get(&pdev->dev, "disp-axi"); |
457 | if (IS_ERR(disp_axi_clk)) { | 502 | if (IS_ERR(disp_axi_clk)) { |
458 | dev_err(&pdev->dev, "get csi clock failed\n"); | 503 | dev_err(&pdev->dev, "get csi clock failed\n"); |
459 | return PTR_ERR(disp_axi_clk); | 504 | return PTR_ERR(disp_axi_clk); |
460 | } | 505 | } |
461 | csi_clk = devm_clk_get(&pdev->dev, "csi_mclk"); | 506 | csi_clk = devm_clk_get(&pdev->dev, "csi_mclk"); |
462 | if (IS_ERR(csi_clk)) { | 507 | if (IS_ERR(csi_clk)) { |
463 | dev_err(&pdev->dev, "get csi mclk failed\n"); | 508 | dev_err(&pdev->dev, "get csi mclk failed\n"); |
464 | return PTR_ERR(csi_clk); | 509 | return PTR_ERR(csi_clk); |
465 | } | 510 | } |
466 | 511 | ||
467 | dcic_clk = devm_clk_get(&pdev->dev, "dcic"); | 512 | dcic_clk = devm_clk_get(&pdev->dev, "dcic"); |
468 | if (IS_ERR(dcic_clk)) { | 513 | if (IS_ERR(dcic_clk)) { |
469 | dev_err(&pdev->dev, "get dcic clk failed\n"); | 514 | dev_err(&pdev->dev, "get dcic clk failed\n"); |
470 | return PTR_ERR(dcic_clk); | 515 | return PTR_ERR(dcic_clk); |
471 | } | 516 | } |
472 | 517 | ||
473 | csi->disp_reg = devm_regulator_get(&pdev->dev, "disp"); | 518 | if (disp_reg == NULL) { |
474 | if (IS_ERR(csi->disp_reg)) { | 519 | disp_reg = devm_regulator_get(&pdev->dev, "disp"); |
475 | dev_dbg(&pdev->dev, "display regulator is not ready\n"); | 520 | if (IS_ERR(disp_reg)) { |
476 | csi->disp_reg = NULL; | 521 | dev_dbg(&pdev->dev, "display regulator is not ready\n"); |
522 | disp_reg = NULL; | ||
523 | } | ||
477 | } | 524 | } |
478 | 525 | ||
479 | platform_set_drvdata(pdev, csi); | 526 | platform_set_drvdata(pdev, csi); |
480 | 527 | ||
481 | pm_runtime_enable(&pdev->dev); | 528 | csi_regulator_enable(); |
482 | 529 | ||
483 | csi_clk_enable(); | 530 | csi_clk_enable(); |
484 | csihw_reset(csi); | 531 | csihw_reset(csi); |
485 | csi_init_interface(csi); | 532 | csi_init_interface(csi); |
486 | csi_dmareq_rff_disable(csi); | 533 | csi_dmareq_rff_disable(csi); |
487 | 534 | ||
488 | csi->online = true; | 535 | csi->online = true; |
489 | err: | 536 | err: |
490 | return ret; | 537 | return ret; |
491 | } | 538 | } |
492 | 539 | ||
493 | static int csi_remove(struct platform_device *pdev) | 540 | static int csi_remove(struct platform_device *pdev) |
494 | { | 541 | { |
495 | struct csi_soc *csi = platform_get_drvdata(pdev); | 542 | struct csi_soc *csi = platform_get_drvdata(pdev); |
496 | 543 | ||
497 | csi->online = false; | 544 | csi->online = false; |
498 | platform_set_drvdata(pdev, NULL); | 545 | platform_set_drvdata(pdev, NULL); |
499 | 546 | ||
500 | return 0; | 547 | return 0; |
501 | } | 548 | } |
502 | 549 | ||
503 | #ifdef CONFIG_PM_RUNTIME | ||
504 | static int csi_runtime_suspend(struct device *dev) | ||
505 | { | ||
506 | int ret = 0; | ||
507 | struct platform_device *pdev = to_platform_device(dev); | ||
508 | struct csi_soc *csi = platform_get_drvdata(pdev); | ||
509 | |||
510 | release_bus_freq(BUS_FREQ_HIGH); | ||
511 | dev_info(dev, "csi busfreq high release.\n"); | ||
512 | |||
513 | if (csi->disp_reg) | ||
514 | ret = regulator_disable(csi->disp_reg); | ||
515 | |||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | static int csi_runtime_resume(struct device *dev) | ||
520 | { | ||
521 | int ret = 0; | ||
522 | struct platform_device *pdev = to_platform_device(dev); | ||
523 | struct csi_soc *csi = platform_get_drvdata(pdev); | ||
524 | |||
525 | request_bus_freq(BUS_FREQ_HIGH); | ||
526 | dev_info(dev, "csi busfreq high request.\n"); | ||
527 | |||
528 | if (csi->disp_reg) | ||
529 | ret = regulator_enable(csi->disp_reg); | ||
530 | |||
531 | return ret; | ||
532 | } | ||
533 | #else | ||
534 | #define mxsfb_runtime_suspend NULL | ||
535 | #define mxsfb_runtime_resume NULL | ||
536 | #endif | ||
537 | |||
538 | #ifdef CONFIG_PM_SLEEP | 550 | #ifdef CONFIG_PM_SLEEP |
539 | static int csi_suspend(struct device *dev) | 551 | static int csi_suspend(struct device *dev) |
540 | { | 552 | { |
541 | struct csi_soc *csi = dev_get_drvdata(dev); | 553 | struct csi_soc *csi = dev_get_drvdata(dev); |
542 | 554 | ||
543 | csi->online = false; | 555 | csi->online = false; |
544 | 556 | ||
545 | return 0; | 557 | return 0; |
546 | } | 558 | } |
547 | 559 | ||
548 | static int csi_resume(struct device *dev) | 560 | static int csi_resume(struct device *dev) |
drivers/media/platform/mxc/capture/fsl_csi.h
1 | /* | 1 | /* |
2 | * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved. | 2 | * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | /* | 5 | /* |
6 | * The code contained herein is licensed under the GNU General Public | 6 | * The code contained herein is licensed under the GNU General Public |
7 | * License. You may obtain a copy of the GNU General Public License | 7 | * License. You may obtain a copy of the GNU General Public License |
8 | * Version 2 or later at the following locations: | 8 | * Version 2 or later at the following locations: |
9 | * | 9 | * |
10 | * http://www.opensource.org/licenses/gpl-license.html | 10 | * http://www.opensource.org/licenses/gpl-license.html |
11 | * http://www.gnu.org/copyleft/gpl.html | 11 | * http://www.gnu.org/copyleft/gpl.html |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /*! | 14 | /*! |
15 | * @file fsl_csi.h | 15 | * @file fsl_csi.h |
16 | * | 16 | * |
17 | * @brief mx25 CMOS Sensor interface functions | 17 | * @brief mx25 CMOS Sensor interface functions |
18 | * | 18 | * |
19 | * @ingroup CSI | 19 | * @ingroup CSI |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef MX25_CSI_H | 22 | #ifndef MX25_CSI_H |
23 | #define MX25_CSI_H | 23 | #define MX25_CSI_H |
24 | 24 | ||
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | 26 | ||
27 | /* reset values */ | 27 | /* reset values */ |
28 | #define CSICR1_RESET_VAL 0x40000800 | 28 | #define CSICR1_RESET_VAL 0x40000800 |
29 | #define CSICR2_RESET_VAL 0x0 | 29 | #define CSICR2_RESET_VAL 0x0 |
30 | #define CSICR3_RESET_VAL 0x0 | 30 | #define CSICR3_RESET_VAL 0x0 |
31 | 31 | ||
32 | /* csi control reg 1 */ | 32 | /* csi control reg 1 */ |
33 | #define BIT_SWAP16_EN (0x1 << 31) | 33 | #define BIT_SWAP16_EN (0x1 << 31) |
34 | #define BIT_EXT_VSYNC (0x1 << 30) | 34 | #define BIT_EXT_VSYNC (0x1 << 30) |
35 | #define BIT_EOF_INT_EN (0x1 << 29) | 35 | #define BIT_EOF_INT_EN (0x1 << 29) |
36 | #define BIT_PRP_IF_EN (0x1 << 28) | 36 | #define BIT_PRP_IF_EN (0x1 << 28) |
37 | #define BIT_CCIR_MODE (0x1 << 27) | 37 | #define BIT_CCIR_MODE (0x1 << 27) |
38 | #define BIT_COF_INT_EN (0x1 << 26) | 38 | #define BIT_COF_INT_EN (0x1 << 26) |
39 | #define BIT_SF_OR_INTEN (0x1 << 25) | 39 | #define BIT_SF_OR_INTEN (0x1 << 25) |
40 | #define BIT_RF_OR_INTEN (0x1 << 24) | 40 | #define BIT_RF_OR_INTEN (0x1 << 24) |
41 | #define BIT_SFF_DMA_DONE_INTEN (0x1 << 22) | 41 | #define BIT_SFF_DMA_DONE_INTEN (0x1 << 22) |
42 | #define BIT_STATFF_INTEN (0x1 << 21) | 42 | #define BIT_STATFF_INTEN (0x1 << 21) |
43 | #define BIT_FB2_DMA_DONE_INTEN (0x1 << 20) | 43 | #define BIT_FB2_DMA_DONE_INTEN (0x1 << 20) |
44 | #define BIT_FB1_DMA_DONE_INTEN (0x1 << 19) | 44 | #define BIT_FB1_DMA_DONE_INTEN (0x1 << 19) |
45 | #define BIT_RXFF_INTEN (0x1 << 18) | 45 | #define BIT_RXFF_INTEN (0x1 << 18) |
46 | #define BIT_SOF_POL (0x1 << 17) | 46 | #define BIT_SOF_POL (0x1 << 17) |
47 | #define BIT_SOF_INTEN (0x1 << 16) | 47 | #define BIT_SOF_INTEN (0x1 << 16) |
48 | #define BIT_MCLKDIV (0xF << 12) | 48 | #define BIT_MCLKDIV (0xF << 12) |
49 | #define BIT_HSYNC_POL (0x1 << 11) | 49 | #define BIT_HSYNC_POL (0x1 << 11) |
50 | #define BIT_CCIR_EN (0x1 << 10) | 50 | #define BIT_CCIR_EN (0x1 << 10) |
51 | #define BIT_MCLKEN (0x1 << 9) | 51 | #define BIT_MCLKEN (0x1 << 9) |
52 | #define BIT_FCC (0x1 << 8) | 52 | #define BIT_FCC (0x1 << 8) |
53 | #define BIT_PACK_DIR (0x1 << 7) | 53 | #define BIT_PACK_DIR (0x1 << 7) |
54 | #define BIT_CLR_STATFIFO (0x1 << 6) | 54 | #define BIT_CLR_STATFIFO (0x1 << 6) |
55 | #define BIT_CLR_RXFIFO (0x1 << 5) | 55 | #define BIT_CLR_RXFIFO (0x1 << 5) |
56 | #define BIT_GCLK_MODE (0x1 << 4) | 56 | #define BIT_GCLK_MODE (0x1 << 4) |
57 | #define BIT_INV_DATA (0x1 << 3) | 57 | #define BIT_INV_DATA (0x1 << 3) |
58 | #define BIT_INV_PCLK (0x1 << 2) | 58 | #define BIT_INV_PCLK (0x1 << 2) |
59 | #define BIT_REDGE (0x1 << 1) | 59 | #define BIT_REDGE (0x1 << 1) |
60 | #define BIT_PIXEL_BIT (0x1 << 0) | 60 | #define BIT_PIXEL_BIT (0x1 << 0) |
61 | 61 | ||
62 | #define SHIFT_MCLKDIV 12 | 62 | #define SHIFT_MCLKDIV 12 |
63 | 63 | ||
64 | /* control reg 3 */ | 64 | /* control reg 3 */ |
65 | #define BIT_FRMCNT (0xFFFF << 16) | 65 | #define BIT_FRMCNT (0xFFFF << 16) |
66 | #define BIT_FRMCNT_RST (0x1 << 15) | 66 | #define BIT_FRMCNT_RST (0x1 << 15) |
67 | #define BIT_DMA_REFLASH_RFF (0x1 << 14) | 67 | #define BIT_DMA_REFLASH_RFF (0x1 << 14) |
68 | #define BIT_DMA_REFLASH_SFF (0x1 << 13) | 68 | #define BIT_DMA_REFLASH_SFF (0x1 << 13) |
69 | #define BIT_DMA_REQ_EN_RFF (0x1 << 12) | 69 | #define BIT_DMA_REQ_EN_RFF (0x1 << 12) |
70 | #define BIT_DMA_REQ_EN_SFF (0x1 << 11) | 70 | #define BIT_DMA_REQ_EN_SFF (0x1 << 11) |
71 | #define BIT_STATFF_LEVEL (0x7 << 8) | 71 | #define BIT_STATFF_LEVEL (0x7 << 8) |
72 | #define BIT_HRESP_ERR_EN (0x1 << 7) | 72 | #define BIT_HRESP_ERR_EN (0x1 << 7) |
73 | #define BIT_RXFF_LEVEL (0x7 << 4) | 73 | #define BIT_RXFF_LEVEL (0x7 << 4) |
74 | #define BIT_TWO_8BIT_SENSOR (0x1 << 3) | 74 | #define BIT_TWO_8BIT_SENSOR (0x1 << 3) |
75 | #define BIT_ZERO_PACK_EN (0x1 << 2) | 75 | #define BIT_ZERO_PACK_EN (0x1 << 2) |
76 | #define BIT_ECC_INT_EN (0x1 << 1) | 76 | #define BIT_ECC_INT_EN (0x1 << 1) |
77 | #define BIT_ECC_AUTO_EN (0x1 << 0) | 77 | #define BIT_ECC_AUTO_EN (0x1 << 0) |
78 | 78 | ||
79 | #define SHIFT_FRMCNT 16 | 79 | #define SHIFT_FRMCNT 16 |
80 | #define SHIFT_RXFIFO_LEVEL 4 | 80 | #define SHIFT_RXFIFO_LEVEL 4 |
81 | 81 | ||
82 | /* csi status reg */ | 82 | /* csi status reg */ |
83 | #define BIT_ADDR_CH_ERR_INT (0x1 << 28) | 83 | #define BIT_ADDR_CH_ERR_INT (0x1 << 28) |
84 | #define BIT_FIELD0_INT (0x1 << 27) | 84 | #define BIT_FIELD0_INT (0x1 << 27) |
85 | #define BIT_FIELD1_INT (0x1 << 26) | 85 | #define BIT_FIELD1_INT (0x1 << 26) |
86 | #define BIT_SFF_OR_INT (0x1 << 25) | 86 | #define BIT_SFF_OR_INT (0x1 << 25) |
87 | #define BIT_RFF_OR_INT (0x1 << 24) | 87 | #define BIT_RFF_OR_INT (0x1 << 24) |
88 | #define BIT_DMA_TSF_DONE_SFF (0x1 << 22) | 88 | #define BIT_DMA_TSF_DONE_SFF (0x1 << 22) |
89 | #define BIT_STATFF_INT (0x1 << 21) | 89 | #define BIT_STATFF_INT (0x1 << 21) |
90 | #define BIT_DMA_TSF_DONE_FB2 (0x1 << 20) | 90 | #define BIT_DMA_TSF_DONE_FB2 (0x1 << 20) |
91 | #define BIT_DMA_TSF_DONE_FB1 (0x1 << 19) | 91 | #define BIT_DMA_TSF_DONE_FB1 (0x1 << 19) |
92 | #define BIT_RXFF_INT (0x1 << 18) | 92 | #define BIT_RXFF_INT (0x1 << 18) |
93 | #define BIT_EOF_INT (0x1 << 17) | 93 | #define BIT_EOF_INT (0x1 << 17) |
94 | #define BIT_SOF_INT (0x1 << 16) | 94 | #define BIT_SOF_INT (0x1 << 16) |
95 | #define BIT_F2_INT (0x1 << 15) | 95 | #define BIT_F2_INT (0x1 << 15) |
96 | #define BIT_F1_INT (0x1 << 14) | 96 | #define BIT_F1_INT (0x1 << 14) |
97 | #define BIT_COF_INT (0x1 << 13) | 97 | #define BIT_COF_INT (0x1 << 13) |
98 | #define BIT_HRESP_ERR_INT (0x1 << 7) | 98 | #define BIT_HRESP_ERR_INT (0x1 << 7) |
99 | #define BIT_ECC_INT (0x1 << 1) | 99 | #define BIT_ECC_INT (0x1 << 1) |
100 | #define BIT_DRDY (0x1 << 0) | 100 | #define BIT_DRDY (0x1 << 0) |
101 | 101 | ||
102 | /* csi control reg 18 */ | 102 | /* csi control reg 18 */ |
103 | #define BIT_CSI_ENABLE (0x1 << 31) | 103 | #define BIT_CSI_ENABLE (0x1 << 31) |
104 | #define BIT_BASEADDR_CHG_ERR_EN (0x1 << 9) | 104 | #define BIT_BASEADDR_CHG_ERR_EN (0x1 << 9) |
105 | #define BIT_BASEADDR_SWITCH_SEL (0x1 << 5) | 105 | #define BIT_BASEADDR_SWITCH_SEL (0x1 << 5) |
106 | #define BIT_BASEADDR_SWITCH_EN (0x1 << 4) | 106 | #define BIT_BASEADDR_SWITCH_EN (0x1 << 4) |
107 | #define BIT_PARALLEL24_EN (0x1 << 3) | 107 | #define BIT_PARALLEL24_EN (0x1 << 3) |
108 | #define BIT_DEINTERLACE_EN (0x1 << 2) | 108 | #define BIT_DEINTERLACE_EN (0x1 << 2) |
109 | #define BIT_TVDECODER_IN_EN (0x1 << 1) | 109 | #define BIT_TVDECODER_IN_EN (0x1 << 1) |
110 | #define BIT_NTSC_EN (0x1 << 0) | 110 | #define BIT_NTSC_EN (0x1 << 0) |
111 | 111 | ||
112 | #define CSI_MCLK_VF 1 | 112 | #define CSI_MCLK_VF 1 |
113 | #define CSI_MCLK_ENC 2 | 113 | #define CSI_MCLK_ENC 2 |
114 | #define CSI_MCLK_RAW 4 | 114 | #define CSI_MCLK_RAW 4 |
115 | #define CSI_MCLK_I2C 8 | 115 | #define CSI_MCLK_I2C 8 |
116 | #endif | 116 | #endif |
117 | 117 | ||
118 | #define CSI_CSICR1 0x0 | 118 | #define CSI_CSICR1 0x0 |
119 | #define CSI_CSICR2 0x4 | 119 | #define CSI_CSICR2 0x4 |
120 | #define CSI_CSICR3 0x8 | 120 | #define CSI_CSICR3 0x8 |
121 | #define CSI_STATFIFO 0xC | 121 | #define CSI_STATFIFO 0xC |
122 | #define CSI_CSIRXFIFO 0x10 | 122 | #define CSI_CSIRXFIFO 0x10 |
123 | #define CSI_CSIRXCNT 0x14 | 123 | #define CSI_CSIRXCNT 0x14 |
124 | #define CSI_CSISR 0x18 | 124 | #define CSI_CSISR 0x18 |
125 | 125 | ||
126 | #define CSI_CSIDBG 0x1C | 126 | #define CSI_CSIDBG 0x1C |
127 | #define CSI_CSIDMASA_STATFIFO 0x20 | 127 | #define CSI_CSIDMASA_STATFIFO 0x20 |
128 | #define CSI_CSIDMATS_STATFIFO 0x24 | 128 | #define CSI_CSIDMATS_STATFIFO 0x24 |
129 | #define CSI_CSIDMASA_FB1 0x28 | 129 | #define CSI_CSIDMASA_FB1 0x28 |
130 | #define CSI_CSIDMASA_FB2 0x2C | 130 | #define CSI_CSIDMASA_FB2 0x2C |
131 | #define CSI_CSIFBUF_PARA 0x30 | 131 | #define CSI_CSIFBUF_PARA 0x30 |
132 | #define CSI_CSIIMAG_PARA 0x34 | 132 | #define CSI_CSIIMAG_PARA 0x34 |
133 | 133 | ||
134 | #define CSI_CSICR18 0x48 | 134 | #define CSI_CSICR18 0x48 |
135 | #define CSI_CSICR19 0x4c | 135 | #define CSI_CSICR19 0x4c |
136 | 136 | ||
137 | struct csi_signal_cfg_t { | 137 | struct csi_signal_cfg_t { |
138 | unsigned data_width:3; | 138 | unsigned data_width:3; |
139 | unsigned clk_mode:2; | 139 | unsigned clk_mode:2; |
140 | unsigned ext_vsync:1; | 140 | unsigned ext_vsync:1; |
141 | unsigned Vsync_pol:1; | 141 | unsigned Vsync_pol:1; |
142 | unsigned Hsync_pol:1; | 142 | unsigned Hsync_pol:1; |
143 | unsigned pixclk_pol:1; | 143 | unsigned pixclk_pol:1; |
144 | unsigned data_pol:1; | 144 | unsigned data_pol:1; |
145 | unsigned sens_clksrc:1; | 145 | unsigned sens_clksrc:1; |
146 | }; | 146 | }; |
147 | 147 | ||
148 | struct csi_config_t { | 148 | struct csi_config_t { |
149 | /* control reg 1 */ | 149 | /* control reg 1 */ |
150 | unsigned int swap16_en:1; | 150 | unsigned int swap16_en:1; |
151 | unsigned int ext_vsync:1; | 151 | unsigned int ext_vsync:1; |
152 | unsigned int eof_int_en:1; | 152 | unsigned int eof_int_en:1; |
153 | unsigned int prp_if_en:1; | 153 | unsigned int prp_if_en:1; |
154 | unsigned int ccir_mode:1; | 154 | unsigned int ccir_mode:1; |
155 | unsigned int cof_int_en:1; | 155 | unsigned int cof_int_en:1; |
156 | unsigned int sf_or_inten:1; | 156 | unsigned int sf_or_inten:1; |
157 | unsigned int rf_or_inten:1; | 157 | unsigned int rf_or_inten:1; |
158 | unsigned int sff_dma_done_inten:1; | 158 | unsigned int sff_dma_done_inten:1; |
159 | unsigned int statff_inten:1; | 159 | unsigned int statff_inten:1; |
160 | unsigned int fb2_dma_done_inten:1; | 160 | unsigned int fb2_dma_done_inten:1; |
161 | unsigned int fb1_dma_done_inten:1; | 161 | unsigned int fb1_dma_done_inten:1; |
162 | unsigned int rxff_inten:1; | 162 | unsigned int rxff_inten:1; |
163 | unsigned int sof_pol:1; | 163 | unsigned int sof_pol:1; |
164 | unsigned int sof_inten:1; | 164 | unsigned int sof_inten:1; |
165 | unsigned int mclkdiv:4; | 165 | unsigned int mclkdiv:4; |
166 | unsigned int hsync_pol:1; | 166 | unsigned int hsync_pol:1; |
167 | unsigned int ccir_en:1; | 167 | unsigned int ccir_en:1; |
168 | unsigned int mclken:1; | 168 | unsigned int mclken:1; |
169 | unsigned int fcc:1; | 169 | unsigned int fcc:1; |
170 | unsigned int pack_dir:1; | 170 | unsigned int pack_dir:1; |
171 | unsigned int gclk_mode:1; | 171 | unsigned int gclk_mode:1; |
172 | unsigned int inv_data:1; | 172 | unsigned int inv_data:1; |
173 | unsigned int inv_pclk:1; | 173 | unsigned int inv_pclk:1; |
174 | unsigned int redge:1; | 174 | unsigned int redge:1; |
175 | unsigned int pixel_bit:1; | 175 | unsigned int pixel_bit:1; |
176 | 176 | ||
177 | /* control reg 3 */ | 177 | /* control reg 3 */ |
178 | unsigned int frmcnt:16; | 178 | unsigned int frmcnt:16; |
179 | unsigned int frame_reset:1; | 179 | unsigned int frame_reset:1; |
180 | unsigned int dma_reflash_rff:1; | 180 | unsigned int dma_reflash_rff:1; |
181 | unsigned int dma_reflash_sff:1; | 181 | unsigned int dma_reflash_sff:1; |
182 | unsigned int dma_req_en_rff:1; | 182 | unsigned int dma_req_en_rff:1; |
183 | unsigned int dma_req_en_sff:1; | 183 | unsigned int dma_req_en_sff:1; |
184 | unsigned int statff_level:3; | 184 | unsigned int statff_level:3; |
185 | unsigned int hresp_err_en:1; | 185 | unsigned int hresp_err_en:1; |
186 | unsigned int rxff_level:3; | 186 | unsigned int rxff_level:3; |
187 | unsigned int two_8bit_sensor:1; | 187 | unsigned int two_8bit_sensor:1; |
188 | unsigned int zero_pack_en:1; | 188 | unsigned int zero_pack_en:1; |
189 | unsigned int ecc_int_en:1; | 189 | unsigned int ecc_int_en:1; |
190 | unsigned int ecc_auto_en:1; | 190 | unsigned int ecc_auto_en:1; |
191 | /* fifo counter */ | 191 | /* fifo counter */ |
192 | unsigned int rxcnt; | 192 | unsigned int rxcnt; |
193 | }; | 193 | }; |
194 | 194 | ||
195 | struct csi_soc { | 195 | struct csi_soc { |
196 | bool online; | 196 | bool online; |
197 | int irq_nr; | 197 | int irq_nr; |
198 | void __iomem *regbase; | 198 | void __iomem *regbase; |
199 | struct regulator *disp_reg; | ||
200 | }; | 199 | }; |
201 | 200 | ||
202 | typedef void (*csi_irq_callback_t) (void *data, unsigned long status); | 201 | typedef void (*csi_irq_callback_t) (void *data, unsigned long status); |
203 | 202 | ||
204 | void csi_set_32bit_imagpara(cam_data *cam, int width, int height); | 203 | void csi_set_32bit_imagpara(cam_data *cam, int width, int height); |
205 | void csi_set_16bit_imagpara(cam_data *cam, int width, int height); | 204 | void csi_set_16bit_imagpara(cam_data *cam, int width, int height); |
206 | void csi_set_12bit_imagpara(cam_data *cam, int width, int height); | 205 | void csi_set_12bit_imagpara(cam_data *cam, int width, int height); |
207 | void csi_format_swap16(cam_data *cam, bool enable); | 206 | void csi_format_swap16(cam_data *cam, bool enable); |
208 | int csi_read_mclk_flag(void); | 207 | int csi_read_mclk_flag(void); |
209 | void csi_start_callback(void *data); | 208 | void csi_start_callback(void *data); |
210 | void csi_stop_callback(void *data); | 209 | void csi_stop_callback(void *data); |
211 | void csi_enable_int(cam_data *cam, int arg); | 210 | void csi_enable_int(cam_data *cam, int arg); |
212 | void csi_buf_stride_set(cam_data *cam, u32 stride); | 211 | void csi_buf_stride_set(cam_data *cam, u32 stride); |
213 | void csi_deinterlace_mode(cam_data *cam, int mode); | 212 | void csi_deinterlace_mode(cam_data *cam, int mode); |
214 | void csi_deinterlace_enable(cam_data *cam, bool enable); | 213 | void csi_deinterlace_enable(cam_data *cam, bool enable); |
215 | void csi_tvdec_enable(cam_data *cam, bool enable); | 214 | void csi_tvdec_enable(cam_data *cam, bool enable); |
216 | void csi_enable(cam_data *cam, int arg); | 215 | void csi_enable(cam_data *cam, int arg); |
217 | void csi_disable_int(cam_data *cam); | 216 | void csi_disable_int(cam_data *cam); |
217 | int csi_regulator_enable(void); | ||
218 | void csi_regulator_disable(void); | ||
218 | void csi_clk_enable(void); | 219 | void csi_clk_enable(void); |
219 | void csi_clk_disable(void); | 220 | void csi_clk_disable(void); |
220 | void csi_dmareq_rff_enable(struct csi_soc *csi); | 221 | void csi_dmareq_rff_enable(struct csi_soc *csi); |
221 | void csi_dmareq_rff_disable(struct csi_soc *csi); | 222 | void csi_dmareq_rff_disable(struct csi_soc *csi); |
222 | static inline int csi_read(struct csi_soc *csi, unsigned int offset) | 223 | static inline int csi_read(struct csi_soc *csi, unsigned int offset) |
223 | { | 224 | { |
224 | return __raw_readl(csi->regbase + offset); | 225 | return __raw_readl(csi->regbase + offset); |
225 | } | 226 | } |
226 | static inline void csi_write(struct csi_soc *csi, unsigned int value, | 227 | static inline void csi_write(struct csi_soc *csi, unsigned int value, |
227 | unsigned int offset) | 228 | unsigned int offset) |
228 | { | 229 | { |
229 | __raw_writel(value, csi->regbase + offset); | 230 | __raw_writel(value, csi->regbase + offset); |
230 | } | 231 | } |
231 | 232 | ||
232 | struct csi_soc *csi_get_soc(int id); | 233 | struct csi_soc *csi_get_soc(int id); |
drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
1 | /* | 1 | /* |
2 | * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. | 2 | * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | /* | 5 | /* |
6 | * The code contained herein is licensed under the GNU General Public | 6 | * The code contained herein is licensed under the GNU General Public |
7 | * License. You may obtain a copy of the GNU General Public License | 7 | * License. You may obtain a copy of the GNU General Public License |
8 | * Version 2 or later at the following locations: | 8 | * Version 2 or later at the following locations: |
9 | * | 9 | * |
10 | * http://www.opensource.org/licenses/gpl-license.html | 10 | * http://www.opensource.org/licenses/gpl-license.html |
11 | * http://www.gnu.org/copyleft/gpl.html | 11 | * http://www.gnu.org/copyleft/gpl.html |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /*! | 14 | /*! |
15 | * @defgroup MXC_V4L2_CAPTURE MXC V4L2 Video Capture Driver | 15 | * @defgroup MXC_V4L2_CAPTURE MXC V4L2 Video Capture Driver |
16 | */ | 16 | */ |
17 | /*! | 17 | /*! |
18 | * @file mxc_v4l2_capture.h | 18 | * @file mxc_v4l2_capture.h |
19 | * | 19 | * |
20 | * @brief mxc V4L2 capture device API Header file | 20 | * @brief mxc V4L2 capture device API Header file |
21 | * | 21 | * |
22 | * It include all the defines for frame operations, also three structure defines | 22 | * It include all the defines for frame operations, also three structure defines |
23 | * use case ops structure, common v4l2 driver structure and frame structure. | 23 | * use case ops structure, common v4l2 driver structure and frame structure. |
24 | * | 24 | * |
25 | * @ingroup MXC_V4L2_CAPTURE | 25 | * @ingroup MXC_V4L2_CAPTURE |
26 | */ | 26 | */ |
27 | #ifndef __MXC_V4L2_CAPTURE_H__ | 27 | #ifndef __MXC_V4L2_CAPTURE_H__ |
28 | #define __MXC_V4L2_CAPTURE_H__ | 28 | #define __MXC_V4L2_CAPTURE_H__ |
29 | 29 | ||
30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
32 | #include <linux/mxc_v4l2.h> | 32 | #include <linux/mxc_v4l2.h> |
33 | #include <linux/completion.h> | 33 | #include <linux/completion.h> |
34 | #include <linux/dmaengine.h> | 34 | #include <linux/dmaengine.h> |
35 | #include <linux/pxp_dma.h> | 35 | #include <linux/pxp_dma.h> |
36 | #include <linux/ipu-v3.h> | 36 | #include <linux/ipu-v3.h> |
37 | #include <linux/platform_data/dma-imx.h> | 37 | #include <linux/platform_data/dma-imx.h> |
38 | 38 | ||
39 | #include <media/v4l2-dev.h> | 39 | #include <media/v4l2-dev.h> |
40 | #include <media/v4l2-int-device.h> | 40 | #include <media/v4l2-int-device.h> |
41 | 41 | ||
42 | 42 | ||
43 | #define FRAME_NUM 10 | 43 | #define FRAME_NUM 10 |
44 | #define MXC_SENSOR_NUM 2 | 44 | #define MXC_SENSOR_NUM 2 |
45 | 45 | ||
46 | enum imx_v4l2_devtype { | 46 | enum imx_v4l2_devtype { |
47 | IMX5_V4L2, | 47 | IMX5_V4L2, |
48 | IMX6_V4L2, | 48 | IMX6_V4L2, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | /*! | 51 | /*! |
52 | * v4l2 frame structure. | 52 | * v4l2 frame structure. |
53 | */ | 53 | */ |
54 | struct mxc_v4l_frame { | 54 | struct mxc_v4l_frame { |
55 | u32 paddress; | 55 | u32 paddress; |
56 | void *vaddress; | 56 | void *vaddress; |
57 | int count; | 57 | int count; |
58 | int width; | 58 | int width; |
59 | int height; | 59 | int height; |
60 | 60 | ||
61 | struct v4l2_buffer buffer; | 61 | struct v4l2_buffer buffer; |
62 | struct list_head queue; | 62 | struct list_head queue; |
63 | int index; | 63 | int index; |
64 | union { | 64 | union { |
65 | int ipu_buf_num; | 65 | int ipu_buf_num; |
66 | int csi_buf_num; | 66 | int csi_buf_num; |
67 | }; | 67 | }; |
68 | }; | 68 | }; |
69 | 69 | ||
70 | /* Only for old version. Will go away soon. */ | 70 | /* Only for old version. Will go away soon. */ |
71 | typedef struct { | 71 | typedef struct { |
72 | u8 clk_mode; | 72 | u8 clk_mode; |
73 | u8 ext_vsync; | 73 | u8 ext_vsync; |
74 | u8 Vsync_pol; | 74 | u8 Vsync_pol; |
75 | u8 Hsync_pol; | 75 | u8 Hsync_pol; |
76 | u8 pixclk_pol; | 76 | u8 pixclk_pol; |
77 | u8 data_pol; | 77 | u8 data_pol; |
78 | u8 data_width; | 78 | u8 data_width; |
79 | u8 pack_tight; | 79 | u8 pack_tight; |
80 | u8 force_eof; | 80 | u8 force_eof; |
81 | u8 data_en_pol; | 81 | u8 data_en_pol; |
82 | u16 width; | 82 | u16 width; |
83 | u16 height; | 83 | u16 height; |
84 | u32 pixel_fmt; | 84 | u32 pixel_fmt; |
85 | u32 mclk; | 85 | u32 mclk; |
86 | u16 active_width; | 86 | u16 active_width; |
87 | u16 active_height; | 87 | u16 active_height; |
88 | } sensor_interface; | 88 | } sensor_interface; |
89 | 89 | ||
90 | /* Sensor control function */ | 90 | /* Sensor control function */ |
91 | /* Only for old version. Will go away soon. */ | 91 | /* Only for old version. Will go away soon. */ |
92 | struct camera_sensor { | 92 | struct camera_sensor { |
93 | void (*set_color) (int bright, int saturation, int red, int green, | 93 | void (*set_color) (int bright, int saturation, int red, int green, |
94 | int blue); | 94 | int blue); |
95 | void (*get_color) (int *bright, int *saturation, int *red, int *green, | 95 | void (*get_color) (int *bright, int *saturation, int *red, int *green, |
96 | int *blue); | 96 | int *blue); |
97 | void (*set_ae_mode) (int ae_mode); | 97 | void (*set_ae_mode) (int ae_mode); |
98 | void (*get_ae_mode) (int *ae_mode); | 98 | void (*get_ae_mode) (int *ae_mode); |
99 | sensor_interface *(*config) (int *frame_rate, int high_quality); | 99 | sensor_interface *(*config) (int *frame_rate, int high_quality); |
100 | sensor_interface *(*reset) (void); | 100 | sensor_interface *(*reset) (void); |
101 | void (*get_std) (v4l2_std_id *std); | 101 | void (*get_std) (v4l2_std_id *std); |
102 | void (*set_std) (v4l2_std_id std); | 102 | void (*set_std) (v4l2_std_id std); |
103 | unsigned int csi; | 103 | unsigned int csi; |
104 | }; | 104 | }; |
105 | 105 | ||
106 | /*! | 106 | /*! |
107 | * common v4l2 driver structure. | 107 | * common v4l2 driver structure. |
108 | */ | 108 | */ |
109 | typedef struct _cam_data { | 109 | typedef struct _cam_data { |
110 | struct video_device *video_dev; | 110 | struct video_device *video_dev; |
111 | int device_type; | 111 | int device_type; |
112 | 112 | ||
113 | /* semaphore guard against SMP multithreading */ | 113 | /* semaphore guard against SMP multithreading */ |
114 | struct semaphore busy_lock; | 114 | struct semaphore busy_lock; |
115 | 115 | ||
116 | int open_count; | 116 | int open_count; |
117 | 117 | ||
118 | /* params lock for this camera */ | 118 | /* params lock for this camera */ |
119 | struct semaphore param_lock; | 119 | struct semaphore param_lock; |
120 | 120 | ||
121 | /* Encoder */ | 121 | /* Encoder */ |
122 | struct list_head ready_q; | 122 | struct list_head ready_q; |
123 | struct list_head done_q; | 123 | struct list_head done_q; |
124 | struct list_head working_q; | 124 | struct list_head working_q; |
125 | int ping_pong_csi; | 125 | int ping_pong_csi; |
126 | spinlock_t queue_int_lock; | 126 | spinlock_t queue_int_lock; |
127 | spinlock_t dqueue_int_lock; | 127 | spinlock_t dqueue_int_lock; |
128 | struct mxc_v4l_frame frame[FRAME_NUM]; | 128 | struct mxc_v4l_frame frame[FRAME_NUM]; |
129 | struct mxc_v4l_frame dummy_frame; | 129 | struct mxc_v4l_frame dummy_frame; |
130 | wait_queue_head_t enc_queue; | 130 | wait_queue_head_t enc_queue; |
131 | int enc_counter; | 131 | int enc_counter; |
132 | dma_addr_t rot_enc_bufs[2]; | 132 | dma_addr_t rot_enc_bufs[2]; |
133 | void *rot_enc_bufs_vaddr[2]; | 133 | void *rot_enc_bufs_vaddr[2]; |
134 | int rot_enc_buf_size[2]; | 134 | int rot_enc_buf_size[2]; |
135 | enum v4l2_buf_type type; | 135 | enum v4l2_buf_type type; |
136 | 136 | ||
137 | /* still image capture */ | 137 | /* still image capture */ |
138 | wait_queue_head_t still_queue; | 138 | wait_queue_head_t still_queue; |
139 | int still_counter; | 139 | int still_counter; |
140 | dma_addr_t still_buf[2]; | 140 | dma_addr_t still_buf[2]; |
141 | void *still_buf_vaddr; | 141 | void *still_buf_vaddr; |
142 | 142 | ||
143 | /* overlay */ | 143 | /* overlay */ |
144 | struct v4l2_window win; | 144 | struct v4l2_window win; |
145 | struct v4l2_framebuffer v4l2_fb; | 145 | struct v4l2_framebuffer v4l2_fb; |
146 | dma_addr_t vf_bufs[2]; | 146 | dma_addr_t vf_bufs[2]; |
147 | void *vf_bufs_vaddr[2]; | 147 | void *vf_bufs_vaddr[2]; |
148 | int vf_bufs_size[2]; | 148 | int vf_bufs_size[2]; |
149 | dma_addr_t rot_vf_bufs[2]; | 149 | dma_addr_t rot_vf_bufs[2]; |
150 | void *rot_vf_bufs_vaddr[2]; | 150 | void *rot_vf_bufs_vaddr[2]; |
151 | int rot_vf_buf_size[2]; | 151 | int rot_vf_buf_size[2]; |
152 | bool overlay_active; | 152 | bool overlay_active; |
153 | int output; | 153 | int output; |
154 | struct fb_info *overlay_fb; | 154 | struct fb_info *overlay_fb; |
155 | int fb_origin_std; | 155 | int fb_origin_std; |
156 | struct work_struct csi_work_struct; | 156 | struct work_struct csi_work_struct; |
157 | 157 | ||
158 | /* v4l2 format */ | 158 | /* v4l2 format */ |
159 | struct v4l2_format v2f; | 159 | struct v4l2_format v2f; |
160 | struct v4l2_format input_fmt; /* camera in */ | 160 | struct v4l2_format input_fmt; /* camera in */ |
161 | bool bswapenable; | 161 | bool bswapenable; |
162 | int rotation; /* for IPUv1 and IPUv3, this means encoder rotation */ | 162 | int rotation; /* for IPUv1 and IPUv3, this means encoder rotation */ |
163 | int vf_rotation; /* viewfinder rotation only for IPUv1 and IPUv3 */ | 163 | int vf_rotation; /* viewfinder rotation only for IPUv1 and IPUv3 */ |
164 | struct v4l2_mxc_offset offset; | 164 | struct v4l2_mxc_offset offset; |
165 | 165 | ||
166 | /* V4l2 control bit */ | 166 | /* V4l2 control bit */ |
167 | int bright; | 167 | int bright; |
168 | int hue; | 168 | int hue; |
169 | int contrast; | 169 | int contrast; |
170 | int saturation; | 170 | int saturation; |
171 | int red; | 171 | int red; |
172 | int green; | 172 | int green; |
173 | int blue; | 173 | int blue; |
174 | int ae_mode; | 174 | int ae_mode; |
175 | 175 | ||
176 | /* standard */ | 176 | /* standard */ |
177 | struct v4l2_streamparm streamparm; | 177 | struct v4l2_streamparm streamparm; |
178 | struct v4l2_standard standard; | 178 | struct v4l2_standard standard; |
179 | bool standard_autodetect; | 179 | bool standard_autodetect; |
180 | 180 | ||
181 | /* crop */ | 181 | /* crop */ |
182 | struct v4l2_rect crop_bounds; | 182 | struct v4l2_rect crop_bounds; |
183 | struct v4l2_rect crop_defrect; | 183 | struct v4l2_rect crop_defrect; |
184 | struct v4l2_rect crop_current; | 184 | struct v4l2_rect crop_current; |
185 | 185 | ||
186 | int (*enc_update_eba) (struct ipu_soc *ipu, dma_addr_t eba, | 186 | int (*enc_update_eba) (struct ipu_soc *ipu, dma_addr_t eba, |
187 | int *bufferNum); | 187 | int *bufferNum); |
188 | int (*enc_enable) (void *private); | 188 | int (*enc_enable) (void *private); |
189 | int (*enc_disable) (void *private); | 189 | int (*enc_disable) (void *private); |
190 | int (*enc_enable_csi) (void *private); | 190 | int (*enc_enable_csi) (void *private); |
191 | int (*enc_disable_csi) (void *private); | 191 | int (*enc_disable_csi) (void *private); |
192 | void (*enc_callback) (u32 mask, void *dev); | 192 | void (*enc_callback) (u32 mask, void *dev); |
193 | int (*vf_start_adc) (void *private); | 193 | int (*vf_start_adc) (void *private); |
194 | int (*vf_stop_adc) (void *private); | 194 | int (*vf_stop_adc) (void *private); |
195 | int (*vf_start_sdc) (void *private); | 195 | int (*vf_start_sdc) (void *private); |
196 | int (*vf_stop_sdc) (void *private); | 196 | int (*vf_stop_sdc) (void *private); |
197 | int (*vf_enable_csi) (void *private); | 197 | int (*vf_enable_csi) (void *private); |
198 | int (*vf_disable_csi) (void *private); | 198 | int (*vf_disable_csi) (void *private); |
199 | int (*csi_start) (void *private); | 199 | int (*csi_start) (void *private); |
200 | int (*csi_stop) (void *private); | 200 | int (*csi_stop) (void *private); |
201 | 201 | ||
202 | /* misc status flag */ | 202 | /* misc status flag */ |
203 | bool overlay_on; | 203 | bool overlay_on; |
204 | bool capture_on; | 204 | bool capture_on; |
205 | int overlay_pid; | 205 | int overlay_pid; |
206 | int capture_pid; | 206 | int capture_pid; |
207 | bool low_power; | 207 | bool low_power; |
208 | wait_queue_head_t power_queue; | 208 | wait_queue_head_t power_queue; |
209 | unsigned int ipu_id; | 209 | unsigned int ipu_id; |
210 | unsigned int csi; | 210 | unsigned int csi; |
211 | u8 mclk_source; | 211 | u8 mclk_source; |
212 | bool mclk_on[2]; /* two mclk sources at most now */ | 212 | bool mclk_on[2]; /* two mclk sources at most now */ |
213 | int current_input; | 213 | int current_input; |
214 | 214 | ||
215 | int local_buf_num; | 215 | int local_buf_num; |
216 | 216 | ||
217 | /* camera sensor interface */ | 217 | /* camera sensor interface */ |
218 | struct camera_sensor *cam_sensor; /* old version */ | 218 | struct camera_sensor *cam_sensor; /* old version */ |
219 | struct v4l2_int_device *all_sensors[MXC_SENSOR_NUM]; | 219 | struct v4l2_int_device *all_sensors[MXC_SENSOR_NUM]; |
220 | struct v4l2_int_device *sensor; | 220 | struct v4l2_int_device *sensor; |
221 | struct v4l2_int_device *self; | 221 | struct v4l2_int_device *self; |
222 | int sensor_index; | 222 | int sensor_index; |
223 | void *ipu; | 223 | void *ipu; |
224 | void *csi_soc; | 224 | void *csi_soc; |
225 | enum imx_v4l2_devtype devtype; | 225 | enum imx_v4l2_devtype devtype; |
226 | 226 | ||
227 | /* v4l2 buf elements related to PxP DMA */ | 227 | /* v4l2 buf elements related to PxP DMA */ |
228 | struct completion pxp_tx_cmpl; | 228 | struct completion pxp_tx_cmpl; |
229 | struct pxp_channel *pxp_chan; | 229 | struct pxp_channel *pxp_chan; |
230 | struct pxp_config_data pxp_conf; | 230 | struct pxp_config_data pxp_conf; |
231 | struct dma_async_tx_descriptor *txd; | 231 | struct dma_async_tx_descriptor *txd; |
232 | dma_cookie_t cookie; | 232 | dma_cookie_t cookie; |
233 | struct scatterlist sg[2]; | 233 | struct scatterlist sg[2]; |
234 | |||
235 | /* pdev from runtime pm */ | ||
236 | struct platform_device *pdev; | ||
234 | } cam_data; | 237 | } cam_data; |
235 | 238 | ||
236 | struct sensor_data { | 239 | struct sensor_data { |
237 | const struct ov5642_platform_data *platform_data; | 240 | const struct ov5642_platform_data *platform_data; |
238 | struct v4l2_int_device *v4l2_int_device; | 241 | struct v4l2_int_device *v4l2_int_device; |
239 | struct i2c_client *i2c_client; | 242 | struct i2c_client *i2c_client; |
240 | struct v4l2_pix_format pix; | 243 | struct v4l2_pix_format pix; |
241 | struct v4l2_captureparm streamcap; | 244 | struct v4l2_captureparm streamcap; |
242 | bool on; | 245 | bool on; |
243 | 246 | ||
244 | /* control settings */ | 247 | /* control settings */ |
245 | int brightness; | 248 | int brightness; |
246 | int hue; | 249 | int hue; |
247 | int contrast; | 250 | int contrast; |
248 | int saturation; | 251 | int saturation; |
249 | int red; | 252 | int red; |
250 | int green; | 253 | int green; |
251 | int blue; | 254 | int blue; |
252 | int ae_mode; | 255 | int ae_mode; |
253 | 256 | ||
254 | u32 mclk; | 257 | u32 mclk; |
255 | u8 mclk_source; | 258 | u8 mclk_source; |
256 | struct clk *sensor_clk; | 259 | struct clk *sensor_clk; |
257 | int csi; | 260 | int csi; |
258 | 261 | ||
259 | void (*io_init)(void); | 262 | void (*io_init)(void); |
260 | }; | 263 | }; |
261 | 264 | ||
262 | void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi); | 265 | void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi); |
263 | #endif /* __MXC_V4L2_CAPTURE_H__ */ | 266 | #endif /* __MXC_V4L2_CAPTURE_H__ */ |
264 | 267 |