aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pxa_camera.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2008-04-22 09:40:23 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:09:45 -0400
commit5aa2110f3f33feb4a0c67a4996dc400dc594bc1d (patch)
tree7c7806b8edec85e7afdaea696b7106fa0d683c6f /drivers/media/video/pxa_camera.c
parente7c506881973d0c762d660005be54c4095219c59 (diff)
V4L/DVB (7671): pxa-camera: fix DMA sg-list coalescing for more than 2 buffers
Currently the pxa-camera driver has a bug, visible when the user requests more than 2 video buffers. When the third buffer is queued, it is not appended to the DMA-descriptor list of the second buffer, but is again appended to the first buffer. Fix it. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pxa_camera.c')
-rw-r--r--drivers/media/video/pxa_camera.c35
1 files changed, 15 insertions, 20 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 1dcfd9109c57..7cc8e9b19fb7 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -102,11 +102,6 @@ struct pxa_buffer {
102 enum pxa_camera_active_dma active_dma; 102 enum pxa_camera_active_dma active_dma;
103}; 103};
104 104
105struct pxa_framebuffer_queue {
106 dma_addr_t sg_last_dma;
107 struct pxa_dma_desc *sg_last_cpu;
108};
109
110struct pxa_camera_dev { 105struct pxa_camera_dev {
111 struct device *dev; 106 struct device *dev;
112 /* PXA27x is only supposed to handle one camera on its Quick Capture 107 /* PXA27x is only supposed to handle one camera on its Quick Capture
@@ -131,6 +126,7 @@ struct pxa_camera_dev {
131 spinlock_t lock; 126 spinlock_t lock;
132 127
133 struct pxa_buffer *active; 128 struct pxa_buffer *active;
129 struct pxa_dma_desc *sg_tail[3];
134}; 130};
135 131
136static const char *pxa_cam_driver_description = "PXA_Camera"; 132static const char *pxa_cam_driver_description = "PXA_Camera";
@@ -144,11 +140,14 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
144 unsigned int *size) 140 unsigned int *size)
145{ 141{
146 struct soc_camera_device *icd = vq->priv_data; 142 struct soc_camera_device *icd = vq->priv_data;
143 struct soc_camera_host *ici =
144 to_soc_camera_host(icd->dev.parent);
145 struct pxa_camera_dev *pcdev = ici->priv;
147 146
148 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); 147 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
149 148
150 /* planar capture requires Y, U and V buffers to be page aligned */ 149 /* planar capture requires Y, U and V buffers to be page aligned */
151 if (icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P) { 150 if (pcdev->channels == 3) {
152 *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */ 151 *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */
153 *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */ 152 *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */
154 *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */ 153 *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */
@@ -296,7 +295,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
296 if (ret) 295 if (ret)
297 goto fail; 296 goto fail;
298 297
299 if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) { 298 if (pcdev->channels == 3) {
300 /* FIXME the calculations should be more precise */ 299 /* FIXME the calculations should be more precise */
301 sglen_y = dma->sglen / 2; 300 sglen_y = dma->sglen / 2;
302 sglen_u = sglen_v = dma->sglen / 4 + 1; 301 sglen_u = sglen_v = dma->sglen / 4 + 1;
@@ -318,7 +317,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
318 goto fail; 317 goto fail;
319 } 318 }
320 319
321 if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) { 320 if (pcdev->channels == 3) {
322 /* init DMA for U channel */ 321 /* init DMA for U channel */
323 ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u, 322 ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u,
324 sglen_y, 0x30, size_u); 323 sglen_y, 0x30, size_u);
@@ -343,7 +342,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
343 342
344 buf->inwork = 0; 343 buf->inwork = 0;
345 buf->active_dma = DMA_Y; 344 buf->active_dma = DMA_Y;
346 if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) 345 if (pcdev->channels == 3)
347 buf->active_dma |= DMA_U | DMA_V; 346 buf->active_dma |= DMA_U | DMA_V;
348 347
349 return 0; 348 return 0;
@@ -371,6 +370,7 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq,
371 struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); 370 struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
372 struct pxa_buffer *active; 371 struct pxa_buffer *active;
373 unsigned long flags; 372 unsigned long flags;
373 int i;
374 374
375 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 375 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
376 vb, vb->baddr, vb->bsize); 376 vb, vb->baddr, vb->bsize);
@@ -383,15 +383,11 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq,
383 383
384 if (!active) { 384 if (!active) {
385 CIFR |= CIFR_RESET_F; 385 CIFR |= CIFR_RESET_F;
386 DDADR(pcdev->dma_chans[0]) = buf->dmas[0].sg_dma;
387 DCSR(pcdev->dma_chans[0]) = DCSR_RUN;
388
389 if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) {
390 DDADR(pcdev->dma_chans[1]) = buf->dmas[1].sg_dma;
391 DCSR(pcdev->dma_chans[1]) = DCSR_RUN;
392 386
393 DDADR(pcdev->dma_chans[2]) = buf->dmas[2].sg_dma; 387 for (i = 0; i < pcdev->channels; i++) {
394 DCSR(pcdev->dma_chans[2]) = DCSR_RUN; 388 DDADR(pcdev->dma_chans[i]) = buf->dmas[i].sg_dma;
389 DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
390 pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen - 1;
395 } 391 }
396 392
397 pcdev->active = buf; 393 pcdev->active = buf;
@@ -400,7 +396,6 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq,
400 struct pxa_cam_dma *buf_dma; 396 struct pxa_cam_dma *buf_dma;
401 struct pxa_cam_dma *act_dma; 397 struct pxa_cam_dma *act_dma;
402 int nents; 398 int nents;
403 int i;
404 399
405 for (i = 0; i < pcdev->channels; i++) { 400 for (i = 0; i < pcdev->channels; i++) {
406 buf_dma = &buf->dmas[i]; 401 buf_dma = &buf->dmas[i];
@@ -412,8 +407,8 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq,
412 407
413 /* Add the descriptors we just initialized to 408 /* Add the descriptors we just initialized to
414 the currently running chain */ 409 the currently running chain */
415 act_dma->sg_cpu[act_dma->sglen - 1].ddadr = 410 pcdev->sg_tail[i]->ddadr = buf_dma->sg_dma;
416 buf_dma->sg_dma; 411 pcdev->sg_tail[i] = buf_dma->sg_cpu + buf_dma->sglen - 1;
417 412
418 /* Setup a dummy descriptor with the DMA engines current 413 /* Setup a dummy descriptor with the DMA engines current
419 * state 414 * state