linux/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
<<
>>
Prefs
   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, resource_size(res));
1863}
1864