linux-omap-pm 2.6.29: update to latest git HEAD, sync patches and defconfig with...
[openembedded.git] / recipes / linux / linux-omap-pm-2.6.29 / isp / omap3camera / 0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch
1 From 9a39eab5ed1b70711c3b10de95cd90749293ef7a Mon Sep 17 00:00:00 2001
2 From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3 Date: Tue, 10 Mar 2009 10:49:02 +0200
4 Subject: [PATCH] omap3isp: Add statistics collection modules (H3A and HIST)
5
6 Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7 ---
8  drivers/media/video/isp/isp_af.c  |  784 +++++++++++++++++++++++++++++++
9  drivers/media/video/isp/isp_af.h  |  125 +++++
10  drivers/media/video/isp/isph3a.c  |  932 +++++++++++++++++++++++++++++++++++++
11  drivers/media/video/isp/isph3a.h  |  127 +++++
12  drivers/media/video/isp/isphist.c |  608 ++++++++++++++++++++++++
13  drivers/media/video/isp/isphist.h |  105 +++++
14  6 files changed, 2681 insertions(+), 0 deletions(-)
15  create mode 100644 drivers/media/video/isp/isp_af.c
16  create mode 100644 drivers/media/video/isp/isp_af.h
17  create mode 100644 drivers/media/video/isp/isph3a.c
18  create mode 100644 drivers/media/video/isp/isph3a.h
19  create mode 100644 drivers/media/video/isp/isphist.c
20  create mode 100644 drivers/media/video/isp/isphist.h
21
22 diff --git a/drivers/media/video/isp/isp_af.c b/drivers/media/video/isp/isp_af.c
23 new file mode 100644
24 index 0000000..a607b97
25 --- /dev/null
26 +++ b/drivers/media/video/isp/isp_af.c
27 @@ -0,0 +1,784 @@
28 +/*
29 + * isp_af.c
30 + *
31 + * AF module for TI's OMAP3 Camera ISP
32 + *
33 + * Copyright (C) 2009 Texas Instruments, Inc.
34 + *
35 + * Contributors:
36 + *     Sergio Aguirre <saaguirre@ti.com>
37 + *     Troy Laramy
38 + *
39 + * This package is free software; you can redistribute it and/or modify
40 + * it under the terms of the GNU General Public License version 2 as
41 + * published by the Free Software Foundation.
42 + *
43 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
44 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
45 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
46 + */
47 +
48 +/* Linux specific include files */
49 +#include <asm/cacheflush.h>
50 +
51 +#include <linux/uaccess.h>
52 +#include <linux/dma-mapping.h>
53 +#include <asm/atomic.h>
54 +
55 +#include "isp.h"
56 +#include "ispreg.h"
57 +#include "isph3a.h"
58 +#include "isp_af.h"
59 +#include "ispmmu.h"
60 +
61 +/**
62 + * struct isp_af_buffer - AF frame stats buffer.
63 + * @virt_addr: Virtual address to mmap the buffer.
64 + * @phy_addr: Physical address of the buffer.
65 + * @addr_align: Virtual Address 32 bytes aligned.
66 + * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
67 + * @mmap_addr: Mapped memory area of buffer. For userspace access.
68 + * @locked: 1 - Buffer locked from write. 0 - Buffer can be overwritten.
69 + * @frame_num: Frame number from which the statistics are taken.
70 + * @lens_position: Lens position currently set in the DW9710 Coil motor driver.
71 + * @next: Pointer to link next buffer.
72 + */
73 +struct isp_af_buffer {
74 +       unsigned long virt_addr;
75 +       unsigned long phy_addr;
76 +       unsigned long addr_align;
77 +       unsigned long ispmmu_addr;
78 +       unsigned long mmap_addr;
79 +
80 +       u8 locked;
81 +       u16 frame_num;
82 +       u32 config_counter;
83 +       struct isp_af_xtrastats xtrastats;
84 +       struct isp_af_buffer *next;
85 +};
86 +
87 +/**
88 + * struct isp_af_status - AF status.
89 + * @initialized: 1 - Buffers initialized.
90 + * @update: 1 - Update registers.
91 + * @stats_req: 1 - Future stats requested.
92 + * @stats_done: 1 - Stats ready for user.
93 + * @frame_req: Number of frame requested for statistics.
94 + * @af_buff: Array of statistics buffers to access.
95 + * @stats_buf_size: Statistics buffer size.
96 + * @curr_cfg_buf_size: Current user configured stats buff size.
97 + * @min_buf_size: Minimum statisitics buffer size.
98 + * @frame_count: Frame Count.
99 + * @stats_wait: Wait primitive for locking/unlocking the stats request.
100 + * @buffer_lock: Spinlock for statistics buffers access.
101 + */
102 +static struct isp_af_status {
103 +       u8 initialized;
104 +       u8 update;
105 +       u8 stats_req;
106 +       u8 stats_done;
107 +       u16 frame_req;
108 +
109 +       struct isp_af_buffer af_buff[H3A_MAX_BUFF];
110 +       unsigned int stats_buf_size;
111 +       unsigned int min_buf_size;
112 +       unsigned int curr_cfg_buf_size;
113 +
114 +       int pm_state;
115 +       u32 frame_count;
116 +       wait_queue_head_t stats_wait;
117 +       atomic_t config_counter;
118 +       spinlock_t buffer_lock;         /* For stats buffers read/write sync */
119 +} afstat;
120 +
121 +struct af_device *af_dev_configptr;
122 +static struct isp_af_buffer *active_buff;
123 +static int af_major = -1;
124 +static int camnotify;
125 +
126 +/**
127 + * isp_af_setxtrastats - Receives extra statistics from prior frames.
128 + * @xtrastats: Pointer to structure containing extra statistics fields like
129 + *             field count and timestamp of frame.
130 + *
131 + * Called from update_vbq in camera driver
132 + **/
133 +void isp_af_setxtrastats(struct isp_af_xtrastats *xtrastats, u8 updateflag)
134 +{
135 +       int i, past_i;
136 +
137 +       if (active_buff == NULL)
138 +               return;
139 +
140 +       for (i = 0; i < H3A_MAX_BUFF; i++) {
141 +               if (afstat.af_buff[i].frame_num == active_buff->frame_num)
142 +                       break;
143 +       }
144 +
145 +       if (i == H3A_MAX_BUFF)
146 +               return;
147 +
148 +       if (i == 0) {
149 +               if (afstat.af_buff[H3A_MAX_BUFF - 1].locked == 0)
150 +                       past_i = H3A_MAX_BUFF - 1;
151 +               else
152 +                       past_i = H3A_MAX_BUFF - 2;
153 +       } else if (i == 1) {
154 +               if (afstat.af_buff[0].locked == 0)
155 +                       past_i = 0;
156 +               else
157 +                       past_i = H3A_MAX_BUFF - 1;
158 +       } else {
159 +               if (afstat.af_buff[i - 1].locked == 0)
160 +                       past_i = i - 1;
161 +               else
162 +                       past_i = i - 2;
163 +       }
164 +
165 +       if (updateflag & AF_UPDATEXS_TS)
166 +               afstat.af_buff[past_i].xtrastats.ts = xtrastats->ts;
167 +
168 +       if (updateflag & AF_UPDATEXS_FIELDCOUNT)
169 +               afstat.af_buff[past_i].xtrastats.field_count =
170 +                       xtrastats->field_count;
171 +}
172 +EXPORT_SYMBOL(isp_af_setxtrastats);
173 +
174 +/*
175 + * Helper function to update buffer cache pages
176 + */
177 +static void isp_af_update_req_buffer(struct isp_af_buffer *buffer)
178 +{
179 +       int size = afstat.stats_buf_size;
180 +
181 +       size = PAGE_ALIGN(size);
182 +       /* Update the kernel pages of the requested buffer */
183 +       dmac_inv_range((void *)buffer->addr_align, (void *)buffer->addr_align +
184 +                      size);
185 +}
186 +
187 +#define IS_OUT_OF_BOUNDS(value, min, max)              \
188 +       (((value) < (min)) || ((value) > (max)))
189 +
190 +/* Function to check paxel parameters */
191 +int isp_af_check_paxel(void)
192 +{
193 +       struct af_paxel *paxel_cfg = &af_dev_configptr->config->paxel_config;
194 +       struct af_iir *iir_cfg = &af_dev_configptr->config->iir_config;
195 +
196 +       /* Check horizontal Count */
197 +       if (IS_OUT_OF_BOUNDS(paxel_cfg->hz_cnt, AF_PAXEL_HORIZONTAL_COUNT_MIN,
198 +                            AF_PAXEL_HORIZONTAL_COUNT_MAX)) {
199 +               DPRINTK_ISP_AF("Error : Horizontal Count is incorrect");
200 +               return -AF_ERR_HZ_COUNT;
201 +       }
202 +
203 +       /*Check Vertical Count */
204 +       if (IS_OUT_OF_BOUNDS(paxel_cfg->vt_cnt, AF_PAXEL_VERTICAL_COUNT_MIN,
205 +                            AF_PAXEL_VERTICAL_COUNT_MAX)) {
206 +               DPRINTK_ISP_AF("Error : Vertical Count is incorrect");
207 +               return -AF_ERR_VT_COUNT;
208 +       }
209 +
210 +       /*Check Height */
211 +       if (IS_OUT_OF_BOUNDS(paxel_cfg->height, AF_PAXEL_HEIGHT_MIN,
212 +                            AF_PAXEL_HEIGHT_MAX)) {
213 +               DPRINTK_ISP_AF("Error : Height is incorrect");
214 +               return -AF_ERR_HEIGHT;
215 +       }
216 +
217 +       /*Check width */
218 +       if (IS_OUT_OF_BOUNDS(paxel_cfg->width, AF_PAXEL_WIDTH_MIN,
219 +                            AF_PAXEL_WIDTH_MAX)) {
220 +               DPRINTK_ISP_AF("Error : Width is incorrect");
221 +               return -AF_ERR_WIDTH;
222 +       }
223 +
224 +       /*Check Line Increment */
225 +       if (IS_OUT_OF_BOUNDS(paxel_cfg->line_incr, AF_PAXEL_INCREMENT_MIN,
226 +                            AF_PAXEL_INCREMENT_MAX)) {
227 +               DPRINTK_ISP_AF("Error : Line Increment is incorrect");
228 +               return -AF_ERR_INCR;
229 +       }
230 +
231 +       /*Check Horizontal Start */
232 +       if ((paxel_cfg->hz_start % 2 != 0) ||
233 +           (paxel_cfg->hz_start < (iir_cfg->hz_start_pos + 2)) ||
234 +           IS_OUT_OF_BOUNDS(paxel_cfg->hz_start,
235 +                            AF_PAXEL_HZSTART_MIN, AF_PAXEL_HZSTART_MAX)) {
236 +               DPRINTK_ISP_AF("Error : Horizontal Start is incorrect");
237 +               return -AF_ERR_HZ_START;
238 +       }
239 +
240 +       /*Check Vertical Start */
241 +       if (IS_OUT_OF_BOUNDS(paxel_cfg->vt_start, AF_PAXEL_VTSTART_MIN,
242 +                            AF_PAXEL_VTSTART_MAX)) {
243 +               DPRINTK_ISP_AF("Error : Vertical Start is incorrect");
244 +               return -AF_ERR_VT_START;
245 +       }
246 +       return 0;
247 +}
248 +
249 +/**
250 + * isp_af_check_iir - Function to check IIR Coefficient.
251 + **/
252 +int isp_af_check_iir(void)
253 +{
254 +       struct af_iir *iir_cfg = &af_dev_configptr->config->iir_config;
255 +       int index;
256 +
257 +       for (index = 0; index < AF_NUMBER_OF_COEF; index++) {
258 +               if ((iir_cfg->coeff_set0[index]) > AF_COEF_MAX) {
259 +                       DPRINTK_ISP_AF("Error : Coefficient for set 0 is "
260 +                                      "incorrect");
261 +                       return -AF_ERR_IIR_COEF;
262 +               }
263 +
264 +               if ((iir_cfg->coeff_set1[index]) > AF_COEF_MAX) {
265 +                       DPRINTK_ISP_AF("Error : Coefficient for set 1 is "
266 +                                      "incorrect");
267 +                       return -AF_ERR_IIR_COEF;
268 +               }
269 +       }
270 +
271 +       if (IS_OUT_OF_BOUNDS(iir_cfg->hz_start_pos, AF_IIRSH_MIN,
272 +                            AF_IIRSH_MAX)) {
273 +               DPRINTK_ISP_AF("Error : IIRSH is incorrect");
274 +               return -AF_ERR_IIRSH;
275 +       }
276 +
277 +       return 0;
278 +}
279 +/**
280 + * isp_af_unlock_buffers - Helper function to unlock all buffers.
281 + **/
282 +static void isp_af_unlock_buffers(void)
283 +{
284 +       int i;
285 +       unsigned long irqflags;
286 +
287 +       spin_lock_irqsave(&afstat.buffer_lock, irqflags);
288 +       for (i = 0; i < H3A_MAX_BUFF; i++)
289 +               afstat.af_buff[i].locked = 0;
290 +
291 +       spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
292 +}
293 +
294 +/*
295 + * Helper function to link allocated buffers
296 + */
297 +static void isp_af_link_buffers(void)
298 +{
299 +       int i;
300 +
301 +       for (i = 0; i < H3A_MAX_BUFF; i++) {
302 +               if ((i + 1) < H3A_MAX_BUFF)
303 +                       afstat.af_buff[i].next = &afstat.af_buff[i + 1];
304 +               else
305 +                       afstat.af_buff[i].next = &afstat.af_buff[0];
306 +       }
307 +}
308 +
309 +/* Function to perform hardware set up */
310 +int isp_af_configure(struct af_configuration *afconfig)
311 +{
312 +       int result;
313 +       int buff_size, i;
314 +       unsigned int busyaf;
315 +       struct af_configuration *af_curr_cfg = af_dev_configptr->config;
316 +
317 +       if (NULL == afconfig) {
318 +               printk(KERN_ERR "Null argument in configuration. \n");
319 +               return -EINVAL;
320 +       }
321 +
322 +       memcpy(af_curr_cfg, afconfig, sizeof(struct af_configuration));
323 +       /* Get the value of PCR register */
324 +       busyaf = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
325 +
326 +       if ((busyaf & AF_BUSYAF) == AF_BUSYAF) {
327 +               DPRINTK_ISP_AF("AF_register_setup_ERROR : Engine Busy");
328 +               DPRINTK_ISP_AF("\n Configuration cannot be done ");
329 +               return -AF_ERR_ENGINE_BUSY;
330 +       }
331 +
332 +       /* Check IIR Coefficient and start Values */
333 +       result = isp_af_check_iir();
334 +       if (result < 0)
335 +               return result;
336 +
337 +       /* Check Paxel Values */
338 +       result = isp_af_check_paxel();
339 +       if (result < 0)
340 +               return result;
341 +
342 +       /* Check HMF Threshold Values */
343 +       if (af_curr_cfg->hmf_config.threshold > AF_THRESHOLD_MAX) {
344 +               DPRINTK_ISP_AF("Error : HMF Threshold is incorrect");
345 +               return -AF_ERR_THRESHOLD;
346 +       }
347 +
348 +       /* Compute buffer size */
349 +       buff_size = (af_curr_cfg->paxel_config.hz_cnt + 1) *
350 +               (af_curr_cfg->paxel_config.vt_cnt + 1) * AF_PAXEL_SIZE;
351 +
352 +       afstat.curr_cfg_buf_size = buff_size;
353 +       /* Deallocate the previous buffers */
354 +       if (afstat.stats_buf_size && buff_size > afstat.stats_buf_size) {
355 +               isp_af_enable(0);
356 +               for (i = 0; i < H3A_MAX_BUFF; i++) {
357 +                       ispmmu_kunmap(afstat.af_buff[i].ispmmu_addr);
358 +                       dma_free_coherent(
359 +                               NULL, afstat.min_buf_size,
360 +                               (void *)afstat.af_buff[i].virt_addr,
361 +                               (dma_addr_t)afstat.af_buff[i].phy_addr);
362 +                       afstat.af_buff[i].virt_addr = 0;
363 +               }
364 +               afstat.stats_buf_size = 0;
365 +       }
366 +
367 +       if (!afstat.af_buff[0].virt_addr) {
368 +               afstat.stats_buf_size = buff_size;
369 +               afstat.min_buf_size = PAGE_ALIGN(afstat.stats_buf_size);
370 +
371 +               for (i = 0; i < H3A_MAX_BUFF; i++) {
372 +                       afstat.af_buff[i].virt_addr =
373 +                               (unsigned long)dma_alloc_coherent(
374 +                                       NULL,
375 +                                       afstat.min_buf_size,
376 +                                       (dma_addr_t *)
377 +                                       &afstat.af_buff[i].phy_addr,
378 +                                       GFP_KERNEL | GFP_DMA);
379 +                       if (afstat.af_buff[i].virt_addr == 0) {
380 +                               printk(KERN_ERR "Can't acquire memory for "
381 +                                      "buffer[%d]\n", i);
382 +                               return -ENOMEM;
383 +                       }
384 +                       afstat.af_buff[i].addr_align =
385 +                               afstat.af_buff[i].virt_addr;
386 +                       while ((afstat.af_buff[i].addr_align & 0xFFFFFFC0) !=
387 +                              afstat.af_buff[i].addr_align)
388 +                               afstat.af_buff[i].addr_align++;
389 +                       afstat.af_buff[i].ispmmu_addr =
390 +                               ispmmu_kmap(afstat.af_buff[i].phy_addr,
391 +                                           afstat.min_buf_size);
392 +               }
393 +               isp_af_unlock_buffers();
394 +               isp_af_link_buffers();
395 +
396 +               /* First active buffer */
397 +               if (active_buff == NULL)
398 +                       active_buff = &afstat.af_buff[0];
399 +               isp_af_set_address(active_buff->ispmmu_addr);
400 +       }
401 +
402 +       result = isp_af_register_setup(af_dev_configptr);
403 +       if (result < 0)
404 +               return result;
405 +       af_dev_configptr->size_paxel = buff_size;
406 +       atomic_inc(&afstat.config_counter);
407 +       afstat.initialized = 1;
408 +       afstat.frame_count = 1;
409 +       active_buff->frame_num = 1;
410 +       /* Set configuration flag to indicate HW setup done */
411 +       if (af_curr_cfg->af_config)
412 +               isp_af_enable(1);
413 +       else
414 +               isp_af_enable(0);
415 +
416 +       /* Success */
417 +       return 0;
418 +}
419 +EXPORT_SYMBOL(isp_af_configure);
420 +
421 +int isp_af_register_setup(struct af_device *af_dev)
422 +{
423 +       unsigned int pcr = 0, pax1 = 0, pax2 = 0, paxstart = 0;
424 +       unsigned int coef = 0;
425 +       unsigned int base_coef_set0 = 0;
426 +       unsigned int base_coef_set1 = 0;
427 +       int index;
428 +
429 +       /* Configure Hardware Registers */
430 +       /* Read PCR Register */
431 +       pcr = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
432 +
433 +       /* Set Accumulator Mode */
434 +       if (af_dev->config->mode == ACCUMULATOR_PEAK)
435 +               pcr |= FVMODE;
436 +       else
437 +               pcr &= ~FVMODE;
438 +
439 +       /* Set A-law */
440 +       if (af_dev->config->alaw_enable == H3A_AF_ALAW_ENABLE)
441 +               pcr |= AF_ALAW_EN;
442 +       else
443 +               pcr &= ~AF_ALAW_EN;
444 +
445 +       /* Set RGB Position */
446 +       pcr &= ~RGBPOS;
447 +       pcr |= af_dev->config->rgb_pos << AF_RGBPOS_SHIFT;
448 +
449 +       /* HMF Configurations */
450 +       if (af_dev->config->hmf_config.enable == H3A_AF_HMF_ENABLE) {
451 +               pcr &= ~AF_MED_EN;
452 +               /* Enable HMF */
453 +               pcr |= AF_MED_EN;
454 +
455 +               /* Set Median Threshold */
456 +               pcr &= ~MED_TH;
457 +               pcr |= af_dev->config->hmf_config.threshold << AF_MED_TH_SHIFT;
458 +       } else
459 +               pcr &= ~AF_MED_EN;
460 +
461 +       /* Set PCR Register */
462 +       isp_reg_writel(pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
463 +
464 +       pax1 &= ~PAXW;
465 +       pax1 |= af_dev->config->paxel_config.width << AF_PAXW_SHIFT;
466 +
467 +       /* Set height in AFPAX1 */
468 +       pax1 &= ~PAXH;
469 +       pax1 |= af_dev->config->paxel_config.height;
470 +
471 +       isp_reg_writel(pax1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1);
472 +
473 +       /* Configure AFPAX2 Register */
474 +       /* Set Line Increment in AFPAX2 Register */
475 +       pax2 &= ~AFINCV;
476 +       pax2 |= af_dev->config->paxel_config.line_incr << AF_LINE_INCR_SHIFT;
477 +       /* Set Vertical Count */
478 +       pax2 &= ~PAXVC;
479 +       pax2 |= af_dev->config->paxel_config.vt_cnt << AF_VT_COUNT_SHIFT;
480 +       /* Set Horizontal Count */
481 +       pax2 &= ~PAXHC;
482 +       pax2 |= af_dev->config->paxel_config.hz_cnt;
483 +       isp_reg_writel(pax2, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2);
484 +
485 +       /* Configure PAXSTART Register */
486 +       /*Configure Horizontal Start */
487 +       paxstart &= ~PAXSH;
488 +       paxstart |= af_dev->config->paxel_config.hz_start << AF_HZ_START_SHIFT;
489 +       /* Configure Vertical Start */
490 +       paxstart &= ~PAXSV;
491 +       paxstart |= af_dev->config->paxel_config.vt_start;
492 +       isp_reg_writel(paxstart, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAXSTART);
493 +
494 +       /*SetIIRSH Register */
495 +       isp_reg_writel(af_dev->config->iir_config.hz_start_pos,
496 +                      OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH);
497 +
498 +       /*Set IIR Filter0 Coefficients */
499 +       base_coef_set0 = ISPH3A_AFCOEF010;
500 +       for (index = 0; index <= 8; index += 2) {
501 +               coef &= ~COEF_MASK0;
502 +               coef |= af_dev->config->iir_config.coeff_set0[index];
503 +               coef &= ~COEF_MASK1;
504 +               coef |= af_dev->config->iir_config.coeff_set0[index + 1] <<
505 +                       AF_COEF_SHIFT;
506 +               isp_reg_writel(coef, OMAP3_ISP_IOMEM_H3A, base_coef_set0);
507 +               base_coef_set0 = base_coef_set0 + AFCOEF_OFFSET;
508 +       }
509 +
510 +       /* set AFCOEF0010 Register */
511 +       isp_reg_writel(af_dev->config->iir_config.coeff_set0[10],
512 +                      OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF010);
513 +
514 +       /*Set IIR Filter1 Coefficients */
515 +
516 +       base_coef_set1 = ISPH3A_AFCOEF110;
517 +       for (index = 0; index <= 8; index += 2) {
518 +               coef &= ~COEF_MASK0;
519 +               coef |= af_dev->config->iir_config.coeff_set1[index];
520 +               coef &= ~COEF_MASK1;
521 +               coef |= af_dev->config->iir_config.coeff_set1[index + 1] <<
522 +                       AF_COEF_SHIFT;
523 +               isp_reg_writel(coef, OMAP3_ISP_IOMEM_H3A, base_coef_set1);
524 +
525 +               base_coef_set1 = base_coef_set1 + AFCOEF_OFFSET;
526 +       }
527 +       isp_reg_writel(af_dev->config->iir_config.coeff_set1[10],
528 +                      OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010);
529 +
530 +       return 0;
531 +}
532 +
533 +/* Function to set address */
534 +void isp_af_set_address(unsigned long address)
535 +{
536 +       isp_reg_writel(address, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFBUFST);
537 +}
538 +
539 +static int isp_af_stats_available(struct isp_af_data *afdata)
540 +{
541 +       int i, ret;
542 +       unsigned long irqflags;
543 +
544 +       spin_lock_irqsave(&afstat.buffer_lock, irqflags);
545 +       for (i = 0; i < H3A_MAX_BUFF; i++) {
546 +               DPRINTK_ISP_AF("Checking Stats buff[%d] (%d) for %d\n",
547 +                              i, afstat.af_buff[i].frame_num,
548 +                              afdata->frame_number);
549 +               if (afdata->frame_number == afstat.af_buff[i].frame_num
550 +                   && afstat.af_buff[i].frame_num != active_buff->frame_num) {
551 +                       afstat.af_buff[i].locked = 1;
552 +                       spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
553 +                       isp_af_update_req_buffer(&afstat.af_buff[i]);
554 +                       afstat.af_buff[i].frame_num = 0;
555 +                       ret = copy_to_user((void *)afdata->af_statistics_buf,
556 +                                          (void *)afstat.af_buff[i].virt_addr,
557 +                                          afstat.curr_cfg_buf_size);
558 +                       if (ret) {
559 +                               printk(KERN_ERR "Failed copy_to_user for "
560 +                                      "H3A stats buff, %d\n", ret);
561 +                       }
562 +                       afdata->xtrastats.ts = afstat.af_buff[i].xtrastats.ts;
563 +                       afdata->xtrastats.field_count =
564 +                               afstat.af_buff[i].xtrastats.field_count;
565 +                       return 0;
566 +               }
567 +       }
568 +       spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
569 +       /* Stats unavailable */
570 +
571 +       return -1;
572 +}
573 +
574 +void isp_af_notify(int notify)
575 +{
576 +       camnotify = notify;
577 +       if (camnotify && afstat.initialized) {
578 +               printk(KERN_DEBUG "Warning Camera Off \n");
579 +               afstat.stats_req = 0;
580 +               afstat.stats_done = 1;
581 +               wake_up_interruptible(&afstat.stats_wait);
582 +       }
583 +}
584 +EXPORT_SYMBOL(isp_af_notify);
585 +/*
586 + * This API allows the user to update White Balance gains, as well as
587 + * exposure time and analog gain. It is also used to request frame
588 + * statistics.
589 + */
590 +int isp_af_request_statistics(struct isp_af_data *afdata)
591 +{
592 +       int ret = 0;
593 +       u16 frame_diff = 0;
594 +       u16 frame_cnt = afstat.frame_count;
595 +       wait_queue_t wqt;
596 +
597 +       if (!af_dev_configptr->config->af_config) {
598 +               printk(KERN_ERR "AF engine not enabled\n");
599 +               return -EINVAL;
600 +       }
601 +
602 +       if (!(afdata->update & REQUEST_STATISTICS)) {
603 +               afdata->af_statistics_buf = NULL;
604 +               goto out;
605 +       }
606 +
607 +       isp_af_unlock_buffers();
608 +       /* Stats available? */
609 +       DPRINTK_ISP_AF("Stats available?\n");
610 +       ret = isp_af_stats_available(afdata);
611 +       if (!ret)
612 +               goto out;
613 +
614 +       /* Stats in near future? */
615 +       DPRINTK_ISP_AF("Stats in near future?\n");
616 +       if (afdata->frame_number > frame_cnt)
617 +               frame_diff = afdata->frame_number - frame_cnt;
618 +       else if (afdata->frame_number < frame_cnt) {
619 +               if (frame_cnt > MAX_FRAME_COUNT - MAX_FUTURE_FRAMES
620 +                   && afdata->frame_number < MAX_FRAME_COUNT) {
621 +                       frame_diff = afdata->frame_number + MAX_FRAME_COUNT -
622 +                               frame_cnt;
623 +               } else {
624 +                       /* Frame unavailable */
625 +                       frame_diff = MAX_FUTURE_FRAMES + 1;
626 +               }
627 +       }
628 +
629 +       if (frame_diff > MAX_FUTURE_FRAMES) {
630 +               printk(KERN_ERR "Invalid frame requested, returning current"
631 +                      " frame stats\n");
632 +               afdata->frame_number = frame_cnt;
633 +       }
634 +       if (!camnotify) {
635 +               /* Block until frame in near future completes */
636 +               afstat.frame_req = afdata->frame_number;
637 +               afstat.stats_req = 1;
638 +               afstat.stats_done = 0;
639 +               init_waitqueue_entry(&wqt, current);
640 +               ret = wait_event_interruptible(afstat.stats_wait,
641 +                                              afstat.stats_done == 1);
642 +               if (ret < 0) {
643 +                       afdata->af_statistics_buf = NULL;
644 +                       return ret;
645 +               }
646 +               DPRINTK_ISP_AF("ISP AF request status interrupt raised\n");
647 +
648 +               /* Stats now available */
649 +               ret = isp_af_stats_available(afdata);
650 +               if (ret) {
651 +                       printk(KERN_ERR "After waiting for stats, stats not"
652 +                              " available!!\n");
653 +                       afdata->af_statistics_buf = NULL;
654 +               }
655 +       }
656 +
657 +out:
658 +       afdata->curr_frame = afstat.frame_count;
659 +
660 +       return 0;
661 +}
662 +EXPORT_SYMBOL(isp_af_request_statistics);
663 +
664 +/* This function will handle the H3A interrupt. */
665 +static void isp_af_isr(unsigned long status, isp_vbq_callback_ptr arg1,
666 +                      void *arg2)
667 +{
668 +       u16 frame_align;
669 +
670 +       if ((H3A_AF_DONE & status) != H3A_AF_DONE)
671 +               return;
672 +
673 +       /* timestamp stats buffer */
674 +       do_gettimeofday(&active_buff->xtrastats.ts);
675 +       active_buff->config_counter = atomic_read(&afstat.config_counter);
676 +
677 +       /* Exchange buffers */
678 +       active_buff = active_buff->next;
679 +       if (active_buff->locked == 1)
680 +               active_buff = active_buff->next;
681 +       isp_af_set_address(active_buff->ispmmu_addr);
682 +
683 +       /* Update frame counter */
684 +       afstat.frame_count++;
685 +       frame_align = afstat.frame_count;
686 +       if (afstat.frame_count > MAX_FRAME_COUNT) {
687 +               afstat.frame_count = 1;
688 +               frame_align++;
689 +       }
690 +       active_buff->frame_num = afstat.frame_count;
691 +
692 +       /* Future Stats requested? */
693 +       if (afstat.stats_req) {
694 +               /* Is the frame we want already done? */
695 +               if (frame_align >= afstat.frame_req + 1) {
696 +                       afstat.stats_req = 0;
697 +                       afstat.stats_done = 1;
698 +                       wake_up_interruptible(&afstat.stats_wait);
699 +               }
700 +       }
701 +}
702 +
703 +int __isp_af_enable(int enable)
704 +{
705 +       unsigned int pcr;
706 +
707 +       pcr = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
708 +
709 +       /* Set AF_EN bit in PCR Register */
710 +       if (enable) {
711 +               if (isp_set_callback(CBK_H3A_AF_DONE, isp_af_isr,
712 +                                    (void *)NULL, (void *)NULL)) {
713 +                       printk(KERN_ERR "No callback for AF\n");
714 +                       return -EINVAL;
715 +               }
716 +
717 +               pcr |= AF_EN;
718 +       } else {
719 +               isp_unset_callback(CBK_H3A_AF_DONE);
720 +               pcr &= ~AF_EN;
721 +       }
722 +       isp_reg_writel(pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
723 +       return 0;
724 +}
725 +
726 +/* Function to Enable/Disable AF Engine */
727 +int isp_af_enable(int enable)
728 +{
729 +       int rval;
730 +
731 +       rval = __isp_af_enable(enable);
732 +
733 +       if (!rval)
734 +               afstat.pm_state = enable;
735 +
736 +       return rval;
737 +}
738 +
739 +/* Function to Suspend AF Engine */
740 +void isp_af_suspend(void)
741 +{
742 +       if (afstat.pm_state)
743 +               __isp_af_enable(0);
744 +}
745 +
746 +/* Function to Resume AF Engine */
747 +void isp_af_resume(void)
748 +{
749 +       if (afstat.pm_state)
750 +               __isp_af_enable(1);
751 +}
752 +
753 +int isp_af_busy(void)
754 +{
755 +       return isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
756 +               & ISPH3A_PCR_BUSYAF;
757 +}
758 +
759 +/* Function to register the AF character device driver. */
760 +int __init isp_af_init(void)
761 +{
762 +       /*allocate memory for device structure and initialize it with 0 */
763 +       af_dev_configptr = kzalloc(sizeof(struct af_device), GFP_KERNEL);
764 +       if (!af_dev_configptr)
765 +               goto err_nomem1;
766 +
767 +       active_buff = NULL;
768 +
769 +       af_dev_configptr->config = (struct af_configuration *)
770 +               kzalloc(sizeof(struct af_configuration), GFP_KERNEL);
771 +
772 +       if (af_dev_configptr->config == NULL)
773 +               goto err_nomem2;
774 +
775 +       memset(&afstat, 0, sizeof(afstat));
776 +
777 +       init_waitqueue_head(&afstat.stats_wait);
778 +       spin_lock_init(&afstat.buffer_lock);
779 +
780 +       return 0;
781 +
782 +err_nomem2:
783 +       kfree(af_dev_configptr);
784 +err_nomem1:
785 +       printk(KERN_ERR "Error: kmalloc fail");
786 +       return -ENOMEM;
787 +}
788 +
789 +void isp_af_exit(void)
790 +{
791 +       int i;
792 +
793 +       /* Free buffers */
794 +       for (i = 0; i < H3A_MAX_BUFF; i++) {
795 +               if (!afstat.af_buff[i].phy_addr)
796 +                       continue;
797 +
798 +               ispmmu_kunmap(afstat.af_buff[i].ispmmu_addr);
799 +
800 +               dma_free_coherent(NULL,
801 +                                 afstat.min_buf_size,
802 +                                 (void *)afstat.af_buff[i].virt_addr,
803 +                                 (dma_addr_t)afstat.af_buff[i].phy_addr);
804 +       }
805 +       kfree(af_dev_configptr->config);
806 +       kfree(af_dev_configptr);
807 +
808 +       memset(&afstat, 0, sizeof(afstat));
809 +
810 +       af_major = -1;
811 +}
812 diff --git a/drivers/media/video/isp/isp_af.h b/drivers/media/video/isp/isp_af.h
813 new file mode 100644
814 index 0000000..ee2b89f
815 --- /dev/null
816 +++ b/drivers/media/video/isp/isp_af.h
817 @@ -0,0 +1,125 @@
818 +/*
819 + * isp_af.h
820 + *
821 + * Include file for AF module in TI's OMAP3 Camera ISP
822 + *
823 + * Copyright (C) 2009 Texas Instruments, Inc.
824 + *
825 + * Contributors:
826 + *     Sergio Aguirre <saaguirre@ti.com>
827 + *     Troy Laramy
828 + *
829 + * This package is free software; you can redistribute it and/or modify
830 + * it under the terms of the GNU General Public License version 2 as
831 + * published by the Free Software Foundation.
832 + *
833 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
834 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
835 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
836 + */
837 +
838 +/* Device Constants */
839 +#ifndef OMAP_ISP_AF_H
840 +#define OMAP_ISP_AF_H
841 +
842 +#include <mach/isp_user.h>
843 +
844 +#define AF_MAJOR_NUMBER                        0
845 +#define ISPAF_NAME                     "OMAPISP_AF"
846 +#define AF_NR_DEVS                     1
847 +#define AF_TIMEOUT                     ((300 * HZ) / 1000)
848 +
849 +
850 +
851 +/* Print Macros */
852 +/*list of error code */
853 +#define AF_ERR_HZ_COUNT                        800     /* Invalid Horizontal Count */
854 +#define AF_ERR_VT_COUNT                        801     /* Invalid Vertical Count */
855 +#define AF_ERR_HEIGHT                  802     /* Invalid Height */
856 +#define AF_ERR_WIDTH                   803     /* Invalid width */
857 +#define AF_ERR_INCR                    804     /* Invalid Increment */
858 +#define AF_ERR_HZ_START                        805     /* Invalid horizontal Start */
859 +#define AF_ERR_VT_START                        806     /* Invalud vertical Start */
860 +#define AF_ERR_IIRSH                   807     /* Invalid IIRSH value */
861 +#define AF_ERR_IIR_COEF                        808     /* Invalid Coefficient */
862 +#define AF_ERR_SETUP                   809     /* Setup not done */
863 +#define AF_ERR_THRESHOLD               810     /* Invalid Threshold */
864 +#define AF_ERR_ENGINE_BUSY             811     /* Engine is busy */
865 +
866 +#define AFPID                          0x0     /* Peripheral Revision
867 +                                                * and Class Information
868 +                                                */
869 +
870 +#define AFCOEF_OFFSET                  0x00000004      /* COEFFICIENT BASE
871 +                                                        * ADDRESS
872 +                                                        */
873 +
874 +/*
875 + * PCR fields
876 + */
877 +#define AF_BUSYAF                      (1 << 15)
878 +#define FVMODE                         (1 << 14)
879 +#define RGBPOS                         (0x7 << 11)
880 +#define MED_TH                         (0xFF << 3)
881 +#define AF_MED_EN                      (1 << 2)
882 +#define AF_ALAW_EN                     (1 << 1)
883 +#define AF_EN                          (1 << 0)
884 +
885 +/*
886 + * AFPAX1 fields
887 + */
888 +#define PAXW                           (0x7F << 16)
889 +#define PAXH                           0x7F
890 +
891 +/*
892 + * AFPAX2 fields
893 + */
894 +#define AFINCV                         (0xF << 13)
895 +#define PAXVC                          (0x7F << 6)
896 +#define PAXHC                          0x3F
897 +
898 +/*
899 + * AFPAXSTART fields
900 + */
901 +#define PAXSH                          (0xFFF<<16)
902 +#define PAXSV                          0xFFF
903 +
904 +/*
905 + * COEFFICIENT MASK
906 + */
907 +
908 +#define COEF_MASK0                     0xFFF
909 +#define COEF_MASK1                     (0xFFF<<16)
910 +
911 +/* BIT SHIFTS */
912 +#define AF_RGBPOS_SHIFT                        11
913 +#define AF_MED_TH_SHIFT                        3
914 +#define AF_PAXW_SHIFT                  16
915 +#define AF_LINE_INCR_SHIFT             13
916 +#define AF_VT_COUNT_SHIFT              6
917 +#define AF_HZ_START_SHIFT              16
918 +#define AF_COEF_SHIFT                  16
919 +
920 +#define AF_UPDATEXS_TS                 (1 << 0)
921 +#define AF_UPDATEXS_FIELDCOUNT (1 << 1)
922 +#define AF_UPDATEXS_LENSPOS            (1 << 2)
923 +
924 +/* Structure for device of AF Engine */
925 +struct af_device {
926 +       struct af_configuration *config; /*Device configuration structure */
927 +       int size_paxel;         /*Paxel size in bytes */
928 +};
929 +
930 +int isp_af_check_paxel(void);
931 +int isp_af_check_iir(void);
932 +int isp_af_register_setup(struct af_device *af_dev);
933 +int isp_af_enable(int);
934 +void isp_af_suspend(void);
935 +void isp_af_resume(void);
936 +int isp_af_busy(void);
937 +void isp_af_notify(int notify);
938 +int isp_af_request_statistics(struct isp_af_data *afdata);
939 +int isp_af_configure(struct af_configuration *afconfig);
940 +void isp_af_set_address(unsigned long);
941 +void isp_af_setxtrastats(struct isp_af_xtrastats *xtrastats, u8 updateflag);
942 +#endif /* OMAP_ISP_AF_H */
943 diff --git a/drivers/media/video/isp/isph3a.c b/drivers/media/video/isp/isph3a.c
944 new file mode 100644
945 index 0000000..7ff1c5b
946 --- /dev/null
947 +++ b/drivers/media/video/isp/isph3a.c
948 @@ -0,0 +1,932 @@
949 +/*
950 + * isph3a.c
951 + *
952 + * H3A module for TI's OMAP3 Camera ISP
953 + *
954 + * Copyright (C) 2009 Texas Instruments, Inc.
955 + *
956 + * Contributors:
957 + *     Sergio Aguirre <saaguirre@ti.com>
958 + *     Troy Laramy
959 + *
960 + * This package is free software; you can redistribute it and/or modify
961 + * it under the terms of the GNU General Public License version 2 as
962 + * published by the Free Software Foundation.
963 + *
964 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
965 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
966 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
967 + */
968 +
969 +#include <asm/cacheflush.h>
970 +
971 +#include <linux/dma-mapping.h>
972 +#include <linux/uaccess.h>
973 +
974 +#include "isp.h"
975 +#include "ispreg.h"
976 +#include "isph3a.h"
977 +#include "ispmmu.h"
978 +#include "isppreview.h"
979 +
980 +/**
981 + * struct isph3a_aewb_buffer - AE, AWB frame stats buffer.
982 + * @virt_addr: Virtual address to mmap the buffer.
983 + * @phy_addr: Physical address of the buffer.
984 + * @addr_align: Virtual Address 32 bytes aligned.
985 + * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
986 + * @mmap_addr: Mapped memory area of buffer. For userspace access.
987 + * @locked: 1 - Buffer locked from write. 0 - Buffer can be overwritten.
988 + * @frame_num: Frame number from which the statistics are taken.
989 + * @next: Pointer to link next buffer.
990 + */
991 +struct isph3a_aewb_buffer {
992 +       unsigned long virt_addr;
993 +       unsigned long phy_addr;
994 +       unsigned long addr_align;
995 +       unsigned long ispmmu_addr;
996 +       unsigned long mmap_addr;        /* For userspace */
997 +       struct timeval ts;
998 +       u32 config_counter;
999 +
1000 +       u8 locked;
1001 +       u16 frame_num;
1002 +       struct isph3a_aewb_buffer *next;
1003 +};
1004 +
1005 +/**
1006 + * struct isph3a_aewb_status - AE, AWB status.
1007 + * @initialized: 1 - Buffers initialized.
1008 + * @update: 1 - Update registers.
1009 + * @stats_req: 1 - Future stats requested.
1010 + * @stats_done: 1 - Stats ready for user.
1011 + * @frame_req: Number of frame requested for statistics.
1012 + * @h3a_buff: Array of statistics buffers to access.
1013 + * @stats_buf_size: Statistics buffer size.
1014 + * @min_buf_size: Minimum statisitics buffer size.
1015 + * @win_count: Window Count.
1016 + * @frame_count: Frame Count.
1017 + * @stats_wait: Wait primitive for locking/unlocking the stats request.
1018 + * @buffer_lock: Spinlock for statistics buffers access.
1019 + */
1020 +static struct isph3a_aewb_status {
1021 +       u8 initialized;
1022 +       u8 update;
1023 +       u8 stats_req;
1024 +       u8 stats_done;
1025 +       u16 frame_req;
1026 +       int pm_state;
1027 +
1028 +       struct isph3a_aewb_buffer h3a_buff[H3A_MAX_BUFF];
1029 +       unsigned int stats_buf_size;
1030 +       unsigned int min_buf_size;
1031 +       unsigned int curr_cfg_buf_size;
1032 +
1033 +       atomic_t config_counter;
1034 +
1035 +       u16 win_count;
1036 +       u32 frame_count;
1037 +       wait_queue_head_t stats_wait;
1038 +       spinlock_t buffer_lock;         /* For stats buffers read/write sync */
1039 +} aewbstat;
1040 +
1041 +/**
1042 + * struct isph3a_aewb_regs - Current value of AE, AWB configuration registers.
1043 + * reg_pcr: Peripheral control register.
1044 + * reg_win1: Control register.
1045 + * reg_start: Start position register.
1046 + * reg_blk: Black line register.
1047 + * reg_subwin: Configuration register.
1048 + */
1049 +static struct isph3a_aewb_regs {
1050 +       u32 reg_pcr;
1051 +       u32 reg_win1;
1052 +       u32 reg_start;
1053 +       u32 reg_blk;
1054 +       u32 reg_subwin;
1055 +} aewb_regs;
1056 +
1057 +static struct isph3a_aewb_config aewb_config_local = {
1058 +       .saturation_limit = 0x3FF,
1059 +       .win_height = 0,
1060 +       .win_width = 0,
1061 +       .ver_win_count = 0,
1062 +       .hor_win_count = 0,
1063 +       .ver_win_start = 0,
1064 +       .hor_win_start = 0,
1065 +       .blk_ver_win_start = 0,
1066 +       .blk_win_height = 0,
1067 +       .subsample_ver_inc = 0,
1068 +       .subsample_hor_inc = 0,
1069 +       .alaw_enable = 0,
1070 +       .aewb_enable = 0,
1071 +};
1072 +
1073 +/* Structure for saving/restoring h3a module registers */
1074 +static struct isp_reg isph3a_reg_list[] = {
1075 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, 0}, /* Should be the first one */
1076 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1, 0},
1077 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINSTART, 0},
1078 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK, 0},
1079 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWSUBWIN, 0},
1080 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST, 0},
1081 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1, 0},
1082 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2, 0},
1083 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAXSTART, 0},
1084 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH, 0},
1085 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFBUFST, 0},
1086 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF010, 0},
1087 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF032, 0},
1088 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF054, 0},
1089 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF076, 0},
1090 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF098, 0},
1091 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF0010, 0},
1092 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF110, 0},
1093 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF132, 0},
1094 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF154, 0},
1095 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF176, 0},
1096 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF198, 0},
1097 +       {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010, 0},
1098 +       {0, ISP_TOK_TERM, 0}
1099 +};
1100 +
1101 +static struct ispprev_wbal h3awb_update;
1102 +static struct isph3a_aewb_buffer *active_buff;
1103 +static struct isph3a_aewb_xtrastats h3a_xtrastats[H3A_MAX_BUFF];
1104 +static int camnotify;
1105 +static int wb_update;
1106 +static void isph3a_print_status(void);
1107 +
1108 +/**
1109 + * isph3a_aewb_setxtrastats - Receives extra statistics from prior frames.
1110 + * @xtrastats: Pointer to structure containing extra statistics fields like
1111 + *             field count and timestamp of frame.
1112 + *
1113 + * Called from update_vbq in camera driver
1114 + **/
1115 +void isph3a_aewb_setxtrastats(struct isph3a_aewb_xtrastats *xtrastats)
1116 +{
1117 +       int i;
1118 +
1119 +       if (active_buff == NULL)
1120 +               return;
1121 +
1122 +       for (i = 0; i < H3A_MAX_BUFF; i++) {
1123 +               if (aewbstat.h3a_buff[i].frame_num != active_buff->frame_num)
1124 +                       continue;
1125 +
1126 +               if (i == 0) {
1127 +                       if (aewbstat.h3a_buff[H3A_MAX_BUFF - 1].locked == 0) {
1128 +                               h3a_xtrastats[H3A_MAX_BUFF - 1] =
1129 +                                       *xtrastats;
1130 +                       } else {
1131 +                               h3a_xtrastats[H3A_MAX_BUFF - 2] =
1132 +                                       *xtrastats;
1133 +                       }
1134 +               } else if (i == 1) {
1135 +                       if (aewbstat.h3a_buff[0].locked == 0)
1136 +                               h3a_xtrastats[0] = *xtrastats;
1137 +                       else {
1138 +                               h3a_xtrastats[H3A_MAX_BUFF - 1] =
1139 +                                       *xtrastats;
1140 +                       }
1141 +               } else {
1142 +                       if (aewbstat.h3a_buff[i - 1].locked == 0)
1143 +                               h3a_xtrastats[i - 1] = *xtrastats;
1144 +                       else
1145 +                               h3a_xtrastats[i - 2] = *xtrastats;
1146 +               }
1147 +               return;
1148 +       }
1149 +}
1150 +EXPORT_SYMBOL(isph3a_aewb_setxtrastats);
1151 +
1152 +void __isph3a_aewb_enable(u8 enable)
1153 +{
1154 +       isp_reg_writel(IRQ0STATUS_H3A_AWB_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
1155 +                      ISP_IRQ0STATUS);
1156 +
1157 +       if (enable) {
1158 +               aewb_regs.reg_pcr |= ISPH3A_PCR_AEW_EN;
1159 +               DPRINTK_ISPH3A("    H3A enabled \n");
1160 +       } else {
1161 +               aewb_regs.reg_pcr &= ~ISPH3A_PCR_AEW_EN;
1162 +               DPRINTK_ISPH3A("    H3A disabled \n");
1163 +       }
1164 +       isp_reg_and_or(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, ~ISPH3A_PCR_AEW_EN,
1165 +                      (enable ? ISPH3A_PCR_AEW_EN : 0));
1166 +       aewb_config_local.aewb_enable = enable;
1167 +}
1168 +
1169 +/**
1170 + * isph3a_aewb_enable - Enables AE, AWB engine in the H3A module.
1171 + * @enable: 1 - Enables the AE & AWB engine.
1172 + *
1173 + * Client should configure all the AE & AWB registers in H3A before this.
1174 + **/
1175 +void isph3a_aewb_enable(u8 enable)
1176 +{
1177 +       __isph3a_aewb_enable(enable);
1178 +       aewbstat.pm_state = enable;
1179 +}
1180 +
1181 +/**
1182 + * isph3a_aewb_suspend - Suspend AE, AWB engine in the H3A module.
1183 + **/
1184 +void isph3a_aewb_suspend(void)
1185 +{
1186 +       if (aewbstat.pm_state)
1187 +               __isph3a_aewb_enable(0);
1188 +}
1189 +
1190 +/**
1191 + * isph3a_aewb_resume - Resume AE, AWB engine in the H3A module.
1192 + **/
1193 +void isph3a_aewb_resume(void)
1194 +{
1195 +       if (aewbstat.pm_state)
1196 +               __isph3a_aewb_enable(1);
1197 +}
1198 +
1199 +int isph3a_aewb_busy(void)
1200 +{
1201 +       return isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
1202 +               & ISPH3A_PCR_BUSYAEAWB;
1203 +}
1204 +
1205 +/**
1206 + * isph3a_update_wb - Updates WB parameters.
1207 + *
1208 + * Needs to be called when no ISP Preview processing is taking place.
1209 + **/
1210 +void isph3a_update_wb(void)
1211 +{
1212 +       if (wb_update) {
1213 +               isppreview_config_whitebalance(h3awb_update);
1214 +               wb_update = 0;
1215 +       }
1216 +       return;
1217 +}
1218 +EXPORT_SYMBOL(isph3a_update_wb);
1219 +
1220 +/**
1221 + * isph3a_aewb_update_regs - Helper function to update h3a registers.
1222 + **/
1223 +static void isph3a_aewb_update_regs(void)
1224 +{
1225 +       isp_reg_writel(aewb_regs.reg_pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
1226 +       isp_reg_writel(aewb_regs.reg_win1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1);
1227 +       isp_reg_writel(aewb_regs.reg_start, OMAP3_ISP_IOMEM_H3A,
1228 +                      ISPH3A_AEWINSTART);
1229 +       isp_reg_writel(aewb_regs.reg_blk, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK);
1230 +       isp_reg_writel(aewb_regs.reg_subwin, OMAP3_ISP_IOMEM_H3A,
1231 +                      ISPH3A_AEWSUBWIN);
1232 +
1233 +       aewbstat.update = 0;
1234 +       aewbstat.frame_count = 1;
1235 +}
1236 +
1237 +/**
1238 + * isph3a_aewb_update_req_buffer - Helper function to update buffer cache pages
1239 + * @buffer: Pointer to structure
1240 + **/
1241 +static void isph3a_aewb_update_req_buffer(struct isph3a_aewb_buffer *buffer)
1242 +{
1243 +       int size = aewbstat.stats_buf_size;
1244 +
1245 +       size = PAGE_ALIGN(size);
1246 +       dmac_inv_range((void *)buffer->addr_align,
1247 +                      (void *)buffer->addr_align + size);
1248 +}
1249 +
1250 +/**
1251 + * isph3a_aewb_stats_available - Check for stats available of specified frame.
1252 + * @aewbdata: Pointer to return AE AWB statistics data
1253 + *
1254 + * Returns 0 if successful, or -1 if statistics are unavailable.
1255 + **/
1256 +static int isph3a_aewb_stats_available(struct isph3a_aewb_data *aewbdata)
1257 +{
1258 +       int i, ret;
1259 +       unsigned long irqflags;
1260 +
1261 +       spin_lock_irqsave(&aewbstat.buffer_lock, irqflags);
1262 +       for (i = 0; i < H3A_MAX_BUFF; i++) {
1263 +               DPRINTK_ISPH3A("Checking Stats buff[%d] (%d) for %d\n",
1264 +                              i, aewbstat.h3a_buff[i].frame_num,
1265 +                              aewbdata->frame_number);
1266 +               if ((aewbdata->frame_number !=
1267 +                    aewbstat.h3a_buff[i].frame_num) ||
1268 +                   (aewbstat.h3a_buff[i].frame_num ==
1269 +                    active_buff->frame_num))
1270 +                       continue;
1271 +               aewbstat.h3a_buff[i].locked = 1;
1272 +               spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
1273 +               isph3a_aewb_update_req_buffer(&aewbstat.h3a_buff[i]);
1274 +               aewbstat.h3a_buff[i].frame_num = 0;
1275 +               ret = copy_to_user((void *)aewbdata->h3a_aewb_statistics_buf,
1276 +                                  (void *)aewbstat.h3a_buff[i].virt_addr,
1277 +                                  aewbstat.curr_cfg_buf_size);
1278 +               if (ret) {
1279 +                       printk(KERN_ERR "Failed copy_to_user for "
1280 +                              "H3A stats buff, %d\n", ret);
1281 +               }
1282 +               aewbdata->ts = aewbstat.h3a_buff[i].ts;
1283 +               aewbdata->config_counter = aewbstat.h3a_buff[i].config_counter;
1284 +               aewbdata->field_count = h3a_xtrastats[i].field_count;
1285 +               return 0;
1286 +       }
1287 +       spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
1288 +
1289 +       return -1;
1290 +}
1291 +
1292 +/**
1293 + * isph3a_aewb_link_buffers - Helper function to link allocated buffers.
1294 + **/
1295 +static void isph3a_aewb_link_buffers(void)
1296 +{
1297 +       int i;
1298 +
1299 +       for (i = 0; i < H3A_MAX_BUFF; i++) {
1300 +               if ((i + 1) < H3A_MAX_BUFF) {
1301 +                       aewbstat.h3a_buff[i].next = &aewbstat.h3a_buff[i + 1];
1302 +                       h3a_xtrastats[i].next = &h3a_xtrastats[i + 1];
1303 +               } else {
1304 +                       aewbstat.h3a_buff[i].next = &aewbstat.h3a_buff[0];
1305 +                       h3a_xtrastats[i].next = &h3a_xtrastats[0];
1306 +               }
1307 +       }
1308 +}
1309 +
1310 +/**
1311 + * isph3a_aewb_unlock_buffers - Helper function to unlock all buffers.
1312 + **/
1313 +static void isph3a_aewb_unlock_buffers(void)
1314 +{
1315 +       int i;
1316 +       unsigned long irqflags;
1317 +
1318 +       spin_lock_irqsave(&aewbstat.buffer_lock, irqflags);
1319 +       for (i = 0; i < H3A_MAX_BUFF; i++)
1320 +               aewbstat.h3a_buff[i].locked = 0;
1321 +
1322 +       spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
1323 +}
1324 +
1325 +/**
1326 + * isph3a_aewb_isr - Callback from ISP driver for H3A AEWB interrupt.
1327 + * @status: IRQ0STATUS in case of MMU error, 0 for H3A interrupt.
1328 + * @arg1: Not used as of now.
1329 + * @arg2: Not used as of now.
1330 + */
1331 +static void isph3a_aewb_isr(unsigned long status, isp_vbq_callback_ptr arg1,
1332 +                           void *arg2)
1333 +{
1334 +       u16 frame_align;
1335 +
1336 +       if ((H3A_AWB_DONE & status) != H3A_AWB_DONE)
1337 +               return;
1338 +
1339 +       do_gettimeofday(&active_buff->ts);
1340 +       active_buff->config_counter = atomic_read(&aewbstat.config_counter);
1341 +       active_buff = active_buff->next;
1342 +       if (active_buff->locked == 1)
1343 +               active_buff = active_buff->next;
1344 +       isp_reg_writel(active_buff->ispmmu_addr, OMAP3_ISP_IOMEM_H3A,
1345 +                      ISPH3A_AEWBUFST);
1346 +
1347 +       aewbstat.frame_count++;
1348 +       frame_align = aewbstat.frame_count;
1349 +       if (aewbstat.frame_count > MAX_FRAME_COUNT) {
1350 +               aewbstat.frame_count = 1;
1351 +               frame_align++;
1352 +       }
1353 +       active_buff->frame_num = aewbstat.frame_count;
1354 +
1355 +       if (aewbstat.stats_req) {
1356 +               DPRINTK_ISPH3A("waiting for frame %d\n", aewbstat.frame_req);
1357 +               if (frame_align >= aewbstat.frame_req + 1) {
1358 +                       aewbstat.stats_req = 0;
1359 +                       aewbstat.stats_done = 1;
1360 +                       wake_up_interruptible(&aewbstat.stats_wait);
1361 +               }
1362 +       }
1363 +
1364 +       if (aewbstat.update)
1365 +               isph3a_aewb_update_regs();
1366 +}
1367 +
1368 +/**
1369 + * isph3a_aewb_set_params - Helper function to check & store user given params.
1370 + * @user_cfg: Pointer to AE and AWB parameters struct.
1371 + *
1372 + * As most of them are busy-lock registers, need to wait until AEW_BUSY = 0 to
1373 + * program them during ISR.
1374 + *
1375 + * Returns 0 if successful, or -EINVAL if any of the parameters are invalid.
1376 + **/
1377 +static int isph3a_aewb_set_params(struct isph3a_aewb_config *user_cfg)
1378 +{
1379 +       if (unlikely(user_cfg->saturation_limit > MAX_SATURATION_LIM)) {
1380 +               printk(KERN_ERR "Invalid Saturation_limit: %d\n",
1381 +                      user_cfg->saturation_limit);
1382 +               return -EINVAL;
1383 +       }
1384 +       if (aewb_config_local.saturation_limit != user_cfg->saturation_limit) {
1385 +               WRITE_SAT_LIM(aewb_regs.reg_pcr, user_cfg->saturation_limit);
1386 +               aewb_config_local.saturation_limit =
1387 +                       user_cfg->saturation_limit;
1388 +               aewbstat.update = 1;
1389 +       }
1390 +
1391 +       if (aewb_config_local.alaw_enable != user_cfg->alaw_enable) {
1392 +               WRITE_ALAW(aewb_regs.reg_pcr, user_cfg->alaw_enable);
1393 +               aewb_config_local.alaw_enable = user_cfg->alaw_enable;
1394 +               aewbstat.update = 1;
1395 +       }
1396 +
1397 +       if (unlikely(user_cfg->win_height < MIN_WIN_H ||
1398 +                    user_cfg->win_height > MAX_WIN_H ||
1399 +                    user_cfg->win_height & 0x01)) {
1400 +               printk(KERN_ERR "Invalid window height: %d\n",
1401 +                      user_cfg->win_height);
1402 +               return -EINVAL;
1403 +       }
1404 +       if (aewb_config_local.win_height != user_cfg->win_height) {
1405 +               WRITE_WIN_H(aewb_regs.reg_win1, user_cfg->win_height);
1406 +               aewb_config_local.win_height = user_cfg->win_height;
1407 +               aewbstat.update = 1;
1408 +       }
1409 +
1410 +       if (unlikely(user_cfg->win_width < MIN_WIN_W ||
1411 +                    user_cfg->win_width > MAX_WIN_W ||
1412 +                    user_cfg->win_width & 0x01)) {
1413 +               printk(KERN_ERR "Invalid window width: %d\n",
1414 +                      user_cfg->win_width);
1415 +               return -EINVAL;
1416 +       }
1417 +       if (aewb_config_local.win_width != user_cfg->win_width) {
1418 +               WRITE_WIN_W(aewb_regs.reg_win1, user_cfg->win_width);
1419 +               aewb_config_local.win_width = user_cfg->win_width;
1420 +               aewbstat.update = 1;
1421 +       }
1422 +
1423 +       if (unlikely(user_cfg->ver_win_count < 1 ||
1424 +                    user_cfg->ver_win_count > MAX_WINVC)) {
1425 +               printk(KERN_ERR "Invalid vertical window count: %d\n",
1426 +                      user_cfg->ver_win_count);
1427 +               return -EINVAL;
1428 +       }
1429 +       if (aewb_config_local.ver_win_count != user_cfg->ver_win_count) {
1430 +               WRITE_VER_C(aewb_regs.reg_win1, user_cfg->ver_win_count);
1431 +               aewb_config_local.ver_win_count = user_cfg->ver_win_count;
1432 +               aewbstat.update = 1;
1433 +       }
1434 +
1435 +       if (unlikely(user_cfg->hor_win_count < 1 ||
1436 +                    user_cfg->hor_win_count > MAX_WINHC)) {
1437 +               printk(KERN_ERR "Invalid horizontal window count: %d\n",
1438 +                      user_cfg->hor_win_count);
1439 +               return -EINVAL;
1440 +       }
1441 +       if (aewb_config_local.hor_win_count != user_cfg->hor_win_count) {
1442 +               WRITE_HOR_C(aewb_regs.reg_win1, user_cfg->hor_win_count);
1443 +               aewb_config_local.hor_win_count = user_cfg->hor_win_count;
1444 +               aewbstat.update = 1;
1445 +       }
1446 +
1447 +       if (unlikely(user_cfg->ver_win_start > MAX_WINSTART)) {
1448 +               printk(KERN_ERR "Invalid vertical window start: %d\n",
1449 +                      user_cfg->ver_win_start);
1450 +               return -EINVAL;
1451 +       }
1452 +       if (aewb_config_local.ver_win_start != user_cfg->ver_win_start) {
1453 +               WRITE_VER_WIN_ST(aewb_regs.reg_start, user_cfg->ver_win_start);
1454 +               aewb_config_local.ver_win_start = user_cfg->ver_win_start;
1455 +               aewbstat.update = 1;
1456 +       }
1457 +
1458 +       if (unlikely(user_cfg->hor_win_start > MAX_WINSTART)) {
1459 +               printk(KERN_ERR "Invalid horizontal window start: %d\n",
1460 +                      user_cfg->hor_win_start);
1461 +               return -EINVAL;
1462 +       }
1463 +       if (aewb_config_local.hor_win_start != user_cfg->hor_win_start) {
1464 +               WRITE_HOR_WIN_ST(aewb_regs.reg_start, user_cfg->hor_win_start);
1465 +               aewb_config_local.hor_win_start = user_cfg->hor_win_start;
1466 +               aewbstat.update = 1;
1467 +       }
1468 +
1469 +       if (unlikely(user_cfg->blk_ver_win_start > MAX_WINSTART)) {
1470 +               printk(KERN_ERR "Invalid black vertical window start: %d\n",
1471 +                      user_cfg->blk_ver_win_start);
1472 +               return -EINVAL;
1473 +       }
1474 +       if (aewb_config_local.blk_ver_win_start !=
1475 +           user_cfg->blk_ver_win_start) {
1476 +               WRITE_BLK_VER_WIN_ST(aewb_regs.reg_blk,
1477 +                                    user_cfg->blk_ver_win_start);
1478 +               aewb_config_local.blk_ver_win_start =
1479 +                       user_cfg->blk_ver_win_start;
1480 +               aewbstat.update = 1;
1481 +       }
1482 +
1483 +       if (unlikely(user_cfg->blk_win_height < MIN_WIN_H ||
1484 +                    user_cfg->blk_win_height > MAX_WIN_H ||
1485 +                    user_cfg->blk_win_height & 0x01)) {
1486 +               printk(KERN_ERR "Invalid black window height: %d\n",
1487 +                      user_cfg->blk_win_height);
1488 +               return -EINVAL;
1489 +       }
1490 +       if (aewb_config_local.blk_win_height != user_cfg->blk_win_height) {
1491 +               WRITE_BLK_WIN_H(aewb_regs.reg_blk, user_cfg->blk_win_height);
1492 +               aewb_config_local.blk_win_height = user_cfg->blk_win_height;
1493 +               aewbstat.update = 1;
1494 +       }
1495 +
1496 +       if (unlikely(user_cfg->subsample_ver_inc < MIN_SUB_INC ||
1497 +                    user_cfg->subsample_ver_inc > MAX_SUB_INC ||
1498 +                    user_cfg->subsample_ver_inc & 0x01)) {
1499 +               printk(KERN_ERR "Invalid vertical subsample increment: %d\n",
1500 +                      user_cfg->subsample_ver_inc);
1501 +               return -EINVAL;
1502 +       }
1503 +       if (aewb_config_local.subsample_ver_inc !=
1504 +           user_cfg->subsample_ver_inc) {
1505 +               WRITE_SUB_VER_INC(aewb_regs.reg_subwin,
1506 +                                 user_cfg->subsample_ver_inc);
1507 +               aewb_config_local.subsample_ver_inc =
1508 +                       user_cfg->subsample_ver_inc;
1509 +               aewbstat.update = 1;
1510 +       }
1511 +
1512 +       if (unlikely(user_cfg->subsample_hor_inc < MIN_SUB_INC ||
1513 +                    user_cfg->subsample_hor_inc > MAX_SUB_INC ||
1514 +                    user_cfg->subsample_hor_inc & 0x01)) {
1515 +               printk(KERN_ERR "Invalid horizontal subsample increment: %d\n",
1516 +                      user_cfg->subsample_hor_inc);
1517 +               return -EINVAL;
1518 +       }
1519 +       if (aewb_config_local.subsample_hor_inc !=
1520 +           user_cfg->subsample_hor_inc) {
1521 +               WRITE_SUB_HOR_INC(aewb_regs.reg_subwin,
1522 +                                 user_cfg->subsample_hor_inc);
1523 +               aewb_config_local.subsample_hor_inc =
1524 +                       user_cfg->subsample_hor_inc;
1525 +               aewbstat.update = 1;
1526 +       }
1527 +
1528 +       if (!aewbstat.initialized || !aewb_config_local.aewb_enable) {
1529 +               isph3a_aewb_update_regs();
1530 +               aewbstat.initialized = 1;
1531 +       }
1532 +       return 0;
1533 +}
1534 +
1535 +/**
1536 + * isph3a_aewb_configure - Configure AEWB regs, enable/disable H3A engine.
1537 + * @aewbcfg: Pointer to AEWB config structure.
1538 + *
1539 + * Returns 0 if successful, -EINVAL if aewbcfg pointer is NULL, -ENOMEM if
1540 + * was unable to allocate memory for the buffer, of other errors if H3A
1541 + * callback is not set or the parameters for AEWB are invalid.
1542 + **/
1543 +int isph3a_aewb_configure(struct isph3a_aewb_config *aewbcfg)
1544 +{
1545 +       int ret = 0;
1546 +       int i;
1547 +       int win_count = 0;
1548 +
1549 +       if (NULL == aewbcfg) {
1550 +               printk(KERN_ERR "Null argument in configuration. \n");
1551 +               return -EINVAL;
1552 +       }
1553 +
1554 +       if (!aewbstat.initialized) {
1555 +               DPRINTK_ISPH3A("Setting callback for H3A\n");
1556 +               ret = isp_set_callback(CBK_H3A_AWB_DONE, isph3a_aewb_isr,
1557 +                                      (void *)NULL, (void *)NULL);
1558 +               if (ret) {
1559 +                       printk(KERN_ERR "No callback for H3A\n");
1560 +                       return ret;
1561 +               }
1562 +       }
1563 +
1564 +       ret = isph3a_aewb_set_params(aewbcfg);
1565 +       if (ret) {
1566 +               printk(KERN_ERR "Invalid parameters! \n");
1567 +               return ret;
1568 +       }
1569 +
1570 +       win_count = aewbcfg->ver_win_count * aewbcfg->hor_win_count;
1571 +       win_count += aewbcfg->hor_win_count;
1572 +       ret = win_count / 8;
1573 +       win_count += win_count % 8 ? 1 : 0;
1574 +       win_count += ret;
1575 +
1576 +       aewbstat.win_count = win_count;
1577 +       aewbstat.curr_cfg_buf_size = win_count * AEWB_PACKET_SIZE;
1578 +
1579 +       if (aewbstat.stats_buf_size
1580 +           && win_count * AEWB_PACKET_SIZE > aewbstat.stats_buf_size) {
1581 +               DPRINTK_ISPH3A("There was a previous buffer... "
1582 +                              "Freeing/unmapping current stat busffs\n");
1583 +               isph3a_aewb_enable(0);
1584 +               for (i = 0; i < H3A_MAX_BUFF; i++) {
1585 +                       ispmmu_kunmap(aewbstat.h3a_buff[i].ispmmu_addr);
1586 +                       dma_free_coherent(
1587 +                               NULL,
1588 +                               aewbstat.min_buf_size,
1589 +                               (void *)aewbstat.h3a_buff[i].virt_addr,
1590 +                               (dma_addr_t)aewbstat.h3a_buff[i].phy_addr);
1591 +                       aewbstat.h3a_buff[i].virt_addr = 0;
1592 +               }
1593 +               aewbstat.stats_buf_size = 0;
1594 +       }
1595 +
1596 +       if (!aewbstat.h3a_buff[0].virt_addr) {
1597 +               aewbstat.stats_buf_size = win_count * AEWB_PACKET_SIZE;
1598 +               aewbstat.min_buf_size = PAGE_ALIGN(aewbstat.stats_buf_size);
1599 +
1600 +               DPRINTK_ISPH3A("Allocating/mapping new stat buffs\n");
1601 +               for (i = 0; i < H3A_MAX_BUFF; i++) {
1602 +                       aewbstat.h3a_buff[i].virt_addr =
1603 +                               (unsigned long)dma_alloc_coherent(
1604 +                                       NULL,
1605 +                                       aewbstat.min_buf_size,
1606 +                                       (dma_addr_t *)
1607 +                                       &aewbstat.h3a_buff[i].phy_addr,
1608 +                                       GFP_KERNEL | GFP_DMA);
1609 +                       if (aewbstat.h3a_buff[i].virt_addr == 0) {
1610 +                               printk(KERN_ERR "Can't acquire memory for "
1611 +                                      "buffer[%d]\n", i);
1612 +                               return -ENOMEM;
1613 +                       }
1614 +                       aewbstat.h3a_buff[i].addr_align =
1615 +                               aewbstat.h3a_buff[i].virt_addr;
1616 +                       while ((aewbstat.h3a_buff[i].addr_align & 0xFFFFFFC0) !=
1617 +                              aewbstat.h3a_buff[i].addr_align)
1618 +                               aewbstat.h3a_buff[i].addr_align++;
1619 +                       aewbstat.h3a_buff[i].ispmmu_addr =
1620 +                               ispmmu_kmap(aewbstat.h3a_buff[i].phy_addr,
1621 +                                           aewbstat.min_buf_size);
1622 +               }
1623 +               isph3a_aewb_unlock_buffers();
1624 +               isph3a_aewb_link_buffers();
1625 +
1626 +               if (active_buff == NULL)
1627 +                       active_buff = &aewbstat.h3a_buff[0];
1628 +
1629 +               isp_reg_writel(active_buff->ispmmu_addr, OMAP3_ISP_IOMEM_H3A,
1630 +                              ISPH3A_AEWBUFST);
1631 +       }
1632 +       for (i = 0; i < H3A_MAX_BUFF; i++) {
1633 +               DPRINTK_ISPH3A("buff[%d] addr is:\n    virt    0x%lX\n"
1634 +                              "    aligned 0x%lX\n"
1635 +                              "    phys    0x%lX\n"
1636 +                              "    ispmmu  0x%08lX\n"
1637 +                              "    mmapped 0x%lX\n"
1638 +                              "    frame_num %d\n", i,
1639 +                              aewbstat.h3a_buff[i].virt_addr,
1640 +                              aewbstat.h3a_buff[i].addr_align,
1641 +                              aewbstat.h3a_buff[i].phy_addr,
1642 +                              aewbstat.h3a_buff[i].ispmmu_addr,
1643 +                              aewbstat.h3a_buff[i].mmap_addr,
1644 +                              aewbstat.h3a_buff[i].frame_num);
1645 +       }
1646 +
1647 +       active_buff->frame_num = 1;
1648 +
1649 +       atomic_inc(&aewbstat.config_counter);
1650 +       isph3a_aewb_enable(aewbcfg->aewb_enable);
1651 +       isph3a_print_status();
1652 +
1653 +       return 0;
1654 +}
1655 +EXPORT_SYMBOL(isph3a_aewb_configure);
1656 +
1657 +/**
1658 + * isph3a_aewb_request_statistics - REquest statistics and update gains in AEWB
1659 + * @aewbdata: Pointer to return AE AWB statistics data.
1660 + *
1661 + * This API allows the user to update White Balance gains, as well as
1662 + * exposure time and analog gain. It is also used to request frame
1663 + * statistics.
1664 + *
1665 + * Returns 0 if successful, -EINVAL when H3A engine is not enabled, or other
1666 + * errors when setting gains.
1667 + **/
1668 +int isph3a_aewb_request_statistics(struct isph3a_aewb_data *aewbdata)
1669 +{
1670 +       int ret = 0;
1671 +       u16 frame_diff = 0;
1672 +       u16 frame_cnt = aewbstat.frame_count;
1673 +       wait_queue_t wqt;
1674 +
1675 +       if (!aewb_config_local.aewb_enable) {
1676 +               printk(KERN_ERR "H3A engine not enabled\n");
1677 +               return -EINVAL;
1678 +       }
1679 +
1680 +       DPRINTK_ISPH3A("isph3a_aewb_request_statistics: Enter "
1681 +                      "(frame req. => %d, current frame => %d,"
1682 +                      "update => %d)\n",
1683 +                      aewbdata->frame_number, frame_cnt, aewbdata->update);
1684 +       DPRINTK_ISPH3A("User data received: \n");
1685 +       DPRINTK_ISPH3A("Digital gain = 0x%04x\n", aewbdata->dgain);
1686 +       DPRINTK_ISPH3A("WB gain b *=   0x%04x\n", aewbdata->wb_gain_b);
1687 +       DPRINTK_ISPH3A("WB gain r *=   0x%04x\n", aewbdata->wb_gain_r);
1688 +       DPRINTK_ISPH3A("WB gain gb =   0x%04x\n", aewbdata->wb_gain_gb);
1689 +       DPRINTK_ISPH3A("WB gain gr =   0x%04x\n", aewbdata->wb_gain_gr);
1690 +
1691 +       if (!aewbdata->update) {
1692 +               aewbdata->h3a_aewb_statistics_buf = NULL;
1693 +               goto out;
1694 +       }
1695 +       if (aewbdata->update & SET_DIGITAL_GAIN)
1696 +               h3awb_update.dgain = (u16)aewbdata->dgain;
1697 +       if (aewbdata->update & SET_COLOR_GAINS) {
1698 +               h3awb_update.coef0 = (u8)aewbdata->wb_gain_gr;
1699 +               h3awb_update.coef1 = (u8)aewbdata->wb_gain_r;
1700 +               h3awb_update.coef2 = (u8)aewbdata->wb_gain_b;
1701 +               h3awb_update.coef3 = (u8)aewbdata->wb_gain_gb;
1702 +       }
1703 +       if (aewbdata->update & (SET_COLOR_GAINS | SET_DIGITAL_GAIN))
1704 +               wb_update = 1;
1705 +
1706 +       if (!(aewbdata->update & REQUEST_STATISTICS)) {
1707 +               aewbdata->h3a_aewb_statistics_buf = NULL;
1708 +               goto out;
1709 +       }
1710 +
1711 +       if (aewbdata->frame_number < 1) {
1712 +               printk(KERN_ERR "Illeagal frame number "
1713 +                      "requested (%d)\n",
1714 +                      aewbdata->frame_number);
1715 +               return -EINVAL;
1716 +       }
1717 +
1718 +       isph3a_aewb_unlock_buffers();
1719 +
1720 +       DPRINTK_ISPH3A("Stats available?\n");
1721 +       ret = isph3a_aewb_stats_available(aewbdata);
1722 +       if (!ret)
1723 +               goto out;
1724 +
1725 +       DPRINTK_ISPH3A("Stats in near future?\n");
1726 +       if (aewbdata->frame_number > frame_cnt)
1727 +               frame_diff = aewbdata->frame_number - frame_cnt;
1728 +       else if (aewbdata->frame_number < frame_cnt) {
1729 +               if ((frame_cnt > (MAX_FRAME_COUNT - MAX_FUTURE_FRAMES)) &&
1730 +                   (aewbdata->frame_number < MAX_FRAME_COUNT)) {
1731 +                       frame_diff = aewbdata->frame_number + MAX_FRAME_COUNT -
1732 +                               frame_cnt;
1733 +               } else
1734 +                       frame_diff = MAX_FUTURE_FRAMES + 1;
1735 +       }
1736 +
1737 +       if (frame_diff > MAX_FUTURE_FRAMES) {
1738 +               printk(KERN_ERR "Invalid frame requested, returning current"
1739 +                      " frame stats\n");
1740 +               aewbdata->frame_number = frame_cnt;
1741 +       }
1742 +       if (camnotify) {
1743 +               DPRINTK_ISPH3A("NOT Waiting on stats IRQ for frame %d "
1744 +                              "because camnotify set\n",
1745 +                              aewbdata->frame_number);
1746 +               aewbdata->h3a_aewb_statistics_buf = NULL;
1747 +               goto out;
1748 +       }
1749 +       DPRINTK_ISPH3A("Waiting on stats IRQ for frame %d\n",
1750 +                      aewbdata->frame_number);
1751 +       aewbstat.frame_req = aewbdata->frame_number;
1752 +       aewbstat.stats_req = 1;
1753 +       aewbstat.stats_done = 0;
1754 +       init_waitqueue_entry(&wqt, current);
1755 +       ret = wait_event_interruptible(aewbstat.stats_wait,
1756 +                                      aewbstat.stats_done == 1);
1757 +       if (ret < 0) {
1758 +               printk(KERN_ERR "isph3a_aewb_request_statistics"
1759 +                      " Error on wait event %d\n", ret);
1760 +               aewbdata->h3a_aewb_statistics_buf = NULL;
1761 +               return ret;
1762 +       }
1763 +
1764 +       DPRINTK_ISPH3A("ISP AEWB request status interrupt raised\n");
1765 +       ret = isph3a_aewb_stats_available(aewbdata);
1766 +       if (ret) {
1767 +               DPRINTK_ISPH3A("After waiting for stats,"
1768 +                              " stats not available!!\n");
1769 +               aewbdata->h3a_aewb_statistics_buf = NULL;
1770 +       }
1771 +out:
1772 +       DPRINTK_ISPH3A("isph3a_aewb_request_statistics: "
1773 +                      "aewbdata->h3a_aewb_statistics_buf => %p\n",
1774 +                      aewbdata->h3a_aewb_statistics_buf);
1775 +       aewbdata->curr_frame = aewbstat.frame_count;
1776 +
1777 +       return 0;
1778 +}
1779 +EXPORT_SYMBOL(isph3a_aewb_request_statistics);
1780 +
1781 +/**
1782 + * isph3a_aewb_init - Module Initialisation.
1783 + *
1784 + * Always returns 0.
1785 + **/
1786 +int __init isph3a_aewb_init(void)
1787 +{
1788 +       memset(&aewbstat, 0, sizeof(aewbstat));
1789 +       memset(&aewb_regs, 0, sizeof(aewb_regs));
1790 +
1791 +       init_waitqueue_head(&aewbstat.stats_wait);
1792 +       spin_lock_init(&aewbstat.buffer_lock);
1793 +       return 0;
1794 +}
1795 +
1796 +/**
1797 + * isph3a_aewb_cleanup - Module exit.
1798 + **/
1799 +void isph3a_aewb_cleanup(void)
1800 +{
1801 +       int i;
1802 +
1803 +       for (i = 0; i < H3A_MAX_BUFF; i++) {
1804 +               if (!aewbstat.h3a_buff[i].phy_addr)
1805 +                       continue;
1806 +
1807 +               ispmmu_kunmap(aewbstat.h3a_buff[i].ispmmu_addr);
1808 +               dma_free_coherent(NULL,
1809 +                                 aewbstat.min_buf_size,
1810 +                                 (void *)aewbstat.h3a_buff[i].virt_addr,
1811 +                                 (dma_addr_t)aewbstat.h3a_buff[i].phy_addr);
1812 +       }
1813 +       memset(&aewbstat, 0, sizeof(aewbstat));
1814 +       memset(&aewb_regs, 0, sizeof(aewb_regs));
1815 +}
1816 +
1817 +/**
1818 + * isph3a_print_status - Debug print. Values of H3A related registers.
1819 + **/
1820 +static void isph3a_print_status(void)
1821 +{
1822 +       DPRINTK_ISPH3A("ISPH3A_PCR = 0x%08x\n",
1823 +                      isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR));
1824 +       DPRINTK_ISPH3A("ISPH3A_AEWWIN1 = 0x%08x\n",
1825 +                      isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1));
1826 +       DPRINTK_ISPH3A("ISPH3A_AEWINSTART = 0x%08x\n",
1827 +                      isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINSTART));
1828 +       DPRINTK_ISPH3A("ISPH3A_AEWINBLK = 0x%08x\n",
1829 +                      isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK));
1830 +       DPRINTK_ISPH3A("ISPH3A_AEWSUBWIN = 0x%08x\n",
1831 +                      isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWSUBWIN));
1832 +       DPRINTK_ISPH3A("ISPH3A_AEWBUFST = 0x%08x\n",
1833 +                      isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST));
1834 +       DPRINTK_ISPH3A("stats windows = %d\n", aewbstat.win_count);
1835 +       DPRINTK_ISPH3A("stats buff size = %d\n", aewbstat.stats_buf_size);
1836 +       DPRINTK_ISPH3A("currently configured stats buff size = %d\n",
1837 +                      aewbstat.curr_cfg_buf_size);
1838 +}
1839 +
1840 +/**
1841 + * isph3a_notify - Unblocks user request for statistics when camera is off
1842 + * @notify: 1 - Camera is turned off
1843 + *
1844 + * Used when the user has requested statistics about a future frame, but the
1845 + * camera is turned off before it happens, and this function unblocks the
1846 + * request so the user can continue in its program.
1847 + **/
1848 +void isph3a_notify(int notify)
1849 +{
1850 +       camnotify = notify;
1851 +       if (camnotify && aewbstat.initialized) {
1852 +               printk(KERN_DEBUG "Warning Camera Off \n");
1853 +               aewbstat.stats_req = 0;
1854 +               aewbstat.stats_done = 1;
1855 +               wake_up_interruptible(&aewbstat.stats_wait);
1856 +       }
1857 +}
1858 +EXPORT_SYMBOL(isph3a_notify);
1859 +
1860 +/**
1861 + * isph3a_save_context - Saves the values of the h3a module registers.
1862 + **/
1863 +void isph3a_save_context(void)
1864 +{
1865 +       DPRINTK_ISPH3A(" Saving context\n");
1866 +       isp_save_context(isph3a_reg_list);
1867 +       /* Avoid enable during restore ctx */
1868 +       isph3a_reg_list[0].val &= ~ISPH3A_PCR_AEW_EN;
1869 +}
1870 +EXPORT_SYMBOL(isph3a_save_context);
1871 +
1872 +/**
1873 + * isph3a_restore_context - Restores the values of the h3a module registers.
1874 + **/
1875 +void isph3a_restore_context(void)
1876 +{
1877 +       DPRINTK_ISPH3A(" Restoring context\n");
1878 +       isp_restore_context(isph3a_reg_list);
1879 +}
1880 +EXPORT_SYMBOL(isph3a_restore_context);
1881 diff --git a/drivers/media/video/isp/isph3a.h b/drivers/media/video/isp/isph3a.h
1882 new file mode 100644
1883 index 0000000..7d4c765
1884 --- /dev/null
1885 +++ b/drivers/media/video/isp/isph3a.h
1886 @@ -0,0 +1,127 @@
1887 +/*
1888 + * isph3a.h
1889 + *
1890 + * Include file for H3A module in TI's OMAP3 Camera ISP
1891 + *
1892 + * Copyright (C) 2009 Texas Instruments, Inc.
1893 + *
1894 + * Contributors:
1895 + *     Sergio Aguirre <saaguirre@ti.com>
1896 + *     Troy Laramy
1897 + *
1898 + * This package is free software; you can redistribute it and/or modify
1899 + * it under the terms of the GNU General Public License version 2 as
1900 + * published by the Free Software Foundation.
1901 + *
1902 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1903 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1904 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1905 + */
1906 +
1907 +#ifndef OMAP_ISP_H3A_H
1908 +#define OMAP_ISP_H3A_H
1909 +
1910 +#include <mach/isp_user.h>
1911 +
1912 +#define AEWB_PACKET_SIZE       16
1913 +#define H3A_MAX_BUFF           5
1914 +
1915 +/* Flags for changed registers */
1916 +#define PCR_CHNG               (1 << 0)
1917 +#define AEWWIN1_CHNG           (1 << 1)
1918 +#define AEWINSTART_CHNG                (1 << 2)
1919 +#define AEWINBLK_CHNG          (1 << 3)
1920 +#define AEWSUBWIN_CHNG         (1 << 4)
1921 +#define PRV_WBDGAIN_CHNG       (1 << 5)
1922 +#define PRV_WBGAIN_CHNG                (1 << 6)
1923 +
1924 +/* ISPH3A REGISTERS bits */
1925 +#define ISPH3A_PCR_AF_EN       (1 << 0)
1926 +#define ISPH3A_PCR_AF_ALAW_EN  (1 << 1)
1927 +#define ISPH3A_PCR_AF_MED_EN   (1 << 2)
1928 +#define ISPH3A_PCR_AF_BUSY     (1 << 15)
1929 +#define ISPH3A_PCR_AEW_EN      (1 << 16)
1930 +#define ISPH3A_PCR_AEW_ALAW_EN (1 << 17)
1931 +#define ISPH3A_PCR_AEW_BUSY    (1 << 18)
1932 +
1933 +#define WRITE_SAT_LIM(reg, sat_limit)                  \
1934 +       (reg = (reg & (~(ISPH3A_PCR_AEW_AVE2LMT_MASK))) \
1935 +        | (sat_limit << ISPH3A_PCR_AEW_AVE2LMT_SHIFT))
1936 +
1937 +#define WRITE_ALAW(reg, alaw_en)                       \
1938 +       (reg = (reg & (~(ISPH3A_PCR_AEW_ALAW_EN)))      \
1939 +        | ((alaw_en & ISPH3A_PCR_AF_ALAW_EN)           \
1940 +           << ISPH3A_PCR_AEW_ALAW_EN_SHIFT))
1941 +
1942 +#define WRITE_WIN_H(reg, height)                               \
1943 +       (reg = (reg & (~(ISPH3A_AEWWIN1_WINH_MASK)))            \
1944 +        | (((height >> 1) - 1) << ISPH3A_AEWWIN1_WINH_SHIFT))
1945 +
1946 +#define WRITE_WIN_W(reg, width)                                        \
1947 +       (reg = (reg & (~(ISPH3A_AEWWIN1_WINW_MASK)))            \
1948 +        | (((width >> 1) - 1) << ISPH3A_AEWWIN1_WINW_SHIFT))
1949 +
1950 +#define WRITE_VER_C(reg, ver_count)                            \
1951 +       (reg = (reg & ~(ISPH3A_AEWWIN1_WINVC_MASK))             \
1952 +        | ((ver_count - 1) << ISPH3A_AEWWIN1_WINVC_SHIFT))
1953 +
1954 +#define WRITE_HOR_C(reg, hor_count)                            \
1955 +       (reg = (reg & ~(ISPH3A_AEWWIN1_WINHC_MASK))             \
1956 +        | ((hor_count - 1) << ISPH3A_AEWWIN1_WINHC_SHIFT))
1957 +
1958 +#define WRITE_VER_WIN_ST(reg, ver_win_st)                      \
1959 +       (reg = (reg & ~(ISPH3A_AEWINSTART_WINSV_MASK))          \
1960 +        | (ver_win_st << ISPH3A_AEWINSTART_WINSV_SHIFT))
1961 +
1962 +#define WRITE_HOR_WIN_ST(reg, hor_win_st)                      \
1963 +       (reg = (reg & ~(ISPH3A_AEWINSTART_WINSH_MASK))          \
1964 +        | (hor_win_st << ISPH3A_AEWINSTART_WINSH_SHIFT))
1965 +
1966 +#define WRITE_BLK_VER_WIN_ST(reg, blk_win_st)          \
1967 +       (reg = (reg & ~(ISPH3A_AEWINBLK_WINSV_MASK))    \
1968 +        | (blk_win_st << ISPH3A_AEWINBLK_WINSV_SHIFT))
1969 +
1970 +#define WRITE_BLK_WIN_H(reg, height)                           \
1971 +       (reg = (reg & ~(ISPH3A_AEWINBLK_WINH_MASK))             \
1972 +        | (((height >> 1) - 1) << ISPH3A_AEWINBLK_WINH_SHIFT))
1973 +
1974 +#define WRITE_SUB_VER_INC(reg, sub_ver_inc)                            \
1975 +       (reg = (reg & ~(ISPH3A_AEWSUBWIN_AEWINCV_MASK))                 \
1976 +        | (((sub_ver_inc >> 1) - 1) << ISPH3A_AEWSUBWIN_AEWINCV_SHIFT))
1977 +
1978 +#define WRITE_SUB_HOR_INC(reg, sub_hor_inc)                            \
1979 +       (reg = (reg & ~(ISPH3A_AEWSUBWIN_AEWINCH_MASK))                 \
1980 +        | (((sub_hor_inc >> 1) - 1) << ISPH3A_AEWSUBWIN_AEWINCH_SHIFT))
1981 +
1982 +/**
1983 + * struct isph3a_aewb_xtrastats - Structure with extra statistics sent by cam.
1984 + * @field_count: Sequence number of returned framestats.
1985 + * @isph3a_aewb_xtrastats: Pointer to next buffer with extra stats.
1986 + */
1987 +struct isph3a_aewb_xtrastats {
1988 +       unsigned long field_count;
1989 +       struct isph3a_aewb_xtrastats *next;
1990 +};
1991 +
1992 +void isph3a_aewb_setxtrastats(struct isph3a_aewb_xtrastats *xtrastats);
1993 +
1994 +int isph3a_aewb_configure(struct isph3a_aewb_config *aewbcfg);
1995 +
1996 +int isph3a_aewb_request_statistics(struct isph3a_aewb_data *aewbdata);
1997 +
1998 +void isph3a_save_context(void);
1999 +
2000 +void isph3a_restore_context(void);
2001 +
2002 +void isph3a_aewb_enable(u8 enable);
2003 +
2004 +int isph3a_aewb_busy(void);
2005 +
2006 +void isph3a_aewb_suspend(void);
2007 +
2008 +void isph3a_aewb_resume(void);
2009 +
2010 +void isph3a_update_wb(void);
2011 +
2012 +void isph3a_notify(int notify);
2013 +#endif         /* OMAP_ISP_H3A_H */
2014 diff --git a/drivers/media/video/isp/isphist.c b/drivers/media/video/isp/isphist.c
2015 new file mode 100644
2016 index 0000000..c6f6a77
2017 --- /dev/null
2018 +++ b/drivers/media/video/isp/isphist.c
2019 @@ -0,0 +1,608 @@
2020 +/*
2021 + * isphist.c
2022 + *
2023 + * HISTOGRAM module for TI's OMAP3 Camera ISP
2024 + *
2025 + * Copyright (C) 2009 Texas Instruments, Inc.
2026 + *
2027 + * Contributors:
2028 + *     Sergio Aguirre <saaguirre@ti.com>
2029 + *     Troy Laramy
2030 + *
2031 + * This package is free software; you can redistribute it and/or modify
2032 + * it under the terms of the GNU General Public License version 2 as
2033 + * published by the Free Software Foundation.
2034 + *
2035 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2036 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2037 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2038 + */
2039 +
2040 +#include <asm/cacheflush.h>
2041 +
2042 +#include <linux/delay.h>
2043 +#include <linux/dma-mapping.h>
2044 +#include <linux/uaccess.h>
2045 +
2046 +#include "isp.h"
2047 +#include "ispreg.h"
2048 +#include "isphist.h"
2049 +#include "ispmmu.h"
2050 +
2051 +/**
2052 + * struct isp_hist_status - Histogram status.
2053 + * @hist_enable: Enables the histogram module.
2054 + * @initialized: Flag to indicate that the module is correctly initializated.
2055 + * @frame_cnt: Actual frame count.
2056 + * @frame_req: Frame requested by user.
2057 + * @completed: Flag to indicate if a frame request is completed.
2058 + */
2059 +struct isp_hist_status {
2060 +       u8 hist_enable;
2061 +       u8 pm_state;
2062 +       u8 initialized;
2063 +       u8 frame_cnt;
2064 +       u8 frame_req;
2065 +       u8 completed;
2066 +} histstat;
2067 +
2068 +/**
2069 + * struct isp_hist_buffer - Frame histogram buffer.
2070 + * @virt_addr: Virtual address to mmap the buffer.
2071 + * @phy_addr: Physical address of the buffer.
2072 + * @addr_align: Virtual Address 32 bytes aligned.
2073 + * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
2074 + * @mmap_addr: Mapped memory area of buffer. For userspace access.
2075 + */
2076 +struct isp_hist_buffer {
2077 +       unsigned long virt_addr;
2078 +       unsigned long phy_addr;
2079 +       unsigned long addr_align;
2080 +       unsigned long ispmmu_addr;
2081 +       unsigned long mmap_addr;
2082 +} hist_buff;
2083 +
2084 +/**
2085 + * struct isp_hist_regs - Current value of Histogram configuration registers.
2086 + * @reg_pcr: Peripheral control register.
2087 + * @reg_cnt: Histogram control register.
2088 + * @reg_wb_gain: Histogram white balance gain register.
2089 + * @reg_r0_h: Region 0 horizontal register.
2090 + * @reg_r0_v: Region 0 vertical register.
2091 + * @reg_r1_h: Region 1 horizontal register.
2092 + * @reg_r1_v: Region 1 vertical register.
2093 + * @reg_r2_h: Region 2 horizontal register.
2094 + * @reg_r2_v: Region 2 vertical register.
2095 + * @reg_r3_h: Region 3 horizontal register.
2096 + * @reg_r3_v: Region 3 vertical register.
2097 + * @reg_hist_addr: Histogram address register.
2098 + * @reg_hist_data: Histogram data.
2099 + * @reg_hist_radd: Address register. When input data comes from mem.
2100 + * @reg_hist_radd_off: Address offset register. When input data comes from mem.
2101 + * @reg_h_v_info: Image size register. When input data comes from mem.
2102 + */
2103 +static struct isp_hist_regs {
2104 +       u32 reg_pcr;
2105 +       u32 reg_cnt;
2106 +       u32 reg_wb_gain;
2107 +       u32 reg_r0_h;
2108 +       u32 reg_r0_v;
2109 +       u32 reg_r1_h;
2110 +       u32 reg_r1_v;
2111 +       u32 reg_r2_h;
2112 +       u32 reg_r2_v;
2113 +       u32 reg_r3_h;
2114 +       u32 reg_r3_v;
2115 +       u32 reg_hist_addr;
2116 +       u32 reg_hist_data;
2117 +       u32 reg_hist_radd;
2118 +       u32 reg_hist_radd_off;
2119 +       u32 reg_h_v_info;
2120 +} hist_regs;
2121 +
2122 +/* Structure for saving/restoring histogram module registers */
2123 +struct isp_reg isphist_reg_list[] = {
2124 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, 0},
2125 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN, 0},
2126 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ, 0},
2127 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT, 0},
2128 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ, 0},
2129 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT, 0},
2130 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ, 0},
2131 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT, 0},
2132 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ, 0},
2133 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT, 0},
2134 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR, 0},
2135 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD, 0},
2136 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD_OFF, 0},
2137 +       {OMAP3_ISP_IOMEM_HIST, ISPHIST_H_V_INFO, 0},
2138 +       {0, ISP_TOK_TERM, 0}
2139 +};
2140 +
2141 +static void isp_hist_print_status(void);
2142 +
2143 +void __isp_hist_enable(u8 enable)
2144 +{
2145 +       if (enable)
2146 +               DPRINTK_ISPHIST("   histogram enabled \n");
2147 +       else
2148 +               DPRINTK_ISPHIST("   histogram disabled \n");
2149 +
2150 +       isp_reg_and_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ~ISPHIST_PCR_EN,
2151 +                                               (enable ? ISPHIST_PCR_EN : 0));
2152 +       histstat.hist_enable = enable;
2153 +}
2154 +
2155 +/**
2156 + * isp_hist_enable - Enables ISP Histogram submodule operation.
2157 + * @enable: 1 - Enables the histogram submodule.
2158 + *
2159 + * Client should configure all the Histogram registers before calling this
2160 + * function.
2161 + **/
2162 +void isp_hist_enable(u8 enable)
2163 +{
2164 +       __isp_hist_enable(enable);
2165 +       histstat.pm_state = enable;
2166 +}
2167 +
2168 +/**
2169 + * isp_hist_suspend - Suspend ISP Histogram submodule.
2170 + **/
2171 +void isp_hist_suspend(void)
2172 +{
2173 +       if (histstat.pm_state)
2174 +               __isp_hist_enable(0);
2175 +}
2176 +
2177 +/**
2178 + * isp_hist_resume - Resume ISP Histogram submodule.
2179 + **/
2180 +void isp_hist_resume(void)
2181 +{
2182 +       if (histstat.pm_state)
2183 +               __isp_hist_enable(1);
2184 +}
2185 +
2186 +int isp_hist_busy(void)
2187 +{
2188 +       return isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR) &
2189 +               ISPHIST_PCR_BUSY;
2190 +}
2191 +
2192 +
2193 +/**
2194 + * isp_hist_update_regs - Helper function to update Histogram registers.
2195 + **/
2196 +static void isp_hist_update_regs(void)
2197 +{
2198 +       isp_reg_writel(hist_regs.reg_pcr, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR);
2199 +       isp_reg_writel(hist_regs.reg_cnt, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT);
2200 +       isp_reg_writel(hist_regs.reg_wb_gain, OMAP3_ISP_IOMEM_HIST,
2201 +                      ISPHIST_WB_GAIN);
2202 +       isp_reg_writel(hist_regs.reg_r0_h, OMAP3_ISP_IOMEM_HIST,
2203 +                      ISPHIST_R0_HORZ);
2204 +       isp_reg_writel(hist_regs.reg_r0_v, OMAP3_ISP_IOMEM_HIST,
2205 +                      ISPHIST_R0_VERT);
2206 +       isp_reg_writel(hist_regs.reg_r1_h, OMAP3_ISP_IOMEM_HIST,
2207 +                      ISPHIST_R1_HORZ);
2208 +       isp_reg_writel(hist_regs.reg_r1_v, OMAP3_ISP_IOMEM_HIST,
2209 +                      ISPHIST_R1_VERT);
2210 +       isp_reg_writel(hist_regs.reg_r2_h, OMAP3_ISP_IOMEM_HIST,
2211 +                      ISPHIST_R2_HORZ);
2212 +       isp_reg_writel(hist_regs.reg_r2_v, OMAP3_ISP_IOMEM_HIST,
2213 +                      ISPHIST_R2_VERT);
2214 +       isp_reg_writel(hist_regs.reg_r3_h, OMAP3_ISP_IOMEM_HIST,
2215 +                      ISPHIST_R3_HORZ);
2216 +       isp_reg_writel(hist_regs.reg_r3_v, OMAP3_ISP_IOMEM_HIST,
2217 +                      ISPHIST_R3_VERT);
2218 +       isp_reg_writel(hist_regs.reg_hist_addr, OMAP3_ISP_IOMEM_HIST,
2219 +                      ISPHIST_ADDR);
2220 +       isp_reg_writel(hist_regs.reg_hist_data, OMAP3_ISP_IOMEM_HIST,
2221 +                      ISPHIST_DATA);
2222 +       isp_reg_writel(hist_regs.reg_hist_radd, OMAP3_ISP_IOMEM_HIST,
2223 +                      ISPHIST_RADD);
2224 +       isp_reg_writel(hist_regs.reg_hist_radd_off, OMAP3_ISP_IOMEM_HIST,
2225 +                      ISPHIST_RADD_OFF);
2226 +       isp_reg_writel(hist_regs.reg_h_v_info, OMAP3_ISP_IOMEM_HIST,
2227 +                      ISPHIST_H_V_INFO);
2228 +}
2229 +
2230 +/**
2231 + * isp_hist_isr - Callback from ISP driver for HIST interrupt.
2232 + * @status: IRQ0STATUS in case of MMU error, 0 for hist interrupt.
2233 + *          arg1 and arg2 Not used as of now.
2234 + **/
2235 +static void isp_hist_isr(unsigned long status, isp_vbq_callback_ptr arg1,
2236 +                        void *arg2)
2237 +{
2238 +       isp_hist_enable(0);
2239 +
2240 +       if (!(status & HIST_DONE))
2241 +               return;
2242 +
2243 +       if (!histstat.completed) {
2244 +               if (histstat.frame_req == histstat.frame_cnt) {
2245 +                       histstat.frame_cnt = 0;
2246 +                       histstat.frame_req = 0;
2247 +                       histstat.completed = 1;
2248 +               } else {
2249 +                       isp_hist_enable(1);
2250 +                       histstat.frame_cnt++;
2251 +               }
2252 +       }
2253 +}
2254 +
2255 +/**
2256 + * isp_hist_reset_mem - clear Histogram memory before start stats engine.
2257 + *
2258 + * Returns 0 after histogram memory was cleared.
2259 + **/
2260 +static int isp_hist_reset_mem(void)
2261 +{
2262 +       int i;
2263 +
2264 +       isp_reg_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLR_EN);
2265 +
2266 +       for (i = 0; i < HIST_MEM_SIZE; i++)
2267 +               isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
2268 +
2269 +       isp_reg_and(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ~ISPHIST_CNT_CLR_EN);
2270 +
2271 +       return 0;
2272 +}
2273 +
2274 +/**
2275 + * isp_hist_set_params - Helper function to check and store user given params.
2276 + * @user_cfg: Pointer to user configuration structure.
2277 + *
2278 + * Returns 0 on success configuration.
2279 + **/
2280 +static int isp_hist_set_params(struct isp_hist_config *user_cfg)
2281 +{
2282 +
2283 +       int reg_num = 0;
2284 +       int bit_shift = 0;
2285 +
2286 +
2287 +       if (isp_hist_busy())
2288 +               return -EINVAL;
2289 +
2290 +       if (user_cfg->input_bit_width > MIN_BIT_WIDTH)
2291 +               WRITE_DATA_SIZE(hist_regs.reg_cnt, 0);
2292 +       else
2293 +               WRITE_DATA_SIZE(hist_regs.reg_cnt, 1);
2294 +
2295 +       WRITE_SOURCE(hist_regs.reg_cnt, user_cfg->hist_source);
2296 +
2297 +       if (user_cfg->hist_source) {
2298 +               WRITE_HV_INFO(hist_regs.reg_h_v_info, user_cfg->hist_h_v_info);
2299 +
2300 +               if ((user_cfg->hist_radd & ISP_32B_BOUNDARY_BUF) ==
2301 +                   user_cfg->hist_radd) {
2302 +                       WRITE_RADD(hist_regs.reg_hist_radd,
2303 +                                  user_cfg->hist_radd);
2304 +               } else {
2305 +                       printk(KERN_ERR "Address should be in 32 byte boundary"
2306 +                              "\n");
2307 +                       return -EINVAL;
2308 +               }
2309 +
2310 +               if ((user_cfg->hist_radd_off & ISP_32B_BOUNDARY_OFFSET) ==
2311 +                   user_cfg->hist_radd_off) {
2312 +                       WRITE_RADD_OFF(hist_regs.reg_hist_radd_off,
2313 +                                      user_cfg->hist_radd_off);
2314 +               } else {
2315 +                       printk(KERN_ERR "Offset should be in 32 byte boundary"
2316 +                              "\n");
2317 +                       return -EINVAL;
2318 +               }
2319 +
2320 +       }
2321 +
2322 +       isp_hist_reset_mem();
2323 +       DPRINTK_ISPHIST("ISPHIST: Memory Cleared\n");
2324 +       histstat.frame_req = user_cfg->hist_frames;
2325 +
2326 +       if (unlikely(user_cfg->wb_gain_R > MAX_WB_GAIN ||
2327 +                    user_cfg->wb_gain_RG > MAX_WB_GAIN ||
2328 +                    user_cfg->wb_gain_B > MAX_WB_GAIN ||
2329 +                    user_cfg->wb_gain_BG > MAX_WB_GAIN)) {
2330 +               printk(KERN_ERR "Invalid WB gain\n");
2331 +               return -EINVAL;
2332 +       } else {
2333 +               WRITE_WB_R(hist_regs.reg_wb_gain, user_cfg->wb_gain_R);
2334 +               WRITE_WB_RG(hist_regs.reg_wb_gain, user_cfg->wb_gain_RG);
2335 +               WRITE_WB_B(hist_regs.reg_wb_gain, user_cfg->wb_gain_B);
2336 +               WRITE_WB_BG(hist_regs.reg_wb_gain, user_cfg->wb_gain_BG);
2337 +       }
2338 +
2339 +       /* Regions size and position */
2340 +
2341 +       if (user_cfg->num_regions > MAX_REGIONS)
2342 +               return -EINVAL;
2343 +
2344 +       if (likely((user_cfg->reg0_hor & ISPHIST_REGHORIZ_HEND_MASK) -
2345 +                  ((user_cfg->reg0_hor & ISPHIST_REGHORIZ_HSTART_MASK) >>
2346 +                   ISPHIST_REGHORIZ_HSTART_SHIFT))) {
2347 +               WRITE_REG_HORIZ(hist_regs.reg_r0_h, user_cfg->reg0_hor);
2348 +               reg_num++;
2349 +       } else {
2350 +               printk(KERN_ERR "Invalid Region parameters\n");
2351 +               return -EINVAL;
2352 +       }
2353 +
2354 +       if (likely((user_cfg->reg0_ver & ISPHIST_REGVERT_VEND_MASK) -
2355 +                  ((user_cfg->reg0_ver & ISPHIST_REGVERT_VSTART_MASK) >>
2356 +                   ISPHIST_REGVERT_VSTART_SHIFT))) {
2357 +               WRITE_REG_VERT(hist_regs.reg_r0_v, user_cfg->reg0_ver);
2358 +       } else {
2359 +               printk(KERN_ERR "Invalid Region parameters\n");
2360 +               return -EINVAL;
2361 +       }
2362 +
2363 +       if (user_cfg->num_regions >= 1) {
2364 +               if (likely((user_cfg->reg1_hor & ISPHIST_REGHORIZ_HEND_MASK) -
2365 +                          ((user_cfg->reg1_hor &
2366 +                            ISPHIST_REGHORIZ_HSTART_MASK) >>
2367 +                           ISPHIST_REGHORIZ_HSTART_SHIFT))) {
2368 +                       WRITE_REG_HORIZ(hist_regs.reg_r1_h, user_cfg->reg1_hor);
2369 +               } else {
2370 +                       printk(KERN_ERR "Invalid Region parameters\n");
2371 +                       return -EINVAL;
2372 +               }
2373 +
2374 +               if (likely((user_cfg->reg1_ver & ISPHIST_REGVERT_VEND_MASK) -
2375 +                          ((user_cfg->reg1_ver &
2376 +                            ISPHIST_REGVERT_VSTART_MASK) >>
2377 +                           ISPHIST_REGVERT_VSTART_SHIFT))) {
2378 +                       WRITE_REG_VERT(hist_regs.reg_r1_v, user_cfg->reg1_ver);
2379 +               } else {
2380 +                       printk(KERN_ERR "Invalid Region parameters\n");
2381 +                       return -EINVAL;
2382 +               }
2383 +       }
2384 +
2385 +       if (user_cfg->num_regions >= 2) {
2386 +               if (likely((user_cfg->reg2_hor & ISPHIST_REGHORIZ_HEND_MASK) -
2387 +                          ((user_cfg->reg2_hor &
2388 +                            ISPHIST_REGHORIZ_HSTART_MASK) >>
2389 +                           ISPHIST_REGHORIZ_HSTART_SHIFT))) {
2390 +                       WRITE_REG_HORIZ(hist_regs.reg_r2_h, user_cfg->reg2_hor);
2391 +               } else {
2392 +                       printk(KERN_ERR "Invalid Region parameters\n");
2393 +                       return -EINVAL;
2394 +               }
2395 +
2396 +               if (likely((user_cfg->reg2_ver & ISPHIST_REGVERT_VEND_MASK) -
2397 +                          ((user_cfg->reg2_ver &
2398 +                            ISPHIST_REGVERT_VSTART_MASK) >>
2399 +                           ISPHIST_REGVERT_VSTART_SHIFT))) {
2400 +                       WRITE_REG_VERT(hist_regs.reg_r2_v, user_cfg->reg2_ver);
2401 +               } else {
2402 +                       printk(KERN_ERR "Invalid Region parameters\n");
2403 +                       return -EINVAL;
2404 +               }
2405 +       }
2406 +
2407 +       if (user_cfg->num_regions >= 3) {
2408 +               if (likely((user_cfg->reg3_hor & ISPHIST_REGHORIZ_HEND_MASK) -
2409 +                          ((user_cfg->reg3_hor &
2410 +                            ISPHIST_REGHORIZ_HSTART_MASK) >>
2411 +                           ISPHIST_REGHORIZ_HSTART_SHIFT))) {
2412 +                       WRITE_REG_HORIZ(hist_regs.reg_r3_h, user_cfg->reg3_hor);
2413 +               } else {
2414 +                       printk(KERN_ERR "Invalid Region parameters\n");
2415 +                       return -EINVAL;
2416 +               }
2417 +
2418 +               if (likely((user_cfg->reg3_ver & ISPHIST_REGVERT_VEND_MASK) -
2419 +                          ((user_cfg->reg3_ver &
2420 +                            ISPHIST_REGVERT_VSTART_MASK) >>
2421 +                           ISPHIST_REGVERT_VSTART_SHIFT))) {
2422 +                       WRITE_REG_VERT(hist_regs.reg_r3_v, user_cfg->reg3_ver);
2423 +               } else {
2424 +                       printk(KERN_ERR "Invalid Region parameters\n");
2425 +                       return -EINVAL;
2426 +               }
2427 +       }
2428 +       reg_num = user_cfg->num_regions;
2429 +       if (unlikely(((user_cfg->hist_bins > BINS_256) &&
2430 +                     (user_cfg->hist_bins != BINS_32)) ||
2431 +                    ((user_cfg->hist_bins == BINS_256) &&
2432 +                     reg_num != 0) || ((user_cfg->hist_bins ==
2433 +                                        BINS_128) && reg_num >= 2))) {
2434 +               printk(KERN_ERR "Invalid Bins Number: %d\n",
2435 +                      user_cfg->hist_bins);
2436 +               return -EINVAL;
2437 +       } else {
2438 +               WRITE_NUM_BINS(hist_regs.reg_cnt, user_cfg->hist_bins);
2439 +       }
2440 +
2441 +       if (user_cfg->input_bit_width > MAX_BIT_WIDTH ||
2442 +           user_cfg->input_bit_width < MIN_BIT_WIDTH) {
2443 +               printk(KERN_ERR "Invalid Bit Width: %d\n",
2444 +                      user_cfg->input_bit_width);
2445 +               return -EINVAL;
2446 +       } else {
2447 +               switch (user_cfg->hist_bins) {
2448 +               case BINS_256:
2449 +                       bit_shift = user_cfg->input_bit_width - 8;
2450 +                       break;
2451 +               case BINS_128:
2452 +                       bit_shift = user_cfg->input_bit_width - 7;
2453 +                       break;
2454 +               case BINS_64:
2455 +                       bit_shift = user_cfg->input_bit_width - 6;
2456 +                       break;
2457 +               case BINS_32:
2458 +                       bit_shift = user_cfg->input_bit_width - 5;
2459 +                       break;
2460 +               default:
2461 +                       return -EINVAL;
2462 +               }
2463 +               WRITE_BIT_SHIFT(hist_regs.reg_cnt, bit_shift);
2464 +       }
2465 +
2466 +       isp_hist_update_regs();
2467 +       histstat.initialized = 1;
2468 +
2469 +       return 0;
2470 +}
2471 +
2472 +/**
2473 + * isp_hist_configure - API to configure HIST registers.
2474 + * @histcfg: Pointer to user configuration structure.
2475 + *
2476 + * Returns 0 on success configuration.
2477 + **/
2478 +int isp_hist_configure(struct isp_hist_config *histcfg)
2479 +{
2480 +
2481 +       int ret = 0;
2482 +
2483 +       if (NULL == histcfg) {
2484 +               printk(KERN_ERR "Null argument in configuration. \n");
2485 +               return -EINVAL;
2486 +       }
2487 +
2488 +       if (!histstat.initialized) {
2489 +               DPRINTK_ISPHIST("Setting callback for HISTOGRAM\n");
2490 +               ret = isp_set_callback(CBK_HIST_DONE, isp_hist_isr,
2491 +                                      (void *)NULL, (void *)NULL);
2492 +               if (ret) {
2493 +                       printk(KERN_ERR "No callback for HIST\n");
2494 +                       return ret;
2495 +               }
2496 +       }
2497 +
2498 +       ret = isp_hist_set_params(histcfg);
2499 +       if (ret) {
2500 +               printk(KERN_ERR "Invalid parameters! \n");
2501 +               return ret;
2502 +       }
2503 +
2504 +       histstat.frame_cnt = 0;
2505 +       histstat.completed = 0;
2506 +       isp_hist_enable(1);
2507 +       isp_hist_print_status();
2508 +
2509 +       return 0;
2510 +}
2511 +EXPORT_SYMBOL(isp_hist_configure);
2512 +
2513 +/**
2514 + * isp_hist_request_statistics - Request statistics in Histogram.
2515 + * @histdata: Pointer to data structure.
2516 + *
2517 + * This API allows the user to request for histogram statistics.
2518 + *
2519 + * Returns 0 on successful request.
2520 + **/
2521 +int isp_hist_request_statistics(struct isp_hist_data *histdata)
2522 +{
2523 +       int i, ret;
2524 +       u32 curr;
2525 +
2526 +       if (isp_hist_busy())
2527 +               return -EBUSY;
2528 +
2529 +       if (!histstat.completed && histstat.initialized)
2530 +               return -EINVAL;
2531 +
2532 +       isp_reg_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLR_EN);
2533 +
2534 +       for (i = 0; i < HIST_MEM_SIZE; i++) {
2535 +               curr = isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
2536 +               ret = put_user(curr, histdata->hist_statistics_buf + i);
2537 +               if (ret) {
2538 +                       printk(KERN_ERR "Failed copy_to_user for "
2539 +                              "HIST stats buff, %d\n", ret);
2540 +               }
2541 +       }
2542 +
2543 +       isp_reg_and(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
2544 +                   ~ISPHIST_CNT_CLR_EN);
2545 +       histstat.completed = 0;
2546 +       return 0;
2547 +}
2548 +EXPORT_SYMBOL(isp_hist_request_statistics);
2549 +
2550 +/**
2551 + * isp_hist_init - Module Initialization.
2552 + *
2553 + * Returns 0 if successful.
2554 + **/
2555 +int __init isp_hist_init(void)
2556 +{
2557 +       memset(&histstat, 0, sizeof(histstat));
2558 +       memset(&hist_regs, 0, sizeof(hist_regs));
2559 +
2560 +       return 0;
2561 +}
2562 +
2563 +/**
2564 + * isp_hist_cleanup - Module cleanup.
2565 + **/
2566 +void isp_hist_cleanup(void)
2567 +{
2568 +       memset(&histstat, 0, sizeof(histstat));
2569 +       memset(&hist_regs, 0, sizeof(hist_regs));
2570 +}
2571 +
2572 +/**
2573 + * isphist_save_context - Saves the values of the histogram module registers.
2574 + **/
2575 +void isphist_save_context(void)
2576 +{
2577 +       DPRINTK_ISPHIST(" Saving context\n");
2578 +       isp_save_context(isphist_reg_list);
2579 +}
2580 +EXPORT_SYMBOL(isphist_save_context);
2581 +
2582 +/**
2583 + * isphist_restore_context - Restores the values of the histogram module regs.
2584 + **/
2585 +void isphist_restore_context(void)
2586 +{
2587 +       DPRINTK_ISPHIST(" Restoring context\n");
2588 +       isp_restore_context(isphist_reg_list);
2589 +}
2590 +EXPORT_SYMBOL(isphist_restore_context);
2591 +
2592 +/**
2593 + * isp_hist_print_status - Debug print
2594 + **/
2595 +static void isp_hist_print_status(void)
2596 +{
2597 +       DPRINTK_ISPHIST("ISPHIST_PCR = 0x%08x\n",
2598 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR));
2599 +       DPRINTK_ISPHIST("ISPHIST_CNT = 0x%08x\n",
2600 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT));
2601 +       DPRINTK_ISPHIST("ISPHIST_WB_GAIN = 0x%08x\n",
2602 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN));
2603 +       DPRINTK_ISPHIST("ISPHIST_R0_HORZ = 0x%08x\n",
2604 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ));
2605 +       DPRINTK_ISPHIST("ISPHIST_R0_VERT = 0x%08x\n",
2606 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT));
2607 +       DPRINTK_ISPHIST("ISPHIST_R1_HORZ = 0x%08x\n",
2608 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ));
2609 +       DPRINTK_ISPHIST("ISPHIST_R1_VERT = 0x%08x\n",
2610 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT));
2611 +       DPRINTK_ISPHIST("ISPHIST_R2_HORZ = 0x%08x\n",
2612 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ));
2613 +       DPRINTK_ISPHIST("ISPHIST_R2_VERT = 0x%08x\n",
2614 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT));
2615 +       DPRINTK_ISPHIST("ISPHIST_R3_HORZ = 0x%08x\n",
2616 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ));
2617 +       DPRINTK_ISPHIST("ISPHIST_R3_VERT = 0x%08x\n",
2618 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT));
2619 +       DPRINTK_ISPHIST("ISPHIST_ADDR = 0x%08x\n",
2620 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR));
2621 +       DPRINTK_ISPHIST("ISPHIST_RADD = 0x%08x\n",
2622 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD));
2623 +       DPRINTK_ISPHIST("ISPHIST_RADD_OFF = 0x%08x\n",
2624 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD_OFF));
2625 +       DPRINTK_ISPHIST("ISPHIST_H_V_INFO = 0x%08x\n",
2626 +                       isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_H_V_INFO));
2627 +}
2628 diff --git a/drivers/media/video/isp/isphist.h b/drivers/media/video/isp/isphist.h
2629 new file mode 100644
2630 index 0000000..6b17c4e
2631 --- /dev/null
2632 +++ b/drivers/media/video/isp/isphist.h
2633 @@ -0,0 +1,105 @@
2634 +/*
2635 + * isphist.h
2636 + *
2637 + * Header file for HISTOGRAM module in TI's OMAP3 Camera ISP
2638 + *
2639 + * Copyright (C) 2009 Texas Instruments, Inc.
2640 + *
2641 + * Contributors:
2642 + *     Sergio Aguirre <saaguirre@ti.com>
2643 + *     Troy Laramy
2644 + *
2645 + * This package is free software; you can redistribute it and/or modify
2646 + * it under the terms of the GNU General Public License version 2 as
2647 + * published by the Free Software Foundation.
2648 + *
2649 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2650 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2651 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2652 + */
2653 +
2654 +#ifndef OMAP_ISP_HIST_H
2655 +#define OMAP_ISP_HIST_H
2656 +
2657 +#include <mach/isp_user.h>
2658 +
2659 +#define MAX_REGIONS            0x4
2660 +#define MAX_WB_GAIN            255
2661 +#define MIN_WB_GAIN            0x0
2662 +#define MAX_BIT_WIDTH          14
2663 +#define MIN_BIT_WIDTH          8
2664 +
2665 +#define ISPHIST_PCR_EN         (1 << 0)
2666 +#define HIST_MEM_SIZE          1024
2667 +#define ISPHIST_CNT_CLR_EN     (1 << 7)
2668 +
2669 +#define WRITE_SOURCE(reg, source)                      \
2670 +       (reg = (reg & ~(ISPHIST_CNT_SOURCE_MASK))       \
2671 +        | (source << ISPHIST_CNT_SOURCE_SHIFT))
2672 +
2673 +#define WRITE_HV_INFO(reg, hv_info)                    \
2674 +       (reg = ((reg & ~(ISPHIST_HV_INFO_MASK))         \
2675 +               | (hv_info & ISPHIST_HV_INFO_MASK)))
2676 +
2677 +#define WRITE_RADD(reg, radd)                  \
2678 +       (reg = (reg & ~(ISPHIST_RADD_MASK))     \
2679 +        | (radd << ISPHIST_RADD_SHIFT))
2680 +
2681 +#define WRITE_RADD_OFF(reg, radd_off)                  \
2682 +       (reg = (reg & ~(ISPHIST_RADD_OFF_MASK))         \
2683 +        | (radd_off << ISPHIST_RADD_OFF_SHIFT))
2684 +
2685 +#define WRITE_BIT_SHIFT(reg, bit_shift)                        \
2686 +       (reg = (reg & ~(ISPHIST_CNT_SHIFT_MASK))        \
2687 +        | (bit_shift << ISPHIST_CNT_SHIFT_SHIFT))
2688 +
2689 +#define WRITE_DATA_SIZE(reg, data_size)                        \
2690 +       (reg = (reg & ~(ISPHIST_CNT_DATASIZE_MASK))     \
2691 +        | (data_size << ISPHIST_CNT_DATASIZE_SHIFT))
2692 +
2693 +#define WRITE_NUM_BINS(reg, num_bins)                  \
2694 +       (reg = (reg & ~(ISPHIST_CNT_BINS_MASK))         \
2695 +        | (num_bins << ISPHIST_CNT_BINS_SHIFT))
2696 +
2697 +#define WRITE_WB_R(reg, reg_wb_gain)                           \
2698 +       reg = ((reg & ~(ISPHIST_WB_GAIN_WG00_MASK))             \
2699 +              | (reg_wb_gain << ISPHIST_WB_GAIN_WG00_SHIFT))
2700 +
2701 +#define WRITE_WB_RG(reg, reg_wb_gain)                  \
2702 +       (reg = (reg & ~(ISPHIST_WB_GAIN_WG01_MASK))     \
2703 +        | (reg_wb_gain << ISPHIST_WB_GAIN_WG01_SHIFT))
2704 +
2705 +#define WRITE_WB_B(reg, reg_wb_gain)                   \
2706 +       (reg = (reg & ~(ISPHIST_WB_GAIN_WG02_MASK))     \
2707 +        | (reg_wb_gain << ISPHIST_WB_GAIN_WG02_SHIFT))
2708 +
2709 +#define WRITE_WB_BG(reg, reg_wb_gain)                  \
2710 +       (reg = (reg & ~(ISPHIST_WB_GAIN_WG03_MASK))     \
2711 +        | (reg_wb_gain << ISPHIST_WB_GAIN_WG03_SHIFT))
2712 +
2713 +#define WRITE_REG_HORIZ(reg, reg_n_hor)                        \
2714 +       (reg = ((reg & ~ISPHIST_REGHORIZ_MASK)          \
2715 +               | (reg_n_hor & ISPHIST_REGHORIZ_MASK)))
2716 +
2717 +#define WRITE_REG_VERT(reg, reg_n_vert)                        \
2718 +       (reg = ((reg & ~ISPHIST_REGVERT_MASK)           \
2719 +               | (reg_n_vert & ISPHIST_REGVERT_MASK)))
2720 +
2721 +
2722 +void isp_hist_enable(u8 enable);
2723 +
2724 +int isp_hist_busy(void);
2725 +
2726 +int isp_hist_configure(struct isp_hist_config *histcfg);
2727 +
2728 +int isp_hist_request_statistics(struct isp_hist_data *histdata);
2729 +
2730 +void isphist_save_context(void);
2731 +
2732 +void isp_hist_suspend(void);
2733 +
2734 +void isp_hist_resume(void);
2735 +
2736 +void isphist_restore_context(void);
2737 +
2738 +#endif                         /* OMAP_ISP_HIST */
2739 -- 
2740 1.5.6.5
2741