summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch
diff options
context:
space:
mode:
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.patch730
1 files changed, 730 insertions, 0 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
new file mode 100644
index 0000000000..631b05f417
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch
@@ -0,0 +1,730 @@
1From 20d79137ecaa6c7dad007d9ea1d7be5550db4839 Mon Sep 17 00:00:00 2001
2From: Vaibhav Hiremath <hvaibhav@ti.com>
3Date: Fri, 13 Feb 2009 15:40:25 +0530
4Subject: [PATCH 2/2] Resizer bug fixes on top of 1.0.2 release
5
6This commit contains resizer bug fixes on top of
7 PSP1.0.2 release -
8 - 4096 aligned address constraint
9 - workaround for extra page allocation for page aligned
10 size buffers
11
12Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
13---
14 drivers/media/video/isp/omap_resizer.c | 417 ++++++++++++++++++++++++--------
15 include/linux/omap_resizer.h | 3 +-
16 2 files changed, 321 insertions(+), 99 deletions(-)
17
18diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
19index 54bc425..8059c70 100644
20--- a/drivers/media/video/isp/omap_resizer.c
21+++ b/drivers/media/video/isp/omap_resizer.c
22@@ -28,6 +28,7 @@
23 #include <linux/platform_device.h>
24 #include <linux/io.h>
25 #include <linux/uaccess.h>
26+#include <linux/pci.h>
27 #include <media/v4l2-dev.h>
28 #include <asm/cacheflush.h>
29
30@@ -76,6 +77,10 @@
31 #define MAX_COEF_COUNTER 16
32 #define COEFF_ADDRESS_OFFSET 0x04
33
34+#define RSZ_DEF_REQ_EXP 0xE /* Default read operation expand
35+ * for the Resizer driver; value
36+ * taken from Davinci.
37+ */
38 /* Global structure which contains information about number of channels
39 and protection variables */
40 struct device_params {
41@@ -85,6 +90,7 @@ struct device_params {
42 struct mutex reszwrap_mutex; /* Semaphore for array */
43
44 struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */
45+ unsigned long extra_page_addr;
46 };
47
48 /* Register mapped structure which contains the every register
49@@ -126,6 +132,9 @@ struct resizer_config {
50 u32 rsz_yehn; /* yehn(luma)register mapping
51 * variable.
52 */
53+ u32 sdr_req_exp; /* Configuration for Non
54+ * real time read expand
55+ */
56 };
57
58 struct rsz_mult {
59@@ -179,6 +188,7 @@ struct channel_config {
60 * channel is busy or not
61 */
62 struct mutex chanprotection_mutex;
63+ int buf_address[VIDEO_MAX_FRAME];
64 enum config_done config_state;
65 u8 input_buf_index;
66 u8 output_buf_index;
67@@ -200,8 +210,6 @@ struct rsz_fh {
68 struct videobuf_queue vbq;
69 struct device_params *device;
70
71- dma_addr_t isp_addr_read; /* Input/Output address */
72- dma_addr_t isp_addr_write; /* Input/Output address */
73 u32 rsz_bufsize; /* channel specific buffersize
74 */
75 };
76@@ -227,6 +235,10 @@ static int rsz_set_ratio(struct rsz_mult *multipass,
77 static void rsz_config_ratio(struct rsz_mult *multipass,
78 struct channel_config *rsz_conf_chan);
79
80+static void inline rsz_set_exp(unsigned int exp)
81+{
82+ omap_writel(((exp & 0x3FF) << 10), OMAP3ISP_SBL_REG(0xF8));
83+}
84 /**
85 * rsz_hardware_setup - Sets hardware configuration registers
86 * @rsz_conf_chan: Structure containing channel configuration
87@@ -271,12 +283,15 @@ static void rsz_hardware_setup(struct channel_config *rsz_conf_chan)
88 + coeffoffset));
89 coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET;
90 }
91+ /* Configure the read expand register */
92+ rsz_set_exp(rsz_conf_chan->register_config.sdr_req_exp);
93 }
94
95 /**
96 * rsz_start - Enables Resizer Wrapper
97 * @arg: Currently not used.
98- * @device: Structure containing ISP resizer wrapper global information
99+ * @fh: File structure containing ISP resizer information specific to
100+ * channel opened.
101 *
102 * Submits a resizing task specified by the rsz_resize structure. The call can
103 * either be blocked until the task is completed or returned immediately based
104@@ -292,12 +307,18 @@ int rsz_start(int *arg, struct rsz_fh *fh)
105 struct channel_config *rsz_conf_chan = fh->config;
106 struct rsz_mult *multipass = fh->multipass;
107 struct videobuf_queue *q = &fh->vbq;
108+ struct videobuf_buffer *buf;
109 int ret;
110
111 if (rsz_conf_chan->config_state) {
112 dev_err(rsz_device, "State not configured \n");
113 goto err_einval;
114 }
115+ if (!rsz_conf_chan->register_config.rsz_sdr_inadd ||
116+ !rsz_conf_chan->register_config.rsz_sdr_outadd) {
117+ dev_err(rsz_device, "address is null\n");
118+ goto err_einval;
119+ }
120
121 rsz_conf_chan->status = CHANNEL_BUSY;
122
123@@ -325,33 +346,22 @@ mult:
124 goto mult;
125 }
126
127- if (fh->isp_addr_read) {
128- ispmmu_vunmap(fh->isp_addr_read);
129- fh->isp_addr_read = 0;
130- }
131- if (fh->isp_addr_write) {
132- ispmmu_vunmap(fh->isp_addr_write);
133- fh->isp_addr_write = 0;
134- }
135-
136 rsz_conf_chan->status = CHANNEL_FREE;
137- q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
138- q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
139 rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
140 rsz_conf_chan->register_config.rsz_sdr_inadd = 0;
141
142- /* Unmap and free the DMA memory allocated for buffers */
143- videobuf_dma_unmap(q, videobuf_to_dma(
144- q->bufs[rsz_conf_chan->input_buf_index]));
145- videobuf_dma_unmap(q, videobuf_to_dma(
146- q->bufs[rsz_conf_chan->output_buf_index]));
147- videobuf_dma_free(videobuf_to_dma(
148- q->bufs[rsz_conf_chan->input_buf_index]));
149- videobuf_dma_free(videobuf_to_dma(
150- q->bufs[rsz_conf_chan->output_buf_index]));
151-
152 isp_unset_callback(CBK_RESZ_DONE);
153
154+ /* Empty the Videobuf queue which was filled during the qbuf */
155+ buf = q->bufs[rsz_conf_chan->input_buf_index];
156+ buf->state = VIDEOBUF_IDLE;
157+ list_del(&buf->stream);
158+ if (rsz_conf_chan->input_buf_index != rsz_conf_chan->output_buf_index) {
159+ buf = q->bufs[rsz_conf_chan->output_buf_index];
160+ buf->state = VIDEOBUF_IDLE;
161+ list_del(&buf->stream);
162+ }
163+
164 return 0;
165 err_einval:
166 return -EINVAL;
167@@ -359,6 +369,8 @@ err_einval:
168
169 /**
170 * rsz_set_multipass - Set resizer multipass
171+ * @multipass: Structure containing channel configuration
172+ for multipass support
173 * @rsz_conf_chan: Structure containing channel configuration
174 *
175 * Returns always 0
176@@ -384,6 +396,8 @@ static int rsz_set_multipass(struct rsz_mult *multipass,
177
178 /**
179 * rsz_copy_data - Copy data
180+ * @multipass: Structure containing channel configuration
181+ for multipass support
182 * @params: Structure containing the Resizer Wrapper parameters
183 *
184 * Copy data
185@@ -413,6 +427,8 @@ static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params)
186
187 /**
188 * rsz_set_params - Set parameters for resizer wrapper
189+ * @multipass: Structure containing channel configuration
190+ for multipass support
191 * @params: Structure containing the Resizer Wrapper parameters
192 * @rsz_conf_chan: Structure containing channel configuration
193 *
194@@ -524,6 +540,8 @@ static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params,
195 }
196
197 rsz_config_ratio(multipass, rsz_conf_chan);
198+ /* Default value for read expand:Taken from Davinci */
199+ rsz_conf_chan->register_config.sdr_req_exp = RSZ_DEF_REQ_EXP;
200
201 rsz_conf_chan->config_state = STATE_CONFIGURED;
202
203@@ -534,6 +552,8 @@ err_einval:
204
205 /**
206 * rsz_set_ratio - Set ratio
207+ * @multipass: Structure containing channel configuration
208+ for multipass support
209 * @rsz_conf_chan: Structure containing channel configuration
210 *
211 * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is
212@@ -548,7 +568,8 @@ static int rsz_set_ratio(struct rsz_mult *multipass,
213
214 if ((multipass->out_hsize > MAX_IMAGE_WIDTH) ||
215 (multipass->out_vsize > MAX_IMAGE_WIDTH)) {
216- dev_err(rsz_device, "Invalid output size!");
217+ dev_err(rsz_device, "Invalid output size! - %d", \
218+ multipass->out_hsize);
219 goto err_einval;
220 }
221 if (multipass->cbilin) {
222@@ -758,6 +779,8 @@ err_einval:
223
224 /**
225 * rsz_config_ratio - Configure ratio
226+ * @multipass: Structure containing channel configuration
227+ for multipass support
228 * @rsz_conf_chan: Structure containing channel configuration
229 *
230 * Configure ratio
231@@ -789,6 +812,20 @@ static void rsz_config_ratio(struct rsz_mult *multipass,
232 ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT)
233 & ISPRSZ_IN_SIZE_VERT_MASK);
234
235+ /* This is another workaround for the ISP-MMU translation fault.
236+ For the parameters whose image size comes exactly to PAGE_SIZE
237+ generates ISP-MMU translation fault. The root-cause is the equation
238+ input width = (32*sph + (ow - 1)*hrsz + 16) >> 8 + 7
239+ = (64*sph + (ow - 1)*hrsz + 32) >> 8 + 7
240+ input height = (32*spv + (oh - 1)*vrsz + 16) >> 8 + 4
241+ = (64*spv + (oh - 1)*vrsz + 32) >> 8 + 7
242+
243+ we are adjusting the input width to suit for Resizer module,
244+ application should use this configuration henceforth.
245+ */
246+ multipass->in_hsize = hsize;
247+ multipass->in_vsize = vsize;
248+
249 for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
250 coeffcounter++) {
251 if (multipass->num_htap) {
252@@ -990,24 +1027,15 @@ static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
253 static void rsz_vbq_release(struct videobuf_queue *q,
254 struct videobuf_buffer *vb)
255 {
256- int i;
257 struct rsz_fh *fh = q->priv_data;
258+ struct videobuf_dmabuf *dma = NULL;
259
260- for (i = 0; i < VIDEO_MAX_FRAME; i++) {
261- struct videobuf_dmabuf *dma = NULL;
262- if (!q->bufs[i])
263- continue;
264- if (q->bufs[i]->memory != V4L2_MEMORY_MMAP)
265- continue;
266- dma = videobuf_to_dma(q->bufs[i]);
267- videobuf_dma_unmap(q, dma);
268- videobuf_dma_free(dma);
269- }
270+ dma = videobuf_to_dma(q->bufs[vb->i]);
271+ videobuf_dma_unmap(q, dma);
272+ videobuf_dma_free(dma);
273+ ispmmu_vunmap(fh->config->buf_address[vb->i]);
274+ fh->config->buf_address[vb->i] = 0;
275
276- ispmmu_vunmap(fh->isp_addr_read);
277- ispmmu_vunmap(fh->isp_addr_write);
278- fh->isp_addr_read = 0;
279- fh->isp_addr_write = 0;
280 spin_lock(&fh->vbq_lock);
281 vb->state = VIDEOBUF_NEEDS_INIT;
282 spin_unlock(&fh->vbq_lock);
283@@ -1062,7 +1090,105 @@ err_einval:
284 spin_unlock(&fh->vbq_lock);
285 return -EINVAL;
286 }
287+/*
288+ * This function is work around for the videobuf_iolock API,
289+ * for User memory allocated with ioremap (VM_IO flag) the API
290+ * get_user_pages fails.
291+ *
292+ * To fulfill this requirement, we have completely ignored VM layer of
293+ * Linux, and configuring the ISP MMU with physical address.
294+ */
295+static int omap_videobuf_dma_init_user(struct videobuf_buffer *vb,
296+ unsigned long physp, unsigned long asize)
297+{
298+ struct videobuf_dmabuf *dma;
299+ struct scatterlist *sglist;
300+ unsigned long data, first, last;
301+ int len, i = 0;
302+
303+ dma = videobuf_to_dma(vb);
304+ data = vb->baddr;
305+
306+ first = (data & PAGE_MASK) >> PAGE_SHIFT;
307+ last = ((data+asize-1) & PAGE_MASK) >> PAGE_SHIFT;
308+ dma->offset = data & ~PAGE_MASK;
309+ dma->nr_pages = last-first+1;
310+
311+ dma->direction = PCI_DMA_FROMDEVICE;
312+ /*
313+ * Allocate array of sglen + 1, to add entry of extra page
314+ * for input buffer. Driver always uses 0th buffer as input buffer.
315+ */
316+ len = dma->nr_pages + (vb->i ? 0 : 1);
317+ sglist = kcalloc(len, sizeof(*sglist), GFP_KERNEL);
318+ if (NULL == sglist)
319+ return -ENOMEM;
320+
321+ sglist[0].offset = 0;
322+ sglist[0].length = PAGE_SIZE - dma->offset;
323+ sglist[0].dma_address = (dma_addr_t)physp;
324+ physp += sglist[0].length;
325+ /*
326+ * Iterate in a loop for the number of pages
327+ */
328+ for (i = 1; i < (len - (vb->i ? 0 : 1)); i++) {
329+ sglist[i].offset = 0;
330+ sglist[i].length = PAGE_SIZE;
331+ sglist[i].dma_address = (dma_addr_t)physp;
332+ physp += PAGE_SIZE;
333+ }
334+ if (0 == vb->i) {
335+ sglist[i].offset = 0;
336+ sglist[i].length = PAGE_SIZE;
337+ sglist[i].dma_address =
338+ (dma_addr_t)device_config->extra_page_addr;
339+ }
340+ dma->sglist = sglist;
341+ dma->sglen = len;
342+ return 0;
343+
344+ }
345+/*
346+ * This function is workaround for the issue, where ISP-MMU generated
347+ * translation fault for specific params whose size is aligned to PAGE_SIZE.
348+
349+ * As a workaround we are padding one extra page for input buffer. This page
350+ * we are allocating during init time and will not be released through-out
351+ * life time of resizer driver. Please note that Resizer module only reads
352+ * from this extra page.
353+ */
354+int omap_create_sg(struct videobuf_queue *q, struct videobuf_dmabuf *dma)
355+{
356+ struct scatterlist *sglist;
357+ int sglen;
358
359+ sglen = dma->sglen;
360+ sglist = kcalloc(sglen + 1, sizeof(*sglist), GFP_KERNEL);
361+ if (NULL == sglist)
362+ return -ENOMEM;
363+ /*
364+ * Copy the sglist locally
365+ */
366+ memcpy(sglist, dma->sglist, sglen * sizeof(*sglist));
367+ /*
368+ * Release the old sglist, since we already copied it locally
369+ */
370+ videobuf_dma_unmap(q, dma);
371+ /*
372+ * Add extra entry to sglist to work with specific params, whose
373+ * buffer address alined to PAGE_SIZE.
374+ */
375+ sglist[sglen].offset = 0;
376+ sglist[sglen].length = PAGE_SIZE;
377+ sglist[sglen].dma_address = (dma_addr_t)device_config->extra_page_addr;
378+ sglen++;
379+ /*
380+ * Save the sglist for mapping to ISP-MMU space
381+ */
382+ dma->sglist = sglist;
383+ dma->sglen = sglen;
384+ return 0;
385+}
386 /**
387 * rsz_vbq_prepare - Videobuffer is prepared and mmapped.
388 * @q: Structure containing the videobuffer queue file handle, and device
389@@ -1079,19 +1205,24 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
390 {
391 struct rsz_fh *fh = q->priv_data;
392 struct channel_config *rsz_conf_chan = fh->config;
393- struct rsz_mult *multipass = fh->multipass;
394 int err = 0;
395 unsigned int isp_addr, insize, outsize;
396- struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
397-
398+ struct rsz_mult *multipass = fh->multipass;
399 spin_lock(&fh->vbq_lock);
400 if (vb->baddr) {
401+ /* Check for 32 byte alignement */
402+ if (vb->baddr != (vb->baddr & ~0x1F)) {
403+ spin_unlock(&fh->vbq_lock);
404+ dev_err(rsz_device, "Buffer address should be aligned \
405+ to 32 byte\n");
406+ return -EINVAL;
407+ }
408 vb->size = fh->rsz_bufsize;
409 vb->bsize = fh->rsz_bufsize;
410 } else {
411 spin_unlock(&fh->vbq_lock);
412 dev_err(rsz_device, "No user buffer allocated\n");
413- goto out;
414+ return -EINVAL;
415 }
416 if (vb->i) {
417 vb->width = fh->params->out_hsize;
418@@ -1103,55 +1234,128 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
419
420 vb->field = field;
421 spin_unlock(&fh->vbq_lock);
422+ /*
423+ * Calculate input and output sizes, will be used while mapping
424+ * user pages
425+ */
426+ outsize = multipass->out_pitch * multipass->out_vsize;
427+ insize = multipass->in_pitch * multipass->in_vsize;
428
429 if (vb->state == VIDEOBUF_NEEDS_INIT) {
430- err = videobuf_iolock(q, vb, NULL);
431- if (!err) {
432- isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
433- if (!isp_addr)
434- err = -EIO;
435- else {
436- if (vb->i) {
437- rsz_conf_chan->register_config.
438- rsz_sdr_outadd
439- = isp_addr;
440- fh->isp_addr_write = isp_addr;
441- rsz_conf_chan->output_buf_index = vb->i;
442- } else {
443+ struct videobuf_dmabuf *dma;
444+ struct vm_area_struct *vma;
445+ spin_lock(&fh->vbq_lock);
446+ dma = videobuf_to_dma(vb);
447+ vma = find_vma(current->mm, vb->baddr);
448+ if ((vma) && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) {
449+ /* This will catch ioremaped buffers to the kernel.
450+ * It gives two possible scenarios -
451+ * - Driver allocates buffer using either
452+ * dma_alloc_coherent or get_free_pages,
453+ * and maps to user space using
454+ * io_remap_pfn_range/remap_pfn_range
455+ * - Drivers maps memory outside from Linux using
456+ * io_remap
457+ */
458+ unsigned long physp = 0, asize;
459+ asize = vb->i ? outsize : insize;
460+ if ((vb->baddr + asize) > vma->vm_end) {
461+ spin_unlock(&fh->vbq_lock);
462+ dev_err(rsz_device, "User Buffer Allocation:" \
463+ "err=%lu[%lu]\n",\
464+ (vma->vm_end - vb->baddr), asize);
465+ return -ENOMEM;
466+ }
467+ physp = (vma->vm_pgoff << PAGE_SHIFT) +
468+ (vb->baddr - vma->vm_start);
469+ err = omap_videobuf_dma_init_user(vb, physp, asize);
470+ spin_unlock(&fh->vbq_lock);
471+ if (0 != err)
472+ return err;
473+ } else {
474+ err = videobuf_iolock(q, vb, NULL);
475+ /*
476+ * In case of user pointer mode, the get_user_pages
477+ * will fail if user has allocated less memory than
478+ * vb->size. But it is not error from resizer driver
479+ * point of view. so handled seperately
480+ */
481+ if ((err < 0) && (dma->nr_pages > 0))
482+ err = videobuf_dma_map(q, dma);
483+ if (err)
484+ goto buf_release;
485+ /*
486+ * Add one extra page for input buffer
487+ */
488+ if (0 == vb->i)
489+ err = omap_create_sg(q, dma);
490+ if (err)
491+ goto buf_release;
492+ spin_unlock(&fh->vbq_lock);
493+ }
494+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
495+ if (!isp_addr)
496+ err = -EIO;
497+ else {
498+ if (vb->i) {
499+ rsz_conf_chan->buf_address[vb->i] = isp_addr;
500+ rsz_conf_chan->register_config.
501+ rsz_sdr_outadd
502+ = isp_addr;
503+ rsz_conf_chan->output_buf_index = vb->i;
504+ } else {
505+ rsz_conf_chan->buf_address[vb->i] = isp_addr;
506+ rsz_conf_chan->register_config.
507+ rsz_sdr_inadd
508+ = isp_addr;
509+ rsz_conf_chan->input_buf_index = vb->i;
510+ if (outsize < insize && rsz_conf_chan->
511+ register_config.
512+ rsz_sdr_outadd == 0) {
513 rsz_conf_chan->register_config.
514- rsz_sdr_inadd
515- = isp_addr;
516- rsz_conf_chan->input_buf_index = vb->i;
517- outsize = multipass->out_pitch *
518- multipass->out_vsize;
519- insize = multipass->in_pitch *
520- multipass->in_vsize;
521- if (outsize < insize) {
522- rsz_conf_chan->register_config.
523- rsz_sdr_outadd
524- = isp_addr;
525- rsz_conf_chan->
526- output_buf_index =
527- vb->i;
528- }
529-
530- fh->isp_addr_read = isp_addr;
531+ rsz_sdr_outadd
532+ = isp_addr;
533+ rsz_conf_chan->
534+ output_buf_index =
535+ vb->i;
536 }
537 }
538 }
539
540- }
541+ } else {
542+ if(vb->i) {
543+ rsz_conf_chan->register_config.
544+ rsz_sdr_outadd =
545+ rsz_conf_chan->buf_address[vb->i];
546+ rsz_conf_chan->output_buf_index = vb->i;
547+ } else {
548+ rsz_conf_chan->register_config.
549+ rsz_sdr_inadd =
550+ rsz_conf_chan->buf_address[vb->i];
551+ rsz_conf_chan->input_buf_index = vb->i;
552+ if(outsize < insize && rsz_conf_chan->
553+ register_config.
554+ rsz_sdr_outadd == 0) {
555+ rsz_conf_chan->register_config.
556+ rsz_sdr_outadd
557+ = rsz_conf_chan->buf_address[vb->i];
558+ rsz_conf_chan->output_buf_index = vb->i;
559+ }
560+
561+ }
562
563+ }
564 if (!err) {
565 spin_lock(&fh->vbq_lock);
566 vb->state = VIDEOBUF_PREPARED;
567 spin_unlock(&fh->vbq_lock);
568- flush_cache_user_range(NULL, vb->baddr, (vb->baddr
569- + vb->bsize));
570 } else
571 rsz_vbq_release(q, vb);
572
573-out:
574+ return err;
575+buf_release:
576+ spin_unlock(&fh->vbq_lock);
577+ rsz_vbq_release(q, vb);
578 return err;
579 }
580
581@@ -1255,7 +1459,8 @@ err_enomem0:
582 **/
583 static int rsz_release(struct inode *inode, struct file *filp)
584 {
585- u32 timeout = 0;
586+ int i;
587+ unsigned int timeout = 0;
588 struct rsz_fh *fh = filp->private_data;
589 struct channel_config *rsz_conf_chan = fh->config;
590 struct rsz_params *params = fh->params;
591@@ -1266,17 +1471,17 @@ static int rsz_release(struct inode *inode, struct file *filp)
592 timeout++;
593 schedule();
594 }
595- if (mutex_lock_interruptible(&device_config->reszwrap_mutex))
596- return -EINTR;
597- device_config->opened--;
598- mutex_unlock(&device_config->reszwrap_mutex);
599- /* This will Free memory allocated to the buffers,
600- * and flushes the queue
601- */
602- videobuf_queue_cancel(q);
603- fh->params = NULL;
604- fh->config = NULL;
605+ /* Free memory allocated to the buffers */
606+ for (i = 0 ; i < VIDEO_MAX_FRAME ; i++) {
607+ struct videobuf_dmabuf *dma = NULL;
608+ if (!q->bufs[i])
609+ continue;
610+ dma = videobuf_to_dma(q->bufs[i]);
611+ videobuf_dma_unmap(q, dma);
612+ videobuf_dma_free(dma);
613+ }
614
615+ videobuf_mmap_free(q);
616 fh->rsz_bufsize = 0;
617 filp->private_data = NULL;
618
619@@ -1286,7 +1491,8 @@ static int rsz_release(struct inode *inode, struct file *filp)
620 kfree(fh);
621
622 isp_put();
623-
624+ fh->params = NULL;
625+ fh->config = NULL;
626 return 0;
627 }
628
629@@ -1353,6 +1559,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
630 chanprotection_mutex))
631 return -EINTR;
632 ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf);
633+ if (ret >= 0) {
634+ if (copy_to_user((struct v4l2_requestbuffers *)arg,
635+ &req_buf, sizeof(struct
636+ v4l2_requestbuffers)))
637+ return -EFAULT;
638+ }
639 mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
640 break;
641 }
642@@ -1394,11 +1606,7 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
643 sizeof(struct rsz_params))) {
644 return -EFAULT;
645 }
646- if (mutex_lock_interruptible(&rsz_conf_chan->
647- chanprotection_mutex))
648- return -EINTR;
649- ret = rsz_set_params(fh->multipass, params, rsz_conf_chan);
650- mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
651+ ret = rsz_set_params(fh->multipass, fh->params, rsz_conf_chan);
652 break;
653 }
654 case RSZ_G_PARAM:
655@@ -1433,6 +1641,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
656 rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg);
657 break;
658
659+ case RSZ_S_EXP:
660+ if (mutex_lock_interruptible(&rsz_conf_chan->chanprotection_mutex))
661+ return -EINTR;
662+ rsz_conf_chan->register_config.sdr_req_exp = *((unsigned int *)arg);
663+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
664+ break;
665 default:
666 dev_err(rsz_device, "resizer_ioctl: Invalid Command Value");
667 return -EINVAL;
668@@ -1535,14 +1749,18 @@ static int __init omap_rsz_init(void)
669 "memory\n");
670 return -ENOMEM;
671 }
672-
673+ device->extra_page_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, 0);
674+ if (!device->extra_page_addr) {
675+ dev_err(rsz_device, OMAP_REZR_NAME ":Allocation failed. ");
676+ kfree(device);
677+ return -ENOMEM;
678+ }
679 ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME);
680 if (ret < 0) {
681 dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. "
682 "Could not allocate region "
683 "for character device\n");
684- kfree(device);
685- return -ENODEV;
686+ goto fail1;
687 }
688
689 /* Register the driver in the kernel */
690@@ -1608,6 +1826,8 @@ fail3:
691 cdev_del(&c_dev);
692 fail2:
693 unregister_chrdev_region(dev, 1);
694+fail1:
695+ free_pages((unsigned long)device->extra_page_addr, 0);
696 kfree(device);
697 return ret;
698 }
699@@ -1623,6 +1843,7 @@ void __exit omap_rsz_exit(void)
700 platform_driver_unregister(&omap_resizer_driver);
701 cdev_del(&c_dev);
702 unregister_chrdev_region(dev, 1);
703+ free_pages((unsigned long)device_config->extra_page_addr, 0);
704 kfree(device_config);
705 }
706
707diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h
708index 5ac0c88..47b8dd8 100644
709--- a/include/linux/omap_resizer.h
710+++ b/include/linux/omap_resizer.h
711@@ -21,7 +21,7 @@
712
713 /* ioctls definition */
714 #define RSZ_IOC_BASE 'R'
715-#define RSZ_IOC_MAXNR 8
716+#define RSZ_IOC_MAXNR 9
717
718 /*Ioctl options which are to be passed while calling the ioctl*/
719 #define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\
720@@ -33,6 +33,7 @@
721 #define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status)
722 #define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer)
723 #define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize)
724+#define RSZ_S_EXP _IOWR(RSZ_IOC_BASE, 9, __s32)
725
726 #define RSZ_INTYPE_YCBCR422_16BIT 0
727 #define RSZ_INTYPE_PLANAR_8BIT 1
728--
7291.6.0.3
730