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