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

camif-regs.c (17406B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Samsung s3c24xx/s3c64xx SoC CAMIF driver
      4 *
      5 * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
      6 * Copyright (C) 2012 Tomasz Figa <tomasz.figa@gmail.com>
      7*/
      8#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
      9
     10#include <linux/delay.h>
     11#include "camif-regs.h"
     12
     13#define camif_write(_camif, _off, _val)	writel(_val, (_camif)->io_base + (_off))
     14#define camif_read(_camif, _off)	readl((_camif)->io_base + (_off))
     15
     16void camif_hw_reset(struct camif_dev *camif)
     17{
     18	u32 cfg;
     19
     20	cfg = camif_read(camif, S3C_CAMIF_REG_CISRCFMT);
     21	cfg |= CISRCFMT_ITU601_8BIT;
     22	camif_write(camif, S3C_CAMIF_REG_CISRCFMT, cfg);
     23
     24	/* S/W reset */
     25	cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
     26	cfg |= CIGCTRL_SWRST;
     27	if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV)
     28		cfg |= CIGCTRL_IRQ_LEVEL;
     29	camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
     30	udelay(10);
     31
     32	cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
     33	cfg &= ~CIGCTRL_SWRST;
     34	camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
     35	udelay(10);
     36}
     37
     38void camif_hw_clear_pending_irq(struct camif_vp *vp)
     39{
     40	u32 cfg = camif_read(vp->camif, S3C_CAMIF_REG_CIGCTRL);
     41	cfg |= CIGCTRL_IRQ_CLR(vp->id);
     42	camif_write(vp->camif, S3C_CAMIF_REG_CIGCTRL, cfg);
     43}
     44
     45/*
     46 * Sets video test pattern (off, color bar, horizontal or vertical gradient).
     47 * External sensor pixel clock must be active for the test pattern to work.
     48 */
     49void camif_hw_set_test_pattern(struct camif_dev *camif, unsigned int pattern)
     50{
     51	u32 cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
     52	cfg &= ~CIGCTRL_TESTPATTERN_MASK;
     53	cfg |= (pattern << 27);
     54	camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
     55}
     56
     57void camif_hw_set_effect(struct camif_dev *camif, unsigned int effect,
     58			unsigned int cr, unsigned int cb)
     59{
     60	static const struct v4l2_control colorfx[] = {
     61		{ V4L2_COLORFX_NONE,		CIIMGEFF_FIN_BYPASS },
     62		{ V4L2_COLORFX_BW,		CIIMGEFF_FIN_ARBITRARY },
     63		{ V4L2_COLORFX_SEPIA,		CIIMGEFF_FIN_ARBITRARY },
     64		{ V4L2_COLORFX_NEGATIVE,	CIIMGEFF_FIN_NEGATIVE },
     65		{ V4L2_COLORFX_ART_FREEZE,	CIIMGEFF_FIN_ARTFREEZE },
     66		{ V4L2_COLORFX_EMBOSS,		CIIMGEFF_FIN_EMBOSSING },
     67		{ V4L2_COLORFX_SILHOUETTE,	CIIMGEFF_FIN_SILHOUETTE },
     68		{ V4L2_COLORFX_SET_CBCR,	CIIMGEFF_FIN_ARBITRARY },
     69	};
     70	unsigned int i, cfg;
     71
     72	for (i = 0; i < ARRAY_SIZE(colorfx); i++)
     73		if (colorfx[i].id == effect)
     74			break;
     75
     76	if (i == ARRAY_SIZE(colorfx))
     77		return;
     78
     79	cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGEFF(camif->vp->offset));
     80	/* Set effect */
     81	cfg &= ~CIIMGEFF_FIN_MASK;
     82	cfg |= colorfx[i].value;
     83	/* Set both paths */
     84	if (camif->variant->ip_revision >= S3C6400_CAMIF_IP_REV) {
     85		if (effect == V4L2_COLORFX_NONE)
     86			cfg &= ~CIIMGEFF_IE_ENABLE_MASK;
     87		else
     88			cfg |= CIIMGEFF_IE_ENABLE_MASK;
     89	}
     90	cfg &= ~CIIMGEFF_PAT_CBCR_MASK;
     91	cfg |= cr | (cb << 13);
     92	camif_write(camif, S3C_CAMIF_REG_CIIMGEFF(camif->vp->offset), cfg);
     93}
     94
     95static const u32 src_pixfmt_map[8][2] = {
     96	{ MEDIA_BUS_FMT_YUYV8_2X8, CISRCFMT_ORDER422_YCBYCR },
     97	{ MEDIA_BUS_FMT_YVYU8_2X8, CISRCFMT_ORDER422_YCRYCB },
     98	{ MEDIA_BUS_FMT_UYVY8_2X8, CISRCFMT_ORDER422_CBYCRY },
     99	{ MEDIA_BUS_FMT_VYUY8_2X8, CISRCFMT_ORDER422_CRYCBY },
    100};
    101
    102/* Set camera input pixel format and resolution */
    103void camif_hw_set_source_format(struct camif_dev *camif)
    104{
    105	struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
    106	int i;
    107	u32 cfg;
    108
    109	for (i = ARRAY_SIZE(src_pixfmt_map) - 1; i >= 0; i--) {
    110		if (src_pixfmt_map[i][0] == mf->code)
    111			break;
    112	}
    113	if (i < 0) {
    114		i = 0;
    115		dev_err(camif->dev,
    116			"Unsupported pixel code, falling back to %#08x\n",
    117			src_pixfmt_map[i][0]);
    118	}
    119
    120	cfg = camif_read(camif, S3C_CAMIF_REG_CISRCFMT);
    121	cfg &= ~(CISRCFMT_ORDER422_MASK | CISRCFMT_SIZE_CAM_MASK);
    122	cfg |= (mf->width << 16) | mf->height;
    123	cfg |= src_pixfmt_map[i][1];
    124	camif_write(camif, S3C_CAMIF_REG_CISRCFMT, cfg);
    125}
    126
    127/* Set the camera host input window offsets (cropping) */
    128void camif_hw_set_camera_crop(struct camif_dev *camif)
    129{
    130	struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
    131	struct v4l2_rect *crop = &camif->camif_crop;
    132	u32 hoff2, voff2;
    133	u32 cfg;
    134
    135	/* Note: s3c244x requirement: left = f_width - rect.width / 2 */
    136	cfg = camif_read(camif, S3C_CAMIF_REG_CIWDOFST);
    137	cfg &= ~(CIWDOFST_OFST_MASK | CIWDOFST_WINOFSEN);
    138	cfg |= (crop->left << 16) | crop->top;
    139	if (crop->left != 0 || crop->top != 0)
    140		cfg |= CIWDOFST_WINOFSEN;
    141	camif_write(camif, S3C_CAMIF_REG_CIWDOFST, cfg);
    142
    143	if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
    144		hoff2 = mf->width - crop->width - crop->left;
    145		voff2 = mf->height - crop->height - crop->top;
    146		cfg = (hoff2 << 16) | voff2;
    147		camif_write(camif, S3C_CAMIF_REG_CIWDOFST2, cfg);
    148	}
    149}
    150
    151void camif_hw_clear_fifo_overflow(struct camif_vp *vp)
    152{
    153	struct camif_dev *camif = vp->camif;
    154	u32 cfg;
    155
    156	cfg = camif_read(camif, S3C_CAMIF_REG_CIWDOFST);
    157	if (vp->id == 0)
    158		cfg |= (CIWDOFST_CLROVCOFIY | CIWDOFST_CLROVCOFICB |
    159			CIWDOFST_CLROVCOFICR);
    160	else
    161		cfg |= (/* CIWDOFST_CLROVPRFIY | */ CIWDOFST_CLROVPRFICB |
    162			CIWDOFST_CLROVPRFICR);
    163	camif_write(camif, S3C_CAMIF_REG_CIWDOFST, cfg);
    164}
    165
    166/* Set video bus signals polarity */
    167void camif_hw_set_camera_bus(struct camif_dev *camif)
    168{
    169	unsigned int flags = camif->pdata.sensor.flags;
    170
    171	u32 cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
    172
    173	cfg &= ~(CIGCTRL_INVPOLPCLK | CIGCTRL_INVPOLVSYNC |
    174		 CIGCTRL_INVPOLHREF | CIGCTRL_INVPOLFIELD);
    175
    176	if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
    177		cfg |= CIGCTRL_INVPOLPCLK;
    178
    179	if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
    180		cfg |= CIGCTRL_INVPOLVSYNC;
    181	/*
    182	 * HREF is normally high during frame active data
    183	 * transmission and low during horizontal synchronization
    184	 * period. Thus HREF active high means HSYNC active low.
    185	 */
    186	if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
    187		cfg |= CIGCTRL_INVPOLHREF; /* HREF active low */
    188
    189	if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
    190		if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
    191			cfg |= CIGCTRL_INVPOLFIELD;
    192		cfg |= CIGCTRL_FIELDMODE;
    193	}
    194
    195	pr_debug("Setting CIGCTRL to: %#x\n", cfg);
    196
    197	camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
    198}
    199
    200void camif_hw_set_output_addr(struct camif_vp *vp,
    201			      struct camif_addr *paddr, int i)
    202{
    203	struct camif_dev *camif = vp->camif;
    204
    205	camif_write(camif, S3C_CAMIF_REG_CIYSA(vp->id, i), paddr->y);
    206	if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV
    207		|| vp->id == VP_CODEC) {
    208		camif_write(camif, S3C_CAMIF_REG_CICBSA(vp->id, i),
    209								paddr->cb);
    210		camif_write(camif, S3C_CAMIF_REG_CICRSA(vp->id, i),
    211								paddr->cr);
    212	}
    213
    214	pr_debug("dst_buf[%d]: %pad, cb: %pad, cr: %pad\n",
    215		 i, &paddr->y, &paddr->cb, &paddr->cr);
    216}
    217
    218static void camif_hw_set_out_dma_size(struct camif_vp *vp)
    219{
    220	struct camif_frame *frame = &vp->out_frame;
    221	u32 cfg;
    222
    223	cfg = camif_read(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
    224	cfg &= ~CITRGFMT_TARGETSIZE_MASK;
    225	cfg |= (frame->f_width << 16) | frame->f_height;
    226	camif_write(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
    227}
    228
    229static void camif_get_dma_burst(u32 width, u32 ybpp, u32 *mburst, u32 *rburst)
    230{
    231	unsigned int nwords = width * ybpp / 4;
    232	unsigned int div, rem;
    233
    234	if (WARN_ON(width < 8 || (width * ybpp) & 7))
    235		return;
    236
    237	for (div = 16; div >= 2; div /= 2) {
    238		if (nwords < div)
    239			continue;
    240
    241		rem = nwords & (div - 1);
    242		if (rem == 0) {
    243			*mburst = div;
    244			*rburst = div;
    245			break;
    246		}
    247		if (rem == div / 2 || rem == div / 4) {
    248			*mburst = div;
    249			*rburst = rem;
    250			break;
    251		}
    252	}
    253}
    254
    255void camif_hw_set_output_dma(struct camif_vp *vp)
    256{
    257	struct camif_dev *camif = vp->camif;
    258	struct camif_frame *frame = &vp->out_frame;
    259	const struct camif_fmt *fmt = vp->out_fmt;
    260	unsigned int ymburst = 0, yrburst = 0;
    261	u32 cfg;
    262
    263	camif_hw_set_out_dma_size(vp);
    264
    265	if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
    266		struct camif_dma_offset *offset = &frame->dma_offset;
    267		/* Set the input dma offsets. */
    268		cfg = S3C_CISS_OFFS_INITIAL(offset->initial);
    269		cfg |= S3C_CISS_OFFS_LINE(offset->line);
    270		camif_write(camif, S3C_CAMIF_REG_CISSY(vp->id), cfg);
    271		camif_write(camif, S3C_CAMIF_REG_CISSCB(vp->id), cfg);
    272		camif_write(camif, S3C_CAMIF_REG_CISSCR(vp->id), cfg);
    273	}
    274
    275	/* Configure DMA burst values */
    276	camif_get_dma_burst(frame->rect.width, fmt->ybpp, &ymburst, &yrburst);
    277
    278	cfg = camif_read(camif, S3C_CAMIF_REG_CICTRL(vp->id, vp->offset));
    279	cfg &= ~CICTRL_BURST_MASK;
    280
    281	cfg |= CICTRL_YBURST1(ymburst) | CICTRL_YBURST2(yrburst);
    282	cfg |= CICTRL_CBURST1(ymburst / 2) | CICTRL_CBURST2(yrburst / 2);
    283
    284	camif_write(camif, S3C_CAMIF_REG_CICTRL(vp->id, vp->offset), cfg);
    285
    286	pr_debug("ymburst: %u, yrburst: %u\n", ymburst, yrburst);
    287}
    288
    289void camif_hw_set_input_path(struct camif_vp *vp)
    290{
    291	u32 cfg = camif_read(vp->camif, S3C_CAMIF_REG_MSCTRL(vp->id));
    292	cfg &= ~MSCTRL_SEL_DMA_CAM;
    293	camif_write(vp->camif, S3C_CAMIF_REG_MSCTRL(vp->id), cfg);
    294}
    295
    296void camif_hw_set_target_format(struct camif_vp *vp)
    297{
    298	struct camif_dev *camif = vp->camif;
    299	struct camif_frame *frame = &vp->out_frame;
    300	u32 cfg;
    301
    302	pr_debug("fw: %d, fh: %d color: %d\n", frame->f_width,
    303		 frame->f_height, vp->out_fmt->color);
    304
    305	cfg = camif_read(camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
    306	cfg &= ~CITRGFMT_TARGETSIZE_MASK;
    307
    308	if (camif->variant->ip_revision == S3C244X_CAMIF_IP_REV) {
    309		/* We currently support only YCbCr 4:2:2 at the camera input */
    310		cfg |= CITRGFMT_IN422;
    311		cfg &= ~CITRGFMT_OUT422;
    312		if (vp->out_fmt->color == IMG_FMT_YCBCR422P)
    313			cfg |= CITRGFMT_OUT422;
    314	} else {
    315		cfg &= ~CITRGFMT_OUTFORMAT_MASK;
    316		switch (vp->out_fmt->color) {
    317		case IMG_FMT_RGB565...IMG_FMT_XRGB8888:
    318			cfg |= CITRGFMT_OUTFORMAT_RGB;
    319			break;
    320		case IMG_FMT_YCBCR420...IMG_FMT_YCRCB420:
    321			cfg |= CITRGFMT_OUTFORMAT_YCBCR420;
    322			break;
    323		case IMG_FMT_YCBCR422P:
    324			cfg |= CITRGFMT_OUTFORMAT_YCBCR422;
    325			break;
    326		case IMG_FMT_YCBYCR422...IMG_FMT_CRYCBY422:
    327			cfg |= CITRGFMT_OUTFORMAT_YCBCR422I;
    328			break;
    329		}
    330	}
    331
    332	/* Rotation is only supported by s3c64xx */
    333	if (vp->rotation == 90 || vp->rotation == 270)
    334		cfg |= (frame->f_height << 16) | frame->f_width;
    335	else
    336		cfg |= (frame->f_width << 16) | frame->f_height;
    337	camif_write(camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
    338
    339	/* Target area, output pixel width * height */
    340	cfg = camif_read(camif, S3C_CAMIF_REG_CITAREA(vp->id, vp->offset));
    341	cfg &= ~CITAREA_MASK;
    342	cfg |= (frame->f_width * frame->f_height);
    343	camif_write(camif, S3C_CAMIF_REG_CITAREA(vp->id, vp->offset), cfg);
    344}
    345
    346void camif_hw_set_flip(struct camif_vp *vp)
    347{
    348	u32 cfg = camif_read(vp->camif,
    349				S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
    350
    351	cfg &= ~CITRGFMT_FLIP_MASK;
    352
    353	if (vp->hflip)
    354		cfg |= CITRGFMT_FLIP_Y_MIRROR;
    355	if (vp->vflip)
    356		cfg |= CITRGFMT_FLIP_X_MIRROR;
    357
    358	camif_write(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
    359}
    360
    361static void camif_hw_set_prescaler(struct camif_vp *vp)
    362{
    363	struct camif_dev *camif = vp->camif;
    364	struct camif_scaler *sc = &vp->scaler;
    365	u32 cfg, shfactor, addr;
    366
    367	addr = S3C_CAMIF_REG_CISCPRERATIO(vp->id, vp->offset);
    368
    369	shfactor = 10 - (sc->h_shift + sc->v_shift);
    370	cfg = shfactor << 28;
    371
    372	cfg |= (sc->pre_h_ratio << 16) | sc->pre_v_ratio;
    373	camif_write(camif, addr, cfg);
    374
    375	cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
    376	camif_write(camif, S3C_CAMIF_REG_CISCPREDST(vp->id, vp->offset), cfg);
    377}
    378
    379static void camif_s3c244x_hw_set_scaler(struct camif_vp *vp)
    380{
    381	struct camif_dev *camif = vp->camif;
    382	struct camif_scaler *scaler = &vp->scaler;
    383	unsigned int color = vp->out_fmt->color;
    384	u32 cfg;
    385
    386	camif_hw_set_prescaler(vp);
    387
    388	cfg = camif_read(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset));
    389
    390	cfg &= ~(CISCCTRL_SCALEUP_MASK | CISCCTRL_SCALERBYPASS |
    391		 CISCCTRL_MAIN_RATIO_MASK | CIPRSCCTRL_RGB_FORMAT_24BIT);
    392
    393	if (scaler->enable) {
    394		if (scaler->scaleup_h) {
    395			if (vp->id == VP_CODEC)
    396				cfg |= CISCCTRL_SCALEUP_H;
    397			else
    398				cfg |= CIPRSCCTRL_SCALEUP_H;
    399		}
    400		if (scaler->scaleup_v) {
    401			if (vp->id == VP_CODEC)
    402				cfg |= CISCCTRL_SCALEUP_V;
    403			else
    404				cfg |= CIPRSCCTRL_SCALEUP_V;
    405		}
    406	} else {
    407		if (vp->id == VP_CODEC)
    408			cfg |= CISCCTRL_SCALERBYPASS;
    409	}
    410
    411	cfg |= ((scaler->main_h_ratio & 0x1ff) << 16);
    412	cfg |= scaler->main_v_ratio & 0x1ff;
    413
    414	if (vp->id == VP_PREVIEW) {
    415		if (color == IMG_FMT_XRGB8888)
    416			cfg |= CIPRSCCTRL_RGB_FORMAT_24BIT;
    417		cfg |= CIPRSCCTRL_SAMPLE;
    418	}
    419
    420	camif_write(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset), cfg);
    421
    422	pr_debug("main: h_ratio: %#x, v_ratio: %#x",
    423		 scaler->main_h_ratio, scaler->main_v_ratio);
    424}
    425
    426static void camif_s3c64xx_hw_set_scaler(struct camif_vp *vp)
    427{
    428	struct camif_dev *camif = vp->camif;
    429	struct camif_scaler *scaler = &vp->scaler;
    430	unsigned int color = vp->out_fmt->color;
    431	u32 cfg;
    432
    433	camif_hw_set_prescaler(vp);
    434
    435	cfg = camif_read(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset));
    436
    437	cfg &= ~(CISCCTRL_CSCR2Y_WIDE | CISCCTRL_CSCY2R_WIDE
    438		| CISCCTRL_SCALEUP_H | CISCCTRL_SCALEUP_V
    439		| CISCCTRL_SCALERBYPASS | CISCCTRL_ONE2ONE
    440		| CISCCTRL_INRGB_FMT_MASK | CISCCTRL_OUTRGB_FMT_MASK
    441		| CISCCTRL_INTERLACE | CISCCTRL_EXTRGB_EXTENSION
    442		| CISCCTRL_MAIN_RATIO_MASK);
    443
    444	cfg |= (CISCCTRL_CSCR2Y_WIDE | CISCCTRL_CSCY2R_WIDE);
    445
    446	if (!scaler->enable) {
    447		cfg |= CISCCTRL_SCALERBYPASS;
    448	} else {
    449		if (scaler->scaleup_h)
    450			cfg |= CISCCTRL_SCALEUP_H;
    451		if (scaler->scaleup_v)
    452			cfg |= CISCCTRL_SCALEUP_V;
    453		if (scaler->copy)
    454			cfg |= CISCCTRL_ONE2ONE;
    455	}
    456
    457	switch (color) {
    458	case IMG_FMT_RGB666:
    459		cfg |= CISCCTRL_OUTRGB_FMT_RGB666;
    460		break;
    461	case IMG_FMT_XRGB8888:
    462		cfg |= CISCCTRL_OUTRGB_FMT_RGB888;
    463		break;
    464	}
    465
    466	cfg |= (scaler->main_h_ratio & 0x1ff) << 16;
    467	cfg |= scaler->main_v_ratio & 0x1ff;
    468
    469	camif_write(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset), cfg);
    470
    471	pr_debug("main: h_ratio: %#x, v_ratio: %#x",
    472		 scaler->main_h_ratio, scaler->main_v_ratio);
    473}
    474
    475void camif_hw_set_scaler(struct camif_vp *vp)
    476{
    477	unsigned int ip_rev = vp->camif->variant->ip_revision;
    478
    479	if (ip_rev == S3C244X_CAMIF_IP_REV)
    480		camif_s3c244x_hw_set_scaler(vp);
    481	else
    482		camif_s3c64xx_hw_set_scaler(vp);
    483}
    484
    485void camif_hw_enable_scaler(struct camif_vp *vp, bool on)
    486{
    487	u32 addr = S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset);
    488	u32 cfg;
    489
    490	cfg = camif_read(vp->camif, addr);
    491	if (on)
    492		cfg |= CISCCTRL_SCALERSTART;
    493	else
    494		cfg &= ~CISCCTRL_SCALERSTART;
    495	camif_write(vp->camif, addr, cfg);
    496}
    497
    498void camif_hw_set_lastirq(struct camif_vp *vp, int enable)
    499{
    500	u32 addr = S3C_CAMIF_REG_CICTRL(vp->id, vp->offset);
    501	u32 cfg;
    502
    503	cfg = camif_read(vp->camif, addr);
    504	if (enable)
    505		cfg |= CICTRL_LASTIRQ_ENABLE;
    506	else
    507		cfg &= ~CICTRL_LASTIRQ_ENABLE;
    508	camif_write(vp->camif, addr, cfg);
    509}
    510
    511void camif_hw_enable_capture(struct camif_vp *vp)
    512{
    513	struct camif_dev *camif = vp->camif;
    514	u32 cfg;
    515
    516	cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset));
    517	camif->stream_count++;
    518
    519	if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV)
    520		cfg |= CIIMGCPT_CPT_FREN_ENABLE(vp->id);
    521
    522	if (vp->scaler.enable)
    523		cfg |= CIIMGCPT_IMGCPTEN_SC(vp->id);
    524
    525	if (camif->stream_count == 1)
    526		cfg |= CIIMGCPT_IMGCPTEN;
    527
    528	camif_write(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset), cfg);
    529
    530	pr_debug("CIIMGCPT: %#x, camif->stream_count: %d\n",
    531		 cfg, camif->stream_count);
    532}
    533
    534void camif_hw_disable_capture(struct camif_vp *vp)
    535{
    536	struct camif_dev *camif = vp->camif;
    537	u32 cfg;
    538
    539	cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset));
    540	cfg &= ~CIIMGCPT_IMGCPTEN_SC(vp->id);
    541
    542	if (WARN_ON(--(camif->stream_count) < 0))
    543		camif->stream_count = 0;
    544
    545	if (camif->stream_count == 0)
    546		cfg &= ~CIIMGCPT_IMGCPTEN;
    547
    548	pr_debug("CIIMGCPT: %#x, camif->stream_count: %d\n",
    549		 cfg, camif->stream_count);
    550
    551	camif_write(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset), cfg);
    552}
    553
    554void camif_hw_dump_regs(struct camif_dev *camif, const char *label)
    555{
    556	static const struct {
    557		u32 offset;
    558		const char * const name;
    559	} registers[] = {
    560		{ S3C_CAMIF_REG_CISRCFMT,		"CISRCFMT" },
    561		{ S3C_CAMIF_REG_CIWDOFST,		"CIWDOFST" },
    562		{ S3C_CAMIF_REG_CIGCTRL,		"CIGCTRL" },
    563		{ S3C_CAMIF_REG_CIWDOFST2,		"CIWDOFST2" },
    564		{ S3C_CAMIF_REG_CIYSA(0, 0),		"CICOYSA0" },
    565		{ S3C_CAMIF_REG_CICBSA(0, 0),		"CICOCBSA0" },
    566		{ S3C_CAMIF_REG_CICRSA(0, 0),		"CICOCRSA0" },
    567		{ S3C_CAMIF_REG_CIYSA(0, 1),		"CICOYSA1" },
    568		{ S3C_CAMIF_REG_CICBSA(0, 1),		"CICOCBSA1" },
    569		{ S3C_CAMIF_REG_CICRSA(0, 1),		"CICOCRSA1" },
    570		{ S3C_CAMIF_REG_CIYSA(0, 2),		"CICOYSA2" },
    571		{ S3C_CAMIF_REG_CICBSA(0, 2),		"CICOCBSA2" },
    572		{ S3C_CAMIF_REG_CICRSA(0, 2),		"CICOCRSA2" },
    573		{ S3C_CAMIF_REG_CIYSA(0, 3),		"CICOYSA3" },
    574		{ S3C_CAMIF_REG_CICBSA(0, 3),		"CICOCBSA3" },
    575		{ S3C_CAMIF_REG_CICRSA(0, 3),		"CICOCRSA3" },
    576		{ S3C_CAMIF_REG_CIYSA(1, 0),		"CIPRYSA0" },
    577		{ S3C_CAMIF_REG_CIYSA(1, 1),		"CIPRYSA1" },
    578		{ S3C_CAMIF_REG_CIYSA(1, 2),		"CIPRYSA2" },
    579		{ S3C_CAMIF_REG_CIYSA(1, 3),		"CIPRYSA3" },
    580		{ S3C_CAMIF_REG_CITRGFMT(0, 0),		"CICOTRGFMT" },
    581		{ S3C_CAMIF_REG_CITRGFMT(1, 0),		"CIPRTRGFMT" },
    582		{ S3C_CAMIF_REG_CICTRL(0, 0),		"CICOCTRL" },
    583		{ S3C_CAMIF_REG_CICTRL(1, 0),		"CIPRCTRL" },
    584		{ S3C_CAMIF_REG_CISCPREDST(0, 0),	"CICOSCPREDST" },
    585		{ S3C_CAMIF_REG_CISCPREDST(1, 0),	"CIPRSCPREDST" },
    586		{ S3C_CAMIF_REG_CISCPRERATIO(0, 0),	"CICOSCPRERATIO" },
    587		{ S3C_CAMIF_REG_CISCPRERATIO(1, 0),	"CIPRSCPRERATIO" },
    588		{ S3C_CAMIF_REG_CISCCTRL(0, 0),		"CICOSCCTRL" },
    589		{ S3C_CAMIF_REG_CISCCTRL(1, 0),		"CIPRSCCTRL" },
    590		{ S3C_CAMIF_REG_CITAREA(0, 0),		"CICOTAREA" },
    591		{ S3C_CAMIF_REG_CITAREA(1, 0),		"CIPRTAREA" },
    592		{ S3C_CAMIF_REG_CISTATUS(0, 0),		"CICOSTATUS" },
    593		{ S3C_CAMIF_REG_CISTATUS(1, 0),		"CIPRSTATUS" },
    594		{ S3C_CAMIF_REG_CIIMGCPT(0),		"CIIMGCPT" },
    595	};
    596	u32 i;
    597
    598	pr_info("--- %s ---\n", label);
    599	for (i = 0; i < ARRAY_SIZE(registers); i++) {
    600		u32 cfg = readl(camif->io_base + registers[i].offset);
    601		dev_info(camif->dev, "%s:\t0x%08x\n", registers[i].name, cfg);
    602	}
    603}