487 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* linux/drivers/media/platform/exynos3250-jpeg/jpeg-hw.h3 *4 * Copyright (c) 2014 Samsung Electronics Co., Ltd.5 * http://www.samsung.com6 *7 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>8 */9 10#include <linux/io.h>11#include <linux/videodev2.h>12#include <linux/delay.h>13 14#include "jpeg-core.h"15#include "jpeg-regs.h"16#include "jpeg-hw-exynos3250.h"17 18void exynos3250_jpeg_reset(void __iomem *regs)19{20 u32 reg = 1;21 int count = 1000;22 23 writel(1, regs + EXYNOS3250_SW_RESET);24 /* no other way but polling for when JPEG IP becomes operational */25 while (reg != 0 && --count > 0) {26 udelay(1);27 cpu_relax();28 reg = readl(regs + EXYNOS3250_SW_RESET);29 }30 31 reg = 0;32 count = 1000;33 34 while (reg != 1 && --count > 0) {35 writel(1, regs + EXYNOS3250_JPGDRI);36 udelay(1);37 cpu_relax();38 reg = readl(regs + EXYNOS3250_JPGDRI);39 }40 41 writel(0, regs + EXYNOS3250_JPGDRI);42}43 44void exynos3250_jpeg_poweron(void __iomem *regs)45{46 writel(EXYNOS3250_POWER_ON, regs + EXYNOS3250_JPGCLKCON);47}48 49void exynos3250_jpeg_set_dma_num(void __iomem *regs)50{51 writel(((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT) &52 EXYNOS3250_WDMA_ISSUE_NUM_MASK) |53 ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT) &54 EXYNOS3250_RDMA_ISSUE_NUM_MASK) |55 ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT) &56 EXYNOS3250_ISSUE_GATHER_NUM_MASK),57 regs + EXYNOS3250_DMA_ISSUE_NUM);58}59 60void exynos3250_jpeg_clk_set(void __iomem *base)61{62 u32 reg;63 64 reg = readl(base + EXYNOS3250_JPGCMOD) & ~EXYNOS3250_HALF_EN_MASK;65 66 writel(reg | EXYNOS3250_HALF_EN, base + EXYNOS3250_JPGCMOD);67}68 69void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt)70{71 u32 reg;72 73 reg = readl(regs + EXYNOS3250_JPGCMOD) &74 EXYNOS3250_MODE_Y16_MASK;75 76 switch (fmt) {77 case V4L2_PIX_FMT_RGB32:78 reg |= EXYNOS3250_MODE_SEL_ARGB8888;79 break;80 case V4L2_PIX_FMT_BGR32:81 reg |= EXYNOS3250_MODE_SEL_ARGB8888 | EXYNOS3250_SRC_SWAP_RGB;82 break;83 case V4L2_PIX_FMT_RGB565:84 reg |= EXYNOS3250_MODE_SEL_RGB565;85 break;86 case V4L2_PIX_FMT_RGB565X:87 reg |= EXYNOS3250_MODE_SEL_RGB565 | EXYNOS3250_SRC_SWAP_RGB;88 break;89 case V4L2_PIX_FMT_YUYV:90 reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR;91 break;92 case V4L2_PIX_FMT_YVYU:93 reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR |94 EXYNOS3250_SRC_SWAP_UV;95 break;96 case V4L2_PIX_FMT_UYVY:97 reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM;98 break;99 case V4L2_PIX_FMT_VYUY:100 reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM |101 EXYNOS3250_SRC_SWAP_UV;102 break;103 case V4L2_PIX_FMT_NV12:104 reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV12;105 break;106 case V4L2_PIX_FMT_NV21:107 reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV21;108 break;109 case V4L2_PIX_FMT_YUV420:110 reg |= EXYNOS3250_MODE_SEL_420_3P;111 break;112 default:113 break;114 115 }116 117 writel(reg, regs + EXYNOS3250_JPGCMOD);118}119 120void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16)121{122 u32 reg;123 124 reg = readl(regs + EXYNOS3250_JPGCMOD);125 if (y16)126 reg |= EXYNOS3250_MODE_Y16;127 else128 reg &= ~EXYNOS3250_MODE_Y16_MASK;129 writel(reg, regs + EXYNOS3250_JPGCMOD);130}131 132void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode)133{134 u32 reg, m;135 136 if (mode == S5P_JPEG_ENCODE)137 m = EXYNOS3250_PROC_MODE_COMPR;138 else139 m = EXYNOS3250_PROC_MODE_DECOMPR;140 reg = readl(regs + EXYNOS3250_JPGMOD);141 reg &= ~EXYNOS3250_PROC_MODE_MASK;142 reg |= m;143 writel(reg, regs + EXYNOS3250_JPGMOD);144}145 146void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)147{148 u32 reg, m = 0;149 150 switch (mode) {151 case V4L2_JPEG_CHROMA_SUBSAMPLING_444:152 m = EXYNOS3250_SUBSAMPLING_MODE_444;153 break;154 case V4L2_JPEG_CHROMA_SUBSAMPLING_422:155 m = EXYNOS3250_SUBSAMPLING_MODE_422;156 break;157 case V4L2_JPEG_CHROMA_SUBSAMPLING_420:158 m = EXYNOS3250_SUBSAMPLING_MODE_420;159 break;160 }161 162 reg = readl(regs + EXYNOS3250_JPGMOD);163 reg &= ~EXYNOS3250_SUBSAMPLING_MODE_MASK;164 reg |= m;165 writel(reg, regs + EXYNOS3250_JPGMOD);166}167 168unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs)169{170 return readl(regs + EXYNOS3250_JPGMOD) &171 EXYNOS3250_SUBSAMPLING_MODE_MASK;172}173 174void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri)175{176 u32 reg;177 178 reg = dri & EXYNOS3250_JPGDRI_MASK;179 writel(reg, regs + EXYNOS3250_JPGDRI);180}181 182void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)183{184 unsigned long reg;185 186 reg = readl(regs + EXYNOS3250_QHTBL);187 reg &= ~EXYNOS3250_QT_NUM_MASK(t);188 reg |= (n << EXYNOS3250_QT_NUM_SHIFT(t)) &189 EXYNOS3250_QT_NUM_MASK(t);190 writel(reg, regs + EXYNOS3250_QHTBL);191}192 193void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t)194{195 unsigned long reg;196 197 reg = readl(regs + EXYNOS3250_QHTBL);198 reg &= ~EXYNOS3250_HT_NUM_AC_MASK(t);199 /* this driver uses table 0 for all color components */200 reg |= (0 << EXYNOS3250_HT_NUM_AC_SHIFT(t)) &201 EXYNOS3250_HT_NUM_AC_MASK(t);202 writel(reg, regs + EXYNOS3250_QHTBL);203}204 205void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t)206{207 unsigned long reg;208 209 reg = readl(regs + EXYNOS3250_QHTBL);210 reg &= ~EXYNOS3250_HT_NUM_DC_MASK(t);211 /* this driver uses table 0 for all color components */212 reg |= (0 << EXYNOS3250_HT_NUM_DC_SHIFT(t)) &213 EXYNOS3250_HT_NUM_DC_MASK(t);214 writel(reg, regs + EXYNOS3250_QHTBL);215}216 217void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y)218{219 u32 reg;220 221 reg = y & EXYNOS3250_JPGY_MASK;222 writel(reg, regs + EXYNOS3250_JPGY);223}224 225void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x)226{227 u32 reg;228 229 reg = x & EXYNOS3250_JPGX_MASK;230 writel(reg, regs + EXYNOS3250_JPGX);231}232 233#if 0 /* Currently unused */234unsigned int exynos3250_jpeg_get_y(void __iomem *regs)235{236 return readl(regs + EXYNOS3250_JPGY);237}238 239unsigned int exynos3250_jpeg_get_x(void __iomem *regs)240{241 return readl(regs + EXYNOS3250_JPGX);242}243#endif244 245void exynos3250_jpeg_interrupts_enable(void __iomem *regs)246{247 u32 reg;248 249 reg = readl(regs + EXYNOS3250_JPGINTSE);250 reg |= (EXYNOS3250_JPEG_DONE_EN |251 EXYNOS3250_WDMA_DONE_EN |252 EXYNOS3250_RDMA_DONE_EN |253 EXYNOS3250_ENC_STREAM_INT_EN |254 EXYNOS3250_CORE_DONE_EN |255 EXYNOS3250_ERR_INT_EN |256 EXYNOS3250_HEAD_INT_EN);257 writel(reg, regs + EXYNOS3250_JPGINTSE);258}259 260void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size)261{262 u32 reg;263 264 reg = size & EXYNOS3250_ENC_STREAM_BOUND_MASK;265 writel(reg, regs + EXYNOS3250_ENC_STREAM_BOUND);266}267 268void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt)269{270 u32 reg;271 272 switch (fmt) {273 case V4L2_PIX_FMT_RGB32:274 reg = EXYNOS3250_OUT_FMT_ARGB8888;275 break;276 case V4L2_PIX_FMT_BGR32:277 reg = EXYNOS3250_OUT_FMT_ARGB8888 | EXYNOS3250_OUT_SWAP_RGB;278 break;279 case V4L2_PIX_FMT_RGB565:280 reg = EXYNOS3250_OUT_FMT_RGB565;281 break;282 case V4L2_PIX_FMT_RGB565X:283 reg = EXYNOS3250_OUT_FMT_RGB565 | EXYNOS3250_OUT_SWAP_RGB;284 break;285 case V4L2_PIX_FMT_YUYV:286 reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR;287 break;288 case V4L2_PIX_FMT_YVYU:289 reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR |290 EXYNOS3250_OUT_SWAP_UV;291 break;292 case V4L2_PIX_FMT_UYVY:293 reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM;294 break;295 case V4L2_PIX_FMT_VYUY:296 reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM |297 EXYNOS3250_OUT_SWAP_UV;298 break;299 case V4L2_PIX_FMT_NV12:300 reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV12;301 break;302 case V4L2_PIX_FMT_NV21:303 reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV21;304 break;305 case V4L2_PIX_FMT_YUV420:306 reg = EXYNOS3250_OUT_FMT_420_3P;307 break;308 default:309 reg = 0;310 break;311 }312 313 writel(reg, regs + EXYNOS3250_OUTFORM);314}315 316void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr)317{318 writel(addr, regs + EXYNOS3250_JPG_JPGADR);319}320 321void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr)322{323 writel(img_addr->y, regs + EXYNOS3250_LUMA_BASE);324 writel(img_addr->cb, regs + EXYNOS3250_CHROMA_BASE);325 writel(img_addr->cr, regs + EXYNOS3250_CHROMA_CR_BASE);326}327 328void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,329 unsigned int width)330{331 u32 reg_luma = 0, reg_cr = 0, reg_cb = 0;332 333 switch (img_fmt) {334 case V4L2_PIX_FMT_RGB32:335 reg_luma = 4 * width;336 break;337 case V4L2_PIX_FMT_RGB565:338 case V4L2_PIX_FMT_RGB565X:339 case V4L2_PIX_FMT_YUYV:340 case V4L2_PIX_FMT_YVYU:341 case V4L2_PIX_FMT_UYVY:342 case V4L2_PIX_FMT_VYUY:343 reg_luma = 2 * width;344 break;345 case V4L2_PIX_FMT_NV12:346 case V4L2_PIX_FMT_NV21:347 reg_luma = width;348 reg_cb = reg_luma;349 break;350 case V4L2_PIX_FMT_YUV420:351 reg_luma = width;352 reg_cb = reg_cr = reg_luma / 2;353 break;354 default:355 break;356 }357 358 writel(reg_luma, regs + EXYNOS3250_LUMA_STRIDE);359 writel(reg_cb, regs + EXYNOS3250_CHROMA_STRIDE);360 writel(reg_cr, regs + EXYNOS3250_CHROMA_CR_STRIDE);361}362 363void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,364 unsigned int y_offset)365{366 u32 reg;367 368 reg = (y_offset << EXYNOS3250_LUMA_YY_OFFSET_SHIFT) &369 EXYNOS3250_LUMA_YY_OFFSET_MASK;370 reg |= (x_offset << EXYNOS3250_LUMA_YX_OFFSET_SHIFT) &371 EXYNOS3250_LUMA_YX_OFFSET_MASK;372 373 writel(reg, regs + EXYNOS3250_LUMA_XY_OFFSET);374 375 reg = (y_offset << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT) &376 EXYNOS3250_CHROMA_YY_OFFSET_MASK;377 reg |= (x_offset << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT) &378 EXYNOS3250_CHROMA_YX_OFFSET_MASK;379 380 writel(reg, regs + EXYNOS3250_CHROMA_XY_OFFSET);381 382 reg = (y_offset << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT) &383 EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK;384 reg |= (x_offset << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT) &385 EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK;386 387 writel(reg, regs + EXYNOS3250_CHROMA_CR_XY_OFFSET);388}389 390void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode)391{392 if (mode == S5P_JPEG_ENCODE) {393 writel(EXYNOS3250_JPEG_ENC_COEF1,394 base + EXYNOS3250_JPG_COEF(1));395 writel(EXYNOS3250_JPEG_ENC_COEF2,396 base + EXYNOS3250_JPG_COEF(2));397 writel(EXYNOS3250_JPEG_ENC_COEF3,398 base + EXYNOS3250_JPG_COEF(3));399 } else {400 writel(EXYNOS3250_JPEG_DEC_COEF1,401 base + EXYNOS3250_JPG_COEF(1));402 writel(EXYNOS3250_JPEG_DEC_COEF2,403 base + EXYNOS3250_JPG_COEF(2));404 writel(EXYNOS3250_JPEG_DEC_COEF3,405 base + EXYNOS3250_JPG_COEF(3));406 }407}408 409void exynos3250_jpeg_start(void __iomem *regs)410{411 writel(1, regs + EXYNOS3250_JSTART);412}413 414void exynos3250_jpeg_rstart(void __iomem *regs)415{416 writel(1, regs + EXYNOS3250_JRSTART);417}418 419unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs)420{421 return readl(regs + EXYNOS3250_JPGINTST);422}423 424void exynos3250_jpeg_clear_int_status(void __iomem *regs,425 unsigned int value)426{427 writel(value, regs + EXYNOS3250_JPGINTST);428}429 430unsigned int exynos3250_jpeg_operating(void __iomem *regs)431{432 return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK;433}434 435unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs)436{437 return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK;438}439 440void exynos3250_jpeg_dec_stream_size(void __iomem *regs,441 unsigned int size)442{443 writel(size & EXYNOS3250_DEC_STREAM_MASK,444 regs + EXYNOS3250_DEC_STREAM_SIZE);445}446 447void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs,448 unsigned int sratio)449{450 switch (sratio) {451 case 1:452 default:453 sratio = EXYNOS3250_DEC_SCALE_FACTOR_8_8;454 break;455 case 2:456 sratio = EXYNOS3250_DEC_SCALE_FACTOR_4_8;457 break;458 case 4:459 sratio = EXYNOS3250_DEC_SCALE_FACTOR_2_8;460 break;461 case 8:462 sratio = EXYNOS3250_DEC_SCALE_FACTOR_1_8;463 break;464 }465 466 writel(sratio & EXYNOS3250_DEC_SCALE_FACTOR_MASK,467 regs + EXYNOS3250_DEC_SCALING_RATIO);468}469 470void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value)471{472 time_value &= EXYNOS3250_TIMER_INIT_MASK;473 474 writel(EXYNOS3250_TIMER_INT_STAT | time_value,475 regs + EXYNOS3250_TIMER_SE);476}477 478unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs)479{480 return readl(regs + EXYNOS3250_TIMER_ST);481}482 483void exynos3250_jpeg_clear_timer_status(void __iomem *regs)484{485 writel(EXYNOS3250_TIMER_INT_STAT, regs + EXYNOS3250_TIMER_ST);486}487