diff options
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch')
-rw-r--r-- | meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch | 730 |
1 files changed, 0 insertions, 730 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch deleted file mode 100644 index 631b05f41..000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch +++ /dev/null @@ -1,730 +0,0 @@ -From 20d79137ecaa6c7dad007d9ea1d7be5550db4839 Mon Sep 17 00:00:00 2001 -From: Vaibhav Hiremath <hvaibhav@ti.com> -Date: Fri, 13 Feb 2009 15:40:25 +0530 -Subject: [PATCH 2/2] Resizer bug fixes on top of 1.0.2 release - -This commit contains resizer bug fixes on top of - PSP1.0.2 release - - - 4096 aligned address constraint - - workaround for extra page allocation for page aligned - size buffers - -Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com> ---- - drivers/media/video/isp/omap_resizer.c | 417 ++++++++++++++++++++++++-------- - include/linux/omap_resizer.h | 3 +- - 2 files changed, 321 insertions(+), 99 deletions(-) - -diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c -index 54bc425..8059c70 100644 ---- a/drivers/media/video/isp/omap_resizer.c -+++ b/drivers/media/video/isp/omap_resizer.c -@@ -28,6 +28,7 @@ - #include <linux/platform_device.h> - #include <linux/io.h> - #include <linux/uaccess.h> -+#include <linux/pci.h> - #include <media/v4l2-dev.h> - #include <asm/cacheflush.h> - -@@ -76,6 +77,10 @@ - #define MAX_COEF_COUNTER 16 - #define COEFF_ADDRESS_OFFSET 0x04 - -+#define RSZ_DEF_REQ_EXP 0xE /* Default read operation expand -+ * for the Resizer driver; value -+ * taken from Davinci. -+ */ - /* Global structure which contains information about number of channels - and protection variables */ - struct device_params { -@@ -85,6 +90,7 @@ struct device_params { - struct mutex reszwrap_mutex; /* Semaphore for array */ - - struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */ -+ unsigned long extra_page_addr; - }; - - /* Register mapped structure which contains the every register -@@ -126,6 +132,9 @@ struct resizer_config { - u32 rsz_yehn; /* yehn(luma)register mapping - * variable. - */ -+ u32 sdr_req_exp; /* Configuration for Non -+ * real time read expand -+ */ - }; - - struct rsz_mult { -@@ -179,6 +188,7 @@ struct channel_config { - * channel is busy or not - */ - struct mutex chanprotection_mutex; -+ int buf_address[VIDEO_MAX_FRAME]; - enum config_done config_state; - u8 input_buf_index; - u8 output_buf_index; -@@ -200,8 +210,6 @@ struct rsz_fh { - struct videobuf_queue vbq; - struct device_params *device; - -- dma_addr_t isp_addr_read; /* Input/Output address */ -- dma_addr_t isp_addr_write; /* Input/Output address */ - u32 rsz_bufsize; /* channel specific buffersize - */ - }; -@@ -227,6 +235,10 @@ static int rsz_set_ratio(struct rsz_mult *multipass, - static void rsz_config_ratio(struct rsz_mult *multipass, - struct channel_config *rsz_conf_chan); - -+static void inline rsz_set_exp(unsigned int exp) -+{ -+ omap_writel(((exp & 0x3FF) << 10), OMAP3ISP_SBL_REG(0xF8)); -+} - /** - * rsz_hardware_setup - Sets hardware configuration registers - * @rsz_conf_chan: Structure containing channel configuration -@@ -271,12 +283,15 @@ static void rsz_hardware_setup(struct channel_config *rsz_conf_chan) - + coeffoffset)); - coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET; - } -+ /* Configure the read expand register */ -+ rsz_set_exp(rsz_conf_chan->register_config.sdr_req_exp); - } - - /** - * rsz_start - Enables Resizer Wrapper - * @arg: Currently not used. -- * @device: Structure containing ISP resizer wrapper global information -+ * @fh: File structure containing ISP resizer information specific to -+ * channel opened. - * - * Submits a resizing task specified by the rsz_resize structure. The call can - * either be blocked until the task is completed or returned immediately based -@@ -292,12 +307,18 @@ int rsz_start(int *arg, struct rsz_fh *fh) - struct channel_config *rsz_conf_chan = fh->config; - struct rsz_mult *multipass = fh->multipass; - struct videobuf_queue *q = &fh->vbq; -+ struct videobuf_buffer *buf; - int ret; - - if (rsz_conf_chan->config_state) { - dev_err(rsz_device, "State not configured \n"); - goto err_einval; - } -+ if (!rsz_conf_chan->register_config.rsz_sdr_inadd || -+ !rsz_conf_chan->register_config.rsz_sdr_outadd) { -+ dev_err(rsz_device, "address is null\n"); -+ goto err_einval; -+ } - - rsz_conf_chan->status = CHANNEL_BUSY; - -@@ -325,33 +346,22 @@ mult: - goto mult; - } - -- if (fh->isp_addr_read) { -- ispmmu_vunmap(fh->isp_addr_read); -- fh->isp_addr_read = 0; -- } -- if (fh->isp_addr_write) { -- ispmmu_vunmap(fh->isp_addr_write); -- fh->isp_addr_write = 0; -- } -- - rsz_conf_chan->status = CHANNEL_FREE; -- q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT; -- q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT; - rsz_conf_chan->register_config.rsz_sdr_outadd = 0; - rsz_conf_chan->register_config.rsz_sdr_inadd = 0; - -- /* Unmap and free the DMA memory allocated for buffers */ -- videobuf_dma_unmap(q, videobuf_to_dma( -- q->bufs[rsz_conf_chan->input_buf_index])); -- videobuf_dma_unmap(q, videobuf_to_dma( -- q->bufs[rsz_conf_chan->output_buf_index])); -- videobuf_dma_free(videobuf_to_dma( -- q->bufs[rsz_conf_chan->input_buf_index])); -- videobuf_dma_free(videobuf_to_dma( -- q->bufs[rsz_conf_chan->output_buf_index])); -- - isp_unset_callback(CBK_RESZ_DONE); - -+ /* Empty the Videobuf queue which was filled during the qbuf */ -+ buf = q->bufs[rsz_conf_chan->input_buf_index]; -+ buf->state = VIDEOBUF_IDLE; -+ list_del(&buf->stream); -+ if (rsz_conf_chan->input_buf_index != rsz_conf_chan->output_buf_index) { -+ buf = q->bufs[rsz_conf_chan->output_buf_index]; -+ buf->state = VIDEOBUF_IDLE; -+ list_del(&buf->stream); -+ } -+ - return 0; - err_einval: - return -EINVAL; -@@ -359,6 +369,8 @@ err_einval: - - /** - * rsz_set_multipass - Set resizer multipass -+ * @multipass: Structure containing channel configuration -+ for multipass support - * @rsz_conf_chan: Structure containing channel configuration - * - * Returns always 0 -@@ -384,6 +396,8 @@ static int rsz_set_multipass(struct rsz_mult *multipass, - - /** - * rsz_copy_data - Copy data -+ * @multipass: Structure containing channel configuration -+ for multipass support - * @params: Structure containing the Resizer Wrapper parameters - * - * Copy data -@@ -413,6 +427,8 @@ static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params) - - /** - * rsz_set_params - Set parameters for resizer wrapper -+ * @multipass: Structure containing channel configuration -+ for multipass support - * @params: Structure containing the Resizer Wrapper parameters - * @rsz_conf_chan: Structure containing channel configuration - * -@@ -524,6 +540,8 @@ static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params, - } - - rsz_config_ratio(multipass, rsz_conf_chan); -+ /* Default value for read expand:Taken from Davinci */ -+ rsz_conf_chan->register_config.sdr_req_exp = RSZ_DEF_REQ_EXP; - - rsz_conf_chan->config_state = STATE_CONFIGURED; - -@@ -534,6 +552,8 @@ err_einval: - - /** - * rsz_set_ratio - Set ratio -+ * @multipass: Structure containing channel configuration -+ for multipass support - * @rsz_conf_chan: Structure containing channel configuration - * - * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is -@@ -548,7 +568,8 @@ static int rsz_set_ratio(struct rsz_mult *multipass, - - if ((multipass->out_hsize > MAX_IMAGE_WIDTH) || - (multipass->out_vsize > MAX_IMAGE_WIDTH)) { -- dev_err(rsz_device, "Invalid output size!"); -+ dev_err(rsz_device, "Invalid output size! - %d", \ -+ multipass->out_hsize); - goto err_einval; - } - if (multipass->cbilin) { -@@ -758,6 +779,8 @@ err_einval: - - /** - * rsz_config_ratio - Configure ratio -+ * @multipass: Structure containing channel configuration -+ for multipass support - * @rsz_conf_chan: Structure containing channel configuration - * - * Configure ratio -@@ -789,6 +812,20 @@ static void rsz_config_ratio(struct rsz_mult *multipass, - ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT) - & ISPRSZ_IN_SIZE_VERT_MASK); - -+ /* This is another workaround for the ISP-MMU translation fault. -+ For the parameters whose image size comes exactly to PAGE_SIZE -+ generates ISP-MMU translation fault. The root-cause is the equation -+ input width = (32*sph + (ow - 1)*hrsz + 16) >> 8 + 7 -+ = (64*sph + (ow - 1)*hrsz + 32) >> 8 + 7 -+ input height = (32*spv + (oh - 1)*vrsz + 16) >> 8 + 4 -+ = (64*spv + (oh - 1)*vrsz + 32) >> 8 + 7 -+ -+ we are adjusting the input width to suit for Resizer module, -+ application should use this configuration henceforth. -+ */ -+ multipass->in_hsize = hsize; -+ multipass->in_vsize = vsize; -+ - for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER; - coeffcounter++) { - if (multipass->num_htap) { -@@ -990,24 +1027,15 @@ static void rsz_calculate_crop(struct channel_config *rsz_conf_chan, - static void rsz_vbq_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) - { -- int i; - struct rsz_fh *fh = q->priv_data; -+ struct videobuf_dmabuf *dma = NULL; - -- for (i = 0; i < VIDEO_MAX_FRAME; i++) { -- struct videobuf_dmabuf *dma = NULL; -- if (!q->bufs[i]) -- continue; -- if (q->bufs[i]->memory != V4L2_MEMORY_MMAP) -- continue; -- dma = videobuf_to_dma(q->bufs[i]); -- videobuf_dma_unmap(q, dma); -- videobuf_dma_free(dma); -- } -+ dma = videobuf_to_dma(q->bufs[vb->i]); -+ videobuf_dma_unmap(q, dma); -+ videobuf_dma_free(dma); -+ ispmmu_vunmap(fh->config->buf_address[vb->i]); -+ fh->config->buf_address[vb->i] = 0; - -- ispmmu_vunmap(fh->isp_addr_read); -- ispmmu_vunmap(fh->isp_addr_write); -- fh->isp_addr_read = 0; -- fh->isp_addr_write = 0; - spin_lock(&fh->vbq_lock); - vb->state = VIDEOBUF_NEEDS_INIT; - spin_unlock(&fh->vbq_lock); -@@ -1062,7 +1090,105 @@ err_einval: - spin_unlock(&fh->vbq_lock); - return -EINVAL; - } -+/* -+ * This function is work around for the videobuf_iolock API, -+ * for User memory allocated with ioremap (VM_IO flag) the API -+ * get_user_pages fails. -+ * -+ * To fulfill this requirement, we have completely ignored VM layer of -+ * Linux, and configuring the ISP MMU with physical address. -+ */ -+static int omap_videobuf_dma_init_user(struct videobuf_buffer *vb, -+ unsigned long physp, unsigned long asize) -+{ -+ struct videobuf_dmabuf *dma; -+ struct scatterlist *sglist; -+ unsigned long data, first, last; -+ int len, i = 0; -+ -+ dma = videobuf_to_dma(vb); -+ data = vb->baddr; -+ -+ first = (data & PAGE_MASK) >> PAGE_SHIFT; -+ last = ((data+asize-1) & PAGE_MASK) >> PAGE_SHIFT; -+ dma->offset = data & ~PAGE_MASK; -+ dma->nr_pages = last-first+1; -+ -+ dma->direction = PCI_DMA_FROMDEVICE; -+ /* -+ * Allocate array of sglen + 1, to add entry of extra page -+ * for input buffer. Driver always uses 0th buffer as input buffer. -+ */ -+ len = dma->nr_pages + (vb->i ? 0 : 1); -+ sglist = kcalloc(len, sizeof(*sglist), GFP_KERNEL); -+ if (NULL == sglist) -+ return -ENOMEM; -+ -+ sglist[0].offset = 0; -+ sglist[0].length = PAGE_SIZE - dma->offset; -+ sglist[0].dma_address = (dma_addr_t)physp; -+ physp += sglist[0].length; -+ /* -+ * Iterate in a loop for the number of pages -+ */ -+ for (i = 1; i < (len - (vb->i ? 0 : 1)); i++) { -+ sglist[i].offset = 0; -+ sglist[i].length = PAGE_SIZE; -+ sglist[i].dma_address = (dma_addr_t)physp; -+ physp += PAGE_SIZE; -+ } -+ if (0 == vb->i) { -+ sglist[i].offset = 0; -+ sglist[i].length = PAGE_SIZE; -+ sglist[i].dma_address = -+ (dma_addr_t)device_config->extra_page_addr; -+ } -+ dma->sglist = sglist; -+ dma->sglen = len; -+ return 0; -+ -+ } -+/* -+ * This function is workaround for the issue, where ISP-MMU generated -+ * translation fault for specific params whose size is aligned to PAGE_SIZE. -+ -+ * As a workaround we are padding one extra page for input buffer. This page -+ * we are allocating during init time and will not be released through-out -+ * life time of resizer driver. Please note that Resizer module only reads -+ * from this extra page. -+ */ -+int omap_create_sg(struct videobuf_queue *q, struct videobuf_dmabuf *dma) -+{ -+ struct scatterlist *sglist; -+ int sglen; - -+ sglen = dma->sglen; -+ sglist = kcalloc(sglen + 1, sizeof(*sglist), GFP_KERNEL); -+ if (NULL == sglist) -+ return -ENOMEM; -+ /* -+ * Copy the sglist locally -+ */ -+ memcpy(sglist, dma->sglist, sglen * sizeof(*sglist)); -+ /* -+ * Release the old sglist, since we already copied it locally -+ */ -+ videobuf_dma_unmap(q, dma); -+ /* -+ * Add extra entry to sglist to work with specific params, whose -+ * buffer address alined to PAGE_SIZE. -+ */ -+ sglist[sglen].offset = 0; -+ sglist[sglen].length = PAGE_SIZE; -+ sglist[sglen].dma_address = (dma_addr_t)device_config->extra_page_addr; -+ sglen++; -+ /* -+ * Save the sglist for mapping to ISP-MMU space -+ */ -+ dma->sglist = sglist; -+ dma->sglen = sglen; -+ return 0; -+} - /** - * rsz_vbq_prepare - Videobuffer is prepared and mmapped. - * @q: Structure containing the videobuffer queue file handle, and device -@@ -1079,19 +1205,24 @@ static int rsz_vbq_prepare(struct videobuf_queue *q, - { - struct rsz_fh *fh = q->priv_data; - struct channel_config *rsz_conf_chan = fh->config; -- struct rsz_mult *multipass = fh->multipass; - int err = 0; - unsigned int isp_addr, insize, outsize; -- struct videobuf_dmabuf *dma = videobuf_to_dma(vb); -- -+ struct rsz_mult *multipass = fh->multipass; - spin_lock(&fh->vbq_lock); - if (vb->baddr) { -+ /* Check for 32 byte alignement */ -+ if (vb->baddr != (vb->baddr & ~0x1F)) { -+ spin_unlock(&fh->vbq_lock); -+ dev_err(rsz_device, "Buffer address should be aligned \ -+ to 32 byte\n"); -+ return -EINVAL; -+ } - vb->size = fh->rsz_bufsize; - vb->bsize = fh->rsz_bufsize; - } else { - spin_unlock(&fh->vbq_lock); - dev_err(rsz_device, "No user buffer allocated\n"); -- goto out; -+ return -EINVAL; - } - if (vb->i) { - vb->width = fh->params->out_hsize; -@@ -1103,55 +1234,128 @@ static int rsz_vbq_prepare(struct videobuf_queue *q, - - vb->field = field; - spin_unlock(&fh->vbq_lock); -+ /* -+ * Calculate input and output sizes, will be used while mapping -+ * user pages -+ */ -+ outsize = multipass->out_pitch * multipass->out_vsize; -+ insize = multipass->in_pitch * multipass->in_vsize; - - if (vb->state == VIDEOBUF_NEEDS_INIT) { -- err = videobuf_iolock(q, vb, NULL); -- if (!err) { -- isp_addr = ispmmu_vmap(dma->sglist, dma->sglen); -- if (!isp_addr) -- err = -EIO; -- else { -- if (vb->i) { -- rsz_conf_chan->register_config. -- rsz_sdr_outadd -- = isp_addr; -- fh->isp_addr_write = isp_addr; -- rsz_conf_chan->output_buf_index = vb->i; -- } else { -+ struct videobuf_dmabuf *dma; -+ struct vm_area_struct *vma; -+ spin_lock(&fh->vbq_lock); -+ dma = videobuf_to_dma(vb); -+ vma = find_vma(current->mm, vb->baddr); -+ if ((vma) && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) { -+ /* This will catch ioremaped buffers to the kernel. -+ * It gives two possible scenarios - -+ * - Driver allocates buffer using either -+ * dma_alloc_coherent or get_free_pages, -+ * and maps to user space using -+ * io_remap_pfn_range/remap_pfn_range -+ * - Drivers maps memory outside from Linux using -+ * io_remap -+ */ -+ unsigned long physp = 0, asize; -+ asize = vb->i ? outsize : insize; -+ if ((vb->baddr + asize) > vma->vm_end) { -+ spin_unlock(&fh->vbq_lock); -+ dev_err(rsz_device, "User Buffer Allocation:" \ -+ "err=%lu[%lu]\n",\ -+ (vma->vm_end - vb->baddr), asize); -+ return -ENOMEM; -+ } -+ physp = (vma->vm_pgoff << PAGE_SHIFT) + -+ (vb->baddr - vma->vm_start); -+ err = omap_videobuf_dma_init_user(vb, physp, asize); -+ spin_unlock(&fh->vbq_lock); -+ if (0 != err) -+ return err; -+ } else { -+ err = videobuf_iolock(q, vb, NULL); -+ /* -+ * In case of user pointer mode, the get_user_pages -+ * will fail if user has allocated less memory than -+ * vb->size. But it is not error from resizer driver -+ * point of view. so handled seperately -+ */ -+ if ((err < 0) && (dma->nr_pages > 0)) -+ err = videobuf_dma_map(q, dma); -+ if (err) -+ goto buf_release; -+ /* -+ * Add one extra page for input buffer -+ */ -+ if (0 == vb->i) -+ err = omap_create_sg(q, dma); -+ if (err) -+ goto buf_release; -+ spin_unlock(&fh->vbq_lock); -+ } -+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen); -+ if (!isp_addr) -+ err = -EIO; -+ else { -+ if (vb->i) { -+ rsz_conf_chan->buf_address[vb->i] = isp_addr; -+ rsz_conf_chan->register_config. -+ rsz_sdr_outadd -+ = isp_addr; -+ rsz_conf_chan->output_buf_index = vb->i; -+ } else { -+ rsz_conf_chan->buf_address[vb->i] = isp_addr; -+ rsz_conf_chan->register_config. -+ rsz_sdr_inadd -+ = isp_addr; -+ rsz_conf_chan->input_buf_index = vb->i; -+ if (outsize < insize && rsz_conf_chan-> -+ register_config. -+ rsz_sdr_outadd == 0) { - rsz_conf_chan->register_config. -- rsz_sdr_inadd -- = isp_addr; -- rsz_conf_chan->input_buf_index = vb->i; -- outsize = multipass->out_pitch * -- multipass->out_vsize; -- insize = multipass->in_pitch * -- multipass->in_vsize; -- if (outsize < insize) { -- rsz_conf_chan->register_config. -- rsz_sdr_outadd -- = isp_addr; -- rsz_conf_chan-> -- output_buf_index = -- vb->i; -- } -- -- fh->isp_addr_read = isp_addr; -+ rsz_sdr_outadd -+ = isp_addr; -+ rsz_conf_chan-> -+ output_buf_index = -+ vb->i; - } - } - } - -- } -+ } else { -+ if(vb->i) { -+ rsz_conf_chan->register_config. -+ rsz_sdr_outadd = -+ rsz_conf_chan->buf_address[vb->i]; -+ rsz_conf_chan->output_buf_index = vb->i; -+ } else { -+ rsz_conf_chan->register_config. -+ rsz_sdr_inadd = -+ rsz_conf_chan->buf_address[vb->i]; -+ rsz_conf_chan->input_buf_index = vb->i; -+ if(outsize < insize && rsz_conf_chan-> -+ register_config. -+ rsz_sdr_outadd == 0) { -+ rsz_conf_chan->register_config. -+ rsz_sdr_outadd -+ = rsz_conf_chan->buf_address[vb->i]; -+ rsz_conf_chan->output_buf_index = vb->i; -+ } -+ -+ } - -+ } - if (!err) { - spin_lock(&fh->vbq_lock); - vb->state = VIDEOBUF_PREPARED; - spin_unlock(&fh->vbq_lock); -- flush_cache_user_range(NULL, vb->baddr, (vb->baddr -- + vb->bsize)); - } else - rsz_vbq_release(q, vb); - --out: -+ return err; -+buf_release: -+ spin_unlock(&fh->vbq_lock); -+ rsz_vbq_release(q, vb); - return err; - } - -@@ -1255,7 +1459,8 @@ err_enomem0: - **/ - static int rsz_release(struct inode *inode, struct file *filp) - { -- u32 timeout = 0; -+ int i; -+ unsigned int timeout = 0; - struct rsz_fh *fh = filp->private_data; - struct channel_config *rsz_conf_chan = fh->config; - struct rsz_params *params = fh->params; -@@ -1266,17 +1471,17 @@ static int rsz_release(struct inode *inode, struct file *filp) - timeout++; - schedule(); - } -- if (mutex_lock_interruptible(&device_config->reszwrap_mutex)) -- return -EINTR; -- device_config->opened--; -- mutex_unlock(&device_config->reszwrap_mutex); -- /* This will Free memory allocated to the buffers, -- * and flushes the queue -- */ -- videobuf_queue_cancel(q); -- fh->params = NULL; -- fh->config = NULL; -+ /* Free memory allocated to the buffers */ -+ for (i = 0 ; i < VIDEO_MAX_FRAME ; i++) { -+ struct videobuf_dmabuf *dma = NULL; -+ if (!q->bufs[i]) -+ continue; -+ dma = videobuf_to_dma(q->bufs[i]); -+ videobuf_dma_unmap(q, dma); -+ videobuf_dma_free(dma); -+ } - -+ videobuf_mmap_free(q); - fh->rsz_bufsize = 0; - filp->private_data = NULL; - -@@ -1286,7 +1491,8 @@ static int rsz_release(struct inode *inode, struct file *filp) - kfree(fh); - - isp_put(); -- -+ fh->params = NULL; -+ fh->config = NULL; - return 0; - } - -@@ -1353,6 +1559,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd, - chanprotection_mutex)) - return -EINTR; - ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf); -+ if (ret >= 0) { -+ if (copy_to_user((struct v4l2_requestbuffers *)arg, -+ &req_buf, sizeof(struct -+ v4l2_requestbuffers))) -+ return -EFAULT; -+ } - mutex_unlock(&rsz_conf_chan->chanprotection_mutex); - break; - } -@@ -1394,11 +1606,7 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd, - sizeof(struct rsz_params))) { - return -EFAULT; - } -- if (mutex_lock_interruptible(&rsz_conf_chan-> -- chanprotection_mutex)) -- return -EINTR; -- ret = rsz_set_params(fh->multipass, params, rsz_conf_chan); -- mutex_unlock(&rsz_conf_chan->chanprotection_mutex); -+ ret = rsz_set_params(fh->multipass, fh->params, rsz_conf_chan); - break; - } - case RSZ_G_PARAM: -@@ -1433,6 +1641,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd, - rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg); - break; - -+ case RSZ_S_EXP: -+ if (mutex_lock_interruptible(&rsz_conf_chan->chanprotection_mutex)) -+ return -EINTR; -+ rsz_conf_chan->register_config.sdr_req_exp = *((unsigned int *)arg); -+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex); -+ break; - default: - dev_err(rsz_device, "resizer_ioctl: Invalid Command Value"); - return -EINVAL; -@@ -1535,14 +1749,18 @@ static int __init omap_rsz_init(void) - "memory\n"); - return -ENOMEM; - } -- -+ device->extra_page_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, 0); -+ if (!device->extra_page_addr) { -+ dev_err(rsz_device, OMAP_REZR_NAME ":Allocation failed. "); -+ kfree(device); -+ return -ENOMEM; -+ } - ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME); - if (ret < 0) { - dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. " - "Could not allocate region " - "for character device\n"); -- kfree(device); -- return -ENODEV; -+ goto fail1; - } - - /* Register the driver in the kernel */ -@@ -1608,6 +1826,8 @@ fail3: - cdev_del(&c_dev); - fail2: - unregister_chrdev_region(dev, 1); -+fail1: -+ free_pages((unsigned long)device->extra_page_addr, 0); - kfree(device); - return ret; - } -@@ -1623,6 +1843,7 @@ void __exit omap_rsz_exit(void) - platform_driver_unregister(&omap_resizer_driver); - cdev_del(&c_dev); - unregister_chrdev_region(dev, 1); -+ free_pages((unsigned long)device_config->extra_page_addr, 0); - kfree(device_config); - } - -diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h -index 5ac0c88..47b8dd8 100644 ---- a/include/linux/omap_resizer.h -+++ b/include/linux/omap_resizer.h -@@ -21,7 +21,7 @@ - - /* ioctls definition */ - #define RSZ_IOC_BASE 'R' --#define RSZ_IOC_MAXNR 8 -+#define RSZ_IOC_MAXNR 9 - - /*Ioctl options which are to be passed while calling the ioctl*/ - #define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\ -@@ -33,6 +33,7 @@ - #define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status) - #define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer) - #define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize) -+#define RSZ_S_EXP _IOWR(RSZ_IOC_BASE, 9, __s32) - - #define RSZ_INTYPE_YCBCR422_16BIT 0 - #define RSZ_INTYPE_PLANAR_8BIT 1 --- -1.6.0.3 - |