cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

isppreview.c (70112B)


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