brintos

brintos / linux-shallow public Read only

0
0
Text · 10.0 KiB · 995a1f0 Raw
427 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.4 *		http://www.samsung.com5 *6 * Samsung EXYNOS5 SoC series G-Scaler driver7 */8 9#include <linux/io.h>10#include <linux/delay.h>11 12#include "gsc-core.h"13 14void gsc_hw_set_sw_reset(struct gsc_dev *dev)15{16	writel(GSC_SW_RESET_SRESET, dev->regs + GSC_SW_RESET);17}18 19int gsc_wait_reset(struct gsc_dev *dev)20{21	unsigned long end = jiffies + msecs_to_jiffies(50);22	u32 cfg;23 24	while (time_before(jiffies, end)) {25		cfg = readl(dev->regs + GSC_SW_RESET);26		if (!cfg)27			return 0;28		usleep_range(10, 20);29	}30 31	return -EBUSY;32}33 34void gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask)35{36	u32 cfg;37 38	cfg = readl(dev->regs + GSC_IRQ);39	if (mask)40		cfg |= GSC_IRQ_FRMDONE_MASK;41	else42		cfg &= ~GSC_IRQ_FRMDONE_MASK;43	writel(cfg, dev->regs + GSC_IRQ);44}45 46void gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask)47{48	u32 cfg;49 50	cfg = readl(dev->regs + GSC_IRQ);51	if (mask)52		cfg |= GSC_IRQ_ENABLE;53	else54		cfg &= ~GSC_IRQ_ENABLE;55	writel(cfg, dev->regs + GSC_IRQ);56}57 58void gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift,59				bool enable)60{61	u32 cfg = readl(dev->regs + GSC_IN_BASE_ADDR_Y_MASK);62	u32 mask = 1 << shift;63 64	cfg &= ~mask;65	cfg |= enable << shift;66 67	writel(cfg, dev->regs + GSC_IN_BASE_ADDR_Y_MASK);68	writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CB_MASK);69	writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CR_MASK);70}71 72void gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift,73				bool enable)74{75	u32 cfg = readl(dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);76	u32 mask = 1 << shift;77 78	cfg &= ~mask;79	cfg |= enable << shift;80 81	writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);82	writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CB_MASK);83	writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CR_MASK);84}85 86void gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr,87				int index)88{89	pr_debug("src_buf[%d]: %pad, cb: %pad, cr: %pad", index,90			&addr->y, &addr->cb, &addr->cr);91	writel(addr->y, dev->regs + GSC_IN_BASE_ADDR_Y(index));92	writel(addr->cb, dev->regs + GSC_IN_BASE_ADDR_CB(index));93	writel(addr->cr, dev->regs + GSC_IN_BASE_ADDR_CR(index));94 95}96 97void gsc_hw_set_output_addr(struct gsc_dev *dev,98			     struct gsc_addr *addr, int index)99{100	pr_debug("dst_buf[%d]: %pad, cb: %pad, cr: %pad",101			index, &addr->y, &addr->cb, &addr->cr);102	writel(addr->y, dev->regs + GSC_OUT_BASE_ADDR_Y(index));103	writel(addr->cb, dev->regs + GSC_OUT_BASE_ADDR_CB(index));104	writel(addr->cr, dev->regs + GSC_OUT_BASE_ADDR_CR(index));105}106 107void gsc_hw_set_input_path(struct gsc_ctx *ctx)108{109	struct gsc_dev *dev = ctx->gsc_dev;110 111	u32 cfg = readl(dev->regs + GSC_IN_CON);112	cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);113 114	if (ctx->in_path == GSC_DMA)115		cfg |= GSC_IN_PATH_MEMORY;116 117	writel(cfg, dev->regs + GSC_IN_CON);118}119 120void gsc_hw_set_in_size(struct gsc_ctx *ctx)121{122	struct gsc_dev *dev = ctx->gsc_dev;123	struct gsc_frame *frame = &ctx->s_frame;124	u32 cfg;125 126	/* Set input pixel offset */127	cfg = GSC_SRCIMG_OFFSET_X(frame->crop.left);128	cfg |= GSC_SRCIMG_OFFSET_Y(frame->crop.top);129	writel(cfg, dev->regs + GSC_SRCIMG_OFFSET);130 131	/* Set input original size */132	cfg = GSC_SRCIMG_WIDTH(frame->f_width);133	cfg |= GSC_SRCIMG_HEIGHT(frame->f_height);134	writel(cfg, dev->regs + GSC_SRCIMG_SIZE);135 136	/* Set input cropped size */137	cfg = GSC_CROPPED_WIDTH(frame->crop.width);138	cfg |= GSC_CROPPED_HEIGHT(frame->crop.height);139	writel(cfg, dev->regs + GSC_CROPPED_SIZE);140}141 142void gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx)143{144	struct gsc_dev *dev = ctx->gsc_dev;145	struct gsc_frame *frame = &ctx->s_frame;146	u32 cfg;147 148	cfg = readl(dev->regs + GSC_IN_CON);149	if (frame->colorspace == V4L2_COLORSPACE_REC709)150		cfg |= GSC_IN_RGB_HD_WIDE;151	else152		cfg |= GSC_IN_RGB_SD_WIDE;153 154	if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)155		cfg |= GSC_IN_RGB565;156	else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)157		cfg |= GSC_IN_XRGB8888;158 159	writel(cfg, dev->regs + GSC_IN_CON);160}161 162void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)163{164	struct gsc_dev *dev = ctx->gsc_dev;165	struct gsc_frame *frame = &ctx->s_frame;166	u32 i, depth = 0;167	u32 cfg;168 169	cfg = readl(dev->regs + GSC_IN_CON);170	cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |171		 GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK |172		 GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);173	writel(cfg, dev->regs + GSC_IN_CON);174 175	if (is_rgb(frame->fmt->color)) {176		gsc_hw_set_in_image_rgb(ctx);177		return;178	}179	for (i = 0; i < frame->fmt->num_planes; i++)180		depth += frame->fmt->depth[i];181 182	switch (frame->fmt->num_comp) {183	case 1:184		cfg |= GSC_IN_YUV422_1P;185		if (frame->fmt->yorder == GSC_LSB_Y)186			cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;187		else188			cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;189		if (frame->fmt->corder == GSC_CBCR)190			cfg |= GSC_IN_CHROMA_ORDER_CBCR;191		else192			cfg |= GSC_IN_CHROMA_ORDER_CRCB;193		break;194	case 2:195		if (depth == 12)196			cfg |= GSC_IN_YUV420_2P;197		else198			cfg |= GSC_IN_YUV422_2P;199		if (frame->fmt->corder == GSC_CBCR)200			cfg |= GSC_IN_CHROMA_ORDER_CBCR;201		else202			cfg |= GSC_IN_CHROMA_ORDER_CRCB;203		break;204	case 3:205		if (depth == 12)206			cfg |= GSC_IN_YUV420_3P;207		else208			cfg |= GSC_IN_YUV422_3P;209		break;210	}211 212	if (is_tiled(frame->fmt))213		cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;214 215	writel(cfg, dev->regs + GSC_IN_CON);216}217 218void gsc_hw_set_output_path(struct gsc_ctx *ctx)219{220	struct gsc_dev *dev = ctx->gsc_dev;221 222	u32 cfg = readl(dev->regs + GSC_OUT_CON);223	cfg &= ~GSC_OUT_PATH_MASK;224 225	if (ctx->out_path == GSC_DMA)226		cfg |= GSC_OUT_PATH_MEMORY;227	else228		cfg |= GSC_OUT_PATH_LOCAL;229 230	writel(cfg, dev->regs + GSC_OUT_CON);231}232 233void gsc_hw_set_out_size(struct gsc_ctx *ctx)234{235	struct gsc_dev *dev = ctx->gsc_dev;236	struct gsc_frame *frame = &ctx->d_frame;237	u32 cfg;238 239	/* Set output original size */240	if (ctx->out_path == GSC_DMA) {241		cfg = GSC_DSTIMG_OFFSET_X(frame->crop.left);242		cfg |= GSC_DSTIMG_OFFSET_Y(frame->crop.top);243		writel(cfg, dev->regs + GSC_DSTIMG_OFFSET);244 245		cfg = GSC_DSTIMG_WIDTH(frame->f_width);246		cfg |= GSC_DSTIMG_HEIGHT(frame->f_height);247		writel(cfg, dev->regs + GSC_DSTIMG_SIZE);248	}249 250	/* Set output scaled size */251	if (ctx->gsc_ctrls.rotate->val == 90 ||252	    ctx->gsc_ctrls.rotate->val == 270) {253		cfg = GSC_SCALED_WIDTH(frame->crop.height);254		cfg |= GSC_SCALED_HEIGHT(frame->crop.width);255	} else {256		cfg = GSC_SCALED_WIDTH(frame->crop.width);257		cfg |= GSC_SCALED_HEIGHT(frame->crop.height);258	}259	writel(cfg, dev->regs + GSC_SCALED_SIZE);260}261 262void gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx)263{264	struct gsc_dev *dev = ctx->gsc_dev;265	struct gsc_frame *frame = &ctx->d_frame;266	u32 cfg;267 268	cfg = readl(dev->regs + GSC_OUT_CON);269	if (frame->colorspace == V4L2_COLORSPACE_REC709)270		cfg |= GSC_OUT_RGB_HD_WIDE;271	else272		cfg |= GSC_OUT_RGB_SD_WIDE;273 274	if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)275		cfg |= GSC_OUT_RGB565;276	else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)277		cfg |= GSC_OUT_XRGB8888;278 279	writel(cfg, dev->regs + GSC_OUT_CON);280}281 282void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)283{284	struct gsc_dev *dev = ctx->gsc_dev;285	struct gsc_frame *frame = &ctx->d_frame;286	u32 i, depth = 0;287	u32 cfg;288 289	cfg = readl(dev->regs + GSC_OUT_CON);290	cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |291		 GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK |292		 GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);293	writel(cfg, dev->regs + GSC_OUT_CON);294 295	if (is_rgb(frame->fmt->color)) {296		gsc_hw_set_out_image_rgb(ctx);297		return;298	}299 300	if (ctx->out_path != GSC_DMA) {301		cfg |= GSC_OUT_YUV444;302		goto end_set;303	}304 305	for (i = 0; i < frame->fmt->num_planes; i++)306		depth += frame->fmt->depth[i];307 308	switch (frame->fmt->num_comp) {309	case 1:310		cfg |= GSC_OUT_YUV422_1P;311		if (frame->fmt->yorder == GSC_LSB_Y)312			cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;313		else314			cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;315		if (frame->fmt->corder == GSC_CBCR)316			cfg |= GSC_OUT_CHROMA_ORDER_CBCR;317		else318			cfg |= GSC_OUT_CHROMA_ORDER_CRCB;319		break;320	case 2:321		if (depth == 12)322			cfg |= GSC_OUT_YUV420_2P;323		else324			cfg |= GSC_OUT_YUV422_2P;325		if (frame->fmt->corder == GSC_CBCR)326			cfg |= GSC_OUT_CHROMA_ORDER_CBCR;327		else328			cfg |= GSC_OUT_CHROMA_ORDER_CRCB;329		break;330	case 3:331		cfg |= GSC_OUT_YUV420_3P;332		break;333	}334 335	if (is_tiled(frame->fmt))336		cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;337 338end_set:339	writel(cfg, dev->regs + GSC_OUT_CON);340}341 342void gsc_hw_set_prescaler(struct gsc_ctx *ctx)343{344	struct gsc_dev *dev = ctx->gsc_dev;345	struct gsc_scaler *sc = &ctx->scaler;346	u32 cfg;347 348	cfg = GSC_PRESC_SHFACTOR(sc->pre_shfactor);349	cfg |= GSC_PRESC_H_RATIO(sc->pre_hratio);350	cfg |= GSC_PRESC_V_RATIO(sc->pre_vratio);351	writel(cfg, dev->regs + GSC_PRE_SCALE_RATIO);352}353 354void gsc_hw_set_mainscaler(struct gsc_ctx *ctx)355{356	struct gsc_dev *dev = ctx->gsc_dev;357	struct gsc_scaler *sc = &ctx->scaler;358	u32 cfg;359 360	cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);361	writel(cfg, dev->regs + GSC_MAIN_H_RATIO);362 363	cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio);364	writel(cfg, dev->regs + GSC_MAIN_V_RATIO);365}366 367void gsc_hw_set_rotation(struct gsc_ctx *ctx)368{369	struct gsc_dev *dev = ctx->gsc_dev;370	u32 cfg;371 372	cfg = readl(dev->regs + GSC_IN_CON);373	cfg &= ~GSC_IN_ROT_MASK;374 375	switch (ctx->gsc_ctrls.rotate->val) {376	case 270:377		cfg |= GSC_IN_ROT_270;378		break;379	case 180:380		cfg |= GSC_IN_ROT_180;381		break;382	case 90:383		if (ctx->gsc_ctrls.hflip->val)384			cfg |= GSC_IN_ROT_90_XFLIP;385		else if (ctx->gsc_ctrls.vflip->val)386			cfg |= GSC_IN_ROT_90_YFLIP;387		else388			cfg |= GSC_IN_ROT_90;389		break;390	case 0:391		if (ctx->gsc_ctrls.hflip->val)392			cfg |= GSC_IN_ROT_XFLIP;393		else if (ctx->gsc_ctrls.vflip->val)394			cfg |= GSC_IN_ROT_YFLIP;395	}396 397	writel(cfg, dev->regs + GSC_IN_CON);398}399 400void gsc_hw_set_global_alpha(struct gsc_ctx *ctx)401{402	struct gsc_dev *dev = ctx->gsc_dev;403	struct gsc_frame *frame = &ctx->d_frame;404	u32 cfg;405 406	if (!is_rgb(frame->fmt->color)) {407		pr_debug("Not a RGB format");408		return;409	}410 411	cfg = readl(dev->regs + GSC_OUT_CON);412	cfg &= ~GSC_OUT_GLOBAL_ALPHA_MASK;413 414	cfg |= GSC_OUT_GLOBAL_ALPHA(ctx->gsc_ctrls.global_alpha->val);415	writel(cfg, dev->regs + GSC_OUT_CON);416}417 418void gsc_hw_set_sfr_update(struct gsc_ctx *ctx)419{420	struct gsc_dev *dev = ctx->gsc_dev;421	u32 cfg;422 423	cfg = readl(dev->regs + GSC_ENABLE);424	cfg |= GSC_ENABLE_SFR_UPDATE;425	writel(cfg, dev->regs + GSC_ENABLE);426}427