File Index
Files and directories
Sign in
FILE

isl7998x.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/i2c/isl7998x.c C
   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
 313static 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
 367static 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
 416enum 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
 425struct isl7998x_datafmt {
 426	u32			code;
 427	enum v4l2_colorspace	colorspace;
 428};
 429
 430static 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 */
 435static 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 */
 445static const char * const isl7998x_test_pattern_menu[] = {
 446	"Disabled",
 447	"Enabled",
 448};
 449
 450static const char * const isl7998x_test_pattern_bars[] = {
 451	"bbbbwb", "bbbwwb", "bbwbwb", "bbwwwb",
 452};
 453
 454static const char * const isl7998x_test_pattern_colors[] = {
 455	"Yellow", "Blue", "Green", "Pink",
 456};
 457
 458struct isl7998x_mode {
 459	unsigned int width;
 460	unsigned int height;
 461	enum v4l2_field field;
 462};
 463
 464static 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
 477static 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
 511struct 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
 540static struct isl7998x *sd_to_isl7998x(struct v4l2_subdev *sd)
 541{
 542	return container_of(sd, struct isl7998x, subdev);
 543}
 544
 545static struct isl7998x *i2c_to_isl7998x(const struct i2c_client *client)
 546{
 547	return sd_to_isl7998x(i2c_get_clientdata(client));
 548}
 549
 550static 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
 563static 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
 577static 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
 613static 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
 633static 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
 665static int isl7998x_init(struct isl7998x *isl7998x)
 666{
 667	const unsigned int lanes = isl7998x->nr_mipi_lanes;
 668	static 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
 705static 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
 745static 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
 762static 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
 771static 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
 782static 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
 808static 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
 869out_reset_std:
 870	isl7998x_set_standard(isl7998x, isl7998x->norm);
 871out_unlock:
 872	mutex_unlock(&isl7998x->lock);
 873	pm_runtime_put(dev);
 874
 875	return ret;
 876}
 877
 878static int isl7998x_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *std)
 879{
 880	*std = V4L2_STD_ALL;
 881
 882	return 0;
 883}
 884
 885static 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), &reg);
 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
 915static 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, &reg);
 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
 945out:
 946	mutex_unlock(&isl7998x->lock);
 947
 948	return ret;
 949}
 950
 951static 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
 959static 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
 969static 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
 981static 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
 999static 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_state_get_format(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
1023out:
1024	mutex_unlock(&isl7998x->lock);
1025
1026	return 0;
1027}
1028
1029static 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_state_get_format(sd_state, format->pad) = format->format;
1048
1049	mutex_unlock(&isl7998x->lock);
1050
1051	return 0;
1052}
1053
1054static 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
1090static 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
1097static 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
1108static 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
1115static 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
1121static const struct media_entity_operations isl7998x_entity_ops = {
1122	.link_validate = v4l2_subdev_link_validate,
1123};
1124
1125static const struct v4l2_ctrl_ops isl7998x_ctrl_ops = {
1126	.s_ctrl			= isl7998x_set_ctrl,
1127};
1128
1129static 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
1235static 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
1258static 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
1285static 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
1305static 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
1310static 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
1315static 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
1320static 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
1331static 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_MAPLE,
1341};
1342
1343static 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
1359static 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
1386static void isl7998x_remove_controls(struct isl7998x *isl7998x)
1387{
1388	v4l2_ctrl_handler_free(&isl7998x->ctrl_handler);
1389	mutex_destroy(&isl7998x->ctrl_mutex);
1390}
1391
1392static 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
1445err:
1446	isl7998x_remove_controls(isl7998x);
1447
1448	return ret;
1449}
1450
1451static 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
1539err_controls_cleanup:
1540	isl7998x_remove_controls(isl7998x);
1541err_entity_cleanup:
1542	media_entity_cleanup(&isl7998x->subdev.entity);
1543
1544	return ret;
1545}
1546
1547static 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
1557static const struct of_device_id isl7998x_of_match[] = {
1558	{ .compatible = "isil,isl79987", },
1559	{ /* sentinel */ },
1560};
1561MODULE_DEVICE_TABLE(of, isl7998x_of_match);
1562
1563static const struct i2c_device_id isl7998x_id[] = {
1564	{ "isl79987" },
1565	{ /* sentinel */ }
1566};
1567MODULE_DEVICE_TABLE(i2c, isl7998x_id);
1568
1569static 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
1589err:
1590	gpiod_set_value(isl7998x->pd_gpio, 1);
1591
1592	return ret;
1593}
1594
1595static 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
1605static const struct dev_pm_ops isl7998x_pm_ops = {
1606	SET_RUNTIME_PM_OPS(isl7998x_runtime_suspend,
1607			   isl7998x_runtime_resume,
1608			   NULL)
1609};
1610
1611static struct i2c_driver isl7998x_i2c_driver = {
1612	.driver = {
1613		.name = "isl7998x",
1614		.of_match_table = isl7998x_of_match,
1615		.pm = &isl7998x_pm_ops,
1616	},
1617	.probe		= isl7998x_probe,
1618	.remove		= isl7998x_remove,
1619	.id_table	= isl7998x_id,
1620};
1621
1622module_i2c_driver(isl7998x_i2c_driver);
1623
1624MODULE_DESCRIPTION("Intersil ISL7998x Analog to MIPI CSI-2/BT656 decoder");
1625MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
1626MODULE_LICENSE("GPL v2");
~/ Read-only file preview.