1 // SPDX-License-Identifier: GPL-2.0-only 2 /* linux/drivers/media/platform/exynos3250-jpeg/jpeg-hw.h 3 * 4 * Copyright (c) 2014 Samsung Electronics Co., Ltd. 5 * http://www.samsung.com 6 * 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 18 void 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 44 void exynos3250_jpeg_poweron(void __iomem *regs) 45 { 46 writel(EXYNOS3250_POWER_ON, regs + EXYNOS3250_JPGCLKCON); 47 } 48 49 void 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 60 void 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 69 void 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 120 void 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 else 128 reg &= ~EXYNOS3250_MODE_Y16_MASK; 129 writel(reg, regs + EXYNOS3250_JPGCMOD); 130 } 131 132 void 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 else 139 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 146 void 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 168 unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs) 169 { 170 return readl(regs + EXYNOS3250_JPGMOD) & 171 EXYNOS3250_SUBSAMPLING_MODE_MASK; 172 } 173 174 void 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 182 void 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 193 void 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 205 void 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 217 void 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 225 void 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 */ 234 unsigned int exynos3250_jpeg_get_y(void __iomem *regs) 235 { 236 return readl(regs + EXYNOS3250_JPGY); 237 } 238 239 unsigned int exynos3250_jpeg_get_x(void __iomem *regs) 240 { 241 return readl(regs + EXYNOS3250_JPGX); 242 } 243 #endif 244 245 void 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 260 void 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 268 void 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 316 void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr) 317 { 318 writel(addr, regs + EXYNOS3250_JPG_JPGADR); 319 } 320 321 void 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 328 void 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 363 void 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 390 void 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 409 void exynos3250_jpeg_start(void __iomem *regs) 410 { 411 writel(1, regs + EXYNOS3250_JSTART); 412 } 413 414 void exynos3250_jpeg_rstart(void __iomem *regs) 415 { 416 writel(1, regs + EXYNOS3250_JRSTART); 417 } 418 419 unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs) 420 { 421 return readl(regs + EXYNOS3250_JPGINTST); 422 } 423 424 void exynos3250_jpeg_clear_int_status(void __iomem *regs, 425 unsigned int value) 426 { 427 writel(value, regs + EXYNOS3250_JPGINTST); 428 } 429 430 unsigned int exynos3250_jpeg_operating(void __iomem *regs) 431 { 432 return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK; 433 } 434 435 unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs) 436 { 437 return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK; 438 } 439 440 void 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 447 void 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 470 void 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 478 unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs) 479 { 480 return readl(regs + EXYNOS3250_TIMER_ST); 481 } 482 483 void exynos3250_jpeg_clear_timer_status(void __iomem *regs) 484 { 485 writel(EXYNOS3250_TIMER_INT_STAT, regs + EXYNOS3250_TIMER_ST); 486 } 487