linux/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * camss-vfe-4-7.c
   4 *
   5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v4.7
   6 *
   7 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
   8 * Copyright (C) 2015-2018 Linaro Ltd.
   9 */
  10
  11#include <linux/device.h>
  12#include <linux/interrupt.h>
  13#include <linux/io.h>
  14#include <linux/iopoll.h>
  15
  16#include "camss.h"
  17#include "camss-vfe.h"
  18#include "camss-vfe-gen1.h"
  19
  20
  21#define VFE_0_HW_VERSION                0x000
  22
  23#define VFE_0_GLOBAL_RESET_CMD          0x018
  24#define VFE_0_GLOBAL_RESET_CMD_CORE     BIT(0)
  25#define VFE_0_GLOBAL_RESET_CMD_CAMIF    BIT(1)
  26#define VFE_0_GLOBAL_RESET_CMD_BUS      BIT(2)
  27#define VFE_0_GLOBAL_RESET_CMD_BUS_BDG  BIT(3)
  28#define VFE_0_GLOBAL_RESET_CMD_REGISTER BIT(4)
  29#define VFE_0_GLOBAL_RESET_CMD_PM       BIT(5)
  30#define VFE_0_GLOBAL_RESET_CMD_BUS_MISR BIT(6)
  31#define VFE_0_GLOBAL_RESET_CMD_TESTGEN  BIT(7)
  32#define VFE_0_GLOBAL_RESET_CMD_DSP      BIT(8)
  33#define VFE_0_GLOBAL_RESET_CMD_IDLE_CGC BIT(9)
  34
  35#define VFE_0_MODULE_LENS_EN            0x040
  36#define VFE_0_MODULE_LENS_EN_DEMUX              BIT(2)
  37#define VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE    BIT(3)
  38
  39#define VFE_0_MODULE_ZOOM_EN            0x04c
  40#define VFE_0_MODULE_ZOOM_EN_SCALE_ENC          BIT(1)
  41#define VFE_0_MODULE_ZOOM_EN_CROP_ENC           BIT(2)
  42#define VFE_0_MODULE_ZOOM_EN_REALIGN_BUF        BIT(9)
  43
  44#define VFE_0_CORE_CFG                  0x050
  45#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR     0x4
  46#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB     0x5
  47#define VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY     0x6
  48#define VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY     0x7
  49#define VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN  BIT(4)
  50
  51#define VFE_0_IRQ_CMD                   0x058
  52#define VFE_0_IRQ_CMD_GLOBAL_CLEAR      BIT(0)
  53
  54#define VFE_0_IRQ_MASK_0                0x05c
  55#define VFE_0_IRQ_MASK_0_CAMIF_SOF                      BIT(0)
  56#define VFE_0_IRQ_MASK_0_CAMIF_EOF                      BIT(1)
  57#define VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n)             BIT((n) + 5)
  58#define VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(n)           \
  59        ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n))
  60#define VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(n)    BIT((n) + 8)
  61#define VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(n)      BIT((n) + 25)
  62#define VFE_0_IRQ_MASK_0_RESET_ACK                      BIT(31)
  63#define VFE_0_IRQ_MASK_1                0x060
  64#define VFE_0_IRQ_MASK_1_CAMIF_ERROR                    BIT(0)
  65#define VFE_0_IRQ_MASK_1_VIOLATION                      BIT(7)
  66#define VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK               BIT(8)
  67#define VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(n) BIT((n) + 9)
  68#define VFE_0_IRQ_MASK_1_RDIn_SOF(n)                    BIT((n) + 29)
  69
  70#define VFE_0_IRQ_CLEAR_0               0x064
  71#define VFE_0_IRQ_CLEAR_1               0x068
  72
  73#define VFE_0_IRQ_STATUS_0              0x06c
  74#define VFE_0_IRQ_STATUS_0_CAMIF_SOF                    BIT(0)
  75#define VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n)           BIT((n) + 5)
  76#define VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(n)         \
  77        ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n))
  78#define VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(n)  BIT((n) + 8)
  79#define VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(n)    BIT((n) + 25)
  80#define VFE_0_IRQ_STATUS_0_RESET_ACK                    BIT(31)
  81#define VFE_0_IRQ_STATUS_1              0x070
  82#define VFE_0_IRQ_STATUS_1_VIOLATION                    BIT(7)
  83#define VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK             BIT(8)
  84#define VFE_0_IRQ_STATUS_1_RDIn_SOF(n)                  BIT((n) + 29)
  85
  86#define VFE_0_IRQ_COMPOSITE_MASK_0      0x074
  87#define VFE_0_VIOLATION_STATUS          0x07c
  88
  89#define VFE_0_BUS_CMD                   0x80
  90#define VFE_0_BUS_CMD_Mx_RLD_CMD(x)     BIT(x)
  91
  92#define VFE_0_BUS_CFG                   0x084
  93
  94#define VFE_0_BUS_XBAR_CFG_x(x)         (0x90 + 0x4 * ((x) / 2))
  95#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN                   BIT(2)
  96#define VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN                   BIT(3)
  97#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTRA           (0x1 << 4)
  98#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER           (0x2 << 4)
  99#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA     (0x3 << 4)
 100#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT          8
 101#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA           0x0
 102#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0       0xc
 103#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1       0xd
 104#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2       0xe
 105
 106#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(n)              (0x0a0 + 0x2c * (n))
 107#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT   0
 108#define VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(n)        (0x0a4 + 0x2c * (n))
 109#define VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(n)        (0x0ac + 0x2c * (n))
 110#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(n)         (0x0b4 + 0x2c * (n))
 111#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT    1
 112#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT 2
 113#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK  (0x1f << 2)
 114#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(n)           (0x0b8 + 0x2c * (n))
 115#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT 16
 116#define VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(n)       (0x0bc + 0x2c * (n))
 117#define VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(n)       (0x0c0 + 0x2c * (n))
 118#define VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(n)        \
 119                                                        (0x0c4 + 0x2c * (n))
 120#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(n)    \
 121                                                        (0x0c8 + 0x2c * (n))
 122#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF   0xffffffff
 123
 124#define VFE_0_BUS_PING_PONG_STATUS      0x338
 125
 126#define VFE_0_BUS_BDG_CMD               0x400
 127#define VFE_0_BUS_BDG_CMD_HALT_REQ      1
 128
 129#define VFE_0_BUS_BDG_QOS_CFG_0         0x404
 130#define VFE_0_BUS_BDG_QOS_CFG_0_CFG     0xaaa9aaa9
 131#define VFE_0_BUS_BDG_QOS_CFG_1         0x408
 132#define VFE_0_BUS_BDG_QOS_CFG_2         0x40c
 133#define VFE_0_BUS_BDG_QOS_CFG_3         0x410
 134#define VFE_0_BUS_BDG_QOS_CFG_4         0x414
 135#define VFE_0_BUS_BDG_QOS_CFG_5         0x418
 136#define VFE_0_BUS_BDG_QOS_CFG_6         0x41c
 137#define VFE_0_BUS_BDG_QOS_CFG_7         0x420
 138#define VFE_0_BUS_BDG_QOS_CFG_7_CFG     0x0001aaa9
 139
 140#define VFE48_0_BUS_BDG_QOS_CFG_0_CFG   0xaaa5aaa5
 141#define VFE48_0_BUS_BDG_QOS_CFG_3_CFG   0xaa55aaa5
 142#define VFE48_0_BUS_BDG_QOS_CFG_4_CFG   0xaa55aa55
 143#define VFE48_0_BUS_BDG_QOS_CFG_7_CFG   0x0005aa55
 144
 145#define VFE_0_BUS_BDG_DS_CFG_0          0x424
 146#define VFE_0_BUS_BDG_DS_CFG_0_CFG      0xcccc0011
 147#define VFE_0_BUS_BDG_DS_CFG_1          0x428
 148#define VFE_0_BUS_BDG_DS_CFG_2          0x42c
 149#define VFE_0_BUS_BDG_DS_CFG_3          0x430
 150#define VFE_0_BUS_BDG_DS_CFG_4          0x434
 151#define VFE_0_BUS_BDG_DS_CFG_5          0x438
 152#define VFE_0_BUS_BDG_DS_CFG_6          0x43c
 153#define VFE_0_BUS_BDG_DS_CFG_7          0x440
 154#define VFE_0_BUS_BDG_DS_CFG_8          0x444
 155#define VFE_0_BUS_BDG_DS_CFG_9          0x448
 156#define VFE_0_BUS_BDG_DS_CFG_10         0x44c
 157#define VFE_0_BUS_BDG_DS_CFG_11         0x450
 158#define VFE_0_BUS_BDG_DS_CFG_12         0x454
 159#define VFE_0_BUS_BDG_DS_CFG_13         0x458
 160#define VFE_0_BUS_BDG_DS_CFG_14         0x45c
 161#define VFE_0_BUS_BDG_DS_CFG_15         0x460
 162#define VFE_0_BUS_BDG_DS_CFG_16         0x464
 163#define VFE_0_BUS_BDG_DS_CFG_16_CFG     0x40000103
 164
 165#define VFE48_0_BUS_BDG_DS_CFG_0_CFG    0xcccc1111
 166#define VFE48_0_BUS_BDG_DS_CFG_16_CFG   0x00000110
 167
 168#define VFE_0_RDI_CFG_x(x)              (0x46c + (0x4 * (x)))
 169#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT    28
 170#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK     (0xf << 28)
 171#define VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT        4
 172#define VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK         (0xf << 4)
 173#define VFE_0_RDI_CFG_x_RDI_EN_BIT              BIT(2)
 174#define VFE_0_RDI_CFG_x_MIPI_EN_BITS            0x3
 175
 176#define VFE_0_CAMIF_CMD                         0x478
 177#define VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY  0
 178#define VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY   1
 179#define VFE_0_CAMIF_CMD_NO_CHANGE               3
 180#define VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS      BIT(2)
 181#define VFE_0_CAMIF_CFG                         0x47c
 182#define VFE_0_CAMIF_CFG_VFE_OUTPUT_EN           BIT(6)
 183#define VFE_0_CAMIF_FRAME_CFG                   0x484
 184#define VFE_0_CAMIF_WINDOW_WIDTH_CFG            0x488
 185#define VFE_0_CAMIF_WINDOW_HEIGHT_CFG           0x48c
 186#define VFE_0_CAMIF_SUBSAMPLE_CFG               0x490
 187#define VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN       0x498
 188#define VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN       0x49c
 189#define VFE_0_CAMIF_STATUS                      0x4a4
 190#define VFE_0_CAMIF_STATUS_HALT                 BIT(31)
 191
 192#define VFE_0_REG_UPDATE                0x4ac
 193#define VFE_0_REG_UPDATE_RDIn(n)                BIT(1 + (n))
 194#define VFE_0_REG_UPDATE_line_n(n)              \
 195                        ((n) == VFE_LINE_PIX ? 1 : VFE_0_REG_UPDATE_RDIn(n))
 196
 197#define VFE_0_DEMUX_CFG                         0x560
 198#define VFE_0_DEMUX_CFG_PERIOD                  0x3
 199#define VFE_0_DEMUX_GAIN_0                      0x564
 200#define VFE_0_DEMUX_GAIN_0_CH0_EVEN             (0x80 << 0)
 201#define VFE_0_DEMUX_GAIN_0_CH0_ODD              (0x80 << 16)
 202#define VFE_0_DEMUX_GAIN_1                      0x568
 203#define VFE_0_DEMUX_GAIN_1_CH1                  (0x80 << 0)
 204#define VFE_0_DEMUX_GAIN_1_CH2                  (0x80 << 16)
 205#define VFE_0_DEMUX_EVEN_CFG                    0x574
 206#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV       0x9cac
 207#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU       0xac9c
 208#define VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY       0xc9ca
 209#define VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY       0xcac9
 210#define VFE_0_DEMUX_ODD_CFG                     0x578
 211#define VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV        0x9cac
 212#define VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU        0xac9c
 213#define VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY        0xc9ca
 214#define VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY        0xcac9
 215
 216#define VFE_0_SCALE_ENC_Y_CFG                   0x91c
 217#define VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE          0x920
 218#define VFE_0_SCALE_ENC_Y_H_PHASE               0x924
 219#define VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE          0x934
 220#define VFE_0_SCALE_ENC_Y_V_PHASE               0x938
 221#define VFE_0_SCALE_ENC_CBCR_CFG                0x948
 222#define VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE       0x94c
 223#define VFE_0_SCALE_ENC_CBCR_H_PHASE            0x950
 224#define VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE       0x960
 225#define VFE_0_SCALE_ENC_CBCR_V_PHASE            0x964
 226
 227#define VFE_0_CROP_ENC_Y_WIDTH                  0x974
 228#define VFE_0_CROP_ENC_Y_HEIGHT                 0x978
 229#define VFE_0_CROP_ENC_CBCR_WIDTH               0x97c
 230#define VFE_0_CROP_ENC_CBCR_HEIGHT              0x980
 231
 232#define VFE_0_CLAMP_ENC_MAX_CFG                 0x984
 233#define VFE_0_CLAMP_ENC_MAX_CFG_CH0             (0xff << 0)
 234#define VFE_0_CLAMP_ENC_MAX_CFG_CH1             (0xff << 8)
 235#define VFE_0_CLAMP_ENC_MAX_CFG_CH2             (0xff << 16)
 236#define VFE_0_CLAMP_ENC_MIN_CFG                 0x988
 237#define VFE_0_CLAMP_ENC_MIN_CFG_CH0             (0x0 << 0)
 238#define VFE_0_CLAMP_ENC_MIN_CFG_CH1             (0x0 << 8)
 239#define VFE_0_CLAMP_ENC_MIN_CFG_CH2             (0x0 << 16)
 240
 241#define VFE_0_REALIGN_BUF_CFG                   0xaac
 242#define VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL     BIT(2)
 243#define VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL     BIT(3)
 244#define VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE      BIT(4)
 245
 246#define VFE48_0_BUS_IMAGE_MASTER_CMD            0xcec
 247#define VFE48_0_BUS_IMAGE_MASTER_n_SHIFT(x)     (2 * (x))
 248
 249#define CAMIF_TIMEOUT_SLEEP_US 1000
 250#define CAMIF_TIMEOUT_ALL_US 1000000
 251
 252#define MSM_VFE_VFE0_UB_SIZE 2047
 253#define MSM_VFE_VFE0_UB_SIZE_RDI (MSM_VFE_VFE0_UB_SIZE / 3)
 254#define MSM_VFE_VFE1_UB_SIZE 1535
 255#define MSM_VFE_VFE1_UB_SIZE_RDI (MSM_VFE_VFE1_UB_SIZE / 3)
 256
 257static u32 vfe_hw_version(struct vfe_device *vfe)
 258{
 259        u32 hw_version = readl_relaxed(vfe->base + VFE_0_HW_VERSION);
 260
 261        dev_dbg(vfe->camss->dev, "VFE HW Version = 0x%08x\n", hw_version);
 262
 263        return hw_version;
 264}
 265
 266static u16 vfe_get_ub_size(u8 vfe_id)
 267{
 268        if (vfe_id == 0)
 269                return MSM_VFE_VFE0_UB_SIZE_RDI;
 270        else if (vfe_id == 1)
 271                return MSM_VFE_VFE1_UB_SIZE_RDI;
 272
 273        return 0;
 274}
 275
 276static inline void vfe_reg_clr(struct vfe_device *vfe, u32 reg, u32 clr_bits)
 277{
 278        u32 bits = readl_relaxed(vfe->base + reg);
 279
 280        writel_relaxed(bits & ~clr_bits, vfe->base + reg);
 281}
 282
 283static inline void vfe_reg_set(struct vfe_device *vfe, u32 reg, u32 set_bits)
 284{
 285        u32 bits = readl_relaxed(vfe->base + reg);
 286
 287        writel_relaxed(bits | set_bits, vfe->base + reg);
 288}
 289
 290static void vfe_global_reset(struct vfe_device *vfe)
 291{
 292        u32 reset_bits = VFE_0_GLOBAL_RESET_CMD_IDLE_CGC        |
 293                         VFE_0_GLOBAL_RESET_CMD_DSP             |
 294                         VFE_0_GLOBAL_RESET_CMD_TESTGEN         |
 295                         VFE_0_GLOBAL_RESET_CMD_BUS_MISR        |
 296                         VFE_0_GLOBAL_RESET_CMD_PM              |
 297                         VFE_0_GLOBAL_RESET_CMD_REGISTER        |
 298                         VFE_0_GLOBAL_RESET_CMD_BUS_BDG         |
 299                         VFE_0_GLOBAL_RESET_CMD_BUS             |
 300                         VFE_0_GLOBAL_RESET_CMD_CAMIF           |
 301                         VFE_0_GLOBAL_RESET_CMD_CORE;
 302
 303        writel_relaxed(BIT(31), vfe->base + VFE_0_IRQ_MASK_0);
 304
 305        /* Enforce barrier between IRQ mask setup and global reset */
 306        wmb();
 307        writel_relaxed(reset_bits, vfe->base + VFE_0_GLOBAL_RESET_CMD);
 308}
 309
 310static void vfe_halt_request(struct vfe_device *vfe)
 311{
 312        writel_relaxed(VFE_0_BUS_BDG_CMD_HALT_REQ,
 313                       vfe->base + VFE_0_BUS_BDG_CMD);
 314}
 315
 316static void vfe_halt_clear(struct vfe_device *vfe)
 317{
 318        writel_relaxed(0x0, vfe->base + VFE_0_BUS_BDG_CMD);
 319}
 320
 321static void vfe_wm_enable(struct vfe_device *vfe, u8 wm, u8 enable)
 322{
 323        if (enable)
 324                vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
 325                            1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT);
 326        else
 327                vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
 328                            1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT);
 329}
 330
 331static void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable)
 332{
 333        if (enable)
 334                vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),
 335                        1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);
 336        else
 337                vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),
 338                        1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);
 339}
 340
 341#define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N))
 342
 343static int vfe_word_per_line_by_pixel(u32 format, u32 pixel_per_line)
 344{
 345        int val = 0;
 346
 347        switch (format) {
 348        case V4L2_PIX_FMT_NV12:
 349        case V4L2_PIX_FMT_NV21:
 350        case V4L2_PIX_FMT_NV16:
 351        case V4L2_PIX_FMT_NV61:
 352                val = CALC_WORD(pixel_per_line, 1, 8);
 353                break;
 354        case V4L2_PIX_FMT_YUYV:
 355        case V4L2_PIX_FMT_YVYU:
 356        case V4L2_PIX_FMT_UYVY:
 357        case V4L2_PIX_FMT_VYUY:
 358                val = CALC_WORD(pixel_per_line, 2, 8);
 359                break;
 360        }
 361
 362        return val;
 363}
 364
 365static int vfe_word_per_line_by_bytes(u32 bytes_per_line)
 366{
 367        return CALC_WORD(bytes_per_line, 1, 8);
 368}
 369
 370static void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane,
 371                             u16 *width, u16 *height, u16 *bytesperline)
 372{
 373        *width = pix->width;
 374        *height = pix->height;
 375
 376        switch (pix->pixelformat) {
 377        case V4L2_PIX_FMT_NV12:
 378        case V4L2_PIX_FMT_NV21:
 379                *bytesperline = pix->plane_fmt[0].bytesperline;
 380                if (plane == 1)
 381                        *height /= 2;
 382                break;
 383        case V4L2_PIX_FMT_NV16:
 384        case V4L2_PIX_FMT_NV61:
 385                *bytesperline = pix->plane_fmt[0].bytesperline;
 386                break;
 387        case V4L2_PIX_FMT_YUYV:
 388        case V4L2_PIX_FMT_YVYU:
 389        case V4L2_PIX_FMT_VYUY:
 390        case V4L2_PIX_FMT_UYVY:
 391                *bytesperline = pix->plane_fmt[plane].bytesperline;
 392                break;
 393        }
 394}
 395
 396static void vfe_wm_line_based(struct vfe_device *vfe, u32 wm,
 397                              struct v4l2_pix_format_mplane *pix,
 398                              u8 plane, u32 enable)
 399{
 400        u32 reg;
 401
 402        if (enable) {
 403                u16 width = 0, height = 0, bytesperline = 0, wpl;
 404
 405                vfe_get_wm_sizes(pix, plane, &width, &height, &bytesperline);
 406
 407                wpl = vfe_word_per_line_by_pixel(pix->pixelformat, width);
 408
 409                reg = height - 1;
 410                reg |= ((wpl + 3) / 4 - 1) << 16;
 411
 412                writel_relaxed(reg, vfe->base +
 413                               VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
 414
 415                wpl = vfe_word_per_line_by_bytes(bytesperline);
 416
 417                reg = 0x3;
 418                reg |= (height - 1) << 2;
 419                reg |= ((wpl + 1) / 2) << 16;
 420
 421                writel_relaxed(reg, vfe->base +
 422                               VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
 423        } else {
 424                writel_relaxed(0, vfe->base +
 425                               VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
 426                writel_relaxed(0, vfe->base +
 427                               VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
 428        }
 429}
 430
 431static void vfe_wm_set_framedrop_period(struct vfe_device *vfe, u8 wm, u8 per)
 432{
 433        u32 reg;
 434
 435        reg = readl_relaxed(vfe->base +
 436                            VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
 437
 438        reg &= ~(VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK);
 439
 440        reg |= (per << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT)
 441                & VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK;
 442
 443        writel_relaxed(reg,
 444                       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
 445}
 446
 447static void vfe_wm_set_framedrop_pattern(struct vfe_device *vfe, u8 wm,
 448                                         u32 pattern)
 449{
 450        writel_relaxed(pattern,
 451               vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(wm));
 452}
 453
 454static void vfe_wm_set_ub_cfg(struct vfe_device *vfe, u8 wm,
 455                              u16 offset, u16 depth)
 456{
 457        u32 reg;
 458
 459        reg = (offset << VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT) |
 460                depth;
 461        writel_relaxed(reg, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(wm));
 462}
 463
 464static void vfe_bus_reload_wm(struct vfe_device *vfe, u8 wm)
 465{
 466        /* Enforce barrier between any outstanding register write */
 467        wmb();
 468
 469        writel_relaxed(VFE_0_BUS_CMD_Mx_RLD_CMD(wm), vfe->base + VFE_0_BUS_CMD);
 470
 471        /* Use barrier to make sure bus reload is issued before anything else */
 472        wmb();
 473}
 474
 475static void vfe_wm_set_ping_addr(struct vfe_device *vfe, u8 wm, u32 addr)
 476{
 477        writel_relaxed(addr,
 478                       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(wm));
 479}
 480
 481static void vfe_wm_set_pong_addr(struct vfe_device *vfe, u8 wm, u32 addr)
 482{
 483        writel_relaxed(addr,
 484                       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(wm));
 485}
 486
 487static int vfe_wm_get_ping_pong_status(struct vfe_device *vfe, u8 wm)
 488{
 489        u32 reg;
 490
 491        reg = readl_relaxed(vfe->base + VFE_0_BUS_PING_PONG_STATUS);
 492
 493        return (reg >> wm) & 0x1;
 494}
 495
 496static void vfe_bus_enable_wr_if(struct vfe_device *vfe, u8 enable)
 497{
 498        if (enable)
 499                writel_relaxed(0x101, vfe->base + VFE_0_BUS_CFG);
 500        else
 501                writel_relaxed(0, vfe->base + VFE_0_BUS_CFG);
 502}
 503
 504static void vfe_bus_connect_wm_to_rdi(struct vfe_device *vfe, u8 wm,
 505                                      enum vfe_line_id id)
 506{
 507        u32 reg;
 508
 509        reg = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
 510        vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), reg);
 511
 512        reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
 513        reg |= ((3 * id) << VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT) &
 514                VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK;
 515        vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), reg);
 516
 517        switch (id) {
 518        case VFE_LINE_RDI0:
 519        default:
 520                reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
 521                      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 522                break;
 523        case VFE_LINE_RDI1:
 524                reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
 525                      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 526                break;
 527        case VFE_LINE_RDI2:
 528                reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
 529                      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 530                break;
 531        }
 532
 533        if (wm % 2 == 1)
 534                reg <<= 16;
 535
 536        vfe_reg_set(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
 537}
 538
 539static void vfe_wm_set_subsample(struct vfe_device *vfe, u8 wm)
 540{
 541        writel_relaxed(VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF,
 542               vfe->base +
 543               VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(wm));
 544}
 545
 546static void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm,
 547                                           enum vfe_line_id id)
 548{
 549        u32 reg;
 550
 551        reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
 552        vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), reg);
 553
 554        switch (id) {
 555        case VFE_LINE_RDI0:
 556        default:
 557                reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
 558                      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 559                break;
 560        case VFE_LINE_RDI1:
 561                reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
 562                      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 563                break;
 564        case VFE_LINE_RDI2:
 565                reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
 566                      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 567                break;
 568        }
 569
 570        if (wm % 2 == 1)
 571                reg <<= 16;
 572
 573        vfe_reg_clr(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
 574}
 575
 576static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
 577                             u8 enable)
 578{
 579        struct vfe_line *line = container_of(output, struct vfe_line, output);
 580        u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
 581        u32 reg;
 582
 583        switch (p) {
 584        case V4L2_PIX_FMT_NV12:
 585        case V4L2_PIX_FMT_NV21:
 586        case V4L2_PIX_FMT_NV16:
 587        case V4L2_PIX_FMT_NV61:
 588                reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA <<
 589                        VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 590
 591                if (output->wm_idx[0] % 2 == 1)
 592                        reg <<= 16;
 593
 594                if (enable)
 595                        vfe_reg_set(vfe,
 596                                    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
 597                                    reg);
 598                else
 599                        vfe_reg_clr(vfe,
 600                                    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
 601                                    reg);
 602
 603                reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
 604                if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16)
 605                        reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
 606
 607                if (output->wm_idx[1] % 2 == 1)
 608                        reg <<= 16;
 609
 610                if (enable)
 611                        vfe_reg_set(vfe,
 612                                    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
 613                                    reg);
 614                else
 615                        vfe_reg_clr(vfe,
 616                                    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
 617                                    reg);
 618                break;
 619        case V4L2_PIX_FMT_YUYV:
 620        case V4L2_PIX_FMT_YVYU:
 621        case V4L2_PIX_FMT_VYUY:
 622        case V4L2_PIX_FMT_UYVY:
 623                reg = VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN;
 624                reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
 625
 626                if (p == V4L2_PIX_FMT_YUYV || p == V4L2_PIX_FMT_YVYU)
 627                        reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
 628
 629                if (output->wm_idx[0] % 2 == 1)
 630                        reg <<= 16;
 631
 632                if (enable)
 633                        vfe_reg_set(vfe,
 634                                    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
 635                                    reg);
 636                else
 637                        vfe_reg_clr(vfe,
 638                                    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
 639                                    reg);
 640                break;
 641        default:
 642                break;
 643        }
 644}
 645
 646static void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line,
 647                                u8 enable)
 648{
 649        u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
 650        u32 val = VFE_0_MODULE_ZOOM_EN_REALIGN_BUF;
 651
 652        if (p != V4L2_PIX_FMT_YUYV && p != V4L2_PIX_FMT_YVYU &&
 653                        p != V4L2_PIX_FMT_VYUY && p != V4L2_PIX_FMT_UYVY)
 654                return;
 655
 656        if (enable) {
 657                vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val);
 658        } else {
 659                vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val);
 660                return;
 661        }
 662
 663        val = VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE;
 664
 665        if (p == V4L2_PIX_FMT_UYVY || p == V4L2_PIX_FMT_YUYV)
 666                val |= VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL;
 667        else
 668                val |= VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL;
 669
 670        writel_relaxed(val, vfe->base + VFE_0_REALIGN_BUF_CFG);
 671}
 672
 673static void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid)
 674{
 675        vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id),
 676                    VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK);
 677
 678        vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id),
 679                    cid << VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT);
 680}
 681
 682static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)
 683{
 684        vfe->reg_update |= VFE_0_REG_UPDATE_line_n(line_id);
 685
 686        /* Enforce barrier between line update and commit */
 687        wmb();
 688        writel_relaxed(vfe->reg_update, vfe->base + VFE_0_REG_UPDATE);
 689
 690        /* Make sure register update is issued before further reg writes */
 691        wmb();
 692}
 693
 694static inline void vfe_reg_update_clear(struct vfe_device *vfe,
 695                                        enum vfe_line_id line_id)
 696{
 697        vfe->reg_update &= ~VFE_0_REG_UPDATE_line_n(line_id);
 698}
 699
 700static void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm,
 701                                   enum vfe_line_id line_id, u8 enable)
 702{
 703        u32 irq_en0 = VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(wm) |
 704                      VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
 705        u32 irq_en1 = VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(wm) |
 706                      VFE_0_IRQ_MASK_1_RDIn_SOF(line_id);
 707
 708        if (enable) {
 709                vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 710                vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 711        } else {
 712                vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 713                vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 714        }
 715}
 716
 717static void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp,
 718                                    enum vfe_line_id line_id, u8 enable)
 719{
 720        struct vfe_output *output = &vfe->line[line_id].output;
 721        unsigned int i;
 722        u32 irq_en0;
 723        u32 irq_en1;
 724        u32 comp_mask = 0;
 725
 726        irq_en0 = VFE_0_IRQ_MASK_0_CAMIF_SOF;
 727        irq_en0 |= VFE_0_IRQ_MASK_0_CAMIF_EOF;
 728        irq_en0 |= VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(comp);
 729        irq_en0 |= VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
 730        irq_en1 = VFE_0_IRQ_MASK_1_CAMIF_ERROR;
 731        for (i = 0; i < output->wm_num; i++) {
 732                irq_en1 |= VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(
 733                                                        output->wm_idx[i]);
 734                comp_mask |= (1 << output->wm_idx[i]) << comp * 8;
 735        }
 736
 737        if (enable) {
 738                vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 739                vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 740                vfe_reg_set(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
 741        } else {
 742                vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 743                vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 744                vfe_reg_clr(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
 745        }
 746}
 747
 748static void vfe_enable_irq_common(struct vfe_device *vfe)
 749{
 750        u32 irq_en0 = VFE_0_IRQ_MASK_0_RESET_ACK;
 751        u32 irq_en1 = VFE_0_IRQ_MASK_1_VIOLATION |
 752                      VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK;
 753
 754        vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 755        vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 756}
 757
 758static void vfe_set_demux_cfg(struct vfe_device *vfe, struct vfe_line *line)
 759{
 760        u32 val, even_cfg, odd_cfg;
 761
 762        writel_relaxed(VFE_0_DEMUX_CFG_PERIOD, vfe->base + VFE_0_DEMUX_CFG);
 763
 764        val = VFE_0_DEMUX_GAIN_0_CH0_EVEN | VFE_0_DEMUX_GAIN_0_CH0_ODD;
 765        writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_0);
 766
 767        val = VFE_0_DEMUX_GAIN_1_CH1 | VFE_0_DEMUX_GAIN_1_CH2;
 768        writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_1);
 769
 770        switch (line->fmt[MSM_VFE_PAD_SINK].code) {
 771        case MEDIA_BUS_FMT_YUYV8_2X8:
 772                even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV;
 773                odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV;
 774                break;
 775        case MEDIA_BUS_FMT_YVYU8_2X8:
 776                even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU;
 777                odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU;
 778                break;
 779        case MEDIA_BUS_FMT_UYVY8_2X8:
 780        default:
 781                even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY;
 782                odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY;
 783                break;
 784        case MEDIA_BUS_FMT_VYUY8_2X8:
 785                even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY;
 786                odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY;
 787                break;
 788        }
 789
 790        writel_relaxed(even_cfg, vfe->base + VFE_0_DEMUX_EVEN_CFG);
 791        writel_relaxed(odd_cfg, vfe->base + VFE_0_DEMUX_ODD_CFG);
 792}
 793
 794static void vfe_set_scale_cfg(struct vfe_device *vfe, struct vfe_line *line)
 795{
 796        u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
 797        u32 reg;
 798        u16 input, output;
 799        u8 interp_reso;
 800        u32 phase_mult;
 801
 802        writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_Y_CFG);
 803
 804        input = line->fmt[MSM_VFE_PAD_SINK].width - 1;
 805        output = line->compose.width - 1;
 806        reg = (output << 16) | input;
 807        writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE);
 808
 809        interp_reso = vfe_calc_interp_reso(input, output);
 810        phase_mult = input * (1 << (14 + interp_reso)) / output;
 811        reg = (interp_reso << 28) | phase_mult;
 812        writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_PHASE);
 813
 814        input = line->fmt[MSM_VFE_PAD_SINK].height - 1;
 815        output = line->compose.height - 1;
 816        reg = (output << 16) | input;
 817        writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE);
 818
 819        interp_reso = vfe_calc_interp_reso(input, output);
 820        phase_mult = input * (1 << (14 + interp_reso)) / output;
 821        reg = (interp_reso << 28) | phase_mult;
 822        writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_PHASE);
 823
 824        writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_CBCR_CFG);
 825
 826        input = line->fmt[MSM_VFE_PAD_SINK].width - 1;
 827        output = line->compose.width / 2 - 1;
 828        reg = (output << 16) | input;
 829        writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE);
 830
 831        interp_reso = vfe_calc_interp_reso(input, output);
 832        phase_mult = input * (1 << (14 + interp_reso)) / output;
 833        reg = (interp_reso << 28) | phase_mult;
 834        writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_PHASE);
 835
 836        input = line->fmt[MSM_VFE_PAD_SINK].height - 1;
 837        output = line->compose.height - 1;
 838        if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21)
 839                output = line->compose.height / 2 - 1;
 840        reg = (output << 16) | input;
 841        writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE);
 842
 843        interp_reso = vfe_calc_interp_reso(input, output);
 844        phase_mult = input * (1 << (14 + interp_reso)) / output;
 845        reg = (interp_reso << 28) | phase_mult;
 846        writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_PHASE);
 847}
 848
 849static void vfe_set_crop_cfg(struct vfe_device *vfe, struct vfe_line *line)
 850{
 851        u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
 852        u32 reg;
 853        u16 first, last;
 854
 855        first = line->crop.left;
 856        last = line->crop.left + line->crop.width - 1;
 857        reg = (first << 16) | last;
 858        writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_WIDTH);
 859
 860        first = line->crop.top;
 861        last = line->crop.top + line->crop.height - 1;
 862        reg = (first << 16) | last;
 863        writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_HEIGHT);
 864
 865        first = line->crop.left / 2;
 866        last = line->crop.left / 2 + line->crop.width / 2 - 1;
 867        reg = (first << 16) | last;
 868        writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_WIDTH);
 869
 870        first = line->crop.top;
 871        last = line->crop.top + line->crop.height - 1;
 872        if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) {
 873                first = line->crop.top / 2;
 874                last = line->crop.top / 2 + line->crop.height / 2 - 1;
 875        }
 876        reg = (first << 16) | last;
 877        writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_HEIGHT);
 878}
 879
 880static void vfe_set_clamp_cfg(struct vfe_device *vfe)
 881{
 882        u32 val = VFE_0_CLAMP_ENC_MAX_CFG_CH0 |
 883                VFE_0_CLAMP_ENC_MAX_CFG_CH1 |
 884                VFE_0_CLAMP_ENC_MAX_CFG_CH2;
 885
 886        writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MAX_CFG);
 887
 888        val = VFE_0_CLAMP_ENC_MIN_CFG_CH0 |
 889                VFE_0_CLAMP_ENC_MIN_CFG_CH1 |
 890                VFE_0_CLAMP_ENC_MIN_CFG_CH2;
 891
 892        writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MIN_CFG);
 893}
 894
 895static void vfe_set_qos(struct vfe_device *vfe)
 896{
 897        u32 val = VFE_0_BUS_BDG_QOS_CFG_0_CFG;
 898        u32 val7 = VFE_0_BUS_BDG_QOS_CFG_7_CFG;
 899
 900        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_0);
 901        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_1);
 902        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_2);
 903        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_3);
 904        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_4);
 905        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_5);
 906        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_6);
 907        writel_relaxed(val7, vfe->base + VFE_0_BUS_BDG_QOS_CFG_7);
 908}
 909
 910static void vfe_set_ds(struct vfe_device *vfe)
 911{
 912        u32 val = VFE_0_BUS_BDG_DS_CFG_0_CFG;
 913        u32 val16 = VFE_0_BUS_BDG_DS_CFG_16_CFG;
 914
 915        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_0);
 916        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_1);
 917        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_2);
 918        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_3);
 919        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_4);
 920        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_5);
 921        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_6);
 922        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_7);
 923        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_8);
 924        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_9);
 925        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_10);
 926        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_11);
 927        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_12);
 928        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_13);
 929        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_14);
 930        writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_15);
 931        writel_relaxed(val16, vfe->base + VFE_0_BUS_BDG_DS_CFG_16);
 932}
 933
 934static void vfe_set_cgc_override(struct vfe_device *vfe, u8 wm, u8 enable)
 935{
 936        /* empty */
 937}
 938
 939static void vfe_set_camif_cfg(struct vfe_device *vfe, struct vfe_line *line)
 940{
 941        u32 val;
 942
 943        switch (line->fmt[MSM_VFE_PAD_SINK].code) {
 944        case MEDIA_BUS_FMT_YUYV8_2X8:
 945                val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR;
 946                break;
 947        case MEDIA_BUS_FMT_YVYU8_2X8:
 948                val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB;
 949                break;
 950        case MEDIA_BUS_FMT_UYVY8_2X8:
 951        default:
 952                val = VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY;
 953                break;
 954        case MEDIA_BUS_FMT_VYUY8_2X8:
 955                val = VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY;
 956                break;
 957        }
 958
 959        val |= VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN;
 960        writel_relaxed(val, vfe->base + VFE_0_CORE_CFG);
 961
 962        val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;
 963        val |= (line->fmt[MSM_VFE_PAD_SINK].height - 1) << 16;
 964        writel_relaxed(val, vfe->base + VFE_0_CAMIF_FRAME_CFG);
 965
 966        val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;
 967        writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_WIDTH_CFG);
 968
 969        val = line->fmt[MSM_VFE_PAD_SINK].height - 1;
 970        writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_HEIGHT_CFG);
 971
 972        val = 0xffffffff;
 973        writel_relaxed(val, vfe->base + VFE_0_CAMIF_SUBSAMPLE_CFG);
 974
 975        val = 0xffffffff;
 976        writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN);
 977
 978        val = 0xffffffff;
 979        writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN);
 980
 981        val = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
 982        vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), val);
 983
 984        val = VFE_0_CAMIF_CFG_VFE_OUTPUT_EN;
 985        writel_relaxed(val, vfe->base + VFE_0_CAMIF_CFG);
 986}
 987
 988static void vfe_set_camif_cmd(struct vfe_device *vfe, u8 enable)
 989{
 990        u32 cmd;
 991
 992        cmd = VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS | VFE_0_CAMIF_CMD_NO_CHANGE;
 993        writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
 994
 995        /* Make sure camif command is issued written before it is changed again */
 996        wmb();
 997
 998        if (enable)
 999                cmd = VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY;
1000        else
1001                cmd = VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY;
1002
1003        writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
1004}
1005
1006static void vfe_set_module_cfg(struct vfe_device *vfe, u8 enable)
1007{
1008        u32 val_lens = VFE_0_MODULE_LENS_EN_DEMUX |
1009                       VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE;
1010        u32 val_zoom = VFE_0_MODULE_ZOOM_EN_SCALE_ENC |
1011                       VFE_0_MODULE_ZOOM_EN_CROP_ENC;
1012
1013        if (enable) {
1014                vfe_reg_set(vfe, VFE_0_MODULE_LENS_EN, val_lens);
1015                vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
1016        } else {
1017                vfe_reg_clr(vfe, VFE_0_MODULE_LENS_EN, val_lens);
1018                vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
1019        }
1020}
1021
1022static int vfe_camif_wait_for_stop(struct vfe_device *vfe, struct device *dev)
1023{
1024        u32 val;
1025        int ret;
1026
1027        ret = readl_poll_timeout(vfe->base + VFE_0_CAMIF_STATUS,
1028                                 val,
1029                                 (val & VFE_0_CAMIF_STATUS_HALT),
1030                                 CAMIF_TIMEOUT_SLEEP_US,
1031                                 CAMIF_TIMEOUT_ALL_US);
1032        if (ret < 0)
1033                dev_err(dev, "%s: camif stop timeout\n", __func__);
1034
1035        return ret;
1036}
1037
1038
1039
1040/*
1041 * vfe_isr - VFE module interrupt handler
1042 * @irq: Interrupt line
1043 * @dev: VFE device
1044 *
1045 * Return IRQ_HANDLED on success
1046 */
1047static irqreturn_t vfe_isr(int irq, void *dev)
1048{
1049        struct vfe_device *vfe = dev;
1050        u32 value0, value1;
1051        int i, j;
1052
1053        vfe->ops->isr_read(vfe, &value0, &value1);
1054
1055        dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",
1056                value0, value1);
1057
1058        if (value0 & VFE_0_IRQ_STATUS_0_RESET_ACK)
1059                vfe->isr_ops.reset_ack(vfe);
1060
1061        if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)
1062                vfe->ops->violation_read(vfe);
1063
1064        if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)
1065                vfe->isr_ops.halt_ack(vfe);
1066
1067        for (i = VFE_LINE_RDI0; i < vfe->line_num; i++)
1068                if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i))
1069                        vfe->isr_ops.reg_update(vfe, i);
1070
1071        if (value0 & VFE_0_IRQ_STATUS_0_CAMIF_SOF)
1072                vfe->isr_ops.sof(vfe, VFE_LINE_PIX);
1073
1074        for (i = VFE_LINE_RDI0; i <= VFE_LINE_RDI2; i++)
1075                if (value1 & VFE_0_IRQ_STATUS_1_RDIn_SOF(i))
1076                        vfe->isr_ops.sof(vfe, i);
1077
1078        for (i = 0; i < MSM_VFE_COMPOSITE_IRQ_NUM; i++)
1079                if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(i)) {
1080                        vfe->isr_ops.comp_done(vfe, i);
1081                        for (j = 0; j < ARRAY_SIZE(vfe->wm_output_map); j++)
1082                                if (vfe->wm_output_map[j] == VFE_LINE_PIX)
1083                                        value0 &= ~VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(j);
1084                }
1085
1086        for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++)
1087                if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(i))
1088                        vfe->isr_ops.wm_done(vfe, i);
1089
1090        return IRQ_HANDLED;
1091}
1092
1093static void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1)
1094{
1095        *value0 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_0);
1096        *value1 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_1);
1097
1098        writel_relaxed(*value0, vfe->base + VFE_0_IRQ_CLEAR_0);
1099        writel_relaxed(*value1, vfe->base + VFE_0_IRQ_CLEAR_1);
1100
1101        /* Enforce barrier between local & global IRQ clear */
1102        wmb();
1103        writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);
1104}
1105
1106/*
1107 * vfe_pm_domain_off - Disable power domains specific to this VFE.
1108 * @vfe: VFE Device
1109 */
1110static void vfe_pm_domain_off(struct vfe_device *vfe)
1111{
1112        struct camss *camss;
1113
1114        if (!vfe)
1115                return;
1116
1117        camss = vfe->camss;
1118
1119        device_link_del(camss->genpd_link[vfe->id]);
1120}
1121
1122/*
1123 * vfe_pm_domain_on - Enable power domains specific to this VFE.
1124 * @vfe: VFE Device
1125 */
1126static int vfe_pm_domain_on(struct vfe_device *vfe)
1127{
1128        struct camss *camss = vfe->camss;
1129        enum vfe_line_id id = vfe->id;
1130
1131        camss->genpd_link[id] = device_link_add(camss->dev, camss->genpd[id], DL_FLAG_STATELESS |
1132                                                DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
1133
1134        if (!camss->genpd_link[id]) {
1135                dev_err(vfe->camss->dev, "Failed to add VFE#%d to power domain\n", id);
1136                return -EINVAL;
1137        }
1138
1139        return 0;
1140}
1141
1142static void vfe_violation_read(struct vfe_device *vfe)
1143{
1144        u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);
1145
1146        pr_err_ratelimited("VFE: violation = 0x%08x\n", violation);
1147}
1148
1149static const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_7 = {
1150        .bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi,
1151        .bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi,
1152        .bus_enable_wr_if = vfe_bus_enable_wr_if,
1153        .bus_reload_wm = vfe_bus_reload_wm,
1154        .camif_wait_for_stop = vfe_camif_wait_for_stop,
1155        .enable_irq_common = vfe_enable_irq_common,
1156        .enable_irq_pix_line = vfe_enable_irq_pix_line,
1157        .enable_irq_wm_line = vfe_enable_irq_wm_line,
1158        .get_ub_size = vfe_get_ub_size,
1159        .halt_clear = vfe_halt_clear,
1160        .halt_request = vfe_halt_request,
1161        .set_camif_cfg = vfe_set_camif_cfg,
1162        .set_camif_cmd = vfe_set_camif_cmd,
1163        .set_cgc_override = vfe_set_cgc_override,
1164        .set_clamp_cfg = vfe_set_clamp_cfg,
1165        .set_crop_cfg = vfe_set_crop_cfg,
1166        .set_demux_cfg = vfe_set_demux_cfg,
1167        .set_ds = vfe_set_ds,
1168        .set_module_cfg = vfe_set_module_cfg,
1169        .set_qos = vfe_set_qos,
1170        .set_rdi_cid = vfe_set_rdi_cid,
1171        .set_realign_cfg = vfe_set_realign_cfg,
1172        .set_scale_cfg = vfe_set_scale_cfg,
1173        .set_xbar_cfg = vfe_set_xbar_cfg,
1174        .wm_enable = vfe_wm_enable,
1175        .wm_frame_based = vfe_wm_frame_based,
1176        .wm_get_ping_pong_status = vfe_wm_get_ping_pong_status,
1177        .wm_line_based = vfe_wm_line_based,
1178        .wm_set_framedrop_pattern = vfe_wm_set_framedrop_pattern,
1179        .wm_set_framedrop_period = vfe_wm_set_framedrop_period,
1180        .wm_set_ping_addr = vfe_wm_set_ping_addr,
1181        .wm_set_pong_addr = vfe_wm_set_pong_addr,
1182        .wm_set_subsample = vfe_wm_set_subsample,
1183        .wm_set_ub_cfg = vfe_wm_set_ub_cfg,
1184};
1185
1186static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe)
1187{
1188        vfe->isr_ops = vfe_isr_ops_gen1;
1189        vfe->ops_gen1 = &vfe_ops_gen1_4_7;
1190        vfe->video_ops = vfe_video_ops_gen1;
1191
1192        vfe->line_num = VFE_LINE_NUM_GEN1;
1193}
1194
1195const struct vfe_hw_ops vfe_ops_4_7 = {
1196        .global_reset = vfe_global_reset,
1197        .hw_version = vfe_hw_version,
1198        .isr_read = vfe_isr_read,
1199        .isr = vfe_isr,
1200        .pm_domain_off = vfe_pm_domain_off,
1201        .pm_domain_on = vfe_pm_domain_on,
1202        .reg_update_clear = vfe_reg_update_clear,
1203        .reg_update = vfe_reg_update,
1204        .subdev_init = vfe_subdev_init,
1205        .vfe_disable = vfe_gen1_disable,
1206        .vfe_enable = vfe_gen1_enable,
1207        .vfe_halt = vfe_gen1_halt,
1208        .violation_read = vfe_violation_read,
1209};
1210