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:
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