1/* 2 * isppreview.c 3 * 4 * TI OMAP3 ISP driver - Preview module 5 * 6 * Copyright (C) 2010 Nokia Corporation 7 * Copyright (C) 2009 Texas Instruments, Inc. 8 * 9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com> 10 * Sakari Ailus <sakari.ailus@iki.fi> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 */ 16 17#include <linux/device.h> 18#include <linux/mm.h> 19#include <linux/module.h> 20#include <linux/mutex.h> 21#include <linux/uaccess.h> 22 23#include "isp.h" 24#include "ispreg.h" 25#include "isppreview.h" 26 27/* Default values in Office Fluorescent Light for RGBtoRGB Blending */ 28static struct omap3isp_prev_rgbtorgb flr_rgb2rgb = { 29 { /* RGB-RGB Matrix */ 30 {0x01E2, 0x0F30, 0x0FEE}, 31 {0x0F9B, 0x01AC, 0x0FB9}, 32 {0x0FE0, 0x0EC0, 0x0260} 33 }, /* RGB Offset */ 34 {0x0000, 0x0000, 0x0000} 35}; 36 37/* Default values in Office Fluorescent Light for RGB to YUV Conversion*/ 38static struct omap3isp_prev_csc flr_prev_csc = { 39 { /* CSC Coef Matrix */ 40 {66, 129, 25}, 41 {-38, -75, 112}, 42 {112, -94 , -18} 43 }, /* CSC Offset */ 44 {0x0, 0x0, 0x0} 45}; 46 47/* Default values in Office Fluorescent Light for CFA Gradient*/ 48#define FLR_CFA_GRADTHRS_HORZ 0x28 49#define FLR_CFA_GRADTHRS_VERT 0x28 50 51/* Default values in Office Fluorescent Light for Chroma Suppression*/ 52#define FLR_CSUP_GAIN 0x0D 53#define FLR_CSUP_THRES 0xEB 54 55/* Default values in Office Fluorescent Light for Noise Filter*/ 56#define FLR_NF_STRGTH 0x03 57 58/* Default values for White Balance */ 59#define FLR_WBAL_DGAIN 0x100 60#define FLR_WBAL_COEF 0x20 61 62/* Default values in Office Fluorescent Light for Black Adjustment*/ 63#define FLR_BLKADJ_BLUE 0x0 64#define FLR_BLKADJ_GREEN 0x0 65#define FLR_BLKADJ_RED 0x0 66 67#define DEF_DETECT_CORRECT_VAL 0xe 68 69/* 70 * Margins and image size limits. 71 * 72 * The preview engine crops several rows and columns internally depending on 73 * which filters are enabled. To avoid format changes when the filters are 74 * enabled or disabled (which would prevent them from being turned on or off 75 * during streaming), the driver assumes all filters that can be configured 76 * during streaming are enabled when computing sink crop and source format 77 * limits. 78 * 79 * If a filter is disabled, additional cropping is automatically added at the 80 * preview engine input by the driver to avoid overflow at line and frame end. 81 * This is completely transparent for applications. 82 * 83 * Median filter 4 pixels 84 * Noise filter, 85 * Faulty pixels correction 4 pixels, 4 lines 86 * Color suppression 2 pixels 87 * or luma enhancement 88 * ------------------------------------------------------------- 89 * Maximum total 10 pixels, 4 lines 90 * 91 * The color suppression and luma enhancement filters are applied after bayer to 92 * YUV conversion. They thus can crop one pixel on the left and one pixel on the 93 * right side of the image without changing the color pattern. When both those 94 * filters are disabled, the driver must crop the two pixels on the same side of 95 * the image to avoid changing the bayer pattern. The left margin is thus set to 96 * 6 pixels and the right margin to 4 pixels. 97 */ 98 99#define PREV_MARGIN_LEFT 6 100#define PREV_MARGIN_RIGHT 4 101#define PREV_MARGIN_TOP 2 102#define PREV_MARGIN_BOTTOM 2 103 104#define PREV_MIN_IN_WIDTH 64 105#define PREV_MIN_IN_HEIGHT 8 106#define PREV_MAX_IN_HEIGHT 16384 107 108#define PREV_MIN_OUT_WIDTH 0 109#define PREV_MIN_OUT_HEIGHT 0 110#define PREV_MAX_OUT_WIDTH_REV_1 1280 111#define PREV_MAX_OUT_WIDTH_REV_2 3300 112#define PREV_MAX_OUT_WIDTH_REV_15 4096 113 114/* 115 * Coefficient Tables for the submodules in Preview. 116 * Array is initialised with the values from.the tables text file. 117 */ 118 119/* 120 * CFA Filter Coefficient Table 121 * 122 */ 123static u32 cfa_coef_table[4][OMAP3ISP_PREV_CFA_BLK_SIZE] = { 124#include "cfa_coef_table.h" 125}; 126 127/* 128 * Default Gamma Correction Table - All components 129 */ 130static u32 gamma_table[] = { 131#include "gamma_table.h" 132}; 133 134/* 135 * Noise Filter Threshold table 136 */ 137static u32 noise_filter_table[] = { 138#include "noise_filter_table.h" 139}; 140 141/* 142 * Luminance Enhancement Table 143 */ 144static u32 luma_enhance_table[] = { 145#include "luma_enhance_table.h" 146}; 147 148/* 149 * preview_config_luma_enhancement - Configure the Luminance Enhancement table 150 */ 151static void 152preview_config_luma_enhancement(struct isp_prev_device *prev, 153 const struct prev_params *params) 154{ 155 struct isp_device *isp = to_isp_device(prev); 156 const struct omap3isp_prev_luma *yt = ¶ms->luma; 157 unsigned int i; 158 159 isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR, 160 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); 161 for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) { 162 isp_reg_writel(isp, yt->table[i], 163 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA); 164 } 165} 166 167/* 168 * preview_enable_luma_enhancement - Enable/disable Luminance Enhancement 169 */ 170static void 171preview_enable_luma_enhancement(struct isp_prev_device *prev, bool enable) 172{ 173 struct isp_device *isp = to_isp_device(prev); 174 175 if (enable) 176 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 177 ISPPRV_PCR_YNENHEN); 178 else 179 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 180 ISPPRV_PCR_YNENHEN); 181} 182 183/* 184 * preview_enable_invalaw - Enable/disable Inverse A-Law decompression 185 */ 186static void preview_enable_invalaw(struct isp_prev_device *prev, bool enable) 187{ 188 struct isp_device *isp = to_isp_device(prev); 189 190 if (enable) 191 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 192 ISPPRV_PCR_INVALAW); 193 else 194 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 195 ISPPRV_PCR_INVALAW); 196} 197 198/* 199 * preview_config_hmed - Configure the Horizontal Median Filter 200 */ 201static void preview_config_hmed(struct isp_prev_device *prev, 202 const struct prev_params *params) 203{ 204 struct isp_device *isp = to_isp_device(prev); 205 const struct omap3isp_prev_hmed *hmed = ¶ms->hmed; 206 207 isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) | 208 (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) | 209 (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT), 210 OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED); 211} 212 213/* 214 * preview_enable_hmed - Enable/disable the Horizontal Median Filter 215 */ 216static void preview_enable_hmed(struct isp_prev_device *prev, bool enable) 217{ 218 struct isp_device *isp = to_isp_device(prev); 219 220 if (enable) 221 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 222 ISPPRV_PCR_HMEDEN); 223 else 224 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 225 ISPPRV_PCR_HMEDEN); 226} 227 228/* 229 * preview_config_cfa - Configure CFA Interpolation for Bayer formats 230 * 231 * The CFA table is organised in four blocks, one per Bayer component. The 232 * hardware expects blocks to follow the Bayer order of the input data, while 233 * the driver stores the table in GRBG order in memory. The blocks need to be 234 * reordered to support non-GRBG Bayer patterns. 235 */ 236static void preview_config_cfa(struct isp_prev_device *prev, 237 const struct prev_params *params) 238{ 239 static const unsigned int cfa_coef_order[4][4] = { 240 { 0, 1, 2, 3 }, /* GRBG */ 241 { 1, 0, 3, 2 }, /* RGGB */ 242 { 2, 3, 0, 1 }, /* BGGR */ 243 { 3, 2, 1, 0 }, /* GBRG */ 244 }; 245 const unsigned int *order = cfa_coef_order[prev->params.cfa_order]; 246 const struct omap3isp_prev_cfa *cfa = ¶ms->cfa; 247 struct isp_device *isp = to_isp_device(prev); 248 unsigned int i; 249 unsigned int j; 250 251 isp_reg_writel(isp, 252 (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) | 253 (cfa->gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT), 254 OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA); 255 256 isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR, 257 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); 258 259 for (i = 0; i < 4; ++i) { 260 const __u32 *block = cfa->table[order[i]]; 261 262 for (j = 0; j < OMAP3ISP_PREV_CFA_BLK_SIZE; ++j) 263 isp_reg_writel(isp, block[j], OMAP3_ISP_IOMEM_PREV, 264 ISPPRV_SET_TBL_DATA); 265 } 266} 267 268/* 269 * preview_config_chroma_suppression - Configure Chroma Suppression 270 */ 271static void 272preview_config_chroma_suppression(struct isp_prev_device *prev, 273 const struct prev_params *params) 274{ 275 struct isp_device *isp = to_isp_device(prev); 276 const struct omap3isp_prev_csup *cs = ¶ms->csup; 277 278 isp_reg_writel(isp, 279 cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) | 280 (cs->hypf_en << ISPPRV_CSUP_HPYF_SHIFT), 281 OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP); 282} 283 284/* 285 * preview_enable_chroma_suppression - Enable/disable Chrominance Suppression 286 */ 287static void 288preview_enable_chroma_suppression(struct isp_prev_device *prev, bool enable) 289{ 290 struct isp_device *isp = to_isp_device(prev); 291 292 if (enable) 293 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 294 ISPPRV_PCR_SUPEN); 295 else 296 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 297 ISPPRV_PCR_SUPEN); 298} 299 300/* 301 * preview_config_whitebalance - Configure White Balance parameters 302 * 303 * Coefficient matrix always with default values. 304 */ 305static void 306preview_config_whitebalance(struct isp_prev_device *prev, 307 const struct prev_params *params) 308{ 309 struct isp_device *isp = to_isp_device(prev); 310 const struct omap3isp_prev_wbal *wbal = ¶ms->wbal; 311 u32 val; 312 313 isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN); 314 315 val = wbal->coef0 << ISPPRV_WBGAIN_COEF0_SHIFT; 316 val |= wbal->coef1 << ISPPRV_WBGAIN_COEF1_SHIFT; 317 val |= wbal->coef2 << ISPPRV_WBGAIN_COEF2_SHIFT; 318 val |= wbal->coef3 << ISPPRV_WBGAIN_COEF3_SHIFT; 319 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN); 320 321 isp_reg_writel(isp, 322 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT | 323 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT | 324 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT | 325 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT | 326 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT | 327 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT | 328 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT | 329 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT | 330 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT | 331 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT | 332 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT | 333 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT | 334 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT | 335 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT | 336 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT | 337 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT, 338 OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL); 339} 340 341/* 342 * preview_config_blkadj - Configure Black Adjustment 343 */ 344static void 345preview_config_blkadj(struct isp_prev_device *prev, 346 const struct prev_params *params) 347{ 348 struct isp_device *isp = to_isp_device(prev); 349 const struct omap3isp_prev_blkadj *blkadj = ¶ms->blkadj; 350 351 isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) | 352 (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) | 353 (blkadj->red << ISPPRV_BLKADJOFF_R_SHIFT), 354 OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF); 355} 356 357/* 358 * preview_config_rgb_blending - Configure RGB-RGB Blending 359 */ 360static void 361preview_config_rgb_blending(struct isp_prev_device *prev, 362 const struct prev_params *params) 363{ 364 struct isp_device *isp = to_isp_device(prev); 365 const struct omap3isp_prev_rgbtorgb *rgbrgb = ¶ms->rgb2rgb; 366 u32 val; 367 368 val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT; 369 val |= (rgbrgb->matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT; 370 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1); 371 372 val = (rgbrgb->matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT; 373 val |= (rgbrgb->matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT; 374 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2); 375 376 val = (rgbrgb->matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT; 377 val |= (rgbrgb->matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT; 378 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3); 379 380 val = (rgbrgb->matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT; 381 val |= (rgbrgb->matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT; 382 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4); 383 384 val = (rgbrgb->matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT; 385 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5); 386 387 val = (rgbrgb->offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT; 388 val |= (rgbrgb->offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT; 389 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1); 390 391 val = (rgbrgb->offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT; 392 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2); 393} 394 395/* 396 * preview_config_csc - Configure Color Space Conversion (RGB to YCbYCr) 397 */ 398static void 399preview_config_csc(struct isp_prev_device *prev, 400 const struct prev_params *params) 401{ 402 struct isp_device *isp = to_isp_device(prev); 403 const struct omap3isp_prev_csc *csc = ¶ms->csc; 404 u32 val; 405 406 val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT; 407 val |= (csc->matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT; 408 val |= (csc->matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT; 409 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0); 410 411 val = (csc->matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT; 412 val |= (csc->matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT; 413 val |= (csc->matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT; 414 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1); 415 416 val = (csc->matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT; 417 val |= (csc->matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT; 418 val |= (csc->matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT; 419 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2); 420 421 val = (csc->offset[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT; 422 val |= (csc->offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT; 423 val |= (csc->offset[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT; 424 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET); 425} 426 427/* 428 * preview_config_yc_range - Configure the max and min Y and C values 429 */ 430static void 431preview_config_yc_range(struct isp_prev_device *prev, 432 const struct prev_params *params) 433{ 434 struct isp_device *isp = to_isp_device(prev); 435 const struct omap3isp_prev_yclimit *yc = ¶ms->yclimit; 436 437 isp_reg_writel(isp, 438 yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT | 439 yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT | 440 yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT | 441 yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT, 442 OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC); 443} 444 445/* 446 * preview_config_dcor - Configure Couplet Defect Correction 447 */ 448static void 449preview_config_dcor(struct isp_prev_device *prev, 450 const struct prev_params *params) 451{ 452 struct isp_device *isp = to_isp_device(prev); 453 const struct omap3isp_prev_dcor *dcor = ¶ms->dcor; 454 455 isp_reg_writel(isp, dcor->detect_correct[0], 456 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0); 457 isp_reg_writel(isp, dcor->detect_correct[1], 458 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1); 459 isp_reg_writel(isp, dcor->detect_correct[2], 460 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2); 461 isp_reg_writel(isp, dcor->detect_correct[3], 462 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3); 463 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 464 ISPPRV_PCR_DCCOUP, 465 dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0); 466} 467 468/* 469 * preview_enable_dcor - Enable/disable Couplet Defect Correction 470 */ 471static void preview_enable_dcor(struct isp_prev_device *prev, bool enable) 472{ 473 struct isp_device *isp = to_isp_device(prev); 474 475 if (enable) 476 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 477 ISPPRV_PCR_DCOREN); 478 else 479 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 480 ISPPRV_PCR_DCOREN); 481} 482 483/* 484 * preview_enable_drkframe_capture - Enable/disable Dark Frame Capture 485 */ 486static void 487preview_enable_drkframe_capture(struct isp_prev_device *prev, bool enable) 488{ 489 struct isp_device *isp = to_isp_device(prev); 490 491 if (enable) 492 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 493 ISPPRV_PCR_DRKFCAP); 494 else 495 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 496 ISPPRV_PCR_DRKFCAP); 497} 498 499/* 500 * preview_enable_drkframe - Enable/disable Dark Frame Subtraction 501 */ 502static void preview_enable_drkframe(struct isp_prev_device *prev, bool enable) 503{ 504 struct isp_device *isp = to_isp_device(prev); 505 506 if (enable) 507 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 508 ISPPRV_PCR_DRKFEN); 509 else 510 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 511 ISPPRV_PCR_DRKFEN); 512} 513 514/* 515 * preview_config_noisefilter - Configure the Noise Filter 516 */ 517static void 518preview_config_noisefilter(struct isp_prev_device *prev, 519 const struct prev_params *params) 520{ 521 struct isp_device *isp = to_isp_device(prev); 522 const struct omap3isp_prev_nf *nf = ¶ms->nf; 523 unsigned int i; 524 525 isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF); 526 isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR, 527 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); 528 for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) { 529 isp_reg_writel(isp, nf->table[i], 530 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA); 531 } 532} 533 534/* 535 * preview_enable_noisefilter - Enable/disable the Noise Filter 536 */ 537static void 538preview_enable_noisefilter(struct isp_prev_device *prev, bool enable) 539{ 540 struct isp_device *isp = to_isp_device(prev); 541 542 if (enable) 543 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 544 ISPPRV_PCR_NFEN); 545 else 546 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 547 ISPPRV_PCR_NFEN); 548} 549 550/* 551 * preview_config_gammacorrn - Configure the Gamma Correction tables 552 */ 553static void 554preview_config_gammacorrn(struct isp_prev_device *prev, 555 const struct prev_params *params) 556{ 557 struct isp_device *isp = to_isp_device(prev); 558 const struct omap3isp_prev_gtables *gt = ¶ms->gamma; 559 unsigned int i; 560 561 isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR, 562 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); 563 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++) 564 isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV, 565 ISPPRV_SET_TBL_DATA); 566 567 isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR, 568 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); 569 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++) 570 isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV, 571 ISPPRV_SET_TBL_DATA); 572 573 isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR, 574 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); 575 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++) 576 isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV, 577 ISPPRV_SET_TBL_DATA); 578} 579 580/* 581 * preview_enable_gammacorrn - Enable/disable Gamma Correction 582 * 583 * When gamma correction is disabled, the module is bypassed and its output is 584 * the 8 MSB of the 10-bit input . 585 */ 586static void 587preview_enable_gammacorrn(struct isp_prev_device *prev, bool enable) 588{ 589 struct isp_device *isp = to_isp_device(prev); 590 591 if (enable) 592 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 593 ISPPRV_PCR_GAMMA_BYPASS); 594 else 595 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 596 ISPPRV_PCR_GAMMA_BYPASS); 597} 598 599/* 600 * preview_config_contrast - Configure the Contrast 601 * 602 * Value should be programmed before enabling the module. 603 */ 604static void 605preview_config_contrast(struct isp_prev_device *prev, 606 const struct prev_params *params) 607{ 608 struct isp_device *isp = to_isp_device(prev); 609 610 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, 611 0xff << ISPPRV_CNT_BRT_CNT_SHIFT, 612 params->contrast << ISPPRV_CNT_BRT_CNT_SHIFT); 613} 614 615/* 616 * preview_config_brightness - Configure the Brightness 617 */ 618static void 619preview_config_brightness(struct isp_prev_device *prev, 620 const struct prev_params *params) 621{ 622 struct isp_device *isp = to_isp_device(prev); 623 624 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, 625 0xff << ISPPRV_CNT_BRT_BRT_SHIFT, 626 params->brightness << ISPPRV_CNT_BRT_BRT_SHIFT); 627} 628 629/* 630 * preview_update_contrast - Updates the contrast. 631 * @contrast: Pointer to hold the current programmed contrast value. 632 * 633 * Value should be programmed before enabling the module. 634 */ 635static void 636preview_update_contrast(struct isp_prev_device *prev, u8 contrast) 637{ 638 struct prev_params *params; 639 unsigned long flags; 640 641 spin_lock_irqsave(&prev->params.lock, flags); 642 params = (prev->params.active & OMAP3ISP_PREV_CONTRAST) 643 ? &prev->params.params[0] : &prev->params.params[1]; 644 645 if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) { 646 params->contrast = contrast * ISPPRV_CONTRAST_UNITS; 647 params->update |= OMAP3ISP_PREV_CONTRAST; 648 } 649 spin_unlock_irqrestore(&prev->params.lock, flags); 650} 651 652/* 653 * preview_update_brightness - Updates the brightness in preview module. 654 * @brightness: Pointer to hold the current programmed brightness value. 655 * 656 */ 657static void 658preview_update_brightness(struct isp_prev_device *prev, u8 brightness) 659{ 660 struct prev_params *params; 661 unsigned long flags; 662 663 spin_lock_irqsave(&prev->params.lock, flags); 664 params = (prev->params.active & OMAP3ISP_PREV_BRIGHTNESS) 665 ? &prev->params.params[0] : &prev->params.params[1]; 666 667 if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) { 668 params->brightness = brightness * ISPPRV_BRIGHT_UNITS; 669 params->update |= OMAP3ISP_PREV_BRIGHTNESS; 670 } 671 spin_unlock_irqrestore(&prev->params.lock, flags); 672} 673 674static u32 675preview_params_lock(struct isp_prev_device *prev, u32 update, bool shadow) 676{ 677 u32 active = prev->params.active; 678 679 if (shadow) { 680 /* Mark all shadow parameters we are going to touch as busy. */ 681 prev->params.params[0].busy |= ~active & update; 682 prev->params.params[1].busy |= active & update; 683 } else { 684 /* Mark all active parameters we are going to touch as busy. */ 685 update = (prev->params.params[0].update & active) 686 | (prev->params.params[1].update & ~active); 687 688 prev->params.params[0].busy |= active & update; 689 prev->params.params[1].busy |= ~active & update; 690 } 691 692 return update; 693} 694 695static void 696preview_params_unlock(struct isp_prev_device *prev, u32 update, bool shadow) 697{ 698 u32 active = prev->params.active; 699 700 if (shadow) { 701 /* Set the update flag for shadow parameters that have been 702 * updated and clear the busy flag for all shadow parameters. 703 */ 704 prev->params.params[0].update |= (~active & update); 705 prev->params.params[1].update |= (active & update); 706 prev->params.params[0].busy &= active; 707 prev->params.params[1].busy &= ~active; 708 } else { 709 /* Clear the update flag for active parameters that have been 710 * applied and the busy flag for all active parameters. 711 */ 712 prev->params.params[0].update &= ~(active & update); 713 prev->params.params[1].update &= ~(~active & update); 714 prev->params.params[0].busy &= ~active; 715 prev->params.params[1].busy &= active; 716 } 717} 718 719static void preview_params_switch(struct isp_prev_device *prev) 720{ 721 u32 to_switch; 722 723 /* Switch active parameters with updated shadow parameters when the 724 * shadow parameter has been updated and neither the active not the 725 * shadow parameter is busy. 726 */ 727 to_switch = (prev->params.params[0].update & ~prev->params.active) 728 | (prev->params.params[1].update & prev->params.active); 729 to_switch &= ~(prev->params.params[0].busy | 730 prev->params.params[1].busy); 731 if (to_switch == 0) 732 return; 733 734 prev->params.active ^= to_switch; 735 736 /* Remove the update flag for the shadow copy of parameters we have 737 * switched. 738 */ 739 prev->params.params[0].update &= ~(~prev->params.active & to_switch); 740 prev->params.params[1].update &= ~(prev->params.active & to_switch); 741} 742 743/* preview parameters update structure */ 744struct preview_update { 745 void (*config)(struct isp_prev_device *, const struct prev_params *); 746 void (*enable)(struct isp_prev_device *, bool); 747 unsigned int param_offset; 748 unsigned int param_size; 749 unsigned int config_offset; 750 bool skip; 751}; 752 753/* Keep the array indexed by the OMAP3ISP_PREV_* bit number. */ 754static const struct preview_update update_attrs[] = { 755 /* OMAP3ISP_PREV_LUMAENH */ { 756 preview_config_luma_enhancement, 757 preview_enable_luma_enhancement, 758 offsetof(struct prev_params, luma), 759 FIELD_SIZEOF(struct prev_params, luma), 760 offsetof(struct omap3isp_prev_update_config, luma), 761 }, /* OMAP3ISP_PREV_INVALAW */ { 762 NULL, 763 preview_enable_invalaw, 764 }, /* OMAP3ISP_PREV_HRZ_MED */ { 765 preview_config_hmed, 766 preview_enable_hmed, 767 offsetof(struct prev_params, hmed), 768 FIELD_SIZEOF(struct prev_params, hmed), 769 offsetof(struct omap3isp_prev_update_config, hmed), 770 }, /* OMAP3ISP_PREV_CFA */ { 771 preview_config_cfa, 772 NULL, 773 offsetof(struct prev_params, cfa), 774 FIELD_SIZEOF(struct prev_params, cfa), 775 offsetof(struct omap3isp_prev_update_config, cfa), 776 }, /* OMAP3ISP_PREV_CHROMA_SUPP */ { 777 preview_config_chroma_suppression, 778 preview_enable_chroma_suppression, 779 offsetof(struct prev_params, csup), 780 FIELD_SIZEOF(struct prev_params, csup), 781 offsetof(struct omap3isp_prev_update_config, csup), 782 }, /* OMAP3ISP_PREV_WB */ { 783 preview_config_whitebalance, 784 NULL, 785 offsetof(struct prev_params, wbal), 786 FIELD_SIZEOF(struct prev_params, wbal), 787 offsetof(struct omap3isp_prev_update_config, wbal), 788 }, /* OMAP3ISP_PREV_BLKADJ */ { 789 preview_config_blkadj, 790 NULL, 791 offsetof(struct prev_params, blkadj), 792 FIELD_SIZEOF(struct prev_params, blkadj), 793 offsetof(struct omap3isp_prev_update_config, blkadj), 794 }, /* OMAP3ISP_PREV_RGB2RGB */ { 795 preview_config_rgb_blending, 796 NULL, 797 offsetof(struct prev_params, rgb2rgb), 798 FIELD_SIZEOF(struct prev_params, rgb2rgb), 799 offsetof(struct omap3isp_prev_update_config, rgb2rgb), 800 }, /* OMAP3ISP_PREV_COLOR_CONV */ { 801 preview_config_csc, 802 NULL, 803 offsetof(struct prev_params, csc), 804 FIELD_SIZEOF(struct prev_params, csc), 805 offsetof(struct omap3isp_prev_update_config, csc), 806 }, /* OMAP3ISP_PREV_YC_LIMIT */ { 807 preview_config_yc_range, 808 NULL, 809 offsetof(struct prev_params, yclimit), 810 FIELD_SIZEOF(struct prev_params, yclimit), 811 offsetof(struct omap3isp_prev_update_config, yclimit), 812 }, /* OMAP3ISP_PREV_DEFECT_COR */ { 813 preview_config_dcor, 814 preview_enable_dcor, 815 offsetof(struct prev_params, dcor), 816 FIELD_SIZEOF(struct prev_params, dcor), 817 offsetof(struct omap3isp_prev_update_config, dcor), 818 }, /* Previously OMAP3ISP_PREV_GAMMABYPASS, not used anymore */ { 819 NULL, 820 NULL, 821 }, /* OMAP3ISP_PREV_DRK_FRM_CAPTURE */ { 822 NULL, 823 preview_enable_drkframe_capture, 824 }, /* OMAP3ISP_PREV_DRK_FRM_SUBTRACT */ { 825 NULL, 826 preview_enable_drkframe, 827 }, /* OMAP3ISP_PREV_LENS_SHADING */ { 828 NULL, 829 preview_enable_drkframe, 830 }, /* OMAP3ISP_PREV_NF */ { 831 preview_config_noisefilter, 832 preview_enable_noisefilter, 833 offsetof(struct prev_params, nf), 834 FIELD_SIZEOF(struct prev_params, nf), 835 offsetof(struct omap3isp_prev_update_config, nf), 836 }, /* OMAP3ISP_PREV_GAMMA */ { 837 preview_config_gammacorrn, 838 preview_enable_gammacorrn, 839 offsetof(struct prev_params, gamma), 840 FIELD_SIZEOF(struct prev_params, gamma), 841 offsetof(struct omap3isp_prev_update_config, gamma), 842 }, /* OMAP3ISP_PREV_CONTRAST */ { 843 preview_config_contrast, 844 NULL, 845 0, 0, 0, true, 846 }, /* OMAP3ISP_PREV_BRIGHTNESS */ { 847 preview_config_brightness, 848 NULL, 849 0, 0, 0, true, 850 }, 851}; 852 853/* 854 * preview_config - Copy and update local structure with userspace preview 855 * configuration. 856 * @prev: ISP preview engine 857 * @cfg: Configuration 858 * 859 * Return zero if success or -EFAULT if the configuration can't be copied from 860 * userspace. 861 */ 862static int preview_config(struct isp_prev_device *prev, 863 struct omap3isp_prev_update_config *cfg) 864{ 865 unsigned long flags; 866 unsigned int i; 867 int rval = 0; 868 u32 update; 869 u32 active; 870 871 if (cfg->update == 0) 872 return 0; 873 874 /* Mark the shadow parameters we're going to update as busy. */ 875 spin_lock_irqsave(&prev->params.lock, flags); 876 preview_params_lock(prev, cfg->update, true); 877 active = prev->params.active; 878 spin_unlock_irqrestore(&prev->params.lock, flags); 879 880 update = 0; 881 882 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) { 883 const struct preview_update *attr = &update_attrs[i]; 884 struct prev_params *params; 885 unsigned int bit = 1 << i; 886 887 if (attr->skip || !(cfg->update & bit)) 888 continue; 889 890 params = &prev->params.params[!!(active & bit)]; 891 892 if (cfg->flag & bit) { 893 void __user *from = *(void * __user *) 894 ((void *)cfg + attr->config_offset); 895 void *to = (void *)params + attr->param_offset; 896 size_t size = attr->param_size; 897 898 if (to && from && size) { 899 if (copy_from_user(to, from, size)) { 900 rval = -EFAULT; 901 break; 902 } 903 } 904 params->features |= bit; 905 } else { 906 params->features &= ~bit; 907 } 908 909 update |= bit; 910 } 911 912 spin_lock_irqsave(&prev->params.lock, flags); 913 preview_params_unlock(prev, update, true); 914 preview_params_switch(prev); 915 spin_unlock_irqrestore(&prev->params.lock, flags); 916 917 return rval; 918} 919 920/* 921 * preview_setup_hw - Setup preview registers and/or internal memory 922 * @prev: pointer to preview private structure 923 * @update: Bitmask of parameters to setup 924 * @active: Bitmask of parameters active in set 0 925 * Note: can be called from interrupt context 926 * Return none 927 */ 928static void preview_setup_hw(struct isp_prev_device *prev, u32 update, 929 u32 active) 930{ 931 unsigned int i; 932 u32 features; 933 934 if (update == 0) 935 return; 936 937 features = (prev->params.params[0].features & active) 938 | (prev->params.params[1].features & ~active); 939 940 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) { 941 const struct preview_update *attr = &update_attrs[i]; 942 struct prev_params *params; 943 unsigned int bit = 1 << i; 944 945 if (!(update & bit)) 946 continue; 947 948 params = &prev->params.params[!(active & bit)]; 949 950 if (params->features & bit) { 951 if (attr->config) 952 attr->config(prev, params); 953 if (attr->enable) 954 attr->enable(prev, true); 955 } else { 956 if (attr->enable) 957 attr->enable(prev, false); 958 } 959 } 960} 961 962/* 963 * preview_config_ycpos - Configure byte layout of YUV image. 964 * @prev: pointer to previewer private structure 965 * @pixelcode: pixel code 966 */ 967static void preview_config_ycpos(struct isp_prev_device *prev, u32 pixelcode) 968{ 969 struct isp_device *isp = to_isp_device(prev); 970 enum preview_ycpos_mode mode; 971 972 switch (pixelcode) { 973 case MEDIA_BUS_FMT_YUYV8_1X16: 974 mode = YCPOS_CrYCbY; 975 break; 976 case MEDIA_BUS_FMT_UYVY8_1X16: 977 mode = YCPOS_YCrYCb; 978 break; 979 default: 980 return; 981 } 982 983 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 984 ISPPRV_PCR_YCPOS_CrYCbY, 985 mode << ISPPRV_PCR_YCPOS_SHIFT); 986} 987 988/* 989 * preview_config_averager - Enable / disable / configure averager 990 * @average: Average value to be configured. 991 */ 992static void preview_config_averager(struct isp_prev_device *prev, u8 average) 993{ 994 struct isp_device *isp = to_isp_device(prev); 995 996 isp_reg_writel(isp, ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT | 997 ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT | 998 average, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE); 999} 1000 1001 1002/* 1003 * preview_config_input_format - Configure the input format 1004 * @prev: The preview engine 1005 * @info: Sink pad format information 1006 * 1007 * Enable and configure CFA interpolation for Bayer formats and disable it for 1008 * greyscale formats. 1009 * 1010 * The CFA table is organised in four blocks, one per Bayer component. The 1011 * hardware expects blocks to follow the Bayer order of the input data, while 1012 * the driver stores the table in GRBG order in memory. The blocks need to be 1013 * reordered to support non-GRBG Bayer patterns. 1014 */ 1015static void preview_config_input_format(struct isp_prev_device *prev, 1016 const struct isp_format_info *info) 1017{ 1018 struct isp_device *isp = to_isp_device(prev); 1019 struct prev_params *params; 1020 1021 if (info->width == 8) 1022 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1023 ISPPRV_PCR_WIDTH); 1024 else 1025 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1026 ISPPRV_PCR_WIDTH); 1027 1028 switch (info->flavor) { 1029 case MEDIA_BUS_FMT_SGRBG8_1X8: 1030 prev->params.cfa_order = 0; 1031 break; 1032 case MEDIA_BUS_FMT_SRGGB8_1X8: 1033 prev->params.cfa_order = 1; 1034 break; 1035 case MEDIA_BUS_FMT_SBGGR8_1X8: 1036 prev->params.cfa_order = 2; 1037 break; 1038 case MEDIA_BUS_FMT_SGBRG8_1X8: 1039 prev->params.cfa_order = 3; 1040 break; 1041 default: 1042 /* Disable CFA for non-Bayer formats. */ 1043 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1044 ISPPRV_PCR_CFAEN); 1045 return; 1046 } 1047 1048 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN); 1049 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1050 ISPPRV_PCR_CFAFMT_MASK, ISPPRV_PCR_CFAFMT_BAYER); 1051 1052 params = (prev->params.active & OMAP3ISP_PREV_CFA) 1053 ? &prev->params.params[0] : &prev->params.params[1]; 1054 1055 preview_config_cfa(prev, params); 1056} 1057 1058/* 1059 * preview_config_input_size - Configure the input frame size 1060 * 1061 * The preview engine crops several rows and columns internally depending on 1062 * which processing blocks are enabled. The driver assumes all those blocks are 1063 * enabled when reporting source pad formats to userspace. If this assumption is 1064 * not true, rows and columns must be manually cropped at the preview engine 1065 * input to avoid overflows at the end of lines and frames. 1066 * 1067 * See the explanation at the PREV_MARGIN_* definitions for more details. 1068 */ 1069static void preview_config_input_size(struct isp_prev_device *prev, u32 active) 1070{ 1071 const struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK]; 1072 struct isp_device *isp = to_isp_device(prev); 1073 unsigned int sph = prev->crop.left; 1074 unsigned int eph = prev->crop.left + prev->crop.width - 1; 1075 unsigned int slv = prev->crop.top; 1076 unsigned int elv = prev->crop.top + prev->crop.height - 1; 1077 u32 features; 1078 1079 if (format->code != MEDIA_BUS_FMT_Y8_1X8 && 1080 format->code != MEDIA_BUS_FMT_Y10_1X10) { 1081 sph -= 2; 1082 eph += 2; 1083 slv -= 2; 1084 elv += 2; 1085 } 1086 1087 features = (prev->params.params[0].features & active) 1088 | (prev->params.params[1].features & ~active); 1089 1090 if (features & (OMAP3ISP_PREV_DEFECT_COR | OMAP3ISP_PREV_NF)) { 1091 sph -= 2; 1092 eph += 2; 1093 slv -= 2; 1094 elv += 2; 1095 } 1096 if (features & OMAP3ISP_PREV_HRZ_MED) { 1097 sph -= 2; 1098 eph += 2; 1099 } 1100 if (features & (OMAP3ISP_PREV_CHROMA_SUPP | OMAP3ISP_PREV_LUMAENH)) 1101 sph -= 2; 1102 1103 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph, 1104 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO); 1105 isp_reg_writel(isp, (slv << ISPPRV_VERT_INFO_SLV_SHIFT) | elv, 1106 OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO); 1107} 1108 1109/* 1110 * preview_config_inlineoffset - Configures the Read address line offset. 1111 * @prev: Preview module 1112 * @offset: Line offset 1113 * 1114 * According to the TRM, the line offset must be aligned on a 32 bytes boundary. 1115 * However, a hardware bug requires the memory start address to be aligned on a 1116 * 64 bytes boundary, so the offset probably should be aligned on 64 bytes as 1117 * well. 1118 */ 1119static void 1120preview_config_inlineoffset(struct isp_prev_device *prev, u32 offset) 1121{ 1122 struct isp_device *isp = to_isp_device(prev); 1123 1124 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV, 1125 ISPPRV_RADR_OFFSET); 1126} 1127 1128/* 1129 * preview_set_inaddr - Sets memory address of input frame. 1130 * @addr: 32bit memory address aligned on 32byte boundary. 1131 * 1132 * Configures the memory address from which the input frame is to be read. 1133 */ 1134static void preview_set_inaddr(struct isp_prev_device *prev, u32 addr) 1135{ 1136 struct isp_device *isp = to_isp_device(prev); 1137 1138 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR); 1139} 1140 1141/* 1142 * preview_config_outlineoffset - Configures the Write address line offset. 1143 * @offset: Line Offset for the preview output. 1144 * 1145 * The offset must be a multiple of 32 bytes. 1146 */ 1147static void preview_config_outlineoffset(struct isp_prev_device *prev, 1148 u32 offset) 1149{ 1150 struct isp_device *isp = to_isp_device(prev); 1151 1152 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV, 1153 ISPPRV_WADD_OFFSET); 1154} 1155 1156/* 1157 * preview_set_outaddr - Sets the memory address to store output frame 1158 * @addr: 32bit memory address aligned on 32byte boundary. 1159 * 1160 * Configures the memory address to which the output frame is written. 1161 */ 1162static void preview_set_outaddr(struct isp_prev_device *prev, u32 addr) 1163{ 1164 struct isp_device *isp = to_isp_device(prev); 1165 1166 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR); 1167} 1168 1169static void preview_adjust_bandwidth(struct isp_prev_device *prev) 1170{ 1171 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity); 1172 struct isp_device *isp = to_isp_device(prev); 1173 const struct v4l2_mbus_framefmt *ifmt = &prev->formats[PREV_PAD_SINK]; 1174 unsigned long l3_ick = pipe->l3_ick; 1175 struct v4l2_fract *timeperframe; 1176 unsigned int cycles_per_frame; 1177 unsigned int requests_per_frame; 1178 unsigned int cycles_per_request; 1179 unsigned int minimum; 1180 unsigned int maximum; 1181 unsigned int value; 1182 1183 if (prev->input != PREVIEW_INPUT_MEMORY) { 1184 isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP, 1185 ISPSBL_SDR_REQ_PRV_EXP_MASK); 1186 return; 1187 } 1188 1189 /* Compute the minimum number of cycles per request, based on the 1190 * pipeline maximum data rate. This is an absolute lower bound if we 1191 * don't want SBL overflows, so round the value up. 1192 */ 1193 cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1, 1194 pipe->max_rate); 1195 minimum = DIV_ROUND_UP(cycles_per_request, 32); 1196 1197 /* Compute the maximum number of cycles per request, based on the 1198 * requested frame rate. This is a soft upper bound to achieve a frame 1199 * rate equal or higher than the requested value, so round the value 1200 * down. 1201 */ 1202 timeperframe = &pipe->max_timeperframe; 1203 1204 requests_per_frame = DIV_ROUND_UP(ifmt->width * 2, 256) * ifmt->height; 1205 cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator, 1206 timeperframe->denominator); 1207 cycles_per_request = cycles_per_frame / requests_per_frame; 1208 1209 maximum = cycles_per_request / 32; 1210 1211 value = max(minimum, maximum); 1212 1213 dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value); 1214 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP, 1215 ISPSBL_SDR_REQ_PRV_EXP_MASK, 1216 value << ISPSBL_SDR_REQ_PRV_EXP_SHIFT); 1217} 1218 1219/* 1220 * omap3isp_preview_busy - Gets busy state of preview module. 1221 */ 1222int omap3isp_preview_busy(struct isp_prev_device *prev) 1223{ 1224 struct isp_device *isp = to_isp_device(prev); 1225 1226 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR) 1227 & ISPPRV_PCR_BUSY; 1228} 1229 1230/* 1231 * omap3isp_preview_restore_context - Restores the values of preview registers 1232 */ 1233void omap3isp_preview_restore_context(struct isp_device *isp) 1234{ 1235 struct isp_prev_device *prev = &isp->isp_prev; 1236 const u32 update = OMAP3ISP_PREV_FEATURES_END - 1; 1237 1238 prev->params.params[0].update = prev->params.active & update; 1239 prev->params.params[1].update = ~prev->params.active & update; 1240 1241 preview_setup_hw(prev, update, prev->params.active); 1242 1243 prev->params.params[0].update = 0; 1244 prev->params.params[1].update = 0; 1245} 1246 1247/* 1248 * preview_print_status - Dump preview module registers to the kernel log 1249 */ 1250#define PREV_PRINT_REGISTER(isp, name)\ 1251 dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \ 1252 isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name)) 1253 1254static void preview_print_status(struct isp_prev_device *prev) 1255{ 1256 struct isp_device *isp = to_isp_device(prev); 1257 1258 dev_dbg(isp->dev, "-------------Preview Register dump----------\n"); 1259 1260 PREV_PRINT_REGISTER(isp, PCR); 1261 PREV_PRINT_REGISTER(isp, HORZ_INFO); 1262 PREV_PRINT_REGISTER(isp, VERT_INFO); 1263 PREV_PRINT_REGISTER(isp, RSDR_ADDR); 1264 PREV_PRINT_REGISTER(isp, RADR_OFFSET); 1265 PREV_PRINT_REGISTER(isp, DSDR_ADDR); 1266 PREV_PRINT_REGISTER(isp, DRKF_OFFSET); 1267 PREV_PRINT_REGISTER(isp, WSDR_ADDR); 1268 PREV_PRINT_REGISTER(isp, WADD_OFFSET); 1269 PREV_PRINT_REGISTER(isp, AVE); 1270 PREV_PRINT_REGISTER(isp, HMED); 1271 PREV_PRINT_REGISTER(isp, NF); 1272 PREV_PRINT_REGISTER(isp, WB_DGAIN); 1273 PREV_PRINT_REGISTER(isp, WBGAIN); 1274 PREV_PRINT_REGISTER(isp, WBSEL); 1275 PREV_PRINT_REGISTER(isp, CFA); 1276 PREV_PRINT_REGISTER(isp, BLKADJOFF); 1277 PREV_PRINT_REGISTER(isp, RGB_MAT1); 1278 PREV_PRINT_REGISTER(isp, RGB_MAT2); 1279 PREV_PRINT_REGISTER(isp, RGB_MAT3); 1280 PREV_PRINT_REGISTER(isp, RGB_MAT4); 1281 PREV_PRINT_REGISTER(isp, RGB_MAT5); 1282 PREV_PRINT_REGISTER(isp, RGB_OFF1); 1283 PREV_PRINT_REGISTER(isp, RGB_OFF2); 1284 PREV_PRINT_REGISTER(isp, CSC0); 1285 PREV_PRINT_REGISTER(isp, CSC1); 1286 PREV_PRINT_REGISTER(isp, CSC2); 1287 PREV_PRINT_REGISTER(isp, CSC_OFFSET); 1288 PREV_PRINT_REGISTER(isp, CNT_BRT); 1289 PREV_PRINT_REGISTER(isp, CSUP); 1290 PREV_PRINT_REGISTER(isp, SETUP_YC); 1291 PREV_PRINT_REGISTER(isp, SET_TBL_ADDR); 1292 PREV_PRINT_REGISTER(isp, CDC_THR0); 1293 PREV_PRINT_REGISTER(isp, CDC_THR1); 1294 PREV_PRINT_REGISTER(isp, CDC_THR2); 1295 PREV_PRINT_REGISTER(isp, CDC_THR3); 1296 1297 dev_dbg(isp->dev, "--------------------------------------------\n"); 1298} 1299 1300/* 1301 * preview_init_params - init image processing parameters. 1302 * @prev: pointer to previewer private structure 1303 */ 1304static void preview_init_params(struct isp_prev_device *prev) 1305{ 1306 struct prev_params *params; 1307 unsigned int i; 1308 1309 spin_lock_init(&prev->params.lock); 1310 1311 prev->params.active = ~0; 1312 prev->params.params[0].busy = 0; 1313 prev->params.params[0].update = OMAP3ISP_PREV_FEATURES_END - 1; 1314 prev->params.params[1].busy = 0; 1315 prev->params.params[1].update = 0; 1316 1317 params = &prev->params.params[0]; 1318 1319 /* Init values */ 1320 params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS; 1321 params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS; 1322 params->cfa.format = OMAP3ISP_CFAFMT_BAYER; 1323 memcpy(params->cfa.table, cfa_coef_table, 1324 sizeof(params->cfa.table)); 1325 params->cfa.gradthrs_horz = FLR_CFA_GRADTHRS_HORZ; 1326 params->cfa.gradthrs_vert = FLR_CFA_GRADTHRS_VERT; 1327 params->csup.gain = FLR_CSUP_GAIN; 1328 params->csup.thres = FLR_CSUP_THRES; 1329 params->csup.hypf_en = 0; 1330 memcpy(params->luma.table, luma_enhance_table, 1331 sizeof(params->luma.table)); 1332 params->nf.spread = FLR_NF_STRGTH; 1333 memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table)); 1334 params->dcor.couplet_mode_en = 1; 1335 for (i = 0; i < OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS; i++) 1336 params->dcor.detect_correct[i] = DEF_DETECT_CORRECT_VAL; 1337 memcpy(params->gamma.blue, gamma_table, sizeof(params->gamma.blue)); 1338 memcpy(params->gamma.green, gamma_table, sizeof(params->gamma.green)); 1339 memcpy(params->gamma.red, gamma_table, sizeof(params->gamma.red)); 1340 params->wbal.dgain = FLR_WBAL_DGAIN; 1341 params->wbal.coef0 = FLR_WBAL_COEF; 1342 params->wbal.coef1 = FLR_WBAL_COEF; 1343 params->wbal.coef2 = FLR_WBAL_COEF; 1344 params->wbal.coef3 = FLR_WBAL_COEF; 1345 params->blkadj.red = FLR_BLKADJ_RED; 1346 params->blkadj.green = FLR_BLKADJ_GREEN; 1347 params->blkadj.blue = FLR_BLKADJ_BLUE; 1348 params->rgb2rgb = flr_rgb2rgb; 1349 params->csc = flr_prev_csc; 1350 params->yclimit.minC = ISPPRV_YC_MIN; 1351 params->yclimit.maxC = ISPPRV_YC_MAX; 1352 params->yclimit.minY = ISPPRV_YC_MIN; 1353 params->yclimit.maxY = ISPPRV_YC_MAX; 1354 1355 params->features = OMAP3ISP_PREV_CFA | OMAP3ISP_PREV_DEFECT_COR 1356 | OMAP3ISP_PREV_NF | OMAP3ISP_PREV_GAMMA 1357 | OMAP3ISP_PREV_BLKADJ | OMAP3ISP_PREV_YC_LIMIT 1358 | OMAP3ISP_PREV_RGB2RGB | OMAP3ISP_PREV_COLOR_CONV 1359 | OMAP3ISP_PREV_WB | OMAP3ISP_PREV_BRIGHTNESS 1360 | OMAP3ISP_PREV_CONTRAST; 1361} 1362 1363/* 1364 * preview_max_out_width - Handle previewer hardware output limitations 1365 * @prev: pointer to previewer private structure 1366 * returns maximum width output for current isp revision 1367 */ 1368static unsigned int preview_max_out_width(struct isp_prev_device *prev) 1369{ 1370 struct isp_device *isp = to_isp_device(prev); 1371 1372 switch (isp->revision) { 1373 case ISP_REVISION_1_0: 1374 return PREV_MAX_OUT_WIDTH_REV_1; 1375 1376 case ISP_REVISION_2_0: 1377 default: 1378 return PREV_MAX_OUT_WIDTH_REV_2; 1379 1380 case ISP_REVISION_15_0: 1381 return PREV_MAX_OUT_WIDTH_REV_15; 1382 } 1383} 1384 1385static void preview_configure(struct isp_prev_device *prev) 1386{ 1387 struct isp_device *isp = to_isp_device(prev); 1388 const struct isp_format_info *info; 1389 struct v4l2_mbus_framefmt *format; 1390 unsigned long flags; 1391 u32 update; 1392 u32 active; 1393 1394 spin_lock_irqsave(&prev->params.lock, flags); 1395 /* Mark all active parameters we are going to touch as busy. */ 1396 update = preview_params_lock(prev, 0, false); 1397 active = prev->params.active; 1398 spin_unlock_irqrestore(&prev->params.lock, flags); 1399 1400 /* PREV_PAD_SINK */ 1401 format = &prev->formats[PREV_PAD_SINK]; 1402 info = omap3isp_video_format_info(format->code); 1403 1404 preview_adjust_bandwidth(prev); 1405 1406 preview_config_input_format(prev, info); 1407 preview_config_input_size(prev, active); 1408 1409 if (prev->input == PREVIEW_INPUT_CCDC) 1410 preview_config_inlineoffset(prev, 0); 1411 else 1412 preview_config_inlineoffset(prev, ALIGN(format->width, 0x20) * 1413 info->bpp); 1414 1415 preview_setup_hw(prev, update, active); 1416 1417 /* PREV_PAD_SOURCE */ 1418 format = &prev->formats[PREV_PAD_SOURCE]; 1419 1420 if (prev->output & PREVIEW_OUTPUT_MEMORY) 1421 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1422 ISPPRV_PCR_SDRPORT); 1423 else 1424 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1425 ISPPRV_PCR_SDRPORT); 1426 1427 if (prev->output & PREVIEW_OUTPUT_RESIZER) 1428 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1429 ISPPRV_PCR_RSZPORT); 1430 else 1431 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1432 ISPPRV_PCR_RSZPORT); 1433 1434 if (prev->output & PREVIEW_OUTPUT_MEMORY) 1435 preview_config_outlineoffset(prev, 1436 ALIGN(format->width, 0x10) * 2); 1437 1438 preview_config_averager(prev, 0); 1439 preview_config_ycpos(prev, format->code); 1440 1441 spin_lock_irqsave(&prev->params.lock, flags); 1442 preview_params_unlock(prev, update, false); 1443 spin_unlock_irqrestore(&prev->params.lock, flags); 1444} 1445 1446/* ----------------------------------------------------------------------------- 1447 * Interrupt handling 1448 */ 1449 1450static void preview_enable_oneshot(struct isp_prev_device *prev) 1451{ 1452 struct isp_device *isp = to_isp_device(prev); 1453 1454 /* The PCR.SOURCE bit is automatically reset to 0 when the PCR.ENABLE 1455 * bit is set. As the preview engine is used in single-shot mode, we 1456 * need to set PCR.SOURCE before enabling the preview engine. 1457 */ 1458 if (prev->input == PREVIEW_INPUT_MEMORY) 1459 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1460 ISPPRV_PCR_SOURCE); 1461 1462 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 1463 ISPPRV_PCR_EN | ISPPRV_PCR_ONESHOT); 1464} 1465 1466void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev) 1467{ 1468 /* 1469 * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun 1470 * condition, the module was paused and now we have a buffer queued 1471 * on the output again. Restart the pipeline if running in continuous 1472 * mode. 1473 */ 1474 if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS && 1475 prev->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) { 1476 preview_enable_oneshot(prev); 1477 isp_video_dmaqueue_flags_clr(&prev->video_out); 1478 } 1479} 1480 1481static void preview_isr_buffer(struct isp_prev_device *prev) 1482{ 1483 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity); 1484 struct isp_buffer *buffer; 1485 int restart = 0; 1486 1487 if (prev->input == PREVIEW_INPUT_MEMORY) { 1488 buffer = omap3isp_video_buffer_next(&prev->video_in); 1489 if (buffer != NULL) 1490 preview_set_inaddr(prev, buffer->dma); 1491 pipe->state |= ISP_PIPELINE_IDLE_INPUT; 1492 } 1493 1494 if (prev->output & PREVIEW_OUTPUT_MEMORY) { 1495 buffer = omap3isp_video_buffer_next(&prev->video_out); 1496 if (buffer != NULL) { 1497 preview_set_outaddr(prev, buffer->dma); 1498 restart = 1; 1499 } 1500 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; 1501 } 1502 1503 switch (prev->state) { 1504 case ISP_PIPELINE_STREAM_SINGLESHOT: 1505 if (isp_pipeline_ready(pipe)) 1506 omap3isp_pipeline_set_stream(pipe, 1507 ISP_PIPELINE_STREAM_SINGLESHOT); 1508 break; 1509 1510 case ISP_PIPELINE_STREAM_CONTINUOUS: 1511 /* If an underrun occurs, the video queue operation handler will 1512 * restart the preview engine. Otherwise restart it immediately. 1513 */ 1514 if (restart) 1515 preview_enable_oneshot(prev); 1516 break; 1517 1518 case ISP_PIPELINE_STREAM_STOPPED: 1519 default: 1520 return; 1521 } 1522} 1523 1524/* 1525 * omap3isp_preview_isr - ISP preview engine interrupt handler 1526 * 1527 * Manage the preview engine video buffers and configure shadowed registers. 1528 */ 1529void omap3isp_preview_isr(struct isp_prev_device *prev) 1530{ 1531 unsigned long flags; 1532 u32 update; 1533 u32 active; 1534 1535 if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping)) 1536 return; 1537 1538 spin_lock_irqsave(&prev->params.lock, flags); 1539 preview_params_switch(prev); 1540 update = preview_params_lock(prev, 0, false); 1541 active = prev->params.active; 1542 spin_unlock_irqrestore(&prev->params.lock, flags); 1543 1544 preview_setup_hw(prev, update, active); 1545 preview_config_input_size(prev, active); 1546 1547 if (prev->input == PREVIEW_INPUT_MEMORY || 1548 prev->output & PREVIEW_OUTPUT_MEMORY) 1549 preview_isr_buffer(prev); 1550 else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS) 1551 preview_enable_oneshot(prev); 1552 1553 spin_lock_irqsave(&prev->params.lock, flags); 1554 preview_params_unlock(prev, update, false); 1555 spin_unlock_irqrestore(&prev->params.lock, flags); 1556} 1557 1558/* ----------------------------------------------------------------------------- 1559 * ISP video operations 1560 */ 1561 1562static int preview_video_queue(struct isp_video *video, 1563 struct isp_buffer *buffer) 1564{ 1565 struct isp_prev_device *prev = &video->isp->isp_prev; 1566 1567 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 1568 preview_set_inaddr(prev, buffer->dma); 1569 1570 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1571 preview_set_outaddr(prev, buffer->dma); 1572 1573 return 0; 1574} 1575 1576static const struct isp_video_operations preview_video_ops = { 1577 .queue = preview_video_queue, 1578}; 1579 1580/* ----------------------------------------------------------------------------- 1581 * V4L2 subdev operations 1582 */ 1583 1584/* 1585 * preview_s_ctrl - Handle set control subdev method 1586 * @ctrl: pointer to v4l2 control structure 1587 */ 1588static int preview_s_ctrl(struct v4l2_ctrl *ctrl) 1589{ 1590 struct isp_prev_device *prev = 1591 container_of(ctrl->handler, struct isp_prev_device, ctrls); 1592 1593 switch (ctrl->id) { 1594 case V4L2_CID_BRIGHTNESS: 1595 preview_update_brightness(prev, ctrl->val); 1596 break; 1597 case V4L2_CID_CONTRAST: 1598 preview_update_contrast(prev, ctrl->val); 1599 break; 1600 } 1601 1602 return 0; 1603} 1604 1605static const struct v4l2_ctrl_ops preview_ctrl_ops = { 1606 .s_ctrl = preview_s_ctrl, 1607}; 1608 1609/* 1610 * preview_ioctl - Handle preview module private ioctl's 1611 * @sd: pointer to v4l2 subdev structure 1612 * @cmd: configuration command 1613 * @arg: configuration argument 1614 * return -EINVAL or zero on success 1615 */ 1616static long preview_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) 1617{ 1618 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 1619 1620 switch (cmd) { 1621 case VIDIOC_OMAP3ISP_PRV_CFG: 1622 return preview_config(prev, arg); 1623 1624 default: 1625 return -ENOIOCTLCMD; 1626 } 1627} 1628 1629/* 1630 * preview_set_stream - Enable/Disable streaming on preview subdev 1631 * @sd : pointer to v4l2 subdev structure 1632 * @enable: 1 == Enable, 0 == Disable 1633 * return -EINVAL or zero on success 1634 */ 1635static int preview_set_stream(struct v4l2_subdev *sd, int enable) 1636{ 1637 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 1638 struct isp_video *video_out = &prev->video_out; 1639 struct isp_device *isp = to_isp_device(prev); 1640 struct device *dev = to_device(prev); 1641 1642 if (prev->state == ISP_PIPELINE_STREAM_STOPPED) { 1643 if (enable == ISP_PIPELINE_STREAM_STOPPED) 1644 return 0; 1645 1646 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW); 1647 preview_configure(prev); 1648 atomic_set(&prev->stopping, 0); 1649 preview_print_status(prev); 1650 } 1651 1652 switch (enable) { 1653 case ISP_PIPELINE_STREAM_CONTINUOUS: 1654 if (prev->output & PREVIEW_OUTPUT_MEMORY) 1655 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE); 1656 1657 if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED || 1658 !(prev->output & PREVIEW_OUTPUT_MEMORY)) 1659 preview_enable_oneshot(prev); 1660 1661 isp_video_dmaqueue_flags_clr(video_out); 1662 break; 1663 1664 case ISP_PIPELINE_STREAM_SINGLESHOT: 1665 if (prev->input == PREVIEW_INPUT_MEMORY) 1666 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_READ); 1667 if (prev->output & PREVIEW_OUTPUT_MEMORY) 1668 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE); 1669 1670 preview_enable_oneshot(prev); 1671 break; 1672 1673 case ISP_PIPELINE_STREAM_STOPPED: 1674 if (omap3isp_module_sync_idle(&sd->entity, &prev->wait, 1675 &prev->stopping)) 1676 dev_dbg(dev, "%s: stop timeout.\n", sd->name); 1677 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ); 1678 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE); 1679 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW); 1680 isp_video_dmaqueue_flags_clr(video_out); 1681 break; 1682 } 1683 1684 prev->state = enable; 1685 return 0; 1686} 1687 1688static struct v4l2_mbus_framefmt * 1689__preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_pad_config *cfg, 1690 unsigned int pad, enum v4l2_subdev_format_whence which) 1691{ 1692 if (which == V4L2_SUBDEV_FORMAT_TRY) 1693 return v4l2_subdev_get_try_format(&prev->subdev, cfg, pad); 1694 else 1695 return &prev->formats[pad]; 1696} 1697 1698static struct v4l2_rect * 1699__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_pad_config *cfg, 1700 enum v4l2_subdev_format_whence which) 1701{ 1702 if (which == V4L2_SUBDEV_FORMAT_TRY) 1703 return v4l2_subdev_get_try_crop(&prev->subdev, cfg, PREV_PAD_SINK); 1704 else 1705 return &prev->crop; 1706} 1707 1708/* previewer format descriptions */ 1709static const unsigned int preview_input_fmts[] = { 1710 MEDIA_BUS_FMT_Y8_1X8, 1711 MEDIA_BUS_FMT_SGRBG8_1X8, 1712 MEDIA_BUS_FMT_SRGGB8_1X8, 1713 MEDIA_BUS_FMT_SBGGR8_1X8, 1714 MEDIA_BUS_FMT_SGBRG8_1X8, 1715 MEDIA_BUS_FMT_Y10_1X10, 1716 MEDIA_BUS_FMT_SGRBG10_1X10, 1717 MEDIA_BUS_FMT_SRGGB10_1X10, 1718 MEDIA_BUS_FMT_SBGGR10_1X10, 1719 MEDIA_BUS_FMT_SGBRG10_1X10, 1720}; 1721 1722static const unsigned int preview_output_fmts[] = { 1723 MEDIA_BUS_FMT_UYVY8_1X16, 1724 MEDIA_BUS_FMT_YUYV8_1X16, 1725}; 1726 1727/* 1728 * preview_try_format - Validate a format 1729 * @prev: ISP preview engine 1730 * @cfg: V4L2 subdev pad configuration 1731 * @pad: pad number 1732 * @fmt: format to be validated 1733 * @which: try/active format selector 1734 * 1735 * Validate and adjust the given format for the given pad based on the preview 1736 * engine limits and the format and crop rectangles on other pads. 1737 */ 1738static void preview_try_format(struct isp_prev_device *prev, 1739 struct v4l2_subdev_pad_config *cfg, unsigned int pad, 1740 struct v4l2_mbus_framefmt *fmt, 1741 enum v4l2_subdev_format_whence which) 1742{ 1743 u32 pixelcode; 1744 struct v4l2_rect *crop; 1745 unsigned int i; 1746 1747 switch (pad) { 1748 case PREV_PAD_SINK: 1749 /* When reading data from the CCDC, the input size has already 1750 * been mangled by the CCDC output pad so it can be accepted 1751 * as-is. 1752 * 1753 * When reading data from memory, clamp the requested width and 1754 * height. The TRM doesn't specify a minimum input height, make 1755 * sure we got enough lines to enable the noise filter and color 1756 * filter array interpolation. 1757 */ 1758 if (prev->input == PREVIEW_INPUT_MEMORY) { 1759 fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH, 1760 preview_max_out_width(prev)); 1761 fmt->height = clamp_t(u32, fmt->height, 1762 PREV_MIN_IN_HEIGHT, 1763 PREV_MAX_IN_HEIGHT); 1764 } 1765 1766 fmt->colorspace = V4L2_COLORSPACE_SRGB; 1767 1768 for (i = 0; i < ARRAY_SIZE(preview_input_fmts); i++) { 1769 if (fmt->code == preview_input_fmts[i]) 1770 break; 1771 } 1772 1773 /* If not found, use SGRBG10 as default */ 1774 if (i >= ARRAY_SIZE(preview_input_fmts)) 1775 fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; 1776 break; 1777 1778 case PREV_PAD_SOURCE: 1779 pixelcode = fmt->code; 1780 *fmt = *__preview_get_format(prev, cfg, PREV_PAD_SINK, which); 1781 1782 switch (pixelcode) { 1783 case MEDIA_BUS_FMT_YUYV8_1X16: 1784 case MEDIA_BUS_FMT_UYVY8_1X16: 1785 fmt->code = pixelcode; 1786 break; 1787 1788 default: 1789 fmt->code = MEDIA_BUS_FMT_YUYV8_1X16; 1790 break; 1791 } 1792 1793 /* The preview module output size is configurable through the 1794 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). This 1795 * is not supported yet, hardcode the output size to the crop 1796 * rectangle size. 1797 */ 1798 crop = __preview_get_crop(prev, cfg, which); 1799 fmt->width = crop->width; 1800 fmt->height = crop->height; 1801 1802 fmt->colorspace = V4L2_COLORSPACE_JPEG; 1803 break; 1804 } 1805 1806 fmt->field = V4L2_FIELD_NONE; 1807} 1808 1809/* 1810 * preview_try_crop - Validate a crop rectangle 1811 * @prev: ISP preview engine 1812 * @sink: format on the sink pad 1813 * @crop: crop rectangle to be validated 1814 * 1815 * The preview engine crops lines and columns for its internal operation, 1816 * depending on which filters are enabled. Enforce minimum crop margins to 1817 * handle that transparently for userspace. 1818 * 1819 * See the explanation at the PREV_MARGIN_* definitions for more details. 1820 */ 1821static void preview_try_crop(struct isp_prev_device *prev, 1822 const struct v4l2_mbus_framefmt *sink, 1823 struct v4l2_rect *crop) 1824{ 1825 unsigned int left = PREV_MARGIN_LEFT; 1826 unsigned int right = sink->width - PREV_MARGIN_RIGHT; 1827 unsigned int top = PREV_MARGIN_TOP; 1828 unsigned int bottom = sink->height - PREV_MARGIN_BOTTOM; 1829 1830 /* When processing data on-the-fly from the CCDC, at least 2 pixels must 1831 * be cropped from the left and right sides of the image. As we don't 1832 * know which filters will be enabled, increase the left and right 1833 * margins by two. 1834 */ 1835 if (prev->input == PREVIEW_INPUT_CCDC) { 1836 left += 2; 1837 right -= 2; 1838 } 1839 1840 /* The CFA filter crops 4 lines and 4 columns in Bayer mode, and 2 lines 1841 * and no columns in other modes. Increase the margins based on the sink 1842 * format. 1843 */ 1844 if (sink->code != MEDIA_BUS_FMT_Y8_1X8 && 1845 sink->code != MEDIA_BUS_FMT_Y10_1X10) { 1846 left += 2; 1847 right -= 2; 1848 top += 2; 1849 bottom -= 2; 1850 } 1851 1852 /* Restrict left/top to even values to keep the Bayer pattern. */ 1853 crop->left &= ~1; 1854 crop->top &= ~1; 1855 1856 crop->left = clamp_t(u32, crop->left, left, right - PREV_MIN_OUT_WIDTH); 1857 crop->top = clamp_t(u32, crop->top, top, bottom - PREV_MIN_OUT_HEIGHT); 1858 crop->width = clamp_t(u32, crop->width, PREV_MIN_OUT_WIDTH, 1859 right - crop->left); 1860 crop->height = clamp_t(u32, crop->height, PREV_MIN_OUT_HEIGHT, 1861 bottom - crop->top); 1862} 1863 1864/* 1865 * preview_enum_mbus_code - Handle pixel format enumeration 1866 * @sd : pointer to v4l2 subdev structure 1867 * @cfg: V4L2 subdev pad configuration 1868 * @code : pointer to v4l2_subdev_mbus_code_enum structure 1869 * return -EINVAL or zero on success 1870 */ 1871static int preview_enum_mbus_code(struct v4l2_subdev *sd, 1872 struct v4l2_subdev_pad_config *cfg, 1873 struct v4l2_subdev_mbus_code_enum *code) 1874{ 1875 switch (code->pad) { 1876 case PREV_PAD_SINK: 1877 if (code->index >= ARRAY_SIZE(preview_input_fmts)) 1878 return -EINVAL; 1879 1880 code->code = preview_input_fmts[code->index]; 1881 break; 1882 case PREV_PAD_SOURCE: 1883 if (code->index >= ARRAY_SIZE(preview_output_fmts)) 1884 return -EINVAL; 1885 1886 code->code = preview_output_fmts[code->index]; 1887 break; 1888 default: 1889 return -EINVAL; 1890 } 1891 1892 return 0; 1893} 1894 1895static int preview_enum_frame_size(struct v4l2_subdev *sd, 1896 struct v4l2_subdev_pad_config *cfg, 1897 struct v4l2_subdev_frame_size_enum *fse) 1898{ 1899 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 1900 struct v4l2_mbus_framefmt format; 1901 1902 if (fse->index != 0) 1903 return -EINVAL; 1904 1905 format.code = fse->code; 1906 format.width = 1; 1907 format.height = 1; 1908 preview_try_format(prev, cfg, fse->pad, &format, fse->which); 1909 fse->min_width = format.width; 1910 fse->min_height = format.height; 1911 1912 if (format.code != fse->code) 1913 return -EINVAL; 1914 1915 format.code = fse->code; 1916 format.width = -1; 1917 format.height = -1; 1918 preview_try_format(prev, cfg, fse->pad, &format, fse->which); 1919 fse->max_width = format.width; 1920 fse->max_height = format.height; 1921 1922 return 0; 1923} 1924 1925/* 1926 * preview_get_selection - Retrieve a selection rectangle on a pad 1927 * @sd: ISP preview V4L2 subdevice 1928 * @cfg: V4L2 subdev pad configuration 1929 * @sel: Selection rectangle 1930 * 1931 * The only supported rectangles are the crop rectangles on the sink pad. 1932 * 1933 * Return 0 on success or a negative error code otherwise. 1934 */ 1935static int preview_get_selection(struct v4l2_subdev *sd, 1936 struct v4l2_subdev_pad_config *cfg, 1937 struct v4l2_subdev_selection *sel) 1938{ 1939 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 1940 struct v4l2_mbus_framefmt *format; 1941 1942 if (sel->pad != PREV_PAD_SINK) 1943 return -EINVAL; 1944 1945 switch (sel->target) { 1946 case V4L2_SEL_TGT_CROP_BOUNDS: 1947 sel->r.left = 0; 1948 sel->r.top = 0; 1949 sel->r.width = INT_MAX; 1950 sel->r.height = INT_MAX; 1951 1952 format = __preview_get_format(prev, cfg, PREV_PAD_SINK, 1953 sel->which); 1954 preview_try_crop(prev, format, &sel->r); 1955 break; 1956 1957 case V4L2_SEL_TGT_CROP: 1958 sel->r = *__preview_get_crop(prev, cfg, sel->which); 1959 break; 1960 1961 default: 1962 return -EINVAL; 1963 } 1964 1965 return 0; 1966} 1967 1968/* 1969 * preview_set_selection - Set a selection rectangle on a pad 1970 * @sd: ISP preview V4L2 subdevice 1971 * @cfg: V4L2 subdev pad configuration 1972 * @sel: Selection rectangle 1973 * 1974 * The only supported rectangle is the actual crop rectangle on the sink pad. 1975 * 1976 * Return 0 on success or a negative error code otherwise. 1977 */ 1978static int preview_set_selection(struct v4l2_subdev *sd, 1979 struct v4l2_subdev_pad_config *cfg, 1980 struct v4l2_subdev_selection *sel) 1981{ 1982 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 1983 struct v4l2_mbus_framefmt *format; 1984 1985 if (sel->target != V4L2_SEL_TGT_CROP || 1986 sel->pad != PREV_PAD_SINK) 1987 return -EINVAL; 1988 1989 /* The crop rectangle can't be changed while streaming. */ 1990 if (prev->state != ISP_PIPELINE_STREAM_STOPPED) 1991 return -EBUSY; 1992 1993 /* Modifying the crop rectangle always changes the format on the source 1994 * pad. If the KEEP_CONFIG flag is set, just return the current crop 1995 * rectangle. 1996 */ 1997 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) { 1998 sel->r = *__preview_get_crop(prev, cfg, sel->which); 1999 return 0; 2000 } 2001 2002 format = __preview_get_format(prev, cfg, PREV_PAD_SINK, sel->which); 2003 preview_try_crop(prev, format, &sel->r); 2004 *__preview_get_crop(prev, cfg, sel->which) = sel->r; 2005 2006 /* Update the source format. */ 2007 format = __preview_get_format(prev, cfg, PREV_PAD_SOURCE, sel->which); 2008 preview_try_format(prev, cfg, PREV_PAD_SOURCE, format, sel->which); 2009 2010 return 0; 2011} 2012 2013/* 2014 * preview_get_format - Handle get format by pads subdev method 2015 * @sd : pointer to v4l2 subdev structure 2016 * @cfg: V4L2 subdev pad configuration 2017 * @fmt: pointer to v4l2 subdev format structure 2018 * return -EINVAL or zero on success 2019 */ 2020static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, 2021 struct v4l2_subdev_format *fmt) 2022{ 2023 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 2024 struct v4l2_mbus_framefmt *format; 2025 2026 format = __preview_get_format(prev, cfg, fmt->pad, fmt->which); 2027 if (format == NULL) 2028 return -EINVAL; 2029 2030 fmt->format = *format; 2031 return 0; 2032} 2033 2034/* 2035 * preview_set_format - Handle set format by pads subdev method 2036 * @sd : pointer to v4l2 subdev structure 2037 * @cfg: V4L2 subdev pad configuration 2038 * @fmt: pointer to v4l2 subdev format structure 2039 * return -EINVAL or zero on success 2040 */ 2041static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, 2042 struct v4l2_subdev_format *fmt) 2043{ 2044 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 2045 struct v4l2_mbus_framefmt *format; 2046 struct v4l2_rect *crop; 2047 2048 format = __preview_get_format(prev, cfg, fmt->pad, fmt->which); 2049 if (format == NULL) 2050 return -EINVAL; 2051 2052 preview_try_format(prev, cfg, fmt->pad, &fmt->format, fmt->which); 2053 *format = fmt->format; 2054 2055 /* Propagate the format from sink to source */ 2056 if (fmt->pad == PREV_PAD_SINK) { 2057 /* Reset the crop rectangle. */ 2058 crop = __preview_get_crop(prev, cfg, fmt->which); 2059 crop->left = 0; 2060 crop->top = 0; 2061 crop->width = fmt->format.width; 2062 crop->height = fmt->format.height; 2063 2064 preview_try_crop(prev, &fmt->format, crop); 2065 2066 /* Update the source format. */ 2067 format = __preview_get_format(prev, cfg, PREV_PAD_SOURCE, 2068 fmt->which); 2069 preview_try_format(prev, cfg, PREV_PAD_SOURCE, format, 2070 fmt->which); 2071 } 2072 2073 return 0; 2074} 2075 2076/* 2077 * preview_init_formats - Initialize formats on all pads 2078 * @sd: ISP preview V4L2 subdevice 2079 * @fh: V4L2 subdev file handle 2080 * 2081 * Initialize all pad formats with default values. If fh is not NULL, try 2082 * formats are initialized on the file handle. Otherwise active formats are 2083 * initialized on the device. 2084 */ 2085static int preview_init_formats(struct v4l2_subdev *sd, 2086 struct v4l2_subdev_fh *fh) 2087{ 2088 struct v4l2_subdev_format format; 2089 2090 memset(&format, 0, sizeof(format)); 2091 format.pad = PREV_PAD_SINK; 2092 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; 2093 format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10; 2094 format.format.width = 4096; 2095 format.format.height = 4096; 2096 preview_set_format(sd, fh ? fh->pad : NULL, &format); 2097 2098 return 0; 2099} 2100 2101/* subdev core operations */ 2102static const struct v4l2_subdev_core_ops preview_v4l2_core_ops = { 2103 .ioctl = preview_ioctl, 2104}; 2105 2106/* subdev video operations */ 2107static const struct v4l2_subdev_video_ops preview_v4l2_video_ops = { 2108 .s_stream = preview_set_stream, 2109}; 2110 2111/* subdev pad operations */ 2112static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = { 2113 .enum_mbus_code = preview_enum_mbus_code, 2114 .enum_frame_size = preview_enum_frame_size, 2115 .get_fmt = preview_get_format, 2116 .set_fmt = preview_set_format, 2117 .get_selection = preview_get_selection, 2118 .set_selection = preview_set_selection, 2119}; 2120 2121/* subdev operations */ 2122static const struct v4l2_subdev_ops preview_v4l2_ops = { 2123 .core = &preview_v4l2_core_ops, 2124 .video = &preview_v4l2_video_ops, 2125 .pad = &preview_v4l2_pad_ops, 2126}; 2127 2128/* subdev internal operations */ 2129static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops = { 2130 .open = preview_init_formats, 2131}; 2132 2133/* ----------------------------------------------------------------------------- 2134 * Media entity operations 2135 */ 2136 2137/* 2138 * preview_link_setup - Setup previewer connections. 2139 * @entity : Pointer to media entity structure 2140 * @local : Pointer to local pad array 2141 * @remote : Pointer to remote pad array 2142 * @flags : Link flags 2143 * return -EINVAL or zero on success 2144 */ 2145static int preview_link_setup(struct media_entity *entity, 2146 const struct media_pad *local, 2147 const struct media_pad *remote, u32 flags) 2148{ 2149 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); 2150 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 2151 2152 switch (local->index | media_entity_type(remote->entity)) { 2153 case PREV_PAD_SINK | MEDIA_ENT_T_DEVNODE: 2154 /* read from memory */ 2155 if (flags & MEDIA_LNK_FL_ENABLED) { 2156 if (prev->input == PREVIEW_INPUT_CCDC) 2157 return -EBUSY; 2158 prev->input = PREVIEW_INPUT_MEMORY; 2159 } else { 2160 if (prev->input == PREVIEW_INPUT_MEMORY) 2161 prev->input = PREVIEW_INPUT_NONE; 2162 } 2163 break; 2164 2165 case PREV_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: 2166 /* read from ccdc */ 2167 if (flags & MEDIA_LNK_FL_ENABLED) { 2168 if (prev->input == PREVIEW_INPUT_MEMORY) 2169 return -EBUSY; 2170 prev->input = PREVIEW_INPUT_CCDC; 2171 } else { 2172 if (prev->input == PREVIEW_INPUT_CCDC) 2173 prev->input = PREVIEW_INPUT_NONE; 2174 } 2175 break; 2176 2177 /* 2178 * The ISP core doesn't support pipelines with multiple video outputs. 2179 * Revisit this when it will be implemented, and return -EBUSY for now. 2180 */ 2181 2182 case PREV_PAD_SOURCE | MEDIA_ENT_T_DEVNODE: 2183 /* write to memory */ 2184 if (flags & MEDIA_LNK_FL_ENABLED) { 2185 if (prev->output & ~PREVIEW_OUTPUT_MEMORY) 2186 return -EBUSY; 2187 prev->output |= PREVIEW_OUTPUT_MEMORY; 2188 } else { 2189 prev->output &= ~PREVIEW_OUTPUT_MEMORY; 2190 } 2191 break; 2192 2193 case PREV_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: 2194 /* write to resizer */ 2195 if (flags & MEDIA_LNK_FL_ENABLED) { 2196 if (prev->output & ~PREVIEW_OUTPUT_RESIZER) 2197 return -EBUSY; 2198 prev->output |= PREVIEW_OUTPUT_RESIZER; 2199 } else { 2200 prev->output &= ~PREVIEW_OUTPUT_RESIZER; 2201 } 2202 break; 2203 2204 default: 2205 return -EINVAL; 2206 } 2207 2208 return 0; 2209} 2210 2211/* media operations */ 2212static const struct media_entity_operations preview_media_ops = { 2213 .link_setup = preview_link_setup, 2214 .link_validate = v4l2_subdev_link_validate, 2215}; 2216 2217void omap3isp_preview_unregister_entities(struct isp_prev_device *prev) 2218{ 2219 v4l2_device_unregister_subdev(&prev->subdev); 2220 omap3isp_video_unregister(&prev->video_in); 2221 omap3isp_video_unregister(&prev->video_out); 2222} 2223 2224int omap3isp_preview_register_entities(struct isp_prev_device *prev, 2225 struct v4l2_device *vdev) 2226{ 2227 int ret; 2228 2229 /* Register the subdev and video nodes. */ 2230 ret = v4l2_device_register_subdev(vdev, &prev->subdev); 2231 if (ret < 0) 2232 goto error; 2233 2234 ret = omap3isp_video_register(&prev->video_in, vdev); 2235 if (ret < 0) 2236 goto error; 2237 2238 ret = omap3isp_video_register(&prev->video_out, vdev); 2239 if (ret < 0) 2240 goto error; 2241 2242 return 0; 2243 2244error: 2245 omap3isp_preview_unregister_entities(prev); 2246 return ret; 2247} 2248 2249/* ----------------------------------------------------------------------------- 2250 * ISP previewer initialisation and cleanup 2251 */ 2252 2253/* 2254 * preview_init_entities - Initialize subdev and media entity. 2255 * @prev : Pointer to preview structure 2256 * return -ENOMEM or zero on success 2257 */ 2258static int preview_init_entities(struct isp_prev_device *prev) 2259{ 2260 struct v4l2_subdev *sd = &prev->subdev; 2261 struct media_pad *pads = prev->pads; 2262 struct media_entity *me = &sd->entity; 2263 int ret; 2264 2265 prev->input = PREVIEW_INPUT_NONE; 2266 2267 v4l2_subdev_init(sd, &preview_v4l2_ops); 2268 sd->internal_ops = &preview_v4l2_internal_ops; 2269 strlcpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name)); 2270 sd->grp_id = 1 << 16; /* group ID for isp subdevs */ 2271 v4l2_set_subdevdata(sd, prev); 2272 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 2273 2274 v4l2_ctrl_handler_init(&prev->ctrls, 2); 2275 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_BRIGHTNESS, 2276 ISPPRV_BRIGHT_LOW, ISPPRV_BRIGHT_HIGH, 2277 ISPPRV_BRIGHT_STEP, ISPPRV_BRIGHT_DEF); 2278 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_CONTRAST, 2279 ISPPRV_CONTRAST_LOW, ISPPRV_CONTRAST_HIGH, 2280 ISPPRV_CONTRAST_STEP, ISPPRV_CONTRAST_DEF); 2281 v4l2_ctrl_handler_setup(&prev->ctrls); 2282 sd->ctrl_handler = &prev->ctrls; 2283 2284 pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK 2285 | MEDIA_PAD_FL_MUST_CONNECT; 2286 pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; 2287 2288 me->ops = &preview_media_ops; 2289 ret = media_entity_init(me, PREV_PADS_NUM, pads, 0); 2290 if (ret < 0) 2291 return ret; 2292 2293 preview_init_formats(sd, NULL); 2294 2295 /* According to the OMAP34xx TRM, video buffers need to be aligned on a 2296 * 32 bytes boundary. However, an undocumented hardware bug requires a 2297 * 64 bytes boundary at the preview engine input. 2298 */ 2299 prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 2300 prev->video_in.ops = &preview_video_ops; 2301 prev->video_in.isp = to_isp_device(prev); 2302 prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3; 2303 prev->video_in.bpl_alignment = 64; 2304 prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2305 prev->video_out.ops = &preview_video_ops; 2306 prev->video_out.isp = to_isp_device(prev); 2307 prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3; 2308 prev->video_out.bpl_alignment = 32; 2309 2310 ret = omap3isp_video_init(&prev->video_in, "preview"); 2311 if (ret < 0) 2312 goto error_video_in; 2313 2314 ret = omap3isp_video_init(&prev->video_out, "preview"); 2315 if (ret < 0) 2316 goto error_video_out; 2317 2318 /* Connect the video nodes to the previewer subdev. */ 2319 ret = media_entity_create_link(&prev->video_in.video.entity, 0, 2320 &prev->subdev.entity, PREV_PAD_SINK, 0); 2321 if (ret < 0) 2322 goto error_link; 2323 2324 ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE, 2325 &prev->video_out.video.entity, 0, 0); 2326 if (ret < 0) 2327 goto error_link; 2328 2329 return 0; 2330 2331error_link: 2332 omap3isp_video_cleanup(&prev->video_out); 2333error_video_out: 2334 omap3isp_video_cleanup(&prev->video_in); 2335error_video_in: 2336 media_entity_cleanup(&prev->subdev.entity); 2337 return ret; 2338} 2339 2340/* 2341 * omap3isp_preview_init - Previewer initialization. 2342 * @isp : Pointer to ISP device 2343 * return -ENOMEM or zero on success 2344 */ 2345int omap3isp_preview_init(struct isp_device *isp) 2346{ 2347 struct isp_prev_device *prev = &isp->isp_prev; 2348 2349 init_waitqueue_head(&prev->wait); 2350 2351 preview_init_params(prev); 2352 2353 return preview_init_entities(prev); 2354} 2355 2356void omap3isp_preview_cleanup(struct isp_device *isp) 2357{ 2358 struct isp_prev_device *prev = &isp->isp_prev; 2359 2360 v4l2_ctrl_handler_free(&prev->ctrls); 2361 omap3isp_video_cleanup(&prev->video_in); 2362 omap3isp_video_cleanup(&prev->video_out); 2363 media_entity_cleanup(&prev->subdev.entity); 2364} 2365