aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorRobby Cai <R63905@freescale.com>2013-12-20 05:20:47 -0500
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:47:31 -0400
commitc60c2626756cdf54d48bd6070f25928b2edf6088 (patch)
treeed82b40d7bc4bb30d7e89852c6935aae9080ab48 /drivers/media
parentda556c02559574c290cf975fb53b4d3cedd1db31 (diff)
ENGR00293132-1 pxp/v4l2: change memory alloc policy for PxP output buffer
In previous implementation, the memory allocation/free for PxP output buffer is done each time v4l2 output device is opened/closed. This is not necessary and may cause memory fragmentation issue after running many many times. Now we re-allocate the memory for it only if the existing memory size is not sufficent for new case. Signed-off-by: Robby Cai <R63905@freescale.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/platform/mxc/output/mxc_pxp_v4l2.c65
-rw-r--r--drivers/media/platform/mxc/output/mxc_pxp_v4l2.h12
2 files changed, 54 insertions, 23 deletions
diff --git a/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c
index 8fe072ecbf1c..08ea59ab5510 100644
--- a/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c
+++ b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. 2 * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
@@ -168,6 +168,30 @@ struct v4l2_queryctrl pxp_controls[] = {
168 }, 168 },
169}; 169};
170 170
171static void free_dma_buf(struct pxps *pxp, struct dma_mem *buf)
172{
173 dma_free_coherent(&pxp->pdev->dev, buf->size, buf->vaddr, buf->paddr);
174 dev_dbg(&pxp->pdev->dev,
175 "free dma size:0x%x, paddr:0x%x\n",
176 buf->size, buf->paddr);
177 memset(buf, 0, sizeof(*buf));
178}
179
180static int alloc_dma_buf(struct pxps *pxp, struct dma_mem *buf)
181{
182
183 buf->vaddr = dma_alloc_coherent(&pxp->pdev->dev, buf->size, &buf->paddr,
184 GFP_DMA | GFP_KERNEL);
185 if (!buf->vaddr) {
186 dev_err(&pxp->pdev->dev,
187 "cannot get dma buf size:0x%x\n", buf->size);
188 return -ENOMEM;
189 }
190 dev_dbg(&pxp->pdev->dev,
191 "alloc dma buf size:0x%x, paddr:0x%x\n", buf->size, buf->paddr);
192 return 0;
193}
194
171/* callback function */ 195/* callback function */
172static void video_dma_done(void *arg) 196static void video_dma_done(void *arg)
173{ 197{
@@ -300,7 +324,7 @@ static int pxp_show_buf(struct pxps *pxp, bool toshow)
300 324
301 console_lock(); 325 console_lock();
302 fbi->fix.smem_start = toshow ? 326 fbi->fix.smem_start = toshow ?
303 pxp->outb_phys : (unsigned long)pxp->fb.base; 327 pxp->outbuf.paddr : (unsigned long)pxp->fb.base;
304 ret = fb_pan_display(fbi, &fbi->var); 328 ret = fb_pan_display(fbi, &fbi->var);
305 console_unlock(); 329 console_unlock();
306 330
@@ -381,7 +405,7 @@ static int pxp_enumoutput(struct file *file, void *fh,
381 } 405 }
382 o->type = V4L2_OUTPUT_TYPE_INTERNAL; 406 o->type = V4L2_OUTPUT_TYPE_INTERNAL;
383 o->std = 0; 407 o->std = 0;
384 o->reserved[0] = pxp->outb_phys; 408 o->reserved[0] = pxp->outbuf.paddr;
385 409
386 return 0; 410 return 0;
387} 411}
@@ -401,30 +425,27 @@ static int pxp_s_output(struct file *file, void *fh,
401{ 425{
402 struct pxps *pxp = video_get_drvdata(video_devdata(file)); 426 struct pxps *pxp = video_get_drvdata(video_devdata(file));
403 struct v4l2_pix_format *fmt = &pxp->fb.fmt; 427 struct v4l2_pix_format *fmt = &pxp->fb.fmt;
404 int bpp; 428 u32 size;
429 int ret, bpp;
405 430
406 if ((i < 0) || (i > 1)) 431 if ((i < 0) || (i > 1))
407 return -EINVAL; 432 return -EINVAL;
408 433
409 if (pxp->outb)
410 return 0;
411
412 /* Output buffer is same format as fbdev */ 434 /* Output buffer is same format as fbdev */
413 if (fmt->pixelformat == V4L2_PIX_FMT_RGB24) 435 if (fmt->pixelformat == V4L2_PIX_FMT_RGB24)
414 bpp = 4; 436 bpp = 4;
415 else 437 else
416 bpp = 2; 438 bpp = 2;
417 439
418 pxp->outb_size = fmt->width * fmt->height * bpp; 440 size = fmt->width * fmt->height * bpp;
419 pxp->outb = kmalloc(fmt->width * fmt->height * bpp, 441 if (size > pxp->outbuf.size) {
420 GFP_KERNEL | GFP_DMA); 442 if (pxp->outbuf.vaddr)
421 if (pxp->outb == NULL) { 443 free_dma_buf(pxp, &pxp->outbuf);
422 dev_err(&pxp->pdev->dev, "No enough memory!\n"); 444 pxp->outbuf.size = size;
423 return -ENOMEM; 445 ret = alloc_dma_buf(pxp, &pxp->outbuf);
446 if (ret < 0)
447 return ret;
424 } 448 }
425 pxp->outb_phys = virt_to_phys(pxp->outb);
426 dma_map_single(NULL, pxp->outb,
427 fmt->width * fmt->height * bpp, DMA_TO_DEVICE);
428 449
429 pxp->pxp_conf.out_param.width = fmt->width; 450 pxp->pxp_conf.out_param.width = fmt->width;
430 pxp->pxp_conf.out_param.height = fmt->height; 451 pxp->pxp_conf.out_param.height = fmt->height;
@@ -726,6 +747,12 @@ static int pxp_buf_prepare(struct videobuf_queue *q,
726 int ret = 0; 747 int ret = 0;
727 int i, length; 748 int i, length;
728 749
750 if (!pxp->outbuf.paddr) {
751 dev_err(&pxp->pdev->dev, "Not allocate memory for "
752 "PxP Out buffer?\n");
753 return -ENOMEM;
754 }
755
729 vb->width = pxp->pxp_conf.s0_param.width; 756 vb->width = pxp->pxp_conf.s0_param.width;
730 vb->height = pxp->pxp_conf.s0_param.height; 757 vb->height = pxp->pxp_conf.s0_param.height;
731 vb->size = vb->width * vb->height * pxp->s0_fmt->bpp; 758 vb->size = vb->width * vb->height * pxp->s0_fmt->bpp;
@@ -785,7 +812,7 @@ static int pxp_buf_prepare(struct videobuf_queue *q,
785 pxp->fb.fmt.height; 812 pxp->fb.fmt.height;
786 } 813 }
787 814
788 pxp_conf->out_param.paddr = pxp->outb_phys; 815 pxp_conf->out_param.paddr = pxp->outbuf.paddr;
789 memcpy(&desc->layer_param.out_param, 816 memcpy(&desc->layer_param.out_param,
790 &pxp_conf->out_param, 817 &pxp_conf->out_param,
791 sizeof(struct pxp_layer_param)); 818 sizeof(struct pxp_layer_param));
@@ -1100,8 +1127,6 @@ static int pxp_close(struct file *file)
1100 videobuf_stop(&pxp->s0_vbq); 1127 videobuf_stop(&pxp->s0_vbq);
1101 videobuf_mmap_free(&pxp->s0_vbq); 1128 videobuf_mmap_free(&pxp->s0_vbq);
1102 pxp->active = NULL; 1129 pxp->active = NULL;
1103 kfree(pxp->outb);
1104 pxp->outb = NULL;
1105 1130
1106 mutex_lock(&pxp->mutex); 1131 mutex_lock(&pxp->mutex);
1107 pxp->users--; 1132 pxp->users--;
@@ -1238,6 +1263,8 @@ static int pxp_remove(struct platform_device *pdev)
1238 video_unregister_device(pxp->vdev); 1263 video_unregister_device(pxp->vdev);
1239 video_device_release(pxp->vdev); 1264 video_device_release(pxp->vdev);
1240 1265
1266 free_dma_buf(pxp, &pxp->outbuf);
1267
1241 kfree(pxp); 1268 kfree(pxp);
1242 1269
1243 return 0; 1270 return 0;
diff --git a/drivers/media/platform/mxc/output/mxc_pxp_v4l2.h b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.h
index f1d3da78c345..8abb4c17f3fd 100644
--- a/drivers/media/platform/mxc/output/mxc_pxp_v4l2.h
+++ b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. 2 * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
@@ -37,6 +37,12 @@ struct pxp_buffer {
37 struct scatterlist sg[3]; 37 struct scatterlist sg[3];
38}; 38};
39 39
40struct dma_mem {
41 void *vaddr;
42 dma_addr_t paddr;
43 size_t size;
44};
45
40struct pxps { 46struct pxps {
41 struct platform_device *pdev; 47 struct platform_device *pdev;
42 48
@@ -51,11 +57,9 @@ struct pxps {
51 struct list_head outq; 57 struct list_head outq;
52 struct pxp_channel *pxp_channel[1]; /* We need 1 channel */ 58 struct pxp_channel *pxp_channel[1]; /* We need 1 channel */
53 struct pxp_config_data pxp_conf; 59 struct pxp_config_data pxp_conf;
60 struct dma_mem outbuf;
54 61
55 int output; 62 int output;
56 u32 *outb;
57 dma_addr_t outb_phys;
58 u32 outb_size;
59 63
60 /* Current S0 configuration */ 64 /* Current S0 configuration */
61 struct pxp_data_format *s0_fmt; 65 struct pxp_data_format *s0_fmt;