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 143 struct 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 152 static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset) 153 { 154 iowrite32(value, vin->base + offset); 155 } 156 157 static 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 166 struct vin_coeff { 167 unsigned short xs_value; 168 u32 coeff_set[24]; 169 }; 170 171 static 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 484 static 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 538 static 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 586 void 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 626 static 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 856 static void rvin_disable_interrupts(struct rvin_dev *vin) 857 { 858 rvin_write(vin, 0, VNIE_REG); 859 } 860 861 static u32 rvin_get_interrupt_status(struct rvin_dev *vin) 862 { 863 return rvin_read(vin, VNINTS_REG); 864 } 865 866 static void rvin_ack_interrupt(struct rvin_dev *vin) 867 { 868 rvin_write(vin, rvin_read(vin, VNINTS_REG), VNINTS_REG); 869 } 870 871 static bool rvin_capture_active(struct rvin_dev *vin) 872 { 873 return rvin_read(vin, VNMS_REG) & VNMS_CA; 874 } 875 876 static 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 888 static 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 */ 920 static 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 975 static 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 1003 static 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 1019 static 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); 1092 done: 1093 spin_unlock_irqrestore(&vin->qlock, flags); 1094 1095 return IRQ_RETVAL(handled); 1096 } 1097 1098 static 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 1114 static 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 1131 static 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 1147 static 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 1160 static 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 1245 static 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_pad_remote_pad_first(&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 1299 int 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 1321 static 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; 1337 err_start: 1338 dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch, 1339 vin->scratch_phys); 1340 err_scratch: 1341 return_unused_buffers(vin, VB2_BUF_STATE_QUEUED); 1342 1343 return ret; 1344 } 1345 1346 void 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 1422 static 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 1435 static 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 1445 void rvin_dma_unregister(struct rvin_dev *vin) 1446 { 1447 mutex_destroy(&vin->lock); 1448 1449 v4l2_device_unregister(&vin->v4l2_dev); 1450 } 1451 1452 int 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; 1499 error: 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 */ 1514 int 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 1562 void 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); 1589 out: 1590 spin_unlock_irqrestore(&vin->qlock, flags); 1591 } 1592