linux/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c
<<
>>
Prefs
   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 = 1;
  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