diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2011-02-21 05:14:01 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:32:15 -0400 |
commit | 379fa5d3567ca2c20843bdba06e456de51b195e9 (patch) | |
tree | f69836edf1a7a21c1bf5e1d2f2eb7f31308a5d9e | |
parent | a616898d6df29b8ffaea5742f678b3ac223b307c (diff) |
[media] V4L: mx3_camera: convert to videobuf2
Now that soc-camera supports videobuf API v1 and v2, camera-host drivers
can be converted to videobuf2 individually. This patch converts the
mx3_camera driver.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/mx3_camera.c | 345 |
1 files changed, 141 insertions, 204 deletions
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index c8c6c03a6a62..502e2a40964c 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #include <media/v4l2-common.h> | 22 | #include <media/v4l2-common.h> |
23 | #include <media/v4l2-dev.h> | 23 | #include <media/v4l2-dev.h> |
24 | #include <media/videobuf-dma-contig.h> | 24 | #include <media/videobuf2-dma-contig.h> |
25 | #include <media/soc_camera.h> | 25 | #include <media/soc_camera.h> |
26 | #include <media/soc_mediabus.h> | 26 | #include <media/soc_mediabus.h> |
27 | 27 | ||
@@ -62,10 +62,16 @@ | |||
62 | 62 | ||
63 | #define MAX_VIDEO_MEM 16 | 63 | #define MAX_VIDEO_MEM 16 |
64 | 64 | ||
65 | enum csi_buffer_state { | ||
66 | CSI_BUF_NEEDS_INIT, | ||
67 | CSI_BUF_PREPARED, | ||
68 | }; | ||
69 | |||
65 | struct mx3_camera_buffer { | 70 | struct mx3_camera_buffer { |
66 | /* common v4l buffer stuff -- must be first */ | 71 | /* common v4l buffer stuff -- must be first */ |
67 | struct videobuf_buffer vb; | 72 | struct vb2_buffer vb; |
68 | enum v4l2_mbus_pixelcode code; | 73 | enum csi_buffer_state state; |
74 | struct list_head queue; | ||
69 | 75 | ||
70 | /* One descriptot per scatterlist (per frame) */ | 76 | /* One descriptot per scatterlist (per frame) */ |
71 | struct dma_async_tx_descriptor *txd; | 77 | struct dma_async_tx_descriptor *txd; |
@@ -108,6 +114,9 @@ struct mx3_camera_dev { | |||
108 | struct list_head capture; | 114 | struct list_head capture; |
109 | spinlock_t lock; /* Protects video buffer lists */ | 115 | spinlock_t lock; /* Protects video buffer lists */ |
110 | struct mx3_camera_buffer *active; | 116 | struct mx3_camera_buffer *active; |
117 | struct vb2_alloc_ctx *alloc_ctx; | ||
118 | enum v4l2_field field; | ||
119 | int sequence; | ||
111 | 120 | ||
112 | /* IDMAC / dmaengine interface */ | 121 | /* IDMAC / dmaengine interface */ |
113 | struct idmac_channel *idmac_channel[1]; /* We need one channel */ | 122 | struct idmac_channel *idmac_channel[1]; /* We need one channel */ |
@@ -130,6 +139,11 @@ static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg) | |||
130 | __raw_writel(value, mx3->base + reg); | 139 | __raw_writel(value, mx3->base + reg); |
131 | } | 140 | } |
132 | 141 | ||
142 | static struct mx3_camera_buffer *to_mx3_vb(struct vb2_buffer *vb) | ||
143 | { | ||
144 | return container_of(vb, struct mx3_camera_buffer, vb); | ||
145 | } | ||
146 | |||
133 | /* Called from the IPU IDMAC ISR */ | 147 | /* Called from the IPU IDMAC ISR */ |
134 | static void mx3_cam_dma_done(void *arg) | 148 | static void mx3_cam_dma_done(void *arg) |
135 | { | 149 | { |
@@ -137,20 +151,20 @@ static void mx3_cam_dma_done(void *arg) | |||
137 | struct dma_chan *chan = desc->txd.chan; | 151 | struct dma_chan *chan = desc->txd.chan; |
138 | struct idmac_channel *ichannel = to_idmac_chan(chan); | 152 | struct idmac_channel *ichannel = to_idmac_chan(chan); |
139 | struct mx3_camera_dev *mx3_cam = ichannel->client; | 153 | struct mx3_camera_dev *mx3_cam = ichannel->client; |
140 | struct videobuf_buffer *vb; | ||
141 | 154 | ||
142 | dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n", | 155 | dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n", |
143 | desc->txd.cookie, mx3_cam->active ? sg_dma_address(&mx3_cam->active->sg) : 0); | 156 | desc->txd.cookie, mx3_cam->active ? sg_dma_address(&mx3_cam->active->sg) : 0); |
144 | 157 | ||
145 | spin_lock(&mx3_cam->lock); | 158 | spin_lock(&mx3_cam->lock); |
146 | if (mx3_cam->active) { | 159 | if (mx3_cam->active) { |
147 | vb = &mx3_cam->active->vb; | 160 | struct vb2_buffer *vb = &mx3_cam->active->vb; |
148 | 161 | struct mx3_camera_buffer *buf = to_mx3_vb(vb); | |
149 | list_del_init(&vb->queue); | 162 | |
150 | vb->state = VIDEOBUF_DONE; | 163 | list_del_init(&buf->queue); |
151 | do_gettimeofday(&vb->ts); | 164 | do_gettimeofday(&vb->v4l2_buf.timestamp); |
152 | vb->field_count++; | 165 | vb->v4l2_buf.field = mx3_cam->field; |
153 | wake_up(&vb->done); | 166 | vb->v4l2_buf.sequence = mx3_cam->sequence++; |
167 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | ||
154 | } | 168 | } |
155 | 169 | ||
156 | if (list_empty(&mx3_cam->capture)) { | 170 | if (list_empty(&mx3_cam->capture)) { |
@@ -165,50 +179,22 @@ static void mx3_cam_dma_done(void *arg) | |||
165 | } | 179 | } |
166 | 180 | ||
167 | mx3_cam->active = list_entry(mx3_cam->capture.next, | 181 | mx3_cam->active = list_entry(mx3_cam->capture.next, |
168 | struct mx3_camera_buffer, vb.queue); | 182 | struct mx3_camera_buffer, queue); |
169 | mx3_cam->active->vb.state = VIDEOBUF_ACTIVE; | ||
170 | spin_unlock(&mx3_cam->lock); | 183 | spin_unlock(&mx3_cam->lock); |
171 | } | 184 | } |
172 | 185 | ||
173 | static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf) | ||
174 | { | ||
175 | struct soc_camera_device *icd = vq->priv_data; | ||
176 | struct videobuf_buffer *vb = &buf->vb; | ||
177 | struct dma_async_tx_descriptor *txd = buf->txd; | ||
178 | struct idmac_channel *ichan; | ||
179 | |||
180 | BUG_ON(in_interrupt()); | ||
181 | |||
182 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | ||
183 | vb, vb->baddr, vb->bsize); | ||
184 | |||
185 | /* | ||
186 | * This waits until this buffer is out of danger, i.e., until it is no | ||
187 | * longer in STATE_QUEUED or STATE_ACTIVE | ||
188 | */ | ||
189 | videobuf_waiton(vq, vb, 0, 0); | ||
190 | if (txd) { | ||
191 | ichan = to_idmac_chan(txd->chan); | ||
192 | async_tx_ack(txd); | ||
193 | } | ||
194 | videobuf_dma_contig_free(vq, vb); | ||
195 | buf->txd = NULL; | ||
196 | |||
197 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
198 | } | ||
199 | |||
200 | /* | 186 | /* |
201 | * Videobuf operations | 187 | * Videobuf operations |
202 | */ | 188 | */ |
203 | 189 | ||
204 | /* | 190 | /* |
205 | * Calculate the __buffer__ (not data) size and number of buffers. | 191 | * Calculate the __buffer__ (not data) size and number of buffers. |
206 | * Called with .vb_lock held | ||
207 | */ | 192 | */ |
208 | static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | 193 | static int mx3_videobuf_setup(struct vb2_queue *vq, |
209 | unsigned int *size) | 194 | unsigned int *count, unsigned int *num_planes, |
195 | unsigned long sizes[], void *alloc_ctxs[]) | ||
210 | { | 196 | { |
211 | struct soc_camera_device *icd = vq->priv_data; | 197 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); |
212 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 198 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
213 | struct mx3_camera_dev *mx3_cam = ici->priv; | 199 | struct mx3_camera_dev *mx3_cam = ici->priv; |
214 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | 200 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
@@ -220,104 +206,66 @@ static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
220 | if (!mx3_cam->idmac_channel[0]) | 206 | if (!mx3_cam->idmac_channel[0]) |
221 | return -EINVAL; | 207 | return -EINVAL; |
222 | 208 | ||
223 | *size = bytes_per_line * icd->user_height; | 209 | *num_planes = 1; |
210 | |||
211 | mx3_cam->sequence = 0; | ||
212 | sizes[0] = bytes_per_line * icd->user_height; | ||
213 | alloc_ctxs[0] = mx3_cam->alloc_ctx; | ||
224 | 214 | ||
225 | if (!*count) | 215 | if (!*count) |
226 | *count = 32; | 216 | *count = 32; |
227 | 217 | ||
228 | if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) | 218 | if (sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024) |
229 | *count = MAX_VIDEO_MEM * 1024 * 1024 / *size; | 219 | *count = MAX_VIDEO_MEM * 1024 * 1024 / sizes[0]; |
230 | 220 | ||
231 | return 0; | 221 | return 0; |
232 | } | 222 | } |
233 | 223 | ||
234 | /* Called with .vb_lock held */ | 224 | static int mx3_videobuf_prepare(struct vb2_buffer *vb) |
235 | static int mx3_videobuf_prepare(struct videobuf_queue *vq, | ||
236 | struct videobuf_buffer *vb, enum v4l2_field field) | ||
237 | { | 225 | { |
238 | struct soc_camera_device *icd = vq->priv_data; | 226 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); |
239 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 227 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
240 | struct mx3_camera_dev *mx3_cam = ici->priv; | 228 | struct mx3_camera_dev *mx3_cam = ici->priv; |
241 | struct mx3_camera_buffer *buf = | 229 | struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; |
242 | container_of(vb, struct mx3_camera_buffer, vb); | 230 | struct scatterlist *sg; |
231 | struct mx3_camera_buffer *buf; | ||
243 | size_t new_size; | 232 | size_t new_size; |
244 | int ret; | ||
245 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | 233 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
246 | icd->current_fmt->host_fmt); | 234 | icd->current_fmt->host_fmt); |
247 | 235 | ||
248 | if (bytes_per_line < 0) | 236 | if (bytes_per_line < 0) |
249 | return bytes_per_line; | 237 | return bytes_per_line; |
250 | 238 | ||
251 | new_size = bytes_per_line * icd->user_height; | 239 | buf = to_mx3_vb(vb); |
252 | 240 | sg = &buf->sg; | |
253 | /* | ||
254 | * I think, in buf_prepare you only have to protect global data, | ||
255 | * the actual buffer is yours | ||
256 | */ | ||
257 | 241 | ||
258 | if (buf->code != icd->current_fmt->code || | 242 | new_size = bytes_per_line * icd->user_height; |
259 | vb->width != icd->user_width || | ||
260 | vb->height != icd->user_height || | ||
261 | vb->field != field) { | ||
262 | buf->code = icd->current_fmt->code; | ||
263 | vb->width = icd->user_width; | ||
264 | vb->height = icd->user_height; | ||
265 | vb->field = field; | ||
266 | if (vb->state != VIDEOBUF_NEEDS_INIT) | ||
267 | free_buffer(vq, buf); | ||
268 | } | ||
269 | 243 | ||
270 | if (vb->baddr && vb->bsize < new_size) { | 244 | if (vb2_plane_size(vb, 0) < new_size) { |
271 | /* User provided buffer, but it is too small */ | 245 | dev_err(icd->dev.parent, "Buffer too small (%lu < %zu)\n", |
272 | ret = -ENOMEM; | 246 | vb2_plane_size(vb, 0), new_size); |
273 | goto out; | 247 | return -ENOBUFS; |
274 | } | 248 | } |
275 | 249 | ||
276 | if (vb->state == VIDEOBUF_NEEDS_INIT) { | 250 | if (buf->state == CSI_BUF_NEEDS_INIT) { |
277 | struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; | 251 | sg_dma_address(sg) = vb2_dma_contig_plane_paddr(vb, 0); |
278 | struct scatterlist *sg = &buf->sg; | 252 | sg_dma_len(sg) = new_size; |
279 | |||
280 | /* | ||
281 | * The total size of video-buffers that will be allocated / mapped. | ||
282 | * *size that we calculated in videobuf_setup gets assigned to | ||
283 | * vb->bsize, and now we use the same calculation to get vb->size. | ||
284 | */ | ||
285 | vb->size = new_size; | ||
286 | |||
287 | /* This actually (allocates and) maps buffers */ | ||
288 | ret = videobuf_iolock(vq, vb, NULL); | ||
289 | if (ret) | ||
290 | goto fail; | ||
291 | |||
292 | /* | ||
293 | * We will have to configure the IDMAC channel. It has two slots | ||
294 | * for DMA buffers, we shall enter the first two buffers there, | ||
295 | * and then submit new buffers in DMA-ready interrupts | ||
296 | */ | ||
297 | sg_init_table(sg, 1); | ||
298 | sg_dma_address(sg) = videobuf_to_dma_contig(vb); | ||
299 | sg_dma_len(sg) = vb->size; | ||
300 | 253 | ||
301 | buf->txd = ichan->dma_chan.device->device_prep_slave_sg( | 254 | buf->txd = ichan->dma_chan.device->device_prep_slave_sg( |
302 | &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE, | 255 | &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE, |
303 | DMA_PREP_INTERRUPT); | 256 | DMA_PREP_INTERRUPT); |
304 | if (!buf->txd) { | 257 | if (!buf->txd) |
305 | ret = -EIO; | 258 | return -EIO; |
306 | goto fail; | ||
307 | } | ||
308 | 259 | ||
309 | buf->txd->callback_param = buf->txd; | 260 | buf->txd->callback_param = buf->txd; |
310 | buf->txd->callback = mx3_cam_dma_done; | 261 | buf->txd->callback = mx3_cam_dma_done; |
311 | 262 | ||
312 | vb->state = VIDEOBUF_PREPARED; | 263 | buf->state = CSI_BUF_PREPARED; |
313 | } | 264 | } |
314 | 265 | ||
315 | return 0; | 266 | vb2_set_plane_payload(vb, 0, new_size); |
316 | 267 | ||
317 | fail: | 268 | return 0; |
318 | free_buffer(vq, buf); | ||
319 | out: | ||
320 | return ret; | ||
321 | } | 269 | } |
322 | 270 | ||
323 | static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) | 271 | static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) |
@@ -333,25 +281,18 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) | |||
333 | } | 281 | } |
334 | } | 282 | } |
335 | 283 | ||
336 | /* | 284 | static void mx3_videobuf_queue(struct vb2_buffer *vb) |
337 | * Called with .vb_lock mutex held and | ||
338 | * under spinlock_irqsave(&mx3_cam->lock, ...) | ||
339 | */ | ||
340 | static void mx3_videobuf_queue(struct videobuf_queue *vq, | ||
341 | struct videobuf_buffer *vb) | ||
342 | { | 285 | { |
343 | struct soc_camera_device *icd = vq->priv_data; | 286 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); |
344 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 287 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
345 | struct mx3_camera_dev *mx3_cam = ici->priv; | 288 | struct mx3_camera_dev *mx3_cam = ici->priv; |
346 | struct mx3_camera_buffer *buf = | 289 | struct mx3_camera_buffer *buf = to_mx3_vb(vb); |
347 | container_of(vb, struct mx3_camera_buffer, vb); | ||
348 | struct dma_async_tx_descriptor *txd = buf->txd; | 290 | struct dma_async_tx_descriptor *txd = buf->txd; |
349 | struct idmac_channel *ichan = to_idmac_chan(txd->chan); | 291 | struct idmac_channel *ichan = to_idmac_chan(txd->chan); |
350 | struct idmac_video_param *video = &ichan->params.video; | 292 | struct idmac_video_param *video = &ichan->params.video; |
351 | dma_cookie_t cookie; | 293 | dma_cookie_t cookie; |
352 | u32 fourcc = icd->current_fmt->host_fmt->fourcc; | 294 | u32 fourcc = icd->current_fmt->host_fmt->fourcc; |
353 | 295 | unsigned long flags; | |
354 | BUG_ON(!irqs_disabled()); | ||
355 | 296 | ||
356 | /* This is the configuration of one sg-element */ | 297 | /* This is the configuration of one sg-element */ |
357 | video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc); | 298 | video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc); |
@@ -383,17 +324,15 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, | |||
383 | 324 | ||
384 | #ifdef DEBUG | 325 | #ifdef DEBUG |
385 | /* helps to see what DMA actually has written */ | 326 | /* helps to see what DMA actually has written */ |
386 | memset((void *)vb->baddr, 0xaa, vb->bsize); | 327 | if (vb2_plane_vaddr(vb, 0)) |
328 | memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0)); | ||
387 | #endif | 329 | #endif |
388 | 330 | ||
389 | list_add_tail(&vb->queue, &mx3_cam->capture); | 331 | spin_lock_irqsave(&mx3_cam->lock, flags); |
332 | list_add_tail(&buf->queue, &mx3_cam->capture); | ||
390 | 333 | ||
391 | if (!mx3_cam->active) { | 334 | if (!mx3_cam->active) |
392 | mx3_cam->active = buf; | 335 | mx3_cam->active = buf; |
393 | vb->state = VIDEOBUF_ACTIVE; | ||
394 | } else { | ||
395 | vb->state = VIDEOBUF_QUEUED; | ||
396 | } | ||
397 | 336 | ||
398 | spin_unlock_irq(&mx3_cam->lock); | 337 | spin_unlock_irq(&mx3_cam->lock); |
399 | 338 | ||
@@ -401,67 +340,87 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, | |||
401 | dev_dbg(icd->dev.parent, "Submitted cookie %d DMA 0x%08x\n", | 340 | dev_dbg(icd->dev.parent, "Submitted cookie %d DMA 0x%08x\n", |
402 | cookie, sg_dma_address(&buf->sg)); | 341 | cookie, sg_dma_address(&buf->sg)); |
403 | 342 | ||
404 | spin_lock_irq(&mx3_cam->lock); | ||
405 | |||
406 | if (cookie >= 0) | 343 | if (cookie >= 0) |
407 | return; | 344 | return; |
408 | 345 | ||
409 | /* Submit error */ | 346 | spin_lock_irq(&mx3_cam->lock); |
410 | vb->state = VIDEOBUF_PREPARED; | ||
411 | 347 | ||
412 | list_del_init(&vb->queue); | 348 | /* Submit error */ |
349 | list_del_init(&buf->queue); | ||
413 | 350 | ||
414 | if (mx3_cam->active == buf) | 351 | if (mx3_cam->active == buf) |
415 | mx3_cam->active = NULL; | 352 | mx3_cam->active = NULL; |
353 | |||
354 | spin_unlock_irqrestore(&mx3_cam->lock, flags); | ||
355 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); | ||
416 | } | 356 | } |
417 | 357 | ||
418 | /* Called with .vb_lock held */ | 358 | static void mx3_videobuf_release(struct vb2_buffer *vb) |
419 | static void mx3_videobuf_release(struct videobuf_queue *vq, | ||
420 | struct videobuf_buffer *vb) | ||
421 | { | 359 | { |
422 | struct soc_camera_device *icd = vq->priv_data; | 360 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); |
423 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 361 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
424 | struct mx3_camera_dev *mx3_cam = ici->priv; | 362 | struct mx3_camera_dev *mx3_cam = ici->priv; |
425 | struct mx3_camera_buffer *buf = | 363 | struct mx3_camera_buffer *buf = to_mx3_vb(vb); |
426 | container_of(vb, struct mx3_camera_buffer, vb); | 364 | struct dma_async_tx_descriptor *txd = buf->txd; |
427 | unsigned long flags; | 365 | unsigned long flags; |
428 | 366 | ||
429 | dev_dbg(icd->dev.parent, | 367 | dev_dbg(icd->dev.parent, |
430 | "Release%s DMA 0x%08x (state %d), queue %sempty\n", | 368 | "Release%s DMA 0x%08x, queue %sempty\n", |
431 | mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg), | 369 | mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg), |
432 | vb->state, list_empty(&vb->queue) ? "" : "not "); | 370 | list_empty(&buf->queue) ? "" : "not "); |
371 | |||
433 | spin_lock_irqsave(&mx3_cam->lock, flags); | 372 | spin_lock_irqsave(&mx3_cam->lock, flags); |
434 | if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && | ||
435 | !list_empty(&vb->queue)) { | ||
436 | vb->state = VIDEOBUF_ERROR; | ||
437 | 373 | ||
438 | list_del_init(&vb->queue); | 374 | if (mx3_cam->active == buf) |
439 | if (mx3_cam->active == buf) | 375 | mx3_cam->active = NULL; |
440 | mx3_cam->active = NULL; | 376 | |
377 | /* Doesn't hurt also if the list is empty */ | ||
378 | list_del_init(&buf->queue); | ||
379 | buf->state = CSI_BUF_NEEDS_INIT; | ||
380 | |||
381 | if (txd) { | ||
382 | buf->txd = NULL; | ||
383 | if (mx3_cam->idmac_channel[0]) | ||
384 | async_tx_ack(txd); | ||
441 | } | 385 | } |
386 | |||
442 | spin_unlock_irqrestore(&mx3_cam->lock, flags); | 387 | spin_unlock_irqrestore(&mx3_cam->lock, flags); |
443 | free_buffer(vq, buf); | ||
444 | } | 388 | } |
445 | 389 | ||
446 | static struct videobuf_queue_ops mx3_videobuf_ops = { | 390 | static int mx3_videobuf_init(struct vb2_buffer *vb) |
447 | .buf_setup = mx3_videobuf_setup, | 391 | { |
448 | .buf_prepare = mx3_videobuf_prepare, | 392 | struct mx3_camera_buffer *buf = to_mx3_vb(vb); |
449 | .buf_queue = mx3_videobuf_queue, | 393 | /* This is for locking debugging only */ |
450 | .buf_release = mx3_videobuf_release, | 394 | INIT_LIST_HEAD(&buf->queue); |
395 | sg_init_table(&buf->sg, 1); | ||
396 | |||
397 | buf->state = CSI_BUF_NEEDS_INIT; | ||
398 | buf->txd = NULL; | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static struct vb2_ops mx3_videobuf_ops = { | ||
404 | .queue_setup = mx3_videobuf_setup, | ||
405 | .buf_prepare = mx3_videobuf_prepare, | ||
406 | .buf_queue = mx3_videobuf_queue, | ||
407 | .buf_cleanup = mx3_videobuf_release, | ||
408 | .buf_init = mx3_videobuf_init, | ||
409 | .wait_prepare = soc_camera_unlock, | ||
410 | .wait_finish = soc_camera_lock, | ||
451 | }; | 411 | }; |
452 | 412 | ||
453 | static void mx3_camera_init_videobuf(struct videobuf_queue *q, | 413 | static int mx3_camera_init_videobuf(struct vb2_queue *q, |
454 | struct soc_camera_device *icd) | 414 | struct soc_camera_device *icd) |
455 | { | 415 | { |
456 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 416 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
457 | struct mx3_camera_dev *mx3_cam = ici->priv; | 417 | q->io_modes = VB2_MMAP | VB2_USERPTR; |
458 | 418 | q->drv_priv = icd; | |
459 | videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, icd->dev.parent, | 419 | q->ops = &mx3_videobuf_ops; |
460 | &mx3_cam->lock, | 420 | q->mem_ops = &vb2_dma_contig_memops; |
461 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 421 | q->buf_struct_size = sizeof(struct mx3_camera_buffer); |
462 | V4L2_FIELD_NONE, | 422 | |
463 | sizeof(struct mx3_camera_buffer), icd, | 423 | return vb2_queue_init(q); |
464 | &icd->video_lock); | ||
465 | } | 424 | } |
466 | 425 | ||
467 | /* First part of ipu_csi_init_interface() */ | 426 | /* First part of ipu_csi_init_interface() */ |
@@ -556,18 +515,6 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) | |||
556 | icd->devnum); | 515 | icd->devnum); |
557 | } | 516 | } |
558 | 517 | ||
559 | static bool channel_change_requested(struct soc_camera_device *icd, | ||
560 | struct v4l2_rect *rect) | ||
561 | { | ||
562 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
563 | struct mx3_camera_dev *mx3_cam = ici->priv; | ||
564 | struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; | ||
565 | |||
566 | /* Do buffers have to be re-allocated or channel re-configured? */ | ||
567 | return ichan && rect->width * rect->height > | ||
568 | icd->user_width * icd->user_height; | ||
569 | } | ||
570 | |||
571 | static int test_platform_param(struct mx3_camera_dev *mx3_cam, | 518 | static int test_platform_param(struct mx3_camera_dev *mx3_cam, |
572 | unsigned char buswidth, unsigned long *flags) | 519 | unsigned char buswidth, unsigned long *flags) |
573 | { | 520 | { |
@@ -808,18 +755,6 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) | |||
808 | struct dma_chan_request rq = {.mx3_cam = mx3_cam, | 755 | struct dma_chan_request rq = {.mx3_cam = mx3_cam, |
809 | .id = IDMAC_IC_7}; | 756 | .id = IDMAC_IC_7}; |
810 | 757 | ||
811 | if (*ichan) { | ||
812 | struct videobuf_buffer *vb, *_vb; | ||
813 | dma_release_channel(&(*ichan)->dma_chan); | ||
814 | *ichan = NULL; | ||
815 | mx3_cam->active = NULL; | ||
816 | list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) { | ||
817 | list_del_init(&vb->queue); | ||
818 | vb->state = VIDEOBUF_ERROR; | ||
819 | wake_up(&vb->done); | ||
820 | } | ||
821 | } | ||
822 | |||
823 | dma_cap_zero(mask); | 758 | dma_cap_zero(mask); |
824 | dma_cap_set(DMA_SLAVE, mask); | 759 | dma_cap_set(DMA_SLAVE, mask); |
825 | dma_cap_set(DMA_PRIVATE, mask); | 760 | dma_cap_set(DMA_PRIVATE, mask); |
@@ -879,19 +814,8 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
879 | return ret; | 814 | return ret; |
880 | } | 815 | } |
881 | 816 | ||
882 | if (mf.width != icd->user_width || mf.height != icd->user_height) { | 817 | if (mf.width != icd->user_width || mf.height != icd->user_height) |
883 | /* | ||
884 | * We now know pixel formats and can decide upon DMA-channel(s) | ||
885 | * So far only direct camera-to-memory is supported | ||
886 | */ | ||
887 | if (channel_change_requested(icd, rect)) { | ||
888 | ret = acquire_dma_channel(mx3_cam); | ||
889 | if (ret < 0) | ||
890 | return ret; | ||
891 | } | ||
892 | |||
893 | configure_geometry(mx3_cam, mf.width, mf.height, mf.code); | 818 | configure_geometry(mx3_cam, mf.width, mf.height, mf.code); |
894 | } | ||
895 | 819 | ||
896 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", | 820 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", |
897 | mf.width, mf.height); | 821 | mf.width, mf.height); |
@@ -923,10 +847,6 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, | |||
923 | stride_align(&pix->width); | 847 | stride_align(&pix->width); |
924 | dev_dbg(icd->dev.parent, "Set format %dx%d\n", pix->width, pix->height); | 848 | dev_dbg(icd->dev.parent, "Set format %dx%d\n", pix->width, pix->height); |
925 | 849 | ||
926 | ret = acquire_dma_channel(mx3_cam); | ||
927 | if (ret < 0) | ||
928 | return ret; | ||
929 | |||
930 | /* | 850 | /* |
931 | * Might have to perform a complete interface initialisation like in | 851 | * Might have to perform a complete interface initialisation like in |
932 | * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider | 852 | * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider |
@@ -948,9 +868,16 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, | |||
948 | if (mf.code != xlate->code) | 868 | if (mf.code != xlate->code) |
949 | return -EINVAL; | 869 | return -EINVAL; |
950 | 870 | ||
871 | if (!mx3_cam->idmac_channel[0]) { | ||
872 | ret = acquire_dma_channel(mx3_cam); | ||
873 | if (ret < 0) | ||
874 | return ret; | ||
875 | } | ||
876 | |||
951 | pix->width = mf.width; | 877 | pix->width = mf.width; |
952 | pix->height = mf.height; | 878 | pix->height = mf.height; |
953 | pix->field = mf.field; | 879 | pix->field = mf.field; |
880 | mx3_cam->field = mf.field; | ||
954 | pix->colorspace = mf.colorspace; | 881 | pix->colorspace = mf.colorspace; |
955 | icd->current_fmt = xlate; | 882 | icd->current_fmt = xlate; |
956 | 883 | ||
@@ -1033,7 +960,7 @@ static unsigned int mx3_camera_poll(struct file *file, poll_table *pt) | |||
1033 | { | 960 | { |
1034 | struct soc_camera_device *icd = file->private_data; | 961 | struct soc_camera_device *icd = file->private_data; |
1035 | 962 | ||
1036 | return videobuf_poll_stream(file, &icd->vb_vidq, pt); | 963 | return vb2_poll(&icd->vb2_vidq, file, pt); |
1037 | } | 964 | } |
1038 | 965 | ||
1039 | static int mx3_camera_querycap(struct soc_camera_host *ici, | 966 | static int mx3_camera_querycap(struct soc_camera_host *ici, |
@@ -1207,7 +1134,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { | |||
1207 | .set_fmt = mx3_camera_set_fmt, | 1134 | .set_fmt = mx3_camera_set_fmt, |
1208 | .try_fmt = mx3_camera_try_fmt, | 1135 | .try_fmt = mx3_camera_try_fmt, |
1209 | .get_formats = mx3_camera_get_formats, | 1136 | .get_formats = mx3_camera_get_formats, |
1210 | .init_videobuf = mx3_camera_init_videobuf, | 1137 | .init_videobuf2 = mx3_camera_init_videobuf, |
1211 | .reqbufs = mx3_camera_reqbufs, | 1138 | .reqbufs = mx3_camera_reqbufs, |
1212 | .poll = mx3_camera_poll, | 1139 | .poll = mx3_camera_poll, |
1213 | .querycap = mx3_camera_querycap, | 1140 | .querycap = mx3_camera_querycap, |
@@ -1283,6 +1210,12 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) | |||
1283 | soc_host->v4l2_dev.dev = &pdev->dev; | 1210 | soc_host->v4l2_dev.dev = &pdev->dev; |
1284 | soc_host->nr = pdev->id; | 1211 | soc_host->nr = pdev->id; |
1285 | 1212 | ||
1213 | mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
1214 | if (IS_ERR(mx3_cam->alloc_ctx)) { | ||
1215 | err = PTR_ERR(mx3_cam->alloc_ctx); | ||
1216 | goto eallocctx; | ||
1217 | } | ||
1218 | |||
1286 | err = soc_camera_host_register(soc_host); | 1219 | err = soc_camera_host_register(soc_host); |
1287 | if (err) | 1220 | if (err) |
1288 | goto ecamhostreg; | 1221 | goto ecamhostreg; |
@@ -1293,6 +1226,8 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) | |||
1293 | return 0; | 1226 | return 0; |
1294 | 1227 | ||
1295 | ecamhostreg: | 1228 | ecamhostreg: |
1229 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); | ||
1230 | eallocctx: | ||
1296 | iounmap(base); | 1231 | iounmap(base); |
1297 | eioremap: | 1232 | eioremap: |
1298 | clk_put(mx3_cam->clk); | 1233 | clk_put(mx3_cam->clk); |
@@ -1322,6 +1257,8 @@ static int __devexit mx3_camera_remove(struct platform_device *pdev) | |||
1322 | if (WARN_ON(mx3_cam->idmac_channel[0])) | 1257 | if (WARN_ON(mx3_cam->idmac_channel[0])) |
1323 | dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan); | 1258 | dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan); |
1324 | 1259 | ||
1260 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); | ||
1261 | |||
1325 | vfree(mx3_cam); | 1262 | vfree(mx3_cam); |
1326 | 1263 | ||
1327 | dmaengine_put(); | 1264 | dmaengine_put(); |