1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Intersil ISL7998x analog to MIPI CSI-2 or BT.656 decoder driver. 4 * 5 * Copyright (C) 2018-2019 Marek Vasut <marex@denx.de> 6 * Copyright (C) 2021 Michael Tretter <kernel@pengutronix.de> 7 */ 8 9 #include <linux/bitfield.h> 10 #include <linux/delay.h> 11 #include <linux/gpio/consumer.h> 12 #include <linux/i2c.h> 13 #include <linux/module.h> 14 #include <linux/of_graph.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/regmap.h> 17 #include <linux/slab.h> 18 #include <linux/v4l2-mediabus.h> 19 #include <linux/videodev2.h> 20 21 #include <media/v4l2-async.h> 22 #include <media/v4l2-common.h> 23 #include <media/v4l2-ctrls.h> 24 #include <media/v4l2-device.h> 25 #include <media/v4l2-fwnode.h> 26 #include <media/v4l2-ioctl.h> 27 28 /* 29 * This control allows to activate and deactivate the test pattern on 30 * selected output channels. 31 * This value is ISL7998x specific. 32 */ 33 #define V4L2_CID_TEST_PATTERN_CHANNELS (V4L2_CID_USER_ISL7998X_BASE + 0) 34 35 /* 36 * This control allows to specify the color of the test pattern. 37 * This value is ISL7998x specific. 38 */ 39 #define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_ISL7998X_BASE + 1) 40 41 /* 42 * This control allows to specify the bar pattern in the test pattern. 43 * This value is ISL7998x specific. 44 */ 45 #define V4L2_CID_TEST_PATTERN_BARS (V4L2_CID_USER_ISL7998X_BASE + 2) 46 47 #define ISL7998X_INPUTS 4 48 49 #define ISL7998X_REG(page, reg) (((page) << 8) | (reg)) 50 51 #define ISL7998X_REG_PN_SIZE 256 52 #define ISL7998X_REG_PN_BASE(n) ((n) * ISL7998X_REG_PN_SIZE) 53 54 #define ISL7998X_REG_PX_DEC_PAGE(page) ISL7998X_REG((page), 0xff) 55 #define ISL7998X_REG_PX_DEC_PAGE_MASK 0xf 56 #define ISL7998X_REG_P0_PRODUCT_ID_CODE ISL7998X_REG(0, 0x00) 57 #define ISL7998X_REG_P0_PRODUCT_REV_CODE ISL7998X_REG(0, 0x01) 58 #define ISL7998X_REG_P0_SW_RESET_CTL ISL7998X_REG(0, 0x02) 59 #define ISL7998X_REG_P0_IO_BUFFER_CTL ISL7998X_REG(0, 0x03) 60 #define ISL7998X_REG_P0_IO_BUFFER_CTL_1_1 ISL7998X_REG(0, 0x04) 61 #define ISL7998X_REG_P0_IO_PAD_PULL_EN_CTL ISL7998X_REG(0, 0x05) 62 #define ISL7998X_REG_P0_IO_BUFFER_CTL_1_2 ISL7998X_REG(0, 0x06) 63 #define ISL7998X_REG_P0_VIDEO_IN_CHAN_CTL ISL7998X_REG(0, 0x07) 64 #define ISL7998X_REG_P0_CLK_CTL_1 ISL7998X_REG(0, 0x08) 65 #define ISL7998X_REG_P0_CLK_CTL_2 ISL7998X_REG(0, 0x09) 66 #define ISL7998X_REG_P0_CLK_CTL_3 ISL7998X_REG(0, 0x0a) 67 #define ISL7998X_REG_P0_CLK_CTL_4 ISL7998X_REG(0, 0x0b) 68 #define ISL7998X_REG_P0_MPP1_SYNC_CTL ISL7998X_REG(0, 0x0c) 69 #define ISL7998X_REG_P0_MPP2_SYNC_CTL ISL7998X_REG(0, 0x0d) 70 #define ISL7998X_REG_P0_IRQ_SYNC_CTL ISL7998X_REG(0, 0x0e) 71 #define ISL7998X_REG_P0_INTERRUPT_STATUS ISL7998X_REG(0, 0x10) 72 #define ISL7998X_REG_P0_CHAN_1_IRQ ISL7998X_REG(0, 0x11) 73 #define ISL7998X_REG_P0_CHAN_2_IRQ ISL7998X_REG(0, 0x12) 74 #define ISL7998X_REG_P0_CHAN_3_IRQ ISL7998X_REG(0, 0x13) 75 #define ISL7998X_REG_P0_CHAN_4_IRQ ISL7998X_REG(0, 0x14) 76 #define ISL7998X_REG_P0_SHORT_DIAG_IRQ ISL7998X_REG(0, 0x15) 77 #define ISL7998X_REG_P0_CHAN_1_IRQ_EN ISL7998X_REG(0, 0x16) 78 #define ISL7998X_REG_P0_CHAN_2_IRQ_EN ISL7998X_REG(0, 0x17) 79 #define ISL7998X_REG_P0_CHAN_3_IRQ_EN ISL7998X_REG(0, 0x18) 80 #define ISL7998X_REG_P0_CHAN_4_IRQ_EN ISL7998X_REG(0, 0x19) 81 #define ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN ISL7998X_REG(0, 0x1a) 82 #define ISL7998X_REG_P0_CHAN_1_STATUS ISL7998X_REG(0, 0x1b) 83 #define ISL7998X_REG_P0_CHAN_2_STATUS ISL7998X_REG(0, 0x1c) 84 #define ISL7998X_REG_P0_CHAN_3_STATUS ISL7998X_REG(0, 0x1d) 85 #define ISL7998X_REG_P0_CHAN_4_STATUS ISL7998X_REG(0, 0x1e) 86 #define ISL7998X_REG_P0_SHORT_DIAG_STATUS ISL7998X_REG(0, 0x1f) 87 #define ISL7998X_REG_P0_CLOCK_DELAY ISL7998X_REG(0, 0x20) 88 89 #define ISL7998X_REG_PX_DEC_INPUT_FMT(pg) ISL7998X_REG((pg), 0x02) 90 #define ISL7998X_REG_PX_DEC_STATUS_1(pg) ISL7998X_REG((pg), 0x03) 91 #define ISL7998X_REG_PX_DEC_STATUS_1_VDLOSS BIT(7) 92 #define ISL7998X_REG_PX_DEC_STATUS_1_HLOCK BIT(6) 93 #define ISL7998X_REG_PX_DEC_STATUS_1_VLOCK BIT(3) 94 #define ISL7998X_REG_PX_DEC_HS_DELAY_CTL(pg) ISL7998X_REG((pg), 0x04) 95 #define ISL7998X_REG_PX_DEC_ANCTL(pg) ISL7998X_REG((pg), 0x06) 96 #define ISL7998X_REG_PX_DEC_CROP_HI(pg) ISL7998X_REG((pg), 0x07) 97 #define ISL7998X_REG_PX_DEC_VDELAY_LO(pg) ISL7998X_REG((pg), 0x08) 98 #define ISL7998X_REG_PX_DEC_VACTIVE_LO(pg) ISL7998X_REG((pg), 0x09) 99 #define ISL7998X_REG_PX_DEC_HDELAY_LO(pg) ISL7998X_REG((pg), 0x0a) 100 #define ISL7998X_REG_PX_DEC_HACTIVE_LO(pg) ISL7998X_REG((pg), 0x0b) 101 #define ISL7998X_REG_PX_DEC_CNTRL1(pg) ISL7998X_REG((pg), 0x0c) 102 #define ISL7998X_REG_PX_DEC_CSC_CTL(pg) ISL7998X_REG((pg), 0x0d) 103 #define ISL7998X_REG_PX_DEC_BRIGHT(pg) ISL7998X_REG((pg), 0x10) 104 #define ISL7998X_REG_PX_DEC_CONTRAST(pg) ISL7998X_REG((pg), 0x11) 105 #define ISL7998X_REG_PX_DEC_SHARPNESS(pg) ISL7998X_REG((pg), 0x12) 106 #define ISL7998X_REG_PX_DEC_SAT_U(pg) ISL7998X_REG((pg), 0x13) 107 #define ISL7998X_REG_PX_DEC_SAT_V(pg) ISL7998X_REG((pg), 0x14) 108 #define ISL7998X_REG_PX_DEC_HUE(pg) ISL7998X_REG((pg), 0x15) 109 #define ISL7998X_REG_PX_DEC_VERT_PEAK(pg) ISL7998X_REG((pg), 0x17) 110 #define ISL7998X_REG_PX_DEC_CORING(pg) ISL7998X_REG((pg), 0x18) 111 #define ISL7998X_REG_PX_DEC_SDT(pg) ISL7998X_REG((pg), 0x1c) 112 #define ISL7998X_REG_PX_DEC_SDT_DET BIT(7) 113 #define ISL7998X_REG_PX_DEC_SDT_NOW GENMASK(6, 4) 114 #define ISL7998X_REG_PX_DEC_SDT_STANDARD GENMASK(2, 0) 115 #define ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_M 0 116 #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL 1 117 #define ISL7998X_REG_PX_DEC_SDT_STANDARD_SECAM 2 118 #define ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_443 3 119 #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_M 4 120 #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_CN 5 121 #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_60 6 122 #define ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN 7 123 #define ISL7998X_REG_PX_DEC_SDTR(pg) ISL7998X_REG((pg), 0x1d) 124 #define ISL7998X_REG_PX_DEC_SDTR_ATSTART BIT(7) 125 #define ISL7998X_REG_PX_DEC_CLMPG(pg) ISL7998X_REG((pg), 0x20) 126 #define ISL7998X_REG_PX_DEC_IAGC(pg) ISL7998X_REG((pg), 0x21) 127 #define ISL7998X_REG_PX_DEC_AGCGAIN(pg) ISL7998X_REG((pg), 0x22) 128 #define ISL7998X_REG_PX_DEC_PEAKWT(pg) ISL7998X_REG((pg), 0x23) 129 #define ISL7998X_REG_PX_DEC_CLMPL(pg) ISL7998X_REG((pg), 0x24) 130 #define ISL7998X_REG_PX_DEC_SYNCT(pg) ISL7998X_REG((pg), 0x25) 131 #define ISL7998X_REG_PX_DEC_MISSCNT(pg) ISL7998X_REG((pg), 0x26) 132 #define ISL7998X_REG_PX_DEC_PCLAMP(pg) ISL7998X_REG((pg), 0x27) 133 #define ISL7998X_REG_PX_DEC_VERT_CTL_1(pg) ISL7998X_REG((pg), 0x28) 134 #define ISL7998X_REG_PX_DEC_VERT_CTL_2(pg) ISL7998X_REG((pg), 0x29) 135 #define ISL7998X_REG_PX_DEC_CLR_KILL_LVL(pg) ISL7998X_REG((pg), 0x2a) 136 #define ISL7998X_REG_PX_DEC_COMB_FILTER_CTL(pg) ISL7998X_REG((pg), 0x2b) 137 #define ISL7998X_REG_PX_DEC_LUMA_DELAY(pg) ISL7998X_REG((pg), 0x2c) 138 #define ISL7998X_REG_PX_DEC_MISC1(pg) ISL7998X_REG((pg), 0x2d) 139 #define ISL7998X_REG_PX_DEC_MISC2(pg) ISL7998X_REG((pg), 0x2e) 140 #define ISL7998X_REG_PX_DEC_MISC3(pg) ISL7998X_REG((pg), 0x2f) 141 #define ISL7998X_REG_PX_DEC_MVSN(pg) ISL7998X_REG((pg), 0x30) 142 #define ISL7998X_REG_PX_DEC_CSTATUS2(pg) ISL7998X_REG((pg), 0x31) 143 #define ISL7998X_REG_PX_DEC_HFREF(pg) ISL7998X_REG((pg), 0x32) 144 #define ISL7998X_REG_PX_DEC_CLMD(pg) ISL7998X_REG((pg), 0x33) 145 #define ISL7998X_REG_PX_DEC_ID_DET_CTL(pg) ISL7998X_REG((pg), 0x34) 146 #define ISL7998X_REG_PX_DEC_CLCNTL(pg) ISL7998X_REG((pg), 0x35) 147 #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_1(pg) ISL7998X_REG((pg), 0x36) 148 #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_2(pg) ISL7998X_REG((pg), 0x37) 149 #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_3(pg) ISL7998X_REG((pg), 0x38) 150 #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_4(pg) ISL7998X_REG((pg), 0x39) 151 #define ISL7998X_REG_PX_DEC_SHORT_DET_CTL(pg) ISL7998X_REG((pg), 0x3a) 152 #define ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(pg) ISL7998X_REG((pg), 0x3b) 153 #define ISL7998X_REG_PX_DEC_AFE_TST_MUX_CTL(pg) ISL7998X_REG((pg), 0x3c) 154 #define ISL7998X_REG_PX_DEC_DATA_CONV(pg) ISL7998X_REG((pg), 0x3d) 155 #define ISL7998X_REG_PX_DEC_INTERNAL_TEST(pg) ISL7998X_REG((pg), 0x3f) 156 #define ISL7998X_REG_PX_DEC_H_DELAY_CTL(pg) ISL7998X_REG((pg), 0x43) 157 #define ISL7998X_REG_PX_DEC_H_DELAY_II_HI(pg) ISL7998X_REG((pg), 0x44) 158 #define ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(pg) ISL7998X_REG((pg), 0x45) 159 160 #define ISL7998X_REG_PX_ACA_CTL_1(pg) ISL7998X_REG((pg), 0x80) 161 #define ISL7998X_REG_PX_ACA_GAIN_CTL(pg) ISL7998X_REG((pg), 0x81) 162 #define ISL7998X_REG_PX_ACA_Y_AVG_HI_LIMIT(pg) ISL7998X_REG((pg), 0x82) 163 #define ISL7998X_REG_PX_ACA_Y_AVG_LO_LIMIT(pg) ISL7998X_REG((pg), 0x83) 164 #define ISL7998X_REG_PX_ACA_Y_DET_THRESHOLD(pg) ISL7998X_REG((pg), 0x84) 165 #define ISL7998X_REG_PX_ACA_BLACK_LVL(pg) ISL7998X_REG((pg), 0x85) 166 #define ISL7998X_REG_PX_ACA_CENTER_LVL(pg) ISL7998X_REG((pg), 0x86) 167 #define ISL7998X_REG_PX_ACA_WHITE_LVL(pg) ISL7998X_REG((pg), 0x87) 168 #define ISL7998X_REG_PX_ACA_MEAN_OFF_LIMIT(pg) ISL7998X_REG((pg), 0x88) 169 #define ISL7998X_REG_PX_ACA_MEAN_OFF_UPGAIN(pg) ISL7998X_REG((pg), 0x89) 170 #define ISL7998X_REG_PX_ACA_MEAN_OFF_SLOPE(pg) ISL7998X_REG((pg), 0x8a) 171 #define ISL7998X_REG_PX_ACA_MEAN_OFF_DNGAIN(pg) ISL7998X_REG((pg), 0x8b) 172 #define ISL7998X_REG_PX_ACA_DELTA_CO_THRES(pg) ISL7998X_REG((pg), 0x8c) 173 #define ISL7998X_REG_PX_ACA_DELTA_SLOPE(pg) ISL7998X_REG((pg), 0x8d) 174 #define ISL7998X_REG_PX_ACA_LO_HI_AVG_THRES(pg) ISL7998X_REG((pg), 0x8e) 175 #define ISL7998X_REG_PX_ACA_LO_MAX_LVL_CTL(pg) ISL7998X_REG((pg), 0x8f) 176 #define ISL7998X_REG_PX_ACA_HI_MAX_LVL_CTL(pg) ISL7998X_REG((pg), 0x90) 177 #define ISL7998X_REG_PX_ACA_LO_UPGAIN_CTL(pg) ISL7998X_REG((pg), 0x91) 178 #define ISL7998X_REG_PX_ACA_LO_DNGAIN_CTL(pg) ISL7998X_REG((pg), 0x92) 179 #define ISL7998X_REG_PX_ACA_HI_UPGAIN_CTL(pg) ISL7998X_REG((pg), 0x93) 180 #define ISL7998X_REG_PX_ACA_HI_DNGAIN_CTL(pg) ISL7998X_REG((pg), 0x94) 181 #define ISL7998X_REG_PX_ACA_LOPASS_FLT_COEF(pg) ISL7998X_REG((pg), 0x95) 182 #define ISL7998X_REG_PX_ACA_PDF_INDEX(pg) ISL7998X_REG((pg), 0x96) 183 #define ISL7998X_REG_PX_ACA_HIST_WIN_H_STT(pg) ISL7998X_REG((pg), 0x97) 184 #define ISL7998X_REG_PX_ACA_HIST_WIN_H_SZ1(pg) ISL7998X_REG((pg), 0x98) 185 #define ISL7998X_REG_PX_ACA_HIST_WIN_H_SZ2(pg) ISL7998X_REG((pg), 0x99) 186 #define ISL7998X_REG_PX_ACA_HIST_WIN_V_STT(pg) ISL7998X_REG((pg), 0x9a) 187 #define ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ1(pg) ISL7998X_REG((pg), 0x9b) 188 #define ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(pg) ISL7998X_REG((pg), 0x9c) 189 #define ISL7998X_REG_PX_ACA_Y_AVG(pg) ISL7998X_REG((pg), 0xa0) 190 #define ISL7998X_REG_PX_ACA_Y_AVG_LIM(pg) ISL7998X_REG((pg), 0xa1) 191 #define ISL7998X_REG_PX_ACA_LO_AVG(pg) ISL7998X_REG((pg), 0xa2) 192 #define ISL7998X_REG_PX_ACA_HI_AVG(pg) ISL7998X_REG((pg), 0xa3) 193 #define ISL7998X_REG_PX_ACA_Y_MAX(pg) ISL7998X_REG((pg), 0xa4) 194 #define ISL7998X_REG_PX_ACA_Y_MIN(pg) ISL7998X_REG((pg), 0xa5) 195 #define ISL7998X_REG_PX_ACA_MOFFSET(pg) ISL7998X_REG((pg), 0xa6) 196 #define ISL7998X_REG_PX_ACA_LO_GAIN(pg) ISL7998X_REG((pg), 0xa7) 197 #define ISL7998X_REG_PX_ACA_HI_GAIN(pg) ISL7998X_REG((pg), 0xa8) 198 #define ISL7998X_REG_PX_ACA_LL_SLOPE(pg) ISL7998X_REG((pg), 0xa9) 199 #define ISL7998X_REG_PX_ACA_LH_SLOPE(pg) ISL7998X_REG((pg), 0xaa) 200 #define ISL7998X_REG_PX_ACA_HL_SLOPE(pg) ISL7998X_REG((pg), 0xab) 201 #define ISL7998X_REG_PX_ACA_HH_SLOPE(pg) ISL7998X_REG((pg), 0xac) 202 #define ISL7998X_REG_PX_ACA_X_LOW(pg) ISL7998X_REG((pg), 0xad) 203 #define ISL7998X_REG_PX_ACA_X_MEAN(pg) ISL7998X_REG((pg), 0xae) 204 #define ISL7998X_REG_PX_ACA_X_HIGH(pg) ISL7998X_REG((pg), 0xaf) 205 #define ISL7998X_REG_PX_ACA_Y_LOW(pg) ISL7998X_REG((pg), 0xb0) 206 #define ISL7998X_REG_PX_ACA_Y_MEAN(pg) ISL7998X_REG((pg), 0xb1) 207 #define ISL7998X_REG_PX_ACA_Y_HIGH(pg) ISL7998X_REG((pg), 0xb2) 208 #define ISL7998X_REG_PX_ACA_CTL_2(pg) ISL7998X_REG((pg), 0xb3) 209 #define ISL7998X_REG_PX_ACA_CTL_3(pg) ISL7998X_REG((pg), 0xb4) 210 #define ISL7998X_REG_PX_ACA_CTL_4(pg) ISL7998X_REG((pg), 0xb5) 211 #define ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(pg) ISL7998X_REG((pg), 0xc0) 212 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TL_H(pg) ISL7998X_REG((pg), 0xc1) 213 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TL_L(pg) ISL7998X_REG((pg), 0xc2) 214 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TL_H(pg) ISL7998X_REG((pg), 0xc3) 215 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TL_L(pg) ISL7998X_REG((pg), 0xc4) 216 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TR_H(pg) ISL7998X_REG((pg), 0xc5) 217 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TR_L(pg) ISL7998X_REG((pg), 0xc6) 218 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TR_H(pg) ISL7998X_REG((pg), 0xc7) 219 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TR_L(pg) ISL7998X_REG((pg), 0xc8) 220 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BL_H(pg) ISL7998X_REG((pg), 0xc9) 221 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BL_L(pg) ISL7998X_REG((pg), 0xca) 222 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BL_H(pg) ISL7998X_REG((pg), 0xcb) 223 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BL_L(pg) ISL7998X_REG((pg), 0xcc) 224 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BR_H(pg) ISL7998X_REG((pg), 0xcd) 225 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BR_L(pg) ISL7998X_REG((pg), 0xce) 226 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BR_H(pg) ISL7998X_REG((pg), 0xcf) 227 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BR_L(pg) ISL7998X_REG((pg), 0xd0) 228 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_LM_H(pg) ISL7998X_REG((pg), 0xd1) 229 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_LM_L(pg) ISL7998X_REG((pg), 0xd2) 230 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_LM_H(pg) ISL7998X_REG((pg), 0xd3) 231 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_LM_L(pg) ISL7998X_REG((pg), 0xd4) 232 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TM_H(pg) ISL7998X_REG((pg), 0xd5) 233 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TM_L(pg) ISL7998X_REG((pg), 0xd6) 234 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TM_H(pg) ISL7998X_REG((pg), 0xd7) 235 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TM_L(pg) ISL7998X_REG((pg), 0xd8) 236 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BM_H(pg) ISL7998X_REG((pg), 0xd9) 237 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BM_L(pg) ISL7998X_REG((pg), 0xda) 238 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BM_H(pg) ISL7998X_REG((pg), 0xdb) 239 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BM_L(pg) ISL7998X_REG((pg), 0xdc) 240 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_RM_H(pg) ISL7998X_REG((pg), 0xdd) 241 #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_RM_L(pg) ISL7998X_REG((pg), 0xde) 242 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_RM_H(pg) ISL7998X_REG((pg), 0xdf) 243 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_RM_L(pg) ISL7998X_REG((pg), 0xe0) 244 #define ISL7998X_REG_PX_ACA_HIST_DATA_LO(pg) ISL7998X_REG((pg), 0xe1) 245 #define ISL7998X_REG_PX_ACA_HIST_DATA_MID(pg) ISL7998X_REG((pg), 0xe2) 246 #define ISL7998X_REG_PX_ACA_HIST_DATA_HI(pg) ISL7998X_REG((pg), 0xe3) 247 #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_CLR(pg) ISL7998X_REG((pg), 0xe4) 248 #define ISL7998X_REG_PX_ACA_FLEX_WIN_CB_CLR(pg) ISL7998X_REG((pg), 0xe5) 249 #define ISL7998X_REG_PX_ACA_FLEX_WIN_CR_CLR(pg) ISL7998X_REG((pg), 0xe6) 250 #define ISL7998X_REG_PX_ACA_XFER_HIST_HOST(pg) ISL7998X_REG((pg), 0xe7) 251 252 #define ISL7998X_REG_P5_LI_ENGINE_CTL ISL7998X_REG(5, 0x00) 253 #define ISL7998X_REG_P5_LI_ENGINE_LINE_CTL ISL7998X_REG(5, 0x01) 254 #define ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH ISL7998X_REG(5, 0x02) 255 #define ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL ISL7998X_REG(5, 0x03) 256 #define ISL7998X_REG_P5_LI_ENGINE_VC_ASSIGNMENT ISL7998X_REG(5, 0x04) 257 #define ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL ISL7998X_REG(5, 0x05) 258 #define ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL ISL7998X_REG(5, 0x06) 259 #define ISL7998X_REG_P5_MIPI_READ_START_CTL ISL7998X_REG(5, 0x07) 260 #define ISL7998X_REG_P5_PSEUDO_FRM_FIELD_CTL ISL7998X_REG(5, 0x08) 261 #define ISL7998X_REG_P5_ONE_FIELD_MODE_CTL ISL7998X_REG(5, 0x09) 262 #define ISL7998X_REG_P5_MIPI_INT_HW_TST_CTR ISL7998X_REG(5, 0x0a) 263 #define ISL7998X_REG_P5_TP_GEN_BAR_PATTERN ISL7998X_REG(5, 0x0b) 264 #define ISL7998X_REG_P5_MIPI_PCNT_PSFRM ISL7998X_REG(5, 0x0c) 265 #define ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL ISL7998X_REG(5, 0x0d) 266 #define ISL7998X_REG_P5_MIPI_VBLANK_PSFRM ISL7998X_REG(5, 0x0e) 267 #define ISL7998X_REG_P5_LI_ENGINE_CTL_2 ISL7998X_REG(5, 0x0f) 268 #define ISL7998X_REG_P5_MIPI_WCNT_1 ISL7998X_REG(5, 0x10) 269 #define ISL7998X_REG_P5_MIPI_WCNT_2 ISL7998X_REG(5, 0x11) 270 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_1 ISL7998X_REG(5, 0x12) 271 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_2 ISL7998X_REG(5, 0x13) 272 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_3 ISL7998X_REG(5, 0x14) 273 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_4 ISL7998X_REG(5, 0x15) 274 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_5 ISL7998X_REG(5, 0x16) 275 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_6 ISL7998X_REG(5, 0x17) 276 #define ISL7998X_REG_P5_MIPI_DPHY_PARAMS_1 ISL7998X_REG(5, 0x18) 277 #define ISL7998X_REG_P5_MIPI_DPHY_SOT_PERIOD ISL7998X_REG(5, 0x19) 278 #define ISL7998X_REG_P5_MIPI_DPHY_EOT_PERIOD ISL7998X_REG(5, 0x1a) 279 #define ISL7998X_REG_P5_MIPI_DPHY_PARAMS_2 ISL7998X_REG(5, 0x1b) 280 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_7 ISL7998X_REG(5, 0x1c) 281 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_8 ISL7998X_REG(5, 0x1d) 282 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_9 ISL7998X_REG(5, 0x1e) 283 #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_10 ISL7998X_REG(5, 0x1f) 284 #define ISL7998X_REG_P5_TP_GEN_MIPI ISL7998X_REG(5, 0x20) 285 #define ISL7998X_REG_P5_ESC_MODE_TIME_CTL ISL7998X_REG(5, 0x21) 286 #define ISL7998X_REG_P5_AUTO_TEST_ERR_DET ISL7998X_REG(5, 0x22) 287 #define ISL7998X_REG_P5_MIPI_TIMING ISL7998X_REG(5, 0x23) 288 #define ISL7998X_REG_P5_PIC_HEIGHT_HIGH ISL7998X_REG(5, 0x24) 289 #define ISL7998X_REG_P5_PIC_HEIGHT_LOW ISL7998X_REG(5, 0x25) 290 #define ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL ISL7998X_REG(5, 0x26) 291 #define ISL7998X_REG_P5_FIFO_THRSH_CNT_1 ISL7998X_REG(5, 0x28) 292 #define ISL7998X_REG_P5_FIFO_THRSH_CNT_2 ISL7998X_REG(5, 0x29) 293 #define ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1 ISL7998X_REG(5, 0x2a) 294 #define ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2 ISL7998X_REG(5, 0x2b) 295 #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_1 ISL7998X_REG(5, 0x2c) 296 #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_2 ISL7998X_REG(5, 0x2d) 297 #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_3 ISL7998X_REG(5, 0x2e) 298 #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_4 ISL7998X_REG(5, 0x2f) 299 #define ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_1 ISL7998X_REG(5, 0x30) 300 #define ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_2 ISL7998X_REG(5, 0x31) 301 #define ISL7998X_REG_P5_MIPI_ANA_CLK_CTL ISL7998X_REG(5, 0x32) 302 #define ISL7998X_REG_P5_PLL_ANA_STATUS ISL7998X_REG(5, 0x33) 303 #define ISL7998X_REG_P5_PLL_ANA_MISC_CTL ISL7998X_REG(5, 0x34) 304 #define ISL7998X_REG_P5_MIPI_ANA ISL7998X_REG(5, 0x35) 305 #define ISL7998X_REG_P5_PLL_ANA ISL7998X_REG(5, 0x36) 306 #define ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1 ISL7998X_REG(5, 0x38) 307 #define ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_2 ISL7998X_REG(5, 0x39) 308 #define ISL7998X_REG_P5_H_LINE_CNT_1 ISL7998X_REG(5, 0x3a) 309 #define ISL7998X_REG_P5_H_LINE_CNT_2 ISL7998X_REG(5, 0x3b) 310 #define ISL7998X_REG_P5_HIST_LINE_CNT_1 ISL7998X_REG(5, 0x3c) 311 #define ISL7998X_REG_P5_HIST_LINE_CNT_2 ISL7998X_REG(5, 0x3d) 312 313 static const struct reg_sequence isl7998x_init_seq_1[] = { 314 { ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN, 0xff }, 315 { ISL7998X_REG_PX_DEC_SDT(0x1), 0x00 }, 316 { ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x1), 0x03 }, 317 { ISL7998X_REG_PX_DEC_SDT(0x2), 0x00 }, 318 { ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x2), 0x03 }, 319 { ISL7998X_REG_PX_DEC_SDT(0x3), 0x00 }, 320 { ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x3), 0x03 }, 321 { ISL7998X_REG_PX_DEC_SDT(0x4), 0x00 }, 322 { ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x4), 0x03 }, 323 { ISL7998X_REG_P5_LI_ENGINE_CTL, 0x00 }, 324 { ISL7998X_REG_P0_SW_RESET_CTL, 0x1f, 10 }, 325 { ISL7998X_REG_P0_IO_BUFFER_CTL, 0x00 }, 326 { ISL7998X_REG_P0_MPP2_SYNC_CTL, 0xc9 }, 327 { ISL7998X_REG_P0_IRQ_SYNC_CTL, 0xc9 }, 328 { ISL7998X_REG_P0_CHAN_1_IRQ, 0x03 }, 329 { ISL7998X_REG_P0_CHAN_2_IRQ, 0x00 }, 330 { ISL7998X_REG_P0_CHAN_3_IRQ, 0x00 }, 331 { ISL7998X_REG_P0_CHAN_4_IRQ, 0x00 }, 332 { ISL7998X_REG_P5_LI_ENGINE_CTL, 0x02 }, 333 { ISL7998X_REG_P5_LI_ENGINE_LINE_CTL, 0x85 }, 334 { ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH, 0xa0 }, 335 { ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL, 0x18 }, 336 { ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL, 0x40 }, 337 { ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL, 0x40 }, 338 { ISL7998X_REG_P5_MIPI_WCNT_1, 0x05 }, 339 { ISL7998X_REG_P5_MIPI_WCNT_2, 0xa0 }, 340 { ISL7998X_REG_P5_TP_GEN_MIPI, 0x00 }, 341 { ISL7998X_REG_P5_ESC_MODE_TIME_CTL, 0x0c }, 342 { ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL, 0x00 }, 343 { ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1, 0x00 }, 344 { ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2, 0x19 }, 345 { ISL7998X_REG_P5_PSF_FIELD_END_CTL_1, 0x18 }, 346 { ISL7998X_REG_P5_PSF_FIELD_END_CTL_2, 0xf1 }, 347 { ISL7998X_REG_P5_PSF_FIELD_END_CTL_3, 0x00 }, 348 { ISL7998X_REG_P5_PSF_FIELD_END_CTL_4, 0xf1 }, 349 { ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_1, 0x00 }, 350 { ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_2, 0x00 }, 351 { ISL7998X_REG_P5_MIPI_ANA_CLK_CTL, 0x00 }, 352 { ISL7998X_REG_P5_PLL_ANA_STATUS, 0xc0 }, 353 { ISL7998X_REG_P5_PLL_ANA_MISC_CTL, 0x18 }, 354 { ISL7998X_REG_P5_PLL_ANA, 0x00 }, 355 { ISL7998X_REG_P0_SW_RESET_CTL, 0x10, 10 }, 356 /* Page 0xf means write to all of pages 1,2,3,4 */ 357 { ISL7998X_REG_PX_DEC_VDELAY_LO(0xf), 0x14 }, 358 { ISL7998X_REG_PX_DEC_MISC3(0xf), 0xe6 }, 359 { ISL7998X_REG_PX_DEC_CLMD(0xf), 0x85 }, 360 { ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(0xf), 0x11 }, 361 { ISL7998X_REG_PX_ACA_XFER_HIST_HOST(0xf), 0x00 }, 362 { ISL7998X_REG_P0_CLK_CTL_1, 0x1f }, 363 { ISL7998X_REG_P0_CLK_CTL_2, 0x43 }, 364 { ISL7998X_REG_P0_CLK_CTL_3, 0x4f }, 365 }; 366 367 static const struct reg_sequence isl7998x_init_seq_2[] = { 368 { ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL, 0x10 }, 369 { ISL7998X_REG_P5_LI_ENGINE_VC_ASSIGNMENT, 0xe4 }, 370 { ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL, 0x00 }, 371 { ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL, 0x60 }, 372 { ISL7998X_REG_P5_MIPI_READ_START_CTL, 0x2b }, 373 { ISL7998X_REG_P5_PSEUDO_FRM_FIELD_CTL, 0x02 }, 374 { ISL7998X_REG_P5_ONE_FIELD_MODE_CTL, 0x00 }, 375 { ISL7998X_REG_P5_MIPI_INT_HW_TST_CTR, 0x62 }, 376 { ISL7998X_REG_P5_TP_GEN_BAR_PATTERN, 0x02 }, 377 { ISL7998X_REG_P5_MIPI_PCNT_PSFRM, 0x36 }, 378 { ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL, 0x00 }, 379 { ISL7998X_REG_P5_MIPI_VBLANK_PSFRM, 0x6c }, 380 { ISL7998X_REG_P5_LI_ENGINE_CTL_2, 0x00 }, 381 { ISL7998X_REG_P5_MIPI_WCNT_1, 0x05 }, 382 { ISL7998X_REG_P5_MIPI_WCNT_2, 0xa0 }, 383 { ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_1, 0x77 }, 384 { ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_2, 0x17 }, 385 { ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_3, 0x08 }, 386 { ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_4, 0x38 }, 387 { ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_5, 0x14 }, 388 { ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_6, 0xf6 }, 389 { ISL7998X_REG_P5_MIPI_DPHY_PARAMS_1, 0x00 }, 390 { ISL7998X_REG_P5_MIPI_DPHY_SOT_PERIOD, 0x17 }, 391 { ISL7998X_REG_P5_MIPI_DPHY_EOT_PERIOD, 0x0a }, 392 { ISL7998X_REG_P5_MIPI_DPHY_PARAMS_2, 0x71 }, 393 { ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_7, 0x7a }, 394 { ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_8, 0x0f }, 395 { ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_9, 0x8c }, 396 { ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL, 0x08 }, 397 { ISL7998X_REG_P5_FIFO_THRSH_CNT_1, 0x01 }, 398 { ISL7998X_REG_P5_FIFO_THRSH_CNT_2, 0x0e }, 399 { ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1, 0x00 }, 400 { ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2, 0x00 }, 401 { ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1, 0x03 }, 402 { ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_2, 0xc0 }, 403 { ISL7998X_REG_P5_H_LINE_CNT_1, 0x06 }, 404 { ISL7998X_REG_P5_H_LINE_CNT_2, 0xb3 }, 405 { ISL7998X_REG_P5_HIST_LINE_CNT_1, 0x00 }, 406 { ISL7998X_REG_P5_HIST_LINE_CNT_2, 0xf1 }, 407 { ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL, 0x00 }, 408 { ISL7998X_REG_P5_MIPI_ANA, 0x00 }, 409 /* 410 * Wait a bit after reset so that the chip can capture a frame 411 * and update internal line counters. 412 */ 413 { ISL7998X_REG_P0_SW_RESET_CTL, 0x00, 50 }, 414 }; 415 416 enum isl7998x_pads { 417 ISL7998X_PAD_OUT, 418 ISL7998X_PAD_VIN1, 419 ISL7998X_PAD_VIN2, 420 ISL7998X_PAD_VIN3, 421 ISL7998X_PAD_VIN4, 422 ISL7998X_NUM_PADS 423 }; 424 425 struct isl7998x_datafmt { 426 u32 code; 427 enum v4l2_colorspace colorspace; 428 }; 429 430 static const struct isl7998x_datafmt isl7998x_colour_fmts[] = { 431 { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB }, 432 }; 433 434 /* Menu items for LINK_FREQ V4L2 control */ 435 static const s64 link_freq_menu_items[] = { 436 /* 1 channel, 1 lane or 2 channels, 2 lanes */ 437 108000000, 438 /* 2 channels, 1 lane or 4 channels, 2 lanes */ 439 216000000, 440 /* 4 channels, 1 lane */ 441 432000000, 442 }; 443 444 /* Menu items for TEST_PATTERN V4L2 control */ 445 static const char * const isl7998x_test_pattern_menu[] = { 446 "Disabled", 447 "Enabled", 448 }; 449 450 static const char * const isl7998x_test_pattern_bars[] = { 451 "bbbbwb", "bbbwwb", "bbwbwb", "bbwwwb", 452 }; 453 454 static const char * const isl7998x_test_pattern_colors[] = { 455 "Yellow", "Blue", "Green", "Pink", 456 }; 457 458 struct isl7998x_mode { 459 unsigned int width; 460 unsigned int height; 461 enum v4l2_field field; 462 }; 463 464 static const struct isl7998x_mode supported_modes[] = { 465 { 466 .width = 720, 467 .height = 576, 468 .field = V4L2_FIELD_SEQ_TB, 469 }, 470 { 471 .width = 720, 472 .height = 480, 473 .field = V4L2_FIELD_SEQ_BT, 474 }, 475 }; 476 477 static const struct isl7998x_video_std { 478 const v4l2_std_id norm; 479 unsigned int id; 480 const struct isl7998x_mode *mode; 481 } isl7998x_std_res[] = { 482 { V4L2_STD_NTSC_443, 483 ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_443, 484 &supported_modes[1] }, 485 { V4L2_STD_PAL_M, 486 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_M, 487 &supported_modes[1] }, 488 { V4L2_STD_PAL_Nc, 489 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_CN, 490 &supported_modes[0] }, 491 { V4L2_STD_PAL_N, 492 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL, 493 &supported_modes[0] }, 494 { V4L2_STD_PAL_60, 495 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_60, 496 &supported_modes[1] }, 497 { V4L2_STD_NTSC, 498 ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_M, 499 &supported_modes[1] }, 500 { V4L2_STD_PAL, 501 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL, 502 &supported_modes[0] }, 503 { V4L2_STD_SECAM, 504 ISL7998X_REG_PX_DEC_SDT_STANDARD_SECAM, 505 &supported_modes[0] }, 506 { V4L2_STD_UNKNOWN, 507 ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN, 508 &supported_modes[1] }, 509 }; 510 511 struct isl7998x { 512 struct v4l2_subdev subdev; 513 struct regmap *regmap; 514 struct gpio_desc *pd_gpio; 515 struct gpio_desc *rstb_gpio; 516 unsigned int nr_mipi_lanes; 517 u32 nr_inputs; 518 519 const struct isl7998x_datafmt *fmt; 520 v4l2_std_id norm; 521 struct media_pad pads[ISL7998X_NUM_PADS]; 522 523 int enabled; 524 525 /* protect fmt, norm, enabled */ 526 struct mutex lock; 527 528 struct v4l2_ctrl_handler ctrl_handler; 529 /* protect ctrl_handler */ 530 struct mutex ctrl_mutex; 531 532 /* V4L2 Controls */ 533 struct v4l2_ctrl *link_freq; 534 u8 test_pattern; 535 u8 test_pattern_bars; 536 u8 test_pattern_chans; 537 u8 test_pattern_color; 538 }; 539 540 static struct isl7998x *sd_to_isl7998x(struct v4l2_subdev *sd) 541 { 542 return container_of(sd, struct isl7998x, subdev); 543 } 544 545 static struct isl7998x *i2c_to_isl7998x(const struct i2c_client *client) 546 { 547 return sd_to_isl7998x(i2c_get_clientdata(client)); 548 } 549 550 static unsigned int isl7998x_norm_to_val(v4l2_std_id norm) 551 { 552 unsigned int i; 553 554 for (i = 0; i < ARRAY_SIZE(isl7998x_std_res); i++) 555 if (isl7998x_std_res[i].norm & norm) 556 break; 557 if (i == ARRAY_SIZE(isl7998x_std_res)) 558 return ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN; 559 560 return isl7998x_std_res[i].id; 561 } 562 563 static const struct isl7998x_mode *isl7998x_norm_to_mode(v4l2_std_id norm) 564 { 565 unsigned int i; 566 567 for (i = 0; i < ARRAY_SIZE(isl7998x_std_res); i++) 568 if (isl7998x_std_res[i].norm & norm) 569 break; 570 /* Use NTSC default resolution during standard detection */ 571 if (i == ARRAY_SIZE(isl7998x_std_res)) 572 return &supported_modes[1]; 573 574 return isl7998x_std_res[i].mode; 575 } 576 577 static int isl7998x_get_nr_inputs(struct device_node *of_node) 578 { 579 struct device_node *port; 580 unsigned int inputs = 0; 581 unsigned int i; 582 583 if (of_graph_get_endpoint_count(of_node) > ISL7998X_NUM_PADS) 584 return -EINVAL; 585 586 /* 587 * The driver does not provide means to remap the input ports. It 588 * always configures input ports to start from VID1. Ensure that the 589 * device tree is correct. 590 */ 591 for (i = ISL7998X_PAD_VIN1; i <= ISL7998X_PAD_VIN4; i++) { 592 port = of_graph_get_port_by_id(of_node, i); 593 if (!port) 594 continue; 595 596 inputs |= BIT(i); 597 of_node_put(port); 598 } 599 600 switch (inputs) { 601 case BIT(ISL7998X_PAD_VIN1): 602 return 1; 603 case BIT(ISL7998X_PAD_VIN1) | BIT(ISL7998X_PAD_VIN2): 604 return 2; 605 case BIT(ISL7998X_PAD_VIN1) | BIT(ISL7998X_PAD_VIN2) | 606 BIT(ISL7998X_PAD_VIN3) | BIT(ISL7998X_PAD_VIN4): 607 return 4; 608 default: 609 return -EINVAL; 610 } 611 } 612 613 static int isl7998x_wait_power_on(struct isl7998x *isl7998x) 614 { 615 struct device *dev = isl7998x->subdev.dev; 616 u32 chip_id; 617 int ret; 618 int err; 619 620 ret = read_poll_timeout(regmap_read, err, !err, 2000, 20000, false, 621 isl7998x->regmap, 622 ISL7998X_REG_P0_PRODUCT_ID_CODE, &chip_id); 623 if (ret) { 624 dev_err(dev, "timeout while waiting for ISL7998X\n"); 625 return ret; 626 } 627 628 dev_dbg(dev, "Found ISL799%x\n", chip_id); 629 630 return ret; 631 } 632 633 static int isl7998x_set_standard(struct isl7998x *isl7998x, v4l2_std_id norm) 634 { 635 const struct isl7998x_mode *mode = isl7998x_norm_to_mode(norm); 636 unsigned int val = isl7998x_norm_to_val(norm); 637 unsigned int width = mode->width; 638 unsigned int i; 639 int ret; 640 641 for (i = 0; i < ISL7998X_INPUTS; i++) { 642 ret = regmap_write_bits(isl7998x->regmap, 643 ISL7998X_REG_PX_DEC_SDT(i + 1), 644 ISL7998X_REG_PX_DEC_SDT_STANDARD, 645 val); 646 if (ret) 647 return ret; 648 } 649 650 ret = regmap_write(isl7998x->regmap, 651 ISL7998X_REG_P5_LI_ENGINE_LINE_CTL, 652 0x20 | ((width >> 7) & 0x1f)); 653 if (ret) 654 return ret; 655 656 ret = regmap_write(isl7998x->regmap, 657 ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH, 658 (width << 1) & 0xff); 659 if (ret) 660 return ret; 661 662 return 0; 663 } 664 665 static int isl7998x_init(struct isl7998x *isl7998x) 666 { 667 const unsigned int lanes = isl7998x->nr_mipi_lanes; 668 const u32 isl7998x_video_in_chan_map[] = { 0x00, 0x11, 0x02, 0x02 }; 669 const struct reg_sequence isl7998x_init_seq_custom[] = { 670 { ISL7998X_REG_P0_VIDEO_IN_CHAN_CTL, 671 isl7998x_video_in_chan_map[isl7998x->nr_inputs - 1] }, 672 { ISL7998X_REG_P0_CLK_CTL_4, 673 (lanes == 1) ? 0x40 : 0x41 }, 674 { ISL7998X_REG_P5_LI_ENGINE_CTL, 675 (lanes == 1) ? 0x01 : 0x02 }, 676 }; 677 struct device *dev = isl7998x->subdev.dev; 678 struct regmap *regmap = isl7998x->regmap; 679 int ret; 680 681 dev_dbg(dev, "configuring %d lanes for %d inputs (norm %s)\n", 682 isl7998x->nr_mipi_lanes, isl7998x->nr_inputs, 683 v4l2_norm_to_name(isl7998x->norm)); 684 685 ret = regmap_register_patch(regmap, isl7998x_init_seq_1, 686 ARRAY_SIZE(isl7998x_init_seq_1)); 687 if (ret) 688 return ret; 689 690 mutex_lock(&isl7998x->lock); 691 ret = isl7998x_set_standard(isl7998x, isl7998x->norm); 692 mutex_unlock(&isl7998x->lock); 693 if (ret) 694 return ret; 695 696 ret = regmap_register_patch(regmap, isl7998x_init_seq_custom, 697 ARRAY_SIZE(isl7998x_init_seq_custom)); 698 if (ret) 699 return ret; 700 701 return regmap_register_patch(regmap, isl7998x_init_seq_2, 702 ARRAY_SIZE(isl7998x_init_seq_2)); 703 } 704 705 static int isl7998x_set_test_pattern(struct isl7998x *isl7998x) 706 { 707 const struct reg_sequence isl7998x_init_seq_tpg_off[] = { 708 { ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL, 0 }, 709 { ISL7998X_REG_P5_LI_ENGINE_CTL_2, 0 } 710 }; 711 const struct reg_sequence isl7998x_init_seq_tpg_on[] = { 712 { ISL7998X_REG_P5_TP_GEN_BAR_PATTERN, 713 isl7998x->test_pattern_bars << 6 }, 714 { ISL7998X_REG_P5_LI_ENGINE_CTL_2, 715 isl7998x->norm & V4L2_STD_PAL ? BIT(2) : 0 }, 716 { ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL, 717 (isl7998x->test_pattern_chans << 4) | 718 (isl7998x->test_pattern_color << 2) } 719 }; 720 struct device *dev = isl7998x->subdev.dev; 721 struct regmap *regmap = isl7998x->regmap; 722 int ret; 723 724 if (pm_runtime_get_if_in_use(dev) <= 0) 725 return 0; 726 727 if (isl7998x->test_pattern != 0) { 728 dev_dbg(dev, "enabling test pattern: channels 0x%x, %s, %s\n", 729 isl7998x->test_pattern_chans, 730 isl7998x_test_pattern_bars[isl7998x->test_pattern_bars], 731 isl7998x_test_pattern_colors[isl7998x->test_pattern_color]); 732 ret = regmap_register_patch(regmap, isl7998x_init_seq_tpg_on, 733 ARRAY_SIZE(isl7998x_init_seq_tpg_on)); 734 } else { 735 ret = regmap_register_patch(regmap, isl7998x_init_seq_tpg_off, 736 ARRAY_SIZE(isl7998x_init_seq_tpg_off)); 737 } 738 739 pm_runtime_put(dev); 740 741 return ret; 742 } 743 744 #ifdef CONFIG_VIDEO_ADV_DEBUG 745 static int isl7998x_g_register(struct v4l2_subdev *sd, 746 struct v4l2_dbg_register *reg) 747 { 748 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 749 int ret; 750 u32 val; 751 752 ret = regmap_read(isl7998x->regmap, reg->reg, &val); 753 if (ret) 754 return ret; 755 756 reg->size = 1; 757 reg->val = val; 758 759 return 0; 760 } 761 762 static int isl7998x_s_register(struct v4l2_subdev *sd, 763 const struct v4l2_dbg_register *reg) 764 { 765 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 766 767 return regmap_write(isl7998x->regmap, reg->reg, reg->val); 768 } 769 #endif 770 771 static int isl7998x_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm) 772 { 773 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 774 775 mutex_lock(&isl7998x->lock); 776 *norm = isl7998x->norm; 777 mutex_unlock(&isl7998x->lock); 778 779 return 0; 780 } 781 782 static int isl7998x_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) 783 { 784 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 785 struct i2c_client *client = v4l2_get_subdevdata(sd); 786 struct device *dev = &client->dev; 787 int ret = 0; 788 789 mutex_lock(&isl7998x->lock); 790 if (isl7998x->enabled) { 791 ret = -EBUSY; 792 mutex_unlock(&isl7998x->lock); 793 return ret; 794 } 795 isl7998x->norm = norm; 796 mutex_unlock(&isl7998x->lock); 797 798 if (pm_runtime_get_if_in_use(dev) <= 0) 799 return ret; 800 801 ret = isl7998x_set_standard(isl7998x, norm); 802 803 pm_runtime_put(dev); 804 805 return ret; 806 } 807 808 static int isl7998x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) 809 { 810 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 811 struct i2c_client *client = v4l2_get_subdevdata(sd); 812 struct device *dev = &client->dev; 813 unsigned int std_id[ISL7998X_INPUTS]; 814 unsigned int i; 815 int ret; 816 u32 reg; 817 818 ret = pm_runtime_resume_and_get(dev); 819 if (ret) 820 return ret; 821 822 dev_dbg(dev, "starting video standard detection\n"); 823 824 mutex_lock(&isl7998x->lock); 825 if (isl7998x->enabled) { 826 ret = -EBUSY; 827 goto out_unlock; 828 } 829 830 ret = isl7998x_set_standard(isl7998x, V4L2_STD_UNKNOWN); 831 if (ret) 832 goto out_unlock; 833 834 for (i = 0; i < ISL7998X_INPUTS; i++) { 835 ret = regmap_write(isl7998x->regmap, 836 ISL7998X_REG_PX_DEC_SDTR(i + 1), 837 ISL7998X_REG_PX_DEC_SDTR_ATSTART); 838 if (ret) 839 goto out_reset_std; 840 } 841 842 for (i = 0; i < ISL7998X_INPUTS; i++) { 843 ret = regmap_read_poll_timeout(isl7998x->regmap, 844 ISL7998X_REG_PX_DEC_SDT(i + 1), 845 reg, 846 !(reg & ISL7998X_REG_PX_DEC_SDT_DET), 847 2000, 500 * USEC_PER_MSEC); 848 if (ret) 849 goto out_reset_std; 850 std_id[i] = FIELD_GET(ISL7998X_REG_PX_DEC_SDT_NOW, reg); 851 } 852 853 /* 854 * According to Renesas FAE, all input cameras must have the 855 * same standard on this chip. 856 */ 857 for (i = 0; i < isl7998x->nr_inputs; i++) { 858 dev_dbg(dev, "input %d: detected %s\n", 859 i, v4l2_norm_to_name(isl7998x_std_res[std_id[i]].norm)); 860 if (std_id[0] != std_id[i]) 861 dev_warn(dev, 862 "incompatible standards: %s on input %d (expected %s)\n", 863 v4l2_norm_to_name(isl7998x_std_res[std_id[i]].norm), i, 864 v4l2_norm_to_name(isl7998x_std_res[std_id[0]].norm)); 865 } 866 867 *std = isl7998x_std_res[std_id[0]].norm; 868 869 out_reset_std: 870 isl7998x_set_standard(isl7998x, isl7998x->norm); 871 out_unlock: 872 mutex_unlock(&isl7998x->lock); 873 pm_runtime_put(dev); 874 875 return ret; 876 } 877 878 static int isl7998x_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *std) 879 { 880 *std = V4L2_STD_ALL; 881 882 return 0; 883 } 884 885 static int isl7998x_g_input_status(struct v4l2_subdev *sd, u32 *status) 886 { 887 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 888 struct i2c_client *client = v4l2_get_subdevdata(sd); 889 struct device *dev = &client->dev; 890 unsigned int i; 891 int ret = 0; 892 u32 reg; 893 894 if (!pm_runtime_active(dev)) { 895 *status |= V4L2_IN_ST_NO_POWER; 896 return 0; 897 } 898 899 for (i = 0; i < isl7998x->nr_inputs; i++) { 900 ret = regmap_read(isl7998x->regmap, 901 ISL7998X_REG_PX_DEC_STATUS_1(i + 1), ®); 902 if (!ret) { 903 if (reg & ISL7998X_REG_PX_DEC_STATUS_1_VDLOSS) 904 *status |= V4L2_IN_ST_NO_SIGNAL; 905 if (!(reg & ISL7998X_REG_PX_DEC_STATUS_1_HLOCK)) 906 *status |= V4L2_IN_ST_NO_H_LOCK; 907 if (!(reg & ISL7998X_REG_PX_DEC_STATUS_1_VLOCK)) 908 *status |= V4L2_IN_ST_NO_V_LOCK; 909 } 910 } 911 912 return ret; 913 } 914 915 static int isl7998x_s_stream(struct v4l2_subdev *sd, int enable) 916 { 917 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 918 struct i2c_client *client = v4l2_get_subdevdata(sd); 919 struct device *dev = &client->dev; 920 int ret = 0; 921 u32 reg; 922 923 dev_dbg(dev, "stream %s\n", enable ? "ON" : "OFF"); 924 925 mutex_lock(&isl7998x->lock); 926 if (isl7998x->enabled == enable) 927 goto out; 928 isl7998x->enabled = enable; 929 930 if (enable) { 931 ret = isl7998x_set_test_pattern(isl7998x); 932 if (ret) 933 goto out; 934 } 935 936 regmap_read(isl7998x->regmap, 937 ISL7998X_REG_P5_LI_ENGINE_CTL, ®); 938 if (enable) 939 reg &= ~BIT(7); 940 else 941 reg |= BIT(7); 942 ret = regmap_write(isl7998x->regmap, 943 ISL7998X_REG_P5_LI_ENGINE_CTL, reg); 944 945 out: 946 mutex_unlock(&isl7998x->lock); 947 948 return ret; 949 } 950 951 static int isl7998x_pre_streamon(struct v4l2_subdev *sd, u32 flags) 952 { 953 struct i2c_client *client = v4l2_get_subdevdata(sd); 954 struct device *dev = &client->dev; 955 956 return pm_runtime_resume_and_get(dev); 957 } 958 959 static int isl7998x_post_streamoff(struct v4l2_subdev *sd) 960 { 961 struct i2c_client *client = v4l2_get_subdevdata(sd); 962 struct device *dev = &client->dev; 963 964 pm_runtime_put(dev); 965 966 return 0; 967 } 968 969 static int isl7998x_enum_mbus_code(struct v4l2_subdev *sd, 970 struct v4l2_subdev_state *sd_state, 971 struct v4l2_subdev_mbus_code_enum *code) 972 { 973 if (code->index >= ARRAY_SIZE(isl7998x_colour_fmts)) 974 return -EINVAL; 975 976 code->code = isl7998x_colour_fmts[code->index].code; 977 978 return 0; 979 } 980 981 static int isl7998x_enum_frame_size(struct v4l2_subdev *sd, 982 struct v4l2_subdev_state *sd_state, 983 struct v4l2_subdev_frame_size_enum *fse) 984 { 985 if (fse->index >= ARRAY_SIZE(supported_modes)) 986 return -EINVAL; 987 988 if (fse->code != isl7998x_colour_fmts[0].code) 989 return -EINVAL; 990 991 fse->min_width = supported_modes[fse->index].width; 992 fse->max_width = fse->min_width; 993 fse->min_height = supported_modes[fse->index].height; 994 fse->max_height = fse->min_height; 995 996 return 0; 997 } 998 999 static int isl7998x_get_fmt(struct v4l2_subdev *sd, 1000 struct v4l2_subdev_state *sd_state, 1001 struct v4l2_subdev_format *format) 1002 { 1003 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 1004 struct v4l2_mbus_framefmt *mf = &format->format; 1005 const struct isl7998x_mode *mode; 1006 1007 mutex_lock(&isl7998x->lock); 1008 1009 if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 1010 format->format = *v4l2_subdev_get_try_format(sd, sd_state, 1011 format->pad); 1012 goto out; 1013 } 1014 1015 mode = isl7998x_norm_to_mode(isl7998x->norm); 1016 1017 mf->width = mode->width; 1018 mf->height = mode->height; 1019 mf->code = isl7998x->fmt->code; 1020 mf->field = mode->field; 1021 mf->colorspace = 0; 1022 1023 out: 1024 mutex_unlock(&isl7998x->lock); 1025 1026 return 0; 1027 } 1028 1029 static int isl7998x_set_fmt(struct v4l2_subdev *sd, 1030 struct v4l2_subdev_state *sd_state, 1031 struct v4l2_subdev_format *format) 1032 { 1033 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 1034 struct v4l2_mbus_framefmt *mf = &format->format; 1035 const struct isl7998x_mode *mode; 1036 1037 mutex_lock(&isl7998x->lock); 1038 1039 mode = isl7998x_norm_to_mode(isl7998x->norm); 1040 1041 mf->width = mode->width; 1042 mf->height = mode->height; 1043 mf->code = isl7998x->fmt->code; 1044 mf->field = mode->field; 1045 1046 if (format->which == V4L2_SUBDEV_FORMAT_TRY) 1047 *v4l2_subdev_get_try_format(sd, sd_state, format->pad) = format->format; 1048 1049 mutex_unlock(&isl7998x->lock); 1050 1051 return 0; 1052 } 1053 1054 static int isl7998x_set_ctrl(struct v4l2_ctrl *ctrl) 1055 { 1056 struct isl7998x *isl7998x = container_of(ctrl->handler, 1057 struct isl7998x, ctrl_handler); 1058 int ret = 0; 1059 1060 switch (ctrl->id) { 1061 case V4L2_CID_TEST_PATTERN_BARS: 1062 mutex_lock(&isl7998x->lock); 1063 isl7998x->test_pattern_bars = ctrl->val & 0x3; 1064 ret = isl7998x_set_test_pattern(isl7998x); 1065 mutex_unlock(&isl7998x->lock); 1066 break; 1067 case V4L2_CID_TEST_PATTERN_CHANNELS: 1068 mutex_lock(&isl7998x->lock); 1069 isl7998x->test_pattern_chans = ctrl->val & 0xf; 1070 ret = isl7998x_set_test_pattern(isl7998x); 1071 mutex_unlock(&isl7998x->lock); 1072 break; 1073 case V4L2_CID_TEST_PATTERN_COLOR: 1074 mutex_lock(&isl7998x->lock); 1075 isl7998x->test_pattern_color = ctrl->val & 0x3; 1076 ret = isl7998x_set_test_pattern(isl7998x); 1077 mutex_unlock(&isl7998x->lock); 1078 break; 1079 case V4L2_CID_TEST_PATTERN: 1080 mutex_lock(&isl7998x->lock); 1081 isl7998x->test_pattern = ctrl->val; 1082 ret = isl7998x_set_test_pattern(isl7998x); 1083 mutex_unlock(&isl7998x->lock); 1084 break; 1085 } 1086 1087 return ret; 1088 } 1089 1090 static const struct v4l2_subdev_core_ops isl7998x_subdev_core_ops = { 1091 #ifdef CONFIG_VIDEO_ADV_DEBUG 1092 .g_register = isl7998x_g_register, 1093 .s_register = isl7998x_s_register, 1094 #endif 1095 }; 1096 1097 static const struct v4l2_subdev_video_ops isl7998x_subdev_video_ops = { 1098 .g_std = isl7998x_g_std, 1099 .s_std = isl7998x_s_std, 1100 .querystd = isl7998x_querystd, 1101 .g_tvnorms = isl7998x_g_tvnorms, 1102 .g_input_status = isl7998x_g_input_status, 1103 .s_stream = isl7998x_s_stream, 1104 .pre_streamon = isl7998x_pre_streamon, 1105 .post_streamoff = isl7998x_post_streamoff, 1106 }; 1107 1108 static const struct v4l2_subdev_pad_ops isl7998x_subdev_pad_ops = { 1109 .enum_mbus_code = isl7998x_enum_mbus_code, 1110 .enum_frame_size = isl7998x_enum_frame_size, 1111 .get_fmt = isl7998x_get_fmt, 1112 .set_fmt = isl7998x_set_fmt, 1113 }; 1114 1115 static const struct v4l2_subdev_ops isl7998x_subdev_ops = { 1116 .core = &isl7998x_subdev_core_ops, 1117 .video = &isl7998x_subdev_video_ops, 1118 .pad = &isl7998x_subdev_pad_ops, 1119 }; 1120 1121 static const struct media_entity_operations isl7998x_entity_ops = { 1122 .link_validate = v4l2_subdev_link_validate, 1123 }; 1124 1125 static const struct v4l2_ctrl_ops isl7998x_ctrl_ops = { 1126 .s_ctrl = isl7998x_set_ctrl, 1127 }; 1128 1129 static const struct v4l2_ctrl_config isl7998x_ctrls[] = { 1130 { 1131 .ops = &isl7998x_ctrl_ops, 1132 .id = V4L2_CID_TEST_PATTERN_BARS, 1133 .type = V4L2_CTRL_TYPE_MENU, 1134 .name = "Test Pattern Bars", 1135 .max = ARRAY_SIZE(isl7998x_test_pattern_bars) - 1, 1136 .def = 0, 1137 .qmenu = isl7998x_test_pattern_bars, 1138 }, { 1139 .ops = &isl7998x_ctrl_ops, 1140 .id = V4L2_CID_TEST_PATTERN_CHANNELS, 1141 .type = V4L2_CTRL_TYPE_INTEGER, 1142 .name = "Test Pattern Channels", 1143 .min = 0, 1144 .max = 0xf, 1145 .step = 1, 1146 .def = 0xf, 1147 .flags = 0, 1148 }, { 1149 .ops = &isl7998x_ctrl_ops, 1150 .id = V4L2_CID_TEST_PATTERN_COLOR, 1151 .type = V4L2_CTRL_TYPE_MENU, 1152 .name = "Test Pattern Color", 1153 .max = ARRAY_SIZE(isl7998x_test_pattern_colors) - 1, 1154 .def = 0, 1155 .qmenu = isl7998x_test_pattern_colors, 1156 }, 1157 }; 1158 1159 #define ISL7998X_REG_DECODER_ACA_READABLE_RANGE(page) \ 1160 /* Decoder range */ \ 1161 regmap_reg_range(ISL7998X_REG_PX_DEC_INPUT_FMT(page), \ 1162 ISL7998X_REG_PX_DEC_HS_DELAY_CTL(page)), \ 1163 regmap_reg_range(ISL7998X_REG_PX_DEC_ANCTL(page), \ 1164 ISL7998X_REG_PX_DEC_CSC_CTL(page)), \ 1165 regmap_reg_range(ISL7998X_REG_PX_DEC_BRIGHT(page), \ 1166 ISL7998X_REG_PX_DEC_HUE(page)), \ 1167 regmap_reg_range(ISL7998X_REG_PX_DEC_VERT_PEAK(page), \ 1168 ISL7998X_REG_PX_DEC_CORING(page)), \ 1169 regmap_reg_range(ISL7998X_REG_PX_DEC_SDT(page), \ 1170 ISL7998X_REG_PX_DEC_SDTR(page)), \ 1171 regmap_reg_range(ISL7998X_REG_PX_DEC_CLMPG(page), \ 1172 ISL7998X_REG_PX_DEC_DATA_CONV(page)), \ 1173 regmap_reg_range(ISL7998X_REG_PX_DEC_INTERNAL_TEST(page), \ 1174 ISL7998X_REG_PX_DEC_INTERNAL_TEST(page)), \ 1175 regmap_reg_range(ISL7998X_REG_PX_DEC_H_DELAY_CTL(page), \ 1176 ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(page)), \ 1177 /* ACA range */ \ 1178 regmap_reg_range(ISL7998X_REG_PX_ACA_CTL_1(page), \ 1179 ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(page)), \ 1180 regmap_reg_range(ISL7998X_REG_PX_ACA_Y_AVG(page), \ 1181 ISL7998X_REG_PX_ACA_CTL_4(page)), \ 1182 regmap_reg_range(ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(page), \ 1183 ISL7998X_REG_PX_ACA_XFER_HIST_HOST(page)), \ 1184 regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(page), \ 1185 ISL7998X_REG_PX_DEC_PAGE(page)) 1186 1187 #define ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(page) \ 1188 /* Decoder range */ \ 1189 regmap_reg_range(ISL7998X_REG_PX_DEC_INPUT_FMT(page), \ 1190 ISL7998X_REG_PX_DEC_INPUT_FMT(page)), \ 1191 regmap_reg_range(ISL7998X_REG_PX_DEC_HS_DELAY_CTL(page), \ 1192 ISL7998X_REG_PX_DEC_HS_DELAY_CTL(page)), \ 1193 regmap_reg_range(ISL7998X_REG_PX_DEC_ANCTL(page), \ 1194 ISL7998X_REG_PX_DEC_CSC_CTL(page)), \ 1195 regmap_reg_range(ISL7998X_REG_PX_DEC_BRIGHT(page), \ 1196 ISL7998X_REG_PX_DEC_HUE(page)), \ 1197 regmap_reg_range(ISL7998X_REG_PX_DEC_VERT_PEAK(page), \ 1198 ISL7998X_REG_PX_DEC_CORING(page)), \ 1199 regmap_reg_range(ISL7998X_REG_PX_DEC_SDT(page), \ 1200 ISL7998X_REG_PX_DEC_SDTR(page)), \ 1201 regmap_reg_range(ISL7998X_REG_PX_DEC_CLMPG(page), \ 1202 ISL7998X_REG_PX_DEC_MISC3(page)), \ 1203 regmap_reg_range(ISL7998X_REG_PX_DEC_CLMD(page), \ 1204 ISL7998X_REG_PX_DEC_DATA_CONV(page)), \ 1205 regmap_reg_range(ISL7998X_REG_PX_DEC_INTERNAL_TEST(page), \ 1206 ISL7998X_REG_PX_DEC_INTERNAL_TEST(page)), \ 1207 regmap_reg_range(ISL7998X_REG_PX_DEC_H_DELAY_CTL(page), \ 1208 ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(page)), \ 1209 /* ACA range */ \ 1210 regmap_reg_range(ISL7998X_REG_PX_ACA_CTL_1(page), \ 1211 ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(page)), \ 1212 regmap_reg_range(ISL7998X_REG_PX_ACA_CTL_2(page), \ 1213 ISL7998X_REG_PX_ACA_CTL_4(page)), \ 1214 regmap_reg_range(ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(page), \ 1215 ISL7998X_REG_PX_ACA_HIST_DATA_LO(page)), \ 1216 regmap_reg_range(ISL7998X_REG_PX_ACA_XFER_HIST_HOST(page), \ 1217 ISL7998X_REG_PX_ACA_XFER_HIST_HOST(page)), \ 1218 regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(page), \ 1219 ISL7998X_REG_PX_DEC_PAGE(page)) 1220 1221 #define ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(page) \ 1222 /* Decoder range */ \ 1223 regmap_reg_range(ISL7998X_REG_PX_DEC_STATUS_1(page), \ 1224 ISL7998X_REG_PX_DEC_STATUS_1(page)), \ 1225 regmap_reg_range(ISL7998X_REG_PX_DEC_SDT(page), \ 1226 ISL7998X_REG_PX_DEC_SDT(page)), \ 1227 regmap_reg_range(ISL7998X_REG_PX_DEC_MVSN(page), \ 1228 ISL7998X_REG_PX_DEC_HFREF(page)), \ 1229 /* ACA range */ \ 1230 regmap_reg_range(ISL7998X_REG_PX_ACA_Y_AVG(page), \ 1231 ISL7998X_REG_PX_ACA_Y_HIGH(page)), \ 1232 regmap_reg_range(ISL7998X_REG_PX_ACA_HIST_DATA_LO(page), \ 1233 ISL7998X_REG_PX_ACA_FLEX_WIN_CR_CLR(page)) 1234 1235 static const struct regmap_range isl7998x_readable_ranges[] = { 1236 regmap_reg_range(ISL7998X_REG_P0_PRODUCT_ID_CODE, 1237 ISL7998X_REG_P0_IRQ_SYNC_CTL), 1238 regmap_reg_range(ISL7998X_REG_P0_INTERRUPT_STATUS, 1239 ISL7998X_REG_P0_CLOCK_DELAY), 1240 regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(0), 1241 ISL7998X_REG_PX_DEC_PAGE(0)), 1242 1243 ISL7998X_REG_DECODER_ACA_READABLE_RANGE(1), 1244 ISL7998X_REG_DECODER_ACA_READABLE_RANGE(2), 1245 ISL7998X_REG_DECODER_ACA_READABLE_RANGE(3), 1246 ISL7998X_REG_DECODER_ACA_READABLE_RANGE(4), 1247 1248 regmap_reg_range(ISL7998X_REG_P5_LI_ENGINE_CTL, 1249 ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL), 1250 regmap_reg_range(ISL7998X_REG_P5_FIFO_THRSH_CNT_1, 1251 ISL7998X_REG_P5_PLL_ANA), 1252 regmap_reg_range(ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1, 1253 ISL7998X_REG_P5_HIST_LINE_CNT_2), 1254 regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(5), 1255 ISL7998X_REG_PX_DEC_PAGE(5)), 1256 }; 1257 1258 static const struct regmap_range isl7998x_writeable_ranges[] = { 1259 regmap_reg_range(ISL7998X_REG_P0_SW_RESET_CTL, 1260 ISL7998X_REG_P0_IRQ_SYNC_CTL), 1261 regmap_reg_range(ISL7998X_REG_P0_CHAN_1_IRQ, 1262 ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN), 1263 regmap_reg_range(ISL7998X_REG_P0_CLOCK_DELAY, 1264 ISL7998X_REG_P0_CLOCK_DELAY), 1265 regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(0), 1266 ISL7998X_REG_PX_DEC_PAGE(0)), 1267 1268 ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(1), 1269 ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(2), 1270 ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(3), 1271 ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(4), 1272 1273 regmap_reg_range(ISL7998X_REG_P5_LI_ENGINE_CTL, 1274 ISL7998X_REG_P5_ESC_MODE_TIME_CTL), 1275 regmap_reg_range(ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL, 1276 ISL7998X_REG_P5_PLL_ANA), 1277 regmap_reg_range(ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1, 1278 ISL7998X_REG_P5_HIST_LINE_CNT_2), 1279 regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(5), 1280 ISL7998X_REG_PX_DEC_PAGE(5)), 1281 1282 ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(0xf), 1283 }; 1284 1285 static const struct regmap_range isl7998x_volatile_ranges[] = { 1286 /* Product id code register is used to check availability */ 1287 regmap_reg_range(ISL7998X_REG_P0_PRODUCT_ID_CODE, 1288 ISL7998X_REG_P0_PRODUCT_ID_CODE), 1289 regmap_reg_range(ISL7998X_REG_P0_MPP1_SYNC_CTL, 1290 ISL7998X_REG_P0_IRQ_SYNC_CTL), 1291 regmap_reg_range(ISL7998X_REG_P0_INTERRUPT_STATUS, 1292 ISL7998X_REG_P0_INTERRUPT_STATUS), 1293 regmap_reg_range(ISL7998X_REG_P0_CHAN_1_STATUS, 1294 ISL7998X_REG_P0_SHORT_DIAG_STATUS), 1295 1296 ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(1), 1297 ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(2), 1298 ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(3), 1299 ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(4), 1300 1301 regmap_reg_range(ISL7998X_REG_P5_AUTO_TEST_ERR_DET, 1302 ISL7998X_REG_P5_PIC_HEIGHT_LOW), 1303 }; 1304 1305 static const struct regmap_access_table isl7998x_readable_table = { 1306 .yes_ranges = isl7998x_readable_ranges, 1307 .n_yes_ranges = ARRAY_SIZE(isl7998x_readable_ranges), 1308 }; 1309 1310 static const struct regmap_access_table isl7998x_writeable_table = { 1311 .yes_ranges = isl7998x_writeable_ranges, 1312 .n_yes_ranges = ARRAY_SIZE(isl7998x_writeable_ranges), 1313 }; 1314 1315 static const struct regmap_access_table isl7998x_volatile_table = { 1316 .yes_ranges = isl7998x_volatile_ranges, 1317 .n_yes_ranges = ARRAY_SIZE(isl7998x_volatile_ranges), 1318 }; 1319 1320 static const struct regmap_range_cfg isl7998x_ranges[] = { 1321 { 1322 .range_min = ISL7998X_REG_PN_BASE(0), 1323 .range_max = ISL7998X_REG_PX_ACA_XFER_HIST_HOST(0xf), 1324 .selector_reg = ISL7998X_REG_PX_DEC_PAGE(0), 1325 .selector_mask = ISL7998X_REG_PX_DEC_PAGE_MASK, 1326 .window_start = 0, 1327 .window_len = 256, 1328 } 1329 }; 1330 1331 static const struct regmap_config isl7998x_regmap = { 1332 .reg_bits = 8, 1333 .val_bits = 8, 1334 .max_register = ISL7998X_REG_PX_ACA_XFER_HIST_HOST(0xf), 1335 .ranges = isl7998x_ranges, 1336 .num_ranges = ARRAY_SIZE(isl7998x_ranges), 1337 .rd_table = &isl7998x_readable_table, 1338 .wr_table = &isl7998x_writeable_table, 1339 .volatile_table = &isl7998x_volatile_table, 1340 .cache_type = REGCACHE_RBTREE, 1341 }; 1342 1343 static int isl7998x_mc_init(struct isl7998x *isl7998x) 1344 { 1345 unsigned int i; 1346 1347 isl7998x->subdev.entity.ops = &isl7998x_entity_ops; 1348 isl7998x->subdev.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; 1349 1350 isl7998x->pads[ISL7998X_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; 1351 for (i = ISL7998X_PAD_VIN1; i < ISL7998X_NUM_PADS; i++) 1352 isl7998x->pads[i].flags = MEDIA_PAD_FL_SINK; 1353 1354 return media_entity_pads_init(&isl7998x->subdev.entity, 1355 ISL7998X_NUM_PADS, 1356 isl7998x->pads); 1357 } 1358 1359 static int get_link_freq_menu_index(unsigned int lanes, 1360 unsigned int inputs) 1361 { 1362 int ret = -EINVAL; 1363 1364 switch (lanes) { 1365 case 1: 1366 if (inputs == 1) 1367 ret = 0; 1368 if (inputs == 2) 1369 ret = 1; 1370 if (inputs == 4) 1371 ret = 2; 1372 break; 1373 case 2: 1374 if (inputs == 2) 1375 ret = 0; 1376 if (inputs == 4) 1377 ret = 1; 1378 break; 1379 default: 1380 break; 1381 } 1382 1383 return ret; 1384 } 1385 1386 static void isl7998x_remove_controls(struct isl7998x *isl7998x) 1387 { 1388 v4l2_ctrl_handler_free(&isl7998x->ctrl_handler); 1389 mutex_destroy(&isl7998x->ctrl_mutex); 1390 } 1391 1392 static int isl7998x_init_controls(struct isl7998x *isl7998x) 1393 { 1394 struct v4l2_subdev *sd = &isl7998x->subdev; 1395 int link_freq_index; 1396 unsigned int i; 1397 int ret; 1398 1399 ret = v4l2_ctrl_handler_init(&isl7998x->ctrl_handler, 1400 2 + ARRAY_SIZE(isl7998x_ctrls)); 1401 if (ret) 1402 return ret; 1403 1404 mutex_init(&isl7998x->ctrl_mutex); 1405 isl7998x->ctrl_handler.lock = &isl7998x->ctrl_mutex; 1406 link_freq_index = get_link_freq_menu_index(isl7998x->nr_mipi_lanes, 1407 isl7998x->nr_inputs); 1408 if (link_freq_index < 0 || 1409 link_freq_index >= ARRAY_SIZE(link_freq_menu_items)) { 1410 dev_err(sd->dev, 1411 "failed to find MIPI link freq: %d lanes, %d inputs\n", 1412 isl7998x->nr_mipi_lanes, isl7998x->nr_inputs); 1413 ret = -EINVAL; 1414 goto err; 1415 } 1416 1417 isl7998x->link_freq = v4l2_ctrl_new_int_menu(&isl7998x->ctrl_handler, 1418 &isl7998x_ctrl_ops, 1419 V4L2_CID_LINK_FREQ, 1420 ARRAY_SIZE(link_freq_menu_items) - 1, 1421 link_freq_index, 1422 link_freq_menu_items); 1423 if (isl7998x->link_freq) 1424 isl7998x->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; 1425 1426 for (i = 0; i < ARRAY_SIZE(isl7998x_ctrls); i++) 1427 v4l2_ctrl_new_custom(&isl7998x->ctrl_handler, 1428 &isl7998x_ctrls[i], NULL); 1429 1430 v4l2_ctrl_new_std_menu_items(&isl7998x->ctrl_handler, 1431 &isl7998x_ctrl_ops, 1432 V4L2_CID_TEST_PATTERN, 1433 ARRAY_SIZE(isl7998x_test_pattern_menu) - 1, 1434 0, 0, isl7998x_test_pattern_menu); 1435 1436 ret = isl7998x->ctrl_handler.error; 1437 if (ret) 1438 goto err; 1439 1440 isl7998x->subdev.ctrl_handler = &isl7998x->ctrl_handler; 1441 v4l2_ctrl_handler_setup(&isl7998x->ctrl_handler); 1442 1443 return 0; 1444 1445 err: 1446 isl7998x_remove_controls(isl7998x); 1447 1448 return ret; 1449 } 1450 1451 static int isl7998x_probe(struct i2c_client *client) 1452 { 1453 struct device *dev = &client->dev; 1454 struct v4l2_fwnode_endpoint endpoint = { 1455 .bus_type = V4L2_MBUS_CSI2_DPHY, 1456 }; 1457 struct fwnode_handle *ep; 1458 struct isl7998x *isl7998x; 1459 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 1460 int nr_inputs; 1461 int ret; 1462 1463 ret = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA); 1464 if (!ret) { 1465 dev_warn(&adapter->dev, 1466 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); 1467 return -EIO; 1468 } 1469 1470 isl7998x = devm_kzalloc(dev, sizeof(*isl7998x), GFP_KERNEL); 1471 if (!isl7998x) 1472 return -ENOMEM; 1473 1474 isl7998x->pd_gpio = devm_gpiod_get_optional(dev, "powerdown", 1475 GPIOD_OUT_HIGH); 1476 if (IS_ERR(isl7998x->pd_gpio)) 1477 return dev_err_probe(dev, PTR_ERR(isl7998x->pd_gpio), 1478 "Failed to retrieve/request PD GPIO\n"); 1479 1480 isl7998x->rstb_gpio = devm_gpiod_get_optional(dev, "reset", 1481 GPIOD_OUT_HIGH); 1482 if (IS_ERR(isl7998x->rstb_gpio)) 1483 return dev_err_probe(dev, PTR_ERR(isl7998x->rstb_gpio), 1484 "Failed to retrieve/request RSTB GPIO\n"); 1485 1486 isl7998x->regmap = devm_regmap_init_i2c(client, &isl7998x_regmap); 1487 if (IS_ERR(isl7998x->regmap)) 1488 return dev_err_probe(dev, PTR_ERR(isl7998x->regmap), 1489 "Failed to allocate register map\n"); 1490 1491 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 1492 ISL7998X_PAD_OUT, 0, 0); 1493 if (!ep) 1494 return dev_err_probe(dev, -EINVAL, "Missing endpoint node\n"); 1495 1496 ret = v4l2_fwnode_endpoint_parse(ep, &endpoint); 1497 fwnode_handle_put(ep); 1498 if (ret) 1499 return dev_err_probe(dev, ret, "Failed to parse endpoint\n"); 1500 1501 if (endpoint.bus.mipi_csi2.num_data_lanes == 0 || 1502 endpoint.bus.mipi_csi2.num_data_lanes > 2) 1503 return dev_err_probe(dev, -EINVAL, 1504 "Invalid number of MIPI lanes\n"); 1505 1506 isl7998x->nr_mipi_lanes = endpoint.bus.mipi_csi2.num_data_lanes; 1507 1508 nr_inputs = isl7998x_get_nr_inputs(dev->of_node); 1509 if (nr_inputs < 0) 1510 return dev_err_probe(dev, nr_inputs, 1511 "Invalid number of input ports\n"); 1512 isl7998x->nr_inputs = nr_inputs; 1513 1514 v4l2_i2c_subdev_init(&isl7998x->subdev, client, &isl7998x_subdev_ops); 1515 isl7998x->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 1516 1517 ret = isl7998x_mc_init(isl7998x); 1518 if (ret < 0) 1519 return ret; 1520 1521 isl7998x->fmt = &isl7998x_colour_fmts[0]; 1522 isl7998x->norm = V4L2_STD_NTSC; 1523 isl7998x->enabled = 0; 1524 1525 mutex_init(&isl7998x->lock); 1526 1527 ret = isl7998x_init_controls(isl7998x); 1528 if (ret) 1529 goto err_entity_cleanup; 1530 1531 ret = v4l2_async_register_subdev(&isl7998x->subdev); 1532 if (ret < 0) 1533 goto err_controls_cleanup; 1534 1535 pm_runtime_enable(dev); 1536 1537 return 0; 1538 1539 err_controls_cleanup: 1540 isl7998x_remove_controls(isl7998x); 1541 err_entity_cleanup: 1542 media_entity_cleanup(&isl7998x->subdev.entity); 1543 1544 return ret; 1545 } 1546 1547 static void isl7998x_remove(struct i2c_client *client) 1548 { 1549 struct isl7998x *isl7998x = i2c_to_isl7998x(client); 1550 1551 pm_runtime_disable(&client->dev); 1552 v4l2_async_unregister_subdev(&isl7998x->subdev); 1553 isl7998x_remove_controls(isl7998x); 1554 media_entity_cleanup(&isl7998x->subdev.entity); 1555 } 1556 1557 static const struct of_device_id isl7998x_of_match[] = { 1558 { .compatible = "isil,isl79987", }, 1559 { /* sentinel */ }, 1560 }; 1561 MODULE_DEVICE_TABLE(of, isl7998x_of_match); 1562 1563 static const struct i2c_device_id isl7998x_id[] = { 1564 { "isl79987", 0 }, 1565 { /* sentinel */ }, 1566 }; 1567 MODULE_DEVICE_TABLE(i2c, isl7998x_id); 1568 1569 static int __maybe_unused isl7998x_runtime_resume(struct device *dev) 1570 { 1571 struct v4l2_subdev *sd = dev_get_drvdata(dev); 1572 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 1573 int ret; 1574 1575 gpiod_set_value(isl7998x->rstb_gpio, 1); 1576 gpiod_set_value(isl7998x->pd_gpio, 0); 1577 gpiod_set_value(isl7998x->rstb_gpio, 0); 1578 1579 ret = isl7998x_wait_power_on(isl7998x); 1580 if (ret) 1581 goto err; 1582 1583 ret = isl7998x_init(isl7998x); 1584 if (ret) 1585 goto err; 1586 1587 return 0; 1588 1589 err: 1590 gpiod_set_value(isl7998x->pd_gpio, 1); 1591 1592 return ret; 1593 } 1594 1595 static int __maybe_unused isl7998x_runtime_suspend(struct device *dev) 1596 { 1597 struct v4l2_subdev *sd = dev_get_drvdata(dev); 1598 struct isl7998x *isl7998x = sd_to_isl7998x(sd); 1599 1600 gpiod_set_value(isl7998x->pd_gpio, 1); 1601 1602 return 0; 1603 } 1604 1605 static const struct dev_pm_ops isl7998x_pm_ops = { 1606 SET_RUNTIME_PM_OPS(isl7998x_runtime_suspend, 1607 isl7998x_runtime_resume, 1608 NULL) 1609 }; 1610 1611 static struct i2c_driver isl7998x_i2c_driver = { 1612 .driver = { 1613 .name = "isl7998x", 1614 .of_match_table = of_match_ptr(isl7998x_of_match), 1615 .pm = &isl7998x_pm_ops, 1616 }, 1617 .probe_new = isl7998x_probe, 1618 .remove = isl7998x_remove, 1619 .id_table = isl7998x_id, 1620 }; 1621 1622 module_i2c_driver(isl7998x_i2c_driver); 1623 1624 MODULE_DESCRIPTION("Intersil ISL7998x Analog to MIPI CSI-2/BT656 decoder"); 1625 MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); 1626 MODULE_LICENSE("GPL v2"); 1627