brintos

brintos / linux-shallow public Read only

0
0
Text · 22.4 KiB · b4ee39e Raw
847 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Register interface file for Samsung Camera Interface (FIMC) driver4 *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 rotator83	 * 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		else89			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	const 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		else128			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	else137		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	const 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	const struct fimc_frame *frame = &ctx->d_frame;170	const struct fimc_dma_offset *offset = &frame->dma_offset;171	const 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	else217		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	else227		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	const struct fimc_frame *src_frame = &ctx->s_frame;252	const 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	else357		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	const 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	const 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	const struct fimc_frame *frame = &ctx->s_frame;424	const 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_MASK446		 | FIMC_REG_MSCTRL_IN_BURST_COUNT_MASK447		 | FIMC_REG_MSCTRL_INPUT_MASK448		 | FIMC_REG_MSCTRL_C_INT_IN_MASK449		 | FIMC_REG_MSCTRL_2P_IN_ORDER_MASK450		 | FIMC_REG_MSCTRL_ORDER422_MASK);451 452	cfg |= (FIMC_REG_MSCTRL_IN_BURST_COUNT(4)453		| FIMC_REG_MSCTRL_INPUT_MEMORY454		| 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		else466			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_1p472				| 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_2p478					| FIMC_REG_MSCTRL_C_INT_IN_2PLANE;479			else480				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	else513		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, const 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			     const 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				const 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	const struct fimc_vid_cap *vc = &fimc->vid_cap;602	const 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, const 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			    const struct fimc_source_info *source)672{673	const 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		else725			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	else751		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	else761		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	else824		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}847