linux/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c
<<
>>
Prefs
   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
  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        else
 128                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        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
 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#endif
 244
 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