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