aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorManjunath Hadli <manjunath.hadli@ti.com>2012-11-28 00:14:10 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-12-21 11:13:53 -0500
commitda43b6ccadcfe801e0316503334f8281b8679210 (patch)
tree142de22b7ddfc84f04a3ea1deca423f7896afbc9 /drivers/staging
parent6a630533c4461c1e6dabfab5f11d9e98cb743bc2 (diff)
[media] davinci: vpfe: dm365: add IPIPE support for media controller driver
Add the IPIPE subdevice to the DM365 vpfe driver. The IPIPE is the major sub IP in the DM365 capture VPFE hardware and implements black clamping, color space conversion, edge enhancements etc. the block is exposed as a subdevice and implements media controller based setup and a private IOCTL for fine grain control. Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com> Signed-off-by: Lad, Prabhakar <prabhakar.lad@ti.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Sakari Ailus <sakari.ailus@iki.fi> Acked-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipe.c1863
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipe.h179
2 files changed, 2042 insertions, 0 deletions
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
new file mode 100644
index 000000000000..92853539cc0a
--- /dev/null
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
@@ -0,0 +1,1863 @@
1/*
2 * Copyright (C) 2012 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Contributors:
18 * Manjunath Hadli <manjunath.hadli@ti.com>
19 * Prabhakar Lad <prabhakar.lad@ti.com>
20 *
21 *
22 * IPIPE allows fine tuning of the input image using different
23 * tuning modules in IPIPE. Some examples :- Noise filter, Defect
24 * pixel correction etc. It essentially operate on Bayer Raw data
25 * or YUV raw data. To do image tuning, application call,
26 *
27 */
28
29#include <linux/slab.h>
30
31#include "dm365_ipipe.h"
32#include "dm365_ipipe_hw.h"
33#include "vpfe_mc_capture.h"
34
35#define MIN_OUT_WIDTH 32
36#define MIN_OUT_HEIGHT 32
37
38/* ipipe input format's */
39static const unsigned int ipipe_input_fmts[] = {
40 V4L2_MBUS_FMT_UYVY8_2X8,
41 V4L2_MBUS_FMT_SGRBG12_1X12,
42 V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
43 V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8,
44};
45
46/* ipipe output format's */
47static const unsigned int ipipe_output_fmts[] = {
48 V4L2_MBUS_FMT_UYVY8_2X8,
49};
50
51static int ipipe_validate_lutdpc_params(struct vpfe_ipipe_lutdpc *lutdpc)
52{
53 int i;
54
55 if (lutdpc->en > 1 || lutdpc->repl_white > 1 ||
56 lutdpc->dpc_size > LUT_DPC_MAX_SIZE)
57 return -EINVAL;
58
59 if (lutdpc->en && !lutdpc->table)
60 return -EINVAL;
61
62 for (i = 0; i < lutdpc->dpc_size; i++)
63 if (lutdpc->table[i].horz_pos > LUT_DPC_H_POS_MASK ||
64 lutdpc->table[i].vert_pos > LUT_DPC_V_POS_MASK)
65 return -EINVAL;
66
67 return 0;
68}
69
70static int ipipe_set_lutdpc_params(struct vpfe_ipipe_device *ipipe, void *param)
71{
72 struct vpfe_ipipe_lutdpc *lutdpc = &ipipe->config.lutdpc;
73 struct vpfe_ipipe_lutdpc *dpc_param;
74 struct device *dev;
75
76 if (!param) {
77 memset((void *)lutdpc, 0, sizeof(struct vpfe_ipipe_lutdpc));
78 goto success;
79 }
80
81 dev = ipipe->subdev.v4l2_dev->dev;
82 dpc_param = (struct vpfe_ipipe_lutdpc *)param;
83 lutdpc->en = dpc_param->en;
84 lutdpc->repl_white = dpc_param->repl_white;
85 lutdpc->dpc_size = dpc_param->dpc_size;
86 memcpy(&lutdpc->table, &dpc_param->table,
87 (dpc_param->dpc_size * sizeof(struct vpfe_ipipe_lutdpc_entry)));
88 if (ipipe_validate_lutdpc_params(lutdpc) < 0)
89 return -EINVAL;
90
91success:
92 ipipe_set_lutdpc_regs(ipipe->base_addr, ipipe->isp5_base_addr, lutdpc);
93
94 return 0;
95}
96
97static int ipipe_get_lutdpc_params(struct vpfe_ipipe_device *ipipe, void *param)
98{
99 struct vpfe_ipipe_lutdpc *lut_param = (struct vpfe_ipipe_lutdpc *)param;
100 struct vpfe_ipipe_lutdpc *lutdpc = &ipipe->config.lutdpc;
101
102 lut_param->en = lutdpc->en;
103 lut_param->repl_white = lutdpc->repl_white;
104 lut_param->dpc_size = lutdpc->dpc_size;
105 memcpy(&lut_param->table, &lutdpc->table,
106 (lutdpc->dpc_size * sizeof(struct vpfe_ipipe_lutdpc_entry)));
107
108 return 0;
109}
110
111static int ipipe_set_input_config(struct vpfe_ipipe_device *ipipe, void *param)
112{
113 struct vpfe_ipipe_input_config *config = &ipipe->config.input_config;
114
115 if (!param)
116 memset(config, 0, sizeof(struct vpfe_ipipe_input_config));
117 else
118 memcpy(config, param, sizeof(struct vpfe_ipipe_input_config));
119 return 0;
120}
121
122static int ipipe_get_input_config(struct vpfe_ipipe_device *ipipe, void *param)
123{
124 struct vpfe_ipipe_input_config *config = &ipipe->config.input_config;
125
126 if (!param)
127 return -EINVAL;
128
129 memcpy(param, config, sizeof(struct vpfe_ipipe_input_config));
130
131 return 0;
132}
133
134static int ipipe_validate_otfdpc_params(struct vpfe_ipipe_otfdpc *dpc_param)
135{
136 struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0;
137 struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0;
138
139 if (dpc_param->en > 1)
140 return -EINVAL;
141
142 if (dpc_param->alg == VPFE_IPIPE_OTFDPC_2_0) {
143 dpc_2_0 = &dpc_param->alg_cfg.dpc_2_0;
144 if (dpc_2_0->det_thr.r > OTFDPC_DPC2_THR_MASK ||
145 dpc_2_0->det_thr.gr > OTFDPC_DPC2_THR_MASK ||
146 dpc_2_0->det_thr.gb > OTFDPC_DPC2_THR_MASK ||
147 dpc_2_0->det_thr.b > OTFDPC_DPC2_THR_MASK ||
148 dpc_2_0->corr_thr.r > OTFDPC_DPC2_THR_MASK ||
149 dpc_2_0->corr_thr.gr > OTFDPC_DPC2_THR_MASK ||
150 dpc_2_0->corr_thr.gb > OTFDPC_DPC2_THR_MASK ||
151 dpc_2_0->corr_thr.b > OTFDPC_DPC2_THR_MASK)
152 return -EINVAL;
153 return 0;
154 }
155
156 dpc_3_0 = &dpc_param->alg_cfg.dpc_3_0;
157
158 if (dpc_3_0->act_adj_shf > OTF_DPC3_0_SHF_MASK ||
159 dpc_3_0->det_thr > OTF_DPC3_0_DET_MASK ||
160 dpc_3_0->det_slp > OTF_DPC3_0_SLP_MASK ||
161 dpc_3_0->det_thr_min > OTF_DPC3_0_DET_MASK ||
162 dpc_3_0->det_thr_max > OTF_DPC3_0_DET_MASK ||
163 dpc_3_0->corr_thr > OTF_DPC3_0_CORR_MASK ||
164 dpc_3_0->corr_slp > OTF_DPC3_0_SLP_MASK ||
165 dpc_3_0->corr_thr_min > OTF_DPC3_0_CORR_MASK ||
166 dpc_3_0->corr_thr_max > OTF_DPC3_0_CORR_MASK)
167 return -EINVAL;
168
169 return 0;
170}
171
172static int ipipe_set_otfdpc_params(struct vpfe_ipipe_device *ipipe, void *param)
173{
174 struct vpfe_ipipe_otfdpc *dpc_param = (struct vpfe_ipipe_otfdpc *)param;
175 struct vpfe_ipipe_otfdpc *otfdpc = &ipipe->config.otfdpc;
176 struct device *dev;
177
178 if (!param) {
179 memset((void *)otfdpc, 0, sizeof(struct ipipe_otfdpc_2_0));
180 goto success;
181 }
182 dev = ipipe->subdev.v4l2_dev->dev;
183 memcpy(otfdpc, dpc_param, sizeof(struct vpfe_ipipe_otfdpc));
184 if (ipipe_validate_otfdpc_params(otfdpc) < 0) {
185 dev_err(dev, "Invalid otfdpc params\n");
186 return -EINVAL;
187 }
188
189success:
190 ipipe_set_otfdpc_regs(ipipe->base_addr, otfdpc);
191
192 return 0;
193}
194
195static int ipipe_get_otfdpc_params(struct vpfe_ipipe_device *ipipe, void *param)
196{
197 struct vpfe_ipipe_otfdpc *dpc_param = (struct vpfe_ipipe_otfdpc *)param;
198 struct vpfe_ipipe_otfdpc *otfdpc = &ipipe->config.otfdpc;
199
200 memcpy(dpc_param, otfdpc, sizeof(struct vpfe_ipipe_otfdpc));
201 return 0;
202}
203
204static int ipipe_validate_nf_params(struct vpfe_ipipe_nf *nf_param)
205{
206 int i;
207
208 if (nf_param->en > 1 || nf_param->shft_val > D2F_SHFT_VAL_MASK ||
209 nf_param->spread_val > D2F_SPR_VAL_MASK ||
210 nf_param->apply_lsc_gain > 1 ||
211 nf_param->edge_det_min_thr > D2F_EDGE_DET_THR_MASK ||
212 nf_param->edge_det_max_thr > D2F_EDGE_DET_THR_MASK)
213 return -EINVAL;
214
215 for (i = 0; i < VPFE_IPIPE_NF_THR_TABLE_SIZE; i++)
216 if (nf_param->thr[i] > D2F_THR_VAL_MASK)
217 return -EINVAL;
218
219 for (i = 0; i < VPFE_IPIPE_NF_STR_TABLE_SIZE; i++)
220 if (nf_param->str[i] > D2F_STR_VAL_MASK)
221 return -EINVAL;
222
223 return 0;
224}
225
226static int ipipe_set_nf_params(struct vpfe_ipipe_device *ipipe,
227 unsigned int id, void *param)
228{
229 struct vpfe_ipipe_nf *nf_param = (struct vpfe_ipipe_nf *)param;
230 struct vpfe_ipipe_nf *nf = &ipipe->config.nf1;
231 struct device *dev;
232
233 if (id == IPIPE_D2F_2ND)
234 nf = &ipipe->config.nf2;
235
236 if (!nf_param) {
237 memset((void *)nf, 0, sizeof(struct vpfe_ipipe_nf));
238 goto success;
239 }
240
241 dev = ipipe->subdev.v4l2_dev->dev;
242 memcpy(nf, nf_param, sizeof(struct vpfe_ipipe_nf));
243 if (ipipe_validate_nf_params(nf) < 0) {
244 dev_err(dev, "Invalid nf params\n");
245 return -EINVAL;
246 }
247
248success:
249 ipipe_set_d2f_regs(ipipe->base_addr, id, nf);
250
251 return 0;
252}
253
254static int ipipe_set_nf1_params(struct vpfe_ipipe_device *ipipe, void *param)
255{
256 return ipipe_set_nf_params(ipipe, IPIPE_D2F_1ST, param);
257}
258
259static int ipipe_set_nf2_params(struct vpfe_ipipe_device *ipipe, void *param)
260{
261 return ipipe_set_nf_params(ipipe, IPIPE_D2F_2ND, param);
262}
263
264static int ipipe_get_nf_params(struct vpfe_ipipe_device *ipipe,
265 unsigned int id, void *param)
266{
267 struct vpfe_ipipe_nf *nf_param = (struct vpfe_ipipe_nf *)param;
268 struct vpfe_ipipe_nf *nf = &ipipe->config.nf1;
269
270 if (id == IPIPE_D2F_2ND)
271 nf = &ipipe->config.nf2;
272
273 memcpy(nf_param, nf, sizeof(struct vpfe_ipipe_nf));
274
275 return 0;
276}
277
278static int ipipe_get_nf1_params(struct vpfe_ipipe_device *ipipe, void *param)
279{
280 return ipipe_get_nf_params(ipipe, IPIPE_D2F_1ST, param);
281}
282
283static int ipipe_get_nf2_params(struct vpfe_ipipe_device *ipipe, void *param)
284{
285 return ipipe_get_nf_params(ipipe, IPIPE_D2F_2ND, param);
286}
287
288static int ipipe_validate_gic_params(struct vpfe_ipipe_gic *gic)
289{
290 if (gic->en > 1 || gic->gain > GIC_GAIN_MASK ||
291 gic->thr > GIC_THR_MASK || gic->slope > GIC_SLOPE_MASK ||
292 gic->apply_lsc_gain > 1 ||
293 gic->nf2_thr_gain.integer > GIC_NFGAN_INT_MASK ||
294 gic->nf2_thr_gain.decimal > GIC_NFGAN_DECI_MASK)
295 return -EINVAL;
296
297 return 0;
298}
299
300static int ipipe_set_gic_params(struct vpfe_ipipe_device *ipipe, void *param)
301{
302 struct vpfe_ipipe_gic *gic_param = (struct vpfe_ipipe_gic *)param;
303 struct device *dev = ipipe->subdev.v4l2_dev->dev;
304 struct vpfe_ipipe_gic *gic = &ipipe->config.gic;
305
306 if (!gic_param) {
307 memset((void *)gic, 0, sizeof(struct vpfe_ipipe_gic));
308 goto success;
309 }
310
311 memcpy(gic, gic_param, sizeof(struct vpfe_ipipe_gic));
312 if (ipipe_validate_gic_params(gic) < 0) {
313 dev_err(dev, "Invalid gic params\n");
314 return -EINVAL;
315 }
316
317success:
318 ipipe_set_gic_regs(ipipe->base_addr, gic);
319
320 return 0;
321}
322
323static int ipipe_get_gic_params(struct vpfe_ipipe_device *ipipe, void *param)
324{
325 struct vpfe_ipipe_gic *gic_param = (struct vpfe_ipipe_gic *)param;
326 struct vpfe_ipipe_gic *gic = &ipipe->config.gic;
327
328 memcpy(gic_param, gic, sizeof(struct vpfe_ipipe_gic));
329
330 return 0;
331}
332
333static int ipipe_validate_wb_params(struct vpfe_ipipe_wb *wbal)
334{
335 if (wbal->ofst_r > WB_OFFSET_MASK ||
336 wbal->ofst_gr > WB_OFFSET_MASK ||
337 wbal->ofst_gb > WB_OFFSET_MASK ||
338 wbal->ofst_b > WB_OFFSET_MASK ||
339 wbal->gain_r.integer > WB_GAIN_INT_MASK ||
340 wbal->gain_r.decimal > WB_GAIN_DECI_MASK ||
341 wbal->gain_gr.integer > WB_GAIN_INT_MASK ||
342 wbal->gain_gr.decimal > WB_GAIN_DECI_MASK ||
343 wbal->gain_gb.integer > WB_GAIN_INT_MASK ||
344 wbal->gain_gb.decimal > WB_GAIN_DECI_MASK ||
345 wbal->gain_b.integer > WB_GAIN_INT_MASK ||
346 wbal->gain_b.decimal > WB_GAIN_DECI_MASK)
347 return -EINVAL;
348
349 return 0;
350}
351
352static int ipipe_set_wb_params(struct vpfe_ipipe_device *ipipe, void *param)
353{
354 struct vpfe_ipipe_wb *wb_param = (struct vpfe_ipipe_wb *)param;
355 struct vpfe_ipipe_wb *wbal = &ipipe->config.wbal;
356
357 if (!wb_param) {
358 const struct vpfe_ipipe_wb wb_defaults = {
359 .gain_r = {2, 0x0},
360 .gain_gr = {2, 0x0},
361 .gain_gb = {2, 0x0},
362 .gain_b = {2, 0x0}
363 };
364 memcpy(wbal, &wb_defaults, sizeof(struct vpfe_ipipe_wb));
365 goto success;
366 }
367
368 memcpy(wbal, wb_param, sizeof(struct vpfe_ipipe_wb));
369 if (ipipe_validate_wb_params(wbal) < 0)
370 return -EINVAL;
371
372success:
373 ipipe_set_wb_regs(ipipe->base_addr, wbal);
374
375 return 0;
376}
377
378static int ipipe_get_wb_params(struct vpfe_ipipe_device *ipipe, void *param)
379{
380 struct vpfe_ipipe_wb *wb_param = (struct vpfe_ipipe_wb *)param;
381 struct vpfe_ipipe_wb *wbal = &ipipe->config.wbal;
382
383 memcpy(wb_param, wbal, sizeof(struct vpfe_ipipe_wb));
384 return 0;
385}
386
387static int ipipe_validate_cfa_params(struct vpfe_ipipe_cfa *cfa)
388{
389 if (cfa->hpf_thr_2dir > CFA_HPF_THR_2DIR_MASK ||
390 cfa->hpf_slp_2dir > CFA_HPF_SLOPE_2DIR_MASK ||
391 cfa->hp_mix_thr_2dir > CFA_HPF_MIX_THR_2DIR_MASK ||
392 cfa->hp_mix_slope_2dir > CFA_HPF_MIX_SLP_2DIR_MASK ||
393 cfa->dir_thr_2dir > CFA_DIR_THR_2DIR_MASK ||
394 cfa->dir_slope_2dir > CFA_DIR_SLP_2DIR_MASK ||
395 cfa->nd_wt_2dir > CFA_ND_WT_2DIR_MASK ||
396 cfa->hue_fract_daa > CFA_DAA_HUE_FRA_MASK ||
397 cfa->edge_thr_daa > CFA_DAA_EDG_THR_MASK ||
398 cfa->thr_min_daa > CFA_DAA_THR_MIN_MASK ||
399 cfa->thr_slope_daa > CFA_DAA_THR_SLP_MASK ||
400 cfa->slope_min_daa > CFA_DAA_SLP_MIN_MASK ||
401 cfa->slope_slope_daa > CFA_DAA_SLP_SLP_MASK ||
402 cfa->lp_wt_daa > CFA_DAA_LP_WT_MASK)
403 return -EINVAL;
404
405 return 0;
406}
407
408static int ipipe_set_cfa_params(struct vpfe_ipipe_device *ipipe, void *param)
409{
410 struct vpfe_ipipe_cfa *cfa_param = (struct vpfe_ipipe_cfa *)param;
411 struct vpfe_ipipe_cfa *cfa = &ipipe->config.cfa;
412
413 if (!cfa_param) {
414 memset(cfa, 0, sizeof(struct vpfe_ipipe_cfa));
415 cfa->alg = VPFE_IPIPE_CFA_ALG_2DIRAC;
416 goto success;
417 }
418
419 memcpy(cfa, cfa_param, sizeof(struct vpfe_ipipe_cfa));
420 if (ipipe_validate_cfa_params(cfa) < 0)
421 return -EINVAL;
422
423success:
424 ipipe_set_cfa_regs(ipipe->base_addr, cfa);
425
426 return 0;
427}
428
429static int ipipe_get_cfa_params(struct vpfe_ipipe_device *ipipe, void *param)
430{
431 struct vpfe_ipipe_cfa *cfa_param = (struct vpfe_ipipe_cfa *)param;
432 struct vpfe_ipipe_cfa *cfa = &ipipe->config.cfa;
433
434 memcpy(cfa_param, cfa, sizeof(struct vpfe_ipipe_cfa));
435 return 0;
436}
437
438static int
439ipipe_validate_rgb2rgb_params(struct vpfe_ipipe_rgb2rgb *rgb2rgb,
440 unsigned int id)
441{
442 u32 gain_int_upper = RGB2RGB_1_GAIN_INT_MASK;
443 u32 offset_upper = RGB2RGB_1_OFST_MASK;
444
445 if (id == IPIPE_RGB2RGB_2) {
446 offset_upper = RGB2RGB_2_OFST_MASK;
447 gain_int_upper = RGB2RGB_2_GAIN_INT_MASK;
448 }
449
450 if (rgb2rgb->coef_rr.decimal > RGB2RGB_GAIN_DECI_MASK ||
451 rgb2rgb->coef_rr.integer > gain_int_upper)
452 return -EINVAL;
453
454 if (rgb2rgb->coef_gr.decimal > RGB2RGB_GAIN_DECI_MASK ||
455 rgb2rgb->coef_gr.integer > gain_int_upper)
456 return -EINVAL;
457
458 if (rgb2rgb->coef_br.decimal > RGB2RGB_GAIN_DECI_MASK ||
459 rgb2rgb->coef_br.integer > gain_int_upper)
460 return -EINVAL;
461
462 if (rgb2rgb->coef_rg.decimal > RGB2RGB_GAIN_DECI_MASK ||
463 rgb2rgb->coef_rg.integer > gain_int_upper)
464 return -EINVAL;
465
466 if (rgb2rgb->coef_gg.decimal > RGB2RGB_GAIN_DECI_MASK ||
467 rgb2rgb->coef_gg.integer > gain_int_upper)
468 return -EINVAL;
469
470 if (rgb2rgb->coef_bg.decimal > RGB2RGB_GAIN_DECI_MASK ||
471 rgb2rgb->coef_bg.integer > gain_int_upper)
472 return -EINVAL;
473
474 if (rgb2rgb->coef_rb.decimal > RGB2RGB_GAIN_DECI_MASK ||
475 rgb2rgb->coef_rb.integer > gain_int_upper)
476 return -EINVAL;
477
478 if (rgb2rgb->coef_gb.decimal > RGB2RGB_GAIN_DECI_MASK ||
479 rgb2rgb->coef_gb.integer > gain_int_upper)
480 return -EINVAL;
481
482 if (rgb2rgb->coef_bb.decimal > RGB2RGB_GAIN_DECI_MASK ||
483 rgb2rgb->coef_bb.integer > gain_int_upper)
484 return -EINVAL;
485
486 if (rgb2rgb->out_ofst_r > offset_upper ||
487 rgb2rgb->out_ofst_g > offset_upper ||
488 rgb2rgb->out_ofst_b > offset_upper)
489 return -EINVAL;
490
491 return 0;
492}
493
494static int ipipe_set_rgb2rgb_params(struct vpfe_ipipe_device *ipipe,
495 unsigned int id, void *param)
496{
497 struct vpfe_ipipe_rgb2rgb *rgb2rgb = &ipipe->config.rgb2rgb1;
498 struct device *dev = ipipe->subdev.v4l2_dev->dev;
499 struct vpfe_ipipe_rgb2rgb *rgb2rgb_param;
500
501 rgb2rgb_param = (struct vpfe_ipipe_rgb2rgb *)param;
502
503 if (id == IPIPE_RGB2RGB_2)
504 rgb2rgb = &ipipe->config.rgb2rgb2;
505
506 if (!rgb2rgb_param) {
507 const struct vpfe_ipipe_rgb2rgb rgb2rgb_defaults = {
508 .coef_rr = {1, 0}, /* 256 */
509 .coef_gr = {0, 0},
510 .coef_br = {0, 0},
511 .coef_rg = {0, 0},
512 .coef_gg = {1, 0}, /* 256 */
513 .coef_bg = {0, 0},
514 .coef_rb = {0, 0},
515 .coef_gb = {0, 0},
516 .coef_bb = {1, 0}, /* 256 */
517 };
518 /* Copy defaults for rgb2rgb conversion */
519 memcpy(rgb2rgb, &rgb2rgb_defaults,
520 sizeof(struct vpfe_ipipe_rgb2rgb));
521 goto success;
522 }
523
524 memcpy(rgb2rgb, rgb2rgb_param, sizeof(struct vpfe_ipipe_rgb2rgb));
525 if (ipipe_validate_rgb2rgb_params(rgb2rgb, id) < 0) {
526 dev_err(dev, "Invalid rgb2rgb params\n");
527 return -EINVAL;
528 }
529
530success:
531 ipipe_set_rgb2rgb_regs(ipipe->base_addr, id, rgb2rgb);
532
533 return 0;
534}
535
536static int
537ipipe_set_rgb2rgb_1_params(struct vpfe_ipipe_device *ipipe, void *param)
538{
539 return ipipe_set_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_1, param);
540}
541
542static int
543ipipe_set_rgb2rgb_2_params(struct vpfe_ipipe_device *ipipe, void *param)
544{
545 return ipipe_set_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_2, param);
546}
547
548static int ipipe_get_rgb2rgb_params(struct vpfe_ipipe_device *ipipe,
549 unsigned int id, void *param)
550{
551 struct vpfe_ipipe_rgb2rgb *rgb2rgb = &ipipe->config.rgb2rgb1;
552 struct vpfe_ipipe_rgb2rgb *rgb2rgb_param;
553
554 rgb2rgb_param = (struct vpfe_ipipe_rgb2rgb *)param;
555
556 if (id == IPIPE_RGB2RGB_2)
557 rgb2rgb = &ipipe->config.rgb2rgb2;
558
559 memcpy(rgb2rgb_param, rgb2rgb, sizeof(struct vpfe_ipipe_rgb2rgb));
560
561 return 0;
562}
563
564static int
565ipipe_get_rgb2rgb_1_params(struct vpfe_ipipe_device *ipipe, void *param)
566{
567 return ipipe_get_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_1, param);
568}
569
570static int
571ipipe_get_rgb2rgb_2_params(struct vpfe_ipipe_device *ipipe, void *param)
572{
573 return ipipe_get_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_2, param);
574}
575
576static int
577ipipe_validate_gamma_entry(struct vpfe_ipipe_gamma_entry *table, int size)
578{
579 int i;
580
581 if (!table)
582 return -EINVAL;
583
584 for (i = 0; i < size; i++)
585 if (table[i].slope > GAMMA_MASK ||
586 table[i].offset > GAMMA_MASK)
587 return -EINVAL;
588
589 return 0;
590}
591
592static int
593ipipe_validate_gamma_params(struct vpfe_ipipe_gamma *gamma, struct device *dev)
594{
595 int table_size;
596 int err;
597
598 if (gamma->bypass_r > 1 ||
599 gamma->bypass_b > 1 ||
600 gamma->bypass_g > 1)
601 return -EINVAL;
602
603 if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
604 return 0;
605
606 table_size = gamma->tbl_size;
607 if (!gamma->bypass_r) {
608 err = ipipe_validate_gamma_entry(gamma->table_r, table_size);
609 if (err) {
610 dev_err(dev, "GAMMA R - table entry invalid\n");
611 return err;
612 }
613 }
614
615 if (!gamma->bypass_b) {
616 err = ipipe_validate_gamma_entry(gamma->table_b, table_size);
617 if (err) {
618 dev_err(dev, "GAMMA B - table entry invalid\n");
619 return err;
620 }
621 }
622
623 if (!gamma->bypass_g) {
624 err = ipipe_validate_gamma_entry(gamma->table_g, table_size);
625 if (err) {
626 dev_err(dev, "GAMMA G - table entry invalid\n");
627 return err;
628 }
629 }
630
631 return 0;
632}
633
634static int
635ipipe_set_gamma_params(struct vpfe_ipipe_device *ipipe, void *param)
636{
637 struct vpfe_ipipe_gamma *gamma_param = (struct vpfe_ipipe_gamma *)param;
638 struct vpfe_ipipe_gamma *gamma = &ipipe->config.gamma;
639 struct device *dev = ipipe->subdev.v4l2_dev->dev;
640 int table_size;
641
642 if (!gamma_param) {
643 memset(gamma, 0, sizeof(struct vpfe_ipipe_gamma));
644 gamma->tbl_sel = VPFE_IPIPE_GAMMA_TBL_ROM;
645 goto success;
646 }
647
648 gamma->bypass_r = gamma_param->bypass_r;
649 gamma->bypass_b = gamma_param->bypass_b;
650 gamma->bypass_g = gamma_param->bypass_g;
651 gamma->tbl_sel = gamma_param->tbl_sel;
652 gamma->tbl_size = gamma_param->tbl_size;
653
654 if (ipipe_validate_gamma_params(gamma, dev) < 0)
655 return -EINVAL;
656
657 if (gamma_param->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
658 goto success;
659
660 table_size = gamma->tbl_size;
661 if (!gamma_param->bypass_r)
662 memcpy(&gamma->table_r, &gamma_param->table_r,
663 (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
664
665 if (!gamma_param->bypass_b)
666 memcpy(&gamma->table_b, &gamma_param->table_b,
667 (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
668
669 if (!gamma_param->bypass_g)
670 memcpy(&gamma->table_g, &gamma_param->table_g,
671 (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
672
673success:
674 ipipe_set_gamma_regs(ipipe->base_addr, ipipe->isp5_base_addr, gamma);
675
676 return 0;
677}
678
679static int ipipe_get_gamma_params(struct vpfe_ipipe_device *ipipe, void *param)
680{
681 struct vpfe_ipipe_gamma *gamma_param = (struct vpfe_ipipe_gamma *)param;
682 struct vpfe_ipipe_gamma *gamma = &ipipe->config.gamma;
683 struct device *dev = ipipe->subdev.v4l2_dev->dev;
684 int table_size;
685
686 gamma_param->bypass_r = gamma->bypass_r;
687 gamma_param->bypass_g = gamma->bypass_g;
688 gamma_param->bypass_b = gamma->bypass_b;
689 gamma_param->tbl_sel = gamma->tbl_sel;
690 gamma_param->tbl_size = gamma->tbl_size;
691
692 if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
693 return 0;
694
695 table_size = gamma->tbl_size;
696
697 if (!gamma->bypass_r && !gamma_param->table_r) {
698 dev_err(dev,
699 "ipipe_get_gamma_params: table ptr empty for R\n");
700 return -EINVAL;
701 }
702 memcpy(gamma_param->table_r, gamma->table_r,
703 (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
704
705 if (!gamma->bypass_g && !gamma_param->table_g) {
706 dev_err(dev, "ipipe_get_gamma_params: table ptr empty for G\n");
707 return -EINVAL;
708 }
709 memcpy(gamma_param->table_g, gamma->table_g,
710 (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
711
712 if (!gamma->bypass_b && !gamma_param->table_b) {
713 dev_err(dev, "ipipe_get_gamma_params: table ptr empty for B\n");
714 return -EINVAL;
715 }
716 memcpy(gamma_param->table_b, gamma->table_b,
717 (table_size * sizeof(struct vpfe_ipipe_gamma_entry)));
718
719 return 0;
720}
721
722static int ipipe_validate_3d_lut_params(struct vpfe_ipipe_3d_lut *lut)
723{
724 int i;
725
726 if (!lut->en)
727 return 0;
728
729 for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++)
730 if (lut->table[i].r > D3_LUT_ENTRY_MASK ||
731 lut->table[i].g > D3_LUT_ENTRY_MASK ||
732 lut->table[i].b > D3_LUT_ENTRY_MASK)
733 return -EINVAL;
734
735 return 0;
736}
737
738static int ipipe_get_3d_lut_params(struct vpfe_ipipe_device *ipipe, void *param)
739{
740 struct vpfe_ipipe_3d_lut *lut_param = (struct vpfe_ipipe_3d_lut *)param;
741 struct vpfe_ipipe_3d_lut *lut = &ipipe->config.lut;
742 struct device *dev = ipipe->subdev.v4l2_dev->dev;
743
744 lut_param->en = lut->en;
745 if (!lut_param->table) {
746 dev_err(dev, "ipipe_get_3d_lut_params: Invalid table ptr\n");
747 return -EINVAL;
748 }
749
750 memcpy(lut_param->table, &lut->table,
751 (VPFE_IPIPE_MAX_SIZE_3D_LUT *
752 sizeof(struct vpfe_ipipe_3d_lut_entry)));
753
754 return 0;
755}
756
757static int
758ipipe_set_3d_lut_params(struct vpfe_ipipe_device *ipipe, void *param)
759{
760 struct vpfe_ipipe_3d_lut *lut_param = (struct vpfe_ipipe_3d_lut *)param;
761 struct vpfe_ipipe_3d_lut *lut = &ipipe->config.lut;
762 struct device *dev = ipipe->subdev.v4l2_dev->dev;
763
764 if (!lut_param) {
765 memset(lut, 0, sizeof(struct vpfe_ipipe_3d_lut));
766 goto success;
767 }
768
769 memcpy(lut, lut_param, sizeof(struct vpfe_ipipe_3d_lut));
770 if (ipipe_validate_3d_lut_params(lut) < 0) {
771 dev_err(dev, "Invalid 3D-LUT Params\n");
772 return -EINVAL;
773 }
774
775success:
776 ipipe_set_3d_lut_regs(ipipe->base_addr, ipipe->isp5_base_addr, lut);
777
778 return 0;
779}
780
781static int ipipe_validate_rgb2yuv_params(struct vpfe_ipipe_rgb2yuv *rgb2yuv)
782{
783 if (rgb2yuv->coef_ry.decimal > RGB2YCBCR_COEF_DECI_MASK ||
784 rgb2yuv->coef_ry.integer > RGB2YCBCR_COEF_INT_MASK)
785 return -EINVAL;
786
787 if (rgb2yuv->coef_gy.decimal > RGB2YCBCR_COEF_DECI_MASK ||
788 rgb2yuv->coef_gy.integer > RGB2YCBCR_COEF_INT_MASK)
789 return -EINVAL;
790
791 if (rgb2yuv->coef_by.decimal > RGB2YCBCR_COEF_DECI_MASK ||
792 rgb2yuv->coef_by.integer > RGB2YCBCR_COEF_INT_MASK)
793 return -EINVAL;
794
795 if (rgb2yuv->coef_rcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
796 rgb2yuv->coef_rcb.integer > RGB2YCBCR_COEF_INT_MASK)
797 return -EINVAL;
798
799 if (rgb2yuv->coef_gcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
800 rgb2yuv->coef_gcb.integer > RGB2YCBCR_COEF_INT_MASK)
801 return -EINVAL;
802
803 if (rgb2yuv->coef_bcb.decimal > RGB2YCBCR_COEF_DECI_MASK ||
804 rgb2yuv->coef_bcb.integer > RGB2YCBCR_COEF_INT_MASK)
805 return -EINVAL;
806
807 if (rgb2yuv->coef_rcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
808 rgb2yuv->coef_rcr.integer > RGB2YCBCR_COEF_INT_MASK)
809 return -EINVAL;
810
811 if (rgb2yuv->coef_gcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
812 rgb2yuv->coef_gcr.integer > RGB2YCBCR_COEF_INT_MASK)
813 return -EINVAL;
814
815 if (rgb2yuv->coef_bcr.decimal > RGB2YCBCR_COEF_DECI_MASK ||
816 rgb2yuv->coef_bcr.integer > RGB2YCBCR_COEF_INT_MASK)
817 return -EINVAL;
818
819 if (rgb2yuv->out_ofst_y > RGB2YCBCR_OFST_MASK ||
820 rgb2yuv->out_ofst_cb > RGB2YCBCR_OFST_MASK ||
821 rgb2yuv->out_ofst_cr > RGB2YCBCR_OFST_MASK)
822 return -EINVAL;
823
824 return 0;
825}
826
827static int
828ipipe_set_rgb2yuv_params(struct vpfe_ipipe_device *ipipe, void *param)
829{
830 struct vpfe_ipipe_rgb2yuv *rgb2yuv = &ipipe->config.rgb2yuv;
831 struct device *dev = ipipe->subdev.v4l2_dev->dev;
832 struct vpfe_ipipe_rgb2yuv *rgb2yuv_param;
833
834 rgb2yuv_param = (struct vpfe_ipipe_rgb2yuv *)param;
835 if (!rgb2yuv_param) {
836 /* Defaults for rgb2yuv conversion */
837 const struct vpfe_ipipe_rgb2yuv rgb2yuv_defaults = {
838 .coef_ry = {0, 0x4d},
839 .coef_gy = {0, 0x96},
840 .coef_by = {0, 0x1d},
841 .coef_rcb = {0xf, 0xd5},
842 .coef_gcb = {0xf, 0xab},
843 .coef_bcb = {0, 0x80},
844 .coef_rcr = {0, 0x80},
845 .coef_gcr = {0xf, 0x95},
846 .coef_bcr = {0xf, 0xeb},
847 .out_ofst_cb = 0x80,
848 .out_ofst_cr = 0x80,
849 };
850 /* Copy defaults for rgb2yuv conversion */
851 memcpy(rgb2yuv, &rgb2yuv_defaults,
852 sizeof(struct vpfe_ipipe_rgb2yuv));
853 goto success;
854 }
855
856 memcpy(rgb2yuv, rgb2yuv_param, sizeof(struct vpfe_ipipe_rgb2yuv));
857 if (ipipe_validate_rgb2yuv_params(rgb2yuv) < 0) {
858 dev_err(dev, "Invalid rgb2yuv params\n");
859 return -EINVAL;
860 }
861
862success:
863 ipipe_set_rgb2ycbcr_regs(ipipe->base_addr, rgb2yuv);
864
865 return 0;
866}
867
868static int
869ipipe_get_rgb2yuv_params(struct vpfe_ipipe_device *ipipe, void *param)
870{
871 struct vpfe_ipipe_rgb2yuv *rgb2yuv = &ipipe->config.rgb2yuv;
872 struct vpfe_ipipe_rgb2yuv *rgb2yuv_param;
873
874 rgb2yuv_param = (struct vpfe_ipipe_rgb2yuv *)param;
875 memcpy(rgb2yuv_param, rgb2yuv, sizeof(struct vpfe_ipipe_rgb2yuv));
876 return 0;
877}
878
879static int ipipe_validate_gbce_params(struct vpfe_ipipe_gbce *gbce)
880{
881 u32 max = GBCE_Y_VAL_MASK;
882 int i;
883
884 if (!gbce->en)
885 return 0;
886
887 if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL)
888 max = GBCE_GAIN_VAL_MASK;
889
890 for (i = 0; i < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; i++)
891 if (gbce->table[i] > max)
892 return -EINVAL;
893
894 return 0;
895}
896
897static int ipipe_set_gbce_params(struct vpfe_ipipe_device *ipipe, void *param)
898{
899 struct vpfe_ipipe_gbce *gbce_param = (struct vpfe_ipipe_gbce *)param;
900 struct vpfe_ipipe_gbce *gbce = &ipipe->config.gbce;
901 struct device *dev = ipipe->subdev.v4l2_dev->dev;
902
903 if (!gbce_param) {
904 memset(gbce, 0 , sizeof(struct vpfe_ipipe_gbce));
905 } else {
906 memcpy(gbce, gbce_param, sizeof(struct vpfe_ipipe_gbce));
907 if (ipipe_validate_gbce_params(gbce) < 0) {
908 dev_err(dev, "Invalid gbce params\n");
909 return -EINVAL;
910 }
911 }
912
913 ipipe_set_gbce_regs(ipipe->base_addr, ipipe->isp5_base_addr, gbce);
914
915 return 0;
916}
917
918static int ipipe_get_gbce_params(struct vpfe_ipipe_device *ipipe, void *param)
919{
920 struct vpfe_ipipe_gbce *gbce_param = (struct vpfe_ipipe_gbce *)param;
921 struct vpfe_ipipe_gbce *gbce = &ipipe->config.gbce;
922 struct device *dev = ipipe->subdev.v4l2_dev->dev;
923
924 gbce_param->en = gbce->en;
925 gbce_param->type = gbce->type;
926 if (!gbce_param->table) {
927 dev_err(dev, "ipipe_get_gbce_params: Invalid table ptr\n");
928 return -EINVAL;
929 }
930
931 memcpy(gbce_param->table, gbce->table,
932 (VPFE_IPIPE_MAX_SIZE_GBCE_LUT * sizeof(unsigned short)));
933
934 return 0;
935}
936
937static int
938ipipe_validate_yuv422_conv_params(struct vpfe_ipipe_yuv422_conv *yuv422_conv)
939{
940 if (yuv422_conv->en_chrom_lpf > 1)
941 return -EINVAL;
942
943 return 0;
944}
945
946static int
947ipipe_set_yuv422_conv_params(struct vpfe_ipipe_device *ipipe, void *param)
948{
949 struct vpfe_ipipe_yuv422_conv *yuv422_conv = &ipipe->config.yuv422_conv;
950 struct vpfe_ipipe_yuv422_conv *yuv422_conv_param;
951 struct device *dev = ipipe->subdev.v4l2_dev->dev;
952
953 yuv422_conv_param = (struct vpfe_ipipe_yuv422_conv *)param;
954 if (!yuv422_conv_param) {
955 memset(yuv422_conv, 0, sizeof(struct vpfe_ipipe_yuv422_conv));
956 yuv422_conv->chrom_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE;
957 } else {
958 memcpy(yuv422_conv, yuv422_conv_param,
959 sizeof(struct vpfe_ipipe_yuv422_conv));
960 if (ipipe_validate_yuv422_conv_params(yuv422_conv) < 0) {
961 dev_err(dev, "Invalid yuv422 params\n");
962 return -EINVAL;
963 }
964 }
965
966 ipipe_set_yuv422_conv_regs(ipipe->base_addr, yuv422_conv);
967
968 return 0;
969}
970
971static int
972ipipe_get_yuv422_conv_params(struct vpfe_ipipe_device *ipipe, void *param)
973{
974 struct vpfe_ipipe_yuv422_conv *yuv422_conv = &ipipe->config.yuv422_conv;
975 struct vpfe_ipipe_yuv422_conv *yuv422_conv_param;
976
977 yuv422_conv_param = (struct vpfe_ipipe_yuv422_conv *)param;
978 memcpy(yuv422_conv_param, yuv422_conv,
979 sizeof(struct vpfe_ipipe_yuv422_conv));
980
981 return 0;
982}
983
984static int ipipe_validate_yee_params(struct vpfe_ipipe_yee *yee)
985{
986 int i;
987
988 if (yee->en > 1 ||
989 yee->en_halo_red > 1 ||
990 yee->hpf_shft > YEE_HPF_SHIFT_MASK)
991 return -EINVAL;
992
993 if (yee->hpf_coef_00 > YEE_COEF_MASK ||
994 yee->hpf_coef_01 > YEE_COEF_MASK ||
995 yee->hpf_coef_02 > YEE_COEF_MASK ||
996 yee->hpf_coef_10 > YEE_COEF_MASK ||
997 yee->hpf_coef_11 > YEE_COEF_MASK ||
998 yee->hpf_coef_12 > YEE_COEF_MASK ||
999 yee->hpf_coef_20 > YEE_COEF_MASK ||
1000 yee->hpf_coef_21 > YEE_COEF_MASK ||
1001 yee->hpf_coef_22 > YEE_COEF_MASK)
1002 return -EINVAL;
1003
1004 if (yee->yee_thr > YEE_THR_MASK ||
1005 yee->es_gain > YEE_ES_GAIN_MASK ||
1006 yee->es_thr1 > YEE_ES_THR1_MASK ||
1007 yee->es_thr2 > YEE_THR_MASK ||
1008 yee->es_gain_grad > YEE_THR_MASK ||
1009 yee->es_ofst_grad > YEE_THR_MASK)
1010 return -EINVAL;
1011
1012 for (i = 0; i < VPFE_IPIPE_MAX_SIZE_YEE_LUT ; i++)
1013 if (yee->table[i] > YEE_ENTRY_MASK)
1014 return -EINVAL;
1015
1016 return 0;
1017}
1018
1019static int ipipe_set_yee_params(struct vpfe_ipipe_device *ipipe, void *param)
1020{
1021 struct vpfe_ipipe_yee *yee_param = (struct vpfe_ipipe_yee *)param;
1022 struct device *dev = ipipe->subdev.v4l2_dev->dev;
1023 struct vpfe_ipipe_yee *yee = &ipipe->config.yee;
1024
1025 if (!yee_param) {
1026 memset(yee, 0, sizeof(struct vpfe_ipipe_yee));
1027 } else {
1028 memcpy(yee, yee_param, sizeof(struct vpfe_ipipe_yee));
1029 if (ipipe_validate_yee_params(yee) < 0) {
1030 dev_err(dev, "Invalid yee params\n");
1031 return -EINVAL;
1032 }
1033 }
1034
1035 ipipe_set_ee_regs(ipipe->base_addr, ipipe->isp5_base_addr, yee);
1036
1037 return 0;
1038}
1039
1040static int ipipe_get_yee_params(struct vpfe_ipipe_device *ipipe, void *param)
1041{
1042 struct vpfe_ipipe_yee *yee_param = (struct vpfe_ipipe_yee *)param;
1043 struct vpfe_ipipe_yee *yee = &ipipe->config.yee;
1044
1045 yee_param->en = yee->en;
1046 yee_param->en_halo_red = yee->en_halo_red;
1047 yee_param->merge_meth = yee->merge_meth;
1048 yee_param->hpf_shft = yee->hpf_shft;
1049 yee_param->hpf_coef_00 = yee->hpf_coef_00;
1050 yee_param->hpf_coef_01 = yee->hpf_coef_01;
1051 yee_param->hpf_coef_02 = yee->hpf_coef_02;
1052 yee_param->hpf_coef_10 = yee->hpf_coef_10;
1053 yee_param->hpf_coef_11 = yee->hpf_coef_11;
1054 yee_param->hpf_coef_12 = yee->hpf_coef_12;
1055 yee_param->hpf_coef_20 = yee->hpf_coef_20;
1056 yee_param->hpf_coef_21 = yee->hpf_coef_21;
1057 yee_param->hpf_coef_22 = yee->hpf_coef_22;
1058 yee_param->yee_thr = yee->yee_thr;
1059 yee_param->es_gain = yee->es_gain;
1060 yee_param->es_thr1 = yee->es_thr1;
1061 yee_param->es_thr2 = yee->es_thr2;
1062 yee_param->es_gain_grad = yee->es_gain_grad;
1063 yee_param->es_ofst_grad = yee->es_ofst_grad;
1064 memcpy(yee_param->table, &yee->table,
1065 (VPFE_IPIPE_MAX_SIZE_YEE_LUT * sizeof(short)));
1066
1067 return 0;
1068}
1069
1070static int ipipe_validate_car_params(struct vpfe_ipipe_car *car)
1071{
1072 if (car->en > 1 || car->hpf_shft > CAR_HPF_SHIFT_MASK ||
1073 car->gain1.shft > CAR_GAIN1_SHFT_MASK ||
1074 car->gain1.gain_min > CAR_GAIN_MIN_MASK ||
1075 car->gain2.shft > CAR_GAIN2_SHFT_MASK ||
1076 car->gain2.gain_min > CAR_GAIN_MIN_MASK)
1077 return -EINVAL;
1078
1079 return 0;
1080}
1081
1082static int ipipe_set_car_params(struct vpfe_ipipe_device *ipipe, void *param)
1083{
1084 struct vpfe_ipipe_car *car_param = (struct vpfe_ipipe_car *)param;
1085 struct device *dev = ipipe->subdev.v4l2_dev->dev;
1086 struct vpfe_ipipe_car *car = &ipipe->config.car;
1087
1088 if (!car_param) {
1089 memset(car , 0, sizeof(struct vpfe_ipipe_car));
1090 } else {
1091 memcpy(car, car_param, sizeof(struct vpfe_ipipe_car));
1092 if (ipipe_validate_car_params(car) < 0) {
1093 dev_err(dev, "Invalid car params\n");
1094 return -EINVAL;
1095 }
1096 }
1097
1098 ipipe_set_car_regs(ipipe->base_addr, car);
1099
1100 return 0;
1101}
1102
1103static int ipipe_get_car_params(struct vpfe_ipipe_device *ipipe, void *param)
1104{
1105 struct vpfe_ipipe_car *car_param = (struct vpfe_ipipe_car *)param;
1106 struct vpfe_ipipe_car *car = &ipipe->config.car;
1107
1108 memcpy(car_param, car, sizeof(struct vpfe_ipipe_car));
1109 return 0;
1110}
1111
1112static int ipipe_validate_cgs_params(struct vpfe_ipipe_cgs *cgs)
1113{
1114 if (cgs->en > 1 || cgs->h_shft > CAR_SHIFT_MASK)
1115 return -EINVAL;
1116
1117 return 0;
1118}
1119
1120static int ipipe_set_cgs_params(struct vpfe_ipipe_device *ipipe, void *param)
1121{
1122 struct vpfe_ipipe_cgs *cgs_param = (struct vpfe_ipipe_cgs *)param;
1123 struct device *dev = ipipe->subdev.v4l2_dev->dev;
1124 struct vpfe_ipipe_cgs *cgs = &ipipe->config.cgs;
1125
1126 if (!cgs_param) {
1127 memset(cgs, 0, sizeof(struct vpfe_ipipe_cgs));
1128 } else {
1129 memcpy(cgs, cgs_param, sizeof(struct vpfe_ipipe_cgs));
1130 if (ipipe_validate_cgs_params(cgs) < 0) {
1131 dev_err(dev, "Invalid cgs params\n");
1132 return -EINVAL;
1133 }
1134 }
1135
1136 ipipe_set_cgs_regs(ipipe->base_addr, cgs);
1137
1138 return 0;
1139}
1140
1141static int ipipe_get_cgs_params(struct vpfe_ipipe_device *ipipe, void *param)
1142{
1143 struct vpfe_ipipe_cgs *cgs_param = (struct vpfe_ipipe_cgs *)param;
1144 struct vpfe_ipipe_cgs *cgs = &ipipe->config.cgs;
1145
1146 memcpy(cgs_param, cgs, sizeof(struct vpfe_ipipe_cgs));
1147
1148 return 0;
1149}
1150
1151static const struct ipipe_module_if ipipe_modules[VPFE_IPIPE_MAX_MODULES] = {
1152 /* VPFE_IPIPE_INPUT_CONFIG */ {
1153 offsetof(struct ipipe_module_params, input_config),
1154 FIELD_SIZEOF(struct ipipe_module_params, input_config),
1155 offsetof(struct vpfe_ipipe_config, input_config),
1156 ipipe_set_input_config,
1157 ipipe_get_input_config,
1158 }, /* VPFE_IPIPE_LUTDPC */ {
1159 offsetof(struct ipipe_module_params, lutdpc),
1160 FIELD_SIZEOF(struct ipipe_module_params, lutdpc),
1161 offsetof(struct vpfe_ipipe_config, lutdpc),
1162 ipipe_set_lutdpc_params,
1163 ipipe_get_lutdpc_params,
1164 }, /* VPFE_IPIPE_OTFDPC */ {
1165 offsetof(struct ipipe_module_params, otfdpc),
1166 FIELD_SIZEOF(struct ipipe_module_params, otfdpc),
1167 offsetof(struct vpfe_ipipe_config, otfdpc),
1168 ipipe_set_otfdpc_params,
1169 ipipe_get_otfdpc_params,
1170 }, /* VPFE_IPIPE_NF1 */ {
1171 offsetof(struct ipipe_module_params, nf1),
1172 FIELD_SIZEOF(struct ipipe_module_params, nf1),
1173 offsetof(struct vpfe_ipipe_config, nf1),
1174 ipipe_set_nf1_params,
1175 ipipe_get_nf1_params,
1176 }, /* VPFE_IPIPE_NF2 */ {
1177 offsetof(struct ipipe_module_params, nf2),
1178 FIELD_SIZEOF(struct ipipe_module_params, nf2),
1179 offsetof(struct vpfe_ipipe_config, nf2),
1180 ipipe_set_nf2_params,
1181 ipipe_get_nf2_params,
1182 }, /* VPFE_IPIPE_WB */ {
1183 offsetof(struct ipipe_module_params, wbal),
1184 FIELD_SIZEOF(struct ipipe_module_params, wbal),
1185 offsetof(struct vpfe_ipipe_config, wbal),
1186 ipipe_set_wb_params,
1187 ipipe_get_wb_params,
1188 }, /* VPFE_IPIPE_RGB2RGB_1 */ {
1189 offsetof(struct ipipe_module_params, rgb2rgb1),
1190 FIELD_SIZEOF(struct ipipe_module_params, rgb2rgb1),
1191 offsetof(struct vpfe_ipipe_config, rgb2rgb1),
1192 ipipe_set_rgb2rgb_1_params,
1193 ipipe_get_rgb2rgb_1_params,
1194 }, /* VPFE_IPIPE_RGB2RGB_2 */ {
1195 offsetof(struct ipipe_module_params, rgb2rgb2),
1196 FIELD_SIZEOF(struct ipipe_module_params, rgb2rgb2),
1197 offsetof(struct vpfe_ipipe_config, rgb2rgb2),
1198 ipipe_set_rgb2rgb_2_params,
1199 ipipe_get_rgb2rgb_2_params,
1200 }, /* VPFE_IPIPE_GAMMA */ {
1201 offsetof(struct ipipe_module_params, gamma),
1202 FIELD_SIZEOF(struct ipipe_module_params, gamma),
1203 offsetof(struct vpfe_ipipe_config, gamma),
1204 ipipe_set_gamma_params,
1205 ipipe_get_gamma_params,
1206 }, /* VPFE_IPIPE_3D_LUT */ {
1207 offsetof(struct ipipe_module_params, lut),
1208 FIELD_SIZEOF(struct ipipe_module_params, lut),
1209 offsetof(struct vpfe_ipipe_config, lut),
1210 ipipe_set_3d_lut_params,
1211 ipipe_get_3d_lut_params,
1212 }, /* VPFE_IPIPE_RGB2YUV */ {
1213 offsetof(struct ipipe_module_params, rgb2yuv),
1214 FIELD_SIZEOF(struct ipipe_module_params, rgb2yuv),
1215 offsetof(struct vpfe_ipipe_config, rgb2yuv),
1216 ipipe_set_rgb2yuv_params,
1217 ipipe_get_rgb2yuv_params,
1218 }, /* VPFE_IPIPE_YUV422_CONV */ {
1219 offsetof(struct ipipe_module_params, yuv422_conv),
1220 FIELD_SIZEOF(struct ipipe_module_params, yuv422_conv),
1221 offsetof(struct vpfe_ipipe_config, yuv422_conv),
1222 ipipe_set_yuv422_conv_params,
1223 ipipe_get_yuv422_conv_params,
1224 }, /* VPFE_IPIPE_YEE */ {
1225 offsetof(struct ipipe_module_params, yee),
1226 FIELD_SIZEOF(struct ipipe_module_params, yee),
1227 offsetof(struct vpfe_ipipe_config, yee),
1228 ipipe_set_yee_params,
1229 ipipe_get_yee_params,
1230 }, /* VPFE_IPIPE_GIC */ {
1231 offsetof(struct ipipe_module_params, gic),
1232 FIELD_SIZEOF(struct ipipe_module_params, gic),
1233 offsetof(struct vpfe_ipipe_config, gic),
1234 ipipe_set_gic_params,
1235 ipipe_get_gic_params,
1236 }, /* VPFE_IPIPE_CFA */ {
1237 offsetof(struct ipipe_module_params, cfa),
1238 FIELD_SIZEOF(struct ipipe_module_params, cfa),
1239 offsetof(struct vpfe_ipipe_config, cfa),
1240 ipipe_set_cfa_params,
1241 ipipe_get_cfa_params,
1242 }, /* VPFE_IPIPE_CAR */ {
1243 offsetof(struct ipipe_module_params, car),
1244 FIELD_SIZEOF(struct ipipe_module_params, car),
1245 offsetof(struct vpfe_ipipe_config, car),
1246 ipipe_set_car_params,
1247 ipipe_get_car_params,
1248 }, /* VPFE_IPIPE_CGS */ {
1249 offsetof(struct ipipe_module_params, cgs),
1250 FIELD_SIZEOF(struct ipipe_module_params, cgs),
1251 offsetof(struct vpfe_ipipe_config, cgs),
1252 ipipe_set_cgs_params,
1253 ipipe_get_cgs_params,
1254 }, /* VPFE_IPIPE_GBCE */ {
1255 offsetof(struct ipipe_module_params, gbce),
1256 FIELD_SIZEOF(struct ipipe_module_params, gbce),
1257 offsetof(struct vpfe_ipipe_config, gbce),
1258 ipipe_set_gbce_params,
1259 ipipe_get_gbce_params,
1260 },
1261};
1262
1263static int ipipe_s_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg)
1264{
1265 struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
1266 unsigned int i;
1267 int rval = 0;
1268
1269 for (i = 0; i < ARRAY_SIZE(ipipe_modules); i++) {
1270 unsigned int bit = 1 << i;
1271 if (cfg->flag & bit) {
1272 const struct ipipe_module_if *module_if =
1273 &ipipe_modules[i];
1274 struct ipipe_module_params *params;
1275 void __user *from = *(void * __user *)
1276 ((void *)cfg + module_if->config_offset);
1277 size_t size;
1278 void *to;
1279
1280 params = kmalloc(sizeof(struct ipipe_module_params),
1281 GFP_KERNEL);
1282 to = (void *)params + module_if->param_offset;
1283 size = module_if->param_size;
1284
1285 if (to && from && size) {
1286 if (copy_from_user(to, from, size)) {
1287 rval = -EFAULT;
1288 break;
1289 }
1290 rval = module_if->set(ipipe, to);
1291 if (rval)
1292 goto error;
1293 } else if (to && !from && size) {
1294 rval = module_if->set(ipipe, NULL);
1295 if (rval)
1296 goto error;
1297 }
1298 kfree(params);
1299 }
1300 }
1301error:
1302 return rval;
1303}
1304
1305static int ipipe_g_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg)
1306{
1307 struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
1308 unsigned int i;
1309 int rval = 0;
1310
1311 for (i = 1; i < ARRAY_SIZE(ipipe_modules); i++) {
1312 unsigned int bit = 1 << i;
1313 if (cfg->flag & bit) {
1314 const struct ipipe_module_if *module_if =
1315 &ipipe_modules[i];
1316 struct ipipe_module_params *params;
1317 void __user *to = *(void * __user *)
1318 ((void *)cfg + module_if->config_offset);
1319 size_t size;
1320 void *from;
1321
1322 params = kmalloc(sizeof(struct ipipe_module_params),
1323 GFP_KERNEL);
1324 from = (void *)params + module_if->param_offset;
1325 size = module_if->param_size;
1326
1327 if (to && from && size) {
1328 rval = module_if->get(ipipe, from);
1329 if (rval)
1330 goto error;
1331 if (copy_to_user(to, from, size)) {
1332 rval = -EFAULT;
1333 break;
1334 }
1335 }
1336 kfree(params);
1337 }
1338 }
1339error:
1340 return rval;
1341}
1342
1343/*
1344 * ipipe_ioctl() - Handle ipipe module private ioctl's
1345 * @sd: pointer to v4l2 subdev structure
1346 * @cmd: configuration command
1347 * @arg: configuration argument
1348 */
1349static long ipipe_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1350{
1351 int ret = 0;
1352
1353 switch (cmd) {
1354 case VIDIOC_VPFE_IPIPE_S_CONFIG:
1355 ret = ipipe_s_config(sd, arg);
1356 break;
1357
1358 case VIDIOC_VPFE_IPIPE_G_CONFIG:
1359 ret = ipipe_g_config(sd, arg);
1360 break;
1361
1362 default:
1363 ret = -ENOIOCTLCMD;
1364 }
1365 return ret;
1366}
1367
1368void vpfe_ipipe_enable(struct vpfe_device *vpfe_dev, int en)
1369{
1370 struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
1371 struct vpfe_ipipe_device *ipipe = &vpfe_dev->vpfe_ipipe;
1372 unsigned char val;
1373
1374 if (ipipe->input == IPIPE_INPUT_NONE)
1375 return;
1376
1377 /* ipipe is set to single shot */
1378 if (ipipeif->input == IPIPEIF_INPUT_MEMORY && en) {
1379 /* for single-shot mode, need to wait for h/w to
1380 * reset many register bits
1381 */
1382 do {
1383 val = regr_ip(vpfe_dev->vpfe_ipipe.base_addr,
1384 IPIPE_SRC_EN);
1385 } while (val);
1386 }
1387 regw_ip(vpfe_dev->vpfe_ipipe.base_addr, en, IPIPE_SRC_EN);
1388}
1389
1390/*
1391 * ipipe_set_stream() - Enable/Disable streaming on the ipipe subdevice
1392 * @sd: pointer to v4l2 subdev structure
1393 * @enable: 1 == Enable, 0 == Disable
1394 */
1395static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
1396{
1397 struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
1398 struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe);
1399
1400 if (enable && ipipe->input != IPIPE_INPUT_NONE &&
1401 ipipe->output != IPIPE_OUTPUT_NONE) {
1402 if (config_ipipe_hw(ipipe) < 0)
1403 return -EINVAL;
1404 }
1405
1406 vpfe_ipipe_enable(vpfe_dev, enable);
1407
1408 return 0;
1409}
1410
1411/*
1412 * __ipipe_get_format() - helper function for getting ipipe format
1413 * @ipipe: pointer to ipipe private structure.
1414 * @pad: pad number.
1415 * @fh: V4L2 subdev file handle.
1416 * @which: wanted subdev format.
1417 *
1418 */
1419static struct v4l2_mbus_framefmt *
1420__ipipe_get_format(struct vpfe_ipipe_device *ipipe,
1421 struct v4l2_subdev_fh *fh, unsigned int pad,
1422 enum v4l2_subdev_format_whence which)
1423{
1424 if (which == V4L2_SUBDEV_FORMAT_TRY)
1425 return v4l2_subdev_get_try_format(fh, pad);
1426
1427 return &ipipe->formats[pad];
1428}
1429
1430/*
1431 * ipipe_try_format() - Handle try format by pad subdev method
1432 * @ipipe: VPFE ipipe device.
1433 * @fh: V4L2 subdev file handle.
1434 * @pad: pad num.
1435 * @fmt: pointer to v4l2 format structure.
1436 * @which : wanted subdev format
1437 */
1438static void
1439ipipe_try_format(struct vpfe_ipipe_device *ipipe,
1440 struct v4l2_subdev_fh *fh, unsigned int pad,
1441 struct v4l2_mbus_framefmt *fmt,
1442 enum v4l2_subdev_format_whence which)
1443{
1444 unsigned int max_out_height;
1445 unsigned int max_out_width;
1446 unsigned int i;
1447
1448 max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A;
1449 max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A;
1450
1451 if (pad == IPIPE_PAD_SINK) {
1452 for (i = 0; i < ARRAY_SIZE(ipipe_input_fmts); i++)
1453 if (fmt->code == ipipe_input_fmts[i])
1454 break;
1455
1456 /* If not found, use SBGGR10 as default */
1457 if (i >= ARRAY_SIZE(ipipe_input_fmts))
1458 fmt->code = V4L2_MBUS_FMT_SGRBG12_1X12;
1459 } else if (pad == IPIPE_PAD_SOURCE) {
1460 for (i = 0; i < ARRAY_SIZE(ipipe_output_fmts); i++)
1461 if (fmt->code == ipipe_output_fmts[i])
1462 break;
1463
1464 /* If not found, use UYVY as default */
1465 if (i >= ARRAY_SIZE(ipipe_output_fmts))
1466 fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
1467 }
1468
1469 fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width);
1470 fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height);
1471}
1472
1473/*
1474 * ipipe_set_format() - Handle set format by pads subdev method
1475 * @sd: pointer to v4l2 subdev structure
1476 * @fh: V4L2 subdev file handle
1477 * @fmt: pointer to v4l2 subdev format structure
1478 * return -EINVAL or zero on success
1479 */
1480static int
1481ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1482 struct v4l2_subdev_format *fmt)
1483{
1484 struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
1485 struct v4l2_mbus_framefmt *format;
1486
1487 format = __ipipe_get_format(ipipe, fh, fmt->pad, fmt->which);
1488 if (format == NULL)
1489 return -EINVAL;
1490
1491 ipipe_try_format(ipipe, fh, fmt->pad, &fmt->format, fmt->which);
1492 *format = fmt->format;
1493
1494 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
1495 return 0;
1496
1497 if (fmt->pad == IPIPE_PAD_SINK &&
1498 (ipipe->input == IPIPE_INPUT_CCDC ||
1499 ipipe->input == IPIPE_INPUT_MEMORY))
1500 ipipe->formats[fmt->pad] = fmt->format;
1501 else if (fmt->pad == IPIPE_PAD_SOURCE &&
1502 ipipe->output == IPIPE_OUTPUT_RESIZER)
1503 ipipe->formats[fmt->pad] = fmt->format;
1504 else
1505 return -EINVAL;
1506
1507 return 0;
1508}
1509
1510/*
1511 * ipipe_get_format() - Handle get format by pads subdev method.
1512 * @sd: pointer to v4l2 subdev structure.
1513 * @fh: V4L2 subdev file handle.
1514 * @fmt: pointer to v4l2 subdev format structure.
1515 */
1516static int
1517ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1518 struct v4l2_subdev_format *fmt)
1519{
1520 struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
1521
1522 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
1523 fmt->format = ipipe->formats[fmt->pad];
1524 else
1525 fmt->format = *(v4l2_subdev_get_try_format(fh, fmt->pad));
1526
1527 return 0;
1528}
1529
1530/*
1531 * ipipe_enum_frame_size() - enum frame sizes on pads
1532 * @sd: pointer to v4l2 subdev structure.
1533 * @fh: V4L2 subdev file handle.
1534 * @fse: pointer to v4l2_subdev_frame_size_enum structure.
1535 */
1536static int
1537ipipe_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1538 struct v4l2_subdev_frame_size_enum *fse)
1539{
1540 struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
1541 struct v4l2_mbus_framefmt format;
1542
1543 if (fse->index != 0)
1544 return -EINVAL;
1545
1546 format.code = fse->code;
1547 format.width = 1;
1548 format.height = 1;
1549 ipipe_try_format(ipipe, fh, fse->pad, &format,
1550 V4L2_SUBDEV_FORMAT_TRY);
1551 fse->min_width = format.width;
1552 fse->min_height = format.height;
1553
1554 if (format.code != fse->code)
1555 return -EINVAL;
1556
1557 format.code = fse->code;
1558 format.width = -1;
1559 format.height = -1;
1560 ipipe_try_format(ipipe, fh, fse->pad, &format,
1561 V4L2_SUBDEV_FORMAT_TRY);
1562 fse->max_width = format.width;
1563 fse->max_height = format.height;
1564
1565 return 0;
1566}
1567
1568/*
1569 * ipipe_enum_mbus_code() - enum mbus codes for pads
1570 * @sd: pointer to v4l2 subdev structure.
1571 * @fh: V4L2 subdev file handle
1572 * @code: pointer to v4l2_subdev_mbus_code_enum structure
1573 */
1574static int
1575ipipe_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1576 struct v4l2_subdev_mbus_code_enum *code)
1577{
1578 switch (code->pad) {
1579 case IPIPE_PAD_SINK:
1580 if (code->index >= ARRAY_SIZE(ipipe_input_fmts))
1581 return -EINVAL;
1582 code->code = ipipe_input_fmts[code->index];
1583 break;
1584
1585 case IPIPE_PAD_SOURCE:
1586 if (code->index >= ARRAY_SIZE(ipipe_output_fmts))
1587 return -EINVAL;
1588 code->code = ipipe_output_fmts[code->index];
1589 break;
1590
1591 default:
1592 return -EINVAL;
1593 }
1594
1595 return 0;
1596}
1597
1598/*
1599 * ipipe_s_ctrl() - Handle set control subdev method
1600 * @ctrl: pointer to v4l2 control structure
1601 */
1602static int ipipe_s_ctrl(struct v4l2_ctrl *ctrl)
1603{
1604 struct vpfe_ipipe_device *ipipe =
1605 container_of(ctrl->handler, struct vpfe_ipipe_device, ctrls);
1606 struct ipipe_lum_adj *lum_adj = &ipipe->config.lum_adj;
1607
1608 switch (ctrl->id) {
1609 case V4L2_CID_BRIGHTNESS:
1610 lum_adj->brightness = ctrl->val;
1611 ipipe_set_lum_adj_regs(ipipe->base_addr, lum_adj);
1612 break;
1613
1614 case V4L2_CID_CONTRAST:
1615 lum_adj->contrast = ctrl->val;
1616 ipipe_set_lum_adj_regs(ipipe->base_addr, lum_adj);
1617 break;
1618
1619 default:
1620 return -EINVAL;
1621 }
1622
1623 return 0;
1624}
1625
1626/*
1627 * ipipe_init_formats() - Initialize formats on all pads
1628 * @sd: pointer to v4l2 subdev structure.
1629 * @fh: V4L2 subdev file handle
1630 *
1631 * Initialize all pad formats with default values. If fh is not NULL, try
1632 * formats are initialized on the file handle. Otherwise active formats are
1633 * initialized on the device.
1634 */
1635static int
1636ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1637{
1638 struct v4l2_subdev_format format;
1639
1640 memset(&format, 0, sizeof(format));
1641 format.pad = IPIPE_PAD_SINK;
1642 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1643 format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
1644 format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
1645 format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
1646 ipipe_set_format(sd, fh, &format);
1647
1648 memset(&format, 0, sizeof(format));
1649 format.pad = IPIPE_PAD_SOURCE;
1650 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1651 format.format.code = V4L2_MBUS_FMT_UYVY8_2X8;
1652 format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
1653 format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
1654 ipipe_set_format(sd, fh, &format);
1655
1656 return 0;
1657}
1658
1659/* subdev core operations */
1660static const struct v4l2_subdev_core_ops ipipe_v4l2_core_ops = {
1661 .ioctl = ipipe_ioctl,
1662};
1663
1664static const struct v4l2_ctrl_ops ipipe_ctrl_ops = {
1665 .s_ctrl = ipipe_s_ctrl,
1666};
1667
1668/* subdev file operations */
1669static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = {
1670 .open = ipipe_init_formats,
1671};
1672
1673/* subdev video operations */
1674static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = {
1675 .s_stream = ipipe_set_stream,
1676};
1677
1678/* subdev pad operations */
1679static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = {
1680 .enum_mbus_code = ipipe_enum_mbus_code,
1681 .enum_frame_size = ipipe_enum_frame_size,
1682 .get_fmt = ipipe_get_format,
1683 .set_fmt = ipipe_set_format,
1684};
1685
1686/* v4l2 subdev operation */
1687static const struct v4l2_subdev_ops ipipe_v4l2_ops = {
1688 .core = &ipipe_v4l2_core_ops,
1689 .video = &ipipe_v4l2_video_ops,
1690 .pad = &ipipe_v4l2_pad_ops,
1691};
1692
1693/*
1694 * Media entity operations
1695 */
1696
1697/*
1698 * ipipe_link_setup() - Setup ipipe connections
1699 * @entity: ipipe media entity
1700 * @local: Pad at the local end of the link
1701 * @remote: Pad at the remote end of the link
1702 * @flags: Link flags
1703 *
1704 * return -EINVAL or zero on success
1705 */
1706static int
1707ipipe_link_setup(struct media_entity *entity, const struct media_pad *local,
1708 const struct media_pad *remote, u32 flags)
1709{
1710 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1711 struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
1712 struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe);
1713 u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
1714
1715 switch (local->index | media_entity_type(remote->entity)) {
1716 case IPIPE_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
1717 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1718 ipipe->input = IPIPE_INPUT_NONE;
1719 break;
1720 }
1721 if (ipipe->input != IPIPE_INPUT_NONE)
1722 return -EBUSY;
1723 if (ipipeif_sink == IPIPEIF_INPUT_MEMORY)
1724 ipipe->input = IPIPE_INPUT_MEMORY;
1725 else
1726 ipipe->input = IPIPE_INPUT_CCDC;
1727 break;
1728
1729 case IPIPE_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
1730 /* out to RESIZER */
1731 if (flags & MEDIA_LNK_FL_ENABLED)
1732 ipipe->output = IPIPE_OUTPUT_RESIZER;
1733 else
1734 ipipe->output = IPIPE_OUTPUT_NONE;
1735 break;
1736
1737 default:
1738 return -EINVAL;
1739 }
1740
1741 return 0;
1742}
1743
1744static const struct media_entity_operations ipipe_media_ops = {
1745 .link_setup = ipipe_link_setup,
1746};
1747
1748/*
1749 * vpfe_ipipe_unregister_entities() - ipipe unregister entity
1750 * @vpfe_ipipe: pointer to ipipe subdevice structure.
1751 */
1752void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *vpfe_ipipe)
1753{
1754 /* cleanup entity */
1755 media_entity_cleanup(&vpfe_ipipe->subdev.entity);
1756 /* unregister subdev */
1757 v4l2_device_unregister_subdev(&vpfe_ipipe->subdev);
1758}
1759
1760/*
1761 * vpfe_ipipe_register_entities() - ipipe register entity
1762 * @ipipe: pointer to ipipe subdevice structure.
1763 * @vdev: pointer to v4l2 device structure.
1764 */
1765int
1766vpfe_ipipe_register_entities(struct vpfe_ipipe_device *ipipe,
1767 struct v4l2_device *vdev)
1768{
1769 int ret;
1770
1771 /* Register the subdev */
1772 ret = v4l2_device_register_subdev(vdev, &ipipe->subdev);
1773 if (ret) {
1774 pr_err("Failed to register ipipe as v4l2 subdevice\n");
1775 return ret;
1776 }
1777
1778 return ret;
1779}
1780
1781#define IPIPE_CONTRAST_HIGH 0xff
1782#define IPIPE_BRIGHT_HIGH 0xff
1783
1784/*
1785 * vpfe_ipipe_init() - ipipe module initialization.
1786 * @ipipe: pointer to ipipe subdevice structure.
1787 * @pdev: platform device pointer.
1788 */
1789int
1790vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe, struct platform_device *pdev)
1791{
1792 struct media_pad *pads = &ipipe->pads[0];
1793 struct v4l2_subdev *sd = &ipipe->subdev;
1794 struct media_entity *me = &sd->entity;
1795 static resource_size_t res_len;
1796 struct resource *res;
1797
1798 res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
1799 if (!res)
1800 return -ENOENT;
1801
1802 res_len = resource_size(res);
1803 res = request_mem_region(res->start, res_len, res->name);
1804 if (!res)
1805 return -EBUSY;
1806 ipipe->base_addr = ioremap_nocache(res->start, res_len);
1807 if (!ipipe->base_addr)
1808 return -EBUSY;
1809
1810 res = platform_get_resource(pdev, IORESOURCE_MEM, 6);
1811 if (!res)
1812 return -ENOENT;
1813 ipipe->isp5_base_addr = ioremap_nocache(res->start, res_len);
1814 if (!ipipe->isp5_base_addr)
1815 return -EBUSY;
1816
1817 v4l2_subdev_init(sd, &ipipe_v4l2_ops);
1818 sd->internal_ops = &ipipe_v4l2_internal_ops;
1819 strlcpy(sd->name, "DAVINCI IPIPE", sizeof(sd->name));
1820 sd->grp_id = 1 << 16; /* group ID for davinci subdevs */
1821 v4l2_set_subdevdata(sd, ipipe);
1822 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1823
1824 pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1825 pads[IPIPE_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1826
1827 ipipe->input = IPIPE_INPUT_NONE;
1828 ipipe->output = IPIPE_OUTPUT_NONE;
1829
1830 me->ops = &ipipe_media_ops;
1831 v4l2_ctrl_handler_init(&ipipe->ctrls, 2);
1832 v4l2_ctrl_new_std(&ipipe->ctrls, &ipipe_ctrl_ops,
1833 V4L2_CID_BRIGHTNESS, 0,
1834 IPIPE_BRIGHT_HIGH, 1, 16);
1835 v4l2_ctrl_new_std(&ipipe->ctrls, &ipipe_ctrl_ops,
1836 V4L2_CID_CONTRAST, 0,
1837 IPIPE_CONTRAST_HIGH, 1, 16);
1838
1839
1840 v4l2_ctrl_handler_setup(&ipipe->ctrls);
1841 sd->ctrl_handler = &ipipe->ctrls;
1842
1843 return media_entity_init(me, IPIPE_PADS_NUM, pads, 0);
1844}
1845
1846/*
1847 * vpfe_ipipe_cleanup() - ipipe subdevice cleanup.
1848 * @ipipe: pointer to ipipe subdevice
1849 * @dev: pointer to platform device
1850 */
1851void vpfe_ipipe_cleanup(struct vpfe_ipipe_device *ipipe,
1852 struct platform_device *pdev)
1853{
1854 struct resource *res;
1855
1856 v4l2_ctrl_handler_free(&ipipe->ctrls);
1857
1858 iounmap(ipipe->base_addr);
1859 iounmap(ipipe->isp5_base_addr);
1860 res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
1861 if (res)
1862 release_mem_region(res->start, res->end - res->start + 1);
1863}
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.h b/drivers/staging/media/davinci_vpfe/dm365_ipipe.h
new file mode 100644
index 000000000000..cf4204603eb8
--- /dev/null
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.h
@@ -0,0 +1,179 @@
1/*
2 * Copyright (C) 2012 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Contributors:
18 * Manjunath Hadli <manjunath.hadli@ti.com>
19 * Prabhakar Lad <prabhakar.lad@ti.com>
20 */
21
22#ifndef _DAVINCI_VPFE_DM365_IPIPE_H
23#define _DAVINCI_VPFE_DM365_IPIPE_H
24
25#include <linux/platform_device.h>
26
27#include <media/v4l2-ctrls.h>
28#include <media/v4l2-subdev.h>
29
30#include "davinci_vpfe_user.h"
31#include "vpfe_video.h"
32
33#define CEIL(a, b) (((a) + (b-1)) / (b))
34
35enum ipipe_noise_filter {
36 IPIPE_D2F_1ST = 0,
37 IPIPE_D2F_2ND = 1,
38};
39
40/* Used for driver storage */
41struct ipipe_otfdpc_2_0 {
42 /* 0 - disable, 1 - enable */
43 unsigned char en;
44 /* defect detection method */
45 enum vpfe_ipipe_otfdpc_det_meth det_method;
46 /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
47 * used
48 */
49 enum vpfe_ipipe_otfdpc_alg alg;
50 struct vpfe_ipipe_otfdpc_2_0_cfg otfdpc_2_0;
51};
52
53struct ipipe_otfdpc_3_0 {
54 /* 0 - disable, 1 - enable */
55 unsigned char en;
56 /* defect detection method */
57 enum vpfe_ipipe_otfdpc_det_meth det_method;
58 /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is
59 * used
60 */
61 enum vpfe_ipipe_otfdpc_alg alg;
62 struct vpfe_ipipe_otfdpc_3_0_cfg otfdpc_3_0;
63};
64
65/* Structure for configuring Luminance Adjustment module */
66struct ipipe_lum_adj {
67 /* Brightness adjustments */
68 unsigned char brightness;
69 /* contrast adjustments */
70 unsigned char contrast;
71};
72
73enum ipipe_rgb2rgb {
74 IPIPE_RGB2RGB_1 = 0,
75 IPIPE_RGB2RGB_2 = 1,
76};
77
78struct ipipe_module_params {
79 __u32 flag;
80 struct vpfe_ipipe_input_config input_config;
81 struct vpfe_ipipe_lutdpc lutdpc;
82 struct vpfe_ipipe_otfdpc otfdpc;
83 struct vpfe_ipipe_nf nf1;
84 struct vpfe_ipipe_nf nf2;
85 struct vpfe_ipipe_gic gic;
86 struct vpfe_ipipe_wb wbal;
87 struct vpfe_ipipe_cfa cfa;
88 struct vpfe_ipipe_rgb2rgb rgb2rgb1;
89 struct vpfe_ipipe_rgb2rgb rgb2rgb2;
90 struct vpfe_ipipe_gamma gamma;
91 struct vpfe_ipipe_3d_lut lut;
92 struct vpfe_ipipe_rgb2yuv rgb2yuv;
93 struct vpfe_ipipe_gbce gbce;
94 struct vpfe_ipipe_yuv422_conv yuv422_conv;
95 struct vpfe_ipipe_yee yee;
96 struct vpfe_ipipe_car car;
97 struct vpfe_ipipe_cgs cgs;
98 struct ipipe_lum_adj lum_adj;
99};
100
101#define IPIPE_PAD_SINK 0
102#define IPIPE_PAD_SOURCE 1
103
104#define IPIPE_PADS_NUM 2
105
106#define IPIPE_OUTPUT_NONE 0
107#define IPIPE_OUTPUT_RESIZER (1 << 0)
108
109enum ipipe_input_entity {
110 IPIPE_INPUT_NONE = 0,
111 IPIPE_INPUT_MEMORY = 1,
112 IPIPE_INPUT_CCDC = 2,
113};
114
115
116struct vpfe_ipipe_device {
117 struct v4l2_subdev subdev;
118 struct media_pad pads[IPIPE_PADS_NUM];
119 struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM];
120 enum ipipe_input_entity input;
121 unsigned int output;
122 struct v4l2_ctrl_handler ctrls;
123 void *__iomem base_addr;
124 void *__iomem isp5_base_addr;
125 struct ipipe_module_params config;
126};
127
128struct ipipe_module_if {
129 unsigned int param_offset;
130 unsigned int param_size;
131 unsigned int config_offset;
132 int (*set)(struct vpfe_ipipe_device *ipipe, void *param);
133 int (*get)(struct vpfe_ipipe_device *ipipe, void *param);
134};
135
136/* data paths */
137enum ipipe_data_paths {
138 IPIPE_RAW2YUV,
139 /* Bayer RAW input to YCbCr output */
140 IPIPE_RAW2RAW,
141 /* Bayer Raw to Bayer output */
142 IPIPE_RAW2BOX,
143 /* Bayer Raw to Boxcar output */
144 IPIPE_YUV2YUV
145 /* YUV Raw to YUV Raw output */
146};
147
148#define IPIPE_COLPTN_R_Ye 0x0
149#define IPIPE_COLPTN_Gr_Cy 0x1
150#define IPIPE_COLPTN_Gb_G 0x2
151#define IPIPE_COLPTN_B_Mg 0x3
152
153#define COLPAT_EE_SHIFT 0
154#define COLPAT_EO_SHIFT 2
155#define COLPAT_OE_SHIFT 4
156#define COLPAT_OO_SHIFT 6
157
158#define ipipe_sgrbg_pattern \
159 (IPIPE_COLPTN_Gr_Cy << COLPAT_EE_SHIFT | \
160 IPIPE_COLPTN_R_Ye << COLPAT_EO_SHIFT | \
161 IPIPE_COLPTN_B_Mg << COLPAT_OE_SHIFT | \
162 IPIPE_COLPTN_Gb_G << COLPAT_OO_SHIFT)
163
164#define ipipe_srggb_pattern \
165 (IPIPE_COLPTN_R_Ye << COLPAT_EE_SHIFT | \
166 IPIPE_COLPTN_Gr_Cy << COLPAT_EO_SHIFT | \
167 IPIPE_COLPTN_Gb_G << COLPAT_OE_SHIFT | \
168 IPIPE_COLPTN_B_Mg << COLPAT_OO_SHIFT)
169
170int vpfe_ipipe_register_entities(struct vpfe_ipipe_device *ipipe,
171 struct v4l2_device *v4l2_dev);
172int vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe,
173 struct platform_device *pdev);
174void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *ipipe);
175void vpfe_ipipe_cleanup(struct vpfe_ipipe_device *ipipe,
176 struct platform_device *pdev);
177void vpfe_ipipe_enable(struct vpfe_device *vpfe_dev, int en);
178
179#endif /* _DAVINCI_VPFE_DM365_IPIPE_H */