summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch2741
1 files changed, 2741 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch
new file mode 100644
index 0000000000..876ce780f0
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch
@@ -0,0 +1,2741 @@
1From 9a39eab5ed1b70711c3b10de95cd90749293ef7a Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add statistics collection modules (H3A and HIST)
5
6Signed-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
22diff --git a/drivers/media/video/isp/isp_af.c b/drivers/media/video/isp/isp_af.c
23new file mode 100644
24index 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+}
812diff --git a/drivers/media/video/isp/isp_af.h b/drivers/media/video/isp/isp_af.h
813new file mode 100644
814index 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 */
943diff --git a/drivers/media/video/isp/isph3a.c b/drivers/media/video/isp/isph3a.c
944new file mode 100644
945index 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);
1881diff --git a/drivers/media/video/isp/isph3a.h b/drivers/media/video/isp/isph3a.h
1882new file mode 100644
1883index 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 */
2014diff --git a/drivers/media/video/isp/isphist.c b/drivers/media/video/isp/isphist.c
2015new file mode 100644
2016index 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+}
2628diff --git a/drivers/media/video/isp/isphist.h b/drivers/media/video/isp/isphist.h
2629new file mode 100644
2630index 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--
27401.5.6.5
2741