linux/drivers/media/platform/exynos-gsc/gsc-regs.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
   3 *              http://www.samsung.com
   4 *
   5 * Samsung EXYNOS5 SoC series G-Scaler driver
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published
   9 * by the Free Software Foundation, either version 2 of the License,
  10 * or (at your option) any later version.
  11 */
  12
  13#include <linux/io.h>
  14#include <linux/delay.h>
  15
  16#include "gsc-core.h"
  17
  18void gsc_hw_set_sw_reset(struct gsc_dev *dev)
  19{
  20        writel(GSC_SW_RESET_SRESET, dev->regs + GSC_SW_RESET);
  21}
  22
  23int gsc_wait_reset(struct gsc_dev *dev)
  24{
  25        unsigned long end = jiffies + msecs_to_jiffies(50);
  26        u32 cfg;
  27
  28        while (time_before(jiffies, end)) {
  29                cfg = readl(dev->regs + GSC_SW_RESET);
  30                if (!cfg)
  31                        return 0;
  32                usleep_range(10, 20);
  33        }
  34
  35        return -EBUSY;
  36}
  37
  38void gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask)
  39{
  40        u32 cfg;
  41
  42        cfg = readl(dev->regs + GSC_IRQ);
  43        if (mask)
  44                cfg |= GSC_IRQ_FRMDONE_MASK;
  45        else
  46                cfg &= ~GSC_IRQ_FRMDONE_MASK;
  47        writel(cfg, dev->regs + GSC_IRQ);
  48}
  49
  50void gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask)
  51{
  52        u32 cfg;
  53
  54        cfg = readl(dev->regs + GSC_IRQ);
  55        if (mask)
  56                cfg |= GSC_IRQ_ENABLE;
  57        else
  58                cfg &= ~GSC_IRQ_ENABLE;
  59        writel(cfg, dev->regs + GSC_IRQ);
  60}
  61
  62void gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift,
  63                                bool enable)
  64{
  65        u32 cfg = readl(dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
  66        u32 mask = 1 << shift;
  67
  68        cfg &= ~mask;
  69        cfg |= enable << shift;
  70
  71        writel(cfg, dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
  72        writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CB_MASK);
  73        writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CR_MASK);
  74}
  75
  76void gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift,
  77                                bool enable)
  78{
  79        u32 cfg = readl(dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
  80        u32 mask = 1 << shift;
  81
  82        cfg &= ~mask;
  83        cfg |= enable << shift;
  84
  85        writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
  86        writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CB_MASK);
  87        writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CR_MASK);
  88}
  89
  90void gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr,
  91                                int index)
  92{
  93        pr_debug("src_buf[%d]: %pad, cb: %pad, cr: %pad", index,
  94                        &addr->y, &addr->cb, &addr->cr);
  95        writel(addr->y, dev->regs + GSC_IN_BASE_ADDR_Y(index));
  96        writel(addr->cb, dev->regs + GSC_IN_BASE_ADDR_CB(index));
  97        writel(addr->cr, dev->regs + GSC_IN_BASE_ADDR_CR(index));
  98
  99}
 100
 101void gsc_hw_set_output_addr(struct gsc_dev *dev,
 102                             struct gsc_addr *addr, int index)
 103{
 104        pr_debug("dst_buf[%d]: %pad, cb: %pad, cr: %pad",
 105                        index, &addr->y, &addr->cb, &addr->cr);
 106        writel(addr->y, dev->regs + GSC_OUT_BASE_ADDR_Y(index));
 107        writel(addr->cb, dev->regs + GSC_OUT_BASE_ADDR_CB(index));
 108        writel(addr->cr, dev->regs + GSC_OUT_BASE_ADDR_CR(index));
 109}
 110
 111void gsc_hw_set_input_path(struct gsc_ctx *ctx)
 112{
 113        struct gsc_dev *dev = ctx->gsc_dev;
 114
 115        u32 cfg = readl(dev->regs + GSC_IN_CON);
 116        cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
 117
 118        if (ctx->in_path == GSC_DMA)
 119                cfg |= GSC_IN_PATH_MEMORY;
 120
 121        writel(cfg, dev->regs + GSC_IN_CON);
 122}
 123
 124void gsc_hw_set_in_size(struct gsc_ctx *ctx)
 125{
 126        struct gsc_dev *dev = ctx->gsc_dev;
 127        struct gsc_frame *frame = &ctx->s_frame;
 128        u32 cfg;
 129
 130        /* Set input pixel offset */
 131        cfg = GSC_SRCIMG_OFFSET_X(frame->crop.left);
 132        cfg |= GSC_SRCIMG_OFFSET_Y(frame->crop.top);
 133        writel(cfg, dev->regs + GSC_SRCIMG_OFFSET);
 134
 135        /* Set input original size */
 136        cfg = GSC_SRCIMG_WIDTH(frame->f_width);
 137        cfg |= GSC_SRCIMG_HEIGHT(frame->f_height);
 138        writel(cfg, dev->regs + GSC_SRCIMG_SIZE);
 139
 140        /* Set input cropped size */
 141        cfg = GSC_CROPPED_WIDTH(frame->crop.width);
 142        cfg |= GSC_CROPPED_HEIGHT(frame->crop.height);
 143        writel(cfg, dev->regs + GSC_CROPPED_SIZE);
 144}
 145
 146void gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx)
 147{
 148        struct gsc_dev *dev = ctx->gsc_dev;
 149        struct gsc_frame *frame = &ctx->s_frame;
 150        u32 cfg;
 151
 152        cfg = readl(dev->regs + GSC_IN_CON);
 153        if (frame->colorspace == V4L2_COLORSPACE_REC709)
 154                cfg |= GSC_IN_RGB_HD_WIDE;
 155        else
 156                cfg |= GSC_IN_RGB_SD_WIDE;
 157
 158        if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
 159                cfg |= GSC_IN_RGB565;
 160        else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
 161                cfg |= GSC_IN_XRGB8888;
 162
 163        writel(cfg, dev->regs + GSC_IN_CON);
 164}
 165
 166void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
 167{
 168        struct gsc_dev *dev = ctx->gsc_dev;
 169        struct gsc_frame *frame = &ctx->s_frame;
 170        u32 i, depth = 0;
 171        u32 cfg;
 172
 173        cfg = readl(dev->regs + GSC_IN_CON);
 174        cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
 175                 GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK |
 176                 GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
 177        writel(cfg, dev->regs + GSC_IN_CON);
 178
 179        if (is_rgb(frame->fmt->color)) {
 180                gsc_hw_set_in_image_rgb(ctx);
 181                return;
 182        }
 183        for (i = 0; i < frame->fmt->num_planes; i++)
 184                depth += frame->fmt->depth[i];
 185
 186        switch (frame->fmt->num_comp) {
 187        case 1:
 188                cfg |= GSC_IN_YUV422_1P;
 189                if (frame->fmt->yorder == GSC_LSB_Y)
 190                        cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;
 191                else
 192                        cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;
 193                if (frame->fmt->corder == GSC_CBCR)
 194                        cfg |= GSC_IN_CHROMA_ORDER_CBCR;
 195                else
 196                        cfg |= GSC_IN_CHROMA_ORDER_CRCB;
 197                break;
 198        case 2:
 199                if (depth == 12)
 200                        cfg |= GSC_IN_YUV420_2P;
 201                else
 202                        cfg |= GSC_IN_YUV422_2P;
 203                if (frame->fmt->corder == GSC_CBCR)
 204                        cfg |= GSC_IN_CHROMA_ORDER_CBCR;
 205                else
 206                        cfg |= GSC_IN_CHROMA_ORDER_CRCB;
 207                break;
 208        case 3:
 209                if (depth == 12)
 210                        cfg |= GSC_IN_YUV420_3P;
 211                else
 212                        cfg |= GSC_IN_YUV422_3P;
 213                break;
 214        }
 215
 216        if (is_tiled(frame->fmt))
 217                cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;
 218
 219        writel(cfg, dev->regs + GSC_IN_CON);
 220}
 221
 222void gsc_hw_set_output_path(struct gsc_ctx *ctx)
 223{
 224        struct gsc_dev *dev = ctx->gsc_dev;
 225
 226        u32 cfg = readl(dev->regs + GSC_OUT_CON);
 227        cfg &= ~GSC_OUT_PATH_MASK;
 228
 229        if (ctx->out_path == GSC_DMA)
 230                cfg |= GSC_OUT_PATH_MEMORY;
 231        else
 232                cfg |= GSC_OUT_PATH_LOCAL;
 233
 234        writel(cfg, dev->regs + GSC_OUT_CON);
 235}
 236
 237void gsc_hw_set_out_size(struct gsc_ctx *ctx)
 238{
 239        struct gsc_dev *dev = ctx->gsc_dev;
 240        struct gsc_frame *frame = &ctx->d_frame;
 241        u32 cfg;
 242
 243        /* Set output original size */
 244        if (ctx->out_path == GSC_DMA) {
 245                cfg = GSC_DSTIMG_OFFSET_X(frame->crop.left);
 246                cfg |= GSC_DSTIMG_OFFSET_Y(frame->crop.top);
 247                writel(cfg, dev->regs + GSC_DSTIMG_OFFSET);
 248
 249                cfg = GSC_DSTIMG_WIDTH(frame->f_width);
 250                cfg |= GSC_DSTIMG_HEIGHT(frame->f_height);
 251                writel(cfg, dev->regs + GSC_DSTIMG_SIZE);
 252        }
 253
 254        /* Set output scaled size */
 255        if (ctx->gsc_ctrls.rotate->val == 90 ||
 256            ctx->gsc_ctrls.rotate->val == 270) {
 257                cfg = GSC_SCALED_WIDTH(frame->crop.height);
 258                cfg |= GSC_SCALED_HEIGHT(frame->crop.width);
 259        } else {
 260                cfg = GSC_SCALED_WIDTH(frame->crop.width);
 261                cfg |= GSC_SCALED_HEIGHT(frame->crop.height);
 262        }
 263        writel(cfg, dev->regs + GSC_SCALED_SIZE);
 264}
 265
 266void gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx)
 267{
 268        struct gsc_dev *dev = ctx->gsc_dev;
 269        struct gsc_frame *frame = &ctx->d_frame;
 270        u32 cfg;
 271
 272        cfg = readl(dev->regs + GSC_OUT_CON);
 273        if (frame->colorspace == V4L2_COLORSPACE_REC709)
 274                cfg |= GSC_OUT_RGB_HD_WIDE;
 275        else
 276                cfg |= GSC_OUT_RGB_SD_WIDE;
 277
 278        if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
 279                cfg |= GSC_OUT_RGB565;
 280        else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
 281                cfg |= GSC_OUT_XRGB8888;
 282
 283        writel(cfg, dev->regs + GSC_OUT_CON);
 284}
 285
 286void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
 287{
 288        struct gsc_dev *dev = ctx->gsc_dev;
 289        struct gsc_frame *frame = &ctx->d_frame;
 290        u32 i, depth = 0;
 291        u32 cfg;
 292
 293        cfg = readl(dev->regs + GSC_OUT_CON);
 294        cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
 295                 GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK |
 296                 GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
 297        writel(cfg, dev->regs + GSC_OUT_CON);
 298
 299        if (is_rgb(frame->fmt->color)) {
 300                gsc_hw_set_out_image_rgb(ctx);
 301                return;
 302        }
 303
 304        if (ctx->out_path != GSC_DMA) {
 305                cfg |= GSC_OUT_YUV444;
 306                goto end_set;
 307        }
 308
 309        for (i = 0; i < frame->fmt->num_planes; i++)
 310                depth += frame->fmt->depth[i];
 311
 312        switch (frame->fmt->num_comp) {
 313        case 1:
 314                cfg |= GSC_OUT_YUV422_1P;
 315                if (frame->fmt->yorder == GSC_LSB_Y)
 316                        cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;
 317                else
 318                        cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;
 319                if (frame->fmt->corder == GSC_CBCR)
 320                        cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
 321                else
 322                        cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
 323                break;
 324        case 2:
 325                if (depth == 12)
 326                        cfg |= GSC_OUT_YUV420_2P;
 327                else
 328                        cfg |= GSC_OUT_YUV422_2P;
 329                if (frame->fmt->corder == GSC_CBCR)
 330                        cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
 331                else
 332                        cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
 333                break;
 334        case 3:
 335                cfg |= GSC_OUT_YUV420_3P;
 336                break;
 337        }
 338
 339        if (is_tiled(frame->fmt))
 340                cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;
 341
 342end_set:
 343        writel(cfg, dev->regs + GSC_OUT_CON);
 344}
 345
 346void gsc_hw_set_prescaler(struct gsc_ctx *ctx)
 347{
 348        struct gsc_dev *dev = ctx->gsc_dev;
 349        struct gsc_scaler *sc = &ctx->scaler;
 350        u32 cfg;
 351
 352        cfg = GSC_PRESC_SHFACTOR(sc->pre_shfactor);
 353        cfg |= GSC_PRESC_H_RATIO(sc->pre_hratio);
 354        cfg |= GSC_PRESC_V_RATIO(sc->pre_vratio);
 355        writel(cfg, dev->regs + GSC_PRE_SCALE_RATIO);
 356}
 357
 358void gsc_hw_set_mainscaler(struct gsc_ctx *ctx)
 359{
 360        struct gsc_dev *dev = ctx->gsc_dev;
 361        struct gsc_scaler *sc = &ctx->scaler;
 362        u32 cfg;
 363
 364        cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
 365        writel(cfg, dev->regs + GSC_MAIN_H_RATIO);
 366
 367        cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio);
 368        writel(cfg, dev->regs + GSC_MAIN_V_RATIO);
 369}
 370
 371void gsc_hw_set_rotation(struct gsc_ctx *ctx)
 372{
 373        struct gsc_dev *dev = ctx->gsc_dev;
 374        u32 cfg;
 375
 376        cfg = readl(dev->regs + GSC_IN_CON);
 377        cfg &= ~GSC_IN_ROT_MASK;
 378
 379        switch (ctx->gsc_ctrls.rotate->val) {
 380        case 270:
 381                cfg |= GSC_IN_ROT_270;
 382                break;
 383        case 180:
 384                cfg |= GSC_IN_ROT_180;
 385                break;
 386        case 90:
 387                if (ctx->gsc_ctrls.hflip->val)
 388                        cfg |= GSC_IN_ROT_90_XFLIP;
 389                else if (ctx->gsc_ctrls.vflip->val)
 390                        cfg |= GSC_IN_ROT_90_YFLIP;
 391                else
 392                        cfg |= GSC_IN_ROT_90;
 393                break;
 394        case 0:
 395                if (ctx->gsc_ctrls.hflip->val)
 396                        cfg |= GSC_IN_ROT_XFLIP;
 397                else if (ctx->gsc_ctrls.vflip->val)
 398                        cfg |= GSC_IN_ROT_YFLIP;
 399        }
 400
 401        writel(cfg, dev->regs + GSC_IN_CON);
 402}
 403
 404void gsc_hw_set_global_alpha(struct gsc_ctx *ctx)
 405{
 406        struct gsc_dev *dev = ctx->gsc_dev;
 407        struct gsc_frame *frame = &ctx->d_frame;
 408        u32 cfg;
 409
 410        if (!is_rgb(frame->fmt->color)) {
 411                pr_debug("Not a RGB format");
 412                return;
 413        }
 414
 415        cfg = readl(dev->regs + GSC_OUT_CON);
 416        cfg &= ~GSC_OUT_GLOBAL_ALPHA_MASK;
 417
 418        cfg |= GSC_OUT_GLOBAL_ALPHA(ctx->gsc_ctrls.global_alpha->val);
 419        writel(cfg, dev->regs + GSC_OUT_CON);
 420}
 421
 422void gsc_hw_set_sfr_update(struct gsc_ctx *ctx)
 423{
 424        struct gsc_dev *dev = ctx->gsc_dev;
 425        u32 cfg;
 426
 427        cfg = readl(dev->regs + GSC_ENABLE);
 428        cfg |= GSC_ENABLE_SFR_UPDATE;
 429        writel(cfg, dev->regs + GSC_ENABLE);
 430}
 431