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