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