Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 27 | static void ipipe_clock_enable(void __iomem *base_addr) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 36 | static void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 37 | rsz_set_common_params(void __iomem *rsz_base, struct resizer_params *params) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 68 | static void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 69 | rsz_set_rsz_regs(void __iomem *rsz_base, unsigned int rsz_id, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 */ |
| 173 | static void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 174 | ipipe_setup_resizer(void __iomem *rsz_base, struct resizer_params *params) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
Boris BREZILLON | 3336f07 | 2014-11-10 14:28:33 -0300 | [diff] [blame] | 199 | static u32 ipipe_get_color_pat(u32 pix) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 200 | { |
| 201 | switch (pix) { |
Boris BREZILLON | 3336f07 | 2014-11-10 14:28:33 -0300 | [diff] [blame] | 202 | case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: |
| 203 | case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: |
| 204 | case MEDIA_BUS_FMT_SGRBG12_1X12: |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 205 | return ipipe_sgrbg_pattern; |
| 206 | |
| 207 | default: |
| 208 | return ipipe_srggb_pattern; |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe) |
| 213 | { |
Boris BREZILLON | 3336f07 | 2014-11-10 14:28:33 -0300 | [diff] [blame] | 214 | u32 temp_pix_fmt; |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 215 | |
| 216 | switch (ipipe->formats[IPIPE_PAD_SINK].code) { |
Boris BREZILLON | 3336f07 | 2014-11-10 14:28:33 -0300 | [diff] [blame] | 217 | case MEDIA_BUS_FMT_SBGGR8_1X8: |
| 218 | case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: |
| 219 | case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: |
| 220 | case MEDIA_BUS_FMT_SGRBG12_1X12: |
| 221 | temp_pix_fmt = MEDIA_BUS_FMT_SGRBG12_1X12; |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 222 | break; |
| 223 | |
| 224 | default: |
Boris BREZILLON | 3336f07 | 2014-11-10 14:28:33 -0300 | [diff] [blame] | 225 | temp_pix_fmt = MEDIA_BUS_FMT_UYVY8_2X8; |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 226 | } |
| 227 | |
Boris BREZILLON | 3336f07 | 2014-11-10 14:28:33 -0300 | [diff] [blame] | 228 | if (temp_pix_fmt == MEDIA_BUS_FMT_SGRBG12_1X12) { |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 229 | if (ipipe->formats[IPIPE_PAD_SOURCE].code == |
Boris BREZILLON | 3336f07 | 2014-11-10 14:28:33 -0300 | [diff] [blame] | 230 | MEDIA_BUS_FMT_SGRBG12_1X12) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 231 | return IPIPE_RAW2RAW; |
| 232 | return IPIPE_RAW2YUV; |
| 233 | } |
| 234 | |
| 235 | return IPIPE_YUV2YUV; |
| 236 | } |
| 237 | |
| 238 | static 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 | |
| 251 | int 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); |
Levente Kurusa | 57802c5 | 2014-02-15 07:17:11 -0300 | [diff] [blame] | 270 | if (ipipe_mode < 0) { |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | */ |
| 301 | int config_rsz_hw(struct vpfe_resizer_device *resizer, |
| 302 | struct resizer_params *config) |
| 303 | { |
| 304 | struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 305 | void __iomem *ipipe_base = vpfe_dev->vpfe_ipipe.base_addr; |
| 306 | void __iomem *rsz_base = vpfe_dev->vpfe_resizer.base_addr; |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 317 | static void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 318 | rsz_set_y_address(void __iomem *rsz_base, unsigned int address, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 332 | static void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 333 | rsz_set_c_address(void __iomem *rsz_base, unsigned int address, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | */ |
| 354 | int |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 355 | resizer_set_outaddr(void __iomem *rsz_base, struct resizer_params *params, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 413 | void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 414 | ipipe_set_lutdpc_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 448 | static void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 449 | set_dpc_thresholds(void __iomem *base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 470 | void ipipe_set_otfdpc_regs(void __iomem *base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 */ |
| 525 | void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 526 | ipipe_set_d2f_regs(void __iomem *base_addr, unsigned int id, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 */ |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 574 | void ipipe_set_gic_regs(void __iomem *base_addr, struct vpfe_ipipe_gic *gic) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 */ |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 612 | void ipipe_set_wb_regs(void __iomem *base_addr, struct vpfe_ipipe_wb *wb) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 */ |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 638 | void ipipe_set_cfa_regs(void __iomem *base_addr, struct vpfe_ipipe_cfa *cfa) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 673 | void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 674 | ipipe_set_rgb2rgb_regs(void __iomem *base_addr, unsigned int id, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 726 | static void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 727 | ipipe_update_gamma_tbl(void __iomem *isp5_base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 740 | void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 741 | ipipe_set_gamma_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 772 | void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 773 | ipipe_set_3d_lut_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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; |
Lisa Nguyen | c324981 | 2013-10-28 18:23:34 -0300 | [diff] [blame] | 794 | for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) { |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 */ |
| 821 | void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 822 | ipipe_set_lum_adj_regs(void __iomem *base_addr, struct ipipe_lum_adj *lum_adj) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 837 | void ipipe_set_rgb2ycbcr_regs(void __iomem *base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 */ |
| 868 | void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 869 | ipipe_set_yuv422_conv_regs(void __iomem *base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 881 | void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 882 | ipipe_set_gbce_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
Lisa Nguyen | c324981 | 2013-10-28 18:23:34 -0300 | [diff] [blame] | 902 | for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; count += 2) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 908 | void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 909 | ipipe_set_ee_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 */ |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 953 | static void ipipe_set_mf(void __iomem *base_addr) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
| 961 | static void |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 962 | ipipe_set_gain_ctrl(void __iomem *base_addr, struct vpfe_ipipe_car *car) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 978 | void ipipe_set_car_regs(void __iomem *base_addr, struct vpfe_ipipe_car *car) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 */ |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 1013 | void ipipe_set_cgs_regs(void __iomem *base_addr, struct vpfe_ipipe_cgs *cgs) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 1028 | void rsz_src_enable(void __iomem *rsz_base, int enable) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 1029 | { |
| 1030 | regw_rsz(rsz_base, enable, RSZ_SRC_EN); |
| 1031 | } |
| 1032 | |
Tapasweni Pathak | 2129e17 | 2014-10-08 09:12:17 +0530 | [diff] [blame] | 1033 | int rsz_enable(void __iomem *rsz_base, int rsz_id, int enable) |
Manjunath Hadli | 26c0e99 | 2012-11-28 02:16:35 -0300 | [diff] [blame] | 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 | } |