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#include "dm365_ipipe_hw.h" 23 24#define IPIPE_MODE_CONTINUOUS 0 25#define IPIPE_MODE_SINGLE_SHOT 1 26 27static void ipipe_clock_enable(void *__iomem base_addr) 28{ 29 /* enable IPIPE MMR for register write access */ 30 regw_ip(base_addr, IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR); 31 32 /* enable the clock wb,cfa,dfc,d2f,pre modules */ 33 regw_ip(base_addr, IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX); 34} 35 36static void 37rsz_set_common_params(void *__iomem rsz_base, struct resizer_params *params) 38{ 39 struct rsz_common_params *rsz_common = ¶ms->rsz_common; 40 u32 val; 41 42 /* Set mode */ 43 regw_rsz(rsz_base, params->oper_mode, RSZ_SRC_MODE); 44 45 /* data source selection and bypass */ 46 val = (rsz_common->passthrough << RSZ_BYPASS_SHIFT) | 47 rsz_common->source; 48 regw_rsz(rsz_base, val, RSZ_SRC_FMT0); 49 50 /* src image selection */ 51 val = (rsz_common->raw_flip & 1) | 52 (rsz_common->src_img_fmt << RSZ_SRC_IMG_FMT_SHIFT) | 53 ((rsz_common->y_c & 1) << RSZ_SRC_Y_C_SEL_SHIFT); 54 regw_rsz(rsz_base, val, RSZ_SRC_FMT1); 55 56 regw_rsz(rsz_base, rsz_common->vps & IPIPE_RSZ_VPS_MASK, RSZ_SRC_VPS); 57 regw_rsz(rsz_base, rsz_common->hps & IPIPE_RSZ_HPS_MASK, RSZ_SRC_HPS); 58 regw_rsz(rsz_base, rsz_common->vsz & IPIPE_RSZ_VSZ_MASK, RSZ_SRC_VSZ); 59 regw_rsz(rsz_base, rsz_common->hsz & IPIPE_RSZ_HSZ_MASK, RSZ_SRC_HSZ); 60 regw_rsz(rsz_base, rsz_common->yuv_y_min, RSZ_YUV_Y_MIN); 61 regw_rsz(rsz_base, rsz_common->yuv_y_max, RSZ_YUV_Y_MAX); 62 regw_rsz(rsz_base, rsz_common->yuv_c_min, RSZ_YUV_C_MIN); 63 regw_rsz(rsz_base, rsz_common->yuv_c_max, RSZ_YUV_C_MAX); 64 /* chromatic position */ 65 regw_rsz(rsz_base, rsz_common->out_chr_pos, RSZ_YUV_PHS); 66} 67 68static void 69rsz_set_rsz_regs(void *__iomem rsz_base, unsigned int rsz_id, 70 struct resizer_params *params) 71{ 72 struct resizer_scale_param *rsc_params; 73 struct rsz_ext_mem_param *ext_mem; 74 struct resizer_rgb *rgb; 75 u32 reg_base; 76 u32 val; 77 78 rsc_params = ¶ms->rsz_rsc_param[rsz_id]; 79 rgb = ¶ms->rsz2rgb[rsz_id]; 80 ext_mem = ¶ms->ext_mem_param[rsz_id]; 81 82 if (rsz_id == RSZ_A) { 83 val = rsc_params->h_flip << RSZA_H_FLIP_SHIFT; 84 val |= rsc_params->v_flip << RSZA_V_FLIP_SHIFT; 85 reg_base = RSZ_EN_A; 86 } else { 87 val = rsc_params->h_flip << RSZB_H_FLIP_SHIFT; 88 val |= rsc_params->v_flip << RSZB_V_FLIP_SHIFT; 89 reg_base = RSZ_EN_B; 90 } 91 /* update flip settings */ 92 regw_rsz(rsz_base, val, RSZ_SEQ); 93 94 regw_rsz(rsz_base, params->oper_mode, reg_base + RSZ_MODE); 95 96 val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen; 97 regw_rsz(rsz_base, val, reg_base + RSZ_420); 98 99 regw_rsz(rsz_base, rsc_params->i_vps & RSZ_VPS_MASK, 100 reg_base + RSZ_I_VPS); 101 regw_rsz(rsz_base, rsc_params->i_hps & RSZ_HPS_MASK, 102 reg_base + RSZ_I_HPS); 103 regw_rsz(rsz_base, rsc_params->o_vsz & RSZ_O_VSZ_MASK, 104 reg_base + RSZ_O_VSZ); 105 regw_rsz(rsz_base, rsc_params->o_hsz & RSZ_O_HSZ_MASK, 106 reg_base + RSZ_O_HSZ); 107 regw_rsz(rsz_base, rsc_params->v_phs_y & RSZ_V_PHS_MASK, 108 reg_base + RSZ_V_PHS_Y); 109 regw_rsz(rsz_base, rsc_params->v_phs_c & RSZ_V_PHS_MASK, 110 reg_base + RSZ_V_PHS_C); 111 112 /* keep this additional adjustment to zero for now */ 113 regw_rsz(rsz_base, rsc_params->v_dif & RSZ_V_DIF_MASK, 114 reg_base + RSZ_V_DIF); 115 116 val = (rsc_params->v_typ_y & 1) | 117 ((rsc_params->v_typ_c & 1) << RSZ_TYP_C_SHIFT); 118 regw_rsz(rsz_base, val, reg_base + RSZ_V_TYP); 119 120 val = (rsc_params->v_lpf_int_y & RSZ_LPF_INT_MASK) | 121 ((rsc_params->v_lpf_int_c & RSZ_LPF_INT_MASK) << 122 RSZ_LPF_INT_C_SHIFT); 123 regw_rsz(rsz_base, val, reg_base + RSZ_V_LPF); 124 125 regw_rsz(rsz_base, rsc_params->h_phs & 126 RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS); 127 128 regw_rsz(rsz_base, 0, reg_base + RSZ_H_PHS_ADJ); 129 regw_rsz(rsz_base, rsc_params->h_dif & 130 RSZ_H_DIF_MASK, reg_base + RSZ_H_DIF); 131 132 val = (rsc_params->h_typ_y & 1) | 133 ((rsc_params->h_typ_c & 1) << RSZ_TYP_C_SHIFT); 134 regw_rsz(rsz_base, val, reg_base + RSZ_H_TYP); 135 136 val = (rsc_params->h_lpf_int_y & RSZ_LPF_INT_MASK) | 137 ((rsc_params->h_lpf_int_c & RSZ_LPF_INT_MASK) << 138 RSZ_LPF_INT_C_SHIFT); 139 regw_rsz(rsz_base, val, reg_base + RSZ_H_LPF); 140 141 regw_rsz(rsz_base, rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN); 142 143 val = (rsc_params->h_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) | 144 ((rsc_params->v_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) << 145 RSZ_DWN_SCALE_AV_SZ_V_SHIFT); 146 regw_rsz(rsz_base, val, reg_base + RSZ_DWN_AV); 147 148 /* setting rgb conversion parameters */ 149 regw_rsz(rsz_base, rgb->rgb_en, reg_base + RSZ_RGB_EN); 150 151 val = (rgb->rgb_typ << RSZ_RGB_TYP_SHIFT) | 152 (rgb->rgb_msk0 << RSZ_RGB_MSK0_SHIFT) | 153 (rgb->rgb_msk1 << RSZ_RGB_MSK1_SHIFT); 154 regw_rsz(rsz_base, val, reg_base + RSZ_RGB_TYP); 155 156 regw_rsz(rsz_base, rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK, 157 reg_base + RSZ_RGB_BLD); 158 159 /* setting external memory parameters */ 160 regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_y, reg_base + RSZ_SDR_Y_OFT); 161 regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_y, 162 reg_base + RSZ_SDR_Y_PTR_S); 163 regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_e_y, 164 reg_base + RSZ_SDR_Y_PTR_E); 165 regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_c, reg_base + RSZ_SDR_C_OFT); 166 regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_c, 167 reg_base + RSZ_SDR_C_PTR_S); 168 regw_rsz(rsz_base, (ext_mem->rsz_sdr_ptr_e_c >> 1), 169 reg_base + RSZ_SDR_C_PTR_E); 170} 171 172/*set the registers of either RSZ0 or RSZ1 */ 173static void 174ipipe_setup_resizer(void *__iomem rsz_base, struct resizer_params *params) 175{ 176 /* enable MMR gate to write to Resizer */ 177 regw_rsz(rsz_base, 1, RSZ_GCK_MMR); 178 179 /* Enable resizer if it is not in bypass mode */ 180 if (params->rsz_common.passthrough) 181 regw_rsz(rsz_base, 0, RSZ_GCK_SDR); 182 else 183 regw_rsz(rsz_base, 1, RSZ_GCK_SDR); 184 185 rsz_set_common_params(rsz_base, params); 186 187 regw_rsz(rsz_base, params->rsz_en[RSZ_A], RSZ_EN_A); 188 189 if (params->rsz_en[RSZ_A]) 190 /*setting rescale parameters */ 191 rsz_set_rsz_regs(rsz_base, RSZ_A, params); 192 193 regw_rsz(rsz_base, params->rsz_en[RSZ_B], RSZ_EN_B); 194 195 if (params->rsz_en[RSZ_B]) 196 rsz_set_rsz_regs(rsz_base, RSZ_B, params); 197} 198 199static u32 ipipe_get_color_pat(enum v4l2_mbus_pixelcode pix) 200{ 201 switch (pix) { 202 case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8: 203 case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8: 204 case V4L2_MBUS_FMT_SGRBG12_1X12: 205 return ipipe_sgrbg_pattern; 206 207 default: 208 return ipipe_srggb_pattern; 209 } 210} 211 212static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe) 213{ 214 enum v4l2_mbus_pixelcode temp_pix_fmt; 215 216 switch (ipipe->formats[IPIPE_PAD_SINK].code) { 217 case V4L2_MBUS_FMT_SBGGR8_1X8: 218 case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8: 219 case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8: 220 case V4L2_MBUS_FMT_SGRBG12_1X12: 221 temp_pix_fmt = V4L2_MBUS_FMT_SGRBG12_1X12; 222 break; 223 224 default: 225 temp_pix_fmt = V4L2_MBUS_FMT_UYVY8_2X8; 226 } 227 228 if (temp_pix_fmt == V4L2_MBUS_FMT_SGRBG12_1X12) { 229 if (ipipe->formats[IPIPE_PAD_SOURCE].code == 230 V4L2_MBUS_FMT_SGRBG12_1X12) 231 return IPIPE_RAW2RAW; 232 return IPIPE_RAW2YUV; 233 } 234 235 return IPIPE_YUV2YUV; 236} 237 238static int get_ipipe_mode(struct vpfe_ipipe_device *ipipe) 239{ 240 struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe); 241 u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; 242 243 if (ipipeif_sink == IPIPEIF_INPUT_MEMORY) 244 return IPIPE_MODE_SINGLE_SHOT; 245 else if (ipipeif_sink == IPIPEIF_INPUT_ISIF) 246 return IPIPE_MODE_CONTINUOUS; 247 248 return -EINVAL; 249} 250 251int config_ipipe_hw(struct vpfe_ipipe_device *ipipe) 252{ 253 struct vpfe_ipipe_input_config *config = &ipipe->config.input_config; 254 void __iomem *ipipe_base = ipipe->base_addr; 255 struct v4l2_mbus_framefmt *outformat; 256 u32 color_pat; 257 u32 ipipe_mode; 258 u32 data_path; 259 260 /* enable clock to IPIPE */ 261 vpss_enable_clock(VPSS_IPIPE_CLOCK, 1); 262 ipipe_clock_enable(ipipe_base); 263 264 if (ipipe->input == IPIPE_INPUT_NONE) { 265 regw_ip(ipipe_base, 0, IPIPE_SRC_EN); 266 return 0; 267 } 268 269 ipipe_mode = get_ipipe_mode(ipipe); 270 if (ipipe_mode < 0) { 271 pr_err("Failed to get ipipe mode"); 272 return -EINVAL; 273 } 274 regw_ip(ipipe_base, ipipe_mode, IPIPE_SRC_MODE); 275 276 data_path = ipipe_get_data_path(ipipe); 277 regw_ip(ipipe_base, data_path, IPIPE_SRC_FMT); 278 279 regw_ip(ipipe_base, config->vst & IPIPE_RSZ_VPS_MASK, IPIPE_SRC_VPS); 280 regw_ip(ipipe_base, config->hst & IPIPE_RSZ_HPS_MASK, IPIPE_SRC_HPS); 281 282 outformat = &ipipe->formats[IPIPE_PAD_SOURCE]; 283 regw_ip(ipipe_base, (outformat->height + 1) & IPIPE_RSZ_VSZ_MASK, 284 IPIPE_SRC_VSZ); 285 regw_ip(ipipe_base, (outformat->width + 1) & IPIPE_RSZ_HSZ_MASK, 286 IPIPE_SRC_HSZ); 287 288 if (data_path == IPIPE_RAW2YUV || 289 data_path == IPIPE_RAW2RAW) { 290 color_pat = 291 ipipe_get_color_pat(ipipe->formats[IPIPE_PAD_SINK].code); 292 regw_ip(ipipe_base, color_pat, IPIPE_SRC_COL); 293 } 294 295 return 0; 296} 297 298/* 299 * config_rsz_hw() - Performs hardware setup of resizer. 300 */ 301int config_rsz_hw(struct vpfe_resizer_device *resizer, 302 struct resizer_params *config) 303{ 304 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); 305 void *__iomem ipipe_base = vpfe_dev->vpfe_ipipe.base_addr; 306 void *__iomem rsz_base = vpfe_dev->vpfe_resizer.base_addr; 307 308 /* enable VPSS clock */ 309 vpss_enable_clock(VPSS_IPIPE_CLOCK, 1); 310 ipipe_clock_enable(ipipe_base); 311 312 ipipe_setup_resizer(rsz_base, config); 313 314 return 0; 315} 316 317static void 318rsz_set_y_address(void *__iomem rsz_base, unsigned int address, 319 unsigned int offset) 320{ 321 u32 val; 322 323 val = address & SET_LOW_ADDR; 324 regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_L); 325 regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_L); 326 327 val = (address & SET_HIGH_ADDR) >> 16; 328 regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_H); 329 regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_H); 330} 331 332static void 333rsz_set_c_address(void *__iomem rsz_base, unsigned int address, 334 unsigned int offset) 335{ 336 u32 val; 337 338 val = address & SET_LOW_ADDR; 339 regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_L); 340 regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_L); 341 342 val = (address & SET_HIGH_ADDR) >> 16; 343 regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_H); 344 regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_H); 345} 346 347/* 348 * resizer_set_outaddr() - set the address for given resize_no 349 * @rsz_base: resizer base address 350 * @params: pointer to ipipe_params structure 351 * @resize_no: 0 - Resizer-A, 1 - Resizer B 352 * @address: the address to set 353 */ 354int 355resizer_set_outaddr(void *__iomem rsz_base, struct resizer_params *params, 356 int resize_no, unsigned int address) 357{ 358 struct resizer_scale_param *rsc_param; 359 struct rsz_ext_mem_param *mem_param; 360 struct rsz_common_params *rsz_common; 361 unsigned int rsz_start_add; 362 unsigned int val; 363 364 if (resize_no != RSZ_A && resize_no != RSZ_B) 365 return -EINVAL; 366 367 mem_param = ¶ms->ext_mem_param[resize_no]; 368 rsc_param = ¶ms->rsz_rsc_param[resize_no]; 369 rsz_common = ¶ms->rsz_common; 370 371 if (resize_no == RSZ_A) 372 rsz_start_add = RSZ_EN_A; 373 else 374 rsz_start_add = RSZ_EN_B; 375 376 /* y_c = 0 for y, = 1 for c */ 377 if (rsz_common->src_img_fmt == RSZ_IMG_420) { 378 if (rsz_common->y_c) { 379 /* C channel */ 380 val = address + mem_param->flip_ofst_c; 381 rsz_set_c_address(rsz_base, val, rsz_start_add); 382 } else { 383 val = address + mem_param->flip_ofst_y; 384 rsz_set_y_address(rsz_base, val, rsz_start_add); 385 } 386 } else { 387 if (rsc_param->cen && rsc_param->yen) { 388 /* 420 */ 389 val = address + mem_param->c_offset + 390 mem_param->flip_ofst_c + 391 mem_param->user_y_ofst + 392 mem_param->user_c_ofst; 393 if (resize_no == RSZ_B) 394 val += 395 params->ext_mem_param[RSZ_A].user_y_ofst + 396 params->ext_mem_param[RSZ_A].user_c_ofst; 397 /* set C address */ 398 rsz_set_c_address(rsz_base, val, rsz_start_add); 399 } 400 val = address + mem_param->flip_ofst_y + mem_param->user_y_ofst; 401 if (resize_no == RSZ_B) 402 val += params->ext_mem_param[RSZ_A].user_y_ofst + 403 params->ext_mem_param[RSZ_A].user_c_ofst; 404 /* set Y address */ 405 rsz_set_y_address(rsz_base, val, rsz_start_add); 406 } 407 /* resizer must be enabled */ 408 regw_rsz(rsz_base, params->rsz_en[resize_no], rsz_start_add); 409 410 return 0; 411} 412 413void 414ipipe_set_lutdpc_regs(void *__iomem base_addr, void *__iomem isp5_base_addr, 415 struct vpfe_ipipe_lutdpc *dpc) 416{ 417 u32 max_tbl_size = LUT_DPC_MAX_SIZE >> 1; 418 u32 lut_start_addr = DPC_TB0_START_ADDR; 419 u32 val; 420 u32 count; 421 422 ipipe_clock_enable(base_addr); 423 regw_ip(base_addr, dpc->en, DPC_LUT_EN); 424 425 if (dpc->en != 1) 426 return; 427 428 val = LUTDPC_TBL_256_EN | (dpc->repl_white & 1); 429 regw_ip(base_addr, val, DPC_LUT_SEL); 430 regw_ip(base_addr, LUT_DPC_START_ADDR, DPC_LUT_ADR); 431 regw_ip(base_addr, dpc->dpc_size, DPC_LUT_SIZ & LUT_DPC_SIZE_MASK); 432 433 if (dpc->table == NULL) 434 return; 435 436 for (count = 0; count < dpc->dpc_size; count++) { 437 if (count >= max_tbl_size) 438 lut_start_addr = DPC_TB1_START_ADDR; 439 val = (dpc->table[count].horz_pos & LUT_DPC_H_POS_MASK) | 440 ((dpc->table[count].vert_pos & LUT_DPC_V_POS_MASK) << 441 LUT_DPC_V_POS_SHIFT) | (dpc->table[count].method << 442 LUT_DPC_CORR_METH_SHIFT); 443 w_ip_table(isp5_base_addr, val, (lut_start_addr + 444 ((count % max_tbl_size) << 2))); 445 } 446} 447 448static void 449set_dpc_thresholds(void *__iomem base_addr, 450 struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_thr) 451{ 452 regw_ip(base_addr, dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK, 453 DPC_OTF_2C_THR_R); 454 regw_ip(base_addr, dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK, 455 DPC_OTF_2C_THR_GR); 456 regw_ip(base_addr, dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK, 457 DPC_OTF_2C_THR_GB); 458 regw_ip(base_addr, dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK, 459 DPC_OTF_2C_THR_B); 460 regw_ip(base_addr, dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK, 461 DPC_OTF_2D_THR_R); 462 regw_ip(base_addr, dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK, 463 DPC_OTF_2D_THR_GR); 464 regw_ip(base_addr, dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK, 465 DPC_OTF_2D_THR_GB); 466 regw_ip(base_addr, dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK, 467 DPC_OTF_2D_THR_B); 468} 469 470void ipipe_set_otfdpc_regs(void *__iomem base_addr, 471 struct vpfe_ipipe_otfdpc *otfdpc) 472{ 473 struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0; 474 struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0; 475 u32 val; 476 477 ipipe_clock_enable(base_addr); 478 479 regw_ip(base_addr, (otfdpc->en & 1), DPC_OTF_EN); 480 if (!otfdpc->en) 481 return; 482 483 /* dpc enabled */ 484 val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT) | otfdpc->alg; 485 regw_ip(base_addr, val, DPC_OTF_TYP); 486 487 if (otfdpc->det_method == VPFE_IPIPE_DPC_OTF_MIN_MAX) { 488 /* ALG= 0, TYP = 0, DPC_OTF_2D_THR_[x]=0 489 * DPC_OTF_2C_THR_[x] = Maximum thresohld 490 * MinMax method 491 */ 492 dpc_2_0->det_thr.r = dpc_2_0->det_thr.gb = 493 dpc_2_0->det_thr.gr = dpc_2_0->det_thr.b = 0; 494 set_dpc_thresholds(base_addr, dpc_2_0); 495 return; 496 } 497 /* MinMax2 */ 498 if (otfdpc->alg == VPFE_IPIPE_OTFDPC_2_0) { 499 set_dpc_thresholds(base_addr, dpc_2_0); 500 return; 501 } 502 regw_ip(base_addr, dpc_3_0->act_adj_shf & 503 OTF_DPC3_0_SHF_MASK, DPC_OTF_3_SHF); 504 /* Detection thresholds */ 505 regw_ip(base_addr, ((dpc_3_0->det_thr & OTF_DPC3_0_THR_MASK) << 506 OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR); 507 regw_ip(base_addr, dpc_3_0->det_slp & 508 OTF_DPC3_0_SLP_MASK, DPC_OTF_3D_SLP); 509 regw_ip(base_addr, dpc_3_0->det_thr_min & 510 OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MIN); 511 regw_ip(base_addr, dpc_3_0->det_thr_max & 512 OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MAX); 513 /* Correction thresholds */ 514 regw_ip(base_addr, ((dpc_3_0->corr_thr & OTF_DPC3_0_THR_MASK) << 515 OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR); 516 regw_ip(base_addr, dpc_3_0->corr_slp & 517 OTF_DPC3_0_SLP_MASK, DPC_OTF_3C_SLP); 518 regw_ip(base_addr, dpc_3_0->corr_thr_min & 519 OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MIN); 520 regw_ip(base_addr, dpc_3_0->corr_thr_max & 521 OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MAX); 522} 523 524/* 2D Noise filter */ 525void 526ipipe_set_d2f_regs(void *__iomem base_addr, unsigned int id, 527 struct vpfe_ipipe_nf *noise_filter) 528{ 529 530 u32 offset = D2F_1ST; 531 int count; 532 u32 val; 533 534 if (id == IPIPE_D2F_2ND) 535 offset = D2F_2ND; 536 537 ipipe_clock_enable(base_addr); 538 regw_ip(base_addr, noise_filter->en & 1, offset + D2F_EN); 539 if (!noise_filter->en) 540 return; 541 542 /*noise filter enabled */ 543 /* Combine all the fields to make D2F_CFG register of IPIPE */ 544 val = ((noise_filter->spread_val & D2F_SPR_VAL_MASK) << 545 D2F_SPR_VAL_SHIFT) | ((noise_filter->shft_val & 546 D2F_SHFT_VAL_MASK) << D2F_SHFT_VAL_SHIFT) | 547 (noise_filter->gr_sample_meth << D2F_SAMPLE_METH_SHIFT) | 548 ((noise_filter->apply_lsc_gain & 1) << 549 D2F_APPLY_LSC_GAIN_SHIFT) | D2F_USE_SPR_REG_VAL; 550 regw_ip(base_addr, val, offset + D2F_TYP); 551 552 /* edge detection minimum */ 553 regw_ip(base_addr, noise_filter->edge_det_min_thr & 554 D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MIN); 555 556 /* edge detection maximum */ 557 regw_ip(base_addr, noise_filter->edge_det_max_thr & 558 D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MAX); 559 560 for (count = 0; count < VPFE_IPIPE_NF_STR_TABLE_SIZE; count++) 561 regw_ip(base_addr, 562 (noise_filter->str[count] & D2F_STR_VAL_MASK), 563 offset + D2F_STR + count * 4); 564 565 for (count = 0; count < VPFE_IPIPE_NF_THR_TABLE_SIZE; count++) 566 regw_ip(base_addr, noise_filter->thr[count] & D2F_THR_VAL_MASK, 567 offset + D2F_THR + count * 4); 568} 569 570#define IPIPE_U8Q5(decimal, integer) \ 571 (((decimal & 0x1f) | ((integer & 0x7) << 5))) 572 573/* Green Imbalance Correction */ 574void ipipe_set_gic_regs(void *__iomem base_addr, struct vpfe_ipipe_gic *gic) 575{ 576 u32 val; 577 578 ipipe_clock_enable(base_addr); 579 regw_ip(base_addr, gic->en & 1, GIC_EN); 580 581 if (!gic->en) 582 return; 583 584 /*gic enabled */ 585 val = (gic->wt_fn_type << GIC_TYP_SHIFT) | 586 (gic->thr_sel << GIC_THR_SEL_SHIFT) | 587 ((gic->apply_lsc_gain & 1) << GIC_APPLY_LSC_GAIN_SHIFT); 588 regw_ip(base_addr, val, GIC_TYP); 589 590 regw_ip(base_addr, gic->gain & GIC_GAIN_MASK, GIC_GAN); 591 592 if (gic->gic_alg != VPFE_IPIPE_GIC_ALG_ADAPT_GAIN) { 593 /* Constant Gain. Set threshold to maximum */ 594 regw_ip(base_addr, GIC_THR_MASK, GIC_THR); 595 return; 596 } 597 598 if (gic->thr_sel == VPFE_IPIPE_GIC_THR_REG) { 599 regw_ip(base_addr, gic->thr & GIC_THR_MASK, GIC_THR); 600 regw_ip(base_addr, gic->slope & GIC_SLOPE_MASK, GIC_SLP); 601 } else { 602 /* Use NF thresholds */ 603 val = IPIPE_U8Q5(gic->nf2_thr_gain.decimal, 604 gic->nf2_thr_gain.integer); 605 regw_ip(base_addr, val, GIC_NFGAN); 606 } 607} 608 609#define IPIPE_U13Q9(decimal, integer) \ 610 (((decimal & 0x1ff) | ((integer & 0xf) << 9))) 611/* White balance */ 612void ipipe_set_wb_regs(void *__iomem base_addr, struct vpfe_ipipe_wb *wb) 613{ 614 u32 val; 615 616 ipipe_clock_enable(base_addr); 617 /* Ofsets. S12 */ 618 regw_ip(base_addr, wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R); 619 regw_ip(base_addr, wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR); 620 regw_ip(base_addr, wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB); 621 regw_ip(base_addr, wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B); 622 623 /* Gains. U13Q9 */ 624 val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer); 625 regw_ip(base_addr, val, WB2_WGN_R); 626 627 val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer); 628 regw_ip(base_addr, val, WB2_WGN_GR); 629 630 val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer); 631 regw_ip(base_addr, val, WB2_WGN_GB); 632 633 val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer); 634 regw_ip(base_addr, val, WB2_WGN_B); 635} 636 637/* CFA */ 638void ipipe_set_cfa_regs(void *__iomem base_addr, struct vpfe_ipipe_cfa *cfa) 639{ 640 ipipe_clock_enable(base_addr); 641 642 regw_ip(base_addr, cfa->alg, CFA_MODE); 643 regw_ip(base_addr, cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK, 644 CFA_2DIR_HPF_THR); 645 regw_ip(base_addr, cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK, 646 CFA_2DIR_HPF_SLP); 647 regw_ip(base_addr, cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK, 648 CFA_2DIR_MIX_THR); 649 regw_ip(base_addr, cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK, 650 CFA_2DIR_MIX_SLP); 651 regw_ip(base_addr, cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK, 652 CFA_2DIR_DIR_THR); 653 regw_ip(base_addr, cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK, 654 CFA_2DIR_DIR_SLP); 655 regw_ip(base_addr, cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK, 656 CFA_2DIR_NDWT); 657 regw_ip(base_addr, cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK, 658 CFA_MONO_HUE_FRA); 659 regw_ip(base_addr, cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK, 660 CFA_MONO_EDG_THR); 661 regw_ip(base_addr, cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK, 662 CFA_MONO_THR_MIN); 663 regw_ip(base_addr, cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK, 664 CFA_MONO_THR_SLP); 665 regw_ip(base_addr, cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK, 666 CFA_MONO_SLP_MIN); 667 regw_ip(base_addr, cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK, 668 CFA_MONO_SLP_SLP); 669 regw_ip(base_addr, cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK, 670 CFA_MONO_LPWT); 671} 672 673void 674ipipe_set_rgb2rgb_regs(void *__iomem base_addr, unsigned int id, 675 struct vpfe_ipipe_rgb2rgb *rgb) 676{ 677 u32 offset_mask = RGB2RGB_1_OFST_MASK; 678 u32 offset = RGB1_MUL_BASE; 679 u32 integ_mask = 0xf; 680 u32 val; 681 682 ipipe_clock_enable(base_addr); 683 684 if (id == IPIPE_RGB2RGB_2) { 685 /* For second RGB module, gain integer is 3 bits instead 686 of 4, offset has 11 bits insread of 13 */ 687 offset = RGB2_MUL_BASE; 688 integ_mask = 0x7; 689 offset_mask = RGB2RGB_2_OFST_MASK; 690 } 691 /* Gains */ 692 val = (rgb->coef_rr.decimal & 0xff) | 693 ((rgb->coef_rr.integer & integ_mask) << 8); 694 regw_ip(base_addr, val, offset + RGB_MUL_RR); 695 val = (rgb->coef_gr.decimal & 0xff) | 696 ((rgb->coef_gr.integer & integ_mask) << 8); 697 regw_ip(base_addr, val, offset + RGB_MUL_GR); 698 val = (rgb->coef_br.decimal & 0xff) | 699 ((rgb->coef_br.integer & integ_mask) << 8); 700 regw_ip(base_addr, val, offset + RGB_MUL_BR); 701 val = (rgb->coef_rg.decimal & 0xff) | 702 ((rgb->coef_rg.integer & integ_mask) << 8); 703 regw_ip(base_addr, val, offset + RGB_MUL_RG); 704 val = (rgb->coef_gg.decimal & 0xff) | 705 ((rgb->coef_gg.integer & integ_mask) << 8); 706 regw_ip(base_addr, val, offset + RGB_MUL_GG); 707 val = (rgb->coef_bg.decimal & 0xff) | 708 ((rgb->coef_bg.integer & integ_mask) << 8); 709 regw_ip(base_addr, val, offset + RGB_MUL_BG); 710 val = (rgb->coef_rb.decimal & 0xff) | 711 ((rgb->coef_rb.integer & integ_mask) << 8); 712 regw_ip(base_addr, val, offset + RGB_MUL_RB); 713 val = (rgb->coef_gb.decimal & 0xff) | 714 ((rgb->coef_gb.integer & integ_mask) << 8); 715 regw_ip(base_addr, val, offset + RGB_MUL_GB); 716 val = (rgb->coef_bb.decimal & 0xff) | 717 ((rgb->coef_bb.integer & integ_mask) << 8); 718 regw_ip(base_addr, val, offset + RGB_MUL_BB); 719 720 /* Offsets */ 721 regw_ip(base_addr, rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR); 722 regw_ip(base_addr, rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG); 723 regw_ip(base_addr, rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB); 724} 725 726static void 727ipipe_update_gamma_tbl(void *__iomem isp5_base_addr, 728 struct vpfe_ipipe_gamma_entry *table, int size, u32 addr) 729{ 730 int count; 731 u32 val; 732 733 for (count = 0; count < size; count++) { 734 val = table[count].slope & GAMMA_MASK; 735 val |= (table[count].offset & GAMMA_MASK) << GAMMA_SHIFT; 736 w_ip_table(isp5_base_addr, val, (addr + (count * 4))); 737 } 738} 739 740void 741ipipe_set_gamma_regs(void *__iomem base_addr, void *__iomem isp5_base_addr, 742 struct vpfe_ipipe_gamma *gamma) 743{ 744 int table_size; 745 u32 val; 746 747 ipipe_clock_enable(base_addr); 748 val = (gamma->bypass_r << GAMMA_BYPR_SHIFT) | 749 (gamma->bypass_b << GAMMA_BYPG_SHIFT) | 750 (gamma->bypass_g << GAMMA_BYPB_SHIFT) | 751 (gamma->tbl_sel << GAMMA_TBL_SEL_SHIFT) | 752 (gamma->tbl_size << GAMMA_TBL_SIZE_SHIFT); 753 754 regw_ip(base_addr, val, GMM_CFG); 755 756 if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM) 757 return; 758 759 table_size = gamma->tbl_size; 760 761 if (!gamma->bypass_r && gamma->table_r != NULL) 762 ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_r, 763 table_size, GAMMA_R_START_ADDR); 764 if (!gamma->bypass_b && gamma->table_b != NULL) 765 ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_b, 766 table_size, GAMMA_B_START_ADDR); 767 if (!gamma->bypass_g && gamma->table_g != NULL) 768 ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_g, 769 table_size, GAMMA_G_START_ADDR); 770} 771 772void 773ipipe_set_3d_lut_regs(void *__iomem base_addr, void *__iomem isp5_base_addr, 774 struct vpfe_ipipe_3d_lut *lut_3d) 775{ 776 struct vpfe_ipipe_3d_lut_entry *tbl; 777 u32 bnk_index; 778 u32 tbl_index; 779 u32 val; 780 u32 i; 781 782 ipipe_clock_enable(base_addr); 783 regw_ip(base_addr, lut_3d->en, D3LUT_EN); 784 785 if (!lut_3d->en) 786 return; 787 788 /* lut_3d enabled */ 789 if (!lut_3d->table) 790 return; 791 792 /* valied table */ 793 tbl = lut_3d->table; 794 for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) { 795 /* Each entry has 0-9 (B), 10-19 (G) and 796 20-29 R values */ 797 val = tbl[i].b & D3_LUT_ENTRY_MASK; 798 val |= (tbl[i].g & D3_LUT_ENTRY_MASK) << 799 D3_LUT_ENTRY_G_SHIFT; 800 val |= (tbl[i].r & D3_LUT_ENTRY_MASK) << 801 D3_LUT_ENTRY_R_SHIFT; 802 bnk_index = i % 4; 803 tbl_index = i >> 2; 804 tbl_index <<= 2; 805 if (bnk_index == 0) 806 w_ip_table(isp5_base_addr, val, 807 tbl_index + D3L_TB0_START_ADDR); 808 else if (bnk_index == 1) 809 w_ip_table(isp5_base_addr, val, 810 tbl_index + D3L_TB1_START_ADDR); 811 else if (bnk_index == 2) 812 w_ip_table(isp5_base_addr, val, 813 tbl_index + D3L_TB2_START_ADDR); 814 else 815 w_ip_table(isp5_base_addr, val, 816 tbl_index + D3L_TB3_START_ADDR); 817 } 818} 819 820/* Lumina adjustments */ 821void 822ipipe_set_lum_adj_regs(void *__iomem base_addr, struct ipipe_lum_adj *lum_adj) 823{ 824 u32 val; 825 826 ipipe_clock_enable(base_addr); 827 828 /* combine fields of YUV_ADJ to set brightness and contrast */ 829 val = lum_adj->contrast << LUM_ADJ_CONTR_SHIFT | 830 lum_adj->brightness << LUM_ADJ_BRIGHT_SHIFT; 831 regw_ip(base_addr, val, YUV_ADJ); 832} 833 834#define IPIPE_S12Q8(decimal, integer) \ 835 (((decimal & 0xff) | ((integer & 0xf) << 8))) 836 837void ipipe_set_rgb2ycbcr_regs(void *__iomem base_addr, 838 struct vpfe_ipipe_rgb2yuv *yuv) 839{ 840 u32 val; 841 842 /* S10Q8 */ 843 ipipe_clock_enable(base_addr); 844 val = IPIPE_S12Q8(yuv->coef_ry.decimal, yuv->coef_ry.integer); 845 regw_ip(base_addr, val, YUV_MUL_RY); 846 val = IPIPE_S12Q8(yuv->coef_gy.decimal, yuv->coef_gy.integer); 847 regw_ip(base_addr, val, YUV_MUL_GY); 848 val = IPIPE_S12Q8(yuv->coef_by.decimal, yuv->coef_by.integer); 849 regw_ip(base_addr, val, YUV_MUL_BY); 850 val = IPIPE_S12Q8(yuv->coef_rcb.decimal, yuv->coef_rcb.integer); 851 regw_ip(base_addr, val, YUV_MUL_RCB); 852 val = IPIPE_S12Q8(yuv->coef_gcb.decimal, yuv->coef_gcb.integer); 853 regw_ip(base_addr, val, YUV_MUL_GCB); 854 val = IPIPE_S12Q8(yuv->coef_bcb.decimal, yuv->coef_bcb.integer); 855 regw_ip(base_addr, val, YUV_MUL_BCB); 856 val = IPIPE_S12Q8(yuv->coef_rcr.decimal, yuv->coef_rcr.integer); 857 regw_ip(base_addr, val, YUV_MUL_RCR); 858 val = IPIPE_S12Q8(yuv->coef_gcr.decimal, yuv->coef_gcr.integer); 859 regw_ip(base_addr, val, YUV_MUL_GCR); 860 val = IPIPE_S12Q8(yuv->coef_bcr.decimal, yuv->coef_bcr.integer); 861 regw_ip(base_addr, val, YUV_MUL_BCR); 862 regw_ip(base_addr, yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y); 863 regw_ip(base_addr, yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB); 864 regw_ip(base_addr, yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR); 865} 866 867/* YUV 422 conversion */ 868void 869ipipe_set_yuv422_conv_regs(void *__iomem base_addr, 870 struct vpfe_ipipe_yuv422_conv *conv) 871{ 872 u32 val; 873 874 ipipe_clock_enable(base_addr); 875 876 /* Combine all the fields to make YUV_PHS register of IPIPE */ 877 val = (conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1); 878 regw_ip(base_addr, val, YUV_PHS); 879} 880 881void 882ipipe_set_gbce_regs(void *__iomem base_addr, void *__iomem isp5_base_addr, 883 struct vpfe_ipipe_gbce *gbce) 884{ 885 unsigned int count; 886 u32 mask = GBCE_Y_VAL_MASK; 887 888 if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL) 889 mask = GBCE_GAIN_VAL_MASK; 890 891 ipipe_clock_enable(base_addr); 892 regw_ip(base_addr, gbce->en & 1, GBCE_EN); 893 894 if (!gbce->en) 895 return; 896 897 regw_ip(base_addr, gbce->type, GBCE_TYP); 898 899 if (!gbce->table) 900 return; 901 902 for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; count += 2) 903 w_ip_table(isp5_base_addr, ((gbce->table[count + 1] & mask) << 904 GBCE_ENTRY_SHIFT) | (gbce->table[count] & mask), 905 ((count/2) << 2) + GBCE_TB_START_ADDR); 906} 907 908void 909ipipe_set_ee_regs(void *__iomem base_addr, void *__iomem isp5_base_addr, 910 struct vpfe_ipipe_yee *ee) 911{ 912 unsigned int count; 913 u32 val; 914 915 ipipe_clock_enable(base_addr); 916 regw_ip(base_addr, ee->en, YEE_EN); 917 918 if (!ee->en) 919 return; 920 921 val = ee->en_halo_red & 1; 922 val |= ee->merge_meth << YEE_HALO_RED_EN_SHIFT; 923 regw_ip(base_addr, val, YEE_TYP); 924 925 regw_ip(base_addr, ee->hpf_shft, YEE_SHF); 926 regw_ip(base_addr, ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00); 927 regw_ip(base_addr, ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01); 928 regw_ip(base_addr, ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02); 929 regw_ip(base_addr, ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10); 930 regw_ip(base_addr, ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11); 931 regw_ip(base_addr, ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12); 932 regw_ip(base_addr, ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20); 933 regw_ip(base_addr, ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21); 934 regw_ip(base_addr, ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22); 935 regw_ip(base_addr, ee->yee_thr & YEE_THR_MASK, YEE_THR); 936 regw_ip(base_addr, ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN); 937 regw_ip(base_addr, ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1); 938 regw_ip(base_addr, ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2); 939 regw_ip(base_addr, ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN); 940 regw_ip(base_addr, ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT); 941 942 if (ee->table == NULL) 943 return; 944 945 for (count = 0; count < VPFE_IPIPE_MAX_SIZE_YEE_LUT; count += 2) 946 w_ip_table(isp5_base_addr, ((ee->table[count + 1] & 947 YEE_ENTRY_MASK) << YEE_ENTRY_SHIFT) | 948 (ee->table[count] & YEE_ENTRY_MASK), 949 ((count/2) << 2) + YEE_TB_START_ADDR); 950} 951 952/* Chromatic Artifact Correction. CAR */ 953static void ipipe_set_mf(void *__iomem base_addr) 954{ 955 /* typ to dynamic switch */ 956 regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP); 957 /* Set SW0 to maximum */ 958 regw_ip(base_addr, CAR_MF_THR, CAR_SW); 959} 960 961static void 962ipipe_set_gain_ctrl(void *__iomem base_addr, struct vpfe_ipipe_car *car) 963{ 964 regw_ip(base_addr, VPFE_IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP); 965 regw_ip(base_addr, car->hpf, CAR_HPF_TYP); 966 regw_ip(base_addr, car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF); 967 regw_ip(base_addr, car->hpf_thr, CAR_HPF_THR); 968 regw_ip(base_addr, car->gain1.gain, CAR_GN1_GAN); 969 regw_ip(base_addr, car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF); 970 regw_ip(base_addr, car->gain1.gain_min & CAR_GAIN_MIN_MASK, 971 CAR_GN1_MIN); 972 regw_ip(base_addr, car->gain2.gain, CAR_GN2_GAN); 973 regw_ip(base_addr, car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF); 974 regw_ip(base_addr, car->gain2.gain_min & CAR_GAIN_MIN_MASK, 975 CAR_GN2_MIN); 976} 977 978void ipipe_set_car_regs(void *__iomem base_addr, struct vpfe_ipipe_car *car) 979{ 980 u32 val; 981 982 ipipe_clock_enable(base_addr); 983 regw_ip(base_addr, car->en, CAR_EN); 984 985 if (!car->en) 986 return; 987 988 switch (car->meth) { 989 case VPFE_IPIPE_CAR_MED_FLTR: 990 ipipe_set_mf(base_addr); 991 break; 992 993 case VPFE_IPIPE_CAR_CHR_GAIN_CTRL: 994 ipipe_set_gain_ctrl(base_addr, car); 995 break; 996 997 default: 998 /* Dynamic switch between MF and Gain Ctrl. */ 999 ipipe_set_mf(base_addr); 1000 ipipe_set_gain_ctrl(base_addr, car); 1001 /* Set the threshold for switching between 1002 * the two Here we overwrite the MF SW0 value 1003 */ 1004 regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP); 1005 val = car->sw1; 1006 val <<= CAR_SW1_SHIFT; 1007 val |= car->sw0; 1008 regw_ip(base_addr, val, CAR_SW); 1009 } 1010} 1011 1012/* Chromatic Gain Suppression */ 1013void ipipe_set_cgs_regs(void *__iomem base_addr, struct vpfe_ipipe_cgs *cgs) 1014{ 1015 ipipe_clock_enable(base_addr); 1016 regw_ip(base_addr, cgs->en, CGS_EN); 1017 1018 if (!cgs->en) 1019 return; 1020 1021 /* Set the bright side parameters */ 1022 regw_ip(base_addr, cgs->h_thr, CGS_GN1_H_THR); 1023 regw_ip(base_addr, cgs->h_slope, CGS_GN1_H_GAN); 1024 regw_ip(base_addr, cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF); 1025 regw_ip(base_addr, cgs->h_min, CGS_GN1_H_MIN); 1026} 1027 1028void rsz_src_enable(void *__iomem rsz_base, int enable) 1029{ 1030 regw_rsz(rsz_base, enable, RSZ_SRC_EN); 1031} 1032 1033int rsz_enable(void *__iomem rsz_base, int rsz_id, int enable) 1034{ 1035 if (rsz_id == RSZ_A) { 1036 regw_rsz(rsz_base, enable, RSZ_EN_A); 1037 /* We always enable RSZ_A. RSZ_B is enable upon request from 1038 * application. So enable RSZ_SRC_EN along with RSZ_A 1039 */ 1040 regw_rsz(rsz_base, enable, RSZ_SRC_EN); 1041 } else if (rsz_id == RSZ_B) { 1042 regw_rsz(rsz_base, enable, RSZ_EN_B); 1043 } else { 1044 BUG(); 1045 } 1046 1047 return 0; 1048} 1049