diff options
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch')
-rw-r--r-- | meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch | 2915 |
1 files changed, 2915 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch new file mode 100644 index 0000000000..f796ce8346 --- /dev/null +++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch | |||
@@ -0,0 +1,2915 @@ | |||
1 | From 3041daa54b49bcb6ab444c7b9e14bc6a1ade6236 Mon Sep 17 00:00:00 2001 | ||
2 | From: Vaibhav Hiremath <hvaibhav@ti.com> | ||
3 | Date: Fri, 13 Feb 2009 14:44:20 +0530 | ||
4 | Subject: [PATCH 1/2] Resizer and Previewer driver added to commit | ||
5 | |||
6 | The Resizer and Previewer driver added to the commit | ||
7 | from the patch submitted by Sergio on 12 Dec 2008. | ||
8 | |||
9 | The new WTBU code base and Nokia fixes package doesn't contain | ||
10 | standalone resizer driver support. | ||
11 | |||
12 | Following major changes done - | ||
13 | |||
14 | - Added stand-alone resizer driver support | ||
15 | in isp.c file. | ||
16 | - Seperate Kconfig file created | ||
17 | - hardware access of resizer module fixed as per new | ||
18 | isp.c | ||
19 | |||
20 | Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com> | ||
21 | --- | ||
22 | drivers/media/video/Kconfig | 5 +- | ||
23 | drivers/media/video/isp/Kconfig | 16 + | ||
24 | drivers/media/video/isp/Makefile | 7 + | ||
25 | drivers/media/video/isp/isp.c | 12 + | ||
26 | drivers/media/video/isp/ispmmu.c | 1 + | ||
27 | drivers/media/video/isp/omap_previewer.c | 825 +++++++++++++++ | ||
28 | drivers/media/video/isp/omap_previewer.h | 162 +++ | ||
29 | drivers/media/video/isp/omap_resizer.c | 1634 ++++++++++++++++++++++++++++++ | ||
30 | include/linux/omap_resizer.h | 136 +++ | ||
31 | 9 files changed, 2794 insertions(+), 4 deletions(-) | ||
32 | create mode 100644 drivers/media/video/isp/Kconfig | ||
33 | create mode 100644 drivers/media/video/isp/omap_previewer.c | ||
34 | create mode 100644 drivers/media/video/isp/omap_previewer.h | ||
35 | create mode 100644 drivers/media/video/isp/omap_resizer.c | ||
36 | create mode 100644 include/linux/omap_resizer.h | ||
37 | |||
38 | diff --git a/drivers/media/video/isp/Kconfig b/drivers/media/video/isp/Kconfig | ||
39 | new file mode 100644 | ||
40 | index 0000000..acda63b | ||
41 | --- /dev/null | ||
42 | +++ b/drivers/media/video/isp/Kconfig | ||
43 | @@ -0,0 +1,16 @@ | ||
44 | +# Kconfig for OMAP3 ISP driver | ||
45 | + | ||
46 | +config VIDEO_OMAP3_ISP | ||
47 | + tristate | ||
48 | + select VIDEOBUF_GEN | ||
49 | + select VIDEOBUF_DMA_SG | ||
50 | + | ||
51 | +config VIDEO_OMAP34XX_ISP_PREVIEWER | ||
52 | + tristate "OMAP ISP Previewer" | ||
53 | + depends on !ARCH_OMAP3410 | ||
54 | + select VIDEO_OMAP3_ISP | ||
55 | + | ||
56 | +config VIDEO_OMAP34XX_ISP_RESIZER | ||
57 | + tristate "OMAP ISP Resizer" | ||
58 | + depends on !ARCH_OMAP3410 | ||
59 | + select VIDEO_OMAP3_ISP | ||
60 | diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile | ||
61 | index 0f9301c..ed10a51 100644 | ||
62 | --- a/drivers/media/video/isp/Makefile | ||
63 | +++ b/drivers/media/video/isp/Makefile | ||
64 | @@ -7,6 +7,13 @@ else | ||
65 | isp-mod-objs += \ | ||
66 | isp.o ispccdc.o ispmmu.o \ | ||
67 | isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o | ||
68 | + | ||
69 | +obj-$(CONFIG_VIDEO_OMAP34XX_ISP_PREVIEWER) += \ | ||
70 | + omap_previewer.o | ||
71 | + | ||
72 | +obj-$(CONFIG_VIDEO_OMAP34XX_ISP_RESIZER) += \ | ||
73 | + omap_resizer.o | ||
74 | + | ||
75 | endif | ||
76 | |||
77 | obj-$(CONFIG_VIDEO_OMAP3_ISP) += isp-mod.o | ||
78 | diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c | ||
79 | index 6034a56..09a1792 100644 | ||
80 | --- a/drivers/media/video/isp/isp.c | ||
81 | +++ b/drivers/media/video/isp/isp.c | ||
82 | @@ -521,6 +521,13 @@ int isp_set_callback(enum isp_callback_type type, isp_callback_t callback, | ||
83 | OMAP3_ISP_IOMEM_MAIN, | ||
84 | ISP_IRQ0ENABLE); | ||
85 | break; | ||
86 | + case CBK_RESZ_DONE: | ||
87 | + isp_reg_writel(IRQ0ENABLE_RSZ_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN, | ||
88 | + ISP_IRQ0STATUS); | ||
89 | + isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE) | | ||
90 | + IRQ0ENABLE_RSZ_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN, | ||
91 | + ISP_IRQ0ENABLE); | ||
92 | + break; | ||
93 | default: | ||
94 | break; | ||
95 | } | ||
96 | @@ -996,6 +1003,11 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_isp) | ||
97 | if (!ispresizer_busy()) | ||
98 | ispresizer_config_shadow_registers(); | ||
99 | isp_buf_process(bufs); | ||
100 | + } else { | ||
101 | + if (irqdis->isp_callbk[CBK_RESZ_DONE]) | ||
102 | + irqdis->isp_callbk[CBK_RESZ_DONE](RESZ_DONE, | ||
103 | + irqdis->isp_callbk_arg1[CBK_RESZ_DONE], | ||
104 | + irqdis->isp_callbk_arg2[CBK_RESZ_DONE]); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | diff --git a/drivers/media/video/isp/ispmmu.c b/drivers/media/video/isp/ispmmu.c | ||
109 | index 076aea1..b943d5b 100644 | ||
110 | --- a/drivers/media/video/isp/ispmmu.c | ||
111 | +++ b/drivers/media/video/isp/ispmmu.c | ||
112 | @@ -289,6 +289,7 @@ int ispmmu_get_mapeable_space(void) | ||
113 | return (L2P_TABLE_NR - no_of_l2p_alloted) * ISPMMU_TTB_ENTRIES_NR * | ||
114 | ISPMMU_L2D_ENTRIES_NR; | ||
115 | } | ||
116 | +EXPORT_SYMBOL_GPL(ispmmu_get_mapeable_space); | ||
117 | |||
118 | /** | ||
119 | * ispmmu_map - Map a physically contiguous buffer to ISP space. | ||
120 | diff --git a/drivers/media/video/isp/omap_previewer.c b/drivers/media/video/isp/omap_previewer.c | ||
121 | new file mode 100644 | ||
122 | index 0000000..634a056 | ||
123 | --- /dev/null | ||
124 | +++ b/drivers/media/video/isp/omap_previewer.c | ||
125 | @@ -0,0 +1,825 @@ | ||
126 | +/* | ||
127 | + * drivers/media/video/isp/omap_previewer.c | ||
128 | + * | ||
129 | + * Wrapper for Preview module in TI's OMAP3430 ISP | ||
130 | + * | ||
131 | + * Copyright (C) 2008 Texas Instruments, Inc. | ||
132 | + * | ||
133 | + * Contributors: | ||
134 | + * Leonides Martinez <leonides.martinez@ti.com> | ||
135 | + * Sergio Aguirre <saaguirre@ti.com> | ||
136 | + * | ||
137 | + * This package is free software; you can redistribute it and/or modify | ||
138 | + * it under the terms of the GNU General Public License version 2 as | ||
139 | + * published by the Free Software Foundation. | ||
140 | + * | ||
141 | + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | ||
142 | + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
143 | + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
144 | + */ | ||
145 | + | ||
146 | +#include <linux/mutex.h> | ||
147 | +#include <linux/cdev.h> | ||
148 | +#include <linux/device.h> | ||
149 | +#include <linux/delay.h> | ||
150 | +#include <linux/fs.h> | ||
151 | +#include <linux/mm.h> | ||
152 | +#include <linux/module.h> | ||
153 | +#include <linux/platform_device.h> | ||
154 | +#include <linux/uaccess.h> | ||
155 | +#include <linux/io.h> | ||
156 | +#include <media/v4l2-dev.h> | ||
157 | +#include <asm/cacheflush.h> | ||
158 | + | ||
159 | +#include "isp.h" | ||
160 | +#include "ispmmu.h" | ||
161 | +#include "ispreg.h" | ||
162 | +#include "omap_previewer.h" | ||
163 | + | ||
164 | +#define OMAP_PREV_NAME "omap-previewer" | ||
165 | + | ||
166 | +static int prev_major = -1; | ||
167 | +static struct device *prev_dev; | ||
168 | +static struct class *prev_class; | ||
169 | +static struct prev_device *prevdevice; | ||
170 | +static struct platform_driver omap_previewer_driver; | ||
171 | + | ||
172 | +static u32 prev_bufsize; | ||
173 | + | ||
174 | +/** | ||
175 | + * prev_calculate_crop - Calculate crop size according to device parameters | ||
176 | + * @device: Structure containing ISP preview wrapper global information | ||
177 | + * @crop: Structure containing crop size | ||
178 | + * | ||
179 | + * This function is used to calculate frame size reduction depending on | ||
180 | + * the features enabled by the application. | ||
181 | + **/ | ||
182 | +static void prev_calculate_crop(struct prev_device *device, | ||
183 | + struct prev_cropsize *crop) | ||
184 | +{ | ||
185 | + dev_dbg(prev_dev, "prev_calculate_crop E\n"); | ||
186 | + | ||
187 | + if (!device || !crop) { | ||
188 | + dev_err(prev_dev, "\nErron in argument"); | ||
189 | + return; | ||
190 | + } | ||
191 | + | ||
192 | + isppreview_try_size(device->params->size_params.hsize, | ||
193 | + device->params->size_params.vsize, | ||
194 | + &crop->hcrop, &crop->vcrop); | ||
195 | + crop->hcrop &= PREV_16PIX_ALIGN_MASK; | ||
196 | + dev_dbg(prev_dev, "prev_calculate_crop L\n"); | ||
197 | +} | ||
198 | + | ||
199 | +/** | ||
200 | + * prev_get_status - Get status of ISP preview module | ||
201 | + * @status: Structure containing the busy state. | ||
202 | + * | ||
203 | + * Checks if the ISP preview module is busy. | ||
204 | + * | ||
205 | + * Returns 0 if successful, or -EINVAL if the status parameter is invalid. | ||
206 | + **/ | ||
207 | +static int prev_get_status(struct prev_status *status) | ||
208 | +{ | ||
209 | + if (!status) { | ||
210 | + dev_err(prev_dev, "get_status: invalid parameter\n"); | ||
211 | + return -EINVAL; | ||
212 | + } | ||
213 | + status->hw_busy = (char)isppreview_busy(); | ||
214 | + return 0; | ||
215 | +} | ||
216 | + | ||
217 | +/** | ||
218 | + * prev_hw_setup - Stores the desired configuration in the proper HW registers | ||
219 | + * @config: Structure containing the desired configuration for ISP preview | ||
220 | + * module. | ||
221 | + * | ||
222 | + * Reads the structure sent, and modifies the desired registers. | ||
223 | + * | ||
224 | + * Always returns 0. | ||
225 | + **/ | ||
226 | +static int prev_hw_setup(struct prev_params *config) | ||
227 | +{ | ||
228 | + dev_dbg(prev_dev, "prev_hw_setup E\n"); | ||
229 | + | ||
230 | + if (config->features & PREV_AVERAGER) | ||
231 | + isppreview_config_averager(config->average); | ||
232 | + else | ||
233 | + isppreview_config_averager(0); | ||
234 | + | ||
235 | + if (config->features & PREV_INVERSE_ALAW) | ||
236 | + isppreview_enable_invalaw(1); | ||
237 | + else | ||
238 | + isppreview_enable_invalaw(0); | ||
239 | + | ||
240 | + if (config->features & PREV_HORZ_MEDIAN_FILTER) { | ||
241 | + isppreview_config_hmed(config->hmf_params); | ||
242 | + isppreview_enable_hmed(1); | ||
243 | + } else | ||
244 | + isppreview_enable_hmed(0); | ||
245 | + | ||
246 | + if (config->features & PREV_DARK_FRAME_SUBTRACT) { | ||
247 | + isppreview_set_darkaddr(config->drkf_params.addr); | ||
248 | + isppreview_config_darklineoffset(config->drkf_params.offset); | ||
249 | + isppreview_enable_drkframe(1); | ||
250 | + } else | ||
251 | + isppreview_enable_drkframe(0); | ||
252 | + | ||
253 | + if (config->features & PREV_LENS_SHADING) { | ||
254 | + isppreview_config_drkf_shadcomp(config->lens_shading_shift); | ||
255 | + isppreview_enable_shadcomp(1); | ||
256 | + } else | ||
257 | + isppreview_enable_shadcomp(0); | ||
258 | + | ||
259 | + dev_dbg(prev_dev, "prev_hw_setup L\n"); | ||
260 | + return 0; | ||
261 | +} | ||
262 | + | ||
263 | +/** | ||
264 | + * prev_validate_params - Validate configuration parameters for Preview Wrapper | ||
265 | + * @params: Structure containing configuration parameters | ||
266 | + * | ||
267 | + * Validate configuration parameters for Preview Wrapper | ||
268 | + * | ||
269 | + * Returns 0 if successful, or -EINVAL if a parameter value is invalid. | ||
270 | + **/ | ||
271 | +static int prev_validate_params(struct prev_params *params) | ||
272 | +{ | ||
273 | + if (!params) { | ||
274 | + dev_err(prev_dev, "validate_params: error in argument"); | ||
275 | + goto err_einval; | ||
276 | + } | ||
277 | + | ||
278 | + if ((params->features & PREV_AVERAGER) == PREV_AVERAGER) { | ||
279 | + if ((params->average != NO_AVE) | ||
280 | + && (params->average != AVE_2_PIX) | ||
281 | + && (params->average != AVE_4_PIX) | ||
282 | + && (params->average != AVE_8_PIX)) { | ||
283 | + dev_err(prev_dev, "validate_params: wrong pix " | ||
284 | + "average\n"); | ||
285 | + goto err_einval; | ||
286 | + } else if (((params->average == AVE_2_PIX) | ||
287 | + && (params->size_params.hsize % 2)) | ||
288 | + || ((params->average == AVE_4_PIX) | ||
289 | + && (params->size_params.hsize % 4)) | ||
290 | + || ((params->average == AVE_8_PIX) | ||
291 | + && (params->size_params.hsize % 8))) { | ||
292 | + dev_err(prev_dev, "validate_params: " | ||
293 | + "wrong pix average for input size\n"); | ||
294 | + goto err_einval; | ||
295 | + } | ||
296 | + } | ||
297 | + | ||
298 | + if ((params->size_params.pixsize != PREV_INWIDTH_8BIT) | ||
299 | + && (params->size_params.pixsize | ||
300 | + != PREV_INWIDTH_10BIT)) { | ||
301 | + dev_err(prev_dev, "validate_params: wrong pixsize\n"); | ||
302 | + goto err_einval; | ||
303 | + } | ||
304 | + | ||
305 | + if (params->size_params.hsize > MAX_IMAGE_WIDTH | ||
306 | + || params->size_params.hsize < 0) { | ||
307 | + dev_err(prev_dev, "validate_params: wrong hsize\n"); | ||
308 | + goto err_einval; | ||
309 | + } | ||
310 | + | ||
311 | + if ((params->pix_fmt != YCPOS_YCrYCb) | ||
312 | + && (YCPOS_YCbYCr != params->pix_fmt) | ||
313 | + && (YCPOS_CbYCrY != params->pix_fmt) | ||
314 | + && (YCPOS_CrYCbY != params->pix_fmt)) { | ||
315 | + dev_err(prev_dev, "validate_params: wrong pix_fmt"); | ||
316 | + goto err_einval; | ||
317 | + } | ||
318 | + | ||
319 | + if ((params->features & PREV_DARK_FRAME_SUBTRACT) | ||
320 | + && (params->features | ||
321 | + & PREV_DARK_FRAME_CAPTURE)) { | ||
322 | + dev_err(prev_dev, "validate_params: DARK FRAME CAPTURE and " | ||
323 | + "SUBSTRACT cannot be enabled " | ||
324 | + "at same time\n"); | ||
325 | + goto err_einval; | ||
326 | + } | ||
327 | + | ||
328 | + if (params->features & PREV_DARK_FRAME_SUBTRACT) | ||
329 | + if (!params->drkf_params.addr | ||
330 | + || (params->drkf_params.offset % 32)) { | ||
331 | + dev_err(prev_dev, "validate_params: dark frame " | ||
332 | + "address\n"); | ||
333 | + goto err_einval; | ||
334 | + } | ||
335 | + | ||
336 | + if (params->features & PREV_LENS_SHADING) | ||
337 | + if ((params->lens_shading_shift > 7) | ||
338 | + || !params->drkf_params.addr | ||
339 | + || (params->drkf_params.offset % 32)) { | ||
340 | + dev_err(prev_dev, "validate_params: lens shading " | ||
341 | + "shift\n"); | ||
342 | + goto err_einval; | ||
343 | + } | ||
344 | + | ||
345 | + if ((params->size_params.in_pitch <= 0) | ||
346 | + || (params->size_params.in_pitch % 32)) { | ||
347 | + params->size_params.in_pitch = | ||
348 | + (params->size_params.hsize * 2) & 0xFFE0; | ||
349 | + dev_err(prev_dev, "\nError in in_pitch; new value = %d", | ||
350 | + params->size_params.in_pitch); | ||
351 | + } | ||
352 | + | ||
353 | + return 0; | ||
354 | +err_einval: | ||
355 | + return -EINVAL; | ||
356 | +} | ||
357 | + | ||
358 | +/** | ||
359 | + * preview_isr - Callback from ISP driver for ISP Preview Interrupt | ||
360 | + * @status: ISP IRQ0STATUS register value | ||
361 | + * @arg1: Structure containing ISP preview wrapper global information | ||
362 | + * @arg2: Currently not used | ||
363 | + **/ | ||
364 | +static void preview_isr(unsigned long status, isp_vbq_callback_ptr arg1, | ||
365 | + void *arg2) | ||
366 | +{ | ||
367 | + struct prev_device *device = (struct prev_device *)arg1; | ||
368 | + | ||
369 | + if ((status & PREV_DONE) != PREV_DONE) | ||
370 | + return; | ||
371 | + | ||
372 | + if (device) | ||
373 | + complete(&device->wfc); | ||
374 | +} | ||
375 | + | ||
376 | +/** | ||
377 | + * prev_do_preview - Performs the Preview process | ||
378 | + * @device: Structure containing ISP preview wrapper global information | ||
379 | + * @arg: Currently not used | ||
380 | + * | ||
381 | + * Returns 0 if successful, or -EINVAL if the sent parameters are invalid. | ||
382 | + **/ | ||
383 | +static int prev_do_preview(struct prev_device *device, int *arg) | ||
384 | +{ | ||
385 | + int bpp, size; | ||
386 | + int ret = 0; | ||
387 | + u32 out_hsize, out_vsize, out_line_offset; | ||
388 | + | ||
389 | + dev_dbg(prev_dev, "prev_do_preview E\n"); | ||
390 | + | ||
391 | + if (!device) { | ||
392 | + dev_err(prev_dev, "preview: invalid parameters\n"); | ||
393 | + return -EINVAL; | ||
394 | + } | ||
395 | + | ||
396 | + if (device->params->size_params.pixsize == PREV_INWIDTH_8BIT) | ||
397 | + bpp = 1; | ||
398 | + else | ||
399 | + bpp = 2; | ||
400 | + | ||
401 | + size = device->params->size_params.hsize * | ||
402 | + device->params->size_params.vsize * bpp; | ||
403 | + | ||
404 | + ret = isppreview_set_inaddr(device->isp_addr_read); | ||
405 | + if (ret) | ||
406 | + goto out; | ||
407 | + | ||
408 | + ret = isppreview_set_outaddr(device->isp_addr_read); | ||
409 | + if (ret) | ||
410 | + goto out; | ||
411 | + | ||
412 | + isppreview_try_size(device->params->size_params.hsize, | ||
413 | + device->params->size_params.vsize, | ||
414 | + &out_hsize, &out_vsize); | ||
415 | + | ||
416 | + ret = isppreview_config_inlineoffset(device->params->size_params.hsize | ||
417 | + * bpp); | ||
418 | + if (ret) | ||
419 | + goto out; | ||
420 | + | ||
421 | + out_line_offset = (out_hsize * bpp) & PREV_32BYTES_ALIGN_MASK; | ||
422 | + | ||
423 | + ret = isppreview_config_outlineoffset(out_line_offset); | ||
424 | + if (ret) | ||
425 | + goto out; | ||
426 | + | ||
427 | + ret = isppreview_config_size(device->params->size_params.hsize, | ||
428 | + device->params->size_params.vsize, | ||
429 | + out_hsize, out_vsize); | ||
430 | + if (ret) | ||
431 | + goto out; | ||
432 | + | ||
433 | + isppreview_config_datapath(PRV_RAW_MEM, PREVIEW_MEM); | ||
434 | + | ||
435 | + ret = isp_set_callback(CBK_PREV_DONE, preview_isr, (void *)device, | ||
436 | + (void *)NULL); | ||
437 | + if (ret) { | ||
438 | + dev_err(prev_dev, "ERROR while setting Previewer callback!\n"); | ||
439 | + goto out; | ||
440 | + } | ||
441 | + isppreview_enable(1); | ||
442 | + | ||
443 | + wait_for_completion_interruptible(&device->wfc); | ||
444 | + | ||
445 | + if (device->isp_addr_read) { | ||
446 | + ispmmu_vunmap(device->isp_addr_read); | ||
447 | + device->isp_addr_read = 0; | ||
448 | + } | ||
449 | + | ||
450 | + ret = isp_unset_callback(CBK_PREV_DONE); | ||
451 | + | ||
452 | + dev_dbg(prev_dev, "prev_do_preview L\n"); | ||
453 | +out: | ||
454 | + return ret; | ||
455 | +} | ||
456 | + | ||
457 | +/** | ||
458 | + * previewer_vbq_release - Videobuffer queue release | ||
459 | + * @q: Structure containing the videobuffer queue. | ||
460 | + * @vb: Structure containing the videobuffer used for previewer processing. | ||
461 | + **/ | ||
462 | +static void previewer_vbq_release(struct videobuf_queue *q, | ||
463 | + struct videobuf_buffer *vb) | ||
464 | +{ | ||
465 | + struct prev_fh *fh = q->priv_data; | ||
466 | + struct prev_device *device = fh->device; | ||
467 | + | ||
468 | + ispmmu_vunmap(device->isp_addr_read); | ||
469 | + device->isp_addr_read = 0; | ||
470 | + spin_lock(&device->vbq_lock); | ||
471 | + vb->state = VIDEOBUF_NEEDS_INIT; | ||
472 | + spin_unlock(&device->vbq_lock); | ||
473 | + dev_dbg(prev_dev, "previewer_vbq_release\n"); | ||
474 | +} | ||
475 | + | ||
476 | +/** | ||
477 | + * previewer_vbq_setup - Sets up the videobuffer size and validates count. | ||
478 | + * @q: Structure containing the videobuffer queue. | ||
479 | + * @cnt: Number of buffers requested | ||
480 | + * @size: Size in bytes of the buffer used for previewing | ||
481 | + * | ||
482 | + * Always returns 0. | ||
483 | + **/ | ||
484 | +static int previewer_vbq_setup(struct videobuf_queue *q, | ||
485 | + unsigned int *cnt, | ||
486 | + unsigned int *size) | ||
487 | +{ | ||
488 | + struct prev_fh *fh = q->priv_data; | ||
489 | + struct prev_device *device = fh->device; | ||
490 | + u32 bpp = 1; | ||
491 | + | ||
492 | + spin_lock(&device->vbq_lock); | ||
493 | + if (*cnt <= 0) | ||
494 | + *cnt = VIDEO_MAX_FRAME; | ||
495 | + | ||
496 | + if (*cnt > VIDEO_MAX_FRAME) | ||
497 | + *cnt = VIDEO_MAX_FRAME; | ||
498 | + | ||
499 | + if (!device->params->size_params.hsize || | ||
500 | + !device->params->size_params.vsize) { | ||
501 | + dev_err(prev_dev, "Can't setup buffer size\n"); | ||
502 | + spin_unlock(&device->vbq_lock); | ||
503 | + return -EINVAL; | ||
504 | + } | ||
505 | + | ||
506 | + if (device->params->size_params.pixsize == PREV_INWIDTH_10BIT) | ||
507 | + bpp = 2; | ||
508 | + *size = prev_bufsize = bpp * device->params->size_params.hsize | ||
509 | + * device->params->size_params.vsize; | ||
510 | + spin_unlock(&device->vbq_lock); | ||
511 | + dev_dbg(prev_dev, "previewer_vbq_setup\n"); | ||
512 | + return 0; | ||
513 | +} | ||
514 | + | ||
515 | +/** | ||
516 | + * previewer_vbq_prepare - Videobuffer is prepared and mmapped. | ||
517 | + * @q: Structure containing the videobuffer queue. | ||
518 | + * @vb: Structure containing the videobuffer used for previewer processing. | ||
519 | + * @field: Type of field to set in videobuffer device. | ||
520 | + * | ||
521 | + * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or | ||
522 | + * -EIO if the ISP MMU mapping fails | ||
523 | + **/ | ||
524 | +static int previewer_vbq_prepare(struct videobuf_queue *q, | ||
525 | + struct videobuf_buffer *vb, | ||
526 | + enum v4l2_field field) | ||
527 | +{ | ||
528 | + struct prev_fh *fh = q->priv_data; | ||
529 | + struct prev_device *device = fh->device; | ||
530 | + int err = -EINVAL; | ||
531 | + unsigned int isp_addr; | ||
532 | + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); | ||
533 | + | ||
534 | + dev_dbg(prev_dev, "previewer_vbq_prepare E\n"); | ||
535 | + spin_lock(&device->vbq_lock); | ||
536 | + if (vb->baddr) { | ||
537 | + vb->size = prev_bufsize; | ||
538 | + vb->bsize = prev_bufsize; | ||
539 | + } else { | ||
540 | + spin_unlock(&device->vbq_lock); | ||
541 | + dev_err(prev_dev, "No user buffer allocated\n"); | ||
542 | + goto out; | ||
543 | + } | ||
544 | + | ||
545 | + vb->width = device->params->size_params.hsize; | ||
546 | + vb->height = device->params->size_params.vsize; | ||
547 | + vb->field = field; | ||
548 | + spin_unlock(&device->vbq_lock); | ||
549 | + | ||
550 | + if (vb->state == VIDEOBUF_NEEDS_INIT) { | ||
551 | + err = videobuf_iolock(q, vb, NULL); | ||
552 | + if (!err) { | ||
553 | + isp_addr = ispmmu_vmap(dma->sglist, dma->sglen); | ||
554 | + if (!isp_addr) | ||
555 | + err = -EIO; | ||
556 | + else | ||
557 | + device->isp_addr_read = isp_addr; | ||
558 | + } | ||
559 | + } | ||
560 | + | ||
561 | + if (!err) { | ||
562 | + vb->state = VIDEOBUF_PREPARED; | ||
563 | + flush_cache_user_range(NULL, vb->baddr, | ||
564 | + (vb->baddr + vb->bsize)); | ||
565 | + } else | ||
566 | + previewer_vbq_release(q, vb); | ||
567 | + | ||
568 | + dev_dbg(prev_dev, "previewer_vbq_prepare L\n"); | ||
569 | +out: | ||
570 | + return err; | ||
571 | +} | ||
572 | + | ||
573 | +static void previewer_vbq_queue(struct videobuf_queue *q, | ||
574 | + struct videobuf_buffer *vb) | ||
575 | +{ | ||
576 | + return; | ||
577 | +} | ||
578 | + | ||
579 | +/** | ||
580 | + * previewer_open - Initializes and opens the Preview Wrapper | ||
581 | + * @inode: Inode structure associated with the Preview Wrapper | ||
582 | + * @filp: File structure associated with the Preview Wrapper | ||
583 | + * | ||
584 | + * Returns 0 if successful, -EACCES if its unable to initialize default config, | ||
585 | + * -EBUSY if its already opened or the ISP module is not available, or -ENOMEM | ||
586 | + * if its unable to allocate the device in kernel space memory. | ||
587 | + **/ | ||
588 | +static int previewer_open(struct inode *inode, struct file *filp) | ||
589 | +{ | ||
590 | + int ret = 0; | ||
591 | + struct prev_device *device = prevdevice; | ||
592 | + struct prev_params *config = isppreview_get_config(); | ||
593 | + struct prev_fh *fh; | ||
594 | + | ||
595 | + if (config == NULL) { | ||
596 | + dev_err(prev_dev, "Unable to initialize default config " | ||
597 | + "from isppreviewer\n\n"); | ||
598 | + return -EACCES; | ||
599 | + } | ||
600 | + | ||
601 | + if (device->opened || (filp->f_flags & O_NONBLOCK)) { | ||
602 | + dev_err(prev_dev, "previewer_open: device is already " | ||
603 | + "opened\n"); | ||
604 | + return -EBUSY; | ||
605 | + } | ||
606 | + | ||
607 | + fh = kzalloc(sizeof(struct prev_fh), GFP_KERNEL); | ||
608 | + if (NULL == fh) | ||
609 | + return -ENOMEM; | ||
610 | + | ||
611 | + isp_get(); | ||
612 | + ret = isppreview_request(); | ||
613 | + if (ret) { | ||
614 | + isp_put(); | ||
615 | + dev_err(prev_dev, "Can't acquire isppreview\n"); | ||
616 | + return ret; | ||
617 | + } | ||
618 | + | ||
619 | + device->params = config; | ||
620 | + device->opened = 1; | ||
621 | + | ||
622 | + filp->private_data = fh; | ||
623 | + fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
624 | + fh->device = device; | ||
625 | + | ||
626 | + videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL, | ||
627 | + &device->vbq_lock, fh->type, | ||
628 | + V4L2_FIELD_NONE, | ||
629 | + sizeof(struct videobuf_buffer), fh); | ||
630 | + | ||
631 | + init_completion(&device->wfc); | ||
632 | + device->wfc.done = 0; | ||
633 | + mutex_init(&device->prevwrap_mutex); | ||
634 | + | ||
635 | + return 0; | ||
636 | +} | ||
637 | + | ||
638 | +/** | ||
639 | + * previewer_release - Releases Preview Wrapper and frees up allocated memory | ||
640 | + * @inode: Inode structure associated with the Preview Wrapper | ||
641 | + * @filp: File structure associated with the Preview Wrapper | ||
642 | + * | ||
643 | + * Always returns 0. | ||
644 | + **/ | ||
645 | +static int previewer_release(struct inode *inode, struct file *filp) | ||
646 | +{ | ||
647 | + struct prev_fh *fh = filp->private_data; | ||
648 | + struct prev_device *device = fh->device; | ||
649 | + struct videobuf_queue *q = &fh->vbq; | ||
650 | + | ||
651 | + device->opened = 0; | ||
652 | + device->params = NULL; | ||
653 | + isppreview_free(); | ||
654 | + videobuf_mmap_free(q); | ||
655 | + isp_put(); | ||
656 | + prev_bufsize = 0; | ||
657 | + filp->private_data = NULL; | ||
658 | + kfree(fh); | ||
659 | + | ||
660 | + dev_dbg(prev_dev, "previewer_release\n"); | ||
661 | + return 0; | ||
662 | +} | ||
663 | + | ||
664 | +/** | ||
665 | + * previewer_mmap - Memory maps the Preview Wrapper module. | ||
666 | + * @file: File structure associated with the Preview Wrapper | ||
667 | + * @vma: Virtual memory area structure. | ||
668 | + * | ||
669 | + * Returns 0 if successful, or returned value by the videobuf_mmap_mapper() | ||
670 | + * function. | ||
671 | + **/ | ||
672 | +static int previewer_mmap(struct file *file, struct vm_area_struct *vma) | ||
673 | +{ | ||
674 | + struct prev_fh *fh = file->private_data; | ||
675 | + dev_dbg(prev_dev, "previewer_mmap\n"); | ||
676 | + | ||
677 | + return videobuf_mmap_mapper(&fh->vbq, vma); | ||
678 | +} | ||
679 | + | ||
680 | +/** | ||
681 | + * previewer_ioctl - I/O control function for Preview Wrapper | ||
682 | + * @inode: Inode structure associated with the Preview Wrapper. | ||
683 | + * @file: File structure associated with the Preview Wrapper. | ||
684 | + * @cmd: Type of command to execute. | ||
685 | + * @arg: Argument to send to requested command. | ||
686 | + * | ||
687 | + * Returns 0 if successful, -1 if bad command passed or access is denied, | ||
688 | + * -EFAULT if copy_from_user() or copy_to_user() fails, -EINVAL if parameter | ||
689 | + * validation fails or parameter structure is not present | ||
690 | + **/ | ||
691 | +static int previewer_ioctl(struct inode *inode, struct file *file, | ||
692 | + unsigned int cmd, unsigned long arg) | ||
693 | +{ | ||
694 | + int ret = 0; | ||
695 | + struct prev_params params; | ||
696 | + struct prev_fh *fh = file->private_data; | ||
697 | + struct prev_device *device = fh->device; | ||
698 | + | ||
699 | + dev_dbg(prev_dev, "Entering previewer_ioctl()\n"); | ||
700 | + | ||
701 | + if ((_IOC_TYPE(cmd) != PREV_IOC_BASE) | ||
702 | + || (_IOC_NR(cmd) > PREV_IOC_MAXNR)) { | ||
703 | + dev_err(prev_dev, "Bad command Value \n"); | ||
704 | + goto err_minusone; | ||
705 | + } | ||
706 | + | ||
707 | + if (_IOC_DIR(cmd) & _IOC_READ) | ||
708 | + ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); | ||
709 | + else if (_IOC_DIR(cmd) & _IOC_WRITE) | ||
710 | + ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); | ||
711 | + if (ret) { | ||
712 | + dev_err(prev_dev, "access denied\n"); | ||
713 | + goto err_minusone; | ||
714 | + } | ||
715 | + | ||
716 | + switch (cmd) { | ||
717 | + case PREV_REQBUF: | ||
718 | + if (mutex_lock_interruptible(&device->prevwrap_mutex)) | ||
719 | + goto err_eintr; | ||
720 | + ret = videobuf_reqbufs(&fh->vbq, (void *)arg); | ||
721 | + mutex_unlock(&device->prevwrap_mutex); | ||
722 | + break; | ||
723 | + | ||
724 | + case PREV_QUERYBUF: | ||
725 | + if (mutex_lock_interruptible(&device->prevwrap_mutex)) | ||
726 | + goto err_eintr; | ||
727 | + ret = videobuf_querybuf(&fh->vbq, (void *)arg); | ||
728 | + mutex_unlock(&device->prevwrap_mutex); | ||
729 | + break; | ||
730 | + | ||
731 | + case PREV_QUEUEBUF: | ||
732 | + if (mutex_lock_interruptible(&device->prevwrap_mutex)) | ||
733 | + goto err_eintr; | ||
734 | + ret = videobuf_qbuf(&fh->vbq, (void *)arg); | ||
735 | + mutex_unlock(&device->prevwrap_mutex); | ||
736 | + break; | ||
737 | + | ||
738 | + case PREV_SET_PARAM: | ||
739 | + if (mutex_lock_interruptible(&device->prevwrap_mutex)) | ||
740 | + goto err_eintr; | ||
741 | + if (copy_from_user(¶ms, (struct prev_params *)arg, | ||
742 | + sizeof(struct prev_params))) { | ||
743 | + mutex_unlock(&device->prevwrap_mutex); | ||
744 | + return -EFAULT; | ||
745 | + } | ||
746 | + ret = prev_validate_params(¶ms); | ||
747 | + if (ret < 0) { | ||
748 | + dev_err(prev_dev, "Error validating parameters!\n"); | ||
749 | + mutex_unlock(&device->prevwrap_mutex); | ||
750 | + goto out; | ||
751 | + } | ||
752 | + if (device->params) | ||
753 | + memcpy(device->params, ¶ms, | ||
754 | + sizeof(struct prev_params)); | ||
755 | + else { | ||
756 | + mutex_unlock(&device->prevwrap_mutex); | ||
757 | + return -EINVAL; | ||
758 | + } | ||
759 | + | ||
760 | + ret = prev_hw_setup(device->params); | ||
761 | + mutex_unlock(&device->prevwrap_mutex); | ||
762 | + break; | ||
763 | + | ||
764 | + case PREV_GET_PARAM: | ||
765 | + if (copy_to_user((struct prev_params *)arg, device->params, | ||
766 | + sizeof(struct prev_params))) | ||
767 | + ret = -EFAULT; | ||
768 | + break; | ||
769 | + | ||
770 | + case PREV_GET_STATUS: | ||
771 | + ret = prev_get_status((struct prev_status *)arg); | ||
772 | + break; | ||
773 | + | ||
774 | + case PREV_PREVIEW: | ||
775 | + if (mutex_lock_interruptible(&device->prevwrap_mutex)) | ||
776 | + goto err_eintr; | ||
777 | + ret = prev_do_preview(device, (int *)arg); | ||
778 | + mutex_unlock(&device->prevwrap_mutex); | ||
779 | + break; | ||
780 | + | ||
781 | + case PREV_GET_CROPSIZE: | ||
782 | + { | ||
783 | + struct prev_cropsize outputsize; | ||
784 | + prev_calculate_crop(device, &outputsize); | ||
785 | + if (copy_to_user((struct prev_cropsize *)arg, &outputsize, | ||
786 | + sizeof(struct prev_cropsize))) | ||
787 | + ret = -EFAULT; | ||
788 | + } | ||
789 | + break; | ||
790 | + | ||
791 | + default: | ||
792 | + dev_err(prev_dev, "previewer_ioctl: Invalid Command Value\n"); | ||
793 | + ret = -EINVAL; | ||
794 | + } | ||
795 | +out: | ||
796 | + return ret; | ||
797 | +err_minusone: | ||
798 | + return -1; | ||
799 | +err_eintr: | ||
800 | + return -EINTR; | ||
801 | +} | ||
802 | + | ||
803 | +/** | ||
804 | + * previewer_platform_release - Acts when Reference count is zero | ||
805 | + * @device: Structure containing ISP preview wrapper global information | ||
806 | + * | ||
807 | + * This is called when the reference count goes to zero | ||
808 | + **/ | ||
809 | +static void previewer_platform_release(struct device *device) | ||
810 | +{ | ||
811 | + dev_dbg(prev_dev, "previewer_platform_release()\n"); | ||
812 | +} | ||
813 | + | ||
814 | +static struct file_operations prev_fops = { | ||
815 | + .owner = THIS_MODULE, | ||
816 | + .open = previewer_open, | ||
817 | + .release = previewer_release, | ||
818 | + .mmap = previewer_mmap, | ||
819 | + .ioctl = previewer_ioctl, | ||
820 | +}; | ||
821 | + | ||
822 | +static struct platform_device omap_previewer_device = { | ||
823 | + .name = OMAP_PREV_NAME, | ||
824 | + .id = -1, | ||
825 | + .dev = { | ||
826 | + .release = previewer_platform_release, | ||
827 | + } | ||
828 | +}; | ||
829 | + | ||
830 | +/** | ||
831 | + * previewer_probe - Checks for device presence | ||
832 | + * @pdev: Structure containing details of the current device. | ||
833 | + * | ||
834 | + * Always returns 0 | ||
835 | + **/ | ||
836 | +static int __init previewer_probe(struct platform_device *pdev) | ||
837 | +{ | ||
838 | + return 0; | ||
839 | +} | ||
840 | + | ||
841 | +/** | ||
842 | + * previewer_remove - Handles the removal of the driver | ||
843 | + * @pdev: Structure containing details of the current device. | ||
844 | + * | ||
845 | + * Always returns 0. | ||
846 | + **/ | ||
847 | +static int previewer_remove(struct platform_device *pdev) | ||
848 | +{ | ||
849 | + dev_dbg(prev_dev, "previewer_remove()\n"); | ||
850 | + | ||
851 | + platform_device_unregister(&omap_previewer_device); | ||
852 | + platform_driver_unregister(&omap_previewer_driver); | ||
853 | + unregister_chrdev(prev_major, OMAP_PREV_NAME); | ||
854 | + return 0; | ||
855 | +} | ||
856 | + | ||
857 | +static struct platform_driver omap_previewer_driver = { | ||
858 | + .probe = previewer_probe, | ||
859 | + .remove = previewer_remove, | ||
860 | + .driver = { | ||
861 | + .owner = THIS_MODULE, | ||
862 | + .name = OMAP_PREV_NAME, | ||
863 | + }, | ||
864 | +}; | ||
865 | + | ||
866 | +/** | ||
867 | + * omap_previewer_init - Initialization of Preview Wrapper | ||
868 | + * | ||
869 | + * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if | ||
870 | + * could not register the wrapper as a character device, or other errors if the | ||
871 | + * device or driver can't register. | ||
872 | + **/ | ||
873 | +static int __init omap_previewer_init(void) | ||
874 | +{ | ||
875 | + int ret; | ||
876 | + struct prev_device *device; | ||
877 | + | ||
878 | + device = kzalloc(sizeof(struct prev_device), GFP_KERNEL); | ||
879 | + if (!device) { | ||
880 | + dev_err(prev_dev, OMAP_PREV_NAME ": could not allocate" | ||
881 | + " memory\n"); | ||
882 | + return -ENOMEM; | ||
883 | + } | ||
884 | + prev_major = register_chrdev(0, OMAP_PREV_NAME, &prev_fops); | ||
885 | + | ||
886 | + if (prev_major < 0) { | ||
887 | + dev_err(prev_dev, OMAP_PREV_NAME ": initialization " | ||
888 | + "failed. could not register character " | ||
889 | + "device\n"); | ||
890 | + return -ENODEV; | ||
891 | + } | ||
892 | + | ||
893 | + ret = platform_driver_register(&omap_previewer_driver); | ||
894 | + if (ret) { | ||
895 | + dev_err(prev_dev, OMAP_PREV_NAME | ||
896 | + ": failed to register platform driver!\n"); | ||
897 | + goto fail2; | ||
898 | + } | ||
899 | + ret = platform_device_register(&omap_previewer_device); | ||
900 | + if (ret) { | ||
901 | + dev_err(prev_dev, OMAP_PREV_NAME | ||
902 | + ": failed to register platform device!\n"); | ||
903 | + goto fail3; | ||
904 | + } | ||
905 | + | ||
906 | + prev_class = class_create(THIS_MODULE, OMAP_PREV_NAME); | ||
907 | + if (!prev_class) | ||
908 | + goto fail4; | ||
909 | + | ||
910 | + prev_dev = device_create(prev_class, prev_dev, | ||
911 | + (MKDEV(prev_major, 0)), NULL, | ||
912 | + OMAP_PREV_NAME); | ||
913 | + dev_dbg(prev_dev, OMAP_PREV_NAME ": Registered Previewer Wrapper\n"); | ||
914 | + device->opened = 0; | ||
915 | + | ||
916 | + device->vbq_ops.buf_setup = previewer_vbq_setup; | ||
917 | + device->vbq_ops.buf_prepare = previewer_vbq_prepare; | ||
918 | + device->vbq_ops.buf_release = previewer_vbq_release; | ||
919 | + device->vbq_ops.buf_queue = previewer_vbq_queue; | ||
920 | + spin_lock_init(&device->vbq_lock); | ||
921 | + | ||
922 | + prevdevice = device; | ||
923 | + return 0; | ||
924 | + | ||
925 | +fail4: | ||
926 | + platform_device_unregister(&omap_previewer_device); | ||
927 | +fail3: | ||
928 | + platform_driver_unregister(&omap_previewer_driver); | ||
929 | +fail2: | ||
930 | + unregister_chrdev(prev_major, OMAP_PREV_NAME); | ||
931 | + | ||
932 | + return ret; | ||
933 | +} | ||
934 | + | ||
935 | +/** | ||
936 | + * omap_previewer_exit - Close of Preview Wrapper | ||
937 | + **/ | ||
938 | +static void __exit omap_previewer_exit(void) | ||
939 | +{ | ||
940 | + previewer_remove(&omap_previewer_device); | ||
941 | + kfree(prevdevice); | ||
942 | + prev_major = -1; | ||
943 | +} | ||
944 | + | ||
945 | +module_init(omap_previewer_init); | ||
946 | +module_exit(omap_previewer_exit); | ||
947 | + | ||
948 | +MODULE_AUTHOR("Texas Instruments"); | ||
949 | +MODULE_DESCRIPTION("OMAP ISP Previewer"); | ||
950 | +MODULE_LICENSE("GPL"); | ||
951 | diff --git a/drivers/media/video/isp/omap_previewer.h b/drivers/media/video/isp/omap_previewer.h | ||
952 | new file mode 100644 | ||
953 | index 0000000..0bb31cd | ||
954 | --- /dev/null | ||
955 | +++ b/drivers/media/video/isp/omap_previewer.h | ||
956 | @@ -0,0 +1,162 @@ | ||
957 | +/* | ||
958 | + * drivers/media/video/isp/omap_previewer.h | ||
959 | + * | ||
960 | + * Header file for Preview module wrapper in TI's OMAP3430 ISP | ||
961 | + * | ||
962 | + * Copyright (C) 2008 Texas Instruments, Inc. | ||
963 | + * | ||
964 | + * Contributors: | ||
965 | + * Leonides Martinez <leonides.martinez@ti.com> | ||
966 | + * Sergio Aguirre <saaguirre@ti.com> | ||
967 | + * | ||
968 | + * This package is free software; you can redistribute it and/or modify | ||
969 | + * it under the terms of the GNU General Public License version 2 as | ||
970 | + * published by the Free Software Foundation. | ||
971 | + * | ||
972 | + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | ||
973 | + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
974 | + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
975 | + */ | ||
976 | + | ||
977 | +#include "isppreview.h" | ||
978 | + | ||
979 | +#ifndef OMAP_ISP_PREVIEW_WRAP_H | ||
980 | +#define OMAP_ISP_PREVIEW_WRAP_H | ||
981 | + | ||
982 | +#define PREV_IOC_BASE 'P' | ||
983 | +#define PREV_REQBUF _IOWR(PREV_IOC_BASE, 1,\ | ||
984 | + struct v4l2_requestbuffers) | ||
985 | +#define PREV_QUERYBUF _IOWR(PREV_IOC_BASE, 2,\ | ||
986 | + struct v4l2_buffer) | ||
987 | +#define PREV_SET_PARAM _IOW(PREV_IOC_BASE, 3,\ | ||
988 | + struct prev_params) | ||
989 | +#define PREV_GET_PARAM _IOWR(PREV_IOC_BASE, 4,\ | ||
990 | + struct prev_params) | ||
991 | +#define PREV_PREVIEW _IOR(PREV_IOC_BASE, 5, int) | ||
992 | +#define PREV_GET_STATUS _IOR(PREV_IOC_BASE, 6, char) | ||
993 | +#define PREV_GET_CROPSIZE _IOR(PREV_IOC_BASE, 7,\ | ||
994 | + struct prev_cropsize) | ||
995 | +#define PREV_QUEUEBUF _IOWR(PREV_IOC_BASE, 8,\ | ||
996 | + struct v4l2_buffer) | ||
997 | +#define PREV_IOC_MAXNR 8 | ||
998 | + | ||
999 | +#define LUMA_TABLE_SIZE 128 | ||
1000 | +#define GAMMA_TABLE_SIZE 1024 | ||
1001 | +#define CFA_COEFF_TABLE_SIZE 576 | ||
1002 | +#define NOISE_FILTER_TABLE_SIZE 256 | ||
1003 | + | ||
1004 | +#define MAX_IMAGE_WIDTH 3300 | ||
1005 | + | ||
1006 | +#define PREV_INWIDTH_8BIT 0 /* pixel width of 8 bits */ | ||
1007 | +#define PREV_INWIDTH_10BIT 1 /* pixel width of 10 bits */ | ||
1008 | + | ||
1009 | +#define PREV_32BYTES_ALIGN_MASK 0xFFFFFFE0 | ||
1010 | +#define PREV_16PIX_ALIGN_MASK 0xFFFFFFF0 | ||
1011 | + | ||
1012 | +/** | ||
1013 | + * struct prev_rgbblending - Structure for RGB2RGB blending parameters | ||
1014 | + * @blending: Color correlation 3x3 matrix. | ||
1015 | + * @offset: Color correlation offsets. | ||
1016 | + */ | ||
1017 | +struct prev_rgbblending { | ||
1018 | + short blending[RGB_MAX][RGB_MAX]; /* color correlation 3x3 | ||
1019 | + * matrix. | ||
1020 | + */ | ||
1021 | + short offset[RGB_MAX]; /* color correlation offsets */ | ||
1022 | +}; | ||
1023 | + | ||
1024 | +/** | ||
1025 | + * struct prev_cfa_coeffs - Structure for CFA coefficients | ||
1026 | + * @hthreshold: Horizontal threshold. | ||
1027 | + * @vthreshold: Vertical threshold. | ||
1028 | + * @coeffs: CFA coefficients | ||
1029 | + */ | ||
1030 | +struct prev_cfa_coeffs { | ||
1031 | + char hthreshold, vthreshold; | ||
1032 | + int coeffs[CFA_COEFF_TABLE_SIZE]; | ||
1033 | +}; | ||
1034 | + | ||
1035 | +/** | ||
1036 | + * struct prev_gamma_coeffs - Structure for Gamma Coefficients | ||
1037 | + * @red: Table of gamma correction values for red color. | ||
1038 | + * @green: Table of gamma correction values for green color. | ||
1039 | + * @blue: Table of gamma correction values for blue color. | ||
1040 | + */ | ||
1041 | +struct prev_gamma_coeffs { | ||
1042 | + unsigned char red[GAMMA_TABLE_SIZE]; | ||
1043 | + unsigned char green[GAMMA_TABLE_SIZE]; | ||
1044 | + unsigned char blue[GAMMA_TABLE_SIZE]; | ||
1045 | +}; | ||
1046 | + | ||
1047 | +/** | ||
1048 | + * struct prev_noiseflt_coeffs - Structure for Noise Filter Coefficients. | ||
1049 | + * @noise: Noise filter table. | ||
1050 | + * @strength: Used to find out weighted average. | ||
1051 | + */ | ||
1052 | +struct prev_noiseflt_coeffs { | ||
1053 | + unsigned char noise[NOISE_FILTER_TABLE_SIZE]; | ||
1054 | + unsigned char strength; | ||
1055 | +}; | ||
1056 | + | ||
1057 | +/** | ||
1058 | + * struct prev_chroma_spr - Structure for Chroma Suppression. | ||
1059 | + * @hpfy: High passed version of Y or normal Y. | ||
1060 | + * @threshold: Threshold for chroma suppress. | ||
1061 | + * @gain: Chroma suppression gain | ||
1062 | + */ | ||
1063 | +struct prev_chroma_spr { | ||
1064 | + unsigned char hpfy; | ||
1065 | + char threshold; | ||
1066 | + unsigned char gain; | ||
1067 | +}; | ||
1068 | + | ||
1069 | +/** | ||
1070 | + * struct prev_status - Structure to know status of the hardware | ||
1071 | + * @hw_busy: Flag to indicate if Hardware is Busy. | ||
1072 | + */ | ||
1073 | +struct prev_status { | ||
1074 | + char hw_busy; | ||
1075 | +}; | ||
1076 | + | ||
1077 | +/** | ||
1078 | + * struct prev_cropsize - Structure to know crop size. | ||
1079 | + * @hcrop: Horizontal size of crop window. | ||
1080 | + * @vcrop: Vertical size of crop window. | ||
1081 | + */ | ||
1082 | +struct prev_cropsize { | ||
1083 | + int hcrop; | ||
1084 | + int vcrop; | ||
1085 | +}; | ||
1086 | + | ||
1087 | +/** | ||
1088 | + * struct prev_device - Global device information structure. | ||
1089 | + * @params: Pointer to structure containing preview parameters. | ||
1090 | + * @opened: State of the device. | ||
1091 | + * @wfc: Wait for completion. Used for locking operations. | ||
1092 | + * @prevwrap_mutex: Mutex for preview wrapper use. | ||
1093 | + * @vbq_lock: Spinlock for videobuf queues. | ||
1094 | + * @vbq_ops: Videobuf queue operations | ||
1095 | + * @isp_addr_read: Input/Output address | ||
1096 | + */ | ||
1097 | +struct prev_device { | ||
1098 | + struct prev_params *params; | ||
1099 | + unsigned char opened; | ||
1100 | + struct completion wfc; | ||
1101 | + struct mutex prevwrap_mutex; /* For generic internal use */ | ||
1102 | + spinlock_t vbq_lock; /* For videobuffer queue handling */ | ||
1103 | + struct videobuf_queue_ops vbq_ops; | ||
1104 | + dma_addr_t isp_addr_read; | ||
1105 | +}; | ||
1106 | + | ||
1107 | +/** | ||
1108 | + * struct prev_fh - Per-filehandle data structure | ||
1109 | + * @type: Used buffer type. | ||
1110 | + * @vbq: Videobuffer queue. | ||
1111 | + * @device: Pointer to device information structure. | ||
1112 | + */ | ||
1113 | +struct prev_fh { | ||
1114 | + enum v4l2_buf_type type; | ||
1115 | + struct videobuf_queue vbq; | ||
1116 | + struct prev_device *device; | ||
1117 | +}; | ||
1118 | +#endif | ||
1119 | diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c | ||
1120 | new file mode 100644 | ||
1121 | index 0000000..54bc425 | ||
1122 | --- /dev/null | ||
1123 | +++ b/drivers/media/video/isp/omap_resizer.c | ||
1124 | @@ -0,0 +1,1634 @@ | ||
1125 | +/* | ||
1126 | + * drivers/media/video/isp/omap_resizer.c | ||
1127 | + * | ||
1128 | + * Wrapper for Resizer module in TI's OMAP3430 ISP | ||
1129 | + * | ||
1130 | + * Copyright (C) 2008 Texas Instruments, Inc. | ||
1131 | + * | ||
1132 | + * Contributors: | ||
1133 | + * Sergio Aguirre <saaguirre@ti.com> | ||
1134 | + * Troy Laramy <t-laramy@ti.com> | ||
1135 | + * | ||
1136 | + * This package is free software; you can redistribute it and/or modify | ||
1137 | + * it under the terms of the GNU General Public License version 2 as | ||
1138 | + * published by the Free Software Foundation. | ||
1139 | + * | ||
1140 | + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | ||
1141 | + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
1142 | + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
1143 | + */ | ||
1144 | + | ||
1145 | +#include <linux/mutex.h> | ||
1146 | +#include <linux/cdev.h> | ||
1147 | +#include <linux/delay.h> | ||
1148 | +#include <linux/device.h> | ||
1149 | +#include <linux/fs.h> | ||
1150 | +#include <linux/mm.h> | ||
1151 | +#include <linux/module.h> | ||
1152 | +#include <linux/platform_device.h> | ||
1153 | +#include <linux/io.h> | ||
1154 | +#include <linux/uaccess.h> | ||
1155 | +#include <media/v4l2-dev.h> | ||
1156 | +#include <asm/cacheflush.h> | ||
1157 | + | ||
1158 | +#include "isp.h" | ||
1159 | +#include "ispmmu.h" | ||
1160 | +#include "ispreg.h" | ||
1161 | +#include "ispresizer.h" | ||
1162 | +#include <linux/omap_resizer.h> | ||
1163 | + | ||
1164 | +#define OMAP_REZR_NAME "omap-resizer" | ||
1165 | + | ||
1166 | +/* Defines and Constants*/ | ||
1167 | +#define MAX_CHANNELS 16 | ||
1168 | +#define MAX_IMAGE_WIDTH 2047 | ||
1169 | +#define MAX_IMAGE_WIDTH_HIGH 2047 | ||
1170 | +#define ALIGNMENT 16 | ||
1171 | +#define CHANNEL_BUSY 1 | ||
1172 | +#define CHANNEL_FREE 0 | ||
1173 | +#define PIXEL_EVEN 2 | ||
1174 | +#define RATIO_MULTIPLIER 256 | ||
1175 | +/* Bit position Macro */ | ||
1176 | +/* macro for bit set and clear */ | ||
1177 | +#define BITSET(variable, bit) ((variable) | (1 << bit)) | ||
1178 | +#define BITRESET(variable, bit) ((variable) & ~(0x00000001 << (bit))) | ||
1179 | +#define SET_BIT_INPUTRAM 28 | ||
1180 | +#define SET_BIT_CBLIN 29 | ||
1181 | +#define SET_BIT_INPTYP 27 | ||
1182 | +#define SET_BIT_YCPOS 26 | ||
1183 | +#define INPUT_RAM 1 | ||
1184 | +#define UP_RSZ_RATIO 64 | ||
1185 | +#define DOWN_RSZ_RATIO 512 | ||
1186 | +#define UP_RSZ_RATIO1 513 | ||
1187 | +#define DOWN_RSZ_RATIO1 1024 | ||
1188 | +#define RSZ_IN_SIZE_VERT_SHIFT 16 | ||
1189 | +#define MAX_HORZ_PIXEL_8BIT 31 | ||
1190 | +#define MAX_HORZ_PIXEL_16BIT 15 | ||
1191 | +#define NUM_PHASES 8 | ||
1192 | +#define NUM_TAPS 4 | ||
1193 | +#define NUM_D2PH 4 /* for downsampling * 2+x ~ 4x, | ||
1194 | + * number of phases | ||
1195 | + */ | ||
1196 | +#define NUM_D2TAPS 7 /* for downsampling * 2+x ~ 4x, | ||
1197 | + * number of taps | ||
1198 | + */ | ||
1199 | +#define ALIGN32 32 | ||
1200 | +#define MAX_COEF_COUNTER 16 | ||
1201 | +#define COEFF_ADDRESS_OFFSET 0x04 | ||
1202 | + | ||
1203 | +/* Global structure which contains information about number of channels | ||
1204 | + and protection variables */ | ||
1205 | +struct device_params { | ||
1206 | + | ||
1207 | + unsigned char opened; /* state of the device */ | ||
1208 | + struct completion compl_isr; /* Completion for interrupt */ | ||
1209 | + struct mutex reszwrap_mutex; /* Semaphore for array */ | ||
1210 | + | ||
1211 | + struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */ | ||
1212 | +}; | ||
1213 | + | ||
1214 | +/* Register mapped structure which contains the every register | ||
1215 | + information */ | ||
1216 | +struct resizer_config { | ||
1217 | + u32 rsz_pcr; /* pcr register mapping | ||
1218 | + * variable. | ||
1219 | + */ | ||
1220 | + u32 rsz_in_start; /* in_start register mapping | ||
1221 | + * variable. | ||
1222 | + */ | ||
1223 | + u32 rsz_in_size; /* in_size register mapping | ||
1224 | + * variable. | ||
1225 | + */ | ||
1226 | + u32 rsz_out_size; /* out_size register mapping | ||
1227 | + * variable. | ||
1228 | + */ | ||
1229 | + u32 rsz_cnt; /* rsz_cnt register mapping | ||
1230 | + * variable. | ||
1231 | + */ | ||
1232 | + u32 rsz_sdr_inadd; /* sdr_inadd register mapping | ||
1233 | + * variable. | ||
1234 | + */ | ||
1235 | + u32 rsz_sdr_inoff; /* sdr_inoff register mapping | ||
1236 | + * variable. | ||
1237 | + */ | ||
1238 | + u32 rsz_sdr_outadd; /* sdr_outadd register mapping | ||
1239 | + * variable. | ||
1240 | + */ | ||
1241 | + u32 rsz_sdr_outoff; /* sdr_outbuff register | ||
1242 | + * mapping variable. | ||
1243 | + */ | ||
1244 | + u32 rsz_coeff_horz[16]; /* horizontal coefficients | ||
1245 | + * mapping array. | ||
1246 | + */ | ||
1247 | + u32 rsz_coeff_vert[16]; /* vertical coefficients | ||
1248 | + * mapping array. | ||
1249 | + */ | ||
1250 | + u32 rsz_yehn; /* yehn(luma)register mapping | ||
1251 | + * variable. | ||
1252 | + */ | ||
1253 | +}; | ||
1254 | + | ||
1255 | +struct rsz_mult { | ||
1256 | + int in_hsize; /* input frame horizontal | ||
1257 | + * size. | ||
1258 | + */ | ||
1259 | + int in_vsize; /* input frame vertical size. | ||
1260 | + */ | ||
1261 | + int out_hsize; /* output frame horizontal | ||
1262 | + * size. | ||
1263 | + */ | ||
1264 | + int out_vsize; /* output frame vertical | ||
1265 | + * size. | ||
1266 | + */ | ||
1267 | + int in_pitch; /* offset between two rows of | ||
1268 | + * input frame. | ||
1269 | + */ | ||
1270 | + int out_pitch; /* offset between two rows of | ||
1271 | + * output frame. | ||
1272 | + */ | ||
1273 | + int end_hsize; | ||
1274 | + int end_vsize; | ||
1275 | + int num_htap; /* 0 = 7tap; 1 = 4tap */ | ||
1276 | + int num_vtap; /* 0 = 7tap; 1 = 4tap */ | ||
1277 | + int active; | ||
1278 | + int inptyp; | ||
1279 | + int vrsz; | ||
1280 | + int hrsz; | ||
1281 | + int hstph; /* for specifying horizontal | ||
1282 | + * starting phase. | ||
1283 | + */ | ||
1284 | + int vstph; | ||
1285 | + int pix_fmt; /* # defined, UYVY or YUYV. */ | ||
1286 | + int cbilin; /* # defined, filter with luma | ||
1287 | + * or bi-linear. | ||
1288 | + */ | ||
1289 | + u16 tap4filt_coeffs[32]; /* horizontal filter | ||
1290 | + * coefficients. | ||
1291 | + */ | ||
1292 | + u16 tap7filt_coeffs[32]; /* vertical filter | ||
1293 | + * coefficients. | ||
1294 | + */ | ||
1295 | +}; | ||
1296 | +/* Channel specific structure contains information regarding | ||
1297 | + the every channel */ | ||
1298 | +struct channel_config { | ||
1299 | + struct resizer_config register_config; /* Instance of register set | ||
1300 | + * mapping structure | ||
1301 | + */ | ||
1302 | + int status; /* Specifies whether the | ||
1303 | + * channel is busy or not | ||
1304 | + */ | ||
1305 | + struct mutex chanprotection_mutex; | ||
1306 | + enum config_done config_state; | ||
1307 | + u8 input_buf_index; | ||
1308 | + u8 output_buf_index; | ||
1309 | + | ||
1310 | +}; | ||
1311 | + | ||
1312 | +/* per-filehandle data structure */ | ||
1313 | +struct rsz_fh { | ||
1314 | + struct rsz_params *params; | ||
1315 | + struct channel_config *config; | ||
1316 | + struct rsz_mult *multipass; /* Multipass to support | ||
1317 | + * resizing ration outside | ||
1318 | + * of 0.25x to 4x | ||
1319 | + */ | ||
1320 | + spinlock_t vbq_lock; /* spinlock for videobuf | ||
1321 | + * queues. | ||
1322 | + */ | ||
1323 | + enum v4l2_buf_type type; | ||
1324 | + struct videobuf_queue vbq; | ||
1325 | + struct device_params *device; | ||
1326 | + | ||
1327 | + dma_addr_t isp_addr_read; /* Input/Output address */ | ||
1328 | + dma_addr_t isp_addr_write; /* Input/Output address */ | ||
1329 | + u32 rsz_bufsize; /* channel specific buffersize | ||
1330 | + */ | ||
1331 | +}; | ||
1332 | + | ||
1333 | +static struct device_params *device_config; | ||
1334 | +static struct device *rsz_device; | ||
1335 | +static int rsz_major = -1; | ||
1336 | +/* functions declaration */ | ||
1337 | +static void rsz_hardware_setup(struct channel_config *rsz_conf_chan); | ||
1338 | +static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *, | ||
1339 | + struct channel_config *); | ||
1340 | +static int rsz_get_params(struct rsz_params *, struct channel_config *); | ||
1341 | +static void rsz_copy_data(struct rsz_mult *multipass, | ||
1342 | + struct rsz_params *params); | ||
1343 | +static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, | ||
1344 | + void *arg2); | ||
1345 | +static void rsz_calculate_crop(struct channel_config *rsz_conf_chan, | ||
1346 | + struct rsz_cropsize *cropsize); | ||
1347 | +static int rsz_set_multipass(struct rsz_mult *multipass, | ||
1348 | + struct channel_config *rsz_conf_chan); | ||
1349 | +static int rsz_set_ratio(struct rsz_mult *multipass, | ||
1350 | + struct channel_config *rsz_conf_chan); | ||
1351 | +static void rsz_config_ratio(struct rsz_mult *multipass, | ||
1352 | + struct channel_config *rsz_conf_chan); | ||
1353 | + | ||
1354 | +/** | ||
1355 | + * rsz_hardware_setup - Sets hardware configuration registers | ||
1356 | + * @rsz_conf_chan: Structure containing channel configuration | ||
1357 | + * | ||
1358 | + * Set hardware configuration registers | ||
1359 | + **/ | ||
1360 | +static void rsz_hardware_setup(struct channel_config *rsz_conf_chan) | ||
1361 | +{ | ||
1362 | + int coeffcounter; | ||
1363 | + int coeffoffset = 0; | ||
1364 | + | ||
1365 | + omap_writel(rsz_conf_chan->register_config.rsz_cnt, | ||
1366 | + OMAP3ISP_RESZ_REG(ISPRSZ_CNT)); | ||
1367 | + | ||
1368 | + omap_writel(rsz_conf_chan->register_config.rsz_in_start, | ||
1369 | + OMAP3ISP_RESZ_REG(ISPRSZ_IN_START)); | ||
1370 | + omap_writel(rsz_conf_chan->register_config.rsz_in_size, | ||
1371 | + OMAP3ISP_RESZ_REG(ISPRSZ_IN_SIZE)); | ||
1372 | + | ||
1373 | + omap_writel(rsz_conf_chan->register_config.rsz_out_size, | ||
1374 | + OMAP3ISP_RESZ_REG(ISPRSZ_OUT_SIZE)); | ||
1375 | + omap_writel(rsz_conf_chan->register_config.rsz_sdr_inadd, | ||
1376 | + OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INADD)); | ||
1377 | + omap_writel(rsz_conf_chan->register_config.rsz_sdr_inoff, | ||
1378 | + OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INOFF)); | ||
1379 | + omap_writel(rsz_conf_chan->register_config.rsz_sdr_outadd, | ||
1380 | + OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTADD)); | ||
1381 | + omap_writel(rsz_conf_chan->register_config.rsz_sdr_outoff, | ||
1382 | + OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTOFF)); | ||
1383 | + omap_writel(rsz_conf_chan->register_config.rsz_yehn, OMAP3ISP_RESZ_REG(ISPRSZ_YENH)); | ||
1384 | + | ||
1385 | + for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER; | ||
1386 | + coeffcounter++) { | ||
1387 | + omap_writel(rsz_conf_chan->register_config. | ||
1388 | + rsz_coeff_horz[coeffcounter], | ||
1389 | + OMAP3ISP_RESZ_REG(ISPRSZ_HFILT10 | ||
1390 | + + coeffoffset)); | ||
1391 | + | ||
1392 | + omap_writel(rsz_conf_chan->register_config. | ||
1393 | + rsz_coeff_vert[coeffcounter], | ||
1394 | + OMAP3ISP_RESZ_REG(ISPRSZ_VFILT10 | ||
1395 | + + coeffoffset)); | ||
1396 | + coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET; | ||
1397 | + } | ||
1398 | +} | ||
1399 | + | ||
1400 | +/** | ||
1401 | + * rsz_start - Enables Resizer Wrapper | ||
1402 | + * @arg: Currently not used. | ||
1403 | + * @device: Structure containing ISP resizer wrapper global information | ||
1404 | + * | ||
1405 | + * Submits a resizing task specified by the rsz_resize structure. The call can | ||
1406 | + * either be blocked until the task is completed or returned immediately based | ||
1407 | + * on the value of the blocking argument in the rsz_resize structure. If it is | ||
1408 | + * blocking, the status of the task can be checked by calling ioctl | ||
1409 | + * RSZ_G_STATUS. Only one task can be outstanding for each logical channel. | ||
1410 | + * | ||
1411 | + * Returns 0 if successful, or -EINVAL if could not set callback for RSZR IRQ | ||
1412 | + * event or the state of the channel is not configured. | ||
1413 | + **/ | ||
1414 | +int rsz_start(int *arg, struct rsz_fh *fh) | ||
1415 | +{ | ||
1416 | + struct channel_config *rsz_conf_chan = fh->config; | ||
1417 | + struct rsz_mult *multipass = fh->multipass; | ||
1418 | + struct videobuf_queue *q = &fh->vbq; | ||
1419 | + int ret; | ||
1420 | + | ||
1421 | + if (rsz_conf_chan->config_state) { | ||
1422 | + dev_err(rsz_device, "State not configured \n"); | ||
1423 | + goto err_einval; | ||
1424 | + } | ||
1425 | + | ||
1426 | + rsz_conf_chan->status = CHANNEL_BUSY; | ||
1427 | + | ||
1428 | + rsz_hardware_setup(rsz_conf_chan); | ||
1429 | + | ||
1430 | + if (isp_set_callback(CBK_RESZ_DONE, rsz_isr, (void *) NULL, | ||
1431 | + (void *)NULL)) { | ||
1432 | + dev_err(rsz_device, "No callback for RSZR\n"); | ||
1433 | + goto err_einval; | ||
1434 | + } | ||
1435 | +mult: | ||
1436 | + device_config->compl_isr.done = 0; | ||
1437 | + | ||
1438 | + ispresizer_enable(1); | ||
1439 | + | ||
1440 | + ret = wait_for_completion_interruptible(&device_config->compl_isr); | ||
1441 | + if (ret != 0) { | ||
1442 | + dev_dbg(rsz_device, "Unexpected exit from " | ||
1443 | + "wait_for_completion_interruptible\n"); | ||
1444 | + wait_for_completion(&device_config->compl_isr); | ||
1445 | + } | ||
1446 | + | ||
1447 | + if (multipass->active) { | ||
1448 | + rsz_set_multipass(multipass, rsz_conf_chan); | ||
1449 | + goto mult; | ||
1450 | + } | ||
1451 | + | ||
1452 | + if (fh->isp_addr_read) { | ||
1453 | + ispmmu_vunmap(fh->isp_addr_read); | ||
1454 | + fh->isp_addr_read = 0; | ||
1455 | + } | ||
1456 | + if (fh->isp_addr_write) { | ||
1457 | + ispmmu_vunmap(fh->isp_addr_write); | ||
1458 | + fh->isp_addr_write = 0; | ||
1459 | + } | ||
1460 | + | ||
1461 | + rsz_conf_chan->status = CHANNEL_FREE; | ||
1462 | + q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT; | ||
1463 | + q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT; | ||
1464 | + rsz_conf_chan->register_config.rsz_sdr_outadd = 0; | ||
1465 | + rsz_conf_chan->register_config.rsz_sdr_inadd = 0; | ||
1466 | + | ||
1467 | + /* Unmap and free the DMA memory allocated for buffers */ | ||
1468 | + videobuf_dma_unmap(q, videobuf_to_dma( | ||
1469 | + q->bufs[rsz_conf_chan->input_buf_index])); | ||
1470 | + videobuf_dma_unmap(q, videobuf_to_dma( | ||
1471 | + q->bufs[rsz_conf_chan->output_buf_index])); | ||
1472 | + videobuf_dma_free(videobuf_to_dma( | ||
1473 | + q->bufs[rsz_conf_chan->input_buf_index])); | ||
1474 | + videobuf_dma_free(videobuf_to_dma( | ||
1475 | + q->bufs[rsz_conf_chan->output_buf_index])); | ||
1476 | + | ||
1477 | + isp_unset_callback(CBK_RESZ_DONE); | ||
1478 | + | ||
1479 | + return 0; | ||
1480 | +err_einval: | ||
1481 | + return -EINVAL; | ||
1482 | +} | ||
1483 | + | ||
1484 | +/** | ||
1485 | + * rsz_set_multipass - Set resizer multipass | ||
1486 | + * @rsz_conf_chan: Structure containing channel configuration | ||
1487 | + * | ||
1488 | + * Returns always 0 | ||
1489 | + **/ | ||
1490 | +static int rsz_set_multipass(struct rsz_mult *multipass, | ||
1491 | + struct channel_config *rsz_conf_chan) | ||
1492 | +{ | ||
1493 | + multipass->in_hsize = multipass->out_hsize; | ||
1494 | + multipass->in_vsize = multipass->out_vsize; | ||
1495 | + multipass->out_hsize = multipass->end_hsize; | ||
1496 | + multipass->out_vsize = multipass->end_vsize; | ||
1497 | + | ||
1498 | + multipass->out_pitch = (multipass->inptyp ? multipass->out_hsize | ||
1499 | + : (multipass->out_hsize * 2)); | ||
1500 | + multipass->in_pitch = (multipass->inptyp ? multipass->in_hsize | ||
1501 | + : (multipass->in_hsize * 2)); | ||
1502 | + | ||
1503 | + rsz_set_ratio(multipass, rsz_conf_chan); | ||
1504 | + rsz_config_ratio(multipass, rsz_conf_chan); | ||
1505 | + rsz_hardware_setup(rsz_conf_chan); | ||
1506 | + return 0; | ||
1507 | +} | ||
1508 | + | ||
1509 | +/** | ||
1510 | + * rsz_copy_data - Copy data | ||
1511 | + * @params: Structure containing the Resizer Wrapper parameters | ||
1512 | + * | ||
1513 | + * Copy data | ||
1514 | + **/ | ||
1515 | +static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params) | ||
1516 | +{ | ||
1517 | + int i; | ||
1518 | + multipass->in_hsize = params->in_hsize; | ||
1519 | + multipass->in_vsize = params->in_vsize; | ||
1520 | + multipass->out_hsize = params->out_hsize; | ||
1521 | + multipass->out_vsize = params->out_vsize; | ||
1522 | + multipass->end_hsize = params->out_hsize; | ||
1523 | + multipass->end_vsize = params->out_vsize; | ||
1524 | + multipass->in_pitch = params->in_pitch; | ||
1525 | + multipass->out_pitch = params->out_pitch; | ||
1526 | + multipass->hstph = params->hstph; | ||
1527 | + multipass->vstph = params->vstph; | ||
1528 | + multipass->inptyp = params->inptyp; | ||
1529 | + multipass->pix_fmt = params->pix_fmt; | ||
1530 | + multipass->cbilin = params->cbilin; | ||
1531 | + | ||
1532 | + for (i = 0; i < 32; i++) { | ||
1533 | + multipass->tap4filt_coeffs[i] = params->tap4filt_coeffs[i]; | ||
1534 | + multipass->tap7filt_coeffs[i] = params->tap7filt_coeffs[i]; | ||
1535 | + } | ||
1536 | +} | ||
1537 | + | ||
1538 | +/** | ||
1539 | + * rsz_set_params - Set parameters for resizer wrapper | ||
1540 | + * @params: Structure containing the Resizer Wrapper parameters | ||
1541 | + * @rsz_conf_chan: Structure containing channel configuration | ||
1542 | + * | ||
1543 | + * Used to set the parameters of the Resizer hardware, including input and | ||
1544 | + * output image size, horizontal and vertical poly-phase filter coefficients, | ||
1545 | + * luma enchancement filter coefficients, etc. | ||
1546 | + **/ | ||
1547 | +static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params, | ||
1548 | + struct channel_config *rsz_conf_chan) | ||
1549 | +{ | ||
1550 | + int mul = 1; | ||
1551 | + if ((params->yenh_params.type < 0) || (params->yenh_params.type > 2)) { | ||
1552 | + dev_err(rsz_device, "rsz_set_params: Wrong yenh type\n"); | ||
1553 | + return -EINVAL; | ||
1554 | + } | ||
1555 | + if ((params->in_vsize <= 0) || (params->in_hsize <= 0) || | ||
1556 | + (params->out_vsize <= 0) || (params->out_hsize <= 0) || | ||
1557 | + (params->in_pitch <= 0) || (params->out_pitch <= 0)) { | ||
1558 | + dev_err(rsz_device, "rsz_set_params: Invalid size params\n"); | ||
1559 | + return -EINVAL; | ||
1560 | + } | ||
1561 | + if ((params->inptyp != RSZ_INTYPE_YCBCR422_16BIT) && | ||
1562 | + (params->inptyp != RSZ_INTYPE_PLANAR_8BIT)) { | ||
1563 | + dev_err(rsz_device, "rsz_set_params: Invalid input type\n"); | ||
1564 | + return -EINVAL; | ||
1565 | + } | ||
1566 | + if ((params->pix_fmt != RSZ_PIX_FMT_UYVY) && | ||
1567 | + (params->pix_fmt != RSZ_PIX_FMT_YUYV)) { | ||
1568 | + dev_err(rsz_device, "rsz_set_params: Invalid pixel format\n"); | ||
1569 | + return -EINVAL; | ||
1570 | + } | ||
1571 | + if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT) | ||
1572 | + mul = 2; | ||
1573 | + else | ||
1574 | + mul = 1; | ||
1575 | + if (params->in_pitch < (params->in_hsize * mul)) { | ||
1576 | + dev_err(rsz_device, "rsz_set_params: Pitch is incorrect\n"); | ||
1577 | + return -EINVAL; | ||
1578 | + } | ||
1579 | + if (params->out_pitch < (params->out_hsize * mul)) { | ||
1580 | + dev_err(rsz_device, "rsz_set_params: Out pitch cannot be less" | ||
1581 | + " than out hsize\n"); | ||
1582 | + return -EINVAL; | ||
1583 | + } | ||
1584 | + /* Output H size should be even */ | ||
1585 | + if ((params->out_hsize % PIXEL_EVEN) != 0) { | ||
1586 | + dev_err(rsz_device, "rsz_set_params: Output H size should" | ||
1587 | + " be even\n"); | ||
1588 | + return -EINVAL; | ||
1589 | + } | ||
1590 | + if (params->horz_starting_pixel < 0) { | ||
1591 | + dev_err(rsz_device, "rsz_set_params: Horz start pixel cannot" | ||
1592 | + " be less than zero\n"); | ||
1593 | + return -EINVAL; | ||
1594 | + } | ||
1595 | + | ||
1596 | + rsz_copy_data(multipass, params); | ||
1597 | + if (0 != rsz_set_ratio(multipass, rsz_conf_chan)) | ||
1598 | + goto err_einval; | ||
1599 | + | ||
1600 | + if (params->yenh_params.type) { | ||
1601 | + if ((multipass->num_htap && multipass->out_hsize > | ||
1602 | + 1280) || | ||
1603 | + (!multipass->num_htap && multipass->out_hsize > | ||
1604 | + 640)) | ||
1605 | + goto err_einval; | ||
1606 | + } | ||
1607 | + | ||
1608 | + if (INPUT_RAM) | ||
1609 | + params->vert_starting_pixel = 0; | ||
1610 | + | ||
1611 | + rsz_conf_chan->register_config.rsz_in_start = | ||
1612 | + (params->vert_starting_pixel | ||
1613 | + << ISPRSZ_IN_SIZE_VERT_SHIFT) | ||
1614 | + & ISPRSZ_IN_SIZE_VERT_MASK; | ||
1615 | + | ||
1616 | + if (params->inptyp == RSZ_INTYPE_PLANAR_8BIT) { | ||
1617 | + if (params->horz_starting_pixel > MAX_HORZ_PIXEL_8BIT) | ||
1618 | + goto err_einval; | ||
1619 | + } | ||
1620 | + if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT) { | ||
1621 | + if (params->horz_starting_pixel > MAX_HORZ_PIXEL_16BIT) | ||
1622 | + goto err_einval; | ||
1623 | + } | ||
1624 | + | ||
1625 | + rsz_conf_chan->register_config.rsz_in_start |= | ||
1626 | + params->horz_starting_pixel | ||
1627 | + & ISPRSZ_IN_START_HORZ_ST_MASK; | ||
1628 | + | ||
1629 | + rsz_conf_chan->register_config.rsz_yehn = | ||
1630 | + (params->yenh_params.type | ||
1631 | + << ISPRSZ_YENH_ALGO_SHIFT) | ||
1632 | + & ISPRSZ_YENH_ALGO_MASK; | ||
1633 | + | ||
1634 | + if (params->yenh_params.type) { | ||
1635 | + rsz_conf_chan->register_config.rsz_yehn |= | ||
1636 | + params->yenh_params.core | ||
1637 | + & ISPRSZ_YENH_CORE_MASK; | ||
1638 | + | ||
1639 | + rsz_conf_chan->register_config.rsz_yehn |= | ||
1640 | + (params->yenh_params.gain | ||
1641 | + << ISPRSZ_YENH_GAIN_SHIFT) | ||
1642 | + & ISPRSZ_YENH_GAIN_MASK; | ||
1643 | + | ||
1644 | + rsz_conf_chan->register_config.rsz_yehn |= | ||
1645 | + (params->yenh_params.slop | ||
1646 | + << ISPRSZ_YENH_SLOP_SHIFT) | ||
1647 | + & ISPRSZ_YENH_SLOP_MASK; | ||
1648 | + } | ||
1649 | + | ||
1650 | + rsz_config_ratio(multipass, rsz_conf_chan); | ||
1651 | + | ||
1652 | + rsz_conf_chan->config_state = STATE_CONFIGURED; | ||
1653 | + | ||
1654 | + return 0; | ||
1655 | +err_einval: | ||
1656 | + return -EINVAL; | ||
1657 | +} | ||
1658 | + | ||
1659 | +/** | ||
1660 | + * rsz_set_ratio - Set ratio | ||
1661 | + * @rsz_conf_chan: Structure containing channel configuration | ||
1662 | + * | ||
1663 | + * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is | ||
1664 | + * being requested, or other ratio configuration value is out of bounds | ||
1665 | + **/ | ||
1666 | +static int rsz_set_ratio(struct rsz_mult *multipass, | ||
1667 | + struct channel_config *rsz_conf_chan) | ||
1668 | +{ | ||
1669 | + int alignment = 0; | ||
1670 | + | ||
1671 | + rsz_conf_chan->register_config.rsz_cnt = 0; | ||
1672 | + | ||
1673 | + if ((multipass->out_hsize > MAX_IMAGE_WIDTH) || | ||
1674 | + (multipass->out_vsize > MAX_IMAGE_WIDTH)) { | ||
1675 | + dev_err(rsz_device, "Invalid output size!"); | ||
1676 | + goto err_einval; | ||
1677 | + } | ||
1678 | + if (multipass->cbilin) { | ||
1679 | + rsz_conf_chan->register_config.rsz_cnt = | ||
1680 | + BITSET(rsz_conf_chan->register_config.rsz_cnt, | ||
1681 | + SET_BIT_CBLIN); | ||
1682 | + } | ||
1683 | + if (INPUT_RAM) { | ||
1684 | + rsz_conf_chan->register_config.rsz_cnt = | ||
1685 | + BITSET(rsz_conf_chan->register_config.rsz_cnt, | ||
1686 | + SET_BIT_INPUTRAM); | ||
1687 | + } | ||
1688 | + if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT) { | ||
1689 | + rsz_conf_chan->register_config.rsz_cnt = | ||
1690 | + BITSET(rsz_conf_chan->register_config.rsz_cnt, | ||
1691 | + SET_BIT_INPTYP); | ||
1692 | + } else { | ||
1693 | + rsz_conf_chan->register_config.rsz_cnt = | ||
1694 | + BITRESET(rsz_conf_chan->register_config. | ||
1695 | + rsz_cnt, SET_BIT_INPTYP); | ||
1696 | + | ||
1697 | + if (multipass->pix_fmt == RSZ_PIX_FMT_UYVY) { | ||
1698 | + rsz_conf_chan->register_config.rsz_cnt = | ||
1699 | + BITRESET(rsz_conf_chan->register_config. | ||
1700 | + rsz_cnt, SET_BIT_YCPOS); | ||
1701 | + } else if (multipass->pix_fmt == RSZ_PIX_FMT_YUYV) { | ||
1702 | + rsz_conf_chan->register_config.rsz_cnt = | ||
1703 | + BITSET(rsz_conf_chan->register_config. | ||
1704 | + rsz_cnt, SET_BIT_YCPOS); | ||
1705 | + } | ||
1706 | + | ||
1707 | + } | ||
1708 | + multipass->vrsz = | ||
1709 | + (multipass->in_vsize * RATIO_MULTIPLIER) / multipass->out_vsize; | ||
1710 | + multipass->hrsz = | ||
1711 | + (multipass->in_hsize * RATIO_MULTIPLIER) / multipass->out_hsize; | ||
1712 | + if (UP_RSZ_RATIO > multipass->vrsz || UP_RSZ_RATIO > multipass->hrsz) { | ||
1713 | + dev_err(rsz_device, "Upscaling ratio not supported!"); | ||
1714 | + goto err_einval; | ||
1715 | + } | ||
1716 | + multipass->vrsz = (multipass->in_vsize - NUM_D2TAPS) * RATIO_MULTIPLIER | ||
1717 | + / (multipass->out_vsize - 1); | ||
1718 | + multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS) | ||
1719 | + * RATIO_MULTIPLIER) / | ||
1720 | + (multipass->out_hsize - 1); | ||
1721 | + | ||
1722 | + if (multipass->hrsz <= 512) { | ||
1723 | + multipass->hrsz = (multipass->in_hsize - NUM_TAPS) | ||
1724 | + * RATIO_MULTIPLIER | ||
1725 | + / (multipass->out_hsize - 1); | ||
1726 | + if (multipass->hrsz < 64) | ||
1727 | + multipass->hrsz = 64; | ||
1728 | + if (multipass->hrsz > 512) | ||
1729 | + multipass->hrsz = 512; | ||
1730 | + if (multipass->hstph > NUM_PHASES) | ||
1731 | + goto err_einval; | ||
1732 | + multipass->num_htap = 1; | ||
1733 | + } else if (multipass->hrsz >= 513 && multipass->hrsz <= 1024) { | ||
1734 | + if (multipass->hstph > NUM_D2PH) | ||
1735 | + goto err_einval; | ||
1736 | + multipass->num_htap = 0; | ||
1737 | + } | ||
1738 | + | ||
1739 | + if (multipass->vrsz <= 512) { | ||
1740 | + multipass->vrsz = (multipass->in_vsize - NUM_TAPS) | ||
1741 | + * RATIO_MULTIPLIER | ||
1742 | + / (multipass->out_vsize - 1); | ||
1743 | + if (multipass->vrsz < 64) | ||
1744 | + multipass->vrsz = 64; | ||
1745 | + if (multipass->vrsz > 512) | ||
1746 | + multipass->vrsz = 512; | ||
1747 | + if (multipass->vstph > NUM_PHASES) | ||
1748 | + goto err_einval; | ||
1749 | + multipass->num_vtap = 1; | ||
1750 | + } else if (multipass->vrsz >= 513 && multipass->vrsz <= 1024) { | ||
1751 | + if (multipass->vstph > NUM_D2PH) | ||
1752 | + goto err_einval; | ||
1753 | + multipass->num_vtap = 0; | ||
1754 | + } | ||
1755 | + | ||
1756 | + if ((multipass->in_pitch) % ALIGN32) { | ||
1757 | + dev_err(rsz_device, "Invalid input pitch: %d \n", | ||
1758 | + multipass->in_pitch); | ||
1759 | + goto err_einval; | ||
1760 | + } | ||
1761 | + if ((multipass->out_pitch) % ALIGN32) { | ||
1762 | + dev_err(rsz_device, "Invalid output pitch %d \n", | ||
1763 | + multipass->out_pitch); | ||
1764 | + goto err_einval; | ||
1765 | + } | ||
1766 | + | ||
1767 | + if (multipass->vrsz < 256 && | ||
1768 | + (multipass->in_vsize < multipass->out_vsize)) { | ||
1769 | + if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT) | ||
1770 | + alignment = ALIGNMENT; | ||
1771 | + else if (multipass->inptyp == RSZ_INTYPE_YCBCR422_16BIT) | ||
1772 | + alignment = (ALIGNMENT / 2); | ||
1773 | + else | ||
1774 | + dev_err(rsz_device, "Invalid input type\n"); | ||
1775 | + | ||
1776 | + if (!(((multipass->out_hsize % PIXEL_EVEN) == 0) | ||
1777 | + && (multipass->out_hsize % alignment) == 0)) { | ||
1778 | + dev_err(rsz_device, "wrong hsize\n"); | ||
1779 | + goto err_einval; | ||
1780 | + } | ||
1781 | + } | ||
1782 | + if (multipass->hrsz >= 64 && multipass->hrsz <= 1024) { | ||
1783 | + if (multipass->out_hsize > MAX_IMAGE_WIDTH) { | ||
1784 | + dev_err(rsz_device, "wrong width\n"); | ||
1785 | + goto err_einval; | ||
1786 | + } | ||
1787 | + multipass->active = 0; | ||
1788 | + | ||
1789 | + } else if (multipass->hrsz > 1024) { | ||
1790 | + if (multipass->out_hsize > MAX_IMAGE_WIDTH) { | ||
1791 | + dev_err(rsz_device, "wrong width\n"); | ||
1792 | + goto err_einval; | ||
1793 | + } | ||
1794 | + if (multipass->hstph > NUM_D2PH) | ||
1795 | + goto err_einval; | ||
1796 | + multipass->num_htap = 0; | ||
1797 | + multipass->out_hsize = multipass->in_hsize * 256 / 1024; | ||
1798 | + if (multipass->out_hsize % ALIGN32) { | ||
1799 | + multipass->out_hsize += | ||
1800 | + abs((multipass->out_hsize % ALIGN32) - ALIGN32); | ||
1801 | + } | ||
1802 | + multipass->out_pitch = ((multipass->inptyp) ? | ||
1803 | + multipass->out_hsize : | ||
1804 | + (multipass->out_hsize * 2)); | ||
1805 | + multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS) | ||
1806 | + * RATIO_MULTIPLIER) | ||
1807 | + / (multipass->out_hsize - 1); | ||
1808 | + multipass->active = 1; | ||
1809 | + | ||
1810 | + } | ||
1811 | + | ||
1812 | + if (multipass->vrsz > 1024) { | ||
1813 | + if (multipass->out_vsize > MAX_IMAGE_WIDTH_HIGH) { | ||
1814 | + dev_err(rsz_device, "wrong width\n"); | ||
1815 | + goto err_einval; | ||
1816 | + } | ||
1817 | + | ||
1818 | + multipass->out_vsize = multipass->in_vsize * 256 / 1024; | ||
1819 | + multipass->vrsz = ((multipass->in_vsize - NUM_D2TAPS) | ||
1820 | + * RATIO_MULTIPLIER) | ||
1821 | + / (multipass->out_vsize - 1); | ||
1822 | + multipass->active = 1; | ||
1823 | + multipass->num_vtap = 0; | ||
1824 | + | ||
1825 | + } | ||
1826 | + rsz_conf_chan->register_config.rsz_out_size = | ||
1827 | + multipass->out_hsize | ||
1828 | + & ISPRSZ_OUT_SIZE_HORZ_MASK; | ||
1829 | + | ||
1830 | + rsz_conf_chan->register_config.rsz_out_size |= | ||
1831 | + (multipass->out_vsize | ||
1832 | + << ISPRSZ_OUT_SIZE_VERT_SHIFT) | ||
1833 | + & ISPRSZ_OUT_SIZE_VERT_MASK; | ||
1834 | + | ||
1835 | + rsz_conf_chan->register_config.rsz_sdr_inoff = | ||
1836 | + multipass->in_pitch | ||
1837 | + & ISPRSZ_SDR_INOFF_OFFSET_MASK; | ||
1838 | + | ||
1839 | + rsz_conf_chan->register_config.rsz_sdr_outoff = | ||
1840 | + multipass->out_pitch | ||
1841 | + & ISPRSZ_SDR_OUTOFF_OFFSET_MASK; | ||
1842 | + | ||
1843 | + if (multipass->hrsz >= 64 && multipass->hrsz <= 512) { | ||
1844 | + if (multipass->hstph > NUM_PHASES) | ||
1845 | + goto err_einval; | ||
1846 | + } else if (multipass->hrsz >= 64 && multipass->hrsz <= 512) { | ||
1847 | + if (multipass->hstph > NUM_D2PH) | ||
1848 | + goto err_einval; | ||
1849 | + } | ||
1850 | + | ||
1851 | + rsz_conf_chan->register_config.rsz_cnt |= | ||
1852 | + (multipass->hstph | ||
1853 | + << ISPRSZ_CNT_HSTPH_SHIFT) | ||
1854 | + & ISPRSZ_CNT_HSTPH_MASK; | ||
1855 | + | ||
1856 | + if (multipass->vrsz >= 64 && multipass->hrsz <= 512) { | ||
1857 | + if (multipass->vstph > NUM_PHASES) | ||
1858 | + goto err_einval; | ||
1859 | + } else if (multipass->vrsz >= 64 && multipass->vrsz <= 512) { | ||
1860 | + if (multipass->vstph > NUM_D2PH) | ||
1861 | + goto err_einval; | ||
1862 | + } | ||
1863 | + | ||
1864 | + rsz_conf_chan->register_config.rsz_cnt |= | ||
1865 | + (multipass->vstph | ||
1866 | + << ISPRSZ_CNT_VSTPH_SHIFT) | ||
1867 | + & ISPRSZ_CNT_VSTPH_MASK; | ||
1868 | + | ||
1869 | + rsz_conf_chan->register_config.rsz_cnt |= | ||
1870 | + (multipass->hrsz - 1) | ||
1871 | + & ISPRSZ_CNT_HRSZ_MASK; | ||
1872 | + | ||
1873 | + rsz_conf_chan->register_config.rsz_cnt |= | ||
1874 | + ((multipass->vrsz - 1) | ||
1875 | + << ISPRSZ_CNT_VRSZ_SHIFT) | ||
1876 | + & ISPRSZ_CNT_VRSZ_MASK; | ||
1877 | + | ||
1878 | + return 0; | ||
1879 | +err_einval: | ||
1880 | + return -EINVAL; | ||
1881 | +} | ||
1882 | + | ||
1883 | +/** | ||
1884 | + * rsz_config_ratio - Configure ratio | ||
1885 | + * @rsz_conf_chan: Structure containing channel configuration | ||
1886 | + * | ||
1887 | + * Configure ratio | ||
1888 | + **/ | ||
1889 | +static void rsz_config_ratio(struct rsz_mult *multipass, | ||
1890 | + struct channel_config *rsz_conf_chan) | ||
1891 | +{ | ||
1892 | + int hsize; | ||
1893 | + int vsize; | ||
1894 | + int coeffcounter; | ||
1895 | + | ||
1896 | + if (multipass->hrsz <= 512) { | ||
1897 | + hsize = ((32 * multipass->hstph + (multipass->out_hsize - 1) | ||
1898 | + * multipass->hrsz + 16) >> 8) + 7; | ||
1899 | + } else { | ||
1900 | + hsize = ((64 * multipass->hstph + (multipass->out_hsize - 1) | ||
1901 | + * multipass->hrsz + 32) >> 8) + 7; | ||
1902 | + } | ||
1903 | + if (multipass->vrsz <= 512) { | ||
1904 | + vsize = ((32 * multipass->vstph + (multipass->out_vsize - 1) | ||
1905 | + * multipass->vrsz + 16) >> 8) + 4; | ||
1906 | + } else { | ||
1907 | + vsize = ((64 * multipass->vstph + (multipass->out_vsize - 1) | ||
1908 | + * multipass->vrsz + 32) >> 8) + 7; | ||
1909 | + } | ||
1910 | + rsz_conf_chan->register_config.rsz_in_size = hsize; | ||
1911 | + | ||
1912 | + rsz_conf_chan->register_config.rsz_in_size |= | ||
1913 | + ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT) | ||
1914 | + & ISPRSZ_IN_SIZE_VERT_MASK); | ||
1915 | + | ||
1916 | + for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER; | ||
1917 | + coeffcounter++) { | ||
1918 | + if (multipass->num_htap) { | ||
1919 | + rsz_conf_chan->register_config. | ||
1920 | + rsz_coeff_horz[coeffcounter] = | ||
1921 | + (multipass->tap4filt_coeffs[2 | ||
1922 | + * coeffcounter] | ||
1923 | + & ISPRSZ_HFILT10_COEF0_MASK); | ||
1924 | + rsz_conf_chan->register_config. | ||
1925 | + rsz_coeff_horz[coeffcounter] |= | ||
1926 | + ((multipass->tap4filt_coeffs[2 | ||
1927 | + * coeffcounter + 1] | ||
1928 | + << ISPRSZ_HFILT10_COEF1_SHIFT) | ||
1929 | + & ISPRSZ_HFILT10_COEF1_MASK); | ||
1930 | + } else { | ||
1931 | + rsz_conf_chan->register_config. | ||
1932 | + rsz_coeff_horz[coeffcounter] = | ||
1933 | + (multipass->tap7filt_coeffs[2 | ||
1934 | + * coeffcounter] | ||
1935 | + & ISPRSZ_HFILT10_COEF0_MASK); | ||
1936 | + | ||
1937 | + rsz_conf_chan->register_config. | ||
1938 | + rsz_coeff_horz[coeffcounter] |= | ||
1939 | + ((multipass->tap7filt_coeffs[2 | ||
1940 | + * coeffcounter + 1] | ||
1941 | + << ISPRSZ_HFILT10_COEF1_SHIFT) | ||
1942 | + & ISPRSZ_HFILT10_COEF1_MASK); | ||
1943 | + } | ||
1944 | + | ||
1945 | + if (multipass->num_vtap) { | ||
1946 | + rsz_conf_chan->register_config. | ||
1947 | + rsz_coeff_vert[coeffcounter] = | ||
1948 | + (multipass->tap4filt_coeffs[2 | ||
1949 | + * coeffcounter] | ||
1950 | + & ISPRSZ_VFILT10_COEF0_MASK); | ||
1951 | + | ||
1952 | + rsz_conf_chan->register_config. | ||
1953 | + rsz_coeff_vert[coeffcounter] |= | ||
1954 | + ((multipass->tap4filt_coeffs[2 | ||
1955 | + * coeffcounter + 1] | ||
1956 | + << ISPRSZ_VFILT10_COEF1_SHIFT) & | ||
1957 | + ISPRSZ_VFILT10_COEF1_MASK); | ||
1958 | + } else { | ||
1959 | + rsz_conf_chan->register_config. | ||
1960 | + rsz_coeff_vert[coeffcounter] = | ||
1961 | + (multipass->tap7filt_coeffs[2 | ||
1962 | + * coeffcounter] | ||
1963 | + & ISPRSZ_VFILT10_COEF0_MASK); | ||
1964 | + rsz_conf_chan->register_config. | ||
1965 | + rsz_coeff_vert[coeffcounter] |= | ||
1966 | + ((multipass->tap7filt_coeffs[2 | ||
1967 | + * coeffcounter + 1] | ||
1968 | + << ISPRSZ_VFILT10_COEF1_SHIFT) | ||
1969 | + & ISPRSZ_VFILT10_COEF1_MASK); | ||
1970 | + } | ||
1971 | + } | ||
1972 | +} | ||
1973 | + | ||
1974 | +/** | ||
1975 | + * rsz_get_params - Gets the parameter values | ||
1976 | + * @params: Structure containing the Resizer Wrapper parameters | ||
1977 | + * @rsz_conf_chan: Structure containing channel configuration | ||
1978 | + * | ||
1979 | + * Used to get the Resizer hardware settings associated with the | ||
1980 | + * current logical channel represented by fd. | ||
1981 | + **/ | ||
1982 | +static int rsz_get_params(struct rsz_params *params, | ||
1983 | + struct channel_config *rsz_conf_chan) | ||
1984 | +{ | ||
1985 | + int coeffcounter; | ||
1986 | + | ||
1987 | + if (rsz_conf_chan->config_state) { | ||
1988 | + dev_err(rsz_device, "state not configured\n"); | ||
1989 | + return -EINVAL; | ||
1990 | + } | ||
1991 | + | ||
1992 | + params->in_hsize = rsz_conf_chan->register_config.rsz_in_size | ||
1993 | + & ISPRSZ_IN_SIZE_HORZ_MASK; | ||
1994 | + params->in_vsize = (rsz_conf_chan->register_config.rsz_in_size | ||
1995 | + & ISPRSZ_IN_SIZE_VERT_MASK) | ||
1996 | + >> ISPRSZ_IN_SIZE_VERT_SHIFT; | ||
1997 | + | ||
1998 | + params->in_pitch = rsz_conf_chan->register_config.rsz_sdr_inoff | ||
1999 | + & ISPRSZ_SDR_INOFF_OFFSET_MASK; | ||
2000 | + | ||
2001 | + params->out_hsize = rsz_conf_chan->register_config.rsz_out_size | ||
2002 | + & ISPRSZ_OUT_SIZE_HORZ_MASK; | ||
2003 | + | ||
2004 | + params->out_vsize = (rsz_conf_chan->register_config.rsz_out_size | ||
2005 | + & ISPRSZ_OUT_SIZE_VERT_MASK) | ||
2006 | + >> ISPRSZ_OUT_SIZE_VERT_SHIFT; | ||
2007 | + | ||
2008 | + params->out_pitch = rsz_conf_chan->register_config.rsz_sdr_outoff | ||
2009 | + & ISPRSZ_SDR_OUTOFF_OFFSET_MASK; | ||
2010 | + | ||
2011 | + params->cbilin = (rsz_conf_chan->register_config.rsz_cnt | ||
2012 | + & SET_BIT_CBLIN) >> SET_BIT_CBLIN; | ||
2013 | + | ||
2014 | + params->inptyp = (rsz_conf_chan->register_config.rsz_cnt | ||
2015 | + & ISPRSZ_CNT_INPTYP_MASK) | ||
2016 | + >> SET_BIT_INPTYP; | ||
2017 | + params->horz_starting_pixel = ((rsz_conf_chan->register_config. | ||
2018 | + rsz_in_start | ||
2019 | + & ISPRSZ_IN_START_HORZ_ST_MASK)); | ||
2020 | + params->vert_starting_pixel = ((rsz_conf_chan->register_config. | ||
2021 | + rsz_in_start | ||
2022 | + & ISPRSZ_IN_START_VERT_ST_MASK) | ||
2023 | + >> ISPRSZ_IN_START_VERT_ST_SHIFT); | ||
2024 | + | ||
2025 | + params->hstph = ((rsz_conf_chan->register_config.rsz_cnt | ||
2026 | + & ISPRSZ_CNT_HSTPH_MASK | ||
2027 | + >> ISPRSZ_CNT_HSTPH_SHIFT)); | ||
2028 | + params->vstph = ((rsz_conf_chan->register_config.rsz_cnt | ||
2029 | + & ISPRSZ_CNT_VSTPH_MASK | ||
2030 | + >> ISPRSZ_CNT_VSTPH_SHIFT)); | ||
2031 | + | ||
2032 | + for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER; | ||
2033 | + coeffcounter++) { | ||
2034 | + params->tap4filt_coeffs[2 * coeffcounter] = | ||
2035 | + rsz_conf_chan->register_config. | ||
2036 | + rsz_coeff_horz[coeffcounter] | ||
2037 | + & ISPRSZ_HFILT10_COEF0_MASK; | ||
2038 | + | ||
2039 | + params->tap4filt_coeffs[2 * coeffcounter + 1] = | ||
2040 | + (rsz_conf_chan->register_config. | ||
2041 | + rsz_coeff_horz[coeffcounter] | ||
2042 | + & ISPRSZ_HFILT10_COEF1_MASK) | ||
2043 | + >> ISPRSZ_HFILT10_COEF1_SHIFT; | ||
2044 | + | ||
2045 | + params->tap7filt_coeffs[2 * coeffcounter] = | ||
2046 | + rsz_conf_chan->register_config. | ||
2047 | + rsz_coeff_vert[coeffcounter] | ||
2048 | + & ISPRSZ_VFILT10_COEF0_MASK; | ||
2049 | + | ||
2050 | + params->tap7filt_coeffs[2 * coeffcounter + 1] = | ||
2051 | + (rsz_conf_chan->register_config. | ||
2052 | + rsz_coeff_vert[coeffcounter] | ||
2053 | + & ISPRSZ_VFILT10_COEF1_MASK) | ||
2054 | + >> ISPRSZ_VFILT10_COEF1_SHIFT; | ||
2055 | + | ||
2056 | + } | ||
2057 | + | ||
2058 | + params->yenh_params.type = (rsz_conf_chan->register_config.rsz_yehn | ||
2059 | + & ISPRSZ_YENH_ALGO_MASK) | ||
2060 | + >> ISPRSZ_YENH_ALGO_SHIFT; | ||
2061 | + | ||
2062 | + params->yenh_params.core = rsz_conf_chan->register_config.rsz_yehn | ||
2063 | + & ISPRSZ_YENH_CORE_MASK; | ||
2064 | + | ||
2065 | + params->yenh_params.gain = (rsz_conf_chan->register_config.rsz_yehn | ||
2066 | + & ISPRSZ_YENH_GAIN_MASK) | ||
2067 | + >> ISPRSZ_YENH_GAIN_SHIFT; | ||
2068 | + | ||
2069 | + params->yenh_params.slop = (rsz_conf_chan->register_config.rsz_yehn | ||
2070 | + & ISPRSZ_YENH_SLOP_MASK) | ||
2071 | + >> ISPRSZ_YENH_SLOP_SHIFT; | ||
2072 | + | ||
2073 | + params->pix_fmt = ((rsz_conf_chan->register_config.rsz_cnt | ||
2074 | + & ISPRSZ_CNT_PIXFMT_MASK) | ||
2075 | + >> SET_BIT_YCPOS); | ||
2076 | + | ||
2077 | + if (params->pix_fmt) | ||
2078 | + params->pix_fmt = RSZ_PIX_FMT_UYVY; | ||
2079 | + else | ||
2080 | + params->pix_fmt = RSZ_PIX_FMT_YUYV; | ||
2081 | + | ||
2082 | + return 0; | ||
2083 | +} | ||
2084 | + | ||
2085 | +/** | ||
2086 | + * rsz_calculate_crop - Calculate Crop values | ||
2087 | + * @rsz_conf_chan: Structure containing channel configuration | ||
2088 | + * @cropsize: Structure containing crop parameters | ||
2089 | + * | ||
2090 | + * Calculate Crop values | ||
2091 | + **/ | ||
2092 | +static void rsz_calculate_crop(struct channel_config *rsz_conf_chan, | ||
2093 | + struct rsz_cropsize *cropsize) | ||
2094 | +{ | ||
2095 | + int luma_enable; | ||
2096 | + | ||
2097 | + cropsize->hcrop = 0; | ||
2098 | + cropsize->vcrop = 0; | ||
2099 | + | ||
2100 | + luma_enable = (rsz_conf_chan->register_config.rsz_yehn | ||
2101 | + & ISPRSZ_YENH_ALGO_MASK) | ||
2102 | + >> ISPRSZ_YENH_ALGO_SHIFT; | ||
2103 | + | ||
2104 | + if (luma_enable) | ||
2105 | + cropsize->hcrop += 2; | ||
2106 | +} | ||
2107 | + | ||
2108 | +/** | ||
2109 | + * rsz_vbq_release - Videobuffer queue release | ||
2110 | + * @q: Structure containing the videobuffer queue file handle, and device | ||
2111 | + * structure which contains the actual configuration. | ||
2112 | + * @vb: Structure containing the videobuffer used for resizer processing. | ||
2113 | + **/ | ||
2114 | +static void rsz_vbq_release(struct videobuf_queue *q, | ||
2115 | + struct videobuf_buffer *vb) | ||
2116 | +{ | ||
2117 | + int i; | ||
2118 | + struct rsz_fh *fh = q->priv_data; | ||
2119 | + | ||
2120 | + for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
2121 | + struct videobuf_dmabuf *dma = NULL; | ||
2122 | + if (!q->bufs[i]) | ||
2123 | + continue; | ||
2124 | + if (q->bufs[i]->memory != V4L2_MEMORY_MMAP) | ||
2125 | + continue; | ||
2126 | + dma = videobuf_to_dma(q->bufs[i]); | ||
2127 | + videobuf_dma_unmap(q, dma); | ||
2128 | + videobuf_dma_free(dma); | ||
2129 | + } | ||
2130 | + | ||
2131 | + ispmmu_vunmap(fh->isp_addr_read); | ||
2132 | + ispmmu_vunmap(fh->isp_addr_write); | ||
2133 | + fh->isp_addr_read = 0; | ||
2134 | + fh->isp_addr_write = 0; | ||
2135 | + spin_lock(&fh->vbq_lock); | ||
2136 | + vb->state = VIDEOBUF_NEEDS_INIT; | ||
2137 | + spin_unlock(&fh->vbq_lock); | ||
2138 | + | ||
2139 | +} | ||
2140 | + | ||
2141 | +/** | ||
2142 | + * rsz_vbq_setup - Sets up the videobuffer size and validates count. | ||
2143 | + * @q: Structure containing the videobuffer queue file handle, and device | ||
2144 | + * structure which contains the actual configuration. | ||
2145 | + * @cnt: Number of buffers requested | ||
2146 | + * @size: Size in bytes of the buffer used for previewing | ||
2147 | + * | ||
2148 | + * Always returns 0. | ||
2149 | + **/ | ||
2150 | +static int rsz_vbq_setup(struct videobuf_queue *q, unsigned int *cnt, | ||
2151 | + unsigned int *size) | ||
2152 | +{ | ||
2153 | + struct rsz_fh *fh = q->priv_data; | ||
2154 | + struct rsz_mult *multipass = fh->multipass; | ||
2155 | + u32 insize, outsize; | ||
2156 | + | ||
2157 | + spin_lock(&fh->vbq_lock); | ||
2158 | + if (*cnt <= 0) | ||
2159 | + *cnt = VIDEO_MAX_FRAME; | ||
2160 | + | ||
2161 | + if (*cnt > VIDEO_MAX_FRAME) | ||
2162 | + *cnt = VIDEO_MAX_FRAME; | ||
2163 | + | ||
2164 | + outsize = multipass->out_pitch * multipass->out_vsize; | ||
2165 | + insize = multipass->in_pitch * multipass->in_vsize; | ||
2166 | + if (*cnt == 1 && (outsize > insize)) { | ||
2167 | + dev_err(rsz_device, "2 buffers are required for Upscaling " | ||
2168 | + "mode\n"); | ||
2169 | + goto err_einval; | ||
2170 | + } | ||
2171 | + if (!fh->params->in_hsize || !fh->params->in_vsize) { | ||
2172 | + dev_err(rsz_device, "Can't setup buffer size\n"); | ||
2173 | + goto err_einval; | ||
2174 | + } else { | ||
2175 | + if (outsize > insize) | ||
2176 | + *size = outsize; | ||
2177 | + else | ||
2178 | + *size = insize; | ||
2179 | + | ||
2180 | + fh->rsz_bufsize = *size; | ||
2181 | + } | ||
2182 | + spin_unlock(&fh->vbq_lock); | ||
2183 | + | ||
2184 | + return 0; | ||
2185 | +err_einval: | ||
2186 | + spin_unlock(&fh->vbq_lock); | ||
2187 | + return -EINVAL; | ||
2188 | +} | ||
2189 | + | ||
2190 | +/** | ||
2191 | + * rsz_vbq_prepare - Videobuffer is prepared and mmapped. | ||
2192 | + * @q: Structure containing the videobuffer queue file handle, and device | ||
2193 | + * structure which contains the actual configuration. | ||
2194 | + * @vb: Structure containing the videobuffer used for resizer processing. | ||
2195 | + * @field: Type of field to set in videobuffer device. | ||
2196 | + * | ||
2197 | + * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or | ||
2198 | + * -EIO if the ISP MMU mapping fails | ||
2199 | + **/ | ||
2200 | +static int rsz_vbq_prepare(struct videobuf_queue *q, | ||
2201 | + struct videobuf_buffer *vb, | ||
2202 | + enum v4l2_field field) | ||
2203 | +{ | ||
2204 | + struct rsz_fh *fh = q->priv_data; | ||
2205 | + struct channel_config *rsz_conf_chan = fh->config; | ||
2206 | + struct rsz_mult *multipass = fh->multipass; | ||
2207 | + int err = 0; | ||
2208 | + unsigned int isp_addr, insize, outsize; | ||
2209 | + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); | ||
2210 | + | ||
2211 | + spin_lock(&fh->vbq_lock); | ||
2212 | + if (vb->baddr) { | ||
2213 | + vb->size = fh->rsz_bufsize; | ||
2214 | + vb->bsize = fh->rsz_bufsize; | ||
2215 | + } else { | ||
2216 | + spin_unlock(&fh->vbq_lock); | ||
2217 | + dev_err(rsz_device, "No user buffer allocated\n"); | ||
2218 | + goto out; | ||
2219 | + } | ||
2220 | + if (vb->i) { | ||
2221 | + vb->width = fh->params->out_hsize; | ||
2222 | + vb->height = fh->params->out_vsize; | ||
2223 | + } else { | ||
2224 | + vb->width = fh->params->in_hsize; | ||
2225 | + vb->height = fh->params->in_vsize; | ||
2226 | + } | ||
2227 | + | ||
2228 | + vb->field = field; | ||
2229 | + spin_unlock(&fh->vbq_lock); | ||
2230 | + | ||
2231 | + if (vb->state == VIDEOBUF_NEEDS_INIT) { | ||
2232 | + err = videobuf_iolock(q, vb, NULL); | ||
2233 | + if (!err) { | ||
2234 | + isp_addr = ispmmu_vmap(dma->sglist, dma->sglen); | ||
2235 | + if (!isp_addr) | ||
2236 | + err = -EIO; | ||
2237 | + else { | ||
2238 | + if (vb->i) { | ||
2239 | + rsz_conf_chan->register_config. | ||
2240 | + rsz_sdr_outadd | ||
2241 | + = isp_addr; | ||
2242 | + fh->isp_addr_write = isp_addr; | ||
2243 | + rsz_conf_chan->output_buf_index = vb->i; | ||
2244 | + } else { | ||
2245 | + rsz_conf_chan->register_config. | ||
2246 | + rsz_sdr_inadd | ||
2247 | + = isp_addr; | ||
2248 | + rsz_conf_chan->input_buf_index = vb->i; | ||
2249 | + outsize = multipass->out_pitch * | ||
2250 | + multipass->out_vsize; | ||
2251 | + insize = multipass->in_pitch * | ||
2252 | + multipass->in_vsize; | ||
2253 | + if (outsize < insize) { | ||
2254 | + rsz_conf_chan->register_config. | ||
2255 | + rsz_sdr_outadd | ||
2256 | + = isp_addr; | ||
2257 | + rsz_conf_chan-> | ||
2258 | + output_buf_index = | ||
2259 | + vb->i; | ||
2260 | + } | ||
2261 | + | ||
2262 | + fh->isp_addr_read = isp_addr; | ||
2263 | + } | ||
2264 | + } | ||
2265 | + } | ||
2266 | + | ||
2267 | + } | ||
2268 | + | ||
2269 | + if (!err) { | ||
2270 | + spin_lock(&fh->vbq_lock); | ||
2271 | + vb->state = VIDEOBUF_PREPARED; | ||
2272 | + spin_unlock(&fh->vbq_lock); | ||
2273 | + flush_cache_user_range(NULL, vb->baddr, (vb->baddr | ||
2274 | + + vb->bsize)); | ||
2275 | + } else | ||
2276 | + rsz_vbq_release(q, vb); | ||
2277 | + | ||
2278 | +out: | ||
2279 | + return err; | ||
2280 | +} | ||
2281 | + | ||
2282 | +static void rsz_vbq_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
2283 | +{ | ||
2284 | + return; | ||
2285 | +} | ||
2286 | + | ||
2287 | +/** | ||
2288 | + * rsz_open - Initializes and opens the Resizer Wrapper | ||
2289 | + * @inode: Inode structure associated with the Resizer Wrapper | ||
2290 | + * @filp: File structure associated with the Resizer Wrapper | ||
2291 | + * | ||
2292 | + * Returns 0 if successful, -EBUSY if its already opened or the ISP module is | ||
2293 | + * not available, or -ENOMEM if its unable to allocate the device in kernel | ||
2294 | + * space memory. | ||
2295 | + **/ | ||
2296 | +static int rsz_open(struct inode *inode, struct file *filp) | ||
2297 | +{ | ||
2298 | + int ret = 0; | ||
2299 | + struct channel_config *rsz_conf_chan; | ||
2300 | + struct rsz_fh *fh; | ||
2301 | + struct device_params *device = device_config; | ||
2302 | + struct rsz_params *params; | ||
2303 | + struct rsz_mult *multipass; | ||
2304 | + | ||
2305 | + if ((filp->f_flags & O_NONBLOCK) == O_NONBLOCK) { | ||
2306 | + printk(KERN_DEBUG "omap-resizer: Device is opened in " | ||
2307 | + "non blocking mode\n"); | ||
2308 | + } else { | ||
2309 | + printk(KERN_DEBUG "omap-resizer: Device is opened in blocking " | ||
2310 | + "mode\n"); | ||
2311 | + } | ||
2312 | + fh = kzalloc(sizeof(struct rsz_fh), GFP_KERNEL); | ||
2313 | + if (NULL == fh) | ||
2314 | + return -ENOMEM; | ||
2315 | + | ||
2316 | + isp_get(); | ||
2317 | + | ||
2318 | + rsz_conf_chan = kzalloc(sizeof(struct channel_config), GFP_KERNEL); | ||
2319 | + if (rsz_conf_chan == NULL) { | ||
2320 | + dev_err(rsz_device, "\n cannot allocate memory to config"); | ||
2321 | + ret = -ENOMEM; | ||
2322 | + goto err_enomem0; | ||
2323 | + } | ||
2324 | + params = kzalloc(sizeof(struct rsz_params), GFP_KERNEL); | ||
2325 | + if (params == NULL) { | ||
2326 | + dev_err(rsz_device, "\n cannot allocate memory to params"); | ||
2327 | + ret = -ENOMEM; | ||
2328 | + goto err_enomem1; | ||
2329 | + } | ||
2330 | + multipass = kzalloc(sizeof(struct rsz_mult), GFP_KERNEL); | ||
2331 | + if (multipass == NULL) { | ||
2332 | + dev_err(rsz_device, "\n cannot allocate memory to multipass"); | ||
2333 | + ret = -ENOMEM; | ||
2334 | + goto err_enomem2; | ||
2335 | + } | ||
2336 | + | ||
2337 | + fh->multipass = multipass; | ||
2338 | + fh->params = params; | ||
2339 | + fh->config = rsz_conf_chan; | ||
2340 | + | ||
2341 | + if (mutex_lock_interruptible(&device->reszwrap_mutex)) { | ||
2342 | + ret = -EINTR; | ||
2343 | + goto err_enomem2; | ||
2344 | + } | ||
2345 | + device->opened++; | ||
2346 | + mutex_unlock(&device->reszwrap_mutex); | ||
2347 | + | ||
2348 | + rsz_conf_chan->config_state = STATE_NOT_CONFIGURED; | ||
2349 | + rsz_conf_chan->status = CHANNEL_FREE; | ||
2350 | + | ||
2351 | + filp->private_data = fh; | ||
2352 | + fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
2353 | + fh->device = device; | ||
2354 | + | ||
2355 | + videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL, | ||
2356 | + &fh->vbq_lock, fh->type, | ||
2357 | + V4L2_FIELD_NONE, | ||
2358 | + sizeof(struct videobuf_buffer), fh); | ||
2359 | + | ||
2360 | + spin_lock_init(&fh->vbq_lock); | ||
2361 | + mutex_init(&rsz_conf_chan->chanprotection_mutex); | ||
2362 | + | ||
2363 | + return 0; | ||
2364 | +err_enomem2: | ||
2365 | + kfree(params); | ||
2366 | +err_enomem1: | ||
2367 | + kfree(rsz_conf_chan); | ||
2368 | +err_enomem0: | ||
2369 | + kfree(fh); | ||
2370 | + return ret; | ||
2371 | +} | ||
2372 | + | ||
2373 | +/** | ||
2374 | + * rsz_release - Releases Resizer Wrapper and frees up allocated memory | ||
2375 | + * @inode: Inode structure associated with the Resizer Wrapper | ||
2376 | + * @filp: File structure associated with the Resizer Wrapper | ||
2377 | + * | ||
2378 | + * Returns 0 if successful, or -EBUSY if channel is being used. | ||
2379 | + **/ | ||
2380 | +static int rsz_release(struct inode *inode, struct file *filp) | ||
2381 | +{ | ||
2382 | + u32 timeout = 0; | ||
2383 | + struct rsz_fh *fh = filp->private_data; | ||
2384 | + struct channel_config *rsz_conf_chan = fh->config; | ||
2385 | + struct rsz_params *params = fh->params; | ||
2386 | + struct rsz_mult *multipass = fh->multipass; | ||
2387 | + struct videobuf_queue *q = &fh->vbq; | ||
2388 | + | ||
2389 | + while ((rsz_conf_chan->status != CHANNEL_FREE) && (timeout < 20)) { | ||
2390 | + timeout++; | ||
2391 | + schedule(); | ||
2392 | + } | ||
2393 | + if (mutex_lock_interruptible(&device_config->reszwrap_mutex)) | ||
2394 | + return -EINTR; | ||
2395 | + device_config->opened--; | ||
2396 | + mutex_unlock(&device_config->reszwrap_mutex); | ||
2397 | + /* This will Free memory allocated to the buffers, | ||
2398 | + * and flushes the queue | ||
2399 | + */ | ||
2400 | + videobuf_queue_cancel(q); | ||
2401 | + fh->params = NULL; | ||
2402 | + fh->config = NULL; | ||
2403 | + | ||
2404 | + fh->rsz_bufsize = 0; | ||
2405 | + filp->private_data = NULL; | ||
2406 | + | ||
2407 | + kfree(rsz_conf_chan); | ||
2408 | + kfree(params); | ||
2409 | + kfree(multipass); | ||
2410 | + kfree(fh); | ||
2411 | + | ||
2412 | + isp_put(); | ||
2413 | + | ||
2414 | + return 0; | ||
2415 | +} | ||
2416 | + | ||
2417 | +/** | ||
2418 | + * rsz_mmap - Memory maps the Resizer Wrapper module. | ||
2419 | + * @file: File structure associated with the Resizer Wrapper | ||
2420 | + * @vma: Virtual memory area structure. | ||
2421 | + * | ||
2422 | + * Returns 0 if successful, or returned value by the videobuf_mmap_mapper() | ||
2423 | + * function. | ||
2424 | + **/ | ||
2425 | +static int rsz_mmap(struct file *file, struct vm_area_struct *vma) | ||
2426 | +{ | ||
2427 | + struct rsz_fh *fh = file->private_data; | ||
2428 | + | ||
2429 | + return videobuf_mmap_mapper(&fh->vbq, vma); | ||
2430 | +} | ||
2431 | + | ||
2432 | +/** | ||
2433 | + * rsz_ioctl - I/O control function for Resizer Wrapper | ||
2434 | + * @inode: Inode structure associated with the Resizer Wrapper. | ||
2435 | + * @file: File structure associated with the Resizer Wrapper. | ||
2436 | + * @cmd: Type of command to execute. | ||
2437 | + * @arg: Argument to send to requested command. | ||
2438 | + * | ||
2439 | + * Returns 0 if successful, -EBUSY if channel is being used, -1 if bad command | ||
2440 | + * passed or access is denied, -EFAULT if copy_from_user() or copy_to_user() | ||
2441 | + * fails, -EINVAL if parameter validation fails or parameter structure is not | ||
2442 | + * present. | ||
2443 | + **/ | ||
2444 | +static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd, | ||
2445 | + unsigned long arg) | ||
2446 | +{ | ||
2447 | + int ret = 0; | ||
2448 | + struct rsz_fh *fh = file->private_data; | ||
2449 | + struct device_params *device = fh->device; | ||
2450 | + struct channel_config *rsz_conf_chan = fh->config; | ||
2451 | + | ||
2452 | + if ((_IOC_TYPE(cmd) != RSZ_IOC_BASE) | ||
2453 | + || (_IOC_NR(cmd) > RSZ_IOC_MAXNR)) { | ||
2454 | + dev_err(rsz_device, "Bad command value \n"); | ||
2455 | + return -1; | ||
2456 | + } | ||
2457 | + | ||
2458 | + if (_IOC_DIR(cmd) & _IOC_READ) | ||
2459 | + ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); | ||
2460 | + else if (_IOC_DIR(cmd) & _IOC_WRITE) | ||
2461 | + ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); | ||
2462 | + | ||
2463 | + if (ret) { | ||
2464 | + dev_err(rsz_device, "Access denied\n"); | ||
2465 | + return -1; | ||
2466 | + } | ||
2467 | + | ||
2468 | + switch (cmd) { | ||
2469 | + case RSZ_REQBUF: | ||
2470 | + { | ||
2471 | + struct v4l2_requestbuffers req_buf; | ||
2472 | + if (copy_from_user(&req_buf, (struct v4l2_requestbuffers *)arg, | ||
2473 | + sizeof(struct v4l2_requestbuffers))) { | ||
2474 | + return -EFAULT; | ||
2475 | + } | ||
2476 | + if (mutex_lock_interruptible(&rsz_conf_chan-> | ||
2477 | + chanprotection_mutex)) | ||
2478 | + return -EINTR; | ||
2479 | + ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf); | ||
2480 | + mutex_unlock(&rsz_conf_chan->chanprotection_mutex); | ||
2481 | + break; | ||
2482 | + } | ||
2483 | + case RSZ_QUERYBUF: | ||
2484 | + { | ||
2485 | + struct v4l2_buffer buf; | ||
2486 | + if (copy_from_user(&buf, (struct v4l2_buffer *)arg, | ||
2487 | + sizeof(struct v4l2_buffer))) { | ||
2488 | + return -EFAULT; | ||
2489 | + } | ||
2490 | + if (mutex_lock_interruptible(&rsz_conf_chan-> | ||
2491 | + chanprotection_mutex)) | ||
2492 | + return -EINTR; | ||
2493 | + ret = videobuf_querybuf(&fh->vbq, (void *)&buf); | ||
2494 | + mutex_unlock(&rsz_conf_chan->chanprotection_mutex); | ||
2495 | + if (copy_to_user((struct v4l2_buffer *)arg, &buf, | ||
2496 | + sizeof(struct v4l2_buffer))) | ||
2497 | + return -EFAULT; | ||
2498 | + break; | ||
2499 | + } | ||
2500 | + case RSZ_QUEUEBUF: | ||
2501 | + { | ||
2502 | + struct v4l2_buffer buf; | ||
2503 | + if (copy_from_user(&buf, (struct v4l2_buffer *)arg, | ||
2504 | + sizeof(struct v4l2_buffer))) { | ||
2505 | + return -EFAULT; | ||
2506 | + } | ||
2507 | + if (mutex_lock_interruptible(&rsz_conf_chan-> | ||
2508 | + chanprotection_mutex)) | ||
2509 | + return -EINTR; | ||
2510 | + ret = videobuf_qbuf(&fh->vbq, (void *)&buf); | ||
2511 | + mutex_unlock(&rsz_conf_chan->chanprotection_mutex); | ||
2512 | + break; | ||
2513 | + } | ||
2514 | + case RSZ_S_PARAM: | ||
2515 | + { | ||
2516 | + struct rsz_params *params = fh->params; | ||
2517 | + if (copy_from_user(params, (struct rsz_params *)arg, | ||
2518 | + sizeof(struct rsz_params))) { | ||
2519 | + return -EFAULT; | ||
2520 | + } | ||
2521 | + if (mutex_lock_interruptible(&rsz_conf_chan-> | ||
2522 | + chanprotection_mutex)) | ||
2523 | + return -EINTR; | ||
2524 | + ret = rsz_set_params(fh->multipass, params, rsz_conf_chan); | ||
2525 | + mutex_unlock(&rsz_conf_chan->chanprotection_mutex); | ||
2526 | + break; | ||
2527 | + } | ||
2528 | + case RSZ_G_PARAM: | ||
2529 | + ret = rsz_get_params((struct rsz_params *)arg, rsz_conf_chan); | ||
2530 | + break; | ||
2531 | + | ||
2532 | + case RSZ_G_STATUS: | ||
2533 | + { | ||
2534 | + struct rsz_status *status; | ||
2535 | + status = (struct rsz_status *)arg; | ||
2536 | + status->chan_busy = rsz_conf_chan->status; | ||
2537 | + status->hw_busy = ispresizer_busy(); | ||
2538 | + status->src = INPUT_RAM; | ||
2539 | + break; | ||
2540 | + } | ||
2541 | + case RSZ_RESIZE: | ||
2542 | + if (file->f_flags & O_NONBLOCK) { | ||
2543 | + if (ispresizer_busy()) | ||
2544 | + return -EBUSY; | ||
2545 | + else { | ||
2546 | + if (!mutex_trylock(&device->reszwrap_mutex)) | ||
2547 | + return -EBUSY; | ||
2548 | + } | ||
2549 | + } else { | ||
2550 | + if (mutex_lock_interruptible(&device->reszwrap_mutex)) | ||
2551 | + return -EINTR; | ||
2552 | + } | ||
2553 | + ret = rsz_start((int *)arg, fh); | ||
2554 | + mutex_unlock(&device->reszwrap_mutex); | ||
2555 | + break; | ||
2556 | + case RSZ_GET_CROPSIZE: | ||
2557 | + rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg); | ||
2558 | + break; | ||
2559 | + | ||
2560 | + default: | ||
2561 | + dev_err(rsz_device, "resizer_ioctl: Invalid Command Value"); | ||
2562 | + return -EINVAL; | ||
2563 | + } | ||
2564 | + | ||
2565 | + return (long)ret; | ||
2566 | +} | ||
2567 | + | ||
2568 | +static struct file_operations rsz_fops = { | ||
2569 | + .owner = THIS_MODULE, | ||
2570 | + .open = rsz_open, | ||
2571 | + .release = rsz_release, | ||
2572 | + .mmap = rsz_mmap, | ||
2573 | + .unlocked_ioctl = rsz_unlocked_ioctl, | ||
2574 | +}; | ||
2575 | + | ||
2576 | +/** | ||
2577 | + * rsz_isr - Interrupt Service Routine for Resizer wrapper | ||
2578 | + * @status: ISP IRQ0STATUS register value | ||
2579 | + * @arg1: Currently not used | ||
2580 | + * @arg2: Currently not used | ||
2581 | + * | ||
2582 | + * Interrupt Service Routine for Resizer wrapper | ||
2583 | + **/ | ||
2584 | +static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2) | ||
2585 | +{ | ||
2586 | + | ||
2587 | + if ((status & RESZ_DONE) != RESZ_DONE) | ||
2588 | + return; | ||
2589 | + | ||
2590 | + complete(&(device_config->compl_isr)); | ||
2591 | + | ||
2592 | +} | ||
2593 | + | ||
2594 | +/** | ||
2595 | + * resizer_platform_release - Acts when Reference count is zero | ||
2596 | + * @device: Structure containing ISP resizer wrapper global information | ||
2597 | + * | ||
2598 | + * This is called when the reference count goes to zero. | ||
2599 | + **/ | ||
2600 | +static void resizer_platform_release(struct device *device) | ||
2601 | +{ | ||
2602 | +} | ||
2603 | + | ||
2604 | +/** | ||
2605 | + * resizer_probe - Checks for device presence | ||
2606 | + * @device: Structure containing details of the current device. | ||
2607 | + * | ||
2608 | + * Always returns 0. | ||
2609 | + **/ | ||
2610 | +static int __init resizer_probe(struct platform_device *device) | ||
2611 | +{ | ||
2612 | + return 0; | ||
2613 | +} | ||
2614 | + | ||
2615 | +/** | ||
2616 | + * resizer_remove - Handles the removal of the driver | ||
2617 | + * @omap_resizer_device: Structure containing details of the current device. | ||
2618 | + * | ||
2619 | + * Always returns 0. | ||
2620 | + **/ | ||
2621 | +static int resizer_remove(struct platform_device *omap_resizer_device) | ||
2622 | +{ | ||
2623 | + return 0; | ||
2624 | +} | ||
2625 | + | ||
2626 | +static struct class *rsz_class; | ||
2627 | +static struct cdev c_dev; | ||
2628 | +static dev_t dev; | ||
2629 | +static struct platform_device omap_resizer_device = { | ||
2630 | + .name = OMAP_REZR_NAME, | ||
2631 | + .id = 2, | ||
2632 | + .dev = { | ||
2633 | + .release = resizer_platform_release,} | ||
2634 | +}; | ||
2635 | + | ||
2636 | +static struct platform_driver omap_resizer_driver = { | ||
2637 | + .probe = resizer_probe, | ||
2638 | + .remove = resizer_remove, | ||
2639 | + .driver = { | ||
2640 | + .bus = &platform_bus_type, | ||
2641 | + .name = OMAP_REZR_NAME, | ||
2642 | + }, | ||
2643 | +}; | ||
2644 | + | ||
2645 | +/** | ||
2646 | + * omap_rsz_init - Initialization of Resizer Wrapper | ||
2647 | + * | ||
2648 | + * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if | ||
2649 | + * could not register the wrapper as a character device, or other errors if the | ||
2650 | + * device or driver can't register. | ||
2651 | + **/ | ||
2652 | +static int __init omap_rsz_init(void) | ||
2653 | +{ | ||
2654 | + int ret = 0; | ||
2655 | + struct device_params *device; | ||
2656 | + device = kzalloc(sizeof(struct device_params), GFP_KERNEL); | ||
2657 | + if (!device) { | ||
2658 | + dev_err(rsz_device, OMAP_REZR_NAME ": could not allocate " | ||
2659 | + "memory\n"); | ||
2660 | + return -ENOMEM; | ||
2661 | + } | ||
2662 | + | ||
2663 | + ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME); | ||
2664 | + if (ret < 0) { | ||
2665 | + dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. " | ||
2666 | + "Could not allocate region " | ||
2667 | + "for character device\n"); | ||
2668 | + kfree(device); | ||
2669 | + return -ENODEV; | ||
2670 | + } | ||
2671 | + | ||
2672 | + /* Register the driver in the kernel */ | ||
2673 | + /* Initialize of character device */ | ||
2674 | + cdev_init(&c_dev, &rsz_fops); | ||
2675 | + c_dev.owner = THIS_MODULE; | ||
2676 | + c_dev.ops = &rsz_fops; | ||
2677 | + | ||
2678 | + /* Addding character device */ | ||
2679 | + ret = cdev_add(&c_dev, dev, 1); | ||
2680 | + if (ret) { | ||
2681 | + dev_err(rsz_device, OMAP_REZR_NAME ": Error adding " | ||
2682 | + "device - %d\n", ret); | ||
2683 | + goto fail2; | ||
2684 | + } | ||
2685 | + rsz_major = MAJOR(dev); | ||
2686 | + | ||
2687 | + /* register driver as a platform driver */ | ||
2688 | + ret = platform_driver_register(&omap_resizer_driver); | ||
2689 | + if (ret) { | ||
2690 | + dev_err(rsz_device, OMAP_REZR_NAME | ||
2691 | + ": Failed to register platform driver!\n"); | ||
2692 | + goto fail3; | ||
2693 | + } | ||
2694 | + | ||
2695 | + /* Register the drive as a platform device */ | ||
2696 | + ret = platform_device_register(&omap_resizer_device); | ||
2697 | + if (ret) { | ||
2698 | + dev_err(rsz_device, OMAP_REZR_NAME | ||
2699 | + ": Failed to register platform device!\n"); | ||
2700 | + goto fail4; | ||
2701 | + } | ||
2702 | + | ||
2703 | + rsz_class = class_create(THIS_MODULE, OMAP_REZR_NAME); | ||
2704 | + if (!rsz_class) { | ||
2705 | + dev_err(rsz_device, OMAP_REZR_NAME | ||
2706 | + ": Failed to create class!\n"); | ||
2707 | + goto fail5; | ||
2708 | + } | ||
2709 | + | ||
2710 | + /* make entry in the devfs */ | ||
2711 | + rsz_device = device_create(rsz_class, rsz_device, | ||
2712 | + MKDEV(rsz_major, 0), NULL, | ||
2713 | + OMAP_REZR_NAME); | ||
2714 | + dev_dbg(rsz_device, OMAP_REZR_NAME ": Registered Resizer Wrapper\n"); | ||
2715 | + device->opened = 0; | ||
2716 | + | ||
2717 | + device->vbq_ops.buf_setup = rsz_vbq_setup; | ||
2718 | + device->vbq_ops.buf_prepare = rsz_vbq_prepare; | ||
2719 | + device->vbq_ops.buf_release = rsz_vbq_release; | ||
2720 | + device->vbq_ops.buf_queue = rsz_vbq_queue; | ||
2721 | + init_completion(&device->compl_isr); | ||
2722 | + mutex_init(&device->reszwrap_mutex); | ||
2723 | + | ||
2724 | + device_config = device; | ||
2725 | + return 0; | ||
2726 | + | ||
2727 | +fail5: | ||
2728 | + platform_device_unregister(&omap_resizer_device); | ||
2729 | +fail4: | ||
2730 | + platform_driver_unregister(&omap_resizer_driver); | ||
2731 | +fail3: | ||
2732 | + cdev_del(&c_dev); | ||
2733 | +fail2: | ||
2734 | + unregister_chrdev_region(dev, 1); | ||
2735 | + kfree(device); | ||
2736 | + return ret; | ||
2737 | +} | ||
2738 | + | ||
2739 | +/** | ||
2740 | + * omap_rsz_exit - Close of Resizer Wrapper | ||
2741 | + **/ | ||
2742 | +void __exit omap_rsz_exit(void) | ||
2743 | +{ | ||
2744 | + device_destroy(rsz_class, dev); | ||
2745 | + class_destroy(rsz_class); | ||
2746 | + platform_device_unregister(&omap_resizer_device); | ||
2747 | + platform_driver_unregister(&omap_resizer_driver); | ||
2748 | + cdev_del(&c_dev); | ||
2749 | + unregister_chrdev_region(dev, 1); | ||
2750 | + kfree(device_config); | ||
2751 | +} | ||
2752 | + | ||
2753 | +module_init(omap_rsz_init) | ||
2754 | +module_exit(omap_rsz_exit) | ||
2755 | + | ||
2756 | +MODULE_AUTHOR("Texas Instruments"); | ||
2757 | +MODULE_DESCRIPTION("OMAP ISP Resizer"); | ||
2758 | +MODULE_LICENSE("GPL"); | ||
2759 | diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h | ||
2760 | new file mode 100644 | ||
2761 | index 0000000..5ac0c88 | ||
2762 | --- /dev/null | ||
2763 | +++ b/include/linux/omap_resizer.h | ||
2764 | @@ -0,0 +1,136 @@ | ||
2765 | +/* | ||
2766 | + * drivers/media/video/isp/omap_resizer.h | ||
2767 | + * | ||
2768 | + * Include file for Resizer module wrapper in TI's OMAP3430 ISP | ||
2769 | + * | ||
2770 | + * Copyright (C) 2008 Texas Instruments, Inc. | ||
2771 | + * | ||
2772 | + * This package is free software; you can redistribute it and/or modify | ||
2773 | + * it under the terms of the GNU General Public License version 2 as | ||
2774 | + * published by the Free Software Foundation. | ||
2775 | + * | ||
2776 | + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | ||
2777 | + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
2778 | + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
2779 | + */ | ||
2780 | + | ||
2781 | +#ifndef OMAP_RESIZER_H | ||
2782 | +#define OMAP_RESIZER_H | ||
2783 | + | ||
2784 | +#include <linux/types.h> | ||
2785 | + | ||
2786 | +/* ioctls definition */ | ||
2787 | +#define RSZ_IOC_BASE 'R' | ||
2788 | +#define RSZ_IOC_MAXNR 8 | ||
2789 | + | ||
2790 | +/*Ioctl options which are to be passed while calling the ioctl*/ | ||
2791 | +#define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\ | ||
2792 | + struct v4l2_requestbuffers) | ||
2793 | +#define RSZ_QUERYBUF _IOWR(RSZ_IOC_BASE, 2, struct v4l2_buffer) | ||
2794 | +#define RSZ_S_PARAM _IOWR(RSZ_IOC_BASE, 3, struct rsz_params) | ||
2795 | +#define RSZ_G_PARAM _IOWR(RSZ_IOC_BASE, 4, struct rsz_params) | ||
2796 | +#define RSZ_RESIZE _IOWR(RSZ_IOC_BASE, 5, __s32) | ||
2797 | +#define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status) | ||
2798 | +#define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer) | ||
2799 | +#define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize) | ||
2800 | + | ||
2801 | +#define RSZ_INTYPE_YCBCR422_16BIT 0 | ||
2802 | +#define RSZ_INTYPE_PLANAR_8BIT 1 | ||
2803 | +#define RSZ_PIX_FMT_UYVY 1 /* cb:y:cr:y */ | ||
2804 | +#define RSZ_PIX_FMT_YUYV 0 /* y:cb:y:cr */ | ||
2805 | + | ||
2806 | +enum config_done { | ||
2807 | + STATE_CONFIGURED, /* Resizer driver configured | ||
2808 | + * by application. | ||
2809 | + */ | ||
2810 | + STATE_NOT_CONFIGURED /* Resizer driver not | ||
2811 | + * configured by application. | ||
2812 | + */ | ||
2813 | +}; | ||
2814 | + | ||
2815 | +/* Structure Definitions */ | ||
2816 | + | ||
2817 | +/* used to luma enhancement options */ | ||
2818 | + | ||
2819 | +struct rsz_yenh { | ||
2820 | + __s32 type; /* represents luma enable or | ||
2821 | + * disable. | ||
2822 | + */ | ||
2823 | + __u8 gain; /* represents gain. */ | ||
2824 | + __u8 slop; /* represents slop. */ | ||
2825 | + __u8 core; /* Represents core value. */ | ||
2826 | +}; | ||
2827 | + | ||
2828 | +/* Conatins all the parameters for resizing. This structure | ||
2829 | + * is used to configure resiser parameters | ||
2830 | + */ | ||
2831 | +struct rsz_params { | ||
2832 | + __s32 in_hsize; /* input frame horizontal | ||
2833 | + * size. | ||
2834 | + */ | ||
2835 | + __s32 in_vsize; /* input frame vertical size */ | ||
2836 | + __s32 in_pitch; /* offset between two rows of | ||
2837 | + * input frame. | ||
2838 | + */ | ||
2839 | + __s32 inptyp; /* for determining 16 bit or | ||
2840 | + * 8 bit data. | ||
2841 | + */ | ||
2842 | + __s32 vert_starting_pixel; /* for specifying vertical | ||
2843 | + * starting pixel in input. | ||
2844 | + */ | ||
2845 | + __s32 horz_starting_pixel; /* for specyfing horizontal | ||
2846 | + * starting pixel in input. | ||
2847 | + */ | ||
2848 | + __s32 cbilin; /* # defined, filter with luma | ||
2849 | + * or bi-linear interpolation. | ||
2850 | + */ | ||
2851 | + __s32 pix_fmt; /* # defined, UYVY or YUYV */ | ||
2852 | + __s32 out_hsize; /* output frame horizontal | ||
2853 | + * size. | ||
2854 | + */ | ||
2855 | + __s32 out_vsize; /* output frame vertical | ||
2856 | + * size. | ||
2857 | + */ | ||
2858 | + __s32 out_pitch; /* offset between two rows of | ||
2859 | + * output frame. | ||
2860 | + */ | ||
2861 | + __s32 hstph; /* for specifying horizontal | ||
2862 | + * starting phase. | ||
2863 | + */ | ||
2864 | + __s32 vstph; /* for specifying vertical | ||
2865 | + * starting phase. | ||
2866 | + */ | ||
2867 | + __u16 tap4filt_coeffs[32]; /* horizontal filter | ||
2868 | + * coefficients. | ||
2869 | + */ | ||
2870 | + __u16 tap7filt_coeffs[32]; /* vertical filter | ||
2871 | + * coefficients. | ||
2872 | + */ | ||
2873 | + struct rsz_yenh yenh_params; | ||
2874 | +}; | ||
2875 | + | ||
2876 | +/* Contains the status of hardware and channel */ | ||
2877 | +struct rsz_status { | ||
2878 | + __s32 chan_busy; /* 1: channel is busy, | ||
2879 | + * 0: channel is not busy | ||
2880 | + */ | ||
2881 | + __s32 hw_busy; /* 1: hardware is busy, | ||
2882 | + * 0: hardware is not busy | ||
2883 | + */ | ||
2884 | + __s32 src; /* # defined, can be either | ||
2885 | + * SD-RAM or CCDC/PREVIEWER | ||
2886 | + */ | ||
2887 | +}; | ||
2888 | + | ||
2889 | +/* Passed by application for getting crop size */ | ||
2890 | +struct rsz_cropsize { | ||
2891 | + __u32 hcrop; /* Number of pixels per line | ||
2892 | + * cropped in output image. | ||
2893 | + */ | ||
2894 | + | ||
2895 | + __u32 vcrop; /* Number of lines cropped | ||
2896 | + * in output image. | ||
2897 | + */ | ||
2898 | +}; | ||
2899 | + | ||
2900 | +#endif | ||
2901 | -- | ||
2902 | 1.6.0.3 | ||
2903 | |||
2904 | --- /tmp/Kconfig 2009-04-06 10:56:27.000000000 +0200 | ||
2905 | +++ git/drivers/media/video/Kconfig 2009-04-06 10:57:25.000000000 +0200 | ||
2906 | @@ -711,6 +711,9 @@ | ||
2907 | CMOS camera controller. This is the controller found on first- | ||
2908 | generation OLPC systems. | ||
2909 | |||
2910 | + | ||
2911 | +source "drivers/media/video/isp/Kconfig" | ||
2912 | + | ||
2913 | config VIDEO_OMAP3 | ||
2914 | tristate "OMAP 3 Camera support" | ||
2915 | select VIDEOBUF_GEN | ||