linux/drivers/media/platform/rcar-vin/rcar-dma.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Driver for Renesas R-Car VIN
   4 *
   5 * Copyright (C) 2016 Renesas Electronics Corp.
   6 * Copyright (C) 2011-2013 Renesas Solutions Corp.
   7 * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
   8 * Copyright (C) 2008 Magnus Damm
   9 *
  10 * Based on the soc-camera rcar_vin driver
  11 */
  12
  13#include <linux/delay.h>
  14#include <linux/interrupt.h>
  15#include <linux/pm_runtime.h>
  16
  17#include <media/videobuf2-dma-contig.h>
  18
  19#include "rcar-vin.h"
  20
  21/* -----------------------------------------------------------------------------
  22 * HW Functions
  23 */
  24
  25/* Register offsets for R-Car VIN */
  26#define VNMC_REG        0x00    /* Video n Main Control Register */
  27#define VNMS_REG        0x04    /* Video n Module Status Register */
  28#define VNFC_REG        0x08    /* Video n Frame Capture Register */
  29#define VNSLPRC_REG     0x0C    /* Video n Start Line Pre-Clip Register */
  30#define VNELPRC_REG     0x10    /* Video n End Line Pre-Clip Register */
  31#define VNSPPRC_REG     0x14    /* Video n Start Pixel Pre-Clip Register */
  32#define VNEPPRC_REG     0x18    /* Video n End Pixel Pre-Clip Register */
  33#define VNIS_REG        0x2C    /* Video n Image Stride Register */
  34#define VNMB_REG(m)     (0x30 + ((m) << 2)) /* Video n Memory Base m Register */
  35#define VNIE_REG        0x40    /* Video n Interrupt Enable Register */
  36#define VNINTS_REG      0x44    /* Video n Interrupt Status Register */
  37#define VNSI_REG        0x48    /* Video n Scanline Interrupt Register */
  38#define VNMTC_REG       0x4C    /* Video n Memory Transfer Control Register */
  39#define VNDMR_REG       0x58    /* Video n Data Mode Register */
  40#define VNDMR2_REG      0x5C    /* Video n Data Mode Register 2 */
  41#define VNUVAOF_REG     0x60    /* Video n UV Address Offset Register */
  42
  43/* Register offsets specific for Gen2 */
  44#define VNSLPOC_REG     0x1C    /* Video n Start Line Post-Clip Register */
  45#define VNELPOC_REG     0x20    /* Video n End Line Post-Clip Register */
  46#define VNSPPOC_REG     0x24    /* Video n Start Pixel Post-Clip Register */
  47#define VNEPPOC_REG     0x28    /* Video n End Pixel Post-Clip Register */
  48#define VNYS_REG        0x50    /* Video n Y Scale Register */
  49#define VNXS_REG        0x54    /* Video n X Scale Register */
  50#define VNC1A_REG       0x80    /* Video n Coefficient Set C1A Register */
  51#define VNC1B_REG       0x84    /* Video n Coefficient Set C1B Register */
  52#define VNC1C_REG       0x88    /* Video n Coefficient Set C1C Register */
  53#define VNC2A_REG       0x90    /* Video n Coefficient Set C2A Register */
  54#define VNC2B_REG       0x94    /* Video n Coefficient Set C2B Register */
  55#define VNC2C_REG       0x98    /* Video n Coefficient Set C2C Register */
  56#define VNC3A_REG       0xA0    /* Video n Coefficient Set C3A Register */
  57#define VNC3B_REG       0xA4    /* Video n Coefficient Set C3B Register */
  58#define VNC3C_REG       0xA8    /* Video n Coefficient Set C3C Register */
  59#define VNC4A_REG       0xB0    /* Video n Coefficient Set C4A Register */
  60#define VNC4B_REG       0xB4    /* Video n Coefficient Set C4B Register */
  61#define VNC4C_REG       0xB8    /* Video n Coefficient Set C4C Register */
  62#define VNC5A_REG       0xC0    /* Video n Coefficient Set C5A Register */
  63#define VNC5B_REG       0xC4    /* Video n Coefficient Set C5B Register */
  64#define VNC5C_REG       0xC8    /* Video n Coefficient Set C5C Register */
  65#define VNC6A_REG       0xD0    /* Video n Coefficient Set C6A Register */
  66#define VNC6B_REG       0xD4    /* Video n Coefficient Set C6B Register */
  67#define VNC6C_REG       0xD8    /* Video n Coefficient Set C6C Register */
  68#define VNC7A_REG       0xE0    /* Video n Coefficient Set C7A Register */
  69#define VNC7B_REG       0xE4    /* Video n Coefficient Set C7B Register */
  70#define VNC7C_REG       0xE8    /* Video n Coefficient Set C7C Register */
  71#define VNC8A_REG       0xF0    /* Video n Coefficient Set C8A Register */
  72#define VNC8B_REG       0xF4    /* Video n Coefficient Set C8B Register */
  73#define VNC8C_REG       0xF8    /* Video n Coefficient Set C8C Register */
  74
  75/* Register offsets specific for Gen3 */
  76#define VNCSI_IFMD_REG          0x20 /* Video n CSI2 Interface Mode Register */
  77
  78/* Register bit fields for R-Car VIN */
  79/* Video n Main Control Register bits */
  80#define VNMC_DPINE              (1 << 27) /* Gen3 specific */
  81#define VNMC_SCLE               (1 << 26) /* Gen3 specific */
  82#define VNMC_FOC                (1 << 21)
  83#define VNMC_YCAL               (1 << 19)
  84#define VNMC_INF_YUV8_BT656     (0 << 16)
  85#define VNMC_INF_YUV8_BT601     (1 << 16)
  86#define VNMC_INF_YUV10_BT656    (2 << 16)
  87#define VNMC_INF_YUV10_BT601    (3 << 16)
  88#define VNMC_INF_RAW8           (4 << 16)
  89#define VNMC_INF_YUV16          (5 << 16)
  90#define VNMC_INF_RGB888         (6 << 16)
  91#define VNMC_VUP                (1 << 10)
  92#define VNMC_IM_ODD             (0 << 3)
  93#define VNMC_IM_ODD_EVEN        (1 << 3)
  94#define VNMC_IM_EVEN            (2 << 3)
  95#define VNMC_IM_FULL            (3 << 3)
  96#define VNMC_BPS                (1 << 1)
  97#define VNMC_ME                 (1 << 0)
  98
  99/* Video n Module Status Register bits */
 100#define VNMS_FBS_MASK           (3 << 3)
 101#define VNMS_FBS_SHIFT          3
 102#define VNMS_FS                 (1 << 2)
 103#define VNMS_AV                 (1 << 1)
 104#define VNMS_CA                 (1 << 0)
 105
 106/* Video n Frame Capture Register bits */
 107#define VNFC_C_FRAME            (1 << 1)
 108#define VNFC_S_FRAME            (1 << 0)
 109
 110/* Video n Interrupt Enable Register bits */
 111#define VNIE_FIE                (1 << 4)
 112#define VNIE_EFE                (1 << 1)
 113
 114/* Video n Data Mode Register bits */
 115#define VNDMR_A8BIT(n)          (((n) & 0xff) << 24)
 116#define VNDMR_A8BIT_MASK        (0xff << 24)
 117#define VNDMR_EXRGB             (1 << 8)
 118#define VNDMR_BPSM              (1 << 4)
 119#define VNDMR_ABIT              (1 << 2)
 120#define VNDMR_DTMD_YCSEP        (1 << 1)
 121#define VNDMR_DTMD_ARGB         (1 << 0)
 122#define VNDMR_DTMD_YCSEP_420    (3 << 0)
 123
 124/* Video n Data Mode Register 2 bits */
 125#define VNDMR2_VPS              (1 << 30)
 126#define VNDMR2_HPS              (1 << 29)
 127#define VNDMR2_CES              (1 << 28)
 128#define VNDMR2_YDS              (1 << 22)
 129#define VNDMR2_FTEV             (1 << 17)
 130#define VNDMR2_VLV(n)           ((n & 0xf) << 12)
 131
 132/* Video n CSI2 Interface Mode Register (Gen3) */
 133#define VNCSI_IFMD_DES1         (1 << 26)
 134#define VNCSI_IFMD_DES0         (1 << 25)
 135#define VNCSI_IFMD_CSI_CHSEL(n) (((n) & 0xf) << 0)
 136
 137struct rvin_buffer {
 138        struct vb2_v4l2_buffer vb;
 139        struct list_head list;
 140};
 141
 142#define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
 143                                               struct rvin_buffer, \
 144                                               vb)->list)
 145
 146static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset)
 147{
 148        iowrite32(value, vin->base + offset);
 149}
 150
 151static u32 rvin_read(struct rvin_dev *vin, u32 offset)
 152{
 153        return ioread32(vin->base + offset);
 154}
 155
 156/* -----------------------------------------------------------------------------
 157 * Crop and Scaling Gen2
 158 */
 159
 160struct vin_coeff {
 161        unsigned short xs_value;
 162        u32 coeff_set[24];
 163};
 164
 165static const struct vin_coeff vin_coeff_set[] = {
 166        { 0x0000, {
 167                          0x00000000, 0x00000000, 0x00000000,
 168                          0x00000000, 0x00000000, 0x00000000,
 169                          0x00000000, 0x00000000, 0x00000000,
 170                          0x00000000, 0x00000000, 0x00000000,
 171                          0x00000000, 0x00000000, 0x00000000,
 172                          0x00000000, 0x00000000, 0x00000000,
 173                          0x00000000, 0x00000000, 0x00000000,
 174                          0x00000000, 0x00000000, 0x00000000 },
 175        },
 176        { 0x1000, {
 177                          0x000fa400, 0x000fa400, 0x09625902,
 178                          0x000003f8, 0x00000403, 0x3de0d9f0,
 179                          0x001fffed, 0x00000804, 0x3cc1f9c3,
 180                          0x001003de, 0x00000c01, 0x3cb34d7f,
 181                          0x002003d2, 0x00000c00, 0x3d24a92d,
 182                          0x00200bca, 0x00000bff, 0x3df600d2,
 183                          0x002013cc, 0x000007ff, 0x3ed70c7e,
 184                          0x00100fde, 0x00000000, 0x3f87c036 },
 185        },
 186        { 0x1200, {
 187                          0x002ffff1, 0x002ffff1, 0x02a0a9c8,
 188                          0x002003e7, 0x001ffffa, 0x000185bc,
 189                          0x002007dc, 0x000003ff, 0x3e52859c,
 190                          0x00200bd4, 0x00000002, 0x3d53996b,
 191                          0x00100fd0, 0x00000403, 0x3d04ad2d,
 192                          0x00000bd5, 0x00000403, 0x3d35ace7,
 193                          0x3ff003e4, 0x00000801, 0x3dc674a1,
 194                          0x3fffe800, 0x00000800, 0x3e76f461 },
 195        },
 196        { 0x1400, {
 197                          0x00100be3, 0x00100be3, 0x04d1359a,
 198                          0x00000fdb, 0x002003ed, 0x0211fd93,
 199                          0x00000fd6, 0x002003f4, 0x0002d97b,
 200                          0x000007d6, 0x002ffffb, 0x3e93b956,
 201                          0x3ff003da, 0x001003ff, 0x3db49926,
 202                          0x3fffefe9, 0x00100001, 0x3d655cee,
 203                          0x3fffd400, 0x00000003, 0x3d65f4b6,
 204                          0x000fb421, 0x00000402, 0x3dc6547e },
 205        },
 206        { 0x1600, {
 207                          0x00000bdd, 0x00000bdd, 0x06519578,
 208                          0x3ff007da, 0x00000be3, 0x03c24973,
 209                          0x3ff003d9, 0x00000be9, 0x01b30d5f,
 210                          0x3ffff7df, 0x001003f1, 0x0003c542,
 211                          0x000fdfec, 0x001003f7, 0x3ec4711d,
 212                          0x000fc400, 0x002ffffd, 0x3df504f1,
 213                          0x001fa81a, 0x002ffc00, 0x3d957cc2,
 214                          0x002f8c3c, 0x00100000, 0x3db5c891 },
 215        },
 216        { 0x1800, {
 217                          0x3ff003dc, 0x3ff003dc, 0x0791e558,
 218                          0x000ff7dd, 0x3ff007de, 0x05328554,
 219                          0x000fe7e3, 0x3ff00be2, 0x03232546,
 220                          0x000fd7ee, 0x000007e9, 0x0143bd30,
 221                          0x001fb800, 0x000007ee, 0x00044511,
 222                          0x002fa015, 0x000007f4, 0x3ef4bcee,
 223                          0x002f8832, 0x001003f9, 0x3e4514c7,
 224                          0x001f7853, 0x001003fd, 0x3de54c9f },
 225        },
 226        { 0x1a00, {
 227                          0x000fefe0, 0x000fefe0, 0x08721d3c,
 228                          0x001fdbe7, 0x000ffbde, 0x0652a139,
 229                          0x001fcbf0, 0x000003df, 0x0463292e,
 230                          0x002fb3ff, 0x3ff007e3, 0x0293a91d,
 231                          0x002f9c12, 0x3ff00be7, 0x01241905,
 232                          0x001f8c29, 0x000007ed, 0x3fe470eb,
 233                          0x000f7c46, 0x000007f2, 0x3f04b8ca,
 234                          0x3fef7865, 0x000007f6, 0x3e74e4a8 },
 235        },
 236        { 0x1c00, {
 237                          0x001fd3e9, 0x001fd3e9, 0x08f23d26,
 238                          0x002fbff3, 0x001fe3e4, 0x0712ad23,
 239                          0x002fa800, 0x000ff3e0, 0x05631d1b,
 240                          0x001f9810, 0x000ffbe1, 0x03b3890d,
 241                          0x000f8c23, 0x000003e3, 0x0233e8fa,
 242                          0x3fef843b, 0x000003e7, 0x00f430e4,
 243                          0x3fbf8456, 0x3ff00bea, 0x00046cc8,
 244                          0x3f8f8c72, 0x3ff00bef, 0x3f3490ac },
 245        },
 246        { 0x1e00, {
 247                          0x001fbbf4, 0x001fbbf4, 0x09425112,
 248                          0x001fa800, 0x002fc7ed, 0x0792b110,
 249                          0x000f980e, 0x001fdbe6, 0x0613110a,
 250                          0x3fff8c20, 0x001fe7e3, 0x04a368fd,
 251                          0x3fcf8c33, 0x000ff7e2, 0x0343b8ed,
 252                          0x3f9f8c4a, 0x000fffe3, 0x0203f8da,
 253                          0x3f5f9c61, 0x000003e6, 0x00e428c5,
 254                          0x3f1fb07b, 0x000003eb, 0x3fe440af },
 255        },
 256        { 0x2000, {
 257                          0x000fa400, 0x000fa400, 0x09625902,
 258                          0x3fff980c, 0x001fb7f5, 0x0812b0ff,
 259                          0x3fdf901c, 0x001fc7ed, 0x06b2fcfa,
 260                          0x3faf902d, 0x001fd3e8, 0x055348f1,
 261                          0x3f7f983f, 0x001fe3e5, 0x04038ce3,
 262                          0x3f3fa454, 0x001fefe3, 0x02e3c8d1,
 263                          0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0,
 264                          0x3ecfd880, 0x000fffe6, 0x00c404ac },
 265        },
 266        { 0x2200, {
 267                          0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4,
 268                          0x3fbf9818, 0x3fffa400, 0x0842a8f1,
 269                          0x3f8f9827, 0x000fb3f7, 0x0702f0ec,
 270                          0x3f5fa037, 0x000fc3ef, 0x05d330e4,
 271                          0x3f2fac49, 0x001fcfea, 0x04a364d9,
 272                          0x3effc05c, 0x001fdbe7, 0x038394ca,
 273                          0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb,
 274                          0x3ea00083, 0x001fefe6, 0x0183c0a9 },
 275        },
 276        { 0x2400, {
 277                          0x3f9fa014, 0x3f9fa014, 0x098260e6,
 278                          0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5,
 279                          0x3f4fa431, 0x3fefa400, 0x0742d8e1,
 280                          0x3f1fb440, 0x3fffb3f8, 0x062310d9,
 281                          0x3eefc850, 0x000fbbf2, 0x050340d0,
 282                          0x3ecfe062, 0x000fcbec, 0x041364c2,
 283                          0x3ea00073, 0x001fd3ea, 0x03037cb5,
 284                          0x3e902086, 0x001fdfe8, 0x022388a5 },
 285        },
 286        { 0x2600, {
 287                          0x3f5fa81e, 0x3f5fa81e, 0x096258da,
 288                          0x3f3fac2b, 0x3f8fa412, 0x088290d8,
 289                          0x3f0fbc38, 0x3fafa408, 0x0772c8d5,
 290                          0x3eefcc47, 0x3fcfa800, 0x0672f4ce,
 291                          0x3ecfe456, 0x3fefaffa, 0x05531cc6,
 292                          0x3eb00066, 0x3fffbbf3, 0x047334bb,
 293                          0x3ea01c77, 0x000fc7ee, 0x039348ae,
 294                          0x3ea04486, 0x000fd3eb, 0x02b350a1 },
 295        },
 296        { 0x2800, {
 297                          0x3f2fb426, 0x3f2fb426, 0x094250ce,
 298                          0x3f0fc032, 0x3f4fac1b, 0x086284cd,
 299                          0x3eefd040, 0x3f7fa811, 0x0782acc9,
 300                          0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4,
 301                          0x3eb0005b, 0x3fbfac00, 0x05b2f4bc,
 302                          0x3eb0186a, 0x3fdfb3fa, 0x04c308b4,
 303                          0x3eb04077, 0x3fefbbf4, 0x03f31ca8,
 304                          0x3ec06884, 0x000fbff2, 0x03031c9e },
 305        },
 306        { 0x2a00, {
 307                          0x3f0fc42d, 0x3f0fc42d, 0x090240c4,
 308                          0x3eefd439, 0x3f2fb822, 0x08526cc2,
 309                          0x3edfe845, 0x3f4fb018, 0x078294bf,
 310                          0x3ec00051, 0x3f6fac0f, 0x06b2b4bb,
 311                          0x3ec0185f, 0x3f8fac07, 0x05e2ccb4,
 312                          0x3ec0386b, 0x3fafac00, 0x0502e8ac,
 313                          0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3,
 314                          0x3ef08482, 0x3fdfbbf6, 0x0372f898 },
 315        },
 316        { 0x2c00, {
 317                          0x3eefdc31, 0x3eefdc31, 0x08e238b8,
 318                          0x3edfec3d, 0x3f0fc828, 0x082258b9,
 319                          0x3ed00049, 0x3f1fc01e, 0x077278b6,
 320                          0x3ed01455, 0x3f3fb815, 0x06c294b2,
 321                          0x3ed03460, 0x3f5fb40d, 0x0602acac,
 322                          0x3ef0506c, 0x3f7fb006, 0x0542c0a4,
 323                          0x3f107476, 0x3f9fb400, 0x0472c89d,
 324                          0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 },
 325        },
 326        { 0x2e00, {
 327                          0x3eefec37, 0x3eefec37, 0x088220b0,
 328                          0x3ee00041, 0x3effdc2d, 0x07f244ae,
 329                          0x3ee0144c, 0x3f0fd023, 0x07625cad,
 330                          0x3ef02c57, 0x3f1fc81a, 0x06c274a9,
 331                          0x3f004861, 0x3f3fbc13, 0x060288a6,
 332                          0x3f20686b, 0x3f5fb80c, 0x05529c9e,
 333                          0x3f408c74, 0x3f6fb805, 0x04b2ac96,
 334                          0x3f80ac7e, 0x3f8fb800, 0x0402ac8e },
 335        },
 336        { 0x3000, {
 337                          0x3ef0003a, 0x3ef0003a, 0x084210a6,
 338                          0x3ef01045, 0x3effec32, 0x07b228a7,
 339                          0x3f00284e, 0x3f0fdc29, 0x073244a4,
 340                          0x3f104058, 0x3f0fd420, 0x06a258a2,
 341                          0x3f305c62, 0x3f2fc818, 0x0612689d,
 342                          0x3f508069, 0x3f3fc011, 0x05728496,
 343                          0x3f80a072, 0x3f4fc00a, 0x04d28c90,
 344                          0x3fc0c07b, 0x3f6fbc04, 0x04429088 },
 345        },
 346        { 0x3200, {
 347                          0x3f00103e, 0x3f00103e, 0x07f1fc9e,
 348                          0x3f102447, 0x3f000035, 0x0782149d,
 349                          0x3f203c4f, 0x3f0ff02c, 0x07122c9c,
 350                          0x3f405458, 0x3f0fe424, 0x06924099,
 351                          0x3f607061, 0x3f1fd41d, 0x06024c97,
 352                          0x3f909068, 0x3f2fcc16, 0x05726490,
 353                          0x3fc0b070, 0x3f3fc80f, 0x04f26c8a,
 354                          0x0000d077, 0x3f4fc409, 0x04627484 },
 355        },
 356        { 0x3400, {
 357                          0x3f202040, 0x3f202040, 0x07a1e898,
 358                          0x3f303449, 0x3f100c38, 0x0741fc98,
 359                          0x3f504c50, 0x3f10002f, 0x06e21495,
 360                          0x3f706459, 0x3f1ff028, 0x06722492,
 361                          0x3fa08060, 0x3f1fe421, 0x05f2348f,
 362                          0x3fd09c67, 0x3f1fdc19, 0x05824c89,
 363                          0x0000bc6e, 0x3f2fd014, 0x04f25086,
 364                          0x0040dc74, 0x3f3fcc0d, 0x04825c7f },
 365        },
 366        { 0x3600, {
 367                          0x3f403042, 0x3f403042, 0x0761d890,
 368                          0x3f504848, 0x3f301c3b, 0x0701f090,
 369                          0x3f805c50, 0x3f200c33, 0x06a2008f,
 370                          0x3fa07458, 0x3f10002b, 0x06520c8d,
 371                          0x3fd0905e, 0x3f1ff424, 0x05e22089,
 372                          0x0000ac65, 0x3f1fe81d, 0x05823483,
 373                          0x0030cc6a, 0x3f2fdc18, 0x04f23c81,
 374                          0x0080e871, 0x3f2fd412, 0x0482407c },
 375        },
 376        { 0x3800, {
 377                          0x3f604043, 0x3f604043, 0x0721c88a,
 378                          0x3f80544a, 0x3f502c3c, 0x06d1d88a,
 379                          0x3fb06851, 0x3f301c35, 0x0681e889,
 380                          0x3fd08456, 0x3f30082f, 0x0611fc88,
 381                          0x00009c5d, 0x3f200027, 0x05d20884,
 382                          0x0030b863, 0x3f2ff421, 0x05621880,
 383                          0x0070d468, 0x3f2fe81b, 0x0502247c,
 384                          0x00c0ec6f, 0x3f2fe015, 0x04a22877 },
 385        },
 386        { 0x3a00, {
 387                          0x3f904c44, 0x3f904c44, 0x06e1b884,
 388                          0x3fb0604a, 0x3f70383e, 0x0691c885,
 389                          0x3fe07451, 0x3f502c36, 0x0661d483,
 390                          0x00009055, 0x3f401831, 0x0601ec81,
 391                          0x0030a85b, 0x3f300c2a, 0x05b1f480,
 392                          0x0070c061, 0x3f300024, 0x0562047a,
 393                          0x00b0d867, 0x3f3ff41e, 0x05020c77,
 394                          0x00f0f46b, 0x3f2fec19, 0x04a21474 },
 395        },
 396        { 0x3c00, {
 397                          0x3fb05c43, 0x3fb05c43, 0x06c1b07e,
 398                          0x3fe06c4b, 0x3f902c3f, 0x0681c081,
 399                          0x0000844f, 0x3f703838, 0x0631cc7d,
 400                          0x00309855, 0x3f602433, 0x05d1d47e,
 401                          0x0060b459, 0x3f50142e, 0x0581e47b,
 402                          0x00a0c85f, 0x3f400828, 0x0531f078,
 403                          0x00e0e064, 0x3f300021, 0x0501fc73,
 404                          0x00b0fc6a, 0x3f3ff41d, 0x04a20873 },
 405        },
 406        { 0x3e00, {
 407                          0x3fe06444, 0x3fe06444, 0x0681a07a,
 408                          0x00007849, 0x3fc0503f, 0x0641b07a,
 409                          0x0020904d, 0x3fa0403a, 0x05f1c07a,
 410                          0x0060a453, 0x3f803034, 0x05c1c878,
 411                          0x0090b858, 0x3f70202f, 0x0571d477,
 412                          0x00d0d05d, 0x3f501829, 0x0531e073,
 413                          0x0110e462, 0x3f500825, 0x04e1e471,
 414                          0x01510065, 0x3f40001f, 0x04a1f06d },
 415        },
 416        { 0x4000, {
 417                          0x00007044, 0x00007044, 0x06519476,
 418                          0x00208448, 0x3fe05c3f, 0x0621a476,
 419                          0x0050984d, 0x3fc04c3a, 0x05e1b075,
 420                          0x0080ac52, 0x3fa03c35, 0x05a1b875,
 421                          0x00c0c056, 0x3f803030, 0x0561c473,
 422                          0x0100d45b, 0x3f70202b, 0x0521d46f,
 423                          0x0140e860, 0x3f601427, 0x04d1d46e,
 424                          0x01810064, 0x3f500822, 0x0491dc6b },
 425        },
 426        { 0x5000, {
 427                          0x0110a442, 0x0110a442, 0x0551545e,
 428                          0x0140b045, 0x00e0983f, 0x0531585f,
 429                          0x0160c047, 0x00c08c3c, 0x0511645e,
 430                          0x0190cc4a, 0x00908039, 0x04f1685f,
 431                          0x01c0dc4c, 0x00707436, 0x04d1705e,
 432                          0x0200e850, 0x00506833, 0x04b1785b,
 433                          0x0230f453, 0x00305c30, 0x0491805a,
 434                          0x02710056, 0x0010542d, 0x04718059 },
 435        },
 436        { 0x6000, {
 437                          0x01c0bc40, 0x01c0bc40, 0x04c13052,
 438                          0x01e0c841, 0x01a0b43d, 0x04c13851,
 439                          0x0210cc44, 0x0180a83c, 0x04a13453,
 440                          0x0230d845, 0x0160a03a, 0x04913c52,
 441                          0x0260e047, 0x01409838, 0x04714052,
 442                          0x0280ec49, 0x01208c37, 0x04514c50,
 443                          0x02b0f44b, 0x01008435, 0x04414c50,
 444                          0x02d1004c, 0x00e07c33, 0x0431544f },
 445        },
 446        { 0x7000, {
 447                          0x0230c83e, 0x0230c83e, 0x04711c4c,
 448                          0x0250d03f, 0x0210c43c, 0x0471204b,
 449                          0x0270d840, 0x0200b83c, 0x0451244b,
 450                          0x0290dc42, 0x01e0b43a, 0x0441244c,
 451                          0x02b0e443, 0x01c0b038, 0x0441284b,
 452                          0x02d0ec44, 0x01b0a438, 0x0421304a,
 453                          0x02f0f445, 0x0190a036, 0x04213449,
 454                          0x0310f847, 0x01709c34, 0x04213848 },
 455        },
 456        { 0x8000, {
 457                          0x0280d03d, 0x0280d03d, 0x04310c48,
 458                          0x02a0d43e, 0x0270c83c, 0x04311047,
 459                          0x02b0dc3e, 0x0250c83a, 0x04311447,
 460                          0x02d0e040, 0x0240c03a, 0x04211446,
 461                          0x02e0e840, 0x0220bc39, 0x04111847,
 462                          0x0300e842, 0x0210b438, 0x04012445,
 463                          0x0310f043, 0x0200b037, 0x04012045,
 464                          0x0330f444, 0x01e0ac36, 0x03f12445 },
 465        },
 466        { 0xefff, {
 467                          0x0340dc3a, 0x0340dc3a, 0x03b0ec40,
 468                          0x0340e03a, 0x0330e039, 0x03c0f03e,
 469                          0x0350e03b, 0x0330dc39, 0x03c0ec3e,
 470                          0x0350e43a, 0x0320dc38, 0x03c0f43e,
 471                          0x0360e43b, 0x0320d839, 0x03b0f03e,
 472                          0x0360e83b, 0x0310d838, 0x03c0fc3b,
 473                          0x0370e83b, 0x0310d439, 0x03a0f83d,
 474                          0x0370e83c, 0x0300d438, 0x03b0fc3c },
 475        }
 476};
 477
 478static void rvin_set_coeff(struct rvin_dev *vin, unsigned short xs)
 479{
 480        int i;
 481        const struct vin_coeff *p_prev_set = NULL;
 482        const struct vin_coeff *p_set = NULL;
 483
 484        /* Look for suitable coefficient values */
 485        for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
 486                p_prev_set = p_set;
 487                p_set = &vin_coeff_set[i];
 488
 489                if (xs < p_set->xs_value)
 490                        break;
 491        }
 492
 493        /* Use previous value if its XS value is closer */
 494        if (p_prev_set &&
 495            xs - p_prev_set->xs_value < p_set->xs_value - xs)
 496                p_set = p_prev_set;
 497
 498        /* Set coefficient registers */
 499        rvin_write(vin, p_set->coeff_set[0], VNC1A_REG);
 500        rvin_write(vin, p_set->coeff_set[1], VNC1B_REG);
 501        rvin_write(vin, p_set->coeff_set[2], VNC1C_REG);
 502
 503        rvin_write(vin, p_set->coeff_set[3], VNC2A_REG);
 504        rvin_write(vin, p_set->coeff_set[4], VNC2B_REG);
 505        rvin_write(vin, p_set->coeff_set[5], VNC2C_REG);
 506
 507        rvin_write(vin, p_set->coeff_set[6], VNC3A_REG);
 508        rvin_write(vin, p_set->coeff_set[7], VNC3B_REG);
 509        rvin_write(vin, p_set->coeff_set[8], VNC3C_REG);
 510
 511        rvin_write(vin, p_set->coeff_set[9], VNC4A_REG);
 512        rvin_write(vin, p_set->coeff_set[10], VNC4B_REG);
 513        rvin_write(vin, p_set->coeff_set[11], VNC4C_REG);
 514
 515        rvin_write(vin, p_set->coeff_set[12], VNC5A_REG);
 516        rvin_write(vin, p_set->coeff_set[13], VNC5B_REG);
 517        rvin_write(vin, p_set->coeff_set[14], VNC5C_REG);
 518
 519        rvin_write(vin, p_set->coeff_set[15], VNC6A_REG);
 520        rvin_write(vin, p_set->coeff_set[16], VNC6B_REG);
 521        rvin_write(vin, p_set->coeff_set[17], VNC6C_REG);
 522
 523        rvin_write(vin, p_set->coeff_set[18], VNC7A_REG);
 524        rvin_write(vin, p_set->coeff_set[19], VNC7B_REG);
 525        rvin_write(vin, p_set->coeff_set[20], VNC7C_REG);
 526
 527        rvin_write(vin, p_set->coeff_set[21], VNC8A_REG);
 528        rvin_write(vin, p_set->coeff_set[22], VNC8B_REG);
 529        rvin_write(vin, p_set->coeff_set[23], VNC8C_REG);
 530}
 531
 532static void rvin_crop_scale_comp_gen2(struct rvin_dev *vin)
 533{
 534        unsigned int crop_height;
 535        u32 xs, ys;
 536
 537        /* Set scaling coefficient */
 538        crop_height = vin->crop.height;
 539        if (V4L2_FIELD_HAS_BOTH(vin->format.field))
 540                crop_height *= 2;
 541
 542        ys = 0;
 543        if (crop_height != vin->compose.height)
 544                ys = (4096 * crop_height) / vin->compose.height;
 545        rvin_write(vin, ys, VNYS_REG);
 546
 547        xs = 0;
 548        if (vin->crop.width != vin->compose.width)
 549                xs = (4096 * vin->crop.width) / vin->compose.width;
 550
 551        /* Horizontal upscaling is up to double size */
 552        if (xs > 0 && xs < 2048)
 553                xs = 2048;
 554
 555        rvin_write(vin, xs, VNXS_REG);
 556
 557        /* Horizontal upscaling is done out by scaling down from double size */
 558        if (xs < 4096)
 559                xs *= 2;
 560
 561        rvin_set_coeff(vin, xs);
 562
 563        /* Set Start/End Pixel/Line Post-Clip */
 564        rvin_write(vin, 0, VNSPPOC_REG);
 565        rvin_write(vin, 0, VNSLPOC_REG);
 566        rvin_write(vin, vin->format.width - 1, VNEPPOC_REG);
 567
 568        if (V4L2_FIELD_HAS_BOTH(vin->format.field))
 569                rvin_write(vin, vin->format.height / 2 - 1, VNELPOC_REG);
 570        else
 571                rvin_write(vin, vin->format.height - 1, VNELPOC_REG);
 572
 573        vin_dbg(vin,
 574                "Pre-Clip: %ux%u@%u:%u YS: %d XS: %d Post-Clip: %ux%u@%u:%u\n",
 575                vin->crop.width, vin->crop.height, vin->crop.left,
 576                vin->crop.top, ys, xs, vin->format.width, vin->format.height,
 577                0, 0);
 578}
 579
 580void rvin_crop_scale_comp(struct rvin_dev *vin)
 581{
 582        const struct rvin_video_format *fmt;
 583        u32 stride;
 584
 585        /* Set Start/End Pixel/Line Pre-Clip */
 586        rvin_write(vin, vin->crop.left, VNSPPRC_REG);
 587        rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG);
 588        rvin_write(vin, vin->crop.top, VNSLPRC_REG);
 589        rvin_write(vin, vin->crop.top + vin->crop.height - 1, VNELPRC_REG);
 590
 591        /* TODO: Add support for the UDS scaler. */
 592        if (vin->info->model != RCAR_GEN3)
 593                rvin_crop_scale_comp_gen2(vin);
 594
 595        fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
 596        stride = vin->format.bytesperline / fmt->bpp;
 597
 598        /* For RAW8 format bpp is 1, but the hardware process RAW8
 599         * format in 2 pixel unit hence configure VNIS_REG as stride / 2.
 600         */
 601        switch (vin->format.pixelformat) {
 602        case V4L2_PIX_FMT_SBGGR8:
 603        case V4L2_PIX_FMT_SGBRG8:
 604        case V4L2_PIX_FMT_SGRBG8:
 605        case V4L2_PIX_FMT_SRGGB8:
 606                stride /= 2;
 607                break;
 608        default:
 609                break;
 610        }
 611
 612        rvin_write(vin, stride, VNIS_REG);
 613}
 614
 615/* -----------------------------------------------------------------------------
 616 * Hardware setup
 617 */
 618
 619static int rvin_setup(struct rvin_dev *vin)
 620{
 621        u32 vnmc, dmr, dmr2, interrupts;
 622        bool progressive = false, output_is_yuv = false, input_is_yuv = false;
 623
 624        switch (vin->format.field) {
 625        case V4L2_FIELD_TOP:
 626                vnmc = VNMC_IM_ODD;
 627                break;
 628        case V4L2_FIELD_BOTTOM:
 629                vnmc = VNMC_IM_EVEN;
 630                break;
 631        case V4L2_FIELD_INTERLACED:
 632                /* Default to TB */
 633                vnmc = VNMC_IM_FULL;
 634                /* Use BT if video standard can be read and is 60 Hz format */
 635                if (!vin->info->use_mc && vin->std & V4L2_STD_525_60)
 636                        vnmc = VNMC_IM_FULL | VNMC_FOC;
 637                break;
 638        case V4L2_FIELD_INTERLACED_TB:
 639                vnmc = VNMC_IM_FULL;
 640                break;
 641        case V4L2_FIELD_INTERLACED_BT:
 642                vnmc = VNMC_IM_FULL | VNMC_FOC;
 643                break;
 644        case V4L2_FIELD_SEQ_TB:
 645        case V4L2_FIELD_SEQ_BT:
 646        case V4L2_FIELD_NONE:
 647                vnmc = VNMC_IM_ODD_EVEN;
 648                progressive = true;
 649                break;
 650        case V4L2_FIELD_ALTERNATE:
 651                vnmc = VNMC_IM_ODD_EVEN;
 652                break;
 653        default:
 654                vnmc = VNMC_IM_ODD;
 655                break;
 656        }
 657
 658        /*
 659         * Input interface
 660         */
 661        switch (vin->mbus_code) {
 662        case MEDIA_BUS_FMT_YUYV8_1X16:
 663                /* BT.601/BT.1358 16bit YCbCr422 */
 664                vnmc |= VNMC_INF_YUV16;
 665                input_is_yuv = true;
 666                break;
 667        case MEDIA_BUS_FMT_UYVY8_1X16:
 668                vnmc |= VNMC_INF_YUV16 | VNMC_YCAL;
 669                input_is_yuv = true;
 670                break;
 671        case MEDIA_BUS_FMT_UYVY8_2X8:
 672                /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
 673                if (!vin->is_csi &&
 674                    vin->parallel.mbus_type == V4L2_MBUS_BT656)
 675                        vnmc |= VNMC_INF_YUV8_BT656;
 676                else
 677                        vnmc |= VNMC_INF_YUV8_BT601;
 678
 679                input_is_yuv = true;
 680                break;
 681        case MEDIA_BUS_FMT_RGB888_1X24:
 682                vnmc |= VNMC_INF_RGB888;
 683                break;
 684        case MEDIA_BUS_FMT_UYVY10_2X10:
 685                /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
 686                if (!vin->is_csi &&
 687                    vin->parallel.mbus_type == V4L2_MBUS_BT656)
 688                        vnmc |= VNMC_INF_YUV10_BT656;
 689                else
 690                        vnmc |= VNMC_INF_YUV10_BT601;
 691
 692                input_is_yuv = true;
 693                break;
 694        case MEDIA_BUS_FMT_SBGGR8_1X8:
 695        case MEDIA_BUS_FMT_SGBRG8_1X8:
 696        case MEDIA_BUS_FMT_SGRBG8_1X8:
 697        case MEDIA_BUS_FMT_SRGGB8_1X8:
 698                vnmc |= VNMC_INF_RAW8;
 699                break;
 700        default:
 701                break;
 702        }
 703
 704        /* Enable VSYNC Field Toggle mode after one VSYNC input */
 705        if (vin->info->model == RCAR_GEN3)
 706                dmr2 = VNDMR2_FTEV;
 707        else
 708                dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
 709
 710        if (!vin->is_csi) {
 711                /* Hsync Signal Polarity Select */
 712                if (!(vin->parallel.bus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
 713                        dmr2 |= VNDMR2_HPS;
 714
 715                /* Vsync Signal Polarity Select */
 716                if (!(vin->parallel.bus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
 717                        dmr2 |= VNDMR2_VPS;
 718
 719                /* Data Enable Polarity Select */
 720                if (vin->parallel.bus.flags & V4L2_MBUS_DATA_ENABLE_LOW)
 721                        dmr2 |= VNDMR2_CES;
 722
 723                switch (vin->mbus_code) {
 724                case MEDIA_BUS_FMT_UYVY8_2X8:
 725                        if (vin->parallel.bus.bus_width == 8 &&
 726                            vin->parallel.bus.data_shift == 8)
 727                                dmr2 |= VNDMR2_YDS;
 728                        break;
 729                default:
 730                        break;
 731                }
 732        }
 733
 734        /*
 735         * Output format
 736         */
 737        switch (vin->format.pixelformat) {
 738        case V4L2_PIX_FMT_NV12:
 739        case V4L2_PIX_FMT_NV16:
 740                rvin_write(vin,
 741                           ALIGN(vin->format.bytesperline * vin->format.height,
 742                                 0x80), VNUVAOF_REG);
 743                dmr = vin->format.pixelformat == V4L2_PIX_FMT_NV12 ?
 744                        VNDMR_DTMD_YCSEP_420 : VNDMR_DTMD_YCSEP;
 745                output_is_yuv = true;
 746                break;
 747        case V4L2_PIX_FMT_YUYV:
 748                dmr = VNDMR_BPSM;
 749                output_is_yuv = true;
 750                break;
 751        case V4L2_PIX_FMT_UYVY:
 752                dmr = 0;
 753                output_is_yuv = true;
 754                break;
 755        case V4L2_PIX_FMT_XRGB555:
 756                dmr = VNDMR_DTMD_ARGB;
 757                break;
 758        case V4L2_PIX_FMT_RGB565:
 759                dmr = 0;
 760                break;
 761        case V4L2_PIX_FMT_XBGR32:
 762                /* Note: not supported on M1 */
 763                dmr = VNDMR_EXRGB;
 764                break;
 765        case V4L2_PIX_FMT_ARGB555:
 766                dmr = (vin->alpha ? VNDMR_ABIT : 0) | VNDMR_DTMD_ARGB;
 767                break;
 768        case V4L2_PIX_FMT_ABGR32:
 769                dmr = VNDMR_A8BIT(vin->alpha) | VNDMR_EXRGB | VNDMR_DTMD_ARGB;
 770                break;
 771        case V4L2_PIX_FMT_SBGGR8:
 772        case V4L2_PIX_FMT_SGBRG8:
 773        case V4L2_PIX_FMT_SGRBG8:
 774        case V4L2_PIX_FMT_SRGGB8:
 775                dmr = 0;
 776                break;
 777        default:
 778                vin_err(vin, "Invalid pixelformat (0x%x)\n",
 779                        vin->format.pixelformat);
 780                return -EINVAL;
 781        }
 782
 783        /* Always update on field change */
 784        vnmc |= VNMC_VUP;
 785
 786        /* If input and output use the same colorspace, use bypass mode */
 787        if (input_is_yuv == output_is_yuv)
 788                vnmc |= VNMC_BPS;
 789
 790        if (vin->info->model == RCAR_GEN3) {
 791                /* Select between CSI-2 and parallel input */
 792                if (vin->is_csi)
 793                        vnmc &= ~VNMC_DPINE;
 794                else
 795                        vnmc |= VNMC_DPINE;
 796        }
 797
 798        /* Progressive or interlaced mode */
 799        interrupts = progressive ? VNIE_FIE : VNIE_EFE;
 800
 801        /* Ack interrupts */
 802        rvin_write(vin, interrupts, VNINTS_REG);
 803        /* Enable interrupts */
 804        rvin_write(vin, interrupts, VNIE_REG);
 805        /* Start capturing */
 806        rvin_write(vin, dmr, VNDMR_REG);
 807        rvin_write(vin, dmr2, VNDMR2_REG);
 808
 809        /* Enable module */
 810        rvin_write(vin, vnmc | VNMC_ME, VNMC_REG);
 811
 812        return 0;
 813}
 814
 815static void rvin_disable_interrupts(struct rvin_dev *vin)
 816{
 817        rvin_write(vin, 0, VNIE_REG);
 818}
 819
 820static u32 rvin_get_interrupt_status(struct rvin_dev *vin)
 821{
 822        return rvin_read(vin, VNINTS_REG);
 823}
 824
 825static void rvin_ack_interrupt(struct rvin_dev *vin)
 826{
 827        rvin_write(vin, rvin_read(vin, VNINTS_REG), VNINTS_REG);
 828}
 829
 830static bool rvin_capture_active(struct rvin_dev *vin)
 831{
 832        return rvin_read(vin, VNMS_REG) & VNMS_CA;
 833}
 834
 835static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
 836{
 837        if (vin->format.field == V4L2_FIELD_ALTERNATE) {
 838                /* If FS is set it is an Even field. */
 839                if (vnms & VNMS_FS)
 840                        return V4L2_FIELD_BOTTOM;
 841                return V4L2_FIELD_TOP;
 842        }
 843
 844        return vin->format.field;
 845}
 846
 847static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr)
 848{
 849        const struct rvin_video_format *fmt;
 850        int offsetx, offsety;
 851        dma_addr_t offset;
 852
 853        fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
 854
 855        /*
 856         * There is no HW support for composition do the beast we can
 857         * by modifying the buffer offset
 858         */
 859        offsetx = vin->compose.left * fmt->bpp;
 860        offsety = vin->compose.top * vin->format.bytesperline;
 861        offset = addr + offsetx + offsety;
 862
 863        /*
 864         * The address needs to be 128 bytes aligned. Driver should never accept
 865         * settings that do not satisfy this in the first place...
 866         */
 867        if (WARN_ON((offsetx | offsety | offset) & HW_BUFFER_MASK))
 868                return;
 869
 870        rvin_write(vin, offset, VNMB_REG(slot));
 871}
 872
 873/*
 874 * Moves a buffer from the queue to the HW slot. If no buffer is
 875 * available use the scratch buffer. The scratch buffer is never
 876 * returned to userspace, its only function is to enable the capture
 877 * loop to keep running.
 878 */
 879static void rvin_fill_hw_slot(struct rvin_dev *vin, int slot)
 880{
 881        struct rvin_buffer *buf;
 882        struct vb2_v4l2_buffer *vbuf;
 883        dma_addr_t phys_addr;
 884        int prev;
 885
 886        /* A already populated slot shall never be overwritten. */
 887        if (WARN_ON(vin->buf_hw[slot].buffer))
 888                return;
 889
 890        prev = (slot == 0 ? HW_BUFFER_NUM : slot) - 1;
 891
 892        if (vin->buf_hw[prev].type == HALF_TOP) {
 893                vbuf = vin->buf_hw[prev].buffer;
 894                vin->buf_hw[slot].buffer = vbuf;
 895                vin->buf_hw[slot].type = HALF_BOTTOM;
 896                switch (vin->format.pixelformat) {
 897                case V4L2_PIX_FMT_NV12:
 898                case V4L2_PIX_FMT_NV16:
 899                        phys_addr = vin->buf_hw[prev].phys +
 900                                vin->format.sizeimage / 4;
 901                        break;
 902                default:
 903                        phys_addr = vin->buf_hw[prev].phys +
 904                                vin->format.sizeimage / 2;
 905                        break;
 906                }
 907        } else if (vin->state != RUNNING || list_empty(&vin->buf_list)) {
 908                vin->buf_hw[slot].buffer = NULL;
 909                vin->buf_hw[slot].type = FULL;
 910                phys_addr = vin->scratch_phys;
 911        } else {
 912                /* Keep track of buffer we give to HW */
 913                buf = list_entry(vin->buf_list.next, struct rvin_buffer, list);
 914                vbuf = &buf->vb;
 915                list_del_init(to_buf_list(vbuf));
 916                vin->buf_hw[slot].buffer = vbuf;
 917
 918                vin->buf_hw[slot].type =
 919                        V4L2_FIELD_IS_SEQUENTIAL(vin->format.field) ?
 920                        HALF_TOP : FULL;
 921
 922                /* Setup DMA */
 923                phys_addr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
 924        }
 925
 926        vin_dbg(vin, "Filling HW slot: %d type: %d buffer: %p\n",
 927                slot, vin->buf_hw[slot].type, vin->buf_hw[slot].buffer);
 928
 929        vin->buf_hw[slot].phys = phys_addr;
 930        rvin_set_slot_addr(vin, slot, phys_addr);
 931}
 932
 933static int rvin_capture_start(struct rvin_dev *vin)
 934{
 935        int slot, ret;
 936
 937        for (slot = 0; slot < HW_BUFFER_NUM; slot++) {
 938                vin->buf_hw[slot].buffer = NULL;
 939                vin->buf_hw[slot].type = FULL;
 940        }
 941
 942        for (slot = 0; slot < HW_BUFFER_NUM; slot++)
 943                rvin_fill_hw_slot(vin, slot);
 944
 945        rvin_crop_scale_comp(vin);
 946
 947        ret = rvin_setup(vin);
 948        if (ret)
 949                return ret;
 950
 951        vin_dbg(vin, "Starting to capture\n");
 952
 953        /* Continuous Frame Capture Mode */
 954        rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
 955
 956        vin->state = STARTING;
 957
 958        return 0;
 959}
 960
 961static void rvin_capture_stop(struct rvin_dev *vin)
 962{
 963        /* Set continuous & single transfer off */
 964        rvin_write(vin, 0, VNFC_REG);
 965
 966        /* Disable module */
 967        rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG);
 968}
 969
 970/* -----------------------------------------------------------------------------
 971 * DMA Functions
 972 */
 973
 974#define RVIN_TIMEOUT_MS 100
 975#define RVIN_RETRIES 10
 976
 977static irqreturn_t rvin_irq(int irq, void *data)
 978{
 979        struct rvin_dev *vin = data;
 980        u32 int_status, vnms;
 981        int slot;
 982        unsigned int handled = 0;
 983        unsigned long flags;
 984
 985        spin_lock_irqsave(&vin->qlock, flags);
 986
 987        int_status = rvin_get_interrupt_status(vin);
 988        if (!int_status)
 989                goto done;
 990
 991        rvin_ack_interrupt(vin);
 992        handled = 1;
 993
 994        /* Nothing to do if capture status is 'STOPPED' */
 995        if (vin->state == STOPPED) {
 996                vin_dbg(vin, "IRQ while state stopped\n");
 997                goto done;
 998        }
 999
1000        /* Prepare for capture and update state */
1001        vnms = rvin_read(vin, VNMS_REG);
1002        slot = (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
1003
1004        /*
1005         * To hand buffers back in a known order to userspace start
1006         * to capture first from slot 0.
1007         */
1008        if (vin->state == STARTING) {
1009                if (slot != 0) {
1010                        vin_dbg(vin, "Starting sync slot: %d\n", slot);
1011                        goto done;
1012                }
1013
1014                vin_dbg(vin, "Capture start synced!\n");
1015                vin->state = RUNNING;
1016        }
1017
1018        /* Capture frame */
1019        if (vin->buf_hw[slot].buffer) {
1020                /*
1021                 * Nothing to do but refill the hardware slot if
1022                 * capture only filled first half of vb2 buffer.
1023                 */
1024                if (vin->buf_hw[slot].type == HALF_TOP) {
1025                        vin->buf_hw[slot].buffer = NULL;
1026                        rvin_fill_hw_slot(vin, slot);
1027                        goto done;
1028                }
1029
1030                vin->buf_hw[slot].buffer->field =
1031                        rvin_get_active_field(vin, vnms);
1032                vin->buf_hw[slot].buffer->sequence = vin->sequence;
1033                vin->buf_hw[slot].buffer->vb2_buf.timestamp = ktime_get_ns();
1034                vb2_buffer_done(&vin->buf_hw[slot].buffer->vb2_buf,
1035                                VB2_BUF_STATE_DONE);
1036                vin->buf_hw[slot].buffer = NULL;
1037        } else {
1038                /* Scratch buffer was used, dropping frame. */
1039                vin_dbg(vin, "Dropping frame %u\n", vin->sequence);
1040        }
1041
1042        vin->sequence++;
1043
1044        /* Prepare for next frame */
1045        rvin_fill_hw_slot(vin, slot);
1046done:
1047        spin_unlock_irqrestore(&vin->qlock, flags);
1048
1049        return IRQ_RETVAL(handled);
1050}
1051
1052static void return_unused_buffers(struct rvin_dev *vin,
1053                                  enum vb2_buffer_state state)
1054{
1055        struct rvin_buffer *buf, *node;
1056        unsigned long flags;
1057
1058        spin_lock_irqsave(&vin->qlock, flags);
1059
1060        list_for_each_entry_safe(buf, node, &vin->buf_list, list) {
1061                vb2_buffer_done(&buf->vb.vb2_buf, state);
1062                list_del(&buf->list);
1063        }
1064
1065        spin_unlock_irqrestore(&vin->qlock, flags);
1066}
1067
1068static int rvin_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
1069                            unsigned int *nplanes, unsigned int sizes[],
1070                            struct device *alloc_devs[])
1071
1072{
1073        struct rvin_dev *vin = vb2_get_drv_priv(vq);
1074
1075        /* Make sure the image size is large enough. */
1076        if (*nplanes)
1077                return sizes[0] < vin->format.sizeimage ? -EINVAL : 0;
1078
1079        *nplanes = 1;
1080        sizes[0] = vin->format.sizeimage;
1081
1082        return 0;
1083};
1084
1085static int rvin_buffer_prepare(struct vb2_buffer *vb)
1086{
1087        struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue);
1088        unsigned long size = vin->format.sizeimage;
1089
1090        if (vb2_plane_size(vb, 0) < size) {
1091                vin_err(vin, "buffer too small (%lu < %lu)\n",
1092                        vb2_plane_size(vb, 0), size);
1093                return -EINVAL;
1094        }
1095
1096        vb2_set_plane_payload(vb, 0, size);
1097
1098        return 0;
1099}
1100
1101static void rvin_buffer_queue(struct vb2_buffer *vb)
1102{
1103        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1104        struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue);
1105        unsigned long flags;
1106
1107        spin_lock_irqsave(&vin->qlock, flags);
1108
1109        list_add_tail(to_buf_list(vbuf), &vin->buf_list);
1110
1111        spin_unlock_irqrestore(&vin->qlock, flags);
1112}
1113
1114static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd,
1115                                   struct media_pad *pad)
1116{
1117        struct v4l2_subdev_format fmt = {
1118                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1119        };
1120
1121        fmt.pad = pad->index;
1122        if (v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt))
1123                return -EPIPE;
1124
1125        switch (fmt.format.code) {
1126        case MEDIA_BUS_FMT_YUYV8_1X16:
1127        case MEDIA_BUS_FMT_UYVY8_1X16:
1128        case MEDIA_BUS_FMT_UYVY8_2X8:
1129        case MEDIA_BUS_FMT_UYVY10_2X10:
1130        case MEDIA_BUS_FMT_RGB888_1X24:
1131                break;
1132        case MEDIA_BUS_FMT_SBGGR8_1X8:
1133                if (vin->format.pixelformat != V4L2_PIX_FMT_SBGGR8)
1134                        return -EPIPE;
1135                break;
1136        case MEDIA_BUS_FMT_SGBRG8_1X8:
1137                if (vin->format.pixelformat != V4L2_PIX_FMT_SGBRG8)
1138                        return -EPIPE;
1139                break;
1140        case MEDIA_BUS_FMT_SGRBG8_1X8:
1141                if (vin->format.pixelformat != V4L2_PIX_FMT_SGRBG8)
1142                        return -EPIPE;
1143                break;
1144        case MEDIA_BUS_FMT_SRGGB8_1X8:
1145                if (vin->format.pixelformat != V4L2_PIX_FMT_SRGGB8)
1146                        return -EPIPE;
1147                break;
1148        default:
1149                return -EPIPE;
1150        }
1151        vin->mbus_code = fmt.format.code;
1152
1153        switch (fmt.format.field) {
1154        case V4L2_FIELD_TOP:
1155        case V4L2_FIELD_BOTTOM:
1156        case V4L2_FIELD_NONE:
1157        case V4L2_FIELD_INTERLACED_TB:
1158        case V4L2_FIELD_INTERLACED_BT:
1159        case V4L2_FIELD_INTERLACED:
1160        case V4L2_FIELD_SEQ_TB:
1161        case V4L2_FIELD_SEQ_BT:
1162                /* Supported natively */
1163                break;
1164        case V4L2_FIELD_ALTERNATE:
1165                switch (vin->format.field) {
1166                case V4L2_FIELD_TOP:
1167                case V4L2_FIELD_BOTTOM:
1168                case V4L2_FIELD_NONE:
1169                case V4L2_FIELD_ALTERNATE:
1170                        break;
1171                case V4L2_FIELD_INTERLACED_TB:
1172                case V4L2_FIELD_INTERLACED_BT:
1173                case V4L2_FIELD_INTERLACED:
1174                case V4L2_FIELD_SEQ_TB:
1175                case V4L2_FIELD_SEQ_BT:
1176                        /* Use VIN hardware to combine the two fields */
1177                        fmt.format.height *= 2;
1178                        break;
1179                default:
1180                        return -EPIPE;
1181                }
1182                break;
1183        default:
1184                return -EPIPE;
1185        }
1186
1187        if (fmt.format.width != vin->format.width ||
1188            fmt.format.height != vin->format.height ||
1189            fmt.format.code != vin->mbus_code)
1190                return -EPIPE;
1191
1192        return 0;
1193}
1194
1195static int rvin_set_stream(struct rvin_dev *vin, int on)
1196{
1197        struct media_pipeline *pipe;
1198        struct media_device *mdev;
1199        struct v4l2_subdev *sd;
1200        struct media_pad *pad;
1201        int ret;
1202
1203        /* No media controller used, simply pass operation to subdevice. */
1204        if (!vin->info->use_mc) {
1205                ret = v4l2_subdev_call(vin->parallel.subdev, video, s_stream,
1206                                       on);
1207
1208                return ret == -ENOIOCTLCMD ? 0 : ret;
1209        }
1210
1211        pad = media_entity_remote_pad(&vin->pad);
1212        if (!pad)
1213                return -EPIPE;
1214
1215        sd = media_entity_to_v4l2_subdev(pad->entity);
1216
1217        if (!on) {
1218                media_pipeline_stop(&vin->vdev.entity);
1219                return v4l2_subdev_call(sd, video, s_stream, 0);
1220        }
1221
1222        ret = rvin_mc_validate_format(vin, sd, pad);
1223        if (ret)
1224                return ret;
1225
1226        /*
1227         * The graph lock needs to be taken to protect concurrent
1228         * starts of multiple VIN instances as they might share
1229         * a common subdevice down the line and then should use
1230         * the same pipe.
1231         */
1232        mdev = vin->vdev.entity.graph_obj.mdev;
1233        mutex_lock(&mdev->graph_mutex);
1234        pipe = sd->entity.pipe ? sd->entity.pipe : &vin->vdev.pipe;
1235        ret = __media_pipeline_start(&vin->vdev.entity, pipe);
1236        mutex_unlock(&mdev->graph_mutex);
1237        if (ret)
1238                return ret;
1239
1240        ret = v4l2_subdev_call(sd, video, s_stream, 1);
1241        if (ret == -ENOIOCTLCMD)
1242                ret = 0;
1243        if (ret)
1244                media_pipeline_stop(&vin->vdev.entity);
1245
1246        return ret;
1247}
1248
1249int rvin_start_streaming(struct rvin_dev *vin)
1250{
1251        unsigned long flags;
1252        int ret;
1253
1254        ret = rvin_set_stream(vin, 1);
1255        if (ret)
1256                return ret;
1257
1258        spin_lock_irqsave(&vin->qlock, flags);
1259
1260        vin->sequence = 0;
1261
1262        ret = rvin_capture_start(vin);
1263        if (ret)
1264                rvin_set_stream(vin, 0);
1265
1266        spin_unlock_irqrestore(&vin->qlock, flags);
1267
1268        return ret;
1269}
1270
1271static int rvin_start_streaming_vq(struct vb2_queue *vq, unsigned int count)
1272{
1273        struct rvin_dev *vin = vb2_get_drv_priv(vq);
1274        int ret = -ENOMEM;
1275
1276        /* Allocate scratch buffer. */
1277        vin->scratch = dma_alloc_coherent(vin->dev, vin->format.sizeimage,
1278                                          &vin->scratch_phys, GFP_KERNEL);
1279        if (!vin->scratch)
1280                goto err_scratch;
1281
1282        ret = rvin_start_streaming(vin);
1283        if (ret)
1284                goto err_start;
1285
1286        return 0;
1287err_start:
1288        dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
1289                          vin->scratch_phys);
1290err_scratch:
1291        return_unused_buffers(vin, VB2_BUF_STATE_QUEUED);
1292
1293        return ret;
1294}
1295
1296void rvin_stop_streaming(struct rvin_dev *vin)
1297{
1298        unsigned int i, retries;
1299        unsigned long flags;
1300        bool buffersFreed;
1301
1302        spin_lock_irqsave(&vin->qlock, flags);
1303
1304        if (vin->state == STOPPED) {
1305                spin_unlock_irqrestore(&vin->qlock, flags);
1306                return;
1307        }
1308
1309        vin->state = STOPPING;
1310
1311        /* Wait until only scratch buffer is used, max 3 interrupts. */
1312        retries = 0;
1313        while (retries++ < RVIN_RETRIES) {
1314                buffersFreed = true;
1315                for (i = 0; i < HW_BUFFER_NUM; i++)
1316                        if (vin->buf_hw[i].buffer)
1317                                buffersFreed = false;
1318
1319                if (buffersFreed)
1320                        break;
1321
1322                spin_unlock_irqrestore(&vin->qlock, flags);
1323                msleep(RVIN_TIMEOUT_MS);
1324                spin_lock_irqsave(&vin->qlock, flags);
1325        }
1326
1327        /* Wait for streaming to stop */
1328        retries = 0;
1329        while (retries++ < RVIN_RETRIES) {
1330
1331                rvin_capture_stop(vin);
1332
1333                /* Check if HW is stopped */
1334                if (!rvin_capture_active(vin)) {
1335                        vin->state = STOPPED;
1336                        break;
1337                }
1338
1339                spin_unlock_irqrestore(&vin->qlock, flags);
1340                msleep(RVIN_TIMEOUT_MS);
1341                spin_lock_irqsave(&vin->qlock, flags);
1342        }
1343
1344        if (!buffersFreed || vin->state != STOPPED) {
1345                /*
1346                 * If this happens something have gone horribly wrong.
1347                 * Set state to stopped to prevent the interrupt handler
1348                 * to make things worse...
1349                 */
1350                vin_err(vin, "Failed stop HW, something is seriously broken\n");
1351                vin->state = STOPPED;
1352        }
1353
1354        spin_unlock_irqrestore(&vin->qlock, flags);
1355
1356        rvin_set_stream(vin, 0);
1357
1358        /* disable interrupts */
1359        rvin_disable_interrupts(vin);
1360}
1361
1362static void rvin_stop_streaming_vq(struct vb2_queue *vq)
1363{
1364        struct rvin_dev *vin = vb2_get_drv_priv(vq);
1365
1366        rvin_stop_streaming(vin);
1367
1368        /* Free scratch buffer. */
1369        dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch,
1370                          vin->scratch_phys);
1371
1372        return_unused_buffers(vin, VB2_BUF_STATE_ERROR);
1373}
1374
1375static const struct vb2_ops rvin_qops = {
1376        .queue_setup            = rvin_queue_setup,
1377        .buf_prepare            = rvin_buffer_prepare,
1378        .buf_queue              = rvin_buffer_queue,
1379        .start_streaming        = rvin_start_streaming_vq,
1380        .stop_streaming         = rvin_stop_streaming_vq,
1381        .wait_prepare           = vb2_ops_wait_prepare,
1382        .wait_finish            = vb2_ops_wait_finish,
1383};
1384
1385void rvin_dma_unregister(struct rvin_dev *vin)
1386{
1387        mutex_destroy(&vin->lock);
1388
1389        v4l2_device_unregister(&vin->v4l2_dev);
1390}
1391
1392int rvin_dma_register(struct rvin_dev *vin, int irq)
1393{
1394        struct vb2_queue *q = &vin->queue;
1395        int i, ret;
1396
1397        /* Initialize the top-level structure */
1398        ret = v4l2_device_register(vin->dev, &vin->v4l2_dev);
1399        if (ret)
1400                return ret;
1401
1402        mutex_init(&vin->lock);
1403        INIT_LIST_HEAD(&vin->buf_list);
1404
1405        spin_lock_init(&vin->qlock);
1406
1407        vin->state = STOPPED;
1408
1409        for (i = 0; i < HW_BUFFER_NUM; i++)
1410                vin->buf_hw[i].buffer = NULL;
1411
1412        /* buffer queue */
1413        q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1414        q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
1415        q->lock = &vin->lock;
1416        q->drv_priv = vin;
1417        q->buf_struct_size = sizeof(struct rvin_buffer);
1418        q->ops = &rvin_qops;
1419        q->mem_ops = &vb2_dma_contig_memops;
1420        q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1421        q->min_buffers_needed = 4;
1422        q->dev = vin->dev;
1423
1424        ret = vb2_queue_init(q);
1425        if (ret < 0) {
1426                vin_err(vin, "failed to initialize VB2 queue\n");
1427                goto error;
1428        }
1429
1430        /* irq */
1431        ret = devm_request_irq(vin->dev, irq, rvin_irq, IRQF_SHARED,
1432                               KBUILD_MODNAME, vin);
1433        if (ret) {
1434                vin_err(vin, "failed to request irq\n");
1435                goto error;
1436        }
1437
1438        return 0;
1439error:
1440        rvin_dma_unregister(vin);
1441
1442        return ret;
1443}
1444
1445/* -----------------------------------------------------------------------------
1446 * Gen3 CHSEL manipulation
1447 */
1448
1449/*
1450 * There is no need to have locking around changing the routing
1451 * as it's only possible to do so when no VIN in the group is
1452 * streaming so nothing can race with the VNMC register.
1453 */
1454int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
1455{
1456        const struct rvin_group_route *route;
1457        u32 ifmd = 0;
1458        u32 vnmc;
1459        int ret;
1460
1461        ret = pm_runtime_resume_and_get(vin->dev);
1462        if (ret < 0)
1463                return ret;
1464
1465        /* Make register writes take effect immediately. */
1466        vnmc = rvin_read(vin, VNMC_REG);
1467        rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
1468
1469        /*
1470         * Set data expansion mode to "pad with 0s" by inspecting the routes
1471         * table to find out which bit fields are available in the IFMD
1472         * register. IFMD_DES1 controls data expansion mode for CSI20/21,
1473         * IFMD_DES0 controls data expansion mode for CSI40/41.
1474         */
1475        for (route = vin->info->routes; route->mask; route++) {
1476                if (route->csi == RVIN_CSI20 || route->csi == RVIN_CSI21)
1477                        ifmd |= VNCSI_IFMD_DES1;
1478                else
1479                        ifmd |= VNCSI_IFMD_DES0;
1480
1481                if (ifmd == (VNCSI_IFMD_DES0 | VNCSI_IFMD_DES1))
1482                        break;
1483        }
1484
1485        if (ifmd) {
1486                ifmd |= VNCSI_IFMD_CSI_CHSEL(chsel);
1487                rvin_write(vin, ifmd, VNCSI_IFMD_REG);
1488        }
1489
1490        vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
1491
1492        vin->chsel = chsel;
1493
1494        /* Restore VNMC. */
1495        rvin_write(vin, vnmc, VNMC_REG);
1496
1497        pm_runtime_put(vin->dev);
1498
1499        return 0;
1500}
1501
1502void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha)
1503{
1504        unsigned long flags;
1505        u32 dmr;
1506
1507        spin_lock_irqsave(&vin->qlock, flags);
1508
1509        vin->alpha = alpha;
1510
1511        if (vin->state == STOPPED)
1512                goto out;
1513
1514        switch (vin->format.pixelformat) {
1515        case V4L2_PIX_FMT_ARGB555:
1516                dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_ABIT;
1517                if (vin->alpha)
1518                        dmr |= VNDMR_ABIT;
1519                break;
1520        case V4L2_PIX_FMT_ABGR32:
1521                dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_A8BIT_MASK;
1522                dmr |= VNDMR_A8BIT(vin->alpha);
1523                break;
1524        default:
1525                goto out;
1526        }
1527
1528        rvin_write(vin, dmr,  VNDMR_REG);
1529out:
1530        spin_unlock_irqrestore(&vin->qlock, flags);
1531}
1532