1*ceafdaacSMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0-only
2*ceafdaacSMauro Carvalho Chehab /*
3*ceafdaacSMauro Carvalho Chehab * isph3a.c
4*ceafdaacSMauro Carvalho Chehab *
5*ceafdaacSMauro Carvalho Chehab * TI OMAP3 ISP - H3A module
6*ceafdaacSMauro Carvalho Chehab *
7*ceafdaacSMauro Carvalho Chehab * Copyright (C) 2010 Nokia Corporation
8*ceafdaacSMauro Carvalho Chehab * Copyright (C) 2009 Texas Instruments, Inc.
9*ceafdaacSMauro Carvalho Chehab *
10*ceafdaacSMauro Carvalho Chehab * Contacts: David Cohen <dacohen@gmail.com>
11*ceafdaacSMauro Carvalho Chehab * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
12*ceafdaacSMauro Carvalho Chehab * Sakari Ailus <sakari.ailus@iki.fi>
13*ceafdaacSMauro Carvalho Chehab */
14*ceafdaacSMauro Carvalho Chehab
15*ceafdaacSMauro Carvalho Chehab #include <linux/slab.h>
16*ceafdaacSMauro Carvalho Chehab #include <linux/uaccess.h>
17*ceafdaacSMauro Carvalho Chehab
18*ceafdaacSMauro Carvalho Chehab #include "isp.h"
19*ceafdaacSMauro Carvalho Chehab #include "isph3a.h"
20*ceafdaacSMauro Carvalho Chehab #include "ispstat.h"
21*ceafdaacSMauro Carvalho Chehab
22*ceafdaacSMauro Carvalho Chehab /*
23*ceafdaacSMauro Carvalho Chehab * h3a_aewb_update_regs - Helper function to update h3a registers.
24*ceafdaacSMauro Carvalho Chehab */
h3a_aewb_setup_regs(struct ispstat * aewb,void * priv)25*ceafdaacSMauro Carvalho Chehab static void h3a_aewb_setup_regs(struct ispstat *aewb, void *priv)
26*ceafdaacSMauro Carvalho Chehab {
27*ceafdaacSMauro Carvalho Chehab struct omap3isp_h3a_aewb_config *conf = priv;
28*ceafdaacSMauro Carvalho Chehab u32 pcr;
29*ceafdaacSMauro Carvalho Chehab u32 win1;
30*ceafdaacSMauro Carvalho Chehab u32 start;
31*ceafdaacSMauro Carvalho Chehab u32 blk;
32*ceafdaacSMauro Carvalho Chehab u32 subwin;
33*ceafdaacSMauro Carvalho Chehab
34*ceafdaacSMauro Carvalho Chehab if (aewb->state == ISPSTAT_DISABLED)
35*ceafdaacSMauro Carvalho Chehab return;
36*ceafdaacSMauro Carvalho Chehab
37*ceafdaacSMauro Carvalho Chehab isp_reg_writel(aewb->isp, aewb->active_buf->dma_addr,
38*ceafdaacSMauro Carvalho Chehab OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST);
39*ceafdaacSMauro Carvalho Chehab
40*ceafdaacSMauro Carvalho Chehab if (!aewb->update)
41*ceafdaacSMauro Carvalho Chehab return;
42*ceafdaacSMauro Carvalho Chehab
43*ceafdaacSMauro Carvalho Chehab /* Converting config metadata into reg values */
44*ceafdaacSMauro Carvalho Chehab pcr = conf->saturation_limit << ISPH3A_PCR_AEW_AVE2LMT_SHIFT;
45*ceafdaacSMauro Carvalho Chehab pcr |= !!conf->alaw_enable << ISPH3A_PCR_AEW_ALAW_EN_SHIFT;
46*ceafdaacSMauro Carvalho Chehab
47*ceafdaacSMauro Carvalho Chehab win1 = ((conf->win_height >> 1) - 1) << ISPH3A_AEWWIN1_WINH_SHIFT;
48*ceafdaacSMauro Carvalho Chehab win1 |= ((conf->win_width >> 1) - 1) << ISPH3A_AEWWIN1_WINW_SHIFT;
49*ceafdaacSMauro Carvalho Chehab win1 |= (conf->ver_win_count - 1) << ISPH3A_AEWWIN1_WINVC_SHIFT;
50*ceafdaacSMauro Carvalho Chehab win1 |= (conf->hor_win_count - 1) << ISPH3A_AEWWIN1_WINHC_SHIFT;
51*ceafdaacSMauro Carvalho Chehab
52*ceafdaacSMauro Carvalho Chehab start = conf->hor_win_start << ISPH3A_AEWINSTART_WINSH_SHIFT;
53*ceafdaacSMauro Carvalho Chehab start |= conf->ver_win_start << ISPH3A_AEWINSTART_WINSV_SHIFT;
54*ceafdaacSMauro Carvalho Chehab
55*ceafdaacSMauro Carvalho Chehab blk = conf->blk_ver_win_start << ISPH3A_AEWINBLK_WINSV_SHIFT;
56*ceafdaacSMauro Carvalho Chehab blk |= ((conf->blk_win_height >> 1) - 1) << ISPH3A_AEWINBLK_WINH_SHIFT;
57*ceafdaacSMauro Carvalho Chehab
58*ceafdaacSMauro Carvalho Chehab subwin = ((conf->subsample_ver_inc >> 1) - 1) <<
59*ceafdaacSMauro Carvalho Chehab ISPH3A_AEWSUBWIN_AEWINCV_SHIFT;
60*ceafdaacSMauro Carvalho Chehab subwin |= ((conf->subsample_hor_inc >> 1) - 1) <<
61*ceafdaacSMauro Carvalho Chehab ISPH3A_AEWSUBWIN_AEWINCH_SHIFT;
62*ceafdaacSMauro Carvalho Chehab
63*ceafdaacSMauro Carvalho Chehab isp_reg_writel(aewb->isp, win1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1);
64*ceafdaacSMauro Carvalho Chehab isp_reg_writel(aewb->isp, start, OMAP3_ISP_IOMEM_H3A,
65*ceafdaacSMauro Carvalho Chehab ISPH3A_AEWINSTART);
66*ceafdaacSMauro Carvalho Chehab isp_reg_writel(aewb->isp, blk, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK);
67*ceafdaacSMauro Carvalho Chehab isp_reg_writel(aewb->isp, subwin, OMAP3_ISP_IOMEM_H3A,
68*ceafdaacSMauro Carvalho Chehab ISPH3A_AEWSUBWIN);
69*ceafdaacSMauro Carvalho Chehab isp_reg_clr_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
70*ceafdaacSMauro Carvalho Chehab ISPH3A_PCR_AEW_MASK, pcr);
71*ceafdaacSMauro Carvalho Chehab
72*ceafdaacSMauro Carvalho Chehab aewb->update = 0;
73*ceafdaacSMauro Carvalho Chehab aewb->config_counter += aewb->inc_config;
74*ceafdaacSMauro Carvalho Chehab aewb->inc_config = 0;
75*ceafdaacSMauro Carvalho Chehab aewb->buf_size = conf->buf_size;
76*ceafdaacSMauro Carvalho Chehab }
77*ceafdaacSMauro Carvalho Chehab
h3a_aewb_enable(struct ispstat * aewb,int enable)78*ceafdaacSMauro Carvalho Chehab static void h3a_aewb_enable(struct ispstat *aewb, int enable)
79*ceafdaacSMauro Carvalho Chehab {
80*ceafdaacSMauro Carvalho Chehab if (enable) {
81*ceafdaacSMauro Carvalho Chehab isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
82*ceafdaacSMauro Carvalho Chehab ISPH3A_PCR_AEW_EN);
83*ceafdaacSMauro Carvalho Chehab omap3isp_subclk_enable(aewb->isp, OMAP3_ISP_SUBCLK_AEWB);
84*ceafdaacSMauro Carvalho Chehab } else {
85*ceafdaacSMauro Carvalho Chehab isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
86*ceafdaacSMauro Carvalho Chehab ISPH3A_PCR_AEW_EN);
87*ceafdaacSMauro Carvalho Chehab omap3isp_subclk_disable(aewb->isp, OMAP3_ISP_SUBCLK_AEWB);
88*ceafdaacSMauro Carvalho Chehab }
89*ceafdaacSMauro Carvalho Chehab }
90*ceafdaacSMauro Carvalho Chehab
h3a_aewb_busy(struct ispstat * aewb)91*ceafdaacSMauro Carvalho Chehab static int h3a_aewb_busy(struct ispstat *aewb)
92*ceafdaacSMauro Carvalho Chehab {
93*ceafdaacSMauro Carvalho Chehab return isp_reg_readl(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
94*ceafdaacSMauro Carvalho Chehab & ISPH3A_PCR_BUSYAEAWB;
95*ceafdaacSMauro Carvalho Chehab }
96*ceafdaacSMauro Carvalho Chehab
h3a_aewb_get_buf_size(struct omap3isp_h3a_aewb_config * conf)97*ceafdaacSMauro Carvalho Chehab static u32 h3a_aewb_get_buf_size(struct omap3isp_h3a_aewb_config *conf)
98*ceafdaacSMauro Carvalho Chehab {
99*ceafdaacSMauro Carvalho Chehab /* Number of configured windows + extra row for black data */
100*ceafdaacSMauro Carvalho Chehab u32 win_count = (conf->ver_win_count + 1) * conf->hor_win_count;
101*ceafdaacSMauro Carvalho Chehab
102*ceafdaacSMauro Carvalho Chehab /*
103*ceafdaacSMauro Carvalho Chehab * Unsaturated block counts for each 8 windows.
104*ceafdaacSMauro Carvalho Chehab * 1 extra for the last (win_count % 8) windows if win_count is not
105*ceafdaacSMauro Carvalho Chehab * divisible by 8.
106*ceafdaacSMauro Carvalho Chehab */
107*ceafdaacSMauro Carvalho Chehab win_count += (win_count + 7) / 8;
108*ceafdaacSMauro Carvalho Chehab
109*ceafdaacSMauro Carvalho Chehab return win_count * AEWB_PACKET_SIZE;
110*ceafdaacSMauro Carvalho Chehab }
111*ceafdaacSMauro Carvalho Chehab
h3a_aewb_validate_params(struct ispstat * aewb,void * new_conf)112*ceafdaacSMauro Carvalho Chehab static int h3a_aewb_validate_params(struct ispstat *aewb, void *new_conf)
113*ceafdaacSMauro Carvalho Chehab {
114*ceafdaacSMauro Carvalho Chehab struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
115*ceafdaacSMauro Carvalho Chehab u32 buf_size;
116*ceafdaacSMauro Carvalho Chehab
117*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->saturation_limit >
118*ceafdaacSMauro Carvalho Chehab OMAP3ISP_AEWB_MAX_SATURATION_LIM))
119*ceafdaacSMauro Carvalho Chehab return -EINVAL;
120*ceafdaacSMauro Carvalho Chehab
121*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
122*ceafdaacSMauro Carvalho Chehab user_cfg->win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
123*ceafdaacSMauro Carvalho Chehab user_cfg->win_height & 0x01))
124*ceafdaacSMauro Carvalho Chehab return -EINVAL;
125*ceafdaacSMauro Carvalho Chehab
126*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->win_width < OMAP3ISP_AEWB_MIN_WIN_W ||
127*ceafdaacSMauro Carvalho Chehab user_cfg->win_width > OMAP3ISP_AEWB_MAX_WIN_W ||
128*ceafdaacSMauro Carvalho Chehab user_cfg->win_width & 0x01))
129*ceafdaacSMauro Carvalho Chehab return -EINVAL;
130*ceafdaacSMauro Carvalho Chehab
131*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->ver_win_count < OMAP3ISP_AEWB_MIN_WINVC ||
132*ceafdaacSMauro Carvalho Chehab user_cfg->ver_win_count > OMAP3ISP_AEWB_MAX_WINVC))
133*ceafdaacSMauro Carvalho Chehab return -EINVAL;
134*ceafdaacSMauro Carvalho Chehab
135*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->hor_win_count < OMAP3ISP_AEWB_MIN_WINHC ||
136*ceafdaacSMauro Carvalho Chehab user_cfg->hor_win_count > OMAP3ISP_AEWB_MAX_WINHC))
137*ceafdaacSMauro Carvalho Chehab return -EINVAL;
138*ceafdaacSMauro Carvalho Chehab
139*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
140*ceafdaacSMauro Carvalho Chehab return -EINVAL;
141*ceafdaacSMauro Carvalho Chehab
142*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->hor_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
143*ceafdaacSMauro Carvalho Chehab return -EINVAL;
144*ceafdaacSMauro Carvalho Chehab
145*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->blk_ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
146*ceafdaacSMauro Carvalho Chehab return -EINVAL;
147*ceafdaacSMauro Carvalho Chehab
148*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->blk_win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
149*ceafdaacSMauro Carvalho Chehab user_cfg->blk_win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
150*ceafdaacSMauro Carvalho Chehab user_cfg->blk_win_height & 0x01))
151*ceafdaacSMauro Carvalho Chehab return -EINVAL;
152*ceafdaacSMauro Carvalho Chehab
153*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->subsample_ver_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
154*ceafdaacSMauro Carvalho Chehab user_cfg->subsample_ver_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
155*ceafdaacSMauro Carvalho Chehab user_cfg->subsample_ver_inc & 0x01))
156*ceafdaacSMauro Carvalho Chehab return -EINVAL;
157*ceafdaacSMauro Carvalho Chehab
158*ceafdaacSMauro Carvalho Chehab if (unlikely(user_cfg->subsample_hor_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
159*ceafdaacSMauro Carvalho Chehab user_cfg->subsample_hor_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
160*ceafdaacSMauro Carvalho Chehab user_cfg->subsample_hor_inc & 0x01))
161*ceafdaacSMauro Carvalho Chehab return -EINVAL;
162*ceafdaacSMauro Carvalho Chehab
163*ceafdaacSMauro Carvalho Chehab buf_size = h3a_aewb_get_buf_size(user_cfg);
164*ceafdaacSMauro Carvalho Chehab if (buf_size > user_cfg->buf_size)
165*ceafdaacSMauro Carvalho Chehab user_cfg->buf_size = buf_size;
166*ceafdaacSMauro Carvalho Chehab else if (user_cfg->buf_size > OMAP3ISP_AEWB_MAX_BUF_SIZE)
167*ceafdaacSMauro Carvalho Chehab user_cfg->buf_size = OMAP3ISP_AEWB_MAX_BUF_SIZE;
168*ceafdaacSMauro Carvalho Chehab
169*ceafdaacSMauro Carvalho Chehab return 0;
170*ceafdaacSMauro Carvalho Chehab }
171*ceafdaacSMauro Carvalho Chehab
172*ceafdaacSMauro Carvalho Chehab /*
173*ceafdaacSMauro Carvalho Chehab * h3a_aewb_set_params - Helper function to check & store user given params.
174*ceafdaacSMauro Carvalho Chehab * @new_conf: Pointer to AE and AWB parameters struct.
175*ceafdaacSMauro Carvalho Chehab *
176*ceafdaacSMauro Carvalho Chehab * As most of them are busy-lock registers, need to wait until AEW_BUSY = 0 to
177*ceafdaacSMauro Carvalho Chehab * program them during ISR.
178*ceafdaacSMauro Carvalho Chehab */
h3a_aewb_set_params(struct ispstat * aewb,void * new_conf)179*ceafdaacSMauro Carvalho Chehab static void h3a_aewb_set_params(struct ispstat *aewb, void *new_conf)
180*ceafdaacSMauro Carvalho Chehab {
181*ceafdaacSMauro Carvalho Chehab struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
182*ceafdaacSMauro Carvalho Chehab struct omap3isp_h3a_aewb_config *cur_cfg = aewb->priv;
183*ceafdaacSMauro Carvalho Chehab int update = 0;
184*ceafdaacSMauro Carvalho Chehab
185*ceafdaacSMauro Carvalho Chehab if (cur_cfg->saturation_limit != user_cfg->saturation_limit) {
186*ceafdaacSMauro Carvalho Chehab cur_cfg->saturation_limit = user_cfg->saturation_limit;
187*ceafdaacSMauro Carvalho Chehab update = 1;
188*ceafdaacSMauro Carvalho Chehab }
189*ceafdaacSMauro Carvalho Chehab if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
190*ceafdaacSMauro Carvalho Chehab cur_cfg->alaw_enable = user_cfg->alaw_enable;
191*ceafdaacSMauro Carvalho Chehab update = 1;
192*ceafdaacSMauro Carvalho Chehab }
193*ceafdaacSMauro Carvalho Chehab if (cur_cfg->win_height != user_cfg->win_height) {
194*ceafdaacSMauro Carvalho Chehab cur_cfg->win_height = user_cfg->win_height;
195*ceafdaacSMauro Carvalho Chehab update = 1;
196*ceafdaacSMauro Carvalho Chehab }
197*ceafdaacSMauro Carvalho Chehab if (cur_cfg->win_width != user_cfg->win_width) {
198*ceafdaacSMauro Carvalho Chehab cur_cfg->win_width = user_cfg->win_width;
199*ceafdaacSMauro Carvalho Chehab update = 1;
200*ceafdaacSMauro Carvalho Chehab }
201*ceafdaacSMauro Carvalho Chehab if (cur_cfg->ver_win_count != user_cfg->ver_win_count) {
202*ceafdaacSMauro Carvalho Chehab cur_cfg->ver_win_count = user_cfg->ver_win_count;
203*ceafdaacSMauro Carvalho Chehab update = 1;
204*ceafdaacSMauro Carvalho Chehab }
205*ceafdaacSMauro Carvalho Chehab if (cur_cfg->hor_win_count != user_cfg->hor_win_count) {
206*ceafdaacSMauro Carvalho Chehab cur_cfg->hor_win_count = user_cfg->hor_win_count;
207*ceafdaacSMauro Carvalho Chehab update = 1;
208*ceafdaacSMauro Carvalho Chehab }
209*ceafdaacSMauro Carvalho Chehab if (cur_cfg->ver_win_start != user_cfg->ver_win_start) {
210*ceafdaacSMauro Carvalho Chehab cur_cfg->ver_win_start = user_cfg->ver_win_start;
211*ceafdaacSMauro Carvalho Chehab update = 1;
212*ceafdaacSMauro Carvalho Chehab }
213*ceafdaacSMauro Carvalho Chehab if (cur_cfg->hor_win_start != user_cfg->hor_win_start) {
214*ceafdaacSMauro Carvalho Chehab cur_cfg->hor_win_start = user_cfg->hor_win_start;
215*ceafdaacSMauro Carvalho Chehab update = 1;
216*ceafdaacSMauro Carvalho Chehab }
217*ceafdaacSMauro Carvalho Chehab if (cur_cfg->blk_ver_win_start != user_cfg->blk_ver_win_start) {
218*ceafdaacSMauro Carvalho Chehab cur_cfg->blk_ver_win_start = user_cfg->blk_ver_win_start;
219*ceafdaacSMauro Carvalho Chehab update = 1;
220*ceafdaacSMauro Carvalho Chehab }
221*ceafdaacSMauro Carvalho Chehab if (cur_cfg->blk_win_height != user_cfg->blk_win_height) {
222*ceafdaacSMauro Carvalho Chehab cur_cfg->blk_win_height = user_cfg->blk_win_height;
223*ceafdaacSMauro Carvalho Chehab update = 1;
224*ceafdaacSMauro Carvalho Chehab }
225*ceafdaacSMauro Carvalho Chehab if (cur_cfg->subsample_ver_inc != user_cfg->subsample_ver_inc) {
226*ceafdaacSMauro Carvalho Chehab cur_cfg->subsample_ver_inc = user_cfg->subsample_ver_inc;
227*ceafdaacSMauro Carvalho Chehab update = 1;
228*ceafdaacSMauro Carvalho Chehab }
229*ceafdaacSMauro Carvalho Chehab if (cur_cfg->subsample_hor_inc != user_cfg->subsample_hor_inc) {
230*ceafdaacSMauro Carvalho Chehab cur_cfg->subsample_hor_inc = user_cfg->subsample_hor_inc;
231*ceafdaacSMauro Carvalho Chehab update = 1;
232*ceafdaacSMauro Carvalho Chehab }
233*ceafdaacSMauro Carvalho Chehab
234*ceafdaacSMauro Carvalho Chehab if (update || !aewb->configured) {
235*ceafdaacSMauro Carvalho Chehab aewb->inc_config++;
236*ceafdaacSMauro Carvalho Chehab aewb->update = 1;
237*ceafdaacSMauro Carvalho Chehab cur_cfg->buf_size = h3a_aewb_get_buf_size(cur_cfg);
238*ceafdaacSMauro Carvalho Chehab }
239*ceafdaacSMauro Carvalho Chehab }
240*ceafdaacSMauro Carvalho Chehab
h3a_aewb_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)241*ceafdaacSMauro Carvalho Chehab static long h3a_aewb_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
242*ceafdaacSMauro Carvalho Chehab {
243*ceafdaacSMauro Carvalho Chehab struct ispstat *stat = v4l2_get_subdevdata(sd);
244*ceafdaacSMauro Carvalho Chehab
245*ceafdaacSMauro Carvalho Chehab switch (cmd) {
246*ceafdaacSMauro Carvalho Chehab case VIDIOC_OMAP3ISP_AEWB_CFG:
247*ceafdaacSMauro Carvalho Chehab return omap3isp_stat_config(stat, arg);
248*ceafdaacSMauro Carvalho Chehab case VIDIOC_OMAP3ISP_STAT_REQ:
249*ceafdaacSMauro Carvalho Chehab return omap3isp_stat_request_statistics(stat, arg);
250*ceafdaacSMauro Carvalho Chehab case VIDIOC_OMAP3ISP_STAT_REQ_TIME32:
251*ceafdaacSMauro Carvalho Chehab return omap3isp_stat_request_statistics_time32(stat, arg);
252*ceafdaacSMauro Carvalho Chehab case VIDIOC_OMAP3ISP_STAT_EN: {
253*ceafdaacSMauro Carvalho Chehab unsigned long *en = arg;
254*ceafdaacSMauro Carvalho Chehab return omap3isp_stat_enable(stat, !!*en);
255*ceafdaacSMauro Carvalho Chehab }
256*ceafdaacSMauro Carvalho Chehab }
257*ceafdaacSMauro Carvalho Chehab
258*ceafdaacSMauro Carvalho Chehab return -ENOIOCTLCMD;
259*ceafdaacSMauro Carvalho Chehab }
260*ceafdaacSMauro Carvalho Chehab
261*ceafdaacSMauro Carvalho Chehab static const struct ispstat_ops h3a_aewb_ops = {
262*ceafdaacSMauro Carvalho Chehab .validate_params = h3a_aewb_validate_params,
263*ceafdaacSMauro Carvalho Chehab .set_params = h3a_aewb_set_params,
264*ceafdaacSMauro Carvalho Chehab .setup_regs = h3a_aewb_setup_regs,
265*ceafdaacSMauro Carvalho Chehab .enable = h3a_aewb_enable,
266*ceafdaacSMauro Carvalho Chehab .busy = h3a_aewb_busy,
267*ceafdaacSMauro Carvalho Chehab };
268*ceafdaacSMauro Carvalho Chehab
269*ceafdaacSMauro Carvalho Chehab static const struct v4l2_subdev_core_ops h3a_aewb_subdev_core_ops = {
270*ceafdaacSMauro Carvalho Chehab .ioctl = h3a_aewb_ioctl,
271*ceafdaacSMauro Carvalho Chehab .subscribe_event = omap3isp_stat_subscribe_event,
272*ceafdaacSMauro Carvalho Chehab .unsubscribe_event = omap3isp_stat_unsubscribe_event,
273*ceafdaacSMauro Carvalho Chehab };
274*ceafdaacSMauro Carvalho Chehab
275*ceafdaacSMauro Carvalho Chehab static const struct v4l2_subdev_video_ops h3a_aewb_subdev_video_ops = {
276*ceafdaacSMauro Carvalho Chehab .s_stream = omap3isp_stat_s_stream,
277*ceafdaacSMauro Carvalho Chehab };
278*ceafdaacSMauro Carvalho Chehab
279*ceafdaacSMauro Carvalho Chehab static const struct v4l2_subdev_ops h3a_aewb_subdev_ops = {
280*ceafdaacSMauro Carvalho Chehab .core = &h3a_aewb_subdev_core_ops,
281*ceafdaacSMauro Carvalho Chehab .video = &h3a_aewb_subdev_video_ops,
282*ceafdaacSMauro Carvalho Chehab };
283*ceafdaacSMauro Carvalho Chehab
284*ceafdaacSMauro Carvalho Chehab /*
285*ceafdaacSMauro Carvalho Chehab * omap3isp_h3a_aewb_init - Module Initialisation.
286*ceafdaacSMauro Carvalho Chehab */
omap3isp_h3a_aewb_init(struct isp_device * isp)287*ceafdaacSMauro Carvalho Chehab int omap3isp_h3a_aewb_init(struct isp_device *isp)
288*ceafdaacSMauro Carvalho Chehab {
289*ceafdaacSMauro Carvalho Chehab struct ispstat *aewb = &isp->isp_aewb;
290*ceafdaacSMauro Carvalho Chehab struct omap3isp_h3a_aewb_config *aewb_cfg;
291*ceafdaacSMauro Carvalho Chehab struct omap3isp_h3a_aewb_config *aewb_recover_cfg = NULL;
292*ceafdaacSMauro Carvalho Chehab int ret;
293*ceafdaacSMauro Carvalho Chehab
294*ceafdaacSMauro Carvalho Chehab aewb_cfg = kzalloc(sizeof(*aewb_cfg), GFP_KERNEL);
295*ceafdaacSMauro Carvalho Chehab if (!aewb_cfg)
296*ceafdaacSMauro Carvalho Chehab return -ENOMEM;
297*ceafdaacSMauro Carvalho Chehab
298*ceafdaacSMauro Carvalho Chehab aewb->ops = &h3a_aewb_ops;
299*ceafdaacSMauro Carvalho Chehab aewb->priv = aewb_cfg;
300*ceafdaacSMauro Carvalho Chehab aewb->event_type = V4L2_EVENT_OMAP3ISP_AEWB;
301*ceafdaacSMauro Carvalho Chehab aewb->isp = isp;
302*ceafdaacSMauro Carvalho Chehab
303*ceafdaacSMauro Carvalho Chehab /* Set recover state configuration */
304*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg = kzalloc(sizeof(*aewb_recover_cfg), GFP_KERNEL);
305*ceafdaacSMauro Carvalho Chehab if (!aewb_recover_cfg) {
306*ceafdaacSMauro Carvalho Chehab dev_err(aewb->isp->dev,
307*ceafdaacSMauro Carvalho Chehab "AEWB: cannot allocate memory for recover configuration.\n");
308*ceafdaacSMauro Carvalho Chehab ret = -ENOMEM;
309*ceafdaacSMauro Carvalho Chehab goto err;
310*ceafdaacSMauro Carvalho Chehab }
311*ceafdaacSMauro Carvalho Chehab
312*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->saturation_limit = OMAP3ISP_AEWB_MAX_SATURATION_LIM;
313*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->win_height = OMAP3ISP_AEWB_MIN_WIN_H;
314*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->win_width = OMAP3ISP_AEWB_MIN_WIN_W;
315*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->ver_win_count = OMAP3ISP_AEWB_MIN_WINVC;
316*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->hor_win_count = OMAP3ISP_AEWB_MIN_WINHC;
317*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->blk_ver_win_start = aewb_recover_cfg->ver_win_start +
318*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->win_height * aewb_recover_cfg->ver_win_count;
319*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->blk_win_height = OMAP3ISP_AEWB_MIN_WIN_H;
320*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->subsample_ver_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
321*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->subsample_hor_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
322*ceafdaacSMauro Carvalho Chehab
323*ceafdaacSMauro Carvalho Chehab if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) {
324*ceafdaacSMauro Carvalho Chehab dev_err(aewb->isp->dev,
325*ceafdaacSMauro Carvalho Chehab "AEWB: recover configuration is invalid.\n");
326*ceafdaacSMauro Carvalho Chehab ret = -EINVAL;
327*ceafdaacSMauro Carvalho Chehab goto err;
328*ceafdaacSMauro Carvalho Chehab }
329*ceafdaacSMauro Carvalho Chehab
330*ceafdaacSMauro Carvalho Chehab aewb_recover_cfg->buf_size = h3a_aewb_get_buf_size(aewb_recover_cfg);
331*ceafdaacSMauro Carvalho Chehab aewb->recover_priv = aewb_recover_cfg;
332*ceafdaacSMauro Carvalho Chehab
333*ceafdaacSMauro Carvalho Chehab ret = omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops);
334*ceafdaacSMauro Carvalho Chehab
335*ceafdaacSMauro Carvalho Chehab err:
336*ceafdaacSMauro Carvalho Chehab if (ret) {
337*ceafdaacSMauro Carvalho Chehab kfree(aewb_cfg);
338*ceafdaacSMauro Carvalho Chehab kfree(aewb_recover_cfg);
339*ceafdaacSMauro Carvalho Chehab }
340*ceafdaacSMauro Carvalho Chehab
341*ceafdaacSMauro Carvalho Chehab return ret;
342*ceafdaacSMauro Carvalho Chehab }
343*ceafdaacSMauro Carvalho Chehab
344*ceafdaacSMauro Carvalho Chehab /*
345*ceafdaacSMauro Carvalho Chehab * omap3isp_h3a_aewb_cleanup - Module exit.
346*ceafdaacSMauro Carvalho Chehab */
omap3isp_h3a_aewb_cleanup(struct isp_device * isp)347*ceafdaacSMauro Carvalho Chehab void omap3isp_h3a_aewb_cleanup(struct isp_device *isp)
348*ceafdaacSMauro Carvalho Chehab {
349*ceafdaacSMauro Carvalho Chehab omap3isp_stat_cleanup(&isp->isp_aewb);
350*ceafdaacSMauro Carvalho Chehab }
351