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