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

fimc-reg.c (22798B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Register interface file for Samsung Camera Interface (FIMC) driver
      4 *
      5 * Copyright (C) 2010 - 2013 Samsung Electronics Co., Ltd.
      6 * Sylwester Nawrocki <s.nawrocki@samsung.com>
      7*/
      8
      9#include <linux/delay.h>
     10#include <linux/io.h>
     11#include <linux/regmap.h>
     12
     13#include <media/drv-intf/exynos-fimc.h>
     14#include "media-dev.h"
     15
     16#include "fimc-reg.h"
     17#include "fimc-core.h"
     18
     19void fimc_hw_reset(struct fimc_dev *dev)
     20{
     21	u32 cfg;
     22
     23	cfg = readl(dev->regs + FIMC_REG_CISRCFMT);
     24	cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
     25	writel(cfg, dev->regs + FIMC_REG_CISRCFMT);
     26
     27	/* Software reset. */
     28	cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
     29	cfg |= (FIMC_REG_CIGCTRL_SWRST | FIMC_REG_CIGCTRL_IRQ_LEVEL);
     30	writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
     31	udelay(10);
     32
     33	cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
     34	cfg &= ~FIMC_REG_CIGCTRL_SWRST;
     35	writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
     36
     37	if (dev->drv_data->out_buf_count > 4)
     38		fimc_hw_set_dma_seq(dev, 0xF);
     39}
     40
     41static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
     42{
     43	u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL;
     44
     45	if (ctx->hflip)
     46		flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR;
     47	if (ctx->vflip)
     48		flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR;
     49
     50	if (ctx->rotation <= 90)
     51		return flip;
     52
     53	return (flip ^ FIMC_REG_MSCTRL_FLIP_180) & FIMC_REG_MSCTRL_FLIP_180;
     54}
     55
     56static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
     57{
     58	u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL;
     59
     60	if (ctx->hflip)
     61		flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR;
     62	if (ctx->vflip)
     63		flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR;
     64
     65	if (ctx->rotation <= 90)
     66		return flip;
     67
     68	return (flip ^ FIMC_REG_CITRGFMT_FLIP_180) & FIMC_REG_CITRGFMT_FLIP_180;
     69}
     70
     71void fimc_hw_set_rotation(struct fimc_ctx *ctx)
     72{
     73	u32 cfg, flip;
     74	struct fimc_dev *dev = ctx->fimc_dev;
     75
     76	cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
     77	cfg &= ~(FIMC_REG_CITRGFMT_INROT90 | FIMC_REG_CITRGFMT_OUTROT90 |
     78		 FIMC_REG_CITRGFMT_FLIP_180);
     79
     80	/*
     81	 * The input and output rotator cannot work simultaneously.
     82	 * Use the output rotator in output DMA mode or the input rotator
     83	 * in direct fifo output mode.
     84	 */
     85	if (ctx->rotation == 90 || ctx->rotation == 270) {
     86		if (ctx->out_path == FIMC_IO_LCDFIFO)
     87			cfg |= FIMC_REG_CITRGFMT_INROT90;
     88		else
     89			cfg |= FIMC_REG_CITRGFMT_OUTROT90;
     90	}
     91
     92	if (ctx->out_path == FIMC_IO_DMA) {
     93		cfg |= fimc_hw_get_target_flip(ctx);
     94		writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
     95	} else {
     96		/* LCD FIFO path */
     97		flip = readl(dev->regs + FIMC_REG_MSCTRL);
     98		flip &= ~FIMC_REG_MSCTRL_FLIP_MASK;
     99		flip |= fimc_hw_get_in_flip(ctx);
    100		writel(flip, dev->regs + FIMC_REG_MSCTRL);
    101	}
    102}
    103
    104void fimc_hw_set_target_format(struct fimc_ctx *ctx)
    105{
    106	u32 cfg;
    107	struct fimc_dev *dev = ctx->fimc_dev;
    108	struct fimc_frame *frame = &ctx->d_frame;
    109
    110	dbg("w= %d, h= %d color: %d", frame->width,
    111	    frame->height, frame->fmt->color);
    112
    113	cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
    114	cfg &= ~(FIMC_REG_CITRGFMT_FMT_MASK | FIMC_REG_CITRGFMT_HSIZE_MASK |
    115		 FIMC_REG_CITRGFMT_VSIZE_MASK);
    116
    117	switch (frame->fmt->color) {
    118	case FIMC_FMT_RGB444...FIMC_FMT_RGB888:
    119		cfg |= FIMC_REG_CITRGFMT_RGB;
    120		break;
    121	case FIMC_FMT_YCBCR420:
    122		cfg |= FIMC_REG_CITRGFMT_YCBCR420;
    123		break;
    124	case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
    125		if (frame->fmt->colplanes == 1)
    126			cfg |= FIMC_REG_CITRGFMT_YCBCR422_1P;
    127		else
    128			cfg |= FIMC_REG_CITRGFMT_YCBCR422;
    129		break;
    130	default:
    131		break;
    132	}
    133
    134	if (ctx->rotation == 90 || ctx->rotation == 270)
    135		cfg |= (frame->height << 16) | frame->width;
    136	else
    137		cfg |= (frame->width << 16) | frame->height;
    138
    139	writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
    140
    141	cfg = readl(dev->regs + FIMC_REG_CITAREA);
    142	cfg &= ~FIMC_REG_CITAREA_MASK;
    143	cfg |= (frame->width * frame->height);
    144	writel(cfg, dev->regs + FIMC_REG_CITAREA);
    145}
    146
    147static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
    148{
    149	struct fimc_dev *dev = ctx->fimc_dev;
    150	struct fimc_frame *frame = &ctx->d_frame;
    151	u32 cfg;
    152
    153	cfg = (frame->f_height << 16) | frame->f_width;
    154	writel(cfg, dev->regs + FIMC_REG_ORGOSIZE);
    155
    156	/* Select color space conversion equation (HD/SD size).*/
    157	cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
    158	if (frame->f_width >= 1280) /* HD */
    159		cfg |= FIMC_REG_CIGCTRL_CSC_ITU601_709;
    160	else	/* SD */
    161		cfg &= ~FIMC_REG_CIGCTRL_CSC_ITU601_709;
    162	writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
    163
    164}
    165
    166void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
    167{
    168	struct fimc_dev *dev = ctx->fimc_dev;
    169	struct fimc_frame *frame = &ctx->d_frame;
    170	struct fimc_dma_offset *offset = &frame->dma_offset;
    171	struct fimc_fmt *fmt = frame->fmt;
    172	u32 cfg;
    173
    174	/* Set the input dma offsets. */
    175	cfg = (offset->y_v << 16) | offset->y_h;
    176	writel(cfg, dev->regs + FIMC_REG_CIOYOFF);
    177
    178	cfg = (offset->cb_v << 16) | offset->cb_h;
    179	writel(cfg, dev->regs + FIMC_REG_CIOCBOFF);
    180
    181	cfg = (offset->cr_v << 16) | offset->cr_h;
    182	writel(cfg, dev->regs + FIMC_REG_CIOCROFF);
    183
    184	fimc_hw_set_out_dma_size(ctx);
    185
    186	/* Configure chroma components order. */
    187	cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
    188
    189	cfg &= ~(FIMC_REG_CIOCTRL_ORDER2P_MASK |
    190		 FIMC_REG_CIOCTRL_ORDER422_MASK |
    191		 FIMC_REG_CIOCTRL_YCBCR_PLANE_MASK |
    192		 FIMC_REG_CIOCTRL_RGB16FMT_MASK);
    193
    194	if (fmt->colplanes == 1)
    195		cfg |= ctx->out_order_1p;
    196	else if (fmt->colplanes == 2)
    197		cfg |= ctx->out_order_2p | FIMC_REG_CIOCTRL_YCBCR_2PLANE;
    198	else if (fmt->colplanes == 3)
    199		cfg |= FIMC_REG_CIOCTRL_YCBCR_3PLANE;
    200
    201	if (fmt->color == FIMC_FMT_RGB565)
    202		cfg |= FIMC_REG_CIOCTRL_RGB565;
    203	else if (fmt->color == FIMC_FMT_RGB555)
    204		cfg |= FIMC_REG_CIOCTRL_ARGB1555;
    205	else if (fmt->color == FIMC_FMT_RGB444)
    206		cfg |= FIMC_REG_CIOCTRL_ARGB4444;
    207
    208	writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
    209}
    210
    211static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
    212{
    213	u32 cfg = readl(dev->regs + FIMC_REG_ORGISIZE);
    214	if (enable)
    215		cfg |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
    216	else
    217		cfg &= ~FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
    218	writel(cfg, dev->regs + FIMC_REG_ORGISIZE);
    219}
    220
    221void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
    222{
    223	u32 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
    224	if (enable)
    225		cfg |= FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
    226	else
    227		cfg &= ~FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
    228	writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
    229}
    230
    231void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
    232{
    233	struct fimc_dev *dev =  ctx->fimc_dev;
    234	struct fimc_scaler *sc = &ctx->scaler;
    235	u32 cfg, shfactor;
    236
    237	shfactor = 10 - (sc->hfactor + sc->vfactor);
    238	cfg = shfactor << 28;
    239
    240	cfg |= (sc->pre_hratio << 16) | sc->pre_vratio;
    241	writel(cfg, dev->regs + FIMC_REG_CISCPRERATIO);
    242
    243	cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
    244	writel(cfg, dev->regs + FIMC_REG_CISCPREDST);
    245}
    246
    247static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
    248{
    249	struct fimc_dev *dev = ctx->fimc_dev;
    250	struct fimc_scaler *sc = &ctx->scaler;
    251	struct fimc_frame *src_frame = &ctx->s_frame;
    252	struct fimc_frame *dst_frame = &ctx->d_frame;
    253
    254	u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
    255
    256	cfg &= ~(FIMC_REG_CISCCTRL_CSCR2Y_WIDE | FIMC_REG_CISCCTRL_CSCY2R_WIDE |
    257		 FIMC_REG_CISCCTRL_SCALEUP_H | FIMC_REG_CISCCTRL_SCALEUP_V |
    258		 FIMC_REG_CISCCTRL_SCALERBYPASS | FIMC_REG_CISCCTRL_ONE2ONE |
    259		 FIMC_REG_CISCCTRL_INRGB_FMT_MASK | FIMC_REG_CISCCTRL_OUTRGB_FMT_MASK |
    260		 FIMC_REG_CISCCTRL_INTERLACE | FIMC_REG_CISCCTRL_RGB_EXT);
    261
    262	if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
    263		cfg |= (FIMC_REG_CISCCTRL_CSCR2Y_WIDE |
    264			FIMC_REG_CISCCTRL_CSCY2R_WIDE);
    265
    266	if (!sc->enabled)
    267		cfg |= FIMC_REG_CISCCTRL_SCALERBYPASS;
    268
    269	if (sc->scaleup_h)
    270		cfg |= FIMC_REG_CISCCTRL_SCALEUP_H;
    271
    272	if (sc->scaleup_v)
    273		cfg |= FIMC_REG_CISCCTRL_SCALEUP_V;
    274
    275	if (sc->copy_mode)
    276		cfg |= FIMC_REG_CISCCTRL_ONE2ONE;
    277
    278	if (ctx->in_path == FIMC_IO_DMA) {
    279		switch (src_frame->fmt->color) {
    280		case FIMC_FMT_RGB565:
    281			cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB565;
    282			break;
    283		case FIMC_FMT_RGB666:
    284			cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB666;
    285			break;
    286		case FIMC_FMT_RGB888:
    287			cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB888;
    288			break;
    289		}
    290	}
    291
    292	if (ctx->out_path == FIMC_IO_DMA) {
    293		u32 color = dst_frame->fmt->color;
    294
    295		if (color >= FIMC_FMT_RGB444 && color <= FIMC_FMT_RGB565)
    296			cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565;
    297		else if (color == FIMC_FMT_RGB666)
    298			cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666;
    299		else if (color == FIMC_FMT_RGB888)
    300			cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
    301	} else {
    302		cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
    303
    304		if (ctx->flags & FIMC_SCAN_MODE_INTERLACED)
    305			cfg |= FIMC_REG_CISCCTRL_INTERLACE;
    306	}
    307
    308	writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
    309}
    310
    311void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
    312{
    313	struct fimc_dev *dev = ctx->fimc_dev;
    314	const struct fimc_variant *variant = dev->variant;
    315	struct fimc_scaler *sc = &ctx->scaler;
    316	u32 cfg;
    317
    318	dbg("main_hratio= 0x%X  main_vratio= 0x%X",
    319	    sc->main_hratio, sc->main_vratio);
    320
    321	fimc_hw_set_scaler(ctx);
    322
    323	cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
    324	cfg &= ~(FIMC_REG_CISCCTRL_MHRATIO_MASK |
    325		 FIMC_REG_CISCCTRL_MVRATIO_MASK);
    326
    327	if (variant->has_mainscaler_ext) {
    328		cfg |= FIMC_REG_CISCCTRL_MHRATIO_EXT(sc->main_hratio);
    329		cfg |= FIMC_REG_CISCCTRL_MVRATIO_EXT(sc->main_vratio);
    330		writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
    331
    332		cfg = readl(dev->regs + FIMC_REG_CIEXTEN);
    333
    334		cfg &= ~(FIMC_REG_CIEXTEN_MVRATIO_EXT_MASK |
    335			 FIMC_REG_CIEXTEN_MHRATIO_EXT_MASK);
    336		cfg |= FIMC_REG_CIEXTEN_MHRATIO_EXT(sc->main_hratio);
    337		cfg |= FIMC_REG_CIEXTEN_MVRATIO_EXT(sc->main_vratio);
    338		writel(cfg, dev->regs + FIMC_REG_CIEXTEN);
    339	} else {
    340		cfg |= FIMC_REG_CISCCTRL_MHRATIO(sc->main_hratio);
    341		cfg |= FIMC_REG_CISCCTRL_MVRATIO(sc->main_vratio);
    342		writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
    343	}
    344}
    345
    346void fimc_hw_enable_capture(struct fimc_ctx *ctx)
    347{
    348	struct fimc_dev *dev = ctx->fimc_dev;
    349	u32 cfg;
    350
    351	cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
    352	cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE;
    353
    354	if (ctx->scaler.enabled)
    355		cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
    356	else
    357		cfg &= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
    358
    359	cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
    360	writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
    361}
    362
    363void fimc_hw_disable_capture(struct fimc_dev *dev)
    364{
    365	u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
    366	cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN |
    367		 FIMC_REG_CIIMGCPT_IMGCPTEN_SC);
    368	writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
    369}
    370
    371void fimc_hw_set_effect(struct fimc_ctx *ctx)
    372{
    373	struct fimc_dev *dev = ctx->fimc_dev;
    374	struct fimc_effect *effect = &ctx->effect;
    375	u32 cfg = 0;
    376
    377	if (effect->type != FIMC_REG_CIIMGEFF_FIN_BYPASS) {
    378		cfg |= FIMC_REG_CIIMGEFF_IE_SC_AFTER |
    379			FIMC_REG_CIIMGEFF_IE_ENABLE;
    380		cfg |= effect->type;
    381		if (effect->type == FIMC_REG_CIIMGEFF_FIN_ARBITRARY)
    382			cfg |= (effect->pat_cb << 13) | effect->pat_cr;
    383	}
    384
    385	writel(cfg, dev->regs + FIMC_REG_CIIMGEFF);
    386}
    387
    388void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx)
    389{
    390	struct fimc_dev *dev = ctx->fimc_dev;
    391	struct fimc_frame *frame = &ctx->d_frame;
    392	u32 cfg;
    393
    394	if (!(frame->fmt->flags & FMT_HAS_ALPHA))
    395		return;
    396
    397	cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
    398	cfg &= ~FIMC_REG_CIOCTRL_ALPHA_OUT_MASK;
    399	cfg |= (frame->alpha << 4);
    400	writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
    401}
    402
    403static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
    404{
    405	struct fimc_dev *dev = ctx->fimc_dev;
    406	struct fimc_frame *frame = &ctx->s_frame;
    407	u32 cfg_o = 0;
    408	u32 cfg_r = 0;
    409
    410	if (FIMC_IO_LCDFIFO == ctx->out_path)
    411		cfg_r |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
    412
    413	cfg_o |= (frame->f_height << 16) | frame->f_width;
    414	cfg_r |= (frame->height << 16) | frame->width;
    415
    416	writel(cfg_o, dev->regs + FIMC_REG_ORGISIZE);
    417	writel(cfg_r, dev->regs + FIMC_REG_CIREAL_ISIZE);
    418}
    419
    420void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
    421{
    422	struct fimc_dev *dev = ctx->fimc_dev;
    423	struct fimc_frame *frame = &ctx->s_frame;
    424	struct fimc_dma_offset *offset = &frame->dma_offset;
    425	u32 cfg;
    426
    427	/* Set the pixel offsets. */
    428	cfg = (offset->y_v << 16) | offset->y_h;
    429	writel(cfg, dev->regs + FIMC_REG_CIIYOFF);
    430
    431	cfg = (offset->cb_v << 16) | offset->cb_h;
    432	writel(cfg, dev->regs + FIMC_REG_CIICBOFF);
    433
    434	cfg = (offset->cr_v << 16) | offset->cr_h;
    435	writel(cfg, dev->regs + FIMC_REG_CIICROFF);
    436
    437	/* Input original and real size. */
    438	fimc_hw_set_in_dma_size(ctx);
    439
    440	/* Use DMA autoload only in FIFO mode. */
    441	fimc_hw_en_autoload(dev, ctx->out_path == FIMC_IO_LCDFIFO);
    442
    443	/* Set the input DMA to process single frame only. */
    444	cfg = readl(dev->regs + FIMC_REG_MSCTRL);
    445	cfg &= ~(FIMC_REG_MSCTRL_INFORMAT_MASK
    446		 | FIMC_REG_MSCTRL_IN_BURST_COUNT_MASK
    447		 | FIMC_REG_MSCTRL_INPUT_MASK
    448		 | FIMC_REG_MSCTRL_C_INT_IN_MASK
    449		 | FIMC_REG_MSCTRL_2P_IN_ORDER_MASK
    450		 | FIMC_REG_MSCTRL_ORDER422_MASK);
    451
    452	cfg |= (FIMC_REG_MSCTRL_IN_BURST_COUNT(4)
    453		| FIMC_REG_MSCTRL_INPUT_MEMORY
    454		| FIMC_REG_MSCTRL_FIFO_CTRL_FULL);
    455
    456	switch (frame->fmt->color) {
    457	case FIMC_FMT_RGB565...FIMC_FMT_RGB888:
    458		cfg |= FIMC_REG_MSCTRL_INFORMAT_RGB;
    459		break;
    460	case FIMC_FMT_YCBCR420:
    461		cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR420;
    462
    463		if (frame->fmt->colplanes == 2)
    464			cfg |= ctx->in_order_2p | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
    465		else
    466			cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
    467
    468		break;
    469	case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
    470		if (frame->fmt->colplanes == 1) {
    471			cfg |= ctx->in_order_1p
    472				| FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P;
    473		} else {
    474			cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR422;
    475
    476			if (frame->fmt->colplanes == 2)
    477				cfg |= ctx->in_order_2p
    478					| FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
    479			else
    480				cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
    481		}
    482		break;
    483	default:
    484		break;
    485	}
    486
    487	writel(cfg, dev->regs + FIMC_REG_MSCTRL);
    488
    489	/* Input/output DMA linear/tiled mode. */
    490	cfg = readl(dev->regs + FIMC_REG_CIDMAPARAM);
    491	cfg &= ~FIMC_REG_CIDMAPARAM_TILE_MASK;
    492
    493	if (tiled_fmt(ctx->s_frame.fmt))
    494		cfg |= FIMC_REG_CIDMAPARAM_R_64X32;
    495
    496	if (tiled_fmt(ctx->d_frame.fmt))
    497		cfg |= FIMC_REG_CIDMAPARAM_W_64X32;
    498
    499	writel(cfg, dev->regs + FIMC_REG_CIDMAPARAM);
    500}
    501
    502
    503void fimc_hw_set_input_path(struct fimc_ctx *ctx)
    504{
    505	struct fimc_dev *dev = ctx->fimc_dev;
    506
    507	u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
    508	cfg &= ~FIMC_REG_MSCTRL_INPUT_MASK;
    509
    510	if (ctx->in_path == FIMC_IO_DMA)
    511		cfg |= FIMC_REG_MSCTRL_INPUT_MEMORY;
    512	else
    513		cfg |= FIMC_REG_MSCTRL_INPUT_EXTCAM;
    514
    515	writel(cfg, dev->regs + FIMC_REG_MSCTRL);
    516}
    517
    518void fimc_hw_set_output_path(struct fimc_ctx *ctx)
    519{
    520	struct fimc_dev *dev = ctx->fimc_dev;
    521
    522	u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
    523	cfg &= ~FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
    524	if (ctx->out_path == FIMC_IO_LCDFIFO)
    525		cfg |= FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
    526	writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
    527}
    528
    529void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *addr)
    530{
    531	u32 cfg = readl(dev->regs + FIMC_REG_CIREAL_ISIZE);
    532	cfg |= FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
    533	writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
    534
    535	writel(addr->y, dev->regs + FIMC_REG_CIIYSA(0));
    536	writel(addr->cb, dev->regs + FIMC_REG_CIICBSA(0));
    537	writel(addr->cr, dev->regs + FIMC_REG_CIICRSA(0));
    538
    539	cfg &= ~FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
    540	writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
    541}
    542
    543void fimc_hw_set_output_addr(struct fimc_dev *dev,
    544			     struct fimc_addr *addr, int index)
    545{
    546	int i = (index == -1) ? 0 : index;
    547	do {
    548		writel(addr->y, dev->regs + FIMC_REG_CIOYSA(i));
    549		writel(addr->cb, dev->regs + FIMC_REG_CIOCBSA(i));
    550		writel(addr->cr, dev->regs + FIMC_REG_CIOCRSA(i));
    551		dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
    552		    i, addr->y, addr->cb, addr->cr);
    553	} while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
    554}
    555
    556int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
    557				struct fimc_source_info *cam)
    558{
    559	u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
    560
    561	cfg &= ~(FIMC_REG_CIGCTRL_INVPOLPCLK | FIMC_REG_CIGCTRL_INVPOLVSYNC |
    562		 FIMC_REG_CIGCTRL_INVPOLHREF | FIMC_REG_CIGCTRL_INVPOLHSYNC |
    563		 FIMC_REG_CIGCTRL_INVPOLFIELD);
    564
    565	if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
    566		cfg |= FIMC_REG_CIGCTRL_INVPOLPCLK;
    567
    568	if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
    569		cfg |= FIMC_REG_CIGCTRL_INVPOLVSYNC;
    570
    571	if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
    572		cfg |= FIMC_REG_CIGCTRL_INVPOLHREF;
    573
    574	if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
    575		cfg |= FIMC_REG_CIGCTRL_INVPOLHSYNC;
    576
    577	if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW)
    578		cfg |= FIMC_REG_CIGCTRL_INVPOLFIELD;
    579
    580	writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
    581
    582	return 0;
    583}
    584
    585struct mbus_pixfmt_desc {
    586	u32 pixelcode;
    587	u32 cisrcfmt;
    588	u16 bus_width;
    589};
    590
    591static const struct mbus_pixfmt_desc pix_desc[] = {
    592	{ MEDIA_BUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 },
    593	{ MEDIA_BUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 },
    594	{ MEDIA_BUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 },
    595	{ MEDIA_BUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 },
    596};
    597
    598int fimc_hw_set_camera_source(struct fimc_dev *fimc,
    599			      struct fimc_source_info *source)
    600{
    601	struct fimc_vid_cap *vc = &fimc->vid_cap;
    602	struct fimc_frame *f = &vc->ctx->s_frame;
    603	u32 bus_width, cfg = 0;
    604	int i;
    605
    606	switch (source->fimc_bus_type) {
    607	case FIMC_BUS_TYPE_ITU_601:
    608	case FIMC_BUS_TYPE_ITU_656:
    609		if (fimc_fmt_is_user_defined(f->fmt->color)) {
    610			cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
    611			break;
    612		}
    613
    614		for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
    615			if (vc->ci_fmt.code == pix_desc[i].pixelcode) {
    616				cfg = pix_desc[i].cisrcfmt;
    617				bus_width = pix_desc[i].bus_width;
    618				break;
    619			}
    620		}
    621
    622		if (i == ARRAY_SIZE(pix_desc)) {
    623			v4l2_err(&vc->ve.vdev,
    624				 "Camera color format not supported: %d\n",
    625				 vc->ci_fmt.code);
    626			return -EINVAL;
    627		}
    628
    629		if (source->fimc_bus_type == FIMC_BUS_TYPE_ITU_601) {
    630			if (bus_width == 8)
    631				cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
    632			else if (bus_width == 16)
    633				cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
    634		} /* else defaults to ITU-R BT.656 8-bit */
    635		break;
    636	case FIMC_BUS_TYPE_MIPI_CSI2:
    637		if (fimc_fmt_is_user_defined(f->fmt->color))
    638			cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
    639		break;
    640	default:
    641	case FIMC_BUS_TYPE_ISP_WRITEBACK:
    642		/* Anything to do here ? */
    643		break;
    644	}
    645
    646	cfg |= (f->o_width << 16) | f->o_height;
    647	writel(cfg, fimc->regs + FIMC_REG_CISRCFMT);
    648	return 0;
    649}
    650
    651void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
    652{
    653	u32 hoff2, voff2;
    654
    655	u32 cfg = readl(fimc->regs + FIMC_REG_CIWDOFST);
    656
    657	cfg &= ~(FIMC_REG_CIWDOFST_HOROFF_MASK | FIMC_REG_CIWDOFST_VEROFF_MASK);
    658	cfg |=  FIMC_REG_CIWDOFST_OFF_EN |
    659		(f->offs_h << 16) | f->offs_v;
    660
    661	writel(cfg, fimc->regs + FIMC_REG_CIWDOFST);
    662
    663	/* See CIWDOFSTn register description in the datasheet for details. */
    664	hoff2 = f->o_width - f->width - f->offs_h;
    665	voff2 = f->o_height - f->height - f->offs_v;
    666	cfg = (hoff2 << 16) | voff2;
    667	writel(cfg, fimc->regs + FIMC_REG_CIWDOFST2);
    668}
    669
    670int fimc_hw_set_camera_type(struct fimc_dev *fimc,
    671			    struct fimc_source_info *source)
    672{
    673	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
    674	u32 csis_data_alignment = 32;
    675	u32 cfg, tmp;
    676
    677	cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
    678
    679	/* Select ITU B interface, disable Writeback path and test pattern. */
    680	cfg &= ~(FIMC_REG_CIGCTRL_TESTPAT_MASK | FIMC_REG_CIGCTRL_SELCAM_ITU_A |
    681		FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB |
    682		FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG |
    683		FIMC_REG_CIGCTRL_SELWB_A);
    684
    685	switch (source->fimc_bus_type) {
    686	case FIMC_BUS_TYPE_MIPI_CSI2:
    687		cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI;
    688
    689		if (source->mux_id == 0)
    690			cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A;
    691
    692		/* TODO: add remaining supported formats. */
    693		switch (vid_cap->ci_fmt.code) {
    694		case MEDIA_BUS_FMT_VYUY8_2X8:
    695			tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
    696			break;
    697		case MEDIA_BUS_FMT_JPEG_1X8:
    698		case MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8:
    699			tmp = FIMC_REG_CSIIMGFMT_USER(1);
    700			cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
    701			break;
    702		default:
    703			v4l2_err(&vid_cap->ve.vdev,
    704				 "Not supported camera pixel format: %#x\n",
    705				 vid_cap->ci_fmt.code);
    706			return -EINVAL;
    707		}
    708		tmp |= (csis_data_alignment == 32) << 8;
    709
    710		writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT);
    711		break;
    712	case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656:
    713		if (source->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
    714			cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A;
    715		if (vid_cap->ci_fmt.code == MEDIA_BUS_FMT_JPEG_1X8)
    716			cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
    717		break;
    718	case FIMC_BUS_TYPE_LCD_WRITEBACK_A:
    719		cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
    720		fallthrough;
    721	case FIMC_BUS_TYPE_ISP_WRITEBACK:
    722		if (fimc->variant->has_isp_wb)
    723			cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
    724		else
    725			WARN_ONCE(1, "ISP Writeback input is not supported\n");
    726		break;
    727	default:
    728		v4l2_err(&vid_cap->ve.vdev,
    729			 "Invalid FIMC bus type selected: %d\n",
    730			 source->fimc_bus_type);
    731		return -EINVAL;
    732	}
    733	writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
    734
    735	return 0;
    736}
    737
    738void fimc_hw_clear_irq(struct fimc_dev *dev)
    739{
    740	u32 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
    741	cfg |= FIMC_REG_CIGCTRL_IRQ_CLR;
    742	writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
    743}
    744
    745void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on)
    746{
    747	u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
    748	if (on)
    749		cfg |= FIMC_REG_CISCCTRL_SCALERSTART;
    750	else
    751		cfg &= ~FIMC_REG_CISCCTRL_SCALERSTART;
    752	writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
    753}
    754
    755void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on)
    756{
    757	u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
    758	if (on)
    759		cfg |= FIMC_REG_MSCTRL_ENVID;
    760	else
    761		cfg &= ~FIMC_REG_MSCTRL_ENVID;
    762	writel(cfg, dev->regs + FIMC_REG_MSCTRL);
    763}
    764
    765/* Return an index to the buffer actually being written. */
    766s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
    767{
    768	s32 reg;
    769
    770	if (dev->drv_data->cistatus2) {
    771		reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
    772		return reg - 1;
    773	}
    774
    775	reg = readl(dev->regs + FIMC_REG_CISTATUS);
    776
    777	return (reg & FIMC_REG_CISTATUS_FRAMECNT_MASK) >>
    778		FIMC_REG_CISTATUS_FRAMECNT_SHIFT;
    779}
    780
    781/* Return an index to the buffer being written previously. */
    782s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
    783{
    784	s32 reg;
    785
    786	if (!dev->drv_data->cistatus2)
    787		return -1;
    788
    789	reg = readl(dev->regs + FIMC_REG_CISTATUS2);
    790	return ((reg >> 7) & 0x3f) - 1;
    791}
    792
    793/* Locking: the caller holds fimc->slock */
    794void fimc_activate_capture(struct fimc_ctx *ctx)
    795{
    796	fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled);
    797	fimc_hw_enable_capture(ctx);
    798}
    799
    800void fimc_deactivate_capture(struct fimc_dev *fimc)
    801{
    802	fimc_hw_en_lastirq(fimc, true);
    803	fimc_hw_disable_capture(fimc);
    804	fimc_hw_enable_scaler(fimc, false);
    805	fimc_hw_en_lastirq(fimc, false);
    806}
    807
    808int fimc_hw_camblk_cfg_writeback(struct fimc_dev *fimc)
    809{
    810	struct regmap *map = fimc->sysreg;
    811	unsigned int mask, val, camblk_cfg;
    812	int ret;
    813
    814	if (map == NULL)
    815		return 0;
    816
    817	ret = regmap_read(map, SYSREG_CAMBLK, &camblk_cfg);
    818	if (ret < 0 || ((camblk_cfg & 0x00700000) >> 20 != 0x3))
    819		return ret;
    820
    821	if (!WARN(fimc->id >= 3, "not supported id: %d\n", fimc->id))
    822		val = 0x1 << (fimc->id + 20);
    823	else
    824		val = 0;
    825
    826	mask = SYSREG_CAMBLK_FIFORST_ISP | SYSREG_CAMBLK_ISPWB_FULL_EN;
    827	ret = regmap_update_bits(map, SYSREG_CAMBLK, mask, val);
    828	if (ret < 0)
    829		return ret;
    830
    831	usleep_range(1000, 2000);
    832
    833	val |= SYSREG_CAMBLK_FIFORST_ISP;
    834	ret = regmap_update_bits(map, SYSREG_CAMBLK, mask, val);
    835	if (ret < 0)
    836		return ret;
    837
    838	mask = SYSREG_ISPBLK_FIFORST_CAM_BLK;
    839	ret = regmap_update_bits(map, SYSREG_ISPBLK, mask, ~mask);
    840	if (ret < 0)
    841		return ret;
    842
    843	usleep_range(1000, 2000);
    844
    845	return regmap_update_bits(map, SYSREG_ISPBLK, mask, mask);
    846}