From 20d79137ecaa6c7dad007d9ea1d7be5550db4839 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath 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 --- 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 #include #include +#include #include #include @@ -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