1aa7b8278SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0+ 2f00add96SNiklas Söderlund /* 3f00add96SNiklas Söderlund * Driver for Renesas R-Car VIN 4f00add96SNiklas Söderlund * 5f00add96SNiklas Söderlund * Copyright (C) 2016 Renesas Electronics Corp. 6f00add96SNiklas Söderlund * Copyright (C) 2011-2013 Renesas Solutions Corp. 7f00add96SNiklas Söderlund * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com> 8f00add96SNiklas Söderlund * Copyright (C) 2008 Magnus Damm 9f00add96SNiklas Söderlund * 10f00add96SNiklas Söderlund * Based on the soc-camera rcar_vin driver 11f00add96SNiklas Söderlund */ 12f00add96SNiklas Söderlund 13f00add96SNiklas Söderlund #include <linux/delay.h> 14f00add96SNiklas Söderlund #include <linux/interrupt.h> 1590dedce9SNiklas Söderlund #include <linux/pm_runtime.h> 16f00add96SNiklas Söderlund 17f00add96SNiklas Söderlund #include <media/videobuf2-dma-contig.h> 18f00add96SNiklas Söderlund 19f00add96SNiklas Söderlund #include "rcar-vin.h" 20f00add96SNiklas Söderlund 21f00add96SNiklas Söderlund /* ----------------------------------------------------------------------------- 22f00add96SNiklas Söderlund * HW Functions 23f00add96SNiklas Söderlund */ 24f00add96SNiklas Söderlund 25f00add96SNiklas Söderlund /* Register offsets for R-Car VIN */ 26f00add96SNiklas Söderlund #define VNMC_REG 0x00 /* Video n Main Control Register */ 27f00add96SNiklas Söderlund #define VNMS_REG 0x04 /* Video n Module Status Register */ 28f00add96SNiklas Söderlund #define VNFC_REG 0x08 /* Video n Frame Capture Register */ 29f00add96SNiklas Söderlund #define VNSLPRC_REG 0x0C /* Video n Start Line Pre-Clip Register */ 30f00add96SNiklas Söderlund #define VNELPRC_REG 0x10 /* Video n End Line Pre-Clip Register */ 31f00add96SNiklas Söderlund #define VNSPPRC_REG 0x14 /* Video n Start Pixel Pre-Clip Register */ 32f00add96SNiklas Söderlund #define VNEPPRC_REG 0x18 /* Video n End Pixel Pre-Clip Register */ 33f00add96SNiklas Söderlund #define VNIS_REG 0x2C /* Video n Image Stride Register */ 34f00add96SNiklas Söderlund #define VNMB_REG(m) (0x30 + ((m) << 2)) /* Video n Memory Base m Register */ 35f00add96SNiklas Söderlund #define VNIE_REG 0x40 /* Video n Interrupt Enable Register */ 36f00add96SNiklas Söderlund #define VNINTS_REG 0x44 /* Video n Interrupt Status Register */ 37f00add96SNiklas Söderlund #define VNSI_REG 0x48 /* Video n Scanline Interrupt Register */ 38f00add96SNiklas Söderlund #define VNMTC_REG 0x4C /* Video n Memory Transfer Control Register */ 39f00add96SNiklas Söderlund #define VNDMR_REG 0x58 /* Video n Data Mode Register */ 40f00add96SNiklas Söderlund #define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */ 41f00add96SNiklas Söderlund #define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */ 424394eb24SNiklas Söderlund 434394eb24SNiklas Söderlund /* Register offsets specific for Gen2 */ 444394eb24SNiklas Söderlund #define VNSLPOC_REG 0x1C /* Video n Start Line Post-Clip Register */ 454394eb24SNiklas Söderlund #define VNELPOC_REG 0x20 /* Video n End Line Post-Clip Register */ 464394eb24SNiklas Söderlund #define VNSPPOC_REG 0x24 /* Video n Start Pixel Post-Clip Register */ 474394eb24SNiklas Söderlund #define VNEPPOC_REG 0x28 /* Video n End Pixel Post-Clip Register */ 484394eb24SNiklas Söderlund #define VNYS_REG 0x50 /* Video n Y Scale Register */ 494394eb24SNiklas Söderlund #define VNXS_REG 0x54 /* Video n X Scale Register */ 50f00add96SNiklas Söderlund #define VNC1A_REG 0x80 /* Video n Coefficient Set C1A Register */ 51f00add96SNiklas Söderlund #define VNC1B_REG 0x84 /* Video n Coefficient Set C1B Register */ 52f00add96SNiklas Söderlund #define VNC1C_REG 0x88 /* Video n Coefficient Set C1C Register */ 53f00add96SNiklas Söderlund #define VNC2A_REG 0x90 /* Video n Coefficient Set C2A Register */ 54f00add96SNiklas Söderlund #define VNC2B_REG 0x94 /* Video n Coefficient Set C2B Register */ 55f00add96SNiklas Söderlund #define VNC2C_REG 0x98 /* Video n Coefficient Set C2C Register */ 56f00add96SNiklas Söderlund #define VNC3A_REG 0xA0 /* Video n Coefficient Set C3A Register */ 57f00add96SNiklas Söderlund #define VNC3B_REG 0xA4 /* Video n Coefficient Set C3B Register */ 58f00add96SNiklas Söderlund #define VNC3C_REG 0xA8 /* Video n Coefficient Set C3C Register */ 59f00add96SNiklas Söderlund #define VNC4A_REG 0xB0 /* Video n Coefficient Set C4A Register */ 60f00add96SNiklas Söderlund #define VNC4B_REG 0xB4 /* Video n Coefficient Set C4B Register */ 61f00add96SNiklas Söderlund #define VNC4C_REG 0xB8 /* Video n Coefficient Set C4C Register */ 62f00add96SNiklas Söderlund #define VNC5A_REG 0xC0 /* Video n Coefficient Set C5A Register */ 63f00add96SNiklas Söderlund #define VNC5B_REG 0xC4 /* Video n Coefficient Set C5B Register */ 64f00add96SNiklas Söderlund #define VNC5C_REG 0xC8 /* Video n Coefficient Set C5C Register */ 65f00add96SNiklas Söderlund #define VNC6A_REG 0xD0 /* Video n Coefficient Set C6A Register */ 66f00add96SNiklas Söderlund #define VNC6B_REG 0xD4 /* Video n Coefficient Set C6B Register */ 67f00add96SNiklas Söderlund #define VNC6C_REG 0xD8 /* Video n Coefficient Set C6C Register */ 68f00add96SNiklas Söderlund #define VNC7A_REG 0xE0 /* Video n Coefficient Set C7A Register */ 69f00add96SNiklas Söderlund #define VNC7B_REG 0xE4 /* Video n Coefficient Set C7B Register */ 70f00add96SNiklas Söderlund #define VNC7C_REG 0xE8 /* Video n Coefficient Set C7C Register */ 71f00add96SNiklas Söderlund #define VNC8A_REG 0xF0 /* Video n Coefficient Set C8A Register */ 72f00add96SNiklas Söderlund #define VNC8B_REG 0xF4 /* Video n Coefficient Set C8B Register */ 73f00add96SNiklas Söderlund #define VNC8C_REG 0xF8 /* Video n Coefficient Set C8C Register */ 74f00add96SNiklas Söderlund 754394eb24SNiklas Söderlund /* Register offsets specific for Gen3 */ 764394eb24SNiklas Söderlund #define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */ 77928a6ea4SNiklas Söderlund #define VNUDS_CTRL_REG 0x80 /* Video n scaling control register */ 78928a6ea4SNiklas Söderlund #define VNUDS_SCALE_REG 0x84 /* Video n scaling factor register */ 79928a6ea4SNiklas Söderlund #define VNUDS_PASS_BWIDTH_REG 0x90 /* Video n passband register */ 80928a6ea4SNiklas Söderlund #define VNUDS_CLIP_SIZE_REG 0xa4 /* Video n UDS output size clipping reg */ 81f00add96SNiklas Söderlund 82f00add96SNiklas Söderlund /* Register bit fields for R-Car VIN */ 83f00add96SNiklas Söderlund /* Video n Main Control Register bits */ 8478b3f9d7SNiklas Söderlund #define VNMC_INF_MASK (7 << 16) 854394eb24SNiklas Söderlund #define VNMC_DPINE (1 << 27) /* Gen3 specific */ 864394eb24SNiklas Söderlund #define VNMC_SCLE (1 << 26) /* Gen3 specific */ 87f00add96SNiklas Söderlund #define VNMC_FOC (1 << 21) 88f00add96SNiklas Söderlund #define VNMC_YCAL (1 << 19) 89f00add96SNiklas Söderlund #define VNMC_INF_YUV8_BT656 (0 << 16) 90f00add96SNiklas Söderlund #define VNMC_INF_YUV8_BT601 (1 << 16) 91f00add96SNiklas Söderlund #define VNMC_INF_YUV10_BT656 (2 << 16) 92f00add96SNiklas Söderlund #define VNMC_INF_YUV10_BT601 (3 << 16) 93e87c1a81SLad Prabhakar #define VNMC_INF_RAW8 (4 << 16) 94f00add96SNiklas Söderlund #define VNMC_INF_YUV16 (5 << 16) 95f00add96SNiklas Söderlund #define VNMC_INF_RGB888 (6 << 16) 9678b3f9d7SNiklas Söderlund #define VNMC_INF_RGB666 (7 << 16) 9717b5496cSTomi Valkeinen #define VNMC_EXINF_RAW8 (1 << 12) /* Gen4 specific */ 98f00add96SNiklas Söderlund #define VNMC_VUP (1 << 10) 99f00add96SNiklas Söderlund #define VNMC_IM_ODD (0 << 3) 100f00add96SNiklas Söderlund #define VNMC_IM_ODD_EVEN (1 << 3) 101f00add96SNiklas Söderlund #define VNMC_IM_EVEN (2 << 3) 102f00add96SNiklas Söderlund #define VNMC_IM_FULL (3 << 3) 103f00add96SNiklas Söderlund #define VNMC_BPS (1 << 1) 104f00add96SNiklas Söderlund #define VNMC_ME (1 << 0) 105f00add96SNiklas Söderlund 106f00add96SNiklas Söderlund /* Video n Module Status Register bits */ 107f00add96SNiklas Söderlund #define VNMS_FBS_MASK (3 << 3) 108f00add96SNiklas Söderlund #define VNMS_FBS_SHIFT 3 109b6f556cbSNiklas Söderlund #define VNMS_FS (1 << 2) 110f00add96SNiklas Söderlund #define VNMS_AV (1 << 1) 111f00add96SNiklas Söderlund #define VNMS_CA (1 << 0) 112f00add96SNiklas Söderlund 113f00add96SNiklas Söderlund /* Video n Frame Capture Register bits */ 114f00add96SNiklas Söderlund #define VNFC_C_FRAME (1 << 1) 115f00add96SNiklas Söderlund #define VNFC_S_FRAME (1 << 0) 116f00add96SNiklas Söderlund 117f00add96SNiklas Söderlund /* Video n Interrupt Enable Register bits */ 118f00add96SNiklas Söderlund #define VNIE_FIE (1 << 4) 119f00add96SNiklas Söderlund #define VNIE_EFE (1 << 1) 120f00add96SNiklas Söderlund 12130334d3dSNiklas Söderlund /* Video n Interrupt Status Register bits */ 12230334d3dSNiklas Söderlund #define VNINTS_FIS (1 << 4) 12330334d3dSNiklas Söderlund 124f00add96SNiklas Söderlund /* Video n Data Mode Register bits */ 1251d99e68cSNiklas Söderlund #define VNDMR_A8BIT(n) (((n) & 0xff) << 24) 1261d99e68cSNiklas Söderlund #define VNDMR_A8BIT_MASK (0xff << 24) 1271b7e7240SNiklas Söderlund #define VNDMR_RMODE_RAW10 (2 << 19) 128c93beb52SVladimir Barinov #define VNDMR_YMODE_Y8 (1 << 12) 1291b7e7240SNiklas Söderlund #define VNDMR_YC_THR (1 << 11) 130f00add96SNiklas Söderlund #define VNDMR_EXRGB (1 << 8) 131f00add96SNiklas Söderlund #define VNDMR_BPSM (1 << 4) 1321d99e68cSNiklas Söderlund #define VNDMR_ABIT (1 << 2) 133f00add96SNiklas Söderlund #define VNDMR_DTMD_YCSEP (1 << 1) 13419ab1f64SNiklas Söderlund #define VNDMR_DTMD_ARGB (1 << 0) 1359b744a3eSNiklas Söderlund #define VNDMR_DTMD_YCSEP_420 (3 << 0) 136f00add96SNiklas Söderlund 137f00add96SNiklas Söderlund /* Video n Data Mode Register 2 bits */ 138f00add96SNiklas Söderlund #define VNDMR2_VPS (1 << 30) 139f00add96SNiklas Söderlund #define VNDMR2_HPS (1 << 29) 14053cf3100SJacopo Mondi #define VNDMR2_CES (1 << 28) 141e8834943SLad Prabhakar #define VNDMR2_YDS (1 << 22) 142f00add96SNiklas Söderlund #define VNDMR2_FTEV (1 << 17) 143f00add96SNiklas Söderlund #define VNDMR2_VLV(n) ((n & 0xf) << 12) 144f00add96SNiklas Söderlund 1454394eb24SNiklas Söderlund /* Video n CSI2 Interface Mode Register (Gen3) */ 1464394eb24SNiklas Söderlund #define VNCSI_IFMD_DES1 (1 << 26) 1474394eb24SNiklas Söderlund #define VNCSI_IFMD_DES0 (1 << 25) 1484394eb24SNiklas Söderlund #define VNCSI_IFMD_CSI_CHSEL(n) (((n) & 0xf) << 0) 1494394eb24SNiklas Söderlund 150928a6ea4SNiklas Söderlund /* Video n scaling control register (Gen3) */ 151928a6ea4SNiklas Söderlund #define VNUDS_CTRL_AMD (1 << 30) 152928a6ea4SNiklas Söderlund 1539e921447SNiklas Söderlund struct rvin_buffer { 1549e921447SNiklas Söderlund struct vb2_v4l2_buffer vb; 1559e921447SNiklas Söderlund struct list_head list; 1569e921447SNiklas Söderlund }; 1579e921447SNiklas Söderlund 1589e921447SNiklas Söderlund #define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \ 1599e921447SNiklas Söderlund struct rvin_buffer, \ 1609e921447SNiklas Söderlund vb)->list) 1619e921447SNiklas Söderlund 162f00add96SNiklas Söderlund static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset) 163f00add96SNiklas Söderlund { 164f00add96SNiklas Söderlund iowrite32(value, vin->base + offset); 165f00add96SNiklas Söderlund } 166f00add96SNiklas Söderlund 167f00add96SNiklas Söderlund static u32 rvin_read(struct rvin_dev *vin, u32 offset) 168f00add96SNiklas Söderlund { 169f00add96SNiklas Söderlund return ioread32(vin->base + offset); 170f00add96SNiklas Söderlund } 171f00add96SNiklas Söderlund 172f00add96SNiklas Söderlund /* ----------------------------------------------------------------------------- 1733ad69c61SNiklas Söderlund * Crop and Scaling 174f00add96SNiklas Söderlund */ 175f00add96SNiklas Söderlund 1763ad69c61SNiklas Söderlund static bool rvin_scaler_needed(const struct rvin_dev *vin) 1773ad69c61SNiklas Söderlund { 1783ad69c61SNiklas Söderlund return !(vin->crop.width == vin->format.width && 1793ad69c61SNiklas Söderlund vin->compose.width == vin->format.width && 1803ad69c61SNiklas Söderlund vin->crop.height == vin->format.height && 1813ad69c61SNiklas Söderlund vin->compose.height == vin->format.height); 1823ad69c61SNiklas Söderlund } 1833ad69c61SNiklas Söderlund 184f00add96SNiklas Söderlund struct vin_coeff { 185f00add96SNiklas Söderlund unsigned short xs_value; 186f00add96SNiklas Söderlund u32 coeff_set[24]; 187f00add96SNiklas Söderlund }; 188f00add96SNiklas Söderlund 189f00add96SNiklas Söderlund static const struct vin_coeff vin_coeff_set[] = { 190f00add96SNiklas Söderlund { 0x0000, { 191f00add96SNiklas Söderlund 0x00000000, 0x00000000, 0x00000000, 192f00add96SNiklas Söderlund 0x00000000, 0x00000000, 0x00000000, 193f00add96SNiklas Söderlund 0x00000000, 0x00000000, 0x00000000, 194f00add96SNiklas Söderlund 0x00000000, 0x00000000, 0x00000000, 195f00add96SNiklas Söderlund 0x00000000, 0x00000000, 0x00000000, 196f00add96SNiklas Söderlund 0x00000000, 0x00000000, 0x00000000, 197f00add96SNiklas Söderlund 0x00000000, 0x00000000, 0x00000000, 198f00add96SNiklas Söderlund 0x00000000, 0x00000000, 0x00000000 }, 199f00add96SNiklas Söderlund }, 200f00add96SNiklas Söderlund { 0x1000, { 201f00add96SNiklas Söderlund 0x000fa400, 0x000fa400, 0x09625902, 202f00add96SNiklas Söderlund 0x000003f8, 0x00000403, 0x3de0d9f0, 203f00add96SNiklas Söderlund 0x001fffed, 0x00000804, 0x3cc1f9c3, 204f00add96SNiklas Söderlund 0x001003de, 0x00000c01, 0x3cb34d7f, 205f00add96SNiklas Söderlund 0x002003d2, 0x00000c00, 0x3d24a92d, 206f00add96SNiklas Söderlund 0x00200bca, 0x00000bff, 0x3df600d2, 207f00add96SNiklas Söderlund 0x002013cc, 0x000007ff, 0x3ed70c7e, 208f00add96SNiklas Söderlund 0x00100fde, 0x00000000, 0x3f87c036 }, 209f00add96SNiklas Söderlund }, 210f00add96SNiklas Söderlund { 0x1200, { 211f00add96SNiklas Söderlund 0x002ffff1, 0x002ffff1, 0x02a0a9c8, 212f00add96SNiklas Söderlund 0x002003e7, 0x001ffffa, 0x000185bc, 213f00add96SNiklas Söderlund 0x002007dc, 0x000003ff, 0x3e52859c, 214f00add96SNiklas Söderlund 0x00200bd4, 0x00000002, 0x3d53996b, 215f00add96SNiklas Söderlund 0x00100fd0, 0x00000403, 0x3d04ad2d, 216f00add96SNiklas Söderlund 0x00000bd5, 0x00000403, 0x3d35ace7, 217f00add96SNiklas Söderlund 0x3ff003e4, 0x00000801, 0x3dc674a1, 218f00add96SNiklas Söderlund 0x3fffe800, 0x00000800, 0x3e76f461 }, 219f00add96SNiklas Söderlund }, 220f00add96SNiklas Söderlund { 0x1400, { 221f00add96SNiklas Söderlund 0x00100be3, 0x00100be3, 0x04d1359a, 222f00add96SNiklas Söderlund 0x00000fdb, 0x002003ed, 0x0211fd93, 223f00add96SNiklas Söderlund 0x00000fd6, 0x002003f4, 0x0002d97b, 224f00add96SNiklas Söderlund 0x000007d6, 0x002ffffb, 0x3e93b956, 225f00add96SNiklas Söderlund 0x3ff003da, 0x001003ff, 0x3db49926, 226f00add96SNiklas Söderlund 0x3fffefe9, 0x00100001, 0x3d655cee, 227f00add96SNiklas Söderlund 0x3fffd400, 0x00000003, 0x3d65f4b6, 228f00add96SNiklas Söderlund 0x000fb421, 0x00000402, 0x3dc6547e }, 229f00add96SNiklas Söderlund }, 230f00add96SNiklas Söderlund { 0x1600, { 231f00add96SNiklas Söderlund 0x00000bdd, 0x00000bdd, 0x06519578, 232f00add96SNiklas Söderlund 0x3ff007da, 0x00000be3, 0x03c24973, 233f00add96SNiklas Söderlund 0x3ff003d9, 0x00000be9, 0x01b30d5f, 234f00add96SNiklas Söderlund 0x3ffff7df, 0x001003f1, 0x0003c542, 235f00add96SNiklas Söderlund 0x000fdfec, 0x001003f7, 0x3ec4711d, 236f00add96SNiklas Söderlund 0x000fc400, 0x002ffffd, 0x3df504f1, 237f00add96SNiklas Söderlund 0x001fa81a, 0x002ffc00, 0x3d957cc2, 238f00add96SNiklas Söderlund 0x002f8c3c, 0x00100000, 0x3db5c891 }, 239f00add96SNiklas Söderlund }, 240f00add96SNiklas Söderlund { 0x1800, { 241f00add96SNiklas Söderlund 0x3ff003dc, 0x3ff003dc, 0x0791e558, 242f00add96SNiklas Söderlund 0x000ff7dd, 0x3ff007de, 0x05328554, 243f00add96SNiklas Söderlund 0x000fe7e3, 0x3ff00be2, 0x03232546, 244f00add96SNiklas Söderlund 0x000fd7ee, 0x000007e9, 0x0143bd30, 245f00add96SNiklas Söderlund 0x001fb800, 0x000007ee, 0x00044511, 246f00add96SNiklas Söderlund 0x002fa015, 0x000007f4, 0x3ef4bcee, 247f00add96SNiklas Söderlund 0x002f8832, 0x001003f9, 0x3e4514c7, 248f00add96SNiklas Söderlund 0x001f7853, 0x001003fd, 0x3de54c9f }, 249f00add96SNiklas Söderlund }, 250f00add96SNiklas Söderlund { 0x1a00, { 251f00add96SNiklas Söderlund 0x000fefe0, 0x000fefe0, 0x08721d3c, 252f00add96SNiklas Söderlund 0x001fdbe7, 0x000ffbde, 0x0652a139, 253f00add96SNiklas Söderlund 0x001fcbf0, 0x000003df, 0x0463292e, 254f00add96SNiklas Söderlund 0x002fb3ff, 0x3ff007e3, 0x0293a91d, 255f00add96SNiklas Söderlund 0x002f9c12, 0x3ff00be7, 0x01241905, 256f00add96SNiklas Söderlund 0x001f8c29, 0x000007ed, 0x3fe470eb, 257f00add96SNiklas Söderlund 0x000f7c46, 0x000007f2, 0x3f04b8ca, 258f00add96SNiklas Söderlund 0x3fef7865, 0x000007f6, 0x3e74e4a8 }, 259f00add96SNiklas Söderlund }, 260f00add96SNiklas Söderlund { 0x1c00, { 261f00add96SNiklas Söderlund 0x001fd3e9, 0x001fd3e9, 0x08f23d26, 262f00add96SNiklas Söderlund 0x002fbff3, 0x001fe3e4, 0x0712ad23, 263f00add96SNiklas Söderlund 0x002fa800, 0x000ff3e0, 0x05631d1b, 264f00add96SNiklas Söderlund 0x001f9810, 0x000ffbe1, 0x03b3890d, 265f00add96SNiklas Söderlund 0x000f8c23, 0x000003e3, 0x0233e8fa, 266f00add96SNiklas Söderlund 0x3fef843b, 0x000003e7, 0x00f430e4, 267f00add96SNiklas Söderlund 0x3fbf8456, 0x3ff00bea, 0x00046cc8, 268f00add96SNiklas Söderlund 0x3f8f8c72, 0x3ff00bef, 0x3f3490ac }, 269f00add96SNiklas Söderlund }, 270f00add96SNiklas Söderlund { 0x1e00, { 271f00add96SNiklas Söderlund 0x001fbbf4, 0x001fbbf4, 0x09425112, 272f00add96SNiklas Söderlund 0x001fa800, 0x002fc7ed, 0x0792b110, 273f00add96SNiklas Söderlund 0x000f980e, 0x001fdbe6, 0x0613110a, 274f00add96SNiklas Söderlund 0x3fff8c20, 0x001fe7e3, 0x04a368fd, 275f00add96SNiklas Söderlund 0x3fcf8c33, 0x000ff7e2, 0x0343b8ed, 276f00add96SNiklas Söderlund 0x3f9f8c4a, 0x000fffe3, 0x0203f8da, 277f00add96SNiklas Söderlund 0x3f5f9c61, 0x000003e6, 0x00e428c5, 278f00add96SNiklas Söderlund 0x3f1fb07b, 0x000003eb, 0x3fe440af }, 279f00add96SNiklas Söderlund }, 280f00add96SNiklas Söderlund { 0x2000, { 281f00add96SNiklas Söderlund 0x000fa400, 0x000fa400, 0x09625902, 282f00add96SNiklas Söderlund 0x3fff980c, 0x001fb7f5, 0x0812b0ff, 283f00add96SNiklas Söderlund 0x3fdf901c, 0x001fc7ed, 0x06b2fcfa, 284f00add96SNiklas Söderlund 0x3faf902d, 0x001fd3e8, 0x055348f1, 285f00add96SNiklas Söderlund 0x3f7f983f, 0x001fe3e5, 0x04038ce3, 286f00add96SNiklas Söderlund 0x3f3fa454, 0x001fefe3, 0x02e3c8d1, 287f00add96SNiklas Söderlund 0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0, 288f00add96SNiklas Söderlund 0x3ecfd880, 0x000fffe6, 0x00c404ac }, 289f00add96SNiklas Söderlund }, 290f00add96SNiklas Söderlund { 0x2200, { 291f00add96SNiklas Söderlund 0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4, 292f00add96SNiklas Söderlund 0x3fbf9818, 0x3fffa400, 0x0842a8f1, 293f00add96SNiklas Söderlund 0x3f8f9827, 0x000fb3f7, 0x0702f0ec, 294f00add96SNiklas Söderlund 0x3f5fa037, 0x000fc3ef, 0x05d330e4, 295f00add96SNiklas Söderlund 0x3f2fac49, 0x001fcfea, 0x04a364d9, 296f00add96SNiklas Söderlund 0x3effc05c, 0x001fdbe7, 0x038394ca, 297f00add96SNiklas Söderlund 0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb, 298f00add96SNiklas Söderlund 0x3ea00083, 0x001fefe6, 0x0183c0a9 }, 299f00add96SNiklas Söderlund }, 300f00add96SNiklas Söderlund { 0x2400, { 301f00add96SNiklas Söderlund 0x3f9fa014, 0x3f9fa014, 0x098260e6, 302f00add96SNiklas Söderlund 0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5, 303f00add96SNiklas Söderlund 0x3f4fa431, 0x3fefa400, 0x0742d8e1, 304f00add96SNiklas Söderlund 0x3f1fb440, 0x3fffb3f8, 0x062310d9, 305f00add96SNiklas Söderlund 0x3eefc850, 0x000fbbf2, 0x050340d0, 306f00add96SNiklas Söderlund 0x3ecfe062, 0x000fcbec, 0x041364c2, 307f00add96SNiklas Söderlund 0x3ea00073, 0x001fd3ea, 0x03037cb5, 308f00add96SNiklas Söderlund 0x3e902086, 0x001fdfe8, 0x022388a5 }, 309f00add96SNiklas Söderlund }, 310f00add96SNiklas Söderlund { 0x2600, { 311f00add96SNiklas Söderlund 0x3f5fa81e, 0x3f5fa81e, 0x096258da, 312f00add96SNiklas Söderlund 0x3f3fac2b, 0x3f8fa412, 0x088290d8, 313f00add96SNiklas Söderlund 0x3f0fbc38, 0x3fafa408, 0x0772c8d5, 314f00add96SNiklas Söderlund 0x3eefcc47, 0x3fcfa800, 0x0672f4ce, 315f00add96SNiklas Söderlund 0x3ecfe456, 0x3fefaffa, 0x05531cc6, 316f00add96SNiklas Söderlund 0x3eb00066, 0x3fffbbf3, 0x047334bb, 317f00add96SNiklas Söderlund 0x3ea01c77, 0x000fc7ee, 0x039348ae, 318f00add96SNiklas Söderlund 0x3ea04486, 0x000fd3eb, 0x02b350a1 }, 319f00add96SNiklas Söderlund }, 320f00add96SNiklas Söderlund { 0x2800, { 321f00add96SNiklas Söderlund 0x3f2fb426, 0x3f2fb426, 0x094250ce, 322f00add96SNiklas Söderlund 0x3f0fc032, 0x3f4fac1b, 0x086284cd, 323f00add96SNiklas Söderlund 0x3eefd040, 0x3f7fa811, 0x0782acc9, 324f00add96SNiklas Söderlund 0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4, 325f00add96SNiklas Söderlund 0x3eb0005b, 0x3fbfac00, 0x05b2f4bc, 326f00add96SNiklas Söderlund 0x3eb0186a, 0x3fdfb3fa, 0x04c308b4, 327f00add96SNiklas Söderlund 0x3eb04077, 0x3fefbbf4, 0x03f31ca8, 328f00add96SNiklas Söderlund 0x3ec06884, 0x000fbff2, 0x03031c9e }, 329f00add96SNiklas Söderlund }, 330f00add96SNiklas Söderlund { 0x2a00, { 331f00add96SNiklas Söderlund 0x3f0fc42d, 0x3f0fc42d, 0x090240c4, 332f00add96SNiklas Söderlund 0x3eefd439, 0x3f2fb822, 0x08526cc2, 333f00add96SNiklas Söderlund 0x3edfe845, 0x3f4fb018, 0x078294bf, 334f00add96SNiklas Söderlund 0x3ec00051, 0x3f6fac0f, 0x06b2b4bb, 335f00add96SNiklas Söderlund 0x3ec0185f, 0x3f8fac07, 0x05e2ccb4, 336f00add96SNiklas Söderlund 0x3ec0386b, 0x3fafac00, 0x0502e8ac, 337f00add96SNiklas Söderlund 0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3, 338f00add96SNiklas Söderlund 0x3ef08482, 0x3fdfbbf6, 0x0372f898 }, 339f00add96SNiklas Söderlund }, 340f00add96SNiklas Söderlund { 0x2c00, { 341f00add96SNiklas Söderlund 0x3eefdc31, 0x3eefdc31, 0x08e238b8, 342f00add96SNiklas Söderlund 0x3edfec3d, 0x3f0fc828, 0x082258b9, 343f00add96SNiklas Söderlund 0x3ed00049, 0x3f1fc01e, 0x077278b6, 344f00add96SNiklas Söderlund 0x3ed01455, 0x3f3fb815, 0x06c294b2, 345f00add96SNiklas Söderlund 0x3ed03460, 0x3f5fb40d, 0x0602acac, 346f00add96SNiklas Söderlund 0x3ef0506c, 0x3f7fb006, 0x0542c0a4, 347f00add96SNiklas Söderlund 0x3f107476, 0x3f9fb400, 0x0472c89d, 348f00add96SNiklas Söderlund 0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 }, 349f00add96SNiklas Söderlund }, 350f00add96SNiklas Söderlund { 0x2e00, { 351f00add96SNiklas Söderlund 0x3eefec37, 0x3eefec37, 0x088220b0, 352f00add96SNiklas Söderlund 0x3ee00041, 0x3effdc2d, 0x07f244ae, 353f00add96SNiklas Söderlund 0x3ee0144c, 0x3f0fd023, 0x07625cad, 354f00add96SNiklas Söderlund 0x3ef02c57, 0x3f1fc81a, 0x06c274a9, 355f00add96SNiklas Söderlund 0x3f004861, 0x3f3fbc13, 0x060288a6, 356f00add96SNiklas Söderlund 0x3f20686b, 0x3f5fb80c, 0x05529c9e, 357f00add96SNiklas Söderlund 0x3f408c74, 0x3f6fb805, 0x04b2ac96, 358f00add96SNiklas Söderlund 0x3f80ac7e, 0x3f8fb800, 0x0402ac8e }, 359f00add96SNiklas Söderlund }, 360f00add96SNiklas Söderlund { 0x3000, { 361f00add96SNiklas Söderlund 0x3ef0003a, 0x3ef0003a, 0x084210a6, 362f00add96SNiklas Söderlund 0x3ef01045, 0x3effec32, 0x07b228a7, 363f00add96SNiklas Söderlund 0x3f00284e, 0x3f0fdc29, 0x073244a4, 364f00add96SNiklas Söderlund 0x3f104058, 0x3f0fd420, 0x06a258a2, 365f00add96SNiklas Söderlund 0x3f305c62, 0x3f2fc818, 0x0612689d, 366f00add96SNiklas Söderlund 0x3f508069, 0x3f3fc011, 0x05728496, 367f00add96SNiklas Söderlund 0x3f80a072, 0x3f4fc00a, 0x04d28c90, 368f00add96SNiklas Söderlund 0x3fc0c07b, 0x3f6fbc04, 0x04429088 }, 369f00add96SNiklas Söderlund }, 370f00add96SNiklas Söderlund { 0x3200, { 371f00add96SNiklas Söderlund 0x3f00103e, 0x3f00103e, 0x07f1fc9e, 372f00add96SNiklas Söderlund 0x3f102447, 0x3f000035, 0x0782149d, 373f00add96SNiklas Söderlund 0x3f203c4f, 0x3f0ff02c, 0x07122c9c, 374f00add96SNiklas Söderlund 0x3f405458, 0x3f0fe424, 0x06924099, 375f00add96SNiklas Söderlund 0x3f607061, 0x3f1fd41d, 0x06024c97, 376f00add96SNiklas Söderlund 0x3f909068, 0x3f2fcc16, 0x05726490, 377f00add96SNiklas Söderlund 0x3fc0b070, 0x3f3fc80f, 0x04f26c8a, 378f00add96SNiklas Söderlund 0x0000d077, 0x3f4fc409, 0x04627484 }, 379f00add96SNiklas Söderlund }, 380f00add96SNiklas Söderlund { 0x3400, { 381f00add96SNiklas Söderlund 0x3f202040, 0x3f202040, 0x07a1e898, 382f00add96SNiklas Söderlund 0x3f303449, 0x3f100c38, 0x0741fc98, 383f00add96SNiklas Söderlund 0x3f504c50, 0x3f10002f, 0x06e21495, 384f00add96SNiklas Söderlund 0x3f706459, 0x3f1ff028, 0x06722492, 385f00add96SNiklas Söderlund 0x3fa08060, 0x3f1fe421, 0x05f2348f, 386f00add96SNiklas Söderlund 0x3fd09c67, 0x3f1fdc19, 0x05824c89, 387f00add96SNiklas Söderlund 0x0000bc6e, 0x3f2fd014, 0x04f25086, 388f00add96SNiklas Söderlund 0x0040dc74, 0x3f3fcc0d, 0x04825c7f }, 389f00add96SNiklas Söderlund }, 390f00add96SNiklas Söderlund { 0x3600, { 391f00add96SNiklas Söderlund 0x3f403042, 0x3f403042, 0x0761d890, 392f00add96SNiklas Söderlund 0x3f504848, 0x3f301c3b, 0x0701f090, 393f00add96SNiklas Söderlund 0x3f805c50, 0x3f200c33, 0x06a2008f, 394f00add96SNiklas Söderlund 0x3fa07458, 0x3f10002b, 0x06520c8d, 395f00add96SNiklas Söderlund 0x3fd0905e, 0x3f1ff424, 0x05e22089, 396f00add96SNiklas Söderlund 0x0000ac65, 0x3f1fe81d, 0x05823483, 397f00add96SNiklas Söderlund 0x0030cc6a, 0x3f2fdc18, 0x04f23c81, 398f00add96SNiklas Söderlund 0x0080e871, 0x3f2fd412, 0x0482407c }, 399f00add96SNiklas Söderlund }, 400f00add96SNiklas Söderlund { 0x3800, { 401f00add96SNiklas Söderlund 0x3f604043, 0x3f604043, 0x0721c88a, 402f00add96SNiklas Söderlund 0x3f80544a, 0x3f502c3c, 0x06d1d88a, 403f00add96SNiklas Söderlund 0x3fb06851, 0x3f301c35, 0x0681e889, 404f00add96SNiklas Söderlund 0x3fd08456, 0x3f30082f, 0x0611fc88, 405f00add96SNiklas Söderlund 0x00009c5d, 0x3f200027, 0x05d20884, 406f00add96SNiklas Söderlund 0x0030b863, 0x3f2ff421, 0x05621880, 407f00add96SNiklas Söderlund 0x0070d468, 0x3f2fe81b, 0x0502247c, 408f00add96SNiklas Söderlund 0x00c0ec6f, 0x3f2fe015, 0x04a22877 }, 409f00add96SNiklas Söderlund }, 410f00add96SNiklas Söderlund { 0x3a00, { 411f00add96SNiklas Söderlund 0x3f904c44, 0x3f904c44, 0x06e1b884, 412f00add96SNiklas Söderlund 0x3fb0604a, 0x3f70383e, 0x0691c885, 413f00add96SNiklas Söderlund 0x3fe07451, 0x3f502c36, 0x0661d483, 414f00add96SNiklas Söderlund 0x00009055, 0x3f401831, 0x0601ec81, 415f00add96SNiklas Söderlund 0x0030a85b, 0x3f300c2a, 0x05b1f480, 416f00add96SNiklas Söderlund 0x0070c061, 0x3f300024, 0x0562047a, 417f00add96SNiklas Söderlund 0x00b0d867, 0x3f3ff41e, 0x05020c77, 418f00add96SNiklas Söderlund 0x00f0f46b, 0x3f2fec19, 0x04a21474 }, 419f00add96SNiklas Söderlund }, 420f00add96SNiklas Söderlund { 0x3c00, { 421f00add96SNiklas Söderlund 0x3fb05c43, 0x3fb05c43, 0x06c1b07e, 422f00add96SNiklas Söderlund 0x3fe06c4b, 0x3f902c3f, 0x0681c081, 423f00add96SNiklas Söderlund 0x0000844f, 0x3f703838, 0x0631cc7d, 424f00add96SNiklas Söderlund 0x00309855, 0x3f602433, 0x05d1d47e, 425f00add96SNiklas Söderlund 0x0060b459, 0x3f50142e, 0x0581e47b, 426f00add96SNiklas Söderlund 0x00a0c85f, 0x3f400828, 0x0531f078, 427f00add96SNiklas Söderlund 0x00e0e064, 0x3f300021, 0x0501fc73, 428f00add96SNiklas Söderlund 0x00b0fc6a, 0x3f3ff41d, 0x04a20873 }, 429f00add96SNiklas Söderlund }, 430f00add96SNiklas Söderlund { 0x3e00, { 431f00add96SNiklas Söderlund 0x3fe06444, 0x3fe06444, 0x0681a07a, 432f00add96SNiklas Söderlund 0x00007849, 0x3fc0503f, 0x0641b07a, 433f00add96SNiklas Söderlund 0x0020904d, 0x3fa0403a, 0x05f1c07a, 434f00add96SNiklas Söderlund 0x0060a453, 0x3f803034, 0x05c1c878, 435f00add96SNiklas Söderlund 0x0090b858, 0x3f70202f, 0x0571d477, 436f00add96SNiklas Söderlund 0x00d0d05d, 0x3f501829, 0x0531e073, 437f00add96SNiklas Söderlund 0x0110e462, 0x3f500825, 0x04e1e471, 438f00add96SNiklas Söderlund 0x01510065, 0x3f40001f, 0x04a1f06d }, 439f00add96SNiklas Söderlund }, 440f00add96SNiklas Söderlund { 0x4000, { 441f00add96SNiklas Söderlund 0x00007044, 0x00007044, 0x06519476, 442f00add96SNiklas Söderlund 0x00208448, 0x3fe05c3f, 0x0621a476, 443f00add96SNiklas Söderlund 0x0050984d, 0x3fc04c3a, 0x05e1b075, 444f00add96SNiklas Söderlund 0x0080ac52, 0x3fa03c35, 0x05a1b875, 445f00add96SNiklas Söderlund 0x00c0c056, 0x3f803030, 0x0561c473, 446f00add96SNiklas Söderlund 0x0100d45b, 0x3f70202b, 0x0521d46f, 447f00add96SNiklas Söderlund 0x0140e860, 0x3f601427, 0x04d1d46e, 448f00add96SNiklas Söderlund 0x01810064, 0x3f500822, 0x0491dc6b }, 449f00add96SNiklas Söderlund }, 450f00add96SNiklas Söderlund { 0x5000, { 451f00add96SNiklas Söderlund 0x0110a442, 0x0110a442, 0x0551545e, 452f00add96SNiklas Söderlund 0x0140b045, 0x00e0983f, 0x0531585f, 453f00add96SNiklas Söderlund 0x0160c047, 0x00c08c3c, 0x0511645e, 454f00add96SNiklas Söderlund 0x0190cc4a, 0x00908039, 0x04f1685f, 455f00add96SNiklas Söderlund 0x01c0dc4c, 0x00707436, 0x04d1705e, 456f00add96SNiklas Söderlund 0x0200e850, 0x00506833, 0x04b1785b, 457f00add96SNiklas Söderlund 0x0230f453, 0x00305c30, 0x0491805a, 458f00add96SNiklas Söderlund 0x02710056, 0x0010542d, 0x04718059 }, 459f00add96SNiklas Söderlund }, 460f00add96SNiklas Söderlund { 0x6000, { 461f00add96SNiklas Söderlund 0x01c0bc40, 0x01c0bc40, 0x04c13052, 462f00add96SNiklas Söderlund 0x01e0c841, 0x01a0b43d, 0x04c13851, 463f00add96SNiklas Söderlund 0x0210cc44, 0x0180a83c, 0x04a13453, 464f00add96SNiklas Söderlund 0x0230d845, 0x0160a03a, 0x04913c52, 465f00add96SNiklas Söderlund 0x0260e047, 0x01409838, 0x04714052, 466f00add96SNiklas Söderlund 0x0280ec49, 0x01208c37, 0x04514c50, 467f00add96SNiklas Söderlund 0x02b0f44b, 0x01008435, 0x04414c50, 468f00add96SNiklas Söderlund 0x02d1004c, 0x00e07c33, 0x0431544f }, 469f00add96SNiklas Söderlund }, 470f00add96SNiklas Söderlund { 0x7000, { 471f00add96SNiklas Söderlund 0x0230c83e, 0x0230c83e, 0x04711c4c, 472f00add96SNiklas Söderlund 0x0250d03f, 0x0210c43c, 0x0471204b, 473f00add96SNiklas Söderlund 0x0270d840, 0x0200b83c, 0x0451244b, 474f00add96SNiklas Söderlund 0x0290dc42, 0x01e0b43a, 0x0441244c, 475f00add96SNiklas Söderlund 0x02b0e443, 0x01c0b038, 0x0441284b, 476f00add96SNiklas Söderlund 0x02d0ec44, 0x01b0a438, 0x0421304a, 477f00add96SNiklas Söderlund 0x02f0f445, 0x0190a036, 0x04213449, 478f00add96SNiklas Söderlund 0x0310f847, 0x01709c34, 0x04213848 }, 479f00add96SNiklas Söderlund }, 480f00add96SNiklas Söderlund { 0x8000, { 481f00add96SNiklas Söderlund 0x0280d03d, 0x0280d03d, 0x04310c48, 482f00add96SNiklas Söderlund 0x02a0d43e, 0x0270c83c, 0x04311047, 483f00add96SNiklas Söderlund 0x02b0dc3e, 0x0250c83a, 0x04311447, 484f00add96SNiklas Söderlund 0x02d0e040, 0x0240c03a, 0x04211446, 485f00add96SNiklas Söderlund 0x02e0e840, 0x0220bc39, 0x04111847, 486f00add96SNiklas Söderlund 0x0300e842, 0x0210b438, 0x04012445, 487f00add96SNiklas Söderlund 0x0310f043, 0x0200b037, 0x04012045, 488f00add96SNiklas Söderlund 0x0330f444, 0x01e0ac36, 0x03f12445 }, 489f00add96SNiklas Söderlund }, 490f00add96SNiklas Söderlund { 0xefff, { 491f00add96SNiklas Söderlund 0x0340dc3a, 0x0340dc3a, 0x03b0ec40, 492f00add96SNiklas Söderlund 0x0340e03a, 0x0330e039, 0x03c0f03e, 493f00add96SNiklas Söderlund 0x0350e03b, 0x0330dc39, 0x03c0ec3e, 494f00add96SNiklas Söderlund 0x0350e43a, 0x0320dc38, 0x03c0f43e, 495f00add96SNiklas Söderlund 0x0360e43b, 0x0320d839, 0x03b0f03e, 496f00add96SNiklas Söderlund 0x0360e83b, 0x0310d838, 0x03c0fc3b, 497f00add96SNiklas Söderlund 0x0370e83b, 0x0310d439, 0x03a0f83d, 498f00add96SNiklas Söderlund 0x0370e83c, 0x0300d438, 0x03b0fc3c }, 499f00add96SNiklas Söderlund } 500f00add96SNiklas Söderlund }; 501f00add96SNiklas Söderlund 502f00add96SNiklas Söderlund static void rvin_set_coeff(struct rvin_dev *vin, unsigned short xs) 503f00add96SNiklas Söderlund { 504f00add96SNiklas Söderlund int i; 505f00add96SNiklas Söderlund const struct vin_coeff *p_prev_set = NULL; 506f00add96SNiklas Söderlund const struct vin_coeff *p_set = NULL; 507f00add96SNiklas Söderlund 508f00add96SNiklas Söderlund /* Look for suitable coefficient values */ 509f00add96SNiklas Söderlund for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) { 510f00add96SNiklas Söderlund p_prev_set = p_set; 511f00add96SNiklas Söderlund p_set = &vin_coeff_set[i]; 512f00add96SNiklas Söderlund 513f00add96SNiklas Söderlund if (xs < p_set->xs_value) 514f00add96SNiklas Söderlund break; 515f00add96SNiklas Söderlund } 516f00add96SNiklas Söderlund 517f00add96SNiklas Söderlund /* Use previous value if its XS value is closer */ 518bf78f23aSMauro Carvalho Chehab if (p_prev_set && 519f00add96SNiklas Söderlund xs - p_prev_set->xs_value < p_set->xs_value - xs) 520f00add96SNiklas Söderlund p_set = p_prev_set; 521f00add96SNiklas Söderlund 522f00add96SNiklas Söderlund /* Set coefficient registers */ 523f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[0], VNC1A_REG); 524f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[1], VNC1B_REG); 525f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[2], VNC1C_REG); 526f00add96SNiklas Söderlund 527f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[3], VNC2A_REG); 528f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[4], VNC2B_REG); 529f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[5], VNC2C_REG); 530f00add96SNiklas Söderlund 531f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[6], VNC3A_REG); 532f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[7], VNC3B_REG); 533f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[8], VNC3C_REG); 534f00add96SNiklas Söderlund 535f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[9], VNC4A_REG); 536f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[10], VNC4B_REG); 537f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[11], VNC4C_REG); 538f00add96SNiklas Söderlund 539f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[12], VNC5A_REG); 540f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[13], VNC5B_REG); 541f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[14], VNC5C_REG); 542f00add96SNiklas Söderlund 543f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[15], VNC6A_REG); 544f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[16], VNC6B_REG); 545f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[17], VNC6C_REG); 546f00add96SNiklas Söderlund 547f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[18], VNC7A_REG); 548f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[19], VNC7B_REG); 549f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[20], VNC7C_REG); 550f00add96SNiklas Söderlund 551f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[21], VNC8A_REG); 552f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[22], VNC8B_REG); 553f00add96SNiklas Söderlund rvin_write(vin, p_set->coeff_set[23], VNC8C_REG); 554f00add96SNiklas Söderlund } 555f00add96SNiklas Söderlund 5563ad69c61SNiklas Söderlund void rvin_scaler_gen2(struct rvin_dev *vin) 557f00add96SNiklas Söderlund { 55808369321SNiklas Söderlund unsigned int crop_height; 559f00add96SNiklas Söderlund u32 xs, ys; 560f00add96SNiklas Söderlund 561f00add96SNiklas Söderlund /* Set scaling coefficient */ 56208369321SNiklas Söderlund crop_height = vin->crop.height; 5637e0cfdadSNiklas Söderlund if (V4L2_FIELD_HAS_BOTH(vin->format.field)) 56408369321SNiklas Söderlund crop_height *= 2; 56508369321SNiklas Söderlund 566f00add96SNiklas Söderlund ys = 0; 56708369321SNiklas Söderlund if (crop_height != vin->compose.height) 56808369321SNiklas Söderlund ys = (4096 * crop_height) / vin->compose.height; 569f00add96SNiklas Söderlund rvin_write(vin, ys, VNYS_REG); 570f00add96SNiklas Söderlund 571f00add96SNiklas Söderlund xs = 0; 572f00add96SNiklas Söderlund if (vin->crop.width != vin->compose.width) 573f00add96SNiklas Söderlund xs = (4096 * vin->crop.width) / vin->compose.width; 574f00add96SNiklas Söderlund 575f00add96SNiklas Söderlund /* Horizontal upscaling is up to double size */ 576f00add96SNiklas Söderlund if (xs > 0 && xs < 2048) 577f00add96SNiklas Söderlund xs = 2048; 578f00add96SNiklas Söderlund 579f00add96SNiklas Söderlund rvin_write(vin, xs, VNXS_REG); 580f00add96SNiklas Söderlund 581f00add96SNiklas Söderlund /* Horizontal upscaling is done out by scaling down from double size */ 582f00add96SNiklas Söderlund if (xs < 4096) 583f00add96SNiklas Söderlund xs *= 2; 584f00add96SNiklas Söderlund 585f00add96SNiklas Söderlund rvin_set_coeff(vin, xs); 586f00add96SNiklas Söderlund 587f00add96SNiklas Söderlund /* Set Start/End Pixel/Line Post-Clip */ 588f00add96SNiklas Söderlund rvin_write(vin, 0, VNSPPOC_REG); 589f00add96SNiklas Söderlund rvin_write(vin, 0, VNSLPOC_REG); 590f00add96SNiklas Söderlund rvin_write(vin, vin->format.width - 1, VNEPPOC_REG); 591d23e12dcSNiklas Söderlund 5927e0cfdadSNiklas Söderlund if (V4L2_FIELD_HAS_BOTH(vin->format.field)) 593f00add96SNiklas Söderlund rvin_write(vin, vin->format.height / 2 - 1, VNELPOC_REG); 594d23e12dcSNiklas Söderlund else 595f00add96SNiklas Söderlund rvin_write(vin, vin->format.height - 1, VNELPOC_REG); 596f00add96SNiklas Söderlund 597f00add96SNiklas Söderlund vin_dbg(vin, 598f00add96SNiklas Söderlund "Pre-Clip: %ux%u@%u:%u YS: %d XS: %d Post-Clip: %ux%u@%u:%u\n", 599f00add96SNiklas Söderlund vin->crop.width, vin->crop.height, vin->crop.left, 600f00add96SNiklas Söderlund vin->crop.top, ys, xs, vin->format.width, vin->format.height, 601f00add96SNiklas Söderlund 0, 0); 602f00add96SNiklas Söderlund } 603f00add96SNiklas Söderlund 604928a6ea4SNiklas Söderlund static unsigned int rvin_uds_scale_ratio(unsigned int in, unsigned int out) 605928a6ea4SNiklas Söderlund { 606928a6ea4SNiklas Söderlund unsigned int ratio; 607928a6ea4SNiklas Söderlund 608928a6ea4SNiklas Söderlund ratio = in * 4096 / out; 609928a6ea4SNiklas Söderlund return ratio >= 0x10000 ? 0xffff : ratio; 610928a6ea4SNiklas Söderlund } 611928a6ea4SNiklas Söderlund 612928a6ea4SNiklas Söderlund static unsigned int rvin_uds_filter_width(unsigned int ratio) 613928a6ea4SNiklas Söderlund { 614928a6ea4SNiklas Söderlund if (ratio >= 0x1000) 615928a6ea4SNiklas Söderlund return 64 * (ratio & 0xf000) / ratio; 616928a6ea4SNiklas Söderlund 617928a6ea4SNiklas Söderlund return 64; 618928a6ea4SNiklas Söderlund } 619928a6ea4SNiklas Söderlund 620928a6ea4SNiklas Söderlund void rvin_scaler_gen3(struct rvin_dev *vin) 621928a6ea4SNiklas Söderlund { 622928a6ea4SNiklas Söderlund unsigned int ratio_h, ratio_v; 623928a6ea4SNiklas Söderlund unsigned int bwidth_h, bwidth_v; 624928a6ea4SNiklas Söderlund u32 vnmc, clip_size; 625928a6ea4SNiklas Söderlund 626928a6ea4SNiklas Söderlund vnmc = rvin_read(vin, VNMC_REG); 627928a6ea4SNiklas Söderlund 628928a6ea4SNiklas Söderlund /* Disable scaler if not needed. */ 629928a6ea4SNiklas Söderlund if (!rvin_scaler_needed(vin)) { 630928a6ea4SNiklas Söderlund rvin_write(vin, vnmc & ~VNMC_SCLE, VNMC_REG); 631928a6ea4SNiklas Söderlund return; 632928a6ea4SNiklas Söderlund } 633928a6ea4SNiklas Söderlund 634928a6ea4SNiklas Söderlund ratio_h = rvin_uds_scale_ratio(vin->crop.width, vin->compose.width); 635928a6ea4SNiklas Söderlund bwidth_h = rvin_uds_filter_width(ratio_h); 636928a6ea4SNiklas Söderlund 637928a6ea4SNiklas Söderlund ratio_v = rvin_uds_scale_ratio(vin->crop.height, vin->compose.height); 638928a6ea4SNiklas Söderlund bwidth_v = rvin_uds_filter_width(ratio_v); 639928a6ea4SNiklas Söderlund 640928a6ea4SNiklas Söderlund clip_size = vin->compose.width << 16; 641928a6ea4SNiklas Söderlund 642928a6ea4SNiklas Söderlund switch (vin->format.field) { 643928a6ea4SNiklas Söderlund case V4L2_FIELD_INTERLACED_TB: 644928a6ea4SNiklas Söderlund case V4L2_FIELD_INTERLACED_BT: 645928a6ea4SNiklas Söderlund case V4L2_FIELD_INTERLACED: 646928a6ea4SNiklas Söderlund clip_size |= vin->compose.height / 2; 647928a6ea4SNiklas Söderlund break; 648928a6ea4SNiklas Söderlund default: 649928a6ea4SNiklas Söderlund clip_size |= vin->compose.height; 650928a6ea4SNiklas Söderlund break; 651928a6ea4SNiklas Söderlund } 652928a6ea4SNiklas Söderlund 653928a6ea4SNiklas Söderlund rvin_write(vin, vnmc | VNMC_SCLE, VNMC_REG); 654928a6ea4SNiklas Söderlund rvin_write(vin, VNUDS_CTRL_AMD, VNUDS_CTRL_REG); 655928a6ea4SNiklas Söderlund rvin_write(vin, (ratio_h << 16) | ratio_v, VNUDS_SCALE_REG); 656928a6ea4SNiklas Söderlund rvin_write(vin, (bwidth_h << 16) | bwidth_v, VNUDS_PASS_BWIDTH_REG); 657928a6ea4SNiklas Söderlund rvin_write(vin, clip_size, VNUDS_CLIP_SIZE_REG); 658928a6ea4SNiklas Söderlund 659928a6ea4SNiklas Söderlund vin_dbg(vin, "Pre-Clip: %ux%u@%u:%u Post-Clip: %ux%u@%u:%u\n", 660928a6ea4SNiklas Söderlund vin->crop.width, vin->crop.height, vin->crop.left, 661928a6ea4SNiklas Söderlund vin->crop.top, vin->compose.width, vin->compose.height, 662928a6ea4SNiklas Söderlund vin->compose.left, vin->compose.top); 663928a6ea4SNiklas Söderlund } 664928a6ea4SNiklas Söderlund 6654394eb24SNiklas Söderlund void rvin_crop_scale_comp(struct rvin_dev *vin) 6664394eb24SNiklas Söderlund { 66784246ae3SNiklas Söderlund const struct rvin_video_format *fmt; 66884246ae3SNiklas Söderlund u32 stride; 66984246ae3SNiklas Söderlund 6704394eb24SNiklas Söderlund /* Set Start/End Pixel/Line Pre-Clip */ 6714394eb24SNiklas Söderlund rvin_write(vin, vin->crop.left, VNSPPRC_REG); 6724394eb24SNiklas Söderlund rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG); 6734394eb24SNiklas Söderlund rvin_write(vin, vin->crop.top, VNSLPRC_REG); 67408369321SNiklas Söderlund rvin_write(vin, vin->crop.top + vin->crop.height - 1, VNELPRC_REG); 67508369321SNiklas Söderlund 6763ad69c61SNiklas Söderlund if (vin->scaler) 6773ad69c61SNiklas Söderlund vin->scaler(vin); 6784394eb24SNiklas Söderlund 67984246ae3SNiklas Söderlund fmt = rvin_format_from_pixel(vin, vin->format.pixelformat); 68084246ae3SNiklas Söderlund stride = vin->format.bytesperline / fmt->bpp; 68184246ae3SNiklas Söderlund rvin_write(vin, stride, VNIS_REG); 6824394eb24SNiklas Söderlund } 6834394eb24SNiklas Söderlund 684f00add96SNiklas Söderlund /* ----------------------------------------------------------------------------- 6850f4b3378SNiklas Söderlund * Hardware setup 6860f4b3378SNiklas Söderlund */ 6870f4b3378SNiklas Söderlund 6880f4b3378SNiklas Söderlund static int rvin_setup(struct rvin_dev *vin) 6890f4b3378SNiklas Söderlund { 690d73c3357SNiklas Söderlund u32 vnmc, dmr, dmr2, interrupts; 6910f4b3378SNiklas Söderlund bool progressive = false, output_is_yuv = false, input_is_yuv = false; 6920f4b3378SNiklas Söderlund 6930f4b3378SNiklas Söderlund switch (vin->format.field) { 6940f4b3378SNiklas Söderlund case V4L2_FIELD_TOP: 6950f4b3378SNiklas Söderlund vnmc = VNMC_IM_ODD; 6960f4b3378SNiklas Söderlund break; 6970f4b3378SNiklas Söderlund case V4L2_FIELD_BOTTOM: 6980f4b3378SNiklas Söderlund vnmc = VNMC_IM_EVEN; 6990f4b3378SNiklas Söderlund break; 7000f4b3378SNiklas Söderlund case V4L2_FIELD_INTERLACED: 7010f4b3378SNiklas Söderlund /* Default to TB */ 7020f4b3378SNiklas Söderlund vnmc = VNMC_IM_FULL; 7030f4b3378SNiklas Söderlund /* Use BT if video standard can be read and is 60 Hz format */ 7045e7c6236SNiklas Söderlund if (!vin->info->use_mc && vin->std & V4L2_STD_525_60) 7050f4b3378SNiklas Söderlund vnmc = VNMC_IM_FULL | VNMC_FOC; 7060f4b3378SNiklas Söderlund break; 7070f4b3378SNiklas Söderlund case V4L2_FIELD_INTERLACED_TB: 7080f4b3378SNiklas Söderlund vnmc = VNMC_IM_FULL; 7090f4b3378SNiklas Söderlund break; 7100f4b3378SNiklas Söderlund case V4L2_FIELD_INTERLACED_BT: 7110f4b3378SNiklas Söderlund vnmc = VNMC_IM_FULL | VNMC_FOC; 7120f4b3378SNiklas Söderlund break; 7130f4b3378SNiklas Söderlund case V4L2_FIELD_NONE: 71408369321SNiklas Söderlund case V4L2_FIELD_ALTERNATE: 71508369321SNiklas Söderlund vnmc = VNMC_IM_ODD_EVEN; 716e10707d5SNiklas Söderlund progressive = true; 71708369321SNiklas Söderlund break; 7180f4b3378SNiklas Söderlund default: 7190f4b3378SNiklas Söderlund vnmc = VNMC_IM_ODD; 7200f4b3378SNiklas Söderlund break; 7210f4b3378SNiklas Söderlund } 7220f4b3378SNiklas Söderlund 7230f4b3378SNiklas Söderlund /* 7240f4b3378SNiklas Söderlund * Input interface 7250f4b3378SNiklas Söderlund */ 726c65c99b4SNiklas Söderlund switch (vin->mbus_code) { 7270f4b3378SNiklas Söderlund case MEDIA_BUS_FMT_YUYV8_1X16: 7289caf253eSJacopo Mondi if (vin->is_csi) 7299caf253eSJacopo Mondi /* YCbCr422 8-bit */ 7309caf253eSJacopo Mondi vnmc |= VNMC_INF_YUV8_BT601; 7319caf253eSJacopo Mondi else 7320f4b3378SNiklas Söderlund /* BT.601/BT.1358 16bit YCbCr422 */ 7330f4b3378SNiklas Söderlund vnmc |= VNMC_INF_YUV16; 7340f4b3378SNiklas Söderlund input_is_yuv = true; 7350f4b3378SNiklas Söderlund break; 73601d72e9dSNiklas Söderlund case MEDIA_BUS_FMT_UYVY8_1X16: 7379caf253eSJacopo Mondi if (vin->is_csi) 7389caf253eSJacopo Mondi /* YCbCr422 8-bit */ 7399caf253eSJacopo Mondi vnmc |= VNMC_INF_YUV8_BT601; 7409caf253eSJacopo Mondi else 7419caf253eSJacopo Mondi /* BT.601/BT.1358 16bit YCbCr422 */ 7429caf253eSJacopo Mondi vnmc |= VNMC_INF_YUV16; 7439caf253eSJacopo Mondi vnmc |= VNMC_YCAL; 74401d72e9dSNiklas Söderlund input_is_yuv = true; 74501d72e9dSNiklas Söderlund break; 7460f4b3378SNiklas Söderlund case MEDIA_BUS_FMT_UYVY8_2X8: 7470f4b3378SNiklas Söderlund /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */ 748158e2a53SJacopo Mondi if (!vin->is_csi && 749d7592b2eSNiklas Söderlund vin->parallel.mbus_type == V4L2_MBUS_BT656) 750158e2a53SJacopo Mondi vnmc |= VNMC_INF_YUV8_BT656; 751158e2a53SJacopo Mondi else 752158e2a53SJacopo Mondi vnmc |= VNMC_INF_YUV8_BT601; 753158e2a53SJacopo Mondi 7540f4b3378SNiklas Söderlund input_is_yuv = true; 7550f4b3378SNiklas Söderlund break; 7560f4b3378SNiklas Söderlund case MEDIA_BUS_FMT_RGB888_1X24: 7570f4b3378SNiklas Söderlund vnmc |= VNMC_INF_RGB888; 7580f4b3378SNiklas Söderlund break; 7590f4b3378SNiklas Söderlund case MEDIA_BUS_FMT_UYVY10_2X10: 7600f4b3378SNiklas Söderlund /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */ 761158e2a53SJacopo Mondi if (!vin->is_csi && 762d7592b2eSNiklas Söderlund vin->parallel.mbus_type == V4L2_MBUS_BT656) 763158e2a53SJacopo Mondi vnmc |= VNMC_INF_YUV10_BT656; 764158e2a53SJacopo Mondi else 765158e2a53SJacopo Mondi vnmc |= VNMC_INF_YUV10_BT601; 766158e2a53SJacopo Mondi 7670f4b3378SNiklas Söderlund input_is_yuv = true; 7680f4b3378SNiklas Söderlund break; 7698c3e0f67SNiklas Söderlund case MEDIA_BUS_FMT_SBGGR8_1X8: 7708c3e0f67SNiklas Söderlund case MEDIA_BUS_FMT_SGBRG8_1X8: 7718c3e0f67SNiklas Söderlund case MEDIA_BUS_FMT_SGRBG8_1X8: 772e87c1a81SLad Prabhakar case MEDIA_BUS_FMT_SRGGB8_1X8: 773c93beb52SVladimir Barinov case MEDIA_BUS_FMT_Y8_1X8: 774e87c1a81SLad Prabhakar vnmc |= VNMC_INF_RAW8; 77517b5496cSTomi Valkeinen if (vin->info->model == RCAR_GEN4) 77617b5496cSTomi Valkeinen vnmc |= VNMC_EXINF_RAW8; 777e87c1a81SLad Prabhakar break; 7781b7e7240SNiklas Söderlund case MEDIA_BUS_FMT_SBGGR10_1X10: 7791b7e7240SNiklas Söderlund case MEDIA_BUS_FMT_SGBRG10_1X10: 7801b7e7240SNiklas Söderlund case MEDIA_BUS_FMT_SGRBG10_1X10: 7811b7e7240SNiklas Söderlund case MEDIA_BUS_FMT_SRGGB10_1X10: 7821b7e7240SNiklas Söderlund vnmc |= VNMC_INF_RGB666; 7831b7e7240SNiklas Söderlund break; 7840f4b3378SNiklas Söderlund default: 7850f4b3378SNiklas Söderlund break; 7860f4b3378SNiklas Söderlund } 7870f4b3378SNiklas Söderlund 7888b72c18dSMauro Carvalho Chehab /* Enable VSYNC Field Toggle mode after one VSYNC input */ 789d6a08667STomi Valkeinen if (vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) 790d73c3357SNiklas Söderlund dmr2 = VNDMR2_FTEV; 791d73c3357SNiklas Söderlund else 7920f4b3378SNiklas Söderlund dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1); 7930f4b3378SNiklas Söderlund 794158e2a53SJacopo Mondi if (!vin->is_csi) { 7950f4b3378SNiklas Söderlund /* Hsync Signal Polarity Select */ 796d7592b2eSNiklas Söderlund if (!(vin->parallel.bus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) 7970f4b3378SNiklas Söderlund dmr2 |= VNDMR2_HPS; 7980f4b3378SNiklas Söderlund 7990f4b3378SNiklas Söderlund /* Vsync Signal Polarity Select */ 800d7592b2eSNiklas Söderlund if (!(vin->parallel.bus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) 8010f4b3378SNiklas Söderlund dmr2 |= VNDMR2_VPS; 80253cf3100SJacopo Mondi 80353cf3100SJacopo Mondi /* Data Enable Polarity Select */ 804d7592b2eSNiklas Söderlund if (vin->parallel.bus.flags & V4L2_MBUS_DATA_ENABLE_LOW) 80553cf3100SJacopo Mondi dmr2 |= VNDMR2_CES; 806e8834943SLad Prabhakar 807e8834943SLad Prabhakar switch (vin->mbus_code) { 808e8834943SLad Prabhakar case MEDIA_BUS_FMT_UYVY8_2X8: 809d7592b2eSNiklas Söderlund if (vin->parallel.bus.bus_width == 8 && 810d7592b2eSNiklas Söderlund vin->parallel.bus.data_shift == 8) 811e8834943SLad Prabhakar dmr2 |= VNDMR2_YDS; 812e8834943SLad Prabhakar break; 813e8834943SLad Prabhakar default: 814e8834943SLad Prabhakar break; 815e8834943SLad Prabhakar } 816158e2a53SJacopo Mondi } 8170f4b3378SNiklas Söderlund 8180f4b3378SNiklas Söderlund /* 8190f4b3378SNiklas Söderlund * Output format 8200f4b3378SNiklas Söderlund */ 8210f4b3378SNiklas Söderlund switch (vin->format.pixelformat) { 8229b744a3eSNiklas Söderlund case V4L2_PIX_FMT_NV12: 8230f4b3378SNiklas Söderlund case V4L2_PIX_FMT_NV16: 8240f4b3378SNiklas Söderlund rvin_write(vin, 8255c9de1faSNiklas Söderlund ALIGN(vin->format.bytesperline * vin->format.height, 8265c9de1faSNiklas Söderlund 0x80), VNUVAOF_REG); 8279b744a3eSNiklas Söderlund dmr = vin->format.pixelformat == V4L2_PIX_FMT_NV12 ? 8289b744a3eSNiklas Söderlund VNDMR_DTMD_YCSEP_420 : VNDMR_DTMD_YCSEP; 8290f4b3378SNiklas Söderlund output_is_yuv = true; 8300f4b3378SNiklas Söderlund break; 8310f4b3378SNiklas Söderlund case V4L2_PIX_FMT_YUYV: 8320f4b3378SNiklas Söderlund dmr = VNDMR_BPSM; 8330f4b3378SNiklas Söderlund output_is_yuv = true; 8340f4b3378SNiklas Söderlund break; 8350f4b3378SNiklas Söderlund case V4L2_PIX_FMT_UYVY: 8360f4b3378SNiklas Söderlund dmr = 0; 8370f4b3378SNiklas Söderlund output_is_yuv = true; 8380f4b3378SNiklas Söderlund break; 8390f4b3378SNiklas Söderlund case V4L2_PIX_FMT_XRGB555: 84019ab1f64SNiklas Söderlund dmr = VNDMR_DTMD_ARGB; 8410f4b3378SNiklas Söderlund break; 8420f4b3378SNiklas Söderlund case V4L2_PIX_FMT_RGB565: 8430f4b3378SNiklas Söderlund dmr = 0; 8440f4b3378SNiklas Söderlund break; 8450f4b3378SNiklas Söderlund case V4L2_PIX_FMT_XBGR32: 8460f4b3378SNiklas Söderlund /* Note: not supported on M1 */ 8470f4b3378SNiklas Söderlund dmr = VNDMR_EXRGB; 8480f4b3378SNiklas Söderlund break; 8491d99e68cSNiklas Söderlund case V4L2_PIX_FMT_ARGB555: 8501d99e68cSNiklas Söderlund dmr = (vin->alpha ? VNDMR_ABIT : 0) | VNDMR_DTMD_ARGB; 8511d99e68cSNiklas Söderlund break; 8521d99e68cSNiklas Söderlund case V4L2_PIX_FMT_ABGR32: 8531d99e68cSNiklas Söderlund dmr = VNDMR_A8BIT(vin->alpha) | VNDMR_EXRGB | VNDMR_DTMD_ARGB; 8541d99e68cSNiklas Söderlund break; 8558c3e0f67SNiklas Söderlund case V4L2_PIX_FMT_SBGGR8: 8568c3e0f67SNiklas Söderlund case V4L2_PIX_FMT_SGBRG8: 8578c3e0f67SNiklas Söderlund case V4L2_PIX_FMT_SGRBG8: 858e87c1a81SLad Prabhakar case V4L2_PIX_FMT_SRGGB8: 859e87c1a81SLad Prabhakar dmr = 0; 860e87c1a81SLad Prabhakar break; 861c93beb52SVladimir Barinov case V4L2_PIX_FMT_GREY: 862c93beb52SVladimir Barinov if (input_is_yuv) { 863c93beb52SVladimir Barinov dmr = VNDMR_DTMD_YCSEP | VNDMR_YMODE_Y8; 864c93beb52SVladimir Barinov output_is_yuv = true; 865c93beb52SVladimir Barinov } else { 866c93beb52SVladimir Barinov dmr = 0; 867c93beb52SVladimir Barinov } 868c93beb52SVladimir Barinov break; 8691b7e7240SNiklas Söderlund case V4L2_PIX_FMT_SBGGR10: 8701b7e7240SNiklas Söderlund case V4L2_PIX_FMT_SGBRG10: 8711b7e7240SNiklas Söderlund case V4L2_PIX_FMT_SGRBG10: 8721b7e7240SNiklas Söderlund case V4L2_PIX_FMT_SRGGB10: 873*94bf847aSTomi Valkeinen dmr = VNDMR_RMODE_RAW10; 8741b7e7240SNiklas Söderlund break; 8750f4b3378SNiklas Söderlund default: 8760f4b3378SNiklas Söderlund vin_err(vin, "Invalid pixelformat (0x%x)\n", 8770f4b3378SNiklas Söderlund vin->format.pixelformat); 8780f4b3378SNiklas Söderlund return -EINVAL; 8790f4b3378SNiklas Söderlund } 8800f4b3378SNiklas Söderlund 8810f4b3378SNiklas Söderlund /* Always update on field change */ 8820f4b3378SNiklas Söderlund vnmc |= VNMC_VUP; 8830f4b3378SNiklas Söderlund 884406bb586SNiklas Söderlund if (!vin->info->use_isp) { 8850f4b3378SNiklas Söderlund /* If input and output use the same colorspace, use bypass mode */ 8860f4b3378SNiklas Söderlund if (input_is_yuv == output_is_yuv) 8870f4b3378SNiklas Söderlund vnmc |= VNMC_BPS; 8880f4b3378SNiklas Söderlund 889d6a08667STomi Valkeinen if (vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) { 890d24c029eSJacopo Mondi /* Select between CSI-2 and parallel input */ 891158e2a53SJacopo Mondi if (vin->is_csi) 8924394eb24SNiklas Söderlund vnmc &= ~VNMC_DPINE; 8934394eb24SNiklas Söderlund else 8944394eb24SNiklas Söderlund vnmc |= VNMC_DPINE; 8954394eb24SNiklas Söderlund } 896406bb586SNiklas Söderlund } 8974394eb24SNiklas Söderlund 8980f4b3378SNiklas Söderlund /* Progressive or interlaced mode */ 8990f4b3378SNiklas Söderlund interrupts = progressive ? VNIE_FIE : VNIE_EFE; 9000f4b3378SNiklas Söderlund 9010f4b3378SNiklas Söderlund /* Ack interrupts */ 9020f4b3378SNiklas Söderlund rvin_write(vin, interrupts, VNINTS_REG); 9030f4b3378SNiklas Söderlund /* Enable interrupts */ 9040f4b3378SNiklas Söderlund rvin_write(vin, interrupts, VNIE_REG); 9050f4b3378SNiklas Söderlund /* Start capturing */ 9060f4b3378SNiklas Söderlund rvin_write(vin, dmr, VNDMR_REG); 9070f4b3378SNiklas Söderlund rvin_write(vin, dmr2, VNDMR2_REG); 9080f4b3378SNiklas Söderlund 9090f4b3378SNiklas Söderlund /* Enable module */ 9100f4b3378SNiklas Söderlund rvin_write(vin, vnmc | VNMC_ME, VNMC_REG); 9110f4b3378SNiklas Söderlund 9120f4b3378SNiklas Söderlund return 0; 9130f4b3378SNiklas Söderlund } 9140f4b3378SNiklas Söderlund 9150f4b3378SNiklas Söderlund static void rvin_disable_interrupts(struct rvin_dev *vin) 9160f4b3378SNiklas Söderlund { 9170f4b3378SNiklas Söderlund rvin_write(vin, 0, VNIE_REG); 9180f4b3378SNiklas Söderlund } 9190f4b3378SNiklas Söderlund 9200f4b3378SNiklas Söderlund static u32 rvin_get_interrupt_status(struct rvin_dev *vin) 9210f4b3378SNiklas Söderlund { 9220f4b3378SNiklas Söderlund return rvin_read(vin, VNINTS_REG); 9230f4b3378SNiklas Söderlund } 9240f4b3378SNiklas Söderlund 9250f4b3378SNiklas Söderlund static void rvin_ack_interrupt(struct rvin_dev *vin) 9260f4b3378SNiklas Söderlund { 9270f4b3378SNiklas Söderlund rvin_write(vin, rvin_read(vin, VNINTS_REG), VNINTS_REG); 9280f4b3378SNiklas Söderlund } 9290f4b3378SNiklas Söderlund 9300f4b3378SNiklas Söderlund static bool rvin_capture_active(struct rvin_dev *vin) 9310f4b3378SNiklas Söderlund { 9320f4b3378SNiklas Söderlund return rvin_read(vin, VNMS_REG) & VNMS_CA; 9330f4b3378SNiklas Söderlund } 9340f4b3378SNiklas Söderlund 93508369321SNiklas Söderlund static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms) 93608369321SNiklas Söderlund { 93708369321SNiklas Söderlund if (vin->format.field == V4L2_FIELD_ALTERNATE) { 93808369321SNiklas Söderlund /* If FS is set it is an Even field. */ 93908369321SNiklas Söderlund if (vnms & VNMS_FS) 94008369321SNiklas Söderlund return V4L2_FIELD_BOTTOM; 94108369321SNiklas Söderlund return V4L2_FIELD_TOP; 94208369321SNiklas Söderlund } 94308369321SNiklas Söderlund 94408369321SNiklas Söderlund return vin->format.field; 94508369321SNiklas Söderlund } 94608369321SNiklas Söderlund 9470f4b3378SNiklas Söderlund static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr) 9480f4b3378SNiklas Söderlund { 9490f4b3378SNiklas Söderlund const struct rvin_video_format *fmt; 9500f4b3378SNiklas Söderlund int offsetx, offsety; 9510f4b3378SNiklas Söderlund dma_addr_t offset; 9520f4b3378SNiklas Söderlund 95321a816e7SNiklas Söderlund fmt = rvin_format_from_pixel(vin, vin->format.pixelformat); 9540f4b3378SNiklas Söderlund 9550f4b3378SNiklas Söderlund /* 9560f4b3378SNiklas Söderlund * There is no HW support for composition do the beast we can 9570f4b3378SNiklas Söderlund * by modifying the buffer offset 9580f4b3378SNiklas Söderlund */ 9590f4b3378SNiklas Söderlund offsetx = vin->compose.left * fmt->bpp; 9600f4b3378SNiklas Söderlund offsety = vin->compose.top * vin->format.bytesperline; 9610f4b3378SNiklas Söderlund offset = addr + offsetx + offsety; 9620f4b3378SNiklas Söderlund 9630f4b3378SNiklas Söderlund /* 9640f4b3378SNiklas Söderlund * The address needs to be 128 bytes aligned. Driver should never accept 9650f4b3378SNiklas Söderlund * settings that do not satisfy this in the first place... 9660f4b3378SNiklas Söderlund */ 9670f4b3378SNiklas Söderlund if (WARN_ON((offsetx | offsety | offset) & HW_BUFFER_MASK)) 9680f4b3378SNiklas Söderlund return; 9690f4b3378SNiklas Söderlund 9700f4b3378SNiklas Söderlund rvin_write(vin, offset, VNMB_REG(slot)); 9710f4b3378SNiklas Söderlund } 9720f4b3378SNiklas Söderlund 9730f4b3378SNiklas Söderlund /* 9740f4b3378SNiklas Söderlund * Moves a buffer from the queue to the HW slot. If no buffer is 9750f4b3378SNiklas Söderlund * available use the scratch buffer. The scratch buffer is never 9760f4b3378SNiklas Söderlund * returned to userspace, its only function is to enable the capture 9770f4b3378SNiklas Söderlund * loop to keep running. 9780f4b3378SNiklas Söderlund */ 9790f4b3378SNiklas Söderlund static void rvin_fill_hw_slot(struct rvin_dev *vin, int slot) 9800f4b3378SNiklas Söderlund { 9810f4b3378SNiklas Söderlund struct rvin_buffer *buf; 9820f4b3378SNiklas Söderlund struct vb2_v4l2_buffer *vbuf; 9830f4b3378SNiklas Söderlund dma_addr_t phys_addr; 9840f4b3378SNiklas Söderlund 9850f4b3378SNiklas Söderlund /* A already populated slot shall never be overwritten. */ 986e72b7359SNiklas Söderlund if (WARN_ON(vin->buf_hw[slot].buffer)) 9870f4b3378SNiklas Söderlund return; 9880f4b3378SNiklas Söderlund 989c1eefe88SNiklas Söderlund if (list_empty(&vin->buf_list)) { 990e72b7359SNiklas Söderlund vin->buf_hw[slot].buffer = NULL; 9910f4b3378SNiklas Söderlund phys_addr = vin->scratch_phys; 9920f4b3378SNiklas Söderlund } else { 9930f4b3378SNiklas Söderlund /* Keep track of buffer we give to HW */ 9940f4b3378SNiklas Söderlund buf = list_entry(vin->buf_list.next, struct rvin_buffer, list); 9950f4b3378SNiklas Söderlund vbuf = &buf->vb; 9960f4b3378SNiklas Söderlund list_del_init(to_buf_list(vbuf)); 997e72b7359SNiklas Söderlund vin->buf_hw[slot].buffer = vbuf; 9980f4b3378SNiklas Söderlund 9990f4b3378SNiklas Söderlund /* Setup DMA */ 10000f4b3378SNiklas Söderlund phys_addr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); 10010f4b3378SNiklas Söderlund } 10020f4b3378SNiklas Söderlund 1003f2f0cd89SNiklas Söderlund vin_dbg(vin, "Filling HW slot: %d buffer: %p\n", 1004f2f0cd89SNiklas Söderlund slot, vin->buf_hw[slot].buffer); 10057e0cfdadSNiklas Söderlund 10067e0cfdadSNiklas Söderlund vin->buf_hw[slot].phys = phys_addr; 10070f4b3378SNiklas Söderlund rvin_set_slot_addr(vin, slot, phys_addr); 10080f4b3378SNiklas Söderlund } 10090f4b3378SNiklas Söderlund 10100f4b3378SNiklas Söderlund static int rvin_capture_start(struct rvin_dev *vin) 10110f4b3378SNiklas Söderlund { 1012f2f0cd89SNiklas Söderlund int ret; 10130f4b3378SNiklas Söderlund 1014f2f0cd89SNiklas Söderlund for (unsigned int slot = 0; slot < HW_BUFFER_NUM; slot++) { 10157e0cfdadSNiklas Söderlund vin->buf_hw[slot].buffer = NULL; 10160f4b3378SNiklas Söderlund rvin_fill_hw_slot(vin, slot); 1017f2f0cd89SNiklas Söderlund } 10180f4b3378SNiklas Söderlund 10190f4b3378SNiklas Söderlund ret = rvin_setup(vin); 10200f4b3378SNiklas Söderlund if (ret) 10210f4b3378SNiklas Söderlund return ret; 10220f4b3378SNiklas Söderlund 10233ad69c61SNiklas Söderlund rvin_crop_scale_comp(vin); 10243ad69c61SNiklas Söderlund 10250f4b3378SNiklas Söderlund vin_dbg(vin, "Starting to capture\n"); 10260f4b3378SNiklas Söderlund 10270f4b3378SNiklas Söderlund /* Continuous Frame Capture Mode */ 10280f4b3378SNiklas Söderlund rvin_write(vin, VNFC_C_FRAME, VNFC_REG); 10290f4b3378SNiklas Söderlund 10300f4b3378SNiklas Söderlund return 0; 10310f4b3378SNiklas Söderlund } 10320f4b3378SNiklas Söderlund 10330f4b3378SNiklas Söderlund static void rvin_capture_stop(struct rvin_dev *vin) 10340f4b3378SNiklas Söderlund { 10350f4b3378SNiklas Söderlund /* Set continuous & single transfer off */ 10360f4b3378SNiklas Söderlund rvin_write(vin, 0, VNFC_REG); 10370f4b3378SNiklas Söderlund 10380f4b3378SNiklas Söderlund /* Disable module */ 10390f4b3378SNiklas Söderlund rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG); 10400f4b3378SNiklas Söderlund } 10410f4b3378SNiklas Söderlund 10420f4b3378SNiklas Söderlund /* ----------------------------------------------------------------------------- 1043f00add96SNiklas Söderlund * DMA Functions 1044f00add96SNiklas Söderlund */ 1045f00add96SNiklas Söderlund 1046f00add96SNiklas Söderlund #define RVIN_TIMEOUT_MS 100 1047f00add96SNiklas Söderlund #define RVIN_RETRIES 10 1048f00add96SNiklas Söderlund 1049f00add96SNiklas Söderlund static irqreturn_t rvin_irq(int irq, void *data) 1050f00add96SNiklas Söderlund { 1051f00add96SNiklas Söderlund struct rvin_dev *vin = data; 1052b6f556cbSNiklas Söderlund u32 int_status, vnms; 1053f00add96SNiklas Söderlund int slot; 1054dc9aec79SNiklas Söderlund unsigned int handled = 0; 1055f00add96SNiklas Söderlund unsigned long flags; 1056f00add96SNiklas Söderlund 1057f00add96SNiklas Söderlund spin_lock_irqsave(&vin->qlock, flags); 1058f00add96SNiklas Söderlund 1059f00add96SNiklas Söderlund int_status = rvin_get_interrupt_status(vin); 1060f00add96SNiklas Söderlund if (!int_status) 1061f00add96SNiklas Söderlund goto done; 1062f00add96SNiklas Söderlund 1063f00add96SNiklas Söderlund rvin_ack_interrupt(vin); 1064f00add96SNiklas Söderlund handled = 1; 1065f00add96SNiklas Söderlund 106630334d3dSNiklas Söderlund /* Nothing to do if nothing was captured. */ 106730334d3dSNiklas Söderlund if (!(int_status & VNINTS_FIS)) 106830334d3dSNiklas Söderlund goto done; 106930334d3dSNiklas Söderlund 1070c1eefe88SNiklas Söderlund /* Nothing to do if not running. */ 1071c1eefe88SNiklas Söderlund if (!vin->running) { 1072c1eefe88SNiklas Söderlund vin_dbg(vin, "IRQ while not running, ignoring\n"); 1073f00add96SNiklas Söderlund goto done; 1074f00add96SNiklas Söderlund } 1075f00add96SNiklas Söderlund 1076f00add96SNiklas Söderlund /* Prepare for capture and update state */ 1077b6f556cbSNiklas Söderlund vnms = rvin_read(vin, VNMS_REG); 1078dc9aec79SNiklas Söderlund slot = (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT; 1079f00add96SNiklas Söderlund 108023689ab1SNiklas Söderlund /* 108123689ab1SNiklas Söderlund * To hand buffers back in a known order to userspace start 108223689ab1SNiklas Söderlund * to capture first from slot 0. 108323689ab1SNiklas Söderlund */ 108425482a98SNiklas Söderlund if (!vin->sequence) { 108523689ab1SNiklas Söderlund if (slot != 0) { 108623689ab1SNiklas Söderlund vin_dbg(vin, "Starting sync slot: %d\n", slot); 108723689ab1SNiklas Söderlund goto done; 108823689ab1SNiklas Söderlund } 108923689ab1SNiklas Söderlund 109023689ab1SNiklas Söderlund vin_dbg(vin, "Capture start synced!\n"); 109123689ab1SNiklas Söderlund } 109223689ab1SNiklas Söderlund 1093f00add96SNiklas Söderlund /* Capture frame */ 1094e72b7359SNiklas Söderlund if (vin->buf_hw[slot].buffer) { 1095e72b7359SNiklas Söderlund vin->buf_hw[slot].buffer->field = 1096e72b7359SNiklas Söderlund rvin_get_active_field(vin, vnms); 1097e72b7359SNiklas Söderlund vin->buf_hw[slot].buffer->sequence = vin->sequence; 1098e72b7359SNiklas Söderlund vin->buf_hw[slot].buffer->vb2_buf.timestamp = ktime_get_ns(); 1099e72b7359SNiklas Söderlund vb2_buffer_done(&vin->buf_hw[slot].buffer->vb2_buf, 1100dc9aec79SNiklas Söderlund VB2_BUF_STATE_DONE); 1101e72b7359SNiklas Söderlund vin->buf_hw[slot].buffer = NULL; 1102dc9aec79SNiklas Söderlund } else { 1103dc9aec79SNiklas Söderlund /* Scratch buffer was used, dropping frame. */ 1104dc9aec79SNiklas Söderlund vin_dbg(vin, "Dropping frame %u\n", vin->sequence); 1105dc9aec79SNiklas Söderlund } 1106dc9aec79SNiklas Söderlund 1107dc9aec79SNiklas Söderlund vin->sequence++; 1108f00add96SNiklas Söderlund 1109f00add96SNiklas Söderlund /* Prepare for next frame */ 1110dc9aec79SNiklas Söderlund rvin_fill_hw_slot(vin, slot); 1111f00add96SNiklas Söderlund done: 1112f00add96SNiklas Söderlund spin_unlock_irqrestore(&vin->qlock, flags); 1113f00add96SNiklas Söderlund 1114f00add96SNiklas Söderlund return IRQ_RETVAL(handled); 1115f00add96SNiklas Söderlund } 1116f00add96SNiklas Söderlund 1117b83a18ccSNiklas Söderlund static void return_unused_buffers(struct rvin_dev *vin, 1118f00add96SNiklas Söderlund enum vb2_buffer_state state) 1119f00add96SNiklas Söderlund { 1120f00add96SNiklas Söderlund struct rvin_buffer *buf, *node; 112163a71dd8SNiklas Söderlund unsigned long flags; 112263a71dd8SNiklas Söderlund 112363a71dd8SNiklas Söderlund spin_lock_irqsave(&vin->qlock, flags); 11247e0cfdadSNiklas Söderlund 1125f00add96SNiklas Söderlund list_for_each_entry_safe(buf, node, &vin->buf_list, list) { 1126f00add96SNiklas Söderlund vb2_buffer_done(&buf->vb.vb2_buf, state); 1127f00add96SNiklas Söderlund list_del(&buf->list); 1128f00add96SNiklas Söderlund } 112963a71dd8SNiklas Söderlund 113063a71dd8SNiklas Söderlund spin_unlock_irqrestore(&vin->qlock, flags); 1131f00add96SNiklas Söderlund } 1132f00add96SNiklas Söderlund 1133f00add96SNiklas Söderlund static int rvin_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, 1134f00add96SNiklas Söderlund unsigned int *nplanes, unsigned int sizes[], 113536c0f8b3SHans Verkuil struct device *alloc_devs[]) 1136f00add96SNiklas Söderlund 1137f00add96SNiklas Söderlund { 1138f00add96SNiklas Söderlund struct rvin_dev *vin = vb2_get_drv_priv(vq); 1139f00add96SNiklas Söderlund 1140f00add96SNiklas Söderlund /* Make sure the image size is large enough. */ 1141f00add96SNiklas Söderlund if (*nplanes) 1142f00add96SNiklas Söderlund return sizes[0] < vin->format.sizeimage ? -EINVAL : 0; 1143f00add96SNiklas Söderlund 1144f00add96SNiklas Söderlund *nplanes = 1; 1145f00add96SNiklas Söderlund sizes[0] = vin->format.sizeimage; 1146f00add96SNiklas Söderlund 1147f00add96SNiklas Söderlund return 0; 1148f00add96SNiklas Söderlund }; 1149f00add96SNiklas Söderlund 1150f00add96SNiklas Söderlund static int rvin_buffer_prepare(struct vb2_buffer *vb) 1151f00add96SNiklas Söderlund { 1152f00add96SNiklas Söderlund struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue); 1153f00add96SNiklas Söderlund unsigned long size = vin->format.sizeimage; 1154f00add96SNiklas Söderlund 1155f00add96SNiklas Söderlund if (vb2_plane_size(vb, 0) < size) { 1156f00add96SNiklas Söderlund vin_err(vin, "buffer too small (%lu < %lu)\n", 1157f00add96SNiklas Söderlund vb2_plane_size(vb, 0), size); 1158f00add96SNiklas Söderlund return -EINVAL; 1159f00add96SNiklas Söderlund } 1160f00add96SNiklas Söderlund 1161f00add96SNiklas Söderlund vb2_set_plane_payload(vb, 0, size); 1162f00add96SNiklas Söderlund 1163f00add96SNiklas Söderlund return 0; 1164f00add96SNiklas Söderlund } 1165f00add96SNiklas Söderlund 1166f00add96SNiklas Söderlund static void rvin_buffer_queue(struct vb2_buffer *vb) 1167f00add96SNiklas Söderlund { 1168f00add96SNiklas Söderlund struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 1169f00add96SNiklas Söderlund struct rvin_dev *vin = vb2_get_drv_priv(vb->vb2_queue); 1170f00add96SNiklas Söderlund unsigned long flags; 1171f00add96SNiklas Söderlund 1172f00add96SNiklas Söderlund spin_lock_irqsave(&vin->qlock, flags); 1173f00add96SNiklas Söderlund 1174f00add96SNiklas Söderlund list_add_tail(to_buf_list(vbuf), &vin->buf_list); 1175f00add96SNiklas Söderlund 1176f00add96SNiklas Söderlund spin_unlock_irqrestore(&vin->qlock, flags); 1177f00add96SNiklas Söderlund } 1178f00add96SNiklas Söderlund 11797b7eb115SNiklas Söderlund static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd, 11807b7eb115SNiklas Söderlund struct media_pad *pad) 11817b7eb115SNiklas Söderlund { 11827b7eb115SNiklas Söderlund struct v4l2_subdev_format fmt = { 11837b7eb115SNiklas Söderlund .which = V4L2_SUBDEV_FORMAT_ACTIVE, 11847b7eb115SNiklas Söderlund }; 11857b7eb115SNiklas Söderlund 11867b7eb115SNiklas Söderlund fmt.pad = pad->index; 11877b7eb115SNiklas Söderlund if (v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt)) 11887b7eb115SNiklas Söderlund return -EPIPE; 11897b7eb115SNiklas Söderlund 11907b7eb115SNiklas Söderlund switch (fmt.format.code) { 11917b7eb115SNiklas Söderlund case MEDIA_BUS_FMT_YUYV8_1X16: 119201d72e9dSNiklas Söderlund case MEDIA_BUS_FMT_UYVY8_1X16: 11937b7eb115SNiklas Söderlund case MEDIA_BUS_FMT_UYVY8_2X8: 11947b7eb115SNiklas Söderlund case MEDIA_BUS_FMT_UYVY10_2X10: 11957b7eb115SNiklas Söderlund case MEDIA_BUS_FMT_RGB888_1X24: 1196fd22e8ebSLad Prabhakar break; 11978c3e0f67SNiklas Söderlund case MEDIA_BUS_FMT_SBGGR8_1X8: 11988c3e0f67SNiklas Söderlund if (vin->format.pixelformat != V4L2_PIX_FMT_SBGGR8) 11998c3e0f67SNiklas Söderlund return -EPIPE; 12008c3e0f67SNiklas Söderlund break; 12018c3e0f67SNiklas Söderlund case MEDIA_BUS_FMT_SGBRG8_1X8: 12028c3e0f67SNiklas Söderlund if (vin->format.pixelformat != V4L2_PIX_FMT_SGBRG8) 12038c3e0f67SNiklas Söderlund return -EPIPE; 12048c3e0f67SNiklas Söderlund break; 12058c3e0f67SNiklas Söderlund case MEDIA_BUS_FMT_SGRBG8_1X8: 12068c3e0f67SNiklas Söderlund if (vin->format.pixelformat != V4L2_PIX_FMT_SGRBG8) 12078c3e0f67SNiklas Söderlund return -EPIPE; 12088c3e0f67SNiklas Söderlund break; 1209fd22e8ebSLad Prabhakar case MEDIA_BUS_FMT_SRGGB8_1X8: 1210fd22e8ebSLad Prabhakar if (vin->format.pixelformat != V4L2_PIX_FMT_SRGGB8) 1211fd22e8ebSLad Prabhakar return -EPIPE; 12127b7eb115SNiklas Söderlund break; 1213c93beb52SVladimir Barinov case MEDIA_BUS_FMT_Y8_1X8: 1214c93beb52SVladimir Barinov if (vin->format.pixelformat != V4L2_PIX_FMT_GREY) 1215c93beb52SVladimir Barinov return -EPIPE; 1216c93beb52SVladimir Barinov break; 12171b7e7240SNiklas Söderlund case MEDIA_BUS_FMT_SBGGR10_1X10: 12181b7e7240SNiklas Söderlund if (vin->format.pixelformat != V4L2_PIX_FMT_SBGGR10) 12191b7e7240SNiklas Söderlund return -EPIPE; 12201b7e7240SNiklas Söderlund break; 12211b7e7240SNiklas Söderlund case MEDIA_BUS_FMT_SGBRG10_1X10: 12221b7e7240SNiklas Söderlund if (vin->format.pixelformat != V4L2_PIX_FMT_SGBRG10) 12231b7e7240SNiklas Söderlund return -EPIPE; 12241b7e7240SNiklas Söderlund break; 12251b7e7240SNiklas Söderlund case MEDIA_BUS_FMT_SGRBG10_1X10: 12261b7e7240SNiklas Söderlund if (vin->format.pixelformat != V4L2_PIX_FMT_SGRBG10) 12271b7e7240SNiklas Söderlund return -EPIPE; 12281b7e7240SNiklas Söderlund break; 12291b7e7240SNiklas Söderlund case MEDIA_BUS_FMT_SRGGB10_1X10: 12301b7e7240SNiklas Söderlund if (vin->format.pixelformat != V4L2_PIX_FMT_SRGGB10) 12311b7e7240SNiklas Söderlund return -EPIPE; 12321b7e7240SNiklas Söderlund break; 12337b7eb115SNiklas Söderlund default: 12347b7eb115SNiklas Söderlund return -EPIPE; 12357b7eb115SNiklas Söderlund } 1236fd22e8ebSLad Prabhakar vin->mbus_code = fmt.format.code; 12377b7eb115SNiklas Söderlund 12387b7eb115SNiklas Söderlund switch (fmt.format.field) { 12397b7eb115SNiklas Söderlund case V4L2_FIELD_TOP: 12407b7eb115SNiklas Söderlund case V4L2_FIELD_BOTTOM: 12417b7eb115SNiklas Söderlund case V4L2_FIELD_NONE: 12427b7eb115SNiklas Söderlund case V4L2_FIELD_INTERLACED_TB: 12437b7eb115SNiklas Söderlund case V4L2_FIELD_INTERLACED_BT: 12447b7eb115SNiklas Söderlund case V4L2_FIELD_INTERLACED: 12457b7eb115SNiklas Söderlund /* Supported natively */ 12467b7eb115SNiklas Söderlund break; 12477b7eb115SNiklas Söderlund case V4L2_FIELD_ALTERNATE: 12487b7eb115SNiklas Söderlund switch (vin->format.field) { 12497b7eb115SNiklas Söderlund case V4L2_FIELD_TOP: 12507b7eb115SNiklas Söderlund case V4L2_FIELD_BOTTOM: 12517b7eb115SNiklas Söderlund case V4L2_FIELD_NONE: 125208369321SNiklas Söderlund case V4L2_FIELD_ALTERNATE: 12537b7eb115SNiklas Söderlund break; 12547b7eb115SNiklas Söderlund case V4L2_FIELD_INTERLACED_TB: 12557b7eb115SNiklas Söderlund case V4L2_FIELD_INTERLACED_BT: 12567b7eb115SNiklas Söderlund case V4L2_FIELD_INTERLACED: 12577b7eb115SNiklas Söderlund /* Use VIN hardware to combine the two fields */ 12587b7eb115SNiklas Söderlund fmt.format.height *= 2; 12597b7eb115SNiklas Söderlund break; 12607b7eb115SNiklas Söderlund default: 12617b7eb115SNiklas Söderlund return -EPIPE; 12627b7eb115SNiklas Söderlund } 12637b7eb115SNiklas Söderlund break; 12647b7eb115SNiklas Söderlund default: 12657b7eb115SNiklas Söderlund return -EPIPE; 12667b7eb115SNiklas Söderlund } 12677b7eb115SNiklas Söderlund 12683ad69c61SNiklas Söderlund if (rvin_scaler_needed(vin)) { 1269879c5a45SNiklas Söderlund /* Gen3 can't scale NV12 */ 1270d6a08667STomi Valkeinen if ((vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) && 1271879c5a45SNiklas Söderlund vin->format.pixelformat == V4L2_PIX_FMT_NV12) 1272879c5a45SNiklas Söderlund return -EPIPE; 1273879c5a45SNiklas Söderlund 12743ad69c61SNiklas Söderlund if (!vin->scaler) 12753ad69c61SNiklas Söderlund return -EPIPE; 12763ad69c61SNiklas Söderlund } else { 1277cb88d828SNiklas Söderlund if (vin->format.pixelformat == V4L2_PIX_FMT_NV12) { 1278cb88d828SNiklas Söderlund if (ALIGN(fmt.format.width, 32) != vin->format.width || 1279cb88d828SNiklas Söderlund ALIGN(fmt.format.height, 32) != vin->format.height) 1280cb88d828SNiklas Söderlund return -EPIPE; 1281cb88d828SNiklas Söderlund } else { 12827b7eb115SNiklas Söderlund if (fmt.format.width != vin->format.width || 12833ad69c61SNiklas Söderlund fmt.format.height != vin->format.height) 12843ad69c61SNiklas Söderlund return -EPIPE; 12853ad69c61SNiklas Söderlund } 1286cb88d828SNiklas Söderlund } 12873ad69c61SNiklas Söderlund 12883ad69c61SNiklas Söderlund if (fmt.format.code != vin->mbus_code) 12897b7eb115SNiklas Söderlund return -EPIPE; 12907b7eb115SNiklas Söderlund 12917b7eb115SNiklas Söderlund return 0; 12927b7eb115SNiklas Söderlund } 12937b7eb115SNiklas Söderlund 12947b7eb115SNiklas Söderlund static int rvin_set_stream(struct rvin_dev *vin, int on) 12957b7eb115SNiklas Söderlund { 12967b7eb115SNiklas Söderlund struct v4l2_subdev *sd; 12977b7eb115SNiklas Söderlund struct media_pad *pad; 12987b7eb115SNiklas Söderlund int ret; 12997b7eb115SNiklas Söderlund 13007b7eb115SNiklas Söderlund /* No media controller used, simply pass operation to subdevice. */ 13017b7eb115SNiklas Söderlund if (!vin->info->use_mc) { 1302d7592b2eSNiklas Söderlund ret = v4l2_subdev_call(vin->parallel.subdev, video, s_stream, 13037b7eb115SNiklas Söderlund on); 13047b7eb115SNiklas Söderlund 13057b7eb115SNiklas Söderlund return ret == -ENOIOCTLCMD ? 0 : ret; 13067b7eb115SNiklas Söderlund } 13077b7eb115SNiklas Söderlund 1308b2e44430SLaurent Pinchart pad = media_pad_remote_pad_first(&vin->pad); 13097b7eb115SNiklas Söderlund if (!pad) 13107b7eb115SNiklas Söderlund return -EPIPE; 13117b7eb115SNiklas Söderlund 13127b7eb115SNiklas Söderlund sd = media_entity_to_v4l2_subdev(pad->entity); 13137b7eb115SNiklas Söderlund 13147b7eb115SNiklas Söderlund if (!on) { 131512cecbf9STomi Valkeinen video_device_pipeline_stop(&vin->vdev); 1316178c1be5STomi Valkeinen return v4l2_subdev_disable_streams(sd, pad->index, BIT_ULL(0)); 13177b7eb115SNiklas Söderlund } 13187b7eb115SNiklas Söderlund 13197b7eb115SNiklas Söderlund ret = rvin_mc_validate_format(vin, sd, pad); 13207b7eb115SNiklas Söderlund if (ret) 13217b7eb115SNiklas Söderlund return ret; 13227b7eb115SNiklas Söderlund 13236eaff06aSTomi Valkeinen ret = video_device_pipeline_alloc_start(&vin->vdev); 13247b7eb115SNiklas Söderlund if (ret) 13257b7eb115SNiklas Söderlund return ret; 13267b7eb115SNiklas Söderlund 1327178c1be5STomi Valkeinen ret = v4l2_subdev_enable_streams(sd, pad->index, BIT_ULL(0)); 13287b7eb115SNiklas Söderlund if (ret == -ENOIOCTLCMD) 13297b7eb115SNiklas Söderlund ret = 0; 13307b7eb115SNiklas Söderlund if (ret) 133112cecbf9STomi Valkeinen video_device_pipeline_stop(&vin->vdev); 13327b7eb115SNiklas Söderlund 13337b7eb115SNiklas Söderlund return ret; 13347b7eb115SNiklas Söderlund } 13357b7eb115SNiklas Söderlund 133663a71dd8SNiklas Söderlund int rvin_start_streaming(struct rvin_dev *vin) 1337f00add96SNiklas Söderlund { 1338f00add96SNiklas Söderlund unsigned long flags; 1339f00add96SNiklas Söderlund int ret; 1340f00add96SNiklas Söderlund 13417b7eb115SNiklas Söderlund ret = rvin_set_stream(vin, 1); 134263a71dd8SNiklas Söderlund if (ret) 134363a71dd8SNiklas Söderlund return ret; 1344f00add96SNiklas Söderlund 1345f00add96SNiklas Söderlund spin_lock_irqsave(&vin->qlock, flags); 1346f00add96SNiklas Söderlund 1347f00add96SNiklas Söderlund vin->sequence = 0; 1348f00add96SNiklas Söderlund 1349f00add96SNiklas Söderlund ret = rvin_capture_start(vin); 135063a71dd8SNiklas Söderlund if (ret) 13517b7eb115SNiklas Söderlund rvin_set_stream(vin, 0); 1352f00add96SNiklas Söderlund 1353c1eefe88SNiklas Söderlund vin->running = true; 1354c1eefe88SNiklas Söderlund 1355f00add96SNiklas Söderlund spin_unlock_irqrestore(&vin->qlock, flags); 13566a8ffa8bSNiklas Söderlund 1357f00add96SNiklas Söderlund return ret; 1358f00add96SNiklas Söderlund } 1359f00add96SNiklas Söderlund 136063a71dd8SNiklas Söderlund static int rvin_start_streaming_vq(struct vb2_queue *vq, unsigned int count) 1361f00add96SNiklas Söderlund { 1362f00add96SNiklas Söderlund struct rvin_dev *vin = vb2_get_drv_priv(vq); 136363a71dd8SNiklas Söderlund int ret = -ENOMEM; 136463a71dd8SNiklas Söderlund 136563a71dd8SNiklas Söderlund /* Allocate scratch buffer. */ 136663a71dd8SNiklas Söderlund vin->scratch = dma_alloc_coherent(vin->dev, vin->format.sizeimage, 136763a71dd8SNiklas Söderlund &vin->scratch_phys, GFP_KERNEL); 136863a71dd8SNiklas Söderlund if (!vin->scratch) 136963a71dd8SNiklas Söderlund goto err_scratch; 137063a71dd8SNiklas Söderlund 137163a71dd8SNiklas Söderlund ret = rvin_start_streaming(vin); 137263a71dd8SNiklas Söderlund if (ret) 137363a71dd8SNiklas Söderlund goto err_start; 137463a71dd8SNiklas Söderlund 137563a71dd8SNiklas Söderlund return 0; 137663a71dd8SNiklas Söderlund err_start: 137763a71dd8SNiklas Söderlund dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch, 137863a71dd8SNiklas Söderlund vin->scratch_phys); 137963a71dd8SNiklas Söderlund err_scratch: 138063a71dd8SNiklas Söderlund return_unused_buffers(vin, VB2_BUF_STATE_QUEUED); 138163a71dd8SNiklas Söderlund 138263a71dd8SNiklas Söderlund return ret; 138363a71dd8SNiklas Söderlund } 138463a71dd8SNiklas Söderlund 138563a71dd8SNiklas Söderlund void rvin_stop_streaming(struct rvin_dev *vin) 138663a71dd8SNiklas Söderlund { 1387f00add96SNiklas Söderlund unsigned long flags; 1388f00add96SNiklas Söderlund 1389f00add96SNiklas Söderlund spin_lock_irqsave(&vin->qlock, flags); 1390f00add96SNiklas Söderlund 1391c1eefe88SNiklas Söderlund if (!vin->running) { 1392c4f11535SNiklas Söderlund spin_unlock_irqrestore(&vin->qlock, flags); 1393c4f11535SNiklas Söderlund return; 1394c4f11535SNiklas Söderlund } 1395c4f11535SNiklas Söderlund 1396f00add96SNiklas Söderlund /* Wait for streaming to stop */ 1397c1eefe88SNiklas Söderlund for (unsigned int i = 0; i < RVIN_RETRIES; i++) { 1398f00add96SNiklas Söderlund rvin_capture_stop(vin); 1399f00add96SNiklas Söderlund 1400f00add96SNiklas Söderlund /* Check if HW is stopped */ 1401f00add96SNiklas Söderlund if (!rvin_capture_active(vin)) { 1402f00add96SNiklas Söderlund break; 1403f00add96SNiklas Söderlund } 1404f00add96SNiklas Söderlund 1405f00add96SNiklas Söderlund spin_unlock_irqrestore(&vin->qlock, flags); 1406f00add96SNiklas Söderlund msleep(RVIN_TIMEOUT_MS); 1407f00add96SNiklas Söderlund spin_lock_irqsave(&vin->qlock, flags); 1408f00add96SNiklas Söderlund } 1409f00add96SNiklas Söderlund 1410c1eefe88SNiklas Söderlund if (rvin_capture_active(vin)) 1411c1eefe88SNiklas Söderlund vin_err(vin, "Hardware did not stop\n"); 1412c1eefe88SNiklas Söderlund 1413c1eefe88SNiklas Söderlund vin->running = false; 1414f00add96SNiklas Söderlund 1415f00add96SNiklas Söderlund spin_unlock_irqrestore(&vin->qlock, flags); 1416f00add96SNiklas Söderlund 14177b7eb115SNiklas Söderlund rvin_set_stream(vin, 0); 1418f00add96SNiklas Söderlund 1419f00add96SNiklas Söderlund /* disable interrupts */ 1420f00add96SNiklas Söderlund rvin_disable_interrupts(vin); 1421c1eefe88SNiklas Söderlund 1422c1eefe88SNiklas Söderlund /* Return unprocessed buffers from hardware. */ 1423c1eefe88SNiklas Söderlund for (unsigned int i = 0; i < HW_BUFFER_NUM; i++) { 1424c1eefe88SNiklas Söderlund if (vin->buf_hw[i].buffer) 1425c1eefe88SNiklas Söderlund vb2_buffer_done(&vin->buf_hw[i].buffer->vb2_buf, 1426c1eefe88SNiklas Söderlund VB2_BUF_STATE_ERROR); 1427c1eefe88SNiklas Söderlund } 1428c1eefe88SNiklas Söderlund 142963a71dd8SNiklas Söderlund } 143063a71dd8SNiklas Söderlund 143163a71dd8SNiklas Söderlund static void rvin_stop_streaming_vq(struct vb2_queue *vq) 143263a71dd8SNiklas Söderlund { 143363a71dd8SNiklas Söderlund struct rvin_dev *vin = vb2_get_drv_priv(vq); 143463a71dd8SNiklas Söderlund 143563a71dd8SNiklas Söderlund rvin_stop_streaming(vin); 14366a8ffa8bSNiklas Söderlund 14376a8ffa8bSNiklas Söderlund /* Free scratch buffer. */ 14386a8ffa8bSNiklas Söderlund dma_free_coherent(vin->dev, vin->format.sizeimage, vin->scratch, 14396a8ffa8bSNiklas Söderlund vin->scratch_phys); 144063a71dd8SNiklas Söderlund 144163a71dd8SNiklas Söderlund return_unused_buffers(vin, VB2_BUF_STATE_ERROR); 1442f00add96SNiklas Söderlund } 1443f00add96SNiklas Söderlund 1444b7b361f0SJulia Lawall static const struct vb2_ops rvin_qops = { 1445f00add96SNiklas Söderlund .queue_setup = rvin_queue_setup, 1446f00add96SNiklas Söderlund .buf_prepare = rvin_buffer_prepare, 1447f00add96SNiklas Söderlund .buf_queue = rvin_buffer_queue, 144863a71dd8SNiklas Söderlund .start_streaming = rvin_start_streaming_vq, 144963a71dd8SNiklas Söderlund .stop_streaming = rvin_stop_streaming_vq, 1450f00add96SNiklas Söderlund }; 1451f00add96SNiklas Söderlund 1452d6ad012eSNiklas Söderlund void rvin_dma_unregister(struct rvin_dev *vin) 1453f00add96SNiklas Söderlund { 1454f00add96SNiklas Söderlund mutex_destroy(&vin->lock); 1455f00add96SNiklas Söderlund 1456f00add96SNiklas Söderlund v4l2_device_unregister(&vin->v4l2_dev); 1457f00add96SNiklas Söderlund } 1458f00add96SNiklas Söderlund 1459d6ad012eSNiklas Söderlund int rvin_dma_register(struct rvin_dev *vin, int irq) 1460f00add96SNiklas Söderlund { 1461f00add96SNiklas Söderlund struct vb2_queue *q = &vin->queue; 1462f00add96SNiklas Söderlund int i, ret; 1463f00add96SNiklas Söderlund 1464f00add96SNiklas Söderlund /* Initialize the top-level structure */ 1465f00add96SNiklas Söderlund ret = v4l2_device_register(vin->dev, &vin->v4l2_dev); 1466f00add96SNiklas Söderlund if (ret) 1467f00add96SNiklas Söderlund return ret; 1468f00add96SNiklas Söderlund 1469f00add96SNiklas Söderlund mutex_init(&vin->lock); 1470f00add96SNiklas Söderlund INIT_LIST_HEAD(&vin->buf_list); 1471f00add96SNiklas Söderlund 1472f00add96SNiklas Söderlund spin_lock_init(&vin->qlock); 1473f00add96SNiklas Söderlund 1474f00add96SNiklas Söderlund for (i = 0; i < HW_BUFFER_NUM; i++) 1475e72b7359SNiklas Söderlund vin->buf_hw[i].buffer = NULL; 1476f00add96SNiklas Söderlund 1477f00add96SNiklas Söderlund /* buffer queue */ 1478f00add96SNiklas Söderlund q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1479f00add96SNiklas Söderlund q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF; 1480f00add96SNiklas Söderlund q->lock = &vin->lock; 1481f00add96SNiklas Söderlund q->drv_priv = vin; 1482f00add96SNiklas Söderlund q->buf_struct_size = sizeof(struct rvin_buffer); 1483f00add96SNiklas Söderlund q->ops = &rvin_qops; 1484f00add96SNiklas Söderlund q->mem_ops = &vb2_dma_contig_memops; 1485f00add96SNiklas Söderlund q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 148680c2b40aSBenjamin Gaignard q->min_queued_buffers = 4; 148753ddcc68SHans Verkuil q->dev = vin->dev; 1488f00add96SNiklas Söderlund 1489f00add96SNiklas Söderlund ret = vb2_queue_init(q); 1490f00add96SNiklas Söderlund if (ret < 0) { 1491f00add96SNiklas Söderlund vin_err(vin, "failed to initialize VB2 queue\n"); 1492f00add96SNiklas Söderlund goto error; 1493f00add96SNiklas Söderlund } 1494f00add96SNiklas Söderlund 1495f00add96SNiklas Söderlund /* irq */ 1496f00add96SNiklas Söderlund ret = devm_request_irq(vin->dev, irq, rvin_irq, IRQF_SHARED, 1497f00add96SNiklas Söderlund KBUILD_MODNAME, vin); 1498f00add96SNiklas Söderlund if (ret) { 1499f00add96SNiklas Söderlund vin_err(vin, "failed to request irq\n"); 1500f00add96SNiklas Söderlund goto error; 1501f00add96SNiklas Söderlund } 1502f00add96SNiklas Söderlund 1503f00add96SNiklas Söderlund return 0; 1504f00add96SNiklas Söderlund error: 1505d6ad012eSNiklas Söderlund rvin_dma_unregister(vin); 1506f00add96SNiklas Söderlund 1507f00add96SNiklas Söderlund return ret; 1508f00add96SNiklas Söderlund } 150990dedce9SNiklas Söderlund 151090dedce9SNiklas Söderlund /* ----------------------------------------------------------------------------- 151190dedce9SNiklas Söderlund * Gen3 CHSEL manipulation 151290dedce9SNiklas Söderlund */ 151390dedce9SNiklas Söderlund 151490dedce9SNiklas Söderlund /* 151590dedce9SNiklas Söderlund * There is no need to have locking around changing the routing 151690dedce9SNiklas Söderlund * as it's only possible to do so when no VIN in the group is 151790dedce9SNiklas Söderlund * streaming so nothing can race with the VNMC register. 151890dedce9SNiklas Söderlund */ 151990dedce9SNiklas Söderlund int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel) 152090dedce9SNiklas Söderlund { 1521fb25ca37SJacopo Mondi const struct rvin_group_route *route; 1522fb25ca37SJacopo Mondi u32 ifmd = 0; 1523fb25ca37SJacopo Mondi u32 vnmc; 152490dedce9SNiklas Söderlund int ret; 152590dedce9SNiklas Söderlund 1526334fe327SMauro Carvalho Chehab ret = pm_runtime_resume_and_get(vin->dev); 1527334fe327SMauro Carvalho Chehab if (ret < 0) 152890dedce9SNiklas Söderlund return ret; 152990dedce9SNiklas Söderlund 153090dedce9SNiklas Söderlund /* Make register writes take effect immediately. */ 153190dedce9SNiklas Söderlund vnmc = rvin_read(vin, VNMC_REG); 153290dedce9SNiklas Söderlund rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG); 153390dedce9SNiklas Söderlund 1534fb25ca37SJacopo Mondi /* 1535fb25ca37SJacopo Mondi * Set data expansion mode to "pad with 0s" by inspecting the routes 1536fb25ca37SJacopo Mondi * table to find out which bit fields are available in the IFMD 1537fb25ca37SJacopo Mondi * register. IFMD_DES1 controls data expansion mode for CSI20/21, 1538fb25ca37SJacopo Mondi * IFMD_DES0 controls data expansion mode for CSI40/41. 1539fb25ca37SJacopo Mondi */ 15403e52419eSNiklas Söderlund for (route = vin->info->routes; route->chsel; route++) { 1541fb25ca37SJacopo Mondi if (route->csi == RVIN_CSI20 || route->csi == RVIN_CSI21) 1542fb25ca37SJacopo Mondi ifmd |= VNCSI_IFMD_DES1; 1543fb25ca37SJacopo Mondi else 1544fb25ca37SJacopo Mondi ifmd |= VNCSI_IFMD_DES0; 154590dedce9SNiklas Söderlund 1546fb25ca37SJacopo Mondi if (ifmd == (VNCSI_IFMD_DES0 | VNCSI_IFMD_DES1)) 1547fb25ca37SJacopo Mondi break; 1548fb25ca37SJacopo Mondi } 1549fb25ca37SJacopo Mondi 1550fb25ca37SJacopo Mondi if (ifmd) { 1551fb25ca37SJacopo Mondi ifmd |= VNCSI_IFMD_CSI_CHSEL(chsel); 155290dedce9SNiklas Söderlund rvin_write(vin, ifmd, VNCSI_IFMD_REG); 1553fb25ca37SJacopo Mondi } 155490dedce9SNiklas Söderlund 155590dedce9SNiklas Söderlund vin_dbg(vin, "Set IFMD 0x%x\n", ifmd); 155690dedce9SNiklas Söderlund 155743e36a22SNiklas Söderlund vin->chsel = chsel; 155843e36a22SNiklas Söderlund 155990dedce9SNiklas Söderlund /* Restore VNMC. */ 156090dedce9SNiklas Söderlund rvin_write(vin, vnmc, VNMC_REG); 156190dedce9SNiklas Söderlund 156290dedce9SNiklas Söderlund pm_runtime_put(vin->dev); 156390dedce9SNiklas Söderlund 15648d19d5d0SNiklas Söderlund return 0; 156590dedce9SNiklas Söderlund } 15665720c733SNiklas Söderlund 15675720c733SNiklas Söderlund void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha) 15685720c733SNiklas Söderlund { 15691d99e68cSNiklas Söderlund unsigned long flags; 15701d99e68cSNiklas Söderlund u32 dmr; 15711d99e68cSNiklas Söderlund 15721d99e68cSNiklas Söderlund spin_lock_irqsave(&vin->qlock, flags); 15731d99e68cSNiklas Söderlund 15745720c733SNiklas Söderlund vin->alpha = alpha; 15751d99e68cSNiklas Söderlund 1576c1eefe88SNiklas Söderlund if (!vin->running) 15771d99e68cSNiklas Söderlund goto out; 15781d99e68cSNiklas Söderlund 15791d99e68cSNiklas Söderlund switch (vin->format.pixelformat) { 15801d99e68cSNiklas Söderlund case V4L2_PIX_FMT_ARGB555: 15811d99e68cSNiklas Söderlund dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_ABIT; 15821d99e68cSNiklas Söderlund if (vin->alpha) 15831d99e68cSNiklas Söderlund dmr |= VNDMR_ABIT; 15841d99e68cSNiklas Söderlund break; 15851d99e68cSNiklas Söderlund case V4L2_PIX_FMT_ABGR32: 15861d99e68cSNiklas Söderlund dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_A8BIT_MASK; 15871d99e68cSNiklas Söderlund dmr |= VNDMR_A8BIT(vin->alpha); 15881d99e68cSNiklas Söderlund break; 15891d99e68cSNiklas Söderlund default: 15901d99e68cSNiklas Söderlund goto out; 15911d99e68cSNiklas Söderlund } 15921d99e68cSNiklas Söderlund 15931d99e68cSNiklas Söderlund rvin_write(vin, dmr, VNDMR_REG); 15941d99e68cSNiklas Söderlund out: 15951d99e68cSNiklas Söderlund spin_unlock_irqrestore(&vin->qlock, flags); 15965720c733SNiklas Söderlund } 1597