3390599292605174dc161c3e267c8740572c31ca
[openembedded.git] /
1 From 38f3cd5564a466e5251fc2ff47e0504148922304 Mon Sep 17 00:00:00 2001
2 From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
3 Date: Wed, 29 Apr 2009 17:18:56 +0530
4 Subject: [PATCH 23/26] OMAP-Resizer: Basic Resizer refreshed with latest gitorious tree
5
6 This is same resizer driver patch posted by Sergio onto
7 mailing list quite a some time back. This commit refreshes
8 the same patch on top of latest gitorious.org tree.
9
10 List of New/Modified files:
11  modified:   drivers/media/video/Kconfig
12  modified:   drivers/media/video/isp/Makefile
13  modified:   drivers/media/video/isp/isp.c
14  modified:   drivers/media/video/isp/ispreg.h
15  new file:   drivers/media/video/isp/omap_resizer.c
16  new file:   include/linux/omap_resizer.h
17
18 TODO:
19  - Resizer driver needs to be independent from camera and ISP
20  - Custom patches implemented ontop of PSP1.0.2 release
21    to fix some V4L2-buf layer issues.
22  -
23 ---
24  drivers/media/video/Kconfig            |    7 +
25  drivers/media/video/isp/Makefile       |    4 +
26  drivers/media/video/isp/isp.c          |   15 +
27  drivers/media/video/isp/omap_resizer.c | 1634 ++++++++++++++++++++++++++++++++
28  include/linux/omap_resizer.h           |  136 +++
29  5 files changed, 1796 insertions(+), 0 deletions(-)
30  create mode 100644 drivers/media/video/isp/omap_resizer.c
31  create mode 100644 include/linux/omap_resizer.h
32
33 diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
34 index 3cdb5a4..d2b4ae1 100644
35 --- a/drivers/media/video/Kconfig
36 +++ b/drivers/media/video/Kconfig
37 @@ -720,6 +720,13 @@ config VIDEO_OMAP3
38         ---help---
39           Driver for an OMAP 3 camera controller.
40  
41 +config VIDEO_OMAP34XX_ISP_RESIZER
42 +       tristate "OMAP ISP Resizer"
43 +       depends on VIDEO_V4L2 && ARCH_OMAP34XX
44 +       select VIDEOBUF_GEN
45 +       select VIDEOBUF_DMA_SG
46 +       select OMAP_IOMMU
47 +
48  config SOC_CAMERA
49         tristate "SoC camera support"
50         depends on VIDEO_V4L2 && HAS_DMA
51 diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
52 index f14d617..d171fb9 100644
53 --- a/drivers/media/video/isp/Makefile
54 +++ b/drivers/media/video/isp/Makefile
55 @@ -7,6 +7,10 @@ else
56  isp-mod-objs += \
57         isp.o ispccdc.o ispmmu.o \
58         isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
59 +
60 +obj-$(CONFIG_VIDEO_OMAP34XX_ISP_RESIZER) += \
61 +       omap_resizer.o
62 +
63  endif
64  
65  obj-$(CONFIG_VIDEO_OMAP3) += isp-mod.o
66 diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
67 index 54c839b..f1f92b4 100644
68 --- a/drivers/media/video/isp/isp.c
69 +++ b/drivers/media/video/isp/isp.c
70 @@ -505,6 +505,12 @@ int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
71                 isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
72                            IRQ0ENABLE_PRV_DONE_IRQ);
73                 break;
74 +       case CBK_RESZ_DONE:
75 +               isp_reg_writel(IRQ0ENABLE_RSZ_DONE_IRQ,
76 +                               OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
77 +               isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
78 +                               IRQ0ENABLE_RSZ_DONE_IRQ);
79 +               break;
80         default:
81                 break;
82         }
83 @@ -556,6 +562,10 @@ int isp_unset_callback(enum isp_callback_type type)
84                 isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
85                             ~IRQ0ENABLE_PRV_DONE_IRQ);
86                 break;
87 +       case CBK_RESZ_DONE:
88 +               isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
89 +                               ~IRQ0ENABLE_RSZ_DONE_IRQ);
90 +               break;
91         default:
92                 break;
93         }
94 @@ -938,6 +948,11 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_isp)
95                         if (!ispresizer_busy())
96                                 ispresizer_config_shadow_registers();
97                         isp_buf_process(bufs);
98 +               } else {
99 +                       if (irqdis->isp_callbk[CBK_RESZ_DONE])
100 +                               irqdis->isp_callbk[CBK_RESZ_DONE](RESZ_DONE,
101 +                                               irqdis->isp_callbk_arg1[CBK_RESZ_DONE],
102 +                                               irqdis->isp_callbk_arg2[CBK_RESZ_DONE]);
103                 }
104         }
105  
106 diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
107 new file mode 100644
108 index 0000000..54bc425
109 --- /dev/null
110 +++ b/drivers/media/video/isp/omap_resizer.c
111 @@ -0,0 +1,1634 @@
112 +/*
113 + * drivers/media/video/isp/omap_resizer.c
114 + *
115 + * Wrapper for Resizer module in TI's OMAP3430 ISP
116 + *
117 + * Copyright (C) 2008 Texas Instruments, Inc.
118 + *
119 + * Contributors:
120 + *     Sergio Aguirre <saaguirre@ti.com>
121 + *     Troy Laramy <t-laramy@ti.com>
122 + *
123 + * This package is free software; you can redistribute it and/or modify
124 + * it under the terms of the GNU General Public License version 2 as
125 + * published by the Free Software Foundation.
126 + *
127 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
128 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
129 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
130 + */
131 +
132 +#include <linux/mutex.h>
133 +#include <linux/cdev.h>
134 +#include <linux/delay.h>
135 +#include <linux/device.h>
136 +#include <linux/fs.h>
137 +#include <linux/mm.h>
138 +#include <linux/module.h>
139 +#include <linux/platform_device.h>
140 +#include <linux/io.h>
141 +#include <linux/uaccess.h>
142 +#include <media/v4l2-dev.h>
143 +#include <asm/cacheflush.h>
144 +
145 +#include "isp.h"
146 +#include "ispmmu.h"
147 +#include "ispreg.h"
148 +#include "ispresizer.h"
149 +#include <linux/omap_resizer.h>
150 +
151 +#define OMAP_REZR_NAME         "omap-resizer"
152 +
153 +/* Defines and Constants*/
154 +#define MAX_CHANNELS           16
155 +#define MAX_IMAGE_WIDTH                2047
156 +#define MAX_IMAGE_WIDTH_HIGH   2047
157 +#define ALIGNMENT              16
158 +#define CHANNEL_BUSY           1
159 +#define CHANNEL_FREE           0
160 +#define PIXEL_EVEN             2
161 +#define RATIO_MULTIPLIER       256
162 +/* Bit position Macro */
163 +/* macro for bit set and clear */
164 +#define BITSET(variable, bit)  ((variable) | (1 << bit))
165 +#define BITRESET(variable, bit)        ((variable) & ~(0x00000001 << (bit)))
166 +#define SET_BIT_INPUTRAM       28
167 +#define SET_BIT_CBLIN          29
168 +#define SET_BIT_INPTYP         27
169 +#define SET_BIT_YCPOS          26
170 +#define INPUT_RAM              1
171 +#define UP_RSZ_RATIO           64
172 +#define DOWN_RSZ_RATIO         512
173 +#define UP_RSZ_RATIO1          513
174 +#define DOWN_RSZ_RATIO1                1024
175 +#define RSZ_IN_SIZE_VERT_SHIFT 16
176 +#define MAX_HORZ_PIXEL_8BIT    31
177 +#define MAX_HORZ_PIXEL_16BIT   15
178 +#define NUM_PHASES             8
179 +#define NUM_TAPS               4
180 +#define NUM_D2PH               4       /* for downsampling * 2+x ~ 4x,
181 +                                        * number of phases
182 +                                        */
183 +#define NUM_D2TAPS             7       /* for downsampling * 2+x ~ 4x,
184 +                                        * number of taps
185 +                                        */
186 +#define ALIGN32                        32
187 +#define MAX_COEF_COUNTER       16
188 +#define COEFF_ADDRESS_OFFSET   0x04
189 +
190 +/* Global structure which contains information about number of channels
191 +   and protection variables */
192 +struct device_params {
193 +
194 +       unsigned char opened;                   /* state of the device */
195 +       struct completion compl_isr;            /* Completion for interrupt */
196 +       struct mutex reszwrap_mutex;            /* Semaphore for array */
197 +
198 +       struct videobuf_queue_ops vbq_ops;      /* videobuf queue operations */
199 +};
200 +
201 +/* Register mapped structure which contains the every register
202 +   information */
203 +struct resizer_config {
204 +       u32 rsz_pcr;                            /* pcr register mapping
205 +                                                * variable.
206 +                                                */
207 +       u32 rsz_in_start;                       /* in_start register mapping
208 +                                                * variable.
209 +                                                */
210 +       u32 rsz_in_size;                        /* in_size register mapping
211 +                                                * variable.
212 +                                                */
213 +       u32 rsz_out_size;                       /* out_size register mapping
214 +                                                * variable.
215 +                                                */
216 +       u32 rsz_cnt;                            /* rsz_cnt register mapping
217 +                                                * variable.
218 +                                                */
219 +       u32 rsz_sdr_inadd;                      /* sdr_inadd register mapping
220 +                                                * variable.
221 +                                                */
222 +       u32 rsz_sdr_inoff;                      /* sdr_inoff register mapping
223 +                                                * variable.
224 +                                                */
225 +       u32 rsz_sdr_outadd;                     /* sdr_outadd register mapping
226 +                                                * variable.
227 +                                                */
228 +       u32 rsz_sdr_outoff;                     /* sdr_outbuff register
229 +                                                * mapping variable.
230 +                                                */
231 +       u32 rsz_coeff_horz[16];                 /* horizontal coefficients
232 +                                                * mapping array.
233 +                                                */
234 +       u32 rsz_coeff_vert[16];                 /* vertical coefficients
235 +                                                * mapping array.
236 +                                                */
237 +       u32 rsz_yehn;                           /* yehn(luma)register mapping
238 +                                                * variable.
239 +                                                */
240 +};
241 +
242 +struct rsz_mult {
243 +       int in_hsize;                           /* input frame horizontal
244 +                                                * size.
245 +                                                */
246 +       int in_vsize;                           /* input frame vertical size.
247 +                                                */
248 +       int out_hsize;                          /* output frame horizontal
249 +                                                * size.
250 +                                                */
251 +       int out_vsize;                          /* output frame vertical
252 +                                                * size.
253 +                                                */
254 +       int in_pitch;                           /* offset between two rows of
255 +                                                * input frame.
256 +                                                */
257 +       int out_pitch;                          /* offset between two rows of
258 +                                                * output frame.
259 +                                                */
260 +       int end_hsize;
261 +       int end_vsize;
262 +       int num_htap;                           /* 0 = 7tap; 1 = 4tap */
263 +       int num_vtap;                           /* 0 = 7tap; 1 = 4tap */
264 +       int active;
265 +       int inptyp;
266 +       int vrsz;
267 +       int hrsz;
268 +       int hstph;                              /* for specifying horizontal
269 +                                                * starting phase.
270 +                                                */
271 +       int vstph;
272 +       int pix_fmt;                            /* # defined, UYVY or YUYV. */
273 +       int cbilin;                             /* # defined, filter with luma
274 +                                                * or bi-linear.
275 +                                                */
276 +       u16 tap4filt_coeffs[32];                /* horizontal filter
277 +                                                * coefficients.
278 +                                                */
279 +       u16 tap7filt_coeffs[32];                /* vertical filter
280 +                                                * coefficients.
281 +                                                */
282 +};
283 +/* Channel specific structure contains information regarding
284 +   the every channel */
285 +struct channel_config {
286 +       struct resizer_config register_config;  /* Instance of register set
287 +                                                * mapping structure
288 +                                                */
289 +       int status;                             /* Specifies whether the
290 +                                                * channel is busy or not
291 +                                                */
292 +       struct mutex chanprotection_mutex;
293 +       enum config_done config_state;
294 +       u8 input_buf_index;
295 +       u8 output_buf_index;
296 +
297 +};
298 +
299 +/* per-filehandle data structure */
300 +struct rsz_fh {
301 +       struct rsz_params *params;
302 +       struct channel_config *config;
303 +       struct rsz_mult *multipass;             /* Multipass to support
304 +                                                * resizing ration outside
305 +                                                * of 0.25x to 4x
306 +                                                */
307 +       spinlock_t vbq_lock;                    /* spinlock for videobuf
308 +                                                * queues.
309 +                                                */
310 +       enum v4l2_buf_type type;
311 +       struct videobuf_queue vbq;
312 +       struct device_params *device;
313 +
314 +       dma_addr_t isp_addr_read;               /* Input/Output address */
315 +       dma_addr_t isp_addr_write;              /* Input/Output address */
316 +       u32 rsz_bufsize;                        /* channel specific buffersize
317 +                                                */
318 +};
319 +
320 +static struct device_params *device_config;
321 +static struct device *rsz_device;
322 +static int rsz_major = -1;
323 +/* functions declaration */
324 +static void rsz_hardware_setup(struct channel_config *rsz_conf_chan);
325 +static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *,
326 +                                               struct channel_config *);
327 +static int rsz_get_params(struct rsz_params *, struct channel_config *);
328 +static void rsz_copy_data(struct rsz_mult *multipass,
329 +                                               struct rsz_params *params);
330 +static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1,
331 +                                               void *arg2);
332 +static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
333 +                                       struct rsz_cropsize *cropsize);
334 +static int rsz_set_multipass(struct rsz_mult *multipass,
335 +                                       struct channel_config *rsz_conf_chan);
336 +static int rsz_set_ratio(struct rsz_mult *multipass,
337 +                                       struct channel_config *rsz_conf_chan);
338 +static void rsz_config_ratio(struct rsz_mult *multipass,
339 +                                       struct channel_config *rsz_conf_chan);
340 +
341 +/**
342 + * rsz_hardware_setup - Sets hardware configuration registers
343 + * @rsz_conf_chan: Structure containing channel configuration
344 + *
345 + * Set hardware configuration registers
346 + **/
347 +static void rsz_hardware_setup(struct channel_config *rsz_conf_chan)
348 +{
349 +       int coeffcounter;
350 +       int coeffoffset = 0;
351 +
352 +       omap_writel(rsz_conf_chan->register_config.rsz_cnt,
353 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_CNT));
354 +
355 +       omap_writel(rsz_conf_chan->register_config.rsz_in_start,
356 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_IN_START));
357 +       omap_writel(rsz_conf_chan->register_config.rsz_in_size,
358 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_IN_SIZE));
359 +
360 +       omap_writel(rsz_conf_chan->register_config.rsz_out_size,
361 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_OUT_SIZE));
362 +       omap_writel(rsz_conf_chan->register_config.rsz_sdr_inadd,
363 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INADD));
364 +       omap_writel(rsz_conf_chan->register_config.rsz_sdr_inoff,
365 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INOFF));
366 +       omap_writel(rsz_conf_chan->register_config.rsz_sdr_outadd,
367 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTADD));
368 +       omap_writel(rsz_conf_chan->register_config.rsz_sdr_outoff,
369 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTOFF));
370 +       omap_writel(rsz_conf_chan->register_config.rsz_yehn, OMAP3ISP_RESZ_REG(ISPRSZ_YENH));
371 +
372 +       for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
373 +                                                       coeffcounter++) {
374 +               omap_writel(rsz_conf_chan->register_config.
375 +                                       rsz_coeff_horz[coeffcounter],
376 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_HFILT10
377 +                                               + coeffoffset));
378 +
379 +               omap_writel(rsz_conf_chan->register_config.
380 +                                       rsz_coeff_vert[coeffcounter],
381 +                                       OMAP3ISP_RESZ_REG(ISPRSZ_VFILT10
382 +                                               + coeffoffset));
383 +               coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET;
384 +       }
385 +}
386 +
387 +/**
388 + * rsz_start - Enables Resizer Wrapper
389 + * @arg: Currently not used.
390 + * @device: Structure containing ISP resizer wrapper global information
391 + *
392 + * Submits a resizing task specified by the rsz_resize structure. The call can
393 + * either be blocked until the task is completed or returned immediately based
394 + * on the value of the blocking argument in the rsz_resize structure. If it is
395 + * blocking, the status of the task can be checked by calling ioctl
396 + * RSZ_G_STATUS. Only one task can be outstanding for each logical channel.
397 + *
398 + * Returns 0 if successful, or -EINVAL if could not set callback for RSZR IRQ
399 + * event or the state of the channel is not configured.
400 + **/
401 +int rsz_start(int *arg, struct rsz_fh *fh)
402 +{
403 +       struct channel_config *rsz_conf_chan = fh->config;
404 +       struct rsz_mult *multipass = fh->multipass;
405 +       struct videobuf_queue *q = &fh->vbq;
406 +       int ret;
407 +
408 +       if (rsz_conf_chan->config_state) {
409 +               dev_err(rsz_device, "State not configured \n");
410 +               goto err_einval;
411 +       }
412 +
413 +       rsz_conf_chan->status = CHANNEL_BUSY;
414 +
415 +       rsz_hardware_setup(rsz_conf_chan);
416 +
417 +       if (isp_set_callback(CBK_RESZ_DONE, rsz_isr, (void *) NULL,
418 +                                                       (void *)NULL)) {
419 +               dev_err(rsz_device, "No callback for RSZR\n");
420 +               goto err_einval;
421 +       }
422 +mult:
423 +       device_config->compl_isr.done = 0;
424 +
425 +       ispresizer_enable(1);
426 +
427 +       ret = wait_for_completion_interruptible(&device_config->compl_isr);
428 +       if (ret != 0) {
429 +               dev_dbg(rsz_device, "Unexpected exit from "
430 +                               "wait_for_completion_interruptible\n");
431 +               wait_for_completion(&device_config->compl_isr);
432 +       }
433 +
434 +       if (multipass->active) {
435 +               rsz_set_multipass(multipass, rsz_conf_chan);
436 +               goto mult;
437 +       }
438 +
439 +       if (fh->isp_addr_read) {
440 +               ispmmu_unmap(fh->isp_addr_read);
441 +               fh->isp_addr_read = 0;
442 +       }
443 +       if (fh->isp_addr_write) {
444 +               ispmmu_unmap(fh->isp_addr_write);
445 +               fh->isp_addr_write = 0;
446 +       }
447 +
448 +       rsz_conf_chan->status = CHANNEL_FREE;
449 +       q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
450 +       q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
451 +       rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
452 +       rsz_conf_chan->register_config.rsz_sdr_inadd = 0;
453 +
454 +       /* Unmap and free the DMA memory allocated for buffers */
455 +       videobuf_dma_unmap(q, videobuf_to_dma(
456 +                               q->bufs[rsz_conf_chan->input_buf_index]));
457 +       videobuf_dma_unmap(q, videobuf_to_dma(
458 +                               q->bufs[rsz_conf_chan->output_buf_index]));
459 +       videobuf_dma_free(videobuf_to_dma(
460 +                               q->bufs[rsz_conf_chan->input_buf_index]));
461 +       videobuf_dma_free(videobuf_to_dma(
462 +                               q->bufs[rsz_conf_chan->output_buf_index]));
463 +
464 +       isp_unset_callback(CBK_RESZ_DONE);
465 +
466 +       return 0;
467 +err_einval:
468 +       return -EINVAL;
469 +}
470 +
471 +/**
472 + * rsz_set_multipass - Set resizer multipass
473 + * @rsz_conf_chan: Structure containing channel configuration
474 + *
475 + * Returns always 0
476 + **/
477 +static int rsz_set_multipass(struct rsz_mult *multipass,
478 +                       struct channel_config *rsz_conf_chan)
479 +{
480 +       multipass->in_hsize = multipass->out_hsize;
481 +       multipass->in_vsize = multipass->out_vsize;
482 +       multipass->out_hsize = multipass->end_hsize;
483 +       multipass->out_vsize = multipass->end_vsize;
484 +
485 +       multipass->out_pitch = (multipass->inptyp ? multipass->out_hsize
486 +                                               : (multipass->out_hsize * 2));
487 +       multipass->in_pitch = (multipass->inptyp ? multipass->in_hsize
488 +                                               : (multipass->in_hsize * 2));
489 +
490 +       rsz_set_ratio(multipass, rsz_conf_chan);
491 +       rsz_config_ratio(multipass, rsz_conf_chan);
492 +       rsz_hardware_setup(rsz_conf_chan);
493 +       return 0;
494 +}
495 +
496 +/**
497 + * rsz_copy_data - Copy data
498 + * @params: Structure containing the Resizer Wrapper parameters
499 + *
500 + * Copy data
501 + **/
502 +static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params)
503 +{
504 +       int i;
505 +       multipass->in_hsize = params->in_hsize;
506 +       multipass->in_vsize = params->in_vsize;
507 +       multipass->out_hsize = params->out_hsize;
508 +       multipass->out_vsize = params->out_vsize;
509 +       multipass->end_hsize = params->out_hsize;
510 +       multipass->end_vsize = params->out_vsize;
511 +       multipass->in_pitch = params->in_pitch;
512 +       multipass->out_pitch = params->out_pitch;
513 +       multipass->hstph = params->hstph;
514 +       multipass->vstph = params->vstph;
515 +       multipass->inptyp = params->inptyp;
516 +       multipass->pix_fmt = params->pix_fmt;
517 +       multipass->cbilin = params->cbilin;
518 +
519 +       for (i = 0; i < 32; i++) {
520 +               multipass->tap4filt_coeffs[i] = params->tap4filt_coeffs[i];
521 +               multipass->tap7filt_coeffs[i] = params->tap7filt_coeffs[i];
522 +       }
523 +}
524 +
525 +/**
526 + * rsz_set_params - Set parameters for resizer wrapper
527 + * @params: Structure containing the Resizer Wrapper parameters
528 + * @rsz_conf_chan: Structure containing channel configuration
529 + *
530 + * Used to set the parameters of the Resizer hardware, including input and
531 + * output image size, horizontal and vertical poly-phase filter coefficients,
532 + * luma enchancement filter coefficients, etc.
533 + **/
534 +static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params,
535 +                                       struct channel_config *rsz_conf_chan)
536 +{
537 +       int mul = 1;
538 +       if ((params->yenh_params.type < 0) || (params->yenh_params.type > 2)) {
539 +               dev_err(rsz_device, "rsz_set_params: Wrong yenh type\n");
540 +               return -EINVAL;
541 +       }
542 +       if ((params->in_vsize <= 0) || (params->in_hsize <= 0) ||
543 +                       (params->out_vsize <= 0) || (params->out_hsize <= 0) ||
544 +                       (params->in_pitch <= 0) || (params->out_pitch <= 0)) {
545 +               dev_err(rsz_device, "rsz_set_params: Invalid size params\n");
546 +               return -EINVAL;
547 +       }
548 +       if ((params->inptyp != RSZ_INTYPE_YCBCR422_16BIT) &&
549 +                       (params->inptyp != RSZ_INTYPE_PLANAR_8BIT)) {
550 +               dev_err(rsz_device, "rsz_set_params: Invalid input type\n");
551 +               return -EINVAL;
552 +       }
553 +       if ((params->pix_fmt != RSZ_PIX_FMT_UYVY) &&
554 +                       (params->pix_fmt != RSZ_PIX_FMT_YUYV)) {
555 +               dev_err(rsz_device, "rsz_set_params: Invalid pixel format\n");
556 +               return -EINVAL;
557 +       }
558 +       if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
559 +               mul = 2;
560 +       else
561 +               mul = 1;
562 +       if (params->in_pitch < (params->in_hsize * mul)) {
563 +               dev_err(rsz_device, "rsz_set_params: Pitch is incorrect\n");
564 +               return -EINVAL;
565 +       }
566 +       if (params->out_pitch < (params->out_hsize * mul)) {
567 +               dev_err(rsz_device, "rsz_set_params: Out pitch cannot be less"
568 +                                       " than out hsize\n");
569 +               return -EINVAL;
570 +       }
571 +       /* Output H size should be even */
572 +       if ((params->out_hsize % PIXEL_EVEN) != 0) {
573 +               dev_err(rsz_device, "rsz_set_params: Output H size should"
574 +                                       " be even\n");
575 +               return -EINVAL;
576 +       }
577 +       if (params->horz_starting_pixel < 0) {
578 +               dev_err(rsz_device, "rsz_set_params: Horz start pixel cannot"
579 +                                       " be less than zero\n");
580 +               return -EINVAL;
581 +       }
582 +
583 +       rsz_copy_data(multipass, params);
584 +       if (0 != rsz_set_ratio(multipass, rsz_conf_chan))
585 +               goto err_einval;
586 +
587 +       if (params->yenh_params.type) {
588 +               if ((multipass->num_htap && multipass->out_hsize >
589 +                               1280) ||
590 +                               (!multipass->num_htap && multipass->out_hsize >
591 +                               640))
592 +                       goto err_einval;
593 +       }
594 +
595 +       if (INPUT_RAM)
596 +               params->vert_starting_pixel = 0;
597 +
598 +       rsz_conf_chan->register_config.rsz_in_start =
599 +                                               (params->vert_starting_pixel
600 +                                               << ISPRSZ_IN_SIZE_VERT_SHIFT)
601 +                                               & ISPRSZ_IN_SIZE_VERT_MASK;
602 +
603 +       if (params->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
604 +               if (params->horz_starting_pixel > MAX_HORZ_PIXEL_8BIT)
605 +                       goto err_einval;
606 +       }
607 +       if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT) {
608 +               if (params->horz_starting_pixel > MAX_HORZ_PIXEL_16BIT)
609 +                       goto err_einval;
610 +       }
611 +
612 +       rsz_conf_chan->register_config.rsz_in_start |=
613 +                                               params->horz_starting_pixel
614 +                                               & ISPRSZ_IN_START_HORZ_ST_MASK;
615 +
616 +       rsz_conf_chan->register_config.rsz_yehn =
617 +                                               (params->yenh_params.type
618 +                                               << ISPRSZ_YENH_ALGO_SHIFT)
619 +                                               & ISPRSZ_YENH_ALGO_MASK;
620 +
621 +       if (params->yenh_params.type) {
622 +               rsz_conf_chan->register_config.rsz_yehn |=
623 +                                               params->yenh_params.core
624 +                                               & ISPRSZ_YENH_CORE_MASK;
625 +
626 +               rsz_conf_chan->register_config.rsz_yehn |=
627 +                                               (params->yenh_params.gain
628 +                                               << ISPRSZ_YENH_GAIN_SHIFT)
629 +                                               & ISPRSZ_YENH_GAIN_MASK;
630 +
631 +               rsz_conf_chan->register_config.rsz_yehn |=
632 +                                               (params->yenh_params.slop
633 +                                               << ISPRSZ_YENH_SLOP_SHIFT)
634 +                                               & ISPRSZ_YENH_SLOP_MASK;
635 +       }
636 +
637 +       rsz_config_ratio(multipass, rsz_conf_chan);
638 +
639 +       rsz_conf_chan->config_state = STATE_CONFIGURED;
640 +
641 +       return 0;
642 +err_einval:
643 +       return -EINVAL;
644 +}
645 +
646 +/**
647 + * rsz_set_ratio - Set ratio
648 + * @rsz_conf_chan: Structure containing channel configuration
649 + *
650 + * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is
651 + * being requested, or other ratio configuration value is out of bounds
652 + **/
653 +static int rsz_set_ratio(struct rsz_mult *multipass,
654 +                               struct channel_config *rsz_conf_chan)
655 +{
656 +       int alignment = 0;
657 +
658 +       rsz_conf_chan->register_config.rsz_cnt = 0;
659 +
660 +       if ((multipass->out_hsize > MAX_IMAGE_WIDTH) ||
661 +                       (multipass->out_vsize > MAX_IMAGE_WIDTH)) {
662 +               dev_err(rsz_device, "Invalid output size!");
663 +               goto err_einval;
664 +       }
665 +       if (multipass->cbilin) {
666 +               rsz_conf_chan->register_config.rsz_cnt =
667 +                               BITSET(rsz_conf_chan->register_config.rsz_cnt,
668 +                               SET_BIT_CBLIN);
669 +       }
670 +       if (INPUT_RAM) {
671 +               rsz_conf_chan->register_config.rsz_cnt =
672 +                               BITSET(rsz_conf_chan->register_config.rsz_cnt,
673 +                               SET_BIT_INPUTRAM);
674 +       }
675 +       if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
676 +               rsz_conf_chan->register_config.rsz_cnt =
677 +                               BITSET(rsz_conf_chan->register_config.rsz_cnt,
678 +                               SET_BIT_INPTYP);
679 +       } else {
680 +               rsz_conf_chan->register_config.rsz_cnt =
681 +                               BITRESET(rsz_conf_chan->register_config.
682 +                               rsz_cnt, SET_BIT_INPTYP);
683 +
684 +               if (multipass->pix_fmt == RSZ_PIX_FMT_UYVY) {
685 +                       rsz_conf_chan->register_config.rsz_cnt =
686 +                               BITRESET(rsz_conf_chan->register_config.
687 +                               rsz_cnt, SET_BIT_YCPOS);
688 +               } else if (multipass->pix_fmt == RSZ_PIX_FMT_YUYV) {
689 +                       rsz_conf_chan->register_config.rsz_cnt =
690 +                                       BITSET(rsz_conf_chan->register_config.
691 +                                       rsz_cnt, SET_BIT_YCPOS);
692 +               }
693 +
694 +       }
695 +       multipass->vrsz =
696 +               (multipass->in_vsize * RATIO_MULTIPLIER) / multipass->out_vsize;
697 +       multipass->hrsz =
698 +               (multipass->in_hsize * RATIO_MULTIPLIER) / multipass->out_hsize;
699 +       if (UP_RSZ_RATIO > multipass->vrsz || UP_RSZ_RATIO > multipass->hrsz) {
700 +               dev_err(rsz_device, "Upscaling ratio not supported!");
701 +               goto err_einval;
702 +       }
703 +       multipass->vrsz = (multipass->in_vsize - NUM_D2TAPS) * RATIO_MULTIPLIER
704 +                                               / (multipass->out_vsize - 1);
705 +       multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
706 +                                               * RATIO_MULTIPLIER) /
707 +                                               (multipass->out_hsize - 1);
708 +
709 +       if (multipass->hrsz <= 512) {
710 +               multipass->hrsz = (multipass->in_hsize - NUM_TAPS)
711 +                                               * RATIO_MULTIPLIER
712 +                                               / (multipass->out_hsize - 1);
713 +               if (multipass->hrsz < 64)
714 +                       multipass->hrsz = 64;
715 +               if (multipass->hrsz > 512)
716 +                       multipass->hrsz = 512;
717 +               if (multipass->hstph > NUM_PHASES)
718 +                       goto err_einval;
719 +               multipass->num_htap = 1;
720 +       } else if (multipass->hrsz >= 513 && multipass->hrsz <= 1024) {
721 +               if (multipass->hstph > NUM_D2PH)
722 +                       goto err_einval;
723 +               multipass->num_htap = 0;
724 +       }
725 +
726 +       if (multipass->vrsz <= 512) {
727 +               multipass->vrsz = (multipass->in_vsize - NUM_TAPS)
728 +                                               * RATIO_MULTIPLIER
729 +                                               / (multipass->out_vsize - 1);
730 +               if (multipass->vrsz < 64)
731 +                       multipass->vrsz = 64;
732 +               if (multipass->vrsz > 512)
733 +                       multipass->vrsz = 512;
734 +               if (multipass->vstph > NUM_PHASES)
735 +                       goto err_einval;
736 +               multipass->num_vtap = 1;
737 +       } else if (multipass->vrsz >= 513 && multipass->vrsz <= 1024) {
738 +               if (multipass->vstph > NUM_D2PH)
739 +                       goto err_einval;
740 +               multipass->num_vtap = 0;
741 +       }
742 +
743 +       if ((multipass->in_pitch) % ALIGN32) {
744 +               dev_err(rsz_device, "Invalid input pitch: %d \n",
745 +                                                       multipass->in_pitch);
746 +               goto err_einval;
747 +       }
748 +       if ((multipass->out_pitch) % ALIGN32) {
749 +               dev_err(rsz_device, "Invalid output pitch %d \n",
750 +                                                       multipass->out_pitch);
751 +               goto err_einval;
752 +       }
753 +
754 +       if (multipass->vrsz < 256 &&
755 +                       (multipass->in_vsize < multipass->out_vsize)) {
756 +               if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT)
757 +                       alignment = ALIGNMENT;
758 +               else if (multipass->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
759 +                       alignment = (ALIGNMENT / 2);
760 +               else
761 +                       dev_err(rsz_device, "Invalid input type\n");
762 +
763 +               if (!(((multipass->out_hsize % PIXEL_EVEN) == 0)
764 +                               && (multipass->out_hsize % alignment) == 0)) {
765 +                       dev_err(rsz_device, "wrong hsize\n");
766 +                       goto err_einval;
767 +               }
768 +       }
769 +       if (multipass->hrsz >= 64 && multipass->hrsz <= 1024) {
770 +               if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
771 +                       dev_err(rsz_device, "wrong width\n");
772 +                       goto err_einval;
773 +               }
774 +               multipass->active = 0;
775 +
776 +       } else if (multipass->hrsz > 1024) {
777 +               if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
778 +                       dev_err(rsz_device, "wrong width\n");
779 +                       goto err_einval;
780 +               }
781 +               if (multipass->hstph > NUM_D2PH)
782 +                       goto err_einval;
783 +               multipass->num_htap = 0;
784 +               multipass->out_hsize = multipass->in_hsize * 256 / 1024;
785 +               if (multipass->out_hsize % ALIGN32) {
786 +                       multipass->out_hsize +=
787 +                               abs((multipass->out_hsize % ALIGN32) - ALIGN32);
788 +               }
789 +               multipass->out_pitch = ((multipass->inptyp) ?
790 +                                               multipass->out_hsize :
791 +                                               (multipass->out_hsize * 2));
792 +               multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
793 +                                               * RATIO_MULTIPLIER)
794 +                                               / (multipass->out_hsize - 1);
795 +               multipass->active = 1;
796 +
797 +       }
798 +
799 +       if (multipass->vrsz > 1024) {
800 +               if (multipass->out_vsize > MAX_IMAGE_WIDTH_HIGH) {
801 +                       dev_err(rsz_device, "wrong width\n");
802 +                       goto err_einval;
803 +               }
804 +
805 +               multipass->out_vsize = multipass->in_vsize * 256 / 1024;
806 +               multipass->vrsz = ((multipass->in_vsize - NUM_D2TAPS)
807 +                                               * RATIO_MULTIPLIER)
808 +                                               / (multipass->out_vsize - 1);
809 +               multipass->active = 1;
810 +               multipass->num_vtap = 0;
811 +
812 +       }
813 +       rsz_conf_chan->register_config.rsz_out_size =
814 +                                               multipass->out_hsize
815 +                                               & ISPRSZ_OUT_SIZE_HORZ_MASK;
816 +
817 +       rsz_conf_chan->register_config.rsz_out_size |=
818 +                                               (multipass->out_vsize
819 +                                               << ISPRSZ_OUT_SIZE_VERT_SHIFT)
820 +                                               & ISPRSZ_OUT_SIZE_VERT_MASK;
821 +
822 +       rsz_conf_chan->register_config.rsz_sdr_inoff =
823 +                                               multipass->in_pitch
824 +                                               & ISPRSZ_SDR_INOFF_OFFSET_MASK;
825 +
826 +       rsz_conf_chan->register_config.rsz_sdr_outoff =
827 +                                       multipass->out_pitch
828 +                                       & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
829 +
830 +       if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
831 +               if (multipass->hstph > NUM_PHASES)
832 +                       goto err_einval;
833 +       } else if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
834 +               if (multipass->hstph > NUM_D2PH)
835 +                       goto err_einval;
836 +       }
837 +
838 +       rsz_conf_chan->register_config.rsz_cnt |=
839 +                                               (multipass->hstph
840 +                                               << ISPRSZ_CNT_HSTPH_SHIFT)
841 +                                               & ISPRSZ_CNT_HSTPH_MASK;
842 +
843 +       if (multipass->vrsz >= 64 && multipass->hrsz <= 512) {
844 +               if (multipass->vstph > NUM_PHASES)
845 +                       goto err_einval;
846 +       } else if (multipass->vrsz >= 64 && multipass->vrsz <= 512) {
847 +               if (multipass->vstph > NUM_D2PH)
848 +                       goto err_einval;
849 +       }
850 +
851 +       rsz_conf_chan->register_config.rsz_cnt |=
852 +                                               (multipass->vstph
853 +                                               << ISPRSZ_CNT_VSTPH_SHIFT)
854 +                                               & ISPRSZ_CNT_VSTPH_MASK;
855 +
856 +       rsz_conf_chan->register_config.rsz_cnt |=
857 +                                               (multipass->hrsz - 1)
858 +                                               & ISPRSZ_CNT_HRSZ_MASK;
859 +
860 +       rsz_conf_chan->register_config.rsz_cnt |=
861 +                                               ((multipass->vrsz - 1)
862 +                                               << ISPRSZ_CNT_VRSZ_SHIFT)
863 +                                               & ISPRSZ_CNT_VRSZ_MASK;
864 +
865 +       return 0;
866 +err_einval:
867 +       return -EINVAL;
868 +}
869 +
870 +/**
871 + * rsz_config_ratio - Configure ratio
872 + * @rsz_conf_chan: Structure containing channel configuration
873 + *
874 + * Configure ratio
875 + **/
876 +static void rsz_config_ratio(struct rsz_mult *multipass,
877 +                               struct channel_config *rsz_conf_chan)
878 +{
879 +       int hsize;
880 +       int vsize;
881 +       int coeffcounter;
882 +
883 +       if (multipass->hrsz <= 512) {
884 +               hsize = ((32 * multipass->hstph + (multipass->out_hsize - 1)
885 +                                       * multipass->hrsz + 16) >> 8) + 7;
886 +       } else {
887 +               hsize = ((64 * multipass->hstph + (multipass->out_hsize - 1)
888 +                                       * multipass->hrsz + 32) >> 8) + 7;
889 +       }
890 +       if (multipass->vrsz <= 512) {
891 +               vsize = ((32 * multipass->vstph + (multipass->out_vsize - 1)
892 +                                       * multipass->vrsz + 16) >> 8) + 4;
893 +       } else {
894 +               vsize = ((64 * multipass->vstph + (multipass->out_vsize - 1)
895 +                                       * multipass->vrsz + 32) >> 8) + 7;
896 +       }
897 +       rsz_conf_chan->register_config.rsz_in_size = hsize;
898 +
899 +       rsz_conf_chan->register_config.rsz_in_size |=
900 +                                       ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT)
901 +                                       & ISPRSZ_IN_SIZE_VERT_MASK);
902 +
903 +       for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
904 +                                                       coeffcounter++) {
905 +               if (multipass->num_htap) {
906 +                       rsz_conf_chan->register_config.
907 +                                       rsz_coeff_horz[coeffcounter] =
908 +                                       (multipass->tap4filt_coeffs[2
909 +                                       * coeffcounter]
910 +                                       & ISPRSZ_HFILT10_COEF0_MASK);
911 +                       rsz_conf_chan->register_config.
912 +                                       rsz_coeff_horz[coeffcounter] |=
913 +                                       ((multipass->tap4filt_coeffs[2
914 +                                       * coeffcounter + 1]
915 +                                       << ISPRSZ_HFILT10_COEF1_SHIFT)
916 +                                       & ISPRSZ_HFILT10_COEF1_MASK);
917 +               } else {
918 +                       rsz_conf_chan->register_config.
919 +                                       rsz_coeff_horz[coeffcounter] =
920 +                                       (multipass->tap7filt_coeffs[2
921 +                                       * coeffcounter]
922 +                                       & ISPRSZ_HFILT10_COEF0_MASK);
923 +
924 +                       rsz_conf_chan->register_config.
925 +                                       rsz_coeff_horz[coeffcounter] |=
926 +                                       ((multipass->tap7filt_coeffs[2
927 +                                       * coeffcounter + 1]
928 +                                       << ISPRSZ_HFILT10_COEF1_SHIFT)
929 +                                       & ISPRSZ_HFILT10_COEF1_MASK);
930 +               }
931 +
932 +               if (multipass->num_vtap) {
933 +                       rsz_conf_chan->register_config.
934 +                                       rsz_coeff_vert[coeffcounter] =
935 +                                       (multipass->tap4filt_coeffs[2
936 +                                       * coeffcounter]
937 +                                       & ISPRSZ_VFILT10_COEF0_MASK);
938 +
939 +                       rsz_conf_chan->register_config.
940 +                                       rsz_coeff_vert[coeffcounter] |=
941 +                                       ((multipass->tap4filt_coeffs[2
942 +                                       * coeffcounter + 1]
943 +                                       << ISPRSZ_VFILT10_COEF1_SHIFT) &
944 +                                       ISPRSZ_VFILT10_COEF1_MASK);
945 +               } else {
946 +                       rsz_conf_chan->register_config.
947 +                                       rsz_coeff_vert[coeffcounter] =
948 +                                       (multipass->tap7filt_coeffs[2
949 +                                       * coeffcounter]
950 +                                       & ISPRSZ_VFILT10_COEF0_MASK);
951 +                       rsz_conf_chan->register_config.
952 +                                       rsz_coeff_vert[coeffcounter] |=
953 +                                       ((multipass->tap7filt_coeffs[2
954 +                                       * coeffcounter + 1]
955 +                                       << ISPRSZ_VFILT10_COEF1_SHIFT)
956 +                                       & ISPRSZ_VFILT10_COEF1_MASK);
957 +               }
958 +       }
959 +}
960 +
961 +/**
962 + * rsz_get_params - Gets the parameter values
963 + * @params: Structure containing the Resizer Wrapper parameters
964 + * @rsz_conf_chan: Structure containing channel configuration
965 + *
966 + * Used to get the Resizer hardware settings associated with the
967 + * current logical channel represented by fd.
968 + **/
969 +static int rsz_get_params(struct rsz_params *params,
970 +                                       struct channel_config *rsz_conf_chan)
971 +{
972 +       int coeffcounter;
973 +
974 +       if (rsz_conf_chan->config_state) {
975 +               dev_err(rsz_device, "state not configured\n");
976 +               return -EINVAL;
977 +       }
978 +
979 +       params->in_hsize = rsz_conf_chan->register_config.rsz_in_size
980 +                                       & ISPRSZ_IN_SIZE_HORZ_MASK;
981 +       params->in_vsize = (rsz_conf_chan->register_config.rsz_in_size
982 +                                       & ISPRSZ_IN_SIZE_VERT_MASK)
983 +                                       >> ISPRSZ_IN_SIZE_VERT_SHIFT;
984 +
985 +       params->in_pitch = rsz_conf_chan->register_config.rsz_sdr_inoff
986 +                                       & ISPRSZ_SDR_INOFF_OFFSET_MASK;
987 +
988 +       params->out_hsize = rsz_conf_chan->register_config.rsz_out_size
989 +                                       & ISPRSZ_OUT_SIZE_HORZ_MASK;
990 +
991 +       params->out_vsize = (rsz_conf_chan->register_config.rsz_out_size
992 +                                       & ISPRSZ_OUT_SIZE_VERT_MASK)
993 +                                       >> ISPRSZ_OUT_SIZE_VERT_SHIFT;
994 +
995 +       params->out_pitch = rsz_conf_chan->register_config.rsz_sdr_outoff
996 +                                       & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
997 +
998 +       params->cbilin = (rsz_conf_chan->register_config.rsz_cnt
999 +                                       & SET_BIT_CBLIN) >> SET_BIT_CBLIN;
1000 +
1001 +       params->inptyp = (rsz_conf_chan->register_config.rsz_cnt
1002 +                                       & ISPRSZ_CNT_INPTYP_MASK)
1003 +                                       >> SET_BIT_INPTYP;
1004 +       params->horz_starting_pixel = ((rsz_conf_chan->register_config.
1005 +                                       rsz_in_start
1006 +                                       & ISPRSZ_IN_START_HORZ_ST_MASK));
1007 +       params->vert_starting_pixel = ((rsz_conf_chan->register_config.
1008 +                                       rsz_in_start
1009 +                                       & ISPRSZ_IN_START_VERT_ST_MASK)
1010 +                                       >> ISPRSZ_IN_START_VERT_ST_SHIFT);
1011 +
1012 +       params->hstph = ((rsz_conf_chan->register_config.rsz_cnt
1013 +                                       & ISPRSZ_CNT_HSTPH_MASK
1014 +                                       >> ISPRSZ_CNT_HSTPH_SHIFT));
1015 +       params->vstph = ((rsz_conf_chan->register_config.rsz_cnt
1016 +                                       & ISPRSZ_CNT_VSTPH_MASK
1017 +                                       >> ISPRSZ_CNT_VSTPH_SHIFT));
1018 +
1019 +       for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
1020 +                                                       coeffcounter++) {
1021 +               params->tap4filt_coeffs[2 * coeffcounter] =
1022 +                                       rsz_conf_chan->register_config.
1023 +                                       rsz_coeff_horz[coeffcounter]
1024 +                                       & ISPRSZ_HFILT10_COEF0_MASK;
1025 +
1026 +               params->tap4filt_coeffs[2 * coeffcounter + 1] =
1027 +                                       (rsz_conf_chan->register_config.
1028 +                                       rsz_coeff_horz[coeffcounter]
1029 +                                       & ISPRSZ_HFILT10_COEF1_MASK)
1030 +                                       >> ISPRSZ_HFILT10_COEF1_SHIFT;
1031 +
1032 +               params->tap7filt_coeffs[2 * coeffcounter] =
1033 +                                       rsz_conf_chan->register_config.
1034 +                                       rsz_coeff_vert[coeffcounter]
1035 +                                       & ISPRSZ_VFILT10_COEF0_MASK;
1036 +
1037 +               params->tap7filt_coeffs[2 * coeffcounter + 1] =
1038 +                                       (rsz_conf_chan->register_config.
1039 +                                       rsz_coeff_vert[coeffcounter]
1040 +                                       & ISPRSZ_VFILT10_COEF1_MASK)
1041 +                                       >> ISPRSZ_VFILT10_COEF1_SHIFT;
1042 +
1043 +       }
1044 +
1045 +       params->yenh_params.type = (rsz_conf_chan->register_config.rsz_yehn
1046 +                                       & ISPRSZ_YENH_ALGO_MASK)
1047 +                                       >> ISPRSZ_YENH_ALGO_SHIFT;
1048 +
1049 +       params->yenh_params.core = rsz_conf_chan->register_config.rsz_yehn
1050 +                                       & ISPRSZ_YENH_CORE_MASK;
1051 +
1052 +       params->yenh_params.gain = (rsz_conf_chan->register_config.rsz_yehn
1053 +                                       & ISPRSZ_YENH_GAIN_MASK)
1054 +                                       >> ISPRSZ_YENH_GAIN_SHIFT;
1055 +
1056 +       params->yenh_params.slop = (rsz_conf_chan->register_config.rsz_yehn
1057 +                                       & ISPRSZ_YENH_SLOP_MASK)
1058 +                                       >> ISPRSZ_YENH_SLOP_SHIFT;
1059 +
1060 +       params->pix_fmt = ((rsz_conf_chan->register_config.rsz_cnt
1061 +                                       & ISPRSZ_CNT_PIXFMT_MASK)
1062 +                                       >> SET_BIT_YCPOS);
1063 +
1064 +       if (params->pix_fmt)
1065 +               params->pix_fmt = RSZ_PIX_FMT_UYVY;
1066 +       else
1067 +               params->pix_fmt = RSZ_PIX_FMT_YUYV;
1068 +
1069 +       return 0;
1070 +}
1071 +
1072 +/**
1073 + * rsz_calculate_crop - Calculate Crop values
1074 + * @rsz_conf_chan: Structure containing channel configuration
1075 + * @cropsize: Structure containing crop parameters
1076 + *
1077 + * Calculate Crop values
1078 + **/
1079 +static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
1080 +                                               struct rsz_cropsize *cropsize)
1081 +{
1082 +       int luma_enable;
1083 +
1084 +       cropsize->hcrop = 0;
1085 +       cropsize->vcrop = 0;
1086 +
1087 +       luma_enable = (rsz_conf_chan->register_config.rsz_yehn
1088 +                                               & ISPRSZ_YENH_ALGO_MASK)
1089 +                                               >> ISPRSZ_YENH_ALGO_SHIFT;
1090 +
1091 +       if (luma_enable)
1092 +               cropsize->hcrop += 2;
1093 +}
1094 +
1095 +/**
1096 + * rsz_vbq_release - Videobuffer queue release
1097 + * @q: Structure containing the videobuffer queue file handle, and device
1098 + *     structure which contains the actual configuration.
1099 + * @vb: Structure containing the videobuffer used for resizer processing.
1100 + **/
1101 +static void rsz_vbq_release(struct videobuf_queue *q,
1102 +                                               struct videobuf_buffer *vb)
1103 +{
1104 +       int i;
1105 +       struct rsz_fh *fh = q->priv_data;
1106 +
1107 +       for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1108 +               struct videobuf_dmabuf *dma = NULL;
1109 +               if (!q->bufs[i])
1110 +                       continue;
1111 +               if (q->bufs[i]->memory != V4L2_MEMORY_MMAP)
1112 +                       continue;
1113 +               dma = videobuf_to_dma(q->bufs[i]);
1114 +               videobuf_dma_unmap(q, dma);
1115 +               videobuf_dma_free(dma);
1116 +       }
1117 +
1118 +       ispmmu_unmap(fh->isp_addr_read);
1119 +       ispmmu_unmap(fh->isp_addr_write);
1120 +       fh->isp_addr_read = 0;
1121 +       fh->isp_addr_write = 0;
1122 +       spin_lock(&fh->vbq_lock);
1123 +       vb->state = VIDEOBUF_NEEDS_INIT;
1124 +       spin_unlock(&fh->vbq_lock);
1125 +
1126 +}
1127 +
1128 +/**
1129 + * rsz_vbq_setup - Sets up the videobuffer size and validates count.
1130 + * @q: Structure containing the videobuffer queue file handle, and device
1131 + *     structure which contains the actual configuration.
1132 + * @cnt: Number of buffers requested
1133 + * @size: Size in bytes of the buffer used for previewing
1134 + *
1135 + * Always returns 0.
1136 + **/
1137 +static int rsz_vbq_setup(struct videobuf_queue *q, unsigned int *cnt,
1138 +                                                       unsigned int *size)
1139 +{
1140 +       struct rsz_fh *fh = q->priv_data;
1141 +       struct rsz_mult *multipass = fh->multipass;
1142 +       u32 insize, outsize;
1143 +
1144 +       spin_lock(&fh->vbq_lock);
1145 +       if (*cnt <= 0)
1146 +               *cnt = VIDEO_MAX_FRAME;
1147 +
1148 +       if (*cnt > VIDEO_MAX_FRAME)
1149 +               *cnt = VIDEO_MAX_FRAME;
1150 +
1151 +       outsize = multipass->out_pitch * multipass->out_vsize;
1152 +       insize = multipass->in_pitch * multipass->in_vsize;
1153 +       if (*cnt == 1 && (outsize > insize)) {
1154 +               dev_err(rsz_device, "2 buffers are required for Upscaling "
1155 +                                                               "mode\n");
1156 +               goto err_einval;
1157 +       }
1158 +       if (!fh->params->in_hsize || !fh->params->in_vsize) {
1159 +               dev_err(rsz_device, "Can't setup buffer size\n");
1160 +               goto err_einval;
1161 +       } else {
1162 +               if (outsize > insize)
1163 +                       *size = outsize;
1164 +               else
1165 +                       *size = insize;
1166 +
1167 +               fh->rsz_bufsize = *size;
1168 +       }
1169 +       spin_unlock(&fh->vbq_lock);
1170 +
1171 +       return 0;
1172 +err_einval:
1173 +       spin_unlock(&fh->vbq_lock);
1174 +       return -EINVAL;
1175 +}
1176 +
1177 +/**
1178 + * rsz_vbq_prepare - Videobuffer is prepared and mmapped.
1179 + * @q: Structure containing the videobuffer queue file handle, and device
1180 + *     structure which contains the actual configuration.
1181 + * @vb: Structure containing the videobuffer used for resizer processing.
1182 + * @field: Type of field to set in videobuffer device.
1183 + *
1184 + * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or
1185 + * -EIO if the ISP MMU mapping fails
1186 + **/
1187 +static int rsz_vbq_prepare(struct videobuf_queue *q,
1188 +                                               struct videobuf_buffer *vb,
1189 +                                               enum v4l2_field field)
1190 +{
1191 +       struct rsz_fh *fh = q->priv_data;
1192 +       struct channel_config *rsz_conf_chan = fh->config;
1193 +       struct rsz_mult *multipass = fh->multipass;
1194 +       int err = 0;
1195 +       unsigned int isp_addr, insize, outsize;
1196 +       struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
1197 +
1198 +       spin_lock(&fh->vbq_lock);
1199 +       if (vb->baddr) {
1200 +               vb->size = fh->rsz_bufsize;
1201 +               vb->bsize = fh->rsz_bufsize;
1202 +       } else {
1203 +               spin_unlock(&fh->vbq_lock);
1204 +               dev_err(rsz_device, "No user buffer allocated\n");
1205 +               goto out;
1206 +       }
1207 +       if (vb->i) {
1208 +               vb->width = fh->params->out_hsize;
1209 +               vb->height = fh->params->out_vsize;
1210 +       } else {
1211 +               vb->width = fh->params->in_hsize;
1212 +               vb->height = fh->params->in_vsize;
1213 +       }
1214 +
1215 +       vb->field = field;
1216 +       spin_unlock(&fh->vbq_lock);
1217 +
1218 +       if (vb->state == VIDEOBUF_NEEDS_INIT) {
1219 +               err = videobuf_iolock(q, vb, NULL);
1220 +               if (!err) {
1221 +                       isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
1222 +                       if (!isp_addr)
1223 +                               err = -EIO;
1224 +                       else {
1225 +                               if (vb->i) {
1226 +                                       rsz_conf_chan->register_config.
1227 +                                                       rsz_sdr_outadd
1228 +                                                       = isp_addr;
1229 +                                       fh->isp_addr_write = isp_addr;
1230 +                                       rsz_conf_chan->output_buf_index = vb->i;
1231 +                               } else {
1232 +                                       rsz_conf_chan->register_config.
1233 +                                                       rsz_sdr_inadd
1234 +                                                       = isp_addr;
1235 +                                       rsz_conf_chan->input_buf_index = vb->i;
1236 +                                       outsize = multipass->out_pitch *
1237 +                                                       multipass->out_vsize;
1238 +                                       insize = multipass->in_pitch *
1239 +                                                       multipass->in_vsize;
1240 +                                       if (outsize < insize) {
1241 +                                               rsz_conf_chan->register_config.
1242 +                                                               rsz_sdr_outadd
1243 +                                                               = isp_addr;
1244 +                                               rsz_conf_chan->
1245 +                                                       output_buf_index =
1246 +                                                       vb->i;
1247 +                                       }
1248 +
1249 +                                       fh->isp_addr_read = isp_addr;
1250 +                               }
1251 +                       }
1252 +               }
1253 +
1254 +       }
1255 +
1256 +       if (!err) {
1257 +               spin_lock(&fh->vbq_lock);
1258 +               vb->state = VIDEOBUF_PREPARED;
1259 +               spin_unlock(&fh->vbq_lock);
1260 +               flush_cache_user_range(NULL, vb->baddr, (vb->baddr
1261 +                                                               + vb->bsize));
1262 +       } else
1263 +               rsz_vbq_release(q, vb);
1264 +
1265 +out:
1266 +       return err;
1267 +}
1268 +
1269 +static void rsz_vbq_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1270 +{
1271 +       return;
1272 +}
1273 +
1274 +/**
1275 + * rsz_open - Initializes and opens the Resizer Wrapper
1276 + * @inode: Inode structure associated with the Resizer Wrapper
1277 + * @filp: File structure associated with the Resizer Wrapper
1278 + *
1279 + * Returns 0 if successful, -EBUSY if its already opened or the ISP module is
1280 + * not available, or -ENOMEM if its unable to allocate the device in kernel
1281 + * space memory.
1282 + **/
1283 +static int rsz_open(struct inode *inode, struct file *filp)
1284 +{
1285 +       int ret = 0;
1286 +       struct channel_config *rsz_conf_chan;
1287 +       struct rsz_fh *fh;
1288 +       struct device_params *device = device_config;
1289 +       struct rsz_params *params;
1290 +       struct rsz_mult *multipass;
1291 +
1292 +       if ((filp->f_flags & O_NONBLOCK) == O_NONBLOCK) {
1293 +               printk(KERN_DEBUG "omap-resizer: Device is opened in "
1294 +                                       "non blocking mode\n");
1295 +       } else {
1296 +               printk(KERN_DEBUG "omap-resizer: Device is opened in blocking "
1297 +                                       "mode\n");
1298 +       }
1299 +       fh = kzalloc(sizeof(struct rsz_fh), GFP_KERNEL);
1300 +       if (NULL == fh)
1301 +               return -ENOMEM;
1302 +
1303 +       isp_get();
1304 +
1305 +       rsz_conf_chan = kzalloc(sizeof(struct channel_config), GFP_KERNEL);
1306 +       if (rsz_conf_chan == NULL) {
1307 +               dev_err(rsz_device, "\n cannot allocate memory to config");
1308 +               ret = -ENOMEM;
1309 +               goto err_enomem0;
1310 +       }
1311 +       params = kzalloc(sizeof(struct rsz_params), GFP_KERNEL);
1312 +       if (params == NULL) {
1313 +               dev_err(rsz_device, "\n cannot allocate memory to params");
1314 +               ret = -ENOMEM;
1315 +               goto err_enomem1;
1316 +       }
1317 +       multipass = kzalloc(sizeof(struct rsz_mult), GFP_KERNEL);
1318 +       if (multipass == NULL) {
1319 +               dev_err(rsz_device, "\n cannot allocate memory to multipass");
1320 +               ret = -ENOMEM;
1321 +               goto err_enomem2;
1322 +       }
1323 +
1324 +       fh->multipass = multipass;
1325 +       fh->params = params;
1326 +       fh->config = rsz_conf_chan;
1327 +
1328 +       if (mutex_lock_interruptible(&device->reszwrap_mutex)) {
1329 +               ret = -EINTR;
1330 +               goto err_enomem2;
1331 +       }
1332 +       device->opened++;
1333 +       mutex_unlock(&device->reszwrap_mutex);
1334 +
1335 +       rsz_conf_chan->config_state = STATE_NOT_CONFIGURED;
1336 +       rsz_conf_chan->status = CHANNEL_FREE;
1337 +
1338 +       filp->private_data = fh;
1339 +       fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1340 +       fh->device = device;
1341 +
1342 +       videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL,
1343 +                                       &fh->vbq_lock, fh->type,
1344 +                                       V4L2_FIELD_NONE,
1345 +                                       sizeof(struct videobuf_buffer), fh);
1346 +
1347 +       spin_lock_init(&fh->vbq_lock);
1348 +       mutex_init(&rsz_conf_chan->chanprotection_mutex);
1349 +
1350 +       return 0;
1351 +err_enomem2:
1352 +       kfree(params);
1353 +err_enomem1:
1354 +       kfree(rsz_conf_chan);
1355 +err_enomem0:
1356 +       kfree(fh);
1357 +       return ret;
1358 +}
1359 +
1360 +/**
1361 + * rsz_release - Releases Resizer Wrapper and frees up allocated memory
1362 + * @inode: Inode structure associated with the Resizer Wrapper
1363 + * @filp: File structure associated with the Resizer Wrapper
1364 + *
1365 + * Returns 0 if successful, or -EBUSY if channel is being used.
1366 + **/
1367 +static int rsz_release(struct inode *inode, struct file *filp)
1368 +{
1369 +       u32 timeout = 0;
1370 +       struct rsz_fh *fh = filp->private_data;
1371 +       struct channel_config *rsz_conf_chan = fh->config;
1372 +       struct rsz_params *params = fh->params;
1373 +       struct rsz_mult *multipass = fh->multipass;
1374 +       struct videobuf_queue *q = &fh->vbq;
1375 +
1376 +       while ((rsz_conf_chan->status != CHANNEL_FREE) && (timeout < 20)) {
1377 +               timeout++;
1378 +               schedule();
1379 +       }
1380 +       if (mutex_lock_interruptible(&device_config->reszwrap_mutex))
1381 +               return -EINTR;
1382 +       device_config->opened--;
1383 +       mutex_unlock(&device_config->reszwrap_mutex);
1384 +       /* This will Free memory allocated to the buffers,
1385 +        * and flushes the queue
1386 +        */
1387 +       videobuf_queue_cancel(q);
1388 +       fh->params = NULL;
1389 +       fh->config = NULL;
1390 +
1391 +       fh->rsz_bufsize = 0;
1392 +       filp->private_data = NULL;
1393 +
1394 +       kfree(rsz_conf_chan);
1395 +       kfree(params);
1396 +       kfree(multipass);
1397 +       kfree(fh);
1398 +
1399 +       isp_put();
1400 +
1401 +       return 0;
1402 +}
1403 +
1404 +/**
1405 + * rsz_mmap - Memory maps the Resizer Wrapper module.
1406 + * @file: File structure associated with the Resizer Wrapper
1407 + * @vma: Virtual memory area structure.
1408 + *
1409 + * Returns 0 if successful, or returned value by the videobuf_mmap_mapper()
1410 + * function.
1411 + **/
1412 +static int rsz_mmap(struct file *file, struct vm_area_struct *vma)
1413 +{
1414 +       struct rsz_fh *fh = file->private_data;
1415 +
1416 +       return videobuf_mmap_mapper(&fh->vbq, vma);
1417 +}
1418 +
1419 +/**
1420 + * rsz_ioctl - I/O control function for Resizer Wrapper
1421 + * @inode: Inode structure associated with the Resizer Wrapper.
1422 + * @file: File structure associated with the Resizer Wrapper.
1423 + * @cmd: Type of command to execute.
1424 + * @arg: Argument to send to requested command.
1425 + *
1426 + * Returns 0 if successful, -EBUSY if channel is being used, -1 if bad command
1427 + * passed or access is denied, -EFAULT if copy_from_user() or copy_to_user()
1428 + * fails, -EINVAL if parameter validation fails or parameter structure is not
1429 + * present.
1430 + **/
1431 +static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
1432 +                                                       unsigned long arg)
1433 +{
1434 +       int ret = 0;
1435 +       struct rsz_fh *fh = file->private_data;
1436 +       struct device_params *device = fh->device;
1437 +       struct channel_config *rsz_conf_chan = fh->config;
1438 +
1439 +       if ((_IOC_TYPE(cmd) != RSZ_IOC_BASE)
1440 +                                       || (_IOC_NR(cmd) > RSZ_IOC_MAXNR)) {
1441 +               dev_err(rsz_device, "Bad command value \n");
1442 +               return -1;
1443 +       }
1444 +
1445 +       if (_IOC_DIR(cmd) & _IOC_READ)
1446 +               ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
1447 +       else if (_IOC_DIR(cmd) & _IOC_WRITE)
1448 +               ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
1449 +
1450 +       if (ret) {
1451 +               dev_err(rsz_device, "Access denied\n");
1452 +               return -1;
1453 +       }
1454 +
1455 +       switch (cmd) {
1456 +       case RSZ_REQBUF:
1457 +       {
1458 +               struct v4l2_requestbuffers req_buf;
1459 +               if (copy_from_user(&req_buf, (struct v4l2_requestbuffers *)arg,
1460 +                                       sizeof(struct v4l2_requestbuffers))) {
1461 +                       return -EFAULT;
1462 +               }
1463 +               if (mutex_lock_interruptible(&rsz_conf_chan->
1464 +                                                       chanprotection_mutex))
1465 +                       return -EINTR;
1466 +               ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf);
1467 +               mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
1468 +               break;
1469 +       }
1470 +       case RSZ_QUERYBUF:
1471 +       {
1472 +               struct v4l2_buffer buf;
1473 +               if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
1474 +                                               sizeof(struct v4l2_buffer))) {
1475 +                       return -EFAULT;
1476 +               }
1477 +               if (mutex_lock_interruptible(&rsz_conf_chan->
1478 +                                                       chanprotection_mutex))
1479 +                       return -EINTR;
1480 +               ret = videobuf_querybuf(&fh->vbq, (void *)&buf);
1481 +               mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
1482 +               if (copy_to_user((struct v4l2_buffer *)arg, &buf,
1483 +                                               sizeof(struct v4l2_buffer)))
1484 +                       return -EFAULT;
1485 +               break;
1486 +       }
1487 +       case RSZ_QUEUEBUF:
1488 +       {
1489 +               struct v4l2_buffer buf;
1490 +               if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
1491 +                                               sizeof(struct v4l2_buffer))) {
1492 +                       return -EFAULT;
1493 +               }
1494 +               if (mutex_lock_interruptible(&rsz_conf_chan->
1495 +                                                       chanprotection_mutex))
1496 +                       return -EINTR;
1497 +               ret = videobuf_qbuf(&fh->vbq, (void *)&buf);
1498 +               mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
1499 +               break;
1500 +       }
1501 +       case RSZ_S_PARAM:
1502 +       {
1503 +               struct rsz_params *params = fh->params;
1504 +               if (copy_from_user(params, (struct rsz_params *)arg,
1505 +                                               sizeof(struct rsz_params))) {
1506 +                       return -EFAULT;
1507 +               }
1508 +               if (mutex_lock_interruptible(&rsz_conf_chan->
1509 +                                                       chanprotection_mutex))
1510 +                       return -EINTR;
1511 +               ret = rsz_set_params(fh->multipass, params, rsz_conf_chan);
1512 +               mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
1513 +               break;
1514 +       }
1515 +       case RSZ_G_PARAM:
1516 +               ret = rsz_get_params((struct rsz_params *)arg, rsz_conf_chan);
1517 +               break;
1518 +
1519 +       case RSZ_G_STATUS:
1520 +       {
1521 +               struct rsz_status *status;
1522 +               status = (struct rsz_status *)arg;
1523 +               status->chan_busy = rsz_conf_chan->status;
1524 +               status->hw_busy = ispresizer_busy();
1525 +               status->src = INPUT_RAM;
1526 +               break;
1527 +       }
1528 +       case RSZ_RESIZE:
1529 +               if (file->f_flags & O_NONBLOCK) {
1530 +                       if (ispresizer_busy())
1531 +                               return -EBUSY;
1532 +                       else {
1533 +                               if (!mutex_trylock(&device->reszwrap_mutex))
1534 +                                       return -EBUSY;
1535 +                       }
1536 +               } else {
1537 +                       if (mutex_lock_interruptible(&device->reszwrap_mutex))
1538 +                               return -EINTR;
1539 +               }
1540 +               ret = rsz_start((int *)arg, fh);
1541 +               mutex_unlock(&device->reszwrap_mutex);
1542 +               break;
1543 +       case RSZ_GET_CROPSIZE:
1544 +               rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg);
1545 +               break;
1546 +
1547 +       default:
1548 +               dev_err(rsz_device, "resizer_ioctl: Invalid Command Value");
1549 +               return -EINVAL;
1550 +       }
1551 +
1552 +       return (long)ret;
1553 +}
1554 +
1555 +static struct file_operations rsz_fops = {
1556 +       .owner = THIS_MODULE,
1557 +       .open = rsz_open,
1558 +       .release = rsz_release,
1559 +       .mmap = rsz_mmap,
1560 +       .unlocked_ioctl = rsz_unlocked_ioctl,
1561 +};
1562 +
1563 +/**
1564 + * rsz_isr - Interrupt Service Routine for Resizer wrapper
1565 + * @status: ISP IRQ0STATUS register value
1566 + * @arg1: Currently not used
1567 + * @arg2: Currently not used
1568 + *
1569 + * Interrupt Service Routine for Resizer wrapper
1570 + **/
1571 +static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2)
1572 +{
1573 +
1574 +       if ((status & RESZ_DONE) != RESZ_DONE)
1575 +               return;
1576 +
1577 +       complete(&(device_config->compl_isr));
1578 +
1579 +}
1580 +
1581 +/**
1582 + * resizer_platform_release - Acts when Reference count is zero
1583 + * @device: Structure containing ISP resizer wrapper global information
1584 + *
1585 + * This is called when the reference count goes to zero.
1586 + **/
1587 +static void resizer_platform_release(struct device *device)
1588 +{
1589 +}
1590 +
1591 +/**
1592 + * resizer_probe - Checks for device presence
1593 + * @device: Structure containing details of the current device.
1594 + *
1595 + * Always returns 0.
1596 + **/
1597 +static int __init resizer_probe(struct platform_device *device)
1598 +{
1599 +       return 0;
1600 +}
1601 +
1602 +/**
1603 + * resizer_remove - Handles the removal of the driver
1604 + * @omap_resizer_device: Structure containing details of the current device.
1605 + *
1606 + * Always returns 0.
1607 + **/
1608 +static int resizer_remove(struct platform_device *omap_resizer_device)
1609 +{
1610 +       return 0;
1611 +}
1612 +
1613 +static struct class *rsz_class;
1614 +static struct cdev c_dev;
1615 +static dev_t dev;
1616 +static struct platform_device omap_resizer_device = {
1617 +       .name = OMAP_REZR_NAME,
1618 +       .id = 2,
1619 +       .dev = {
1620 +               .release = resizer_platform_release,}
1621 +};
1622 +
1623 +static struct platform_driver omap_resizer_driver = {
1624 +       .probe = resizer_probe,
1625 +       .remove = resizer_remove,
1626 +       .driver = {
1627 +                       .bus = &platform_bus_type,
1628 +                       .name = OMAP_REZR_NAME,
1629 +       },
1630 +};
1631 +
1632 +/**
1633 + * omap_rsz_init - Initialization of Resizer Wrapper
1634 + *
1635 + * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if
1636 + * could not register the wrapper as a character device, or other errors if the
1637 + * device or driver can't register.
1638 + **/
1639 +static int __init omap_rsz_init(void)
1640 +{
1641 +       int ret = 0;
1642 +       struct device_params *device;
1643 +       device = kzalloc(sizeof(struct device_params), GFP_KERNEL);
1644 +       if (!device) {
1645 +               dev_err(rsz_device, OMAP_REZR_NAME ": could not allocate "
1646 +                                                               "memory\n");
1647 +               return -ENOMEM;
1648 +       }
1649 +
1650 +       ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME);
1651 +       if (ret < 0) {
1652 +               dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. "
1653 +                       "Could not allocate region "
1654 +                       "for character device\n");
1655 +               kfree(device);
1656 +               return -ENODEV;
1657 +       }
1658 +
1659 +       /* Register the driver in the kernel */
1660 +       /* Initialize of character device */
1661 +       cdev_init(&c_dev, &rsz_fops);
1662 +       c_dev.owner = THIS_MODULE;
1663 +       c_dev.ops = &rsz_fops;
1664 +
1665 +       /* Addding character device */
1666 +       ret = cdev_add(&c_dev, dev, 1);
1667 +       if (ret) {
1668 +               dev_err(rsz_device, OMAP_REZR_NAME ": Error adding "
1669 +                       "device - %d\n", ret);
1670 +               goto fail2;
1671 +       }
1672 +       rsz_major = MAJOR(dev);
1673 +
1674 +       /* register driver as a platform driver */
1675 +       ret = platform_driver_register(&omap_resizer_driver);
1676 +       if (ret) {
1677 +               dev_err(rsz_device, OMAP_REZR_NAME
1678 +                               ": Failed to register platform driver!\n");
1679 +               goto fail3;
1680 +       }
1681 +
1682 +       /* Register the drive as a platform device */
1683 +       ret = platform_device_register(&omap_resizer_device);
1684 +       if (ret) {
1685 +               dev_err(rsz_device, OMAP_REZR_NAME
1686 +                               ": Failed to register platform device!\n");
1687 +               goto fail4;
1688 +       }
1689 +
1690 +       rsz_class = class_create(THIS_MODULE, OMAP_REZR_NAME);
1691 +       if (!rsz_class) {
1692 +               dev_err(rsz_device, OMAP_REZR_NAME
1693 +                       ": Failed to create class!\n");
1694 +               goto fail5;
1695 +       }
1696 +
1697 +       /* make entry in the devfs */
1698 +       rsz_device = device_create(rsz_class, rsz_device,
1699 +                                               MKDEV(rsz_major, 0), NULL,
1700 +                                               OMAP_REZR_NAME);
1701 +       dev_dbg(rsz_device, OMAP_REZR_NAME ": Registered Resizer Wrapper\n");
1702 +       device->opened = 0;
1703 +
1704 +       device->vbq_ops.buf_setup = rsz_vbq_setup;
1705 +       device->vbq_ops.buf_prepare = rsz_vbq_prepare;
1706 +       device->vbq_ops.buf_release = rsz_vbq_release;
1707 +       device->vbq_ops.buf_queue = rsz_vbq_queue;
1708 +       init_completion(&device->compl_isr);
1709 +       mutex_init(&device->reszwrap_mutex);
1710 +
1711 +       device_config = device;
1712 +       return 0;
1713 +
1714 +fail5:
1715 +       platform_device_unregister(&omap_resizer_device);
1716 +fail4:
1717 +       platform_driver_unregister(&omap_resizer_driver);
1718 +fail3:
1719 +       cdev_del(&c_dev);
1720 +fail2:
1721 +       unregister_chrdev_region(dev, 1);
1722 +       kfree(device);
1723 +       return ret;
1724 +}
1725 +
1726 +/**
1727 + * omap_rsz_exit - Close of Resizer Wrapper
1728 + **/
1729 +void __exit omap_rsz_exit(void)
1730 +{
1731 +       device_destroy(rsz_class, dev);
1732 +       class_destroy(rsz_class);
1733 +       platform_device_unregister(&omap_resizer_device);
1734 +       platform_driver_unregister(&omap_resizer_driver);
1735 +       cdev_del(&c_dev);
1736 +       unregister_chrdev_region(dev, 1);
1737 +       kfree(device_config);
1738 +}
1739 +
1740 +module_init(omap_rsz_init)
1741 +module_exit(omap_rsz_exit)
1742 +
1743 +MODULE_AUTHOR("Texas Instruments");
1744 +MODULE_DESCRIPTION("OMAP ISP Resizer");
1745 +MODULE_LICENSE("GPL");
1746 diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h
1747 new file mode 100644
1748 index 0000000..5ac0c88
1749 --- /dev/null
1750 +++ b/include/linux/omap_resizer.h
1751 @@ -0,0 +1,136 @@
1752 +/*
1753 + * drivers/media/video/isp/omap_resizer.h
1754 + *
1755 + * Include file for Resizer module wrapper in TI's OMAP3430 ISP
1756 + *
1757 + * Copyright (C) 2008 Texas Instruments, Inc.
1758 + *
1759 + * This package is free software; you can redistribute it and/or modify
1760 + * it under the terms of the GNU General Public License version 2 as
1761 + * published by the Free Software Foundation.
1762 + *
1763 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1764 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1765 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1766 + */
1767 +
1768 +#ifndef OMAP_RESIZER_H
1769 +#define OMAP_RESIZER_H
1770 +
1771 +#include <linux/types.h>
1772 +
1773 +/* ioctls definition */
1774 +#define RSZ_IOC_BASE           'R'
1775 +#define RSZ_IOC_MAXNR          8
1776 +
1777 +/*Ioctl options which are to be passed while calling the ioctl*/
1778 +#define RSZ_REQBUF             _IOWR(RSZ_IOC_BASE, 1,\
1779 +                                       struct v4l2_requestbuffers)
1780 +#define RSZ_QUERYBUF           _IOWR(RSZ_IOC_BASE, 2, struct v4l2_buffer)
1781 +#define RSZ_S_PARAM            _IOWR(RSZ_IOC_BASE, 3, struct rsz_params)
1782 +#define RSZ_G_PARAM            _IOWR(RSZ_IOC_BASE, 4, struct rsz_params)
1783 +#define RSZ_RESIZE             _IOWR(RSZ_IOC_BASE, 5, __s32)
1784 +#define RSZ_G_STATUS           _IOWR(RSZ_IOC_BASE, 6, struct rsz_status)
1785 +#define RSZ_QUEUEBUF           _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer)
1786 +#define RSZ_GET_CROPSIZE       _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize)
1787 +
1788 +#define RSZ_INTYPE_YCBCR422_16BIT      0
1789 +#define RSZ_INTYPE_PLANAR_8BIT         1
1790 +#define RSZ_PIX_FMT_UYVY               1       /* cb:y:cr:y */
1791 +#define RSZ_PIX_FMT_YUYV               0       /* y:cb:y:cr */
1792 +
1793 +enum config_done {
1794 +       STATE_CONFIGURED,                       /* Resizer driver configured
1795 +                                                * by application.
1796 +                                                */
1797 +       STATE_NOT_CONFIGURED                    /* Resizer driver not
1798 +                                                * configured by application.
1799 +                                                */
1800 +};
1801 +
1802 +/* Structure Definitions */
1803 +
1804 +/* used to luma enhancement options */
1805 +
1806 +struct rsz_yenh {
1807 +       __s32 type;                             /* represents luma enable or
1808 +                                                * disable.
1809 +                                                */
1810 +       __u8 gain;                      /* represents gain. */
1811 +       __u8 slop;                      /* represents slop. */
1812 +       __u8 core;                      /* Represents core value. */
1813 +};
1814 +
1815 +/* Conatins all the parameters for resizing. This structure
1816 + * is used to configure resiser parameters
1817 + */
1818 +struct rsz_params {
1819 +       __s32 in_hsize;                         /* input frame horizontal
1820 +                                                * size.
1821 +                                                */
1822 +       __s32 in_vsize;                         /* input frame vertical size */
1823 +       __s32 in_pitch;                         /* offset between two rows of
1824 +                                                * input frame.
1825 +                                                */
1826 +       __s32 inptyp;                           /* for determining 16 bit or
1827 +                                                * 8 bit data.
1828 +                                                */
1829 +       __s32 vert_starting_pixel;              /* for specifying vertical
1830 +                                                * starting pixel in input.
1831 +                                                */
1832 +       __s32 horz_starting_pixel;              /* for specyfing horizontal
1833 +                                                * starting pixel in input.
1834 +                                                */
1835 +       __s32 cbilin;                           /* # defined, filter with luma
1836 +                                                * or bi-linear interpolation.
1837 +                                                */
1838 +       __s32 pix_fmt;                          /* # defined, UYVY or YUYV */
1839 +       __s32 out_hsize;                        /* output frame horizontal
1840 +                                                * size.
1841 +                                                */
1842 +       __s32 out_vsize;                                /* output frame vertical
1843 +                                                * size.
1844 +                                                */
1845 +       __s32 out_pitch;                        /* offset between two rows of
1846 +                                                * output frame.
1847 +                                                */
1848 +       __s32 hstph;                            /* for specifying horizontal
1849 +                                                * starting phase.
1850 +                                                */
1851 +       __s32 vstph;                            /* for specifying vertical
1852 +                                                * starting phase.
1853 +                                                */
1854 +       __u16 tap4filt_coeffs[32];              /* horizontal filter
1855 +                                                * coefficients.
1856 +                                                */
1857 +       __u16 tap7filt_coeffs[32];              /* vertical filter
1858 +                                                * coefficients.
1859 +                                                */
1860 +       struct rsz_yenh yenh_params;
1861 +};
1862 +
1863 +/* Contains the status of hardware and channel */
1864 +struct rsz_status {
1865 +       __s32 chan_busy;                                /* 1: channel is busy,
1866 +                                                * 0: channel is not busy
1867 +                                                */
1868 +       __s32 hw_busy;                          /* 1: hardware is busy,
1869 +                                                * 0: hardware is not busy
1870 +                                                */
1871 +       __s32 src;                              /* # defined, can be either
1872 +                                                * SD-RAM or CCDC/PREVIEWER
1873 +                                                */
1874 +};
1875 +
1876 +/* Passed by application for getting crop size */
1877 +struct rsz_cropsize {
1878 +       __u32 hcrop;                    /* Number of pixels per line
1879 +                                                * cropped in output image.
1880 +                                                */
1881 +
1882 +       __u32 vcrop;                    /* Number of lines cropped
1883 +                                                * in output image.
1884 +                                                */
1885 +};
1886 +
1887 +#endif
1888 -- 
1889 1.6.2.4
1890