xref: /openbmc/linux/drivers/media/i2c/isl7998x.c (revision aaeb31c0)
151ef2be5SMarek Vasut // SPDX-License-Identifier: GPL-2.0
251ef2be5SMarek Vasut /*
351ef2be5SMarek Vasut  * Intersil ISL7998x analog to MIPI CSI-2 or BT.656 decoder driver.
451ef2be5SMarek Vasut  *
551ef2be5SMarek Vasut  * Copyright (C) 2018-2019 Marek Vasut <marex@denx.de>
651ef2be5SMarek Vasut  * Copyright (C) 2021 Michael Tretter <kernel@pengutronix.de>
751ef2be5SMarek Vasut  */
851ef2be5SMarek Vasut 
951ef2be5SMarek Vasut #include <linux/bitfield.h>
1051ef2be5SMarek Vasut #include <linux/delay.h>
11f001cc8dSLinus Walleij #include <linux/gpio/consumer.h>
1251ef2be5SMarek Vasut #include <linux/i2c.h>
1351ef2be5SMarek Vasut #include <linux/module.h>
1451ef2be5SMarek Vasut #include <linux/of_graph.h>
1551ef2be5SMarek Vasut #include <linux/pm_runtime.h>
1651ef2be5SMarek Vasut #include <linux/regmap.h>
1751ef2be5SMarek Vasut #include <linux/slab.h>
1851ef2be5SMarek Vasut #include <linux/v4l2-mediabus.h>
1951ef2be5SMarek Vasut #include <linux/videodev2.h>
2051ef2be5SMarek Vasut 
2151ef2be5SMarek Vasut #include <media/v4l2-async.h>
2251ef2be5SMarek Vasut #include <media/v4l2-common.h>
2351ef2be5SMarek Vasut #include <media/v4l2-ctrls.h>
2451ef2be5SMarek Vasut #include <media/v4l2-device.h>
2551ef2be5SMarek Vasut #include <media/v4l2-fwnode.h>
2651ef2be5SMarek Vasut #include <media/v4l2-ioctl.h>
2751ef2be5SMarek Vasut 
2851ef2be5SMarek Vasut /*
2951ef2be5SMarek Vasut  * This control allows to activate and deactivate the test pattern on
3051ef2be5SMarek Vasut  * selected output channels.
3151ef2be5SMarek Vasut  * This value is ISL7998x specific.
3251ef2be5SMarek Vasut  */
3351ef2be5SMarek Vasut #define V4L2_CID_TEST_PATTERN_CHANNELS	(V4L2_CID_USER_ISL7998X_BASE + 0)
3451ef2be5SMarek Vasut 
3551ef2be5SMarek Vasut /*
3651ef2be5SMarek Vasut  * This control allows to specify the color of the test pattern.
3751ef2be5SMarek Vasut  * This value is ISL7998x specific.
3851ef2be5SMarek Vasut  */
3951ef2be5SMarek Vasut #define V4L2_CID_TEST_PATTERN_COLOR	(V4L2_CID_USER_ISL7998X_BASE + 1)
4051ef2be5SMarek Vasut 
4151ef2be5SMarek Vasut /*
4251ef2be5SMarek Vasut  * This control allows to specify the bar pattern in the test pattern.
4351ef2be5SMarek Vasut  * This value is ISL7998x specific.
4451ef2be5SMarek Vasut  */
4551ef2be5SMarek Vasut #define V4L2_CID_TEST_PATTERN_BARS	(V4L2_CID_USER_ISL7998X_BASE + 2)
4651ef2be5SMarek Vasut 
4751ef2be5SMarek Vasut #define ISL7998X_INPUTS			4
4851ef2be5SMarek Vasut 
4951ef2be5SMarek Vasut #define ISL7998X_REG(page, reg)		(((page) << 8) | (reg))
5051ef2be5SMarek Vasut 
5151ef2be5SMarek Vasut #define ISL7998X_REG_PN_SIZE			256
5251ef2be5SMarek Vasut #define ISL7998X_REG_PN_BASE(n)			((n) * ISL7998X_REG_PN_SIZE)
5351ef2be5SMarek Vasut 
5451ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_PAGE(page)		ISL7998X_REG((page), 0xff)
5551ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_PAGE_MASK		0xf
5651ef2be5SMarek Vasut #define ISL7998X_REG_P0_PRODUCT_ID_CODE		ISL7998X_REG(0, 0x00)
5751ef2be5SMarek Vasut #define ISL7998X_REG_P0_PRODUCT_REV_CODE	ISL7998X_REG(0, 0x01)
5851ef2be5SMarek Vasut #define ISL7998X_REG_P0_SW_RESET_CTL		ISL7998X_REG(0, 0x02)
5951ef2be5SMarek Vasut #define ISL7998X_REG_P0_IO_BUFFER_CTL		ISL7998X_REG(0, 0x03)
6051ef2be5SMarek Vasut #define ISL7998X_REG_P0_IO_BUFFER_CTL_1_1	ISL7998X_REG(0, 0x04)
6151ef2be5SMarek Vasut #define ISL7998X_REG_P0_IO_PAD_PULL_EN_CTL	ISL7998X_REG(0, 0x05)
6251ef2be5SMarek Vasut #define ISL7998X_REG_P0_IO_BUFFER_CTL_1_2	ISL7998X_REG(0, 0x06)
6351ef2be5SMarek Vasut #define ISL7998X_REG_P0_VIDEO_IN_CHAN_CTL	ISL7998X_REG(0, 0x07)
6451ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLK_CTL_1		ISL7998X_REG(0, 0x08)
6551ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLK_CTL_2		ISL7998X_REG(0, 0x09)
6651ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLK_CTL_3		ISL7998X_REG(0, 0x0a)
6751ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLK_CTL_4		ISL7998X_REG(0, 0x0b)
6851ef2be5SMarek Vasut #define ISL7998X_REG_P0_MPP1_SYNC_CTL		ISL7998X_REG(0, 0x0c)
6951ef2be5SMarek Vasut #define ISL7998X_REG_P0_MPP2_SYNC_CTL		ISL7998X_REG(0, 0x0d)
7051ef2be5SMarek Vasut #define ISL7998X_REG_P0_IRQ_SYNC_CTL		ISL7998X_REG(0, 0x0e)
7151ef2be5SMarek Vasut #define ISL7998X_REG_P0_INTERRUPT_STATUS	ISL7998X_REG(0, 0x10)
7251ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_1_IRQ		ISL7998X_REG(0, 0x11)
7351ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_2_IRQ		ISL7998X_REG(0, 0x12)
7451ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_3_IRQ		ISL7998X_REG(0, 0x13)
7551ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_4_IRQ		ISL7998X_REG(0, 0x14)
7651ef2be5SMarek Vasut #define ISL7998X_REG_P0_SHORT_DIAG_IRQ		ISL7998X_REG(0, 0x15)
7751ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_1_IRQ_EN		ISL7998X_REG(0, 0x16)
7851ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_2_IRQ_EN		ISL7998X_REG(0, 0x17)
7951ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_3_IRQ_EN		ISL7998X_REG(0, 0x18)
8051ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_4_IRQ_EN		ISL7998X_REG(0, 0x19)
8151ef2be5SMarek Vasut #define ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN	ISL7998X_REG(0, 0x1a)
8251ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_1_STATUS		ISL7998X_REG(0, 0x1b)
8351ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_2_STATUS		ISL7998X_REG(0, 0x1c)
8451ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_3_STATUS		ISL7998X_REG(0, 0x1d)
8551ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_4_STATUS		ISL7998X_REG(0, 0x1e)
8651ef2be5SMarek Vasut #define ISL7998X_REG_P0_SHORT_DIAG_STATUS	ISL7998X_REG(0, 0x1f)
8751ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLOCK_DELAY		ISL7998X_REG(0, 0x20)
8851ef2be5SMarek Vasut 
8951ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_INPUT_FMT(pg)	ISL7998X_REG((pg), 0x02)
9051ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_STATUS_1(pg)	ISL7998X_REG((pg), 0x03)
9151ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_STATUS_1_VDLOSS	BIT(7)
9251ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_STATUS_1_HLOCK	BIT(6)
9351ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_STATUS_1_VLOCK	BIT(3)
9451ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HS_DELAY_CTL(pg)	ISL7998X_REG((pg), 0x04)
9551ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_ANCTL(pg)		ISL7998X_REG((pg), 0x06)
9651ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CROP_HI(pg)		ISL7998X_REG((pg), 0x07)
9751ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VDELAY_LO(pg)	ISL7998X_REG((pg), 0x08)
9851ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VACTIVE_LO(pg)	ISL7998X_REG((pg), 0x09)
9951ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HDELAY_LO(pg)	ISL7998X_REG((pg), 0x0a)
10051ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HACTIVE_LO(pg)	ISL7998X_REG((pg), 0x0b)
10151ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CNTRL1(pg)		ISL7998X_REG((pg), 0x0c)
10251ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CSC_CTL(pg)		ISL7998X_REG((pg), 0x0d)
10351ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_BRIGHT(pg)		ISL7998X_REG((pg), 0x10)
10451ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CONTRAST(pg)	ISL7998X_REG((pg), 0x11)
10551ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SHARPNESS(pg)	ISL7998X_REG((pg), 0x12)
10651ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SAT_U(pg)		ISL7998X_REG((pg), 0x13)
10751ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SAT_V(pg)		ISL7998X_REG((pg), 0x14)
10851ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HUE(pg)		ISL7998X_REG((pg), 0x15)
10951ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VERT_PEAK(pg)	ISL7998X_REG((pg), 0x17)
11051ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CORING(pg)		ISL7998X_REG((pg), 0x18)
11151ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT(pg)		ISL7998X_REG((pg), 0x1c)
11251ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_DET		BIT(7)
11351ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_NOW		GENMASK(6, 4)
11451ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD	GENMASK(2, 0)
11551ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_M		0
11651ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL		1
11751ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_SECAM		2
11851ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_443	3
11951ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_M		4
12051ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_CN		5
12151ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_60		6
12251ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN	7
12351ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDTR(pg)		ISL7998X_REG((pg), 0x1d)
12451ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDTR_ATSTART	BIT(7)
12551ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLMPG(pg)		ISL7998X_REG((pg), 0x20)
12651ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_IAGC(pg)		ISL7998X_REG((pg), 0x21)
12751ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_AGCGAIN(pg)		ISL7998X_REG((pg), 0x22)
12851ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_PEAKWT(pg)		ISL7998X_REG((pg), 0x23)
12951ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLMPL(pg)		ISL7998X_REG((pg), 0x24)
13051ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SYNCT(pg)		ISL7998X_REG((pg), 0x25)
13151ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MISSCNT(pg)		ISL7998X_REG((pg), 0x26)
13251ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_PCLAMP(pg)		ISL7998X_REG((pg), 0x27)
13351ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VERT_CTL_1(pg)	ISL7998X_REG((pg), 0x28)
13451ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VERT_CTL_2(pg)	ISL7998X_REG((pg), 0x29)
13551ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLR_KILL_LVL(pg)	ISL7998X_REG((pg), 0x2a)
13651ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_COMB_FILTER_CTL(pg)	ISL7998X_REG((pg), 0x2b)
13751ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_LUMA_DELAY(pg)	ISL7998X_REG((pg), 0x2c)
13851ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MISC1(pg)		ISL7998X_REG((pg), 0x2d)
13951ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MISC2(pg)		ISL7998X_REG((pg), 0x2e)
14051ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MISC3(pg)		ISL7998X_REG((pg), 0x2f)
14151ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MVSN(pg)		ISL7998X_REG((pg), 0x30)
14251ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CSTATUS2(pg)	ISL7998X_REG((pg), 0x31)
14351ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HFREF(pg)		ISL7998X_REG((pg), 0x32)
14451ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLMD(pg)		ISL7998X_REG((pg), 0x33)
14551ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_ID_DET_CTL(pg)	ISL7998X_REG((pg), 0x34)
14651ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLCNTL(pg)		ISL7998X_REG((pg), 0x35)
14751ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_1(pg)	ISL7998X_REG((pg), 0x36)
14851ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_2(pg)	ISL7998X_REG((pg), 0x37)
14951ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_3(pg)	ISL7998X_REG((pg), 0x38)
15051ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_4(pg)	ISL7998X_REG((pg), 0x39)
15151ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SHORT_DET_CTL(pg)	ISL7998X_REG((pg), 0x3a)
15251ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(pg)	ISL7998X_REG((pg), 0x3b)
15351ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_AFE_TST_MUX_CTL(pg)	ISL7998X_REG((pg), 0x3c)
15451ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DATA_CONV(pg)	ISL7998X_REG((pg), 0x3d)
15551ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_INTERNAL_TEST(pg)	ISL7998X_REG((pg), 0x3f)
15651ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_H_DELAY_CTL(pg)	ISL7998X_REG((pg), 0x43)
15751ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_H_DELAY_II_HI(pg)	ISL7998X_REG((pg), 0x44)
15851ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(pg)	ISL7998X_REG((pg), 0x45)
15951ef2be5SMarek Vasut 
16051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CTL_1(pg)		ISL7998X_REG((pg), 0x80)
16151ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_GAIN_CTL(pg)	ISL7998X_REG((pg), 0x81)
16251ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_AVG_HI_LIMIT(pg)	ISL7998X_REG((pg), 0x82)
16351ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_AVG_LO_LIMIT(pg)	ISL7998X_REG((pg), 0x83)
16451ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_DET_THRESHOLD(pg)	ISL7998X_REG((pg), 0x84)
16551ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_BLACK_LVL(pg)	ISL7998X_REG((pg), 0x85)
16651ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CENTER_LVL(pg)	ISL7998X_REG((pg), 0x86)
16751ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_WHITE_LVL(pg)	ISL7998X_REG((pg), 0x87)
16851ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MEAN_OFF_LIMIT(pg)	ISL7998X_REG((pg), 0x88)
16951ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MEAN_OFF_UPGAIN(pg)	ISL7998X_REG((pg), 0x89)
17051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MEAN_OFF_SLOPE(pg)	ISL7998X_REG((pg), 0x8a)
17151ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MEAN_OFF_DNGAIN(pg)	ISL7998X_REG((pg), 0x8b)
17251ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_DELTA_CO_THRES(pg)	ISL7998X_REG((pg), 0x8c)
17351ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_DELTA_SLOPE(pg)	ISL7998X_REG((pg), 0x8d)
17451ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_HI_AVG_THRES(pg)	ISL7998X_REG((pg), 0x8e)
17551ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_MAX_LVL_CTL(pg)	ISL7998X_REG((pg), 0x8f)
17651ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_MAX_LVL_CTL(pg)	ISL7998X_REG((pg), 0x90)
17751ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_UPGAIN_CTL(pg)	ISL7998X_REG((pg), 0x91)
17851ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_DNGAIN_CTL(pg)	ISL7998X_REG((pg), 0x92)
17951ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_UPGAIN_CTL(pg)	ISL7998X_REG((pg), 0x93)
18051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_DNGAIN_CTL(pg)	ISL7998X_REG((pg), 0x94)
18151ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LOPASS_FLT_COEF(pg)	ISL7998X_REG((pg), 0x95)
18251ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_PDF_INDEX(pg)	ISL7998X_REG((pg), 0x96)
18351ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_H_STT(pg)	ISL7998X_REG((pg), 0x97)
18451ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_H_SZ1(pg)	ISL7998X_REG((pg), 0x98)
18551ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_H_SZ2(pg)	ISL7998X_REG((pg), 0x99)
18651ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_V_STT(pg)	ISL7998X_REG((pg), 0x9a)
18751ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ1(pg)	ISL7998X_REG((pg), 0x9b)
18851ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(pg)	ISL7998X_REG((pg), 0x9c)
18951ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_AVG(pg)		ISL7998X_REG((pg), 0xa0)
19051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_AVG_LIM(pg)	ISL7998X_REG((pg), 0xa1)
19151ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_AVG(pg)		ISL7998X_REG((pg), 0xa2)
19251ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_AVG(pg)		ISL7998X_REG((pg), 0xa3)
19351ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_MAX(pg)		ISL7998X_REG((pg), 0xa4)
19451ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_MIN(pg)		ISL7998X_REG((pg), 0xa5)
19551ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MOFFSET(pg)		ISL7998X_REG((pg), 0xa6)
19651ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_GAIN(pg)		ISL7998X_REG((pg), 0xa7)
19751ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_GAIN(pg)		ISL7998X_REG((pg), 0xa8)
19851ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LL_SLOPE(pg)	ISL7998X_REG((pg), 0xa9)
19951ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LH_SLOPE(pg)	ISL7998X_REG((pg), 0xaa)
20051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HL_SLOPE(pg)	ISL7998X_REG((pg), 0xab)
20151ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HH_SLOPE(pg)	ISL7998X_REG((pg), 0xac)
20251ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_X_LOW(pg)		ISL7998X_REG((pg), 0xad)
20351ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_X_MEAN(pg)		ISL7998X_REG((pg), 0xae)
20451ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_X_HIGH(pg)		ISL7998X_REG((pg), 0xaf)
20551ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_LOW(pg)		ISL7998X_REG((pg), 0xb0)
20651ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_MEAN(pg)		ISL7998X_REG((pg), 0xb1)
20751ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_HIGH(pg)		ISL7998X_REG((pg), 0xb2)
20851ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CTL_2(pg)		ISL7998X_REG((pg), 0xb3)
20951ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CTL_3(pg)		ISL7998X_REG((pg), 0xb4)
21051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CTL_4(pg)		ISL7998X_REG((pg), 0xb5)
21151ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(pg)	ISL7998X_REG((pg), 0xc0)
21251ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TL_H(pg)	ISL7998X_REG((pg), 0xc1)
21351ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TL_L(pg)	ISL7998X_REG((pg), 0xc2)
21451ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TL_H(pg)	ISL7998X_REG((pg), 0xc3)
21551ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TL_L(pg)	ISL7998X_REG((pg), 0xc4)
21651ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TR_H(pg)	ISL7998X_REG((pg), 0xc5)
21751ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TR_L(pg)	ISL7998X_REG((pg), 0xc6)
21851ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TR_H(pg)	ISL7998X_REG((pg), 0xc7)
21951ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TR_L(pg)	ISL7998X_REG((pg), 0xc8)
22051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BL_H(pg)	ISL7998X_REG((pg), 0xc9)
22151ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BL_L(pg)	ISL7998X_REG((pg), 0xca)
22251ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BL_H(pg)	ISL7998X_REG((pg), 0xcb)
22351ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BL_L(pg)	ISL7998X_REG((pg), 0xcc)
22451ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BR_H(pg)	ISL7998X_REG((pg), 0xcd)
22551ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BR_L(pg)	ISL7998X_REG((pg), 0xce)
22651ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BR_H(pg)	ISL7998X_REG((pg), 0xcf)
22751ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BR_L(pg)	ISL7998X_REG((pg), 0xd0)
22851ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_LM_H(pg)	ISL7998X_REG((pg), 0xd1)
22951ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_LM_L(pg)	ISL7998X_REG((pg), 0xd2)
23051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_LM_H(pg)	ISL7998X_REG((pg), 0xd3)
23151ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_LM_L(pg)	ISL7998X_REG((pg), 0xd4)
23251ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TM_H(pg)	ISL7998X_REG((pg), 0xd5)
23351ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TM_L(pg)	ISL7998X_REG((pg), 0xd6)
23451ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TM_H(pg)	ISL7998X_REG((pg), 0xd7)
23551ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TM_L(pg)	ISL7998X_REG((pg), 0xd8)
23651ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BM_H(pg)	ISL7998X_REG((pg), 0xd9)
23751ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BM_L(pg)	ISL7998X_REG((pg), 0xda)
23851ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BM_H(pg)	ISL7998X_REG((pg), 0xdb)
23951ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BM_L(pg)	ISL7998X_REG((pg), 0xdc)
24051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_RM_H(pg)	ISL7998X_REG((pg), 0xdd)
24151ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_RM_L(pg)	ISL7998X_REG((pg), 0xde)
24251ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_RM_H(pg)	ISL7998X_REG((pg), 0xdf)
24351ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_RM_L(pg)	ISL7998X_REG((pg), 0xe0)
24451ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_DATA_LO(pg)	ISL7998X_REG((pg), 0xe1)
24551ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_DATA_MID(pg)	ISL7998X_REG((pg), 0xe2)
24651ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_DATA_HI(pg)	ISL7998X_REG((pg), 0xe3)
24751ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_CLR(pg)	ISL7998X_REG((pg), 0xe4)
24851ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_CB_CLR(pg)	ISL7998X_REG((pg), 0xe5)
24951ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_CR_CLR(pg)	ISL7998X_REG((pg), 0xe6)
25051ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_XFER_HIST_HOST(pg)	ISL7998X_REG((pg), 0xe7)
25151ef2be5SMarek Vasut 
25251ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_CTL		ISL7998X_REG(5, 0x00)
25351ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_LINE_CTL	ISL7998X_REG(5, 0x01)
25451ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH	ISL7998X_REG(5, 0x02)
25551ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL	ISL7998X_REG(5, 0x03)
25651ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_VC_ASSIGNMENT	ISL7998X_REG(5, 0x04)
25751ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL	ISL7998X_REG(5, 0x05)
25851ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL	ISL7998X_REG(5, 0x06)
25951ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_READ_START_CTL	ISL7998X_REG(5, 0x07)
26051ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSEUDO_FRM_FIELD_CTL	ISL7998X_REG(5, 0x08)
26151ef2be5SMarek Vasut #define ISL7998X_REG_P5_ONE_FIELD_MODE_CTL	ISL7998X_REG(5, 0x09)
26251ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_INT_HW_TST_CTR	ISL7998X_REG(5, 0x0a)
26351ef2be5SMarek Vasut #define ISL7998X_REG_P5_TP_GEN_BAR_PATTERN	ISL7998X_REG(5, 0x0b)
26451ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_PCNT_PSFRM		ISL7998X_REG(5, 0x0c)
26551ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL	ISL7998X_REG(5, 0x0d)
26651ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_VBLANK_PSFRM	ISL7998X_REG(5, 0x0e)
26751ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_CTL_2		ISL7998X_REG(5, 0x0f)
26851ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_WCNT_1		ISL7998X_REG(5, 0x10)
26951ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_WCNT_2		ISL7998X_REG(5, 0x11)
27051ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_1	ISL7998X_REG(5, 0x12)
27151ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_2	ISL7998X_REG(5, 0x13)
27251ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_3	ISL7998X_REG(5, 0x14)
27351ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_4	ISL7998X_REG(5, 0x15)
27451ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_5	ISL7998X_REG(5, 0x16)
27551ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_6	ISL7998X_REG(5, 0x17)
27651ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_PARAMS_1	ISL7998X_REG(5, 0x18)
27751ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_SOT_PERIOD	ISL7998X_REG(5, 0x19)
27851ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_EOT_PERIOD	ISL7998X_REG(5, 0x1a)
27951ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_PARAMS_2	ISL7998X_REG(5, 0x1b)
28051ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_7	ISL7998X_REG(5, 0x1c)
28151ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_8	ISL7998X_REG(5, 0x1d)
28251ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_9	ISL7998X_REG(5, 0x1e)
28351ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_10	ISL7998X_REG(5, 0x1f)
28451ef2be5SMarek Vasut #define ISL7998X_REG_P5_TP_GEN_MIPI		ISL7998X_REG(5, 0x20)
28551ef2be5SMarek Vasut #define ISL7998X_REG_P5_ESC_MODE_TIME_CTL	ISL7998X_REG(5, 0x21)
28651ef2be5SMarek Vasut #define ISL7998X_REG_P5_AUTO_TEST_ERR_DET	ISL7998X_REG(5, 0x22)
28751ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_TIMING		ISL7998X_REG(5, 0x23)
28851ef2be5SMarek Vasut #define ISL7998X_REG_P5_PIC_HEIGHT_HIGH		ISL7998X_REG(5, 0x24)
28951ef2be5SMarek Vasut #define ISL7998X_REG_P5_PIC_HEIGHT_LOW		ISL7998X_REG(5, 0x25)
29051ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL	ISL7998X_REG(5, 0x26)
29151ef2be5SMarek Vasut #define ISL7998X_REG_P5_FIFO_THRSH_CNT_1	ISL7998X_REG(5, 0x28)
29251ef2be5SMarek Vasut #define ISL7998X_REG_P5_FIFO_THRSH_CNT_2	ISL7998X_REG(5, 0x29)
29351ef2be5SMarek Vasut #define ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1	ISL7998X_REG(5, 0x2a)
29451ef2be5SMarek Vasut #define ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2	ISL7998X_REG(5, 0x2b)
29551ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_1	ISL7998X_REG(5, 0x2c)
29651ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_2	ISL7998X_REG(5, 0x2d)
29751ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_3	ISL7998X_REG(5, 0x2e)
29851ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_4	ISL7998X_REG(5, 0x2f)
29951ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_1	ISL7998X_REG(5, 0x30)
30051ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_2	ISL7998X_REG(5, 0x31)
30151ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_ANA_CLK_CTL	ISL7998X_REG(5, 0x32)
30251ef2be5SMarek Vasut #define ISL7998X_REG_P5_PLL_ANA_STATUS		ISL7998X_REG(5, 0x33)
30351ef2be5SMarek Vasut #define ISL7998X_REG_P5_PLL_ANA_MISC_CTL	ISL7998X_REG(5, 0x34)
30451ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_ANA		ISL7998X_REG(5, 0x35)
30551ef2be5SMarek Vasut #define ISL7998X_REG_P5_PLL_ANA			ISL7998X_REG(5, 0x36)
30651ef2be5SMarek Vasut #define ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1	ISL7998X_REG(5, 0x38)
30751ef2be5SMarek Vasut #define ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_2	ISL7998X_REG(5, 0x39)
30851ef2be5SMarek Vasut #define ISL7998X_REG_P5_H_LINE_CNT_1		ISL7998X_REG(5, 0x3a)
30951ef2be5SMarek Vasut #define ISL7998X_REG_P5_H_LINE_CNT_2		ISL7998X_REG(5, 0x3b)
31051ef2be5SMarek Vasut #define ISL7998X_REG_P5_HIST_LINE_CNT_1		ISL7998X_REG(5, 0x3c)
31151ef2be5SMarek Vasut #define ISL7998X_REG_P5_HIST_LINE_CNT_2		ISL7998X_REG(5, 0x3d)
31251ef2be5SMarek Vasut 
31351ef2be5SMarek Vasut static const struct reg_sequence isl7998x_init_seq_1[] = {
31451ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN, 0xff },
31551ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SDT(0x1), 0x00 },
31651ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x1), 0x03 },
31751ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SDT(0x2), 0x00 },
31851ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x2), 0x03 },
31951ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SDT(0x3), 0x00 },
32051ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x3), 0x03 },
32151ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SDT(0x4), 0x00 },
32251ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x4), 0x03 },
32351ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_CTL, 0x00 },
32451ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_SW_RESET_CTL, 0x1f, 10 },
32551ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_IO_BUFFER_CTL, 0x00 },
32651ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_MPP2_SYNC_CTL, 0xc9 },
32751ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_IRQ_SYNC_CTL, 0xc9 },
32851ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CHAN_1_IRQ, 0x03 },
32951ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CHAN_2_IRQ, 0x00 },
33051ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CHAN_3_IRQ, 0x00 },
33151ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CHAN_4_IRQ, 0x00 },
33251ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_CTL, 0x02 },
33351ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_LINE_CTL, 0x85 },
33451ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH, 0xa0 },
33551ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL, 0x18 },
33651ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL, 0x40 },
33751ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL, 0x40 },
33851ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_WCNT_1, 0x05 },
33951ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_WCNT_2, 0xa0 },
34051ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_MIPI, 0x00 },
34151ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_ESC_MODE_TIME_CTL, 0x0c },
34251ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL, 0x00 },
34351ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1, 0x00 },
34451ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2, 0x19 },
34551ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_1, 0x18 },
34651ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_2, 0xf1 },
34751ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_3, 0x00 },
34851ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_4, 0xf1 },
34951ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_1, 0x00 },
35051ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_2, 0x00 },
35151ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_ANA_CLK_CTL, 0x00 },
35251ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PLL_ANA_STATUS, 0xc0 },
35351ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PLL_ANA_MISC_CTL, 0x18 },
35451ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PLL_ANA, 0x00 },
35551ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_SW_RESET_CTL, 0x10, 10 },
35651ef2be5SMarek Vasut 	/* Page 0xf means write to all of pages 1,2,3,4 */
35751ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_VDELAY_LO(0xf), 0x14 },
35851ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_MISC3(0xf), 0xe6 },
35951ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_CLMD(0xf), 0x85 },
36051ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(0xf), 0x11 },
36151ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_ACA_XFER_HIST_HOST(0xf), 0x00 },
36251ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CLK_CTL_1, 0x1f },
36351ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CLK_CTL_2, 0x43 },
36451ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CLK_CTL_3, 0x4f },
36551ef2be5SMarek Vasut };
36651ef2be5SMarek Vasut 
36751ef2be5SMarek Vasut static const struct reg_sequence isl7998x_init_seq_2[] = {
36851ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL, 0x10 },
36951ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_VC_ASSIGNMENT, 0xe4 },
37051ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL, 0x00 },
37151ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL, 0x60 },
37251ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_READ_START_CTL, 0x2b },
37351ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSEUDO_FRM_FIELD_CTL, 0x02 },
37451ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_ONE_FIELD_MODE_CTL, 0x00 },
37551ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_INT_HW_TST_CTR, 0x62 },
37651ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_BAR_PATTERN, 0x02 },
37751ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_PCNT_PSFRM, 0x36 },
37851ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL, 0x00 },
37951ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_VBLANK_PSFRM, 0x6c },
38051ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_CTL_2, 0x00 },
38151ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_WCNT_1, 0x05 },
38251ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_WCNT_2, 0xa0 },
38351ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_1, 0x77 },
38451ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_2, 0x17 },
38551ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_3, 0x08 },
38651ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_4, 0x38 },
38751ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_5, 0x14 },
38851ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_6, 0xf6 },
38951ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_PARAMS_1, 0x00 },
39051ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_SOT_PERIOD, 0x17 },
39151ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_EOT_PERIOD, 0x0a },
39251ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_PARAMS_2, 0x71 },
39351ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_7, 0x7a },
39451ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_8, 0x0f },
39551ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_9, 0x8c },
39651ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL, 0x08 },
39751ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_FIFO_THRSH_CNT_1, 0x01 },
39851ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_FIFO_THRSH_CNT_2, 0x0e },
39951ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1, 0x00 },
40051ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2, 0x00 },
40151ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1, 0x03 },
40251ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_2, 0xc0 },
40351ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_H_LINE_CNT_1, 0x06 },
40451ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_H_LINE_CNT_2, 0xb3 },
40551ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_HIST_LINE_CNT_1, 0x00 },
40651ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_HIST_LINE_CNT_2, 0xf1 },
40751ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL, 0x00 },
40851ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_ANA, 0x00 },
40951ef2be5SMarek Vasut 	/*
41051ef2be5SMarek Vasut 	 * Wait a bit after reset so that the chip can capture a frame
41151ef2be5SMarek Vasut 	 * and update internal line counters.
41251ef2be5SMarek Vasut 	 */
41351ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_SW_RESET_CTL, 0x00, 50 },
41451ef2be5SMarek Vasut };
41551ef2be5SMarek Vasut 
41651ef2be5SMarek Vasut enum isl7998x_pads {
41751ef2be5SMarek Vasut 	ISL7998X_PAD_OUT,
41851ef2be5SMarek Vasut 	ISL7998X_PAD_VIN1,
41951ef2be5SMarek Vasut 	ISL7998X_PAD_VIN2,
42051ef2be5SMarek Vasut 	ISL7998X_PAD_VIN3,
42151ef2be5SMarek Vasut 	ISL7998X_PAD_VIN4,
42251ef2be5SMarek Vasut 	ISL7998X_NUM_PADS
42351ef2be5SMarek Vasut };
42451ef2be5SMarek Vasut 
42551ef2be5SMarek Vasut struct isl7998x_datafmt {
42651ef2be5SMarek Vasut 	u32			code;
42751ef2be5SMarek Vasut 	enum v4l2_colorspace	colorspace;
42851ef2be5SMarek Vasut };
42951ef2be5SMarek Vasut 
43051ef2be5SMarek Vasut static const struct isl7998x_datafmt isl7998x_colour_fmts[] = {
43151ef2be5SMarek Vasut 	{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB },
43251ef2be5SMarek Vasut };
43351ef2be5SMarek Vasut 
43451ef2be5SMarek Vasut /* Menu items for LINK_FREQ V4L2 control */
43551ef2be5SMarek Vasut static const s64 link_freq_menu_items[] = {
43651ef2be5SMarek Vasut 	/* 1 channel, 1 lane or 2 channels, 2 lanes */
43751ef2be5SMarek Vasut 	108000000,
43851ef2be5SMarek Vasut 	/* 2 channels, 1 lane or 4 channels, 2 lanes */
43951ef2be5SMarek Vasut 	216000000,
44051ef2be5SMarek Vasut 	/* 4 channels, 1 lane */
44151ef2be5SMarek Vasut 	432000000,
44251ef2be5SMarek Vasut };
44351ef2be5SMarek Vasut 
44451ef2be5SMarek Vasut /* Menu items for TEST_PATTERN V4L2 control */
44551ef2be5SMarek Vasut static const char * const isl7998x_test_pattern_menu[] = {
44651ef2be5SMarek Vasut 	"Disabled",
44751ef2be5SMarek Vasut 	"Enabled",
44851ef2be5SMarek Vasut };
44951ef2be5SMarek Vasut 
45051ef2be5SMarek Vasut static const char * const isl7998x_test_pattern_bars[] = {
45151ef2be5SMarek Vasut 	"bbbbwb", "bbbwwb", "bbwbwb", "bbwwwb",
45251ef2be5SMarek Vasut };
45351ef2be5SMarek Vasut 
45451ef2be5SMarek Vasut static const char * const isl7998x_test_pattern_colors[] = {
45551ef2be5SMarek Vasut 	"Yellow", "Blue", "Green", "Pink",
45651ef2be5SMarek Vasut };
45751ef2be5SMarek Vasut 
45851ef2be5SMarek Vasut struct isl7998x_mode {
45951ef2be5SMarek Vasut 	unsigned int width;
46051ef2be5SMarek Vasut 	unsigned int height;
46151ef2be5SMarek Vasut 	enum v4l2_field field;
46251ef2be5SMarek Vasut };
46351ef2be5SMarek Vasut 
46451ef2be5SMarek Vasut static const struct isl7998x_mode supported_modes[] = {
46551ef2be5SMarek Vasut 	{
46651ef2be5SMarek Vasut 		.width = 720,
46751ef2be5SMarek Vasut 		.height = 576,
46851ef2be5SMarek Vasut 		.field = V4L2_FIELD_SEQ_TB,
46951ef2be5SMarek Vasut 	},
47051ef2be5SMarek Vasut 	{
47151ef2be5SMarek Vasut 		.width = 720,
47251ef2be5SMarek Vasut 		.height = 480,
47351ef2be5SMarek Vasut 		.field = V4L2_FIELD_SEQ_BT,
47451ef2be5SMarek Vasut 	},
47551ef2be5SMarek Vasut };
47651ef2be5SMarek Vasut 
47751ef2be5SMarek Vasut static const struct isl7998x_video_std {
47851ef2be5SMarek Vasut 	const v4l2_std_id norm;
47951ef2be5SMarek Vasut 	unsigned int id;
48051ef2be5SMarek Vasut 	const struct isl7998x_mode *mode;
48151ef2be5SMarek Vasut } isl7998x_std_res[] = {
48251ef2be5SMarek Vasut 	{ V4L2_STD_NTSC_443,
48351ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_443,
48451ef2be5SMarek Vasut 	  &supported_modes[1] },
48551ef2be5SMarek Vasut 	{ V4L2_STD_PAL_M,
48651ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_M,
48751ef2be5SMarek Vasut 	  &supported_modes[1] },
48851ef2be5SMarek Vasut 	{ V4L2_STD_PAL_Nc,
48951ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_CN,
49051ef2be5SMarek Vasut 	  &supported_modes[0] },
49151ef2be5SMarek Vasut 	{ V4L2_STD_PAL_N,
49251ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL,
49351ef2be5SMarek Vasut 	  &supported_modes[0] },
49451ef2be5SMarek Vasut 	{ V4L2_STD_PAL_60,
49551ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_60,
49651ef2be5SMarek Vasut 	  &supported_modes[1] },
49751ef2be5SMarek Vasut 	{ V4L2_STD_NTSC,
49851ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_M,
49951ef2be5SMarek Vasut 	  &supported_modes[1] },
50051ef2be5SMarek Vasut 	{ V4L2_STD_PAL,
50151ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL,
50251ef2be5SMarek Vasut 	  &supported_modes[0] },
50351ef2be5SMarek Vasut 	{ V4L2_STD_SECAM,
50451ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_SECAM,
50551ef2be5SMarek Vasut 	  &supported_modes[0] },
50651ef2be5SMarek Vasut 	{ V4L2_STD_UNKNOWN,
50751ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN,
50851ef2be5SMarek Vasut 	  &supported_modes[1] },
50951ef2be5SMarek Vasut };
51051ef2be5SMarek Vasut 
51151ef2be5SMarek Vasut struct isl7998x {
51251ef2be5SMarek Vasut 	struct v4l2_subdev		subdev;
51351ef2be5SMarek Vasut 	struct regmap			*regmap;
51451ef2be5SMarek Vasut 	struct gpio_desc		*pd_gpio;
51551ef2be5SMarek Vasut 	struct gpio_desc		*rstb_gpio;
51651ef2be5SMarek Vasut 	unsigned int			nr_mipi_lanes;
51751ef2be5SMarek Vasut 	u32				nr_inputs;
51851ef2be5SMarek Vasut 
51951ef2be5SMarek Vasut 	const struct isl7998x_datafmt	*fmt;
52051ef2be5SMarek Vasut 	v4l2_std_id			norm;
52151ef2be5SMarek Vasut 	struct media_pad		pads[ISL7998X_NUM_PADS];
52251ef2be5SMarek Vasut 
52351ef2be5SMarek Vasut 	int				enabled;
52451ef2be5SMarek Vasut 
52551ef2be5SMarek Vasut 	/* protect fmt, norm, enabled */
52651ef2be5SMarek Vasut 	struct mutex			lock;
52751ef2be5SMarek Vasut 
52851ef2be5SMarek Vasut 	struct v4l2_ctrl_handler	ctrl_handler;
52951ef2be5SMarek Vasut 	/* protect ctrl_handler */
53051ef2be5SMarek Vasut 	struct mutex			ctrl_mutex;
53151ef2be5SMarek Vasut 
53251ef2be5SMarek Vasut 	/* V4L2 Controls */
53351ef2be5SMarek Vasut 	struct v4l2_ctrl		*link_freq;
53451ef2be5SMarek Vasut 	u8				test_pattern;
53551ef2be5SMarek Vasut 	u8				test_pattern_bars;
53651ef2be5SMarek Vasut 	u8				test_pattern_chans;
53751ef2be5SMarek Vasut 	u8				test_pattern_color;
53851ef2be5SMarek Vasut };
53951ef2be5SMarek Vasut 
54051ef2be5SMarek Vasut static struct isl7998x *sd_to_isl7998x(struct v4l2_subdev *sd)
54151ef2be5SMarek Vasut {
54251ef2be5SMarek Vasut 	return container_of(sd, struct isl7998x, subdev);
54351ef2be5SMarek Vasut }
54451ef2be5SMarek Vasut 
54551ef2be5SMarek Vasut static struct isl7998x *i2c_to_isl7998x(const struct i2c_client *client)
54651ef2be5SMarek Vasut {
54751ef2be5SMarek Vasut 	return sd_to_isl7998x(i2c_get_clientdata(client));
54851ef2be5SMarek Vasut }
54951ef2be5SMarek Vasut 
55051ef2be5SMarek Vasut static unsigned int isl7998x_norm_to_val(v4l2_std_id norm)
55151ef2be5SMarek Vasut {
55251ef2be5SMarek Vasut 	unsigned int i;
55351ef2be5SMarek Vasut 
55451ef2be5SMarek Vasut 	for (i = 0; i < ARRAY_SIZE(isl7998x_std_res); i++)
55551ef2be5SMarek Vasut 		if (isl7998x_std_res[i].norm & norm)
55651ef2be5SMarek Vasut 			break;
55751ef2be5SMarek Vasut 	if (i == ARRAY_SIZE(isl7998x_std_res))
55851ef2be5SMarek Vasut 		return ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN;
55951ef2be5SMarek Vasut 
56051ef2be5SMarek Vasut 	return isl7998x_std_res[i].id;
56151ef2be5SMarek Vasut }
56251ef2be5SMarek Vasut 
56351ef2be5SMarek Vasut static const struct isl7998x_mode *isl7998x_norm_to_mode(v4l2_std_id norm)
56451ef2be5SMarek Vasut {
56551ef2be5SMarek Vasut 	unsigned int i;
56651ef2be5SMarek Vasut 
56751ef2be5SMarek Vasut 	for (i = 0; i < ARRAY_SIZE(isl7998x_std_res); i++)
56851ef2be5SMarek Vasut 		if (isl7998x_std_res[i].norm & norm)
56951ef2be5SMarek Vasut 			break;
57051ef2be5SMarek Vasut 	/* Use NTSC default resolution during standard detection */
57151ef2be5SMarek Vasut 	if (i == ARRAY_SIZE(isl7998x_std_res))
57251ef2be5SMarek Vasut 		return &supported_modes[1];
57351ef2be5SMarek Vasut 
57451ef2be5SMarek Vasut 	return isl7998x_std_res[i].mode;
57551ef2be5SMarek Vasut }
57651ef2be5SMarek Vasut 
57751ef2be5SMarek Vasut static int isl7998x_get_nr_inputs(struct device_node *of_node)
57851ef2be5SMarek Vasut {
57951ef2be5SMarek Vasut 	struct device_node *port;
58051ef2be5SMarek Vasut 	unsigned int inputs = 0;
58151ef2be5SMarek Vasut 	unsigned int i;
58251ef2be5SMarek Vasut 
58351ef2be5SMarek Vasut 	if (of_graph_get_endpoint_count(of_node) > ISL7998X_NUM_PADS)
58451ef2be5SMarek Vasut 		return -EINVAL;
58551ef2be5SMarek Vasut 
58651ef2be5SMarek Vasut 	/*
58751ef2be5SMarek Vasut 	 * The driver does not provide means to remap the input ports. It
58851ef2be5SMarek Vasut 	 * always configures input ports to start from VID1. Ensure that the
58951ef2be5SMarek Vasut 	 * device tree is correct.
59051ef2be5SMarek Vasut 	 */
59151ef2be5SMarek Vasut 	for (i = ISL7998X_PAD_VIN1; i <= ISL7998X_PAD_VIN4; i++) {
59251ef2be5SMarek Vasut 		port = of_graph_get_port_by_id(of_node, i);
59351ef2be5SMarek Vasut 		if (!port)
59451ef2be5SMarek Vasut 			continue;
59551ef2be5SMarek Vasut 
59651ef2be5SMarek Vasut 		inputs |= BIT(i);
59751ef2be5SMarek Vasut 		of_node_put(port);
59851ef2be5SMarek Vasut 	}
59951ef2be5SMarek Vasut 
60051ef2be5SMarek Vasut 	switch (inputs) {
60151ef2be5SMarek Vasut 	case BIT(ISL7998X_PAD_VIN1):
60251ef2be5SMarek Vasut 		return 1;
60351ef2be5SMarek Vasut 	case BIT(ISL7998X_PAD_VIN1) | BIT(ISL7998X_PAD_VIN2):
60451ef2be5SMarek Vasut 		return 2;
60551ef2be5SMarek Vasut 	case BIT(ISL7998X_PAD_VIN1) | BIT(ISL7998X_PAD_VIN2) |
60651ef2be5SMarek Vasut 	     BIT(ISL7998X_PAD_VIN3) | BIT(ISL7998X_PAD_VIN4):
60751ef2be5SMarek Vasut 		return 4;
60851ef2be5SMarek Vasut 	default:
60951ef2be5SMarek Vasut 		return -EINVAL;
61051ef2be5SMarek Vasut 	}
61151ef2be5SMarek Vasut }
61251ef2be5SMarek Vasut 
61351ef2be5SMarek Vasut static int isl7998x_wait_power_on(struct isl7998x *isl7998x)
61451ef2be5SMarek Vasut {
61551ef2be5SMarek Vasut 	struct device *dev = isl7998x->subdev.dev;
61651ef2be5SMarek Vasut 	u32 chip_id;
61751ef2be5SMarek Vasut 	int ret;
61851ef2be5SMarek Vasut 	int err;
61951ef2be5SMarek Vasut 
62051ef2be5SMarek Vasut 	ret = read_poll_timeout(regmap_read, err, !err, 2000, 20000, false,
62151ef2be5SMarek Vasut 				isl7998x->regmap,
62251ef2be5SMarek Vasut 				ISL7998X_REG_P0_PRODUCT_ID_CODE, &chip_id);
62351ef2be5SMarek Vasut 	if (ret) {
62451ef2be5SMarek Vasut 		dev_err(dev, "timeout while waiting for ISL7998X\n");
62551ef2be5SMarek Vasut 		return ret;
62651ef2be5SMarek Vasut 	}
62751ef2be5SMarek Vasut 
62851ef2be5SMarek Vasut 	dev_dbg(dev, "Found ISL799%x\n", chip_id);
62951ef2be5SMarek Vasut 
63051ef2be5SMarek Vasut 	return ret;
63151ef2be5SMarek Vasut }
63251ef2be5SMarek Vasut 
63351ef2be5SMarek Vasut static int isl7998x_set_standard(struct isl7998x *isl7998x, v4l2_std_id norm)
63451ef2be5SMarek Vasut {
63551ef2be5SMarek Vasut 	const struct isl7998x_mode *mode = isl7998x_norm_to_mode(norm);
63651ef2be5SMarek Vasut 	unsigned int val = isl7998x_norm_to_val(norm);
63751ef2be5SMarek Vasut 	unsigned int width = mode->width;
63851ef2be5SMarek Vasut 	unsigned int i;
63951ef2be5SMarek Vasut 	int ret;
64051ef2be5SMarek Vasut 
64151ef2be5SMarek Vasut 	for (i = 0; i < ISL7998X_INPUTS; i++) {
64251ef2be5SMarek Vasut 		ret = regmap_write_bits(isl7998x->regmap,
64351ef2be5SMarek Vasut 					ISL7998X_REG_PX_DEC_SDT(i + 1),
64451ef2be5SMarek Vasut 					ISL7998X_REG_PX_DEC_SDT_STANDARD,
64551ef2be5SMarek Vasut 					val);
64651ef2be5SMarek Vasut 		if (ret)
64751ef2be5SMarek Vasut 			return ret;
64851ef2be5SMarek Vasut 	}
64951ef2be5SMarek Vasut 
65051ef2be5SMarek Vasut 	ret = regmap_write(isl7998x->regmap,
65151ef2be5SMarek Vasut 			   ISL7998X_REG_P5_LI_ENGINE_LINE_CTL,
65251ef2be5SMarek Vasut 			   0x20 | ((width >> 7) & 0x1f));
65351ef2be5SMarek Vasut 	if (ret)
65451ef2be5SMarek Vasut 		return ret;
65551ef2be5SMarek Vasut 
65651ef2be5SMarek Vasut 	ret = regmap_write(isl7998x->regmap,
65751ef2be5SMarek Vasut 			   ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH,
65851ef2be5SMarek Vasut 			   (width << 1) & 0xff);
65951ef2be5SMarek Vasut 	if (ret)
66051ef2be5SMarek Vasut 		return ret;
66151ef2be5SMarek Vasut 
66251ef2be5SMarek Vasut 	return 0;
66351ef2be5SMarek Vasut }
66451ef2be5SMarek Vasut 
66551ef2be5SMarek Vasut static int isl7998x_init(struct isl7998x *isl7998x)
66651ef2be5SMarek Vasut {
66751ef2be5SMarek Vasut 	const unsigned int lanes = isl7998x->nr_mipi_lanes;
668d59014e7SColin Ian King 	static const u32 isl7998x_video_in_chan_map[] = { 0x00, 0x11, 0x02, 0x02 };
66951ef2be5SMarek Vasut 	const struct reg_sequence isl7998x_init_seq_custom[] = {
67051ef2be5SMarek Vasut 		{ ISL7998X_REG_P0_VIDEO_IN_CHAN_CTL,
67151ef2be5SMarek Vasut 		  isl7998x_video_in_chan_map[isl7998x->nr_inputs - 1] },
67251ef2be5SMarek Vasut 		{ ISL7998X_REG_P0_CLK_CTL_4,
67351ef2be5SMarek Vasut 		  (lanes == 1) ? 0x40 : 0x41 },
67451ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_CTL,
67551ef2be5SMarek Vasut 		  (lanes == 1) ? 0x01 : 0x02 },
67651ef2be5SMarek Vasut 	};
67751ef2be5SMarek Vasut 	struct device *dev = isl7998x->subdev.dev;
67851ef2be5SMarek Vasut 	struct regmap *regmap = isl7998x->regmap;
67951ef2be5SMarek Vasut 	int ret;
68051ef2be5SMarek Vasut 
68151ef2be5SMarek Vasut 	dev_dbg(dev, "configuring %d lanes for %d inputs (norm %s)\n",
68251ef2be5SMarek Vasut 		isl7998x->nr_mipi_lanes, isl7998x->nr_inputs,
68351ef2be5SMarek Vasut 		v4l2_norm_to_name(isl7998x->norm));
68451ef2be5SMarek Vasut 
68551ef2be5SMarek Vasut 	ret = regmap_register_patch(regmap, isl7998x_init_seq_1,
68651ef2be5SMarek Vasut 				    ARRAY_SIZE(isl7998x_init_seq_1));
68751ef2be5SMarek Vasut 	if (ret)
68851ef2be5SMarek Vasut 		return ret;
68951ef2be5SMarek Vasut 
69051ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
69151ef2be5SMarek Vasut 	ret = isl7998x_set_standard(isl7998x, isl7998x->norm);
69251ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
69351ef2be5SMarek Vasut 	if (ret)
69451ef2be5SMarek Vasut 		return ret;
69551ef2be5SMarek Vasut 
69651ef2be5SMarek Vasut 	ret = regmap_register_patch(regmap, isl7998x_init_seq_custom,
69751ef2be5SMarek Vasut 				    ARRAY_SIZE(isl7998x_init_seq_custom));
69851ef2be5SMarek Vasut 	if (ret)
69951ef2be5SMarek Vasut 		return ret;
70051ef2be5SMarek Vasut 
70151ef2be5SMarek Vasut 	return regmap_register_patch(regmap, isl7998x_init_seq_2,
70251ef2be5SMarek Vasut 				     ARRAY_SIZE(isl7998x_init_seq_2));
70351ef2be5SMarek Vasut }
70451ef2be5SMarek Vasut 
70551ef2be5SMarek Vasut static int isl7998x_set_test_pattern(struct isl7998x *isl7998x)
70651ef2be5SMarek Vasut {
70751ef2be5SMarek Vasut 	const struct reg_sequence isl7998x_init_seq_tpg_off[] = {
70851ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL, 0 },
70951ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_CTL_2, 0 }
71051ef2be5SMarek Vasut 	};
71151ef2be5SMarek Vasut 	const struct reg_sequence isl7998x_init_seq_tpg_on[] = {
71251ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_TP_GEN_BAR_PATTERN,
71351ef2be5SMarek Vasut 		  isl7998x->test_pattern_bars << 6 },
71451ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_CTL_2,
71551ef2be5SMarek Vasut 		  isl7998x->norm & V4L2_STD_PAL ? BIT(2) : 0 },
71651ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL,
71751ef2be5SMarek Vasut 		  (isl7998x->test_pattern_chans << 4) |
71851ef2be5SMarek Vasut 		  (isl7998x->test_pattern_color << 2) }
71951ef2be5SMarek Vasut 	};
72051ef2be5SMarek Vasut 	struct device *dev = isl7998x->subdev.dev;
72151ef2be5SMarek Vasut 	struct regmap *regmap = isl7998x->regmap;
72251ef2be5SMarek Vasut 	int ret;
72351ef2be5SMarek Vasut 
72451ef2be5SMarek Vasut 	if (pm_runtime_get_if_in_use(dev) <= 0)
72551ef2be5SMarek Vasut 		return 0;
72651ef2be5SMarek Vasut 
72751ef2be5SMarek Vasut 	if (isl7998x->test_pattern != 0) {
72851ef2be5SMarek Vasut 		dev_dbg(dev, "enabling test pattern: channels 0x%x, %s, %s\n",
72951ef2be5SMarek Vasut 			isl7998x->test_pattern_chans,
73051ef2be5SMarek Vasut 			isl7998x_test_pattern_bars[isl7998x->test_pattern_bars],
73151ef2be5SMarek Vasut 			isl7998x_test_pattern_colors[isl7998x->test_pattern_color]);
73251ef2be5SMarek Vasut 		ret = regmap_register_patch(regmap, isl7998x_init_seq_tpg_on,
73351ef2be5SMarek Vasut 					    ARRAY_SIZE(isl7998x_init_seq_tpg_on));
73451ef2be5SMarek Vasut 	} else {
73551ef2be5SMarek Vasut 		ret = regmap_register_patch(regmap, isl7998x_init_seq_tpg_off,
73651ef2be5SMarek Vasut 					    ARRAY_SIZE(isl7998x_init_seq_tpg_off));
73751ef2be5SMarek Vasut 	}
73851ef2be5SMarek Vasut 
73951ef2be5SMarek Vasut 	pm_runtime_put(dev);
74051ef2be5SMarek Vasut 
74151ef2be5SMarek Vasut 	return ret;
74251ef2be5SMarek Vasut }
74351ef2be5SMarek Vasut 
74451ef2be5SMarek Vasut #ifdef CONFIG_VIDEO_ADV_DEBUG
74551ef2be5SMarek Vasut static int isl7998x_g_register(struct v4l2_subdev *sd,
74651ef2be5SMarek Vasut 			       struct v4l2_dbg_register *reg)
74751ef2be5SMarek Vasut {
74851ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
74951ef2be5SMarek Vasut 	int ret;
75051ef2be5SMarek Vasut 	u32 val;
75151ef2be5SMarek Vasut 
75251ef2be5SMarek Vasut 	ret = regmap_read(isl7998x->regmap, reg->reg, &val);
75351ef2be5SMarek Vasut 	if (ret)
75451ef2be5SMarek Vasut 		return ret;
75551ef2be5SMarek Vasut 
75651ef2be5SMarek Vasut 	reg->size = 1;
75751ef2be5SMarek Vasut 	reg->val = val;
75851ef2be5SMarek Vasut 
75951ef2be5SMarek Vasut 	return 0;
76051ef2be5SMarek Vasut }
76151ef2be5SMarek Vasut 
76251ef2be5SMarek Vasut static int isl7998x_s_register(struct v4l2_subdev *sd,
76351ef2be5SMarek Vasut 			       const struct v4l2_dbg_register *reg)
76451ef2be5SMarek Vasut {
76551ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
76651ef2be5SMarek Vasut 
76751ef2be5SMarek Vasut 	return regmap_write(isl7998x->regmap, reg->reg, reg->val);
76851ef2be5SMarek Vasut }
76951ef2be5SMarek Vasut #endif
77051ef2be5SMarek Vasut 
77151ef2be5SMarek Vasut static int isl7998x_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
77251ef2be5SMarek Vasut {
77351ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
77451ef2be5SMarek Vasut 
77551ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
77651ef2be5SMarek Vasut 	*norm = isl7998x->norm;
77751ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
77851ef2be5SMarek Vasut 
77951ef2be5SMarek Vasut 	return 0;
78051ef2be5SMarek Vasut }
78151ef2be5SMarek Vasut 
78251ef2be5SMarek Vasut static int isl7998x_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
78351ef2be5SMarek Vasut {
78451ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
78551ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
78651ef2be5SMarek Vasut 	struct device *dev = &client->dev;
78751ef2be5SMarek Vasut 	int ret = 0;
78851ef2be5SMarek Vasut 
78951ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
79051ef2be5SMarek Vasut 	if (isl7998x->enabled) {
79151ef2be5SMarek Vasut 		ret = -EBUSY;
79251ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
79351ef2be5SMarek Vasut 		return ret;
79451ef2be5SMarek Vasut 	}
79551ef2be5SMarek Vasut 	isl7998x->norm = norm;
79651ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
79751ef2be5SMarek Vasut 
79851ef2be5SMarek Vasut 	if (pm_runtime_get_if_in_use(dev) <= 0)
79951ef2be5SMarek Vasut 		return ret;
80051ef2be5SMarek Vasut 
80151ef2be5SMarek Vasut 	ret = isl7998x_set_standard(isl7998x, norm);
80251ef2be5SMarek Vasut 
80351ef2be5SMarek Vasut 	pm_runtime_put(dev);
80451ef2be5SMarek Vasut 
80551ef2be5SMarek Vasut 	return ret;
80651ef2be5SMarek Vasut }
80751ef2be5SMarek Vasut 
80851ef2be5SMarek Vasut static int isl7998x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
80951ef2be5SMarek Vasut {
81051ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
81151ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
81251ef2be5SMarek Vasut 	struct device *dev = &client->dev;
81351ef2be5SMarek Vasut 	unsigned int std_id[ISL7998X_INPUTS];
81451ef2be5SMarek Vasut 	unsigned int i;
81551ef2be5SMarek Vasut 	int ret;
81651ef2be5SMarek Vasut 	u32 reg;
81751ef2be5SMarek Vasut 
81851ef2be5SMarek Vasut 	ret = pm_runtime_resume_and_get(dev);
81951ef2be5SMarek Vasut 	if (ret)
82051ef2be5SMarek Vasut 		return ret;
82151ef2be5SMarek Vasut 
82251ef2be5SMarek Vasut 	dev_dbg(dev, "starting video standard detection\n");
82351ef2be5SMarek Vasut 
82451ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
82551ef2be5SMarek Vasut 	if (isl7998x->enabled) {
82651ef2be5SMarek Vasut 		ret = -EBUSY;
82751ef2be5SMarek Vasut 		goto out_unlock;
82851ef2be5SMarek Vasut 	}
82951ef2be5SMarek Vasut 
83051ef2be5SMarek Vasut 	ret = isl7998x_set_standard(isl7998x, V4L2_STD_UNKNOWN);
83151ef2be5SMarek Vasut 	if (ret)
83251ef2be5SMarek Vasut 		goto out_unlock;
83351ef2be5SMarek Vasut 
83451ef2be5SMarek Vasut 	for (i = 0; i < ISL7998X_INPUTS; i++) {
83551ef2be5SMarek Vasut 		ret = regmap_write(isl7998x->regmap,
83651ef2be5SMarek Vasut 				   ISL7998X_REG_PX_DEC_SDTR(i + 1),
83751ef2be5SMarek Vasut 				   ISL7998X_REG_PX_DEC_SDTR_ATSTART);
83851ef2be5SMarek Vasut 		if (ret)
83951ef2be5SMarek Vasut 			goto out_reset_std;
84051ef2be5SMarek Vasut 	}
84151ef2be5SMarek Vasut 
84251ef2be5SMarek Vasut 	for (i = 0; i < ISL7998X_INPUTS; i++) {
84351ef2be5SMarek Vasut 		ret = regmap_read_poll_timeout(isl7998x->regmap,
84451ef2be5SMarek Vasut 					       ISL7998X_REG_PX_DEC_SDT(i + 1),
84551ef2be5SMarek Vasut 					       reg,
84651ef2be5SMarek Vasut 					       !(reg & ISL7998X_REG_PX_DEC_SDT_DET),
84751ef2be5SMarek Vasut 					       2000, 500 * USEC_PER_MSEC);
84851ef2be5SMarek Vasut 		if (ret)
84951ef2be5SMarek Vasut 			goto out_reset_std;
85051ef2be5SMarek Vasut 		std_id[i] = FIELD_GET(ISL7998X_REG_PX_DEC_SDT_NOW, reg);
85151ef2be5SMarek Vasut 	}
85251ef2be5SMarek Vasut 
85351ef2be5SMarek Vasut 	/*
85451ef2be5SMarek Vasut 	 * According to Renesas FAE, all input cameras must have the
85551ef2be5SMarek Vasut 	 * same standard on this chip.
85651ef2be5SMarek Vasut 	 */
85751ef2be5SMarek Vasut 	for (i = 0; i < isl7998x->nr_inputs; i++) {
85851ef2be5SMarek Vasut 		dev_dbg(dev, "input %d: detected %s\n",
85951ef2be5SMarek Vasut 			i, v4l2_norm_to_name(isl7998x_std_res[std_id[i]].norm));
86051ef2be5SMarek Vasut 		if (std_id[0] != std_id[i])
86151ef2be5SMarek Vasut 			dev_warn(dev,
86251ef2be5SMarek Vasut 				 "incompatible standards: %s on input %d (expected %s)\n",
86351ef2be5SMarek Vasut 				 v4l2_norm_to_name(isl7998x_std_res[std_id[i]].norm), i,
86451ef2be5SMarek Vasut 				 v4l2_norm_to_name(isl7998x_std_res[std_id[0]].norm));
86551ef2be5SMarek Vasut 	}
86651ef2be5SMarek Vasut 
86751ef2be5SMarek Vasut 	*std = isl7998x_std_res[std_id[0]].norm;
86851ef2be5SMarek Vasut 
86951ef2be5SMarek Vasut out_reset_std:
87051ef2be5SMarek Vasut 	isl7998x_set_standard(isl7998x, isl7998x->norm);
87151ef2be5SMarek Vasut out_unlock:
87251ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
87351ef2be5SMarek Vasut 	pm_runtime_put(dev);
87451ef2be5SMarek Vasut 
87551ef2be5SMarek Vasut 	return ret;
87651ef2be5SMarek Vasut }
87751ef2be5SMarek Vasut 
87851ef2be5SMarek Vasut static int isl7998x_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *std)
87951ef2be5SMarek Vasut {
88051ef2be5SMarek Vasut 	*std = V4L2_STD_ALL;
88151ef2be5SMarek Vasut 
88251ef2be5SMarek Vasut 	return 0;
88351ef2be5SMarek Vasut }
88451ef2be5SMarek Vasut 
88551ef2be5SMarek Vasut static int isl7998x_g_input_status(struct v4l2_subdev *sd, u32 *status)
88651ef2be5SMarek Vasut {
88751ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
88851ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
88951ef2be5SMarek Vasut 	struct device *dev = &client->dev;
89051ef2be5SMarek Vasut 	unsigned int i;
89151ef2be5SMarek Vasut 	int ret = 0;
89251ef2be5SMarek Vasut 	u32 reg;
89351ef2be5SMarek Vasut 
89451ef2be5SMarek Vasut 	if (!pm_runtime_active(dev)) {
89551ef2be5SMarek Vasut 		*status |= V4L2_IN_ST_NO_POWER;
89651ef2be5SMarek Vasut 		return 0;
89751ef2be5SMarek Vasut 	}
89851ef2be5SMarek Vasut 
89951ef2be5SMarek Vasut 	for (i = 0; i < isl7998x->nr_inputs; i++) {
90051ef2be5SMarek Vasut 		ret = regmap_read(isl7998x->regmap,
90151ef2be5SMarek Vasut 				  ISL7998X_REG_PX_DEC_STATUS_1(i + 1), &reg);
90251ef2be5SMarek Vasut 		if (!ret) {
90351ef2be5SMarek Vasut 			if (reg & ISL7998X_REG_PX_DEC_STATUS_1_VDLOSS)
90451ef2be5SMarek Vasut 				*status |= V4L2_IN_ST_NO_SIGNAL;
90551ef2be5SMarek Vasut 			if (!(reg & ISL7998X_REG_PX_DEC_STATUS_1_HLOCK))
90651ef2be5SMarek Vasut 				*status |= V4L2_IN_ST_NO_H_LOCK;
90751ef2be5SMarek Vasut 			if (!(reg & ISL7998X_REG_PX_DEC_STATUS_1_VLOCK))
90851ef2be5SMarek Vasut 				*status |= V4L2_IN_ST_NO_V_LOCK;
90951ef2be5SMarek Vasut 		}
91051ef2be5SMarek Vasut 	}
91151ef2be5SMarek Vasut 
91251ef2be5SMarek Vasut 	return ret;
91351ef2be5SMarek Vasut }
91451ef2be5SMarek Vasut 
91551ef2be5SMarek Vasut static int isl7998x_s_stream(struct v4l2_subdev *sd, int enable)
91651ef2be5SMarek Vasut {
91751ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
91851ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
91951ef2be5SMarek Vasut 	struct device *dev = &client->dev;
92051ef2be5SMarek Vasut 	int ret = 0;
92151ef2be5SMarek Vasut 	u32 reg;
92251ef2be5SMarek Vasut 
92351ef2be5SMarek Vasut 	dev_dbg(dev, "stream %s\n", enable ? "ON" : "OFF");
92451ef2be5SMarek Vasut 
92551ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
92651ef2be5SMarek Vasut 	if (isl7998x->enabled == enable)
92751ef2be5SMarek Vasut 		goto out;
92851ef2be5SMarek Vasut 	isl7998x->enabled = enable;
92951ef2be5SMarek Vasut 
93051ef2be5SMarek Vasut 	if (enable) {
93151ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
93251ef2be5SMarek Vasut 		if (ret)
93351ef2be5SMarek Vasut 			goto out;
93451ef2be5SMarek Vasut 	}
93551ef2be5SMarek Vasut 
93651ef2be5SMarek Vasut 	regmap_read(isl7998x->regmap,
93751ef2be5SMarek Vasut 		    ISL7998X_REG_P5_LI_ENGINE_CTL, &reg);
93851ef2be5SMarek Vasut 	if (enable)
93951ef2be5SMarek Vasut 		reg &= ~BIT(7);
94051ef2be5SMarek Vasut 	else
94151ef2be5SMarek Vasut 		reg |= BIT(7);
94251ef2be5SMarek Vasut 	ret = regmap_write(isl7998x->regmap,
94351ef2be5SMarek Vasut 			   ISL7998X_REG_P5_LI_ENGINE_CTL, reg);
94451ef2be5SMarek Vasut 
94551ef2be5SMarek Vasut out:
94651ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
94751ef2be5SMarek Vasut 
94851ef2be5SMarek Vasut 	return ret;
94951ef2be5SMarek Vasut }
95051ef2be5SMarek Vasut 
95151ef2be5SMarek Vasut static int isl7998x_pre_streamon(struct v4l2_subdev *sd, u32 flags)
95251ef2be5SMarek Vasut {
95351ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
95451ef2be5SMarek Vasut 	struct device *dev = &client->dev;
95551ef2be5SMarek Vasut 
95651ef2be5SMarek Vasut 	return pm_runtime_resume_and_get(dev);
95751ef2be5SMarek Vasut }
95851ef2be5SMarek Vasut 
95951ef2be5SMarek Vasut static int isl7998x_post_streamoff(struct v4l2_subdev *sd)
96051ef2be5SMarek Vasut {
96151ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
96251ef2be5SMarek Vasut 	struct device *dev = &client->dev;
96351ef2be5SMarek Vasut 
96451ef2be5SMarek Vasut 	pm_runtime_put(dev);
96551ef2be5SMarek Vasut 
96651ef2be5SMarek Vasut 	return 0;
96751ef2be5SMarek Vasut }
96851ef2be5SMarek Vasut 
96951ef2be5SMarek Vasut static int isl7998x_enum_mbus_code(struct v4l2_subdev *sd,
97051ef2be5SMarek Vasut 				   struct v4l2_subdev_state *sd_state,
97151ef2be5SMarek Vasut 				   struct v4l2_subdev_mbus_code_enum *code)
97251ef2be5SMarek Vasut {
97351ef2be5SMarek Vasut 	if (code->index >= ARRAY_SIZE(isl7998x_colour_fmts))
97451ef2be5SMarek Vasut 		return -EINVAL;
97551ef2be5SMarek Vasut 
97651ef2be5SMarek Vasut 	code->code = isl7998x_colour_fmts[code->index].code;
97751ef2be5SMarek Vasut 
97851ef2be5SMarek Vasut 	return 0;
97951ef2be5SMarek Vasut }
98051ef2be5SMarek Vasut 
98151ef2be5SMarek Vasut static int isl7998x_enum_frame_size(struct v4l2_subdev *sd,
98251ef2be5SMarek Vasut 				    struct v4l2_subdev_state *sd_state,
98351ef2be5SMarek Vasut 				    struct v4l2_subdev_frame_size_enum *fse)
98451ef2be5SMarek Vasut {
98551ef2be5SMarek Vasut 	if (fse->index >= ARRAY_SIZE(supported_modes))
98651ef2be5SMarek Vasut 		return -EINVAL;
98751ef2be5SMarek Vasut 
98851ef2be5SMarek Vasut 	if (fse->code != isl7998x_colour_fmts[0].code)
98951ef2be5SMarek Vasut 		return -EINVAL;
99051ef2be5SMarek Vasut 
99151ef2be5SMarek Vasut 	fse->min_width = supported_modes[fse->index].width;
99251ef2be5SMarek Vasut 	fse->max_width = fse->min_width;
99351ef2be5SMarek Vasut 	fse->min_height = supported_modes[fse->index].height;
99451ef2be5SMarek Vasut 	fse->max_height = fse->min_height;
99551ef2be5SMarek Vasut 
99651ef2be5SMarek Vasut 	return 0;
99751ef2be5SMarek Vasut }
99851ef2be5SMarek Vasut 
99951ef2be5SMarek Vasut static int isl7998x_get_fmt(struct v4l2_subdev *sd,
100051ef2be5SMarek Vasut 			    struct v4l2_subdev_state *sd_state,
100151ef2be5SMarek Vasut 			    struct v4l2_subdev_format *format)
100251ef2be5SMarek Vasut {
100351ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
100451ef2be5SMarek Vasut 	struct v4l2_mbus_framefmt *mf = &format->format;
100551ef2be5SMarek Vasut 	const struct isl7998x_mode *mode;
100651ef2be5SMarek Vasut 
100751ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
100851ef2be5SMarek Vasut 
100951ef2be5SMarek Vasut 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
101051ef2be5SMarek Vasut 		format->format = *v4l2_subdev_get_try_format(sd, sd_state,
101151ef2be5SMarek Vasut 							     format->pad);
101251ef2be5SMarek Vasut 		goto out;
101351ef2be5SMarek Vasut 	}
101451ef2be5SMarek Vasut 
101551ef2be5SMarek Vasut 	mode = isl7998x_norm_to_mode(isl7998x->norm);
101651ef2be5SMarek Vasut 
101751ef2be5SMarek Vasut 	mf->width	= mode->width;
101851ef2be5SMarek Vasut 	mf->height	= mode->height;
101951ef2be5SMarek Vasut 	mf->code	= isl7998x->fmt->code;
102051ef2be5SMarek Vasut 	mf->field	= mode->field;
102151ef2be5SMarek Vasut 	mf->colorspace	= 0;
102251ef2be5SMarek Vasut 
102351ef2be5SMarek Vasut out:
102451ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
102551ef2be5SMarek Vasut 
102651ef2be5SMarek Vasut 	return 0;
102751ef2be5SMarek Vasut }
102851ef2be5SMarek Vasut 
102951ef2be5SMarek Vasut static int isl7998x_set_fmt(struct v4l2_subdev *sd,
103051ef2be5SMarek Vasut 			    struct v4l2_subdev_state *sd_state,
103151ef2be5SMarek Vasut 			    struct v4l2_subdev_format *format)
103251ef2be5SMarek Vasut {
103351ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
103451ef2be5SMarek Vasut 	struct v4l2_mbus_framefmt *mf = &format->format;
103551ef2be5SMarek Vasut 	const struct isl7998x_mode *mode;
103651ef2be5SMarek Vasut 
103751ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
103851ef2be5SMarek Vasut 
103951ef2be5SMarek Vasut 	mode = isl7998x_norm_to_mode(isl7998x->norm);
104051ef2be5SMarek Vasut 
104151ef2be5SMarek Vasut 	mf->width = mode->width;
104251ef2be5SMarek Vasut 	mf->height = mode->height;
104351ef2be5SMarek Vasut 	mf->code = isl7998x->fmt->code;
104451ef2be5SMarek Vasut 	mf->field = mode->field;
104551ef2be5SMarek Vasut 
104651ef2be5SMarek Vasut 	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
104751ef2be5SMarek Vasut 		*v4l2_subdev_get_try_format(sd, sd_state, format->pad) = format->format;
104851ef2be5SMarek Vasut 
104951ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
105051ef2be5SMarek Vasut 
105151ef2be5SMarek Vasut 	return 0;
105251ef2be5SMarek Vasut }
105351ef2be5SMarek Vasut 
105451ef2be5SMarek Vasut static int isl7998x_set_ctrl(struct v4l2_ctrl *ctrl)
105551ef2be5SMarek Vasut {
105651ef2be5SMarek Vasut 	struct isl7998x *isl7998x = container_of(ctrl->handler,
105751ef2be5SMarek Vasut 						 struct isl7998x, ctrl_handler);
105851ef2be5SMarek Vasut 	int ret = 0;
105951ef2be5SMarek Vasut 
106051ef2be5SMarek Vasut 	switch (ctrl->id) {
106151ef2be5SMarek Vasut 	case V4L2_CID_TEST_PATTERN_BARS:
106251ef2be5SMarek Vasut 		mutex_lock(&isl7998x->lock);
106351ef2be5SMarek Vasut 		isl7998x->test_pattern_bars = ctrl->val & 0x3;
106451ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
106551ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
106651ef2be5SMarek Vasut 		break;
106751ef2be5SMarek Vasut 	case V4L2_CID_TEST_PATTERN_CHANNELS:
106851ef2be5SMarek Vasut 		mutex_lock(&isl7998x->lock);
106951ef2be5SMarek Vasut 		isl7998x->test_pattern_chans = ctrl->val & 0xf;
107051ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
107151ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
107251ef2be5SMarek Vasut 		break;
107351ef2be5SMarek Vasut 	case V4L2_CID_TEST_PATTERN_COLOR:
107451ef2be5SMarek Vasut 		mutex_lock(&isl7998x->lock);
107551ef2be5SMarek Vasut 		isl7998x->test_pattern_color = ctrl->val & 0x3;
107651ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
107751ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
107851ef2be5SMarek Vasut 		break;
107951ef2be5SMarek Vasut 	case V4L2_CID_TEST_PATTERN:
108051ef2be5SMarek Vasut 		mutex_lock(&isl7998x->lock);
108151ef2be5SMarek Vasut 		isl7998x->test_pattern = ctrl->val;
108251ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
108351ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
108451ef2be5SMarek Vasut 		break;
108551ef2be5SMarek Vasut 	}
108651ef2be5SMarek Vasut 
108751ef2be5SMarek Vasut 	return ret;
108851ef2be5SMarek Vasut }
108951ef2be5SMarek Vasut 
109051ef2be5SMarek Vasut static const struct v4l2_subdev_core_ops isl7998x_subdev_core_ops = {
109151ef2be5SMarek Vasut #ifdef CONFIG_VIDEO_ADV_DEBUG
109251ef2be5SMarek Vasut 	.g_register	= isl7998x_g_register,
109351ef2be5SMarek Vasut 	.s_register	= isl7998x_s_register,
109451ef2be5SMarek Vasut #endif
109551ef2be5SMarek Vasut };
109651ef2be5SMarek Vasut 
109751ef2be5SMarek Vasut static const struct v4l2_subdev_video_ops isl7998x_subdev_video_ops = {
109851ef2be5SMarek Vasut 	.g_std		= isl7998x_g_std,
109951ef2be5SMarek Vasut 	.s_std		= isl7998x_s_std,
110051ef2be5SMarek Vasut 	.querystd	= isl7998x_querystd,
110151ef2be5SMarek Vasut 	.g_tvnorms	= isl7998x_g_tvnorms,
110251ef2be5SMarek Vasut 	.g_input_status	= isl7998x_g_input_status,
110351ef2be5SMarek Vasut 	.s_stream	= isl7998x_s_stream,
110451ef2be5SMarek Vasut 	.pre_streamon	= isl7998x_pre_streamon,
110551ef2be5SMarek Vasut 	.post_streamoff	= isl7998x_post_streamoff,
110651ef2be5SMarek Vasut };
110751ef2be5SMarek Vasut 
110851ef2be5SMarek Vasut static const struct v4l2_subdev_pad_ops isl7998x_subdev_pad_ops = {
110951ef2be5SMarek Vasut 	.enum_mbus_code		= isl7998x_enum_mbus_code,
111051ef2be5SMarek Vasut 	.enum_frame_size	= isl7998x_enum_frame_size,
111151ef2be5SMarek Vasut 	.get_fmt		= isl7998x_get_fmt,
111251ef2be5SMarek Vasut 	.set_fmt		= isl7998x_set_fmt,
111351ef2be5SMarek Vasut };
111451ef2be5SMarek Vasut 
111551ef2be5SMarek Vasut static const struct v4l2_subdev_ops isl7998x_subdev_ops = {
111651ef2be5SMarek Vasut 	.core		= &isl7998x_subdev_core_ops,
111751ef2be5SMarek Vasut 	.video		= &isl7998x_subdev_video_ops,
111851ef2be5SMarek Vasut 	.pad		= &isl7998x_subdev_pad_ops,
111951ef2be5SMarek Vasut };
112051ef2be5SMarek Vasut 
112151ef2be5SMarek Vasut static const struct media_entity_operations isl7998x_entity_ops = {
112251ef2be5SMarek Vasut 	.link_validate = v4l2_subdev_link_validate,
112351ef2be5SMarek Vasut };
112451ef2be5SMarek Vasut 
112551ef2be5SMarek Vasut static const struct v4l2_ctrl_ops isl7998x_ctrl_ops = {
112651ef2be5SMarek Vasut 	.s_ctrl			= isl7998x_set_ctrl,
112751ef2be5SMarek Vasut };
112851ef2be5SMarek Vasut 
112951ef2be5SMarek Vasut static const struct v4l2_ctrl_config isl7998x_ctrls[] = {
113051ef2be5SMarek Vasut 	{
113151ef2be5SMarek Vasut 		.ops		= &isl7998x_ctrl_ops,
113251ef2be5SMarek Vasut 		.id		= V4L2_CID_TEST_PATTERN_BARS,
113351ef2be5SMarek Vasut 		.type		= V4L2_CTRL_TYPE_MENU,
113451ef2be5SMarek Vasut 		.name		= "Test Pattern Bars",
113551ef2be5SMarek Vasut 		.max		= ARRAY_SIZE(isl7998x_test_pattern_bars) - 1,
113651ef2be5SMarek Vasut 		.def		= 0,
113751ef2be5SMarek Vasut 		.qmenu		= isl7998x_test_pattern_bars,
113851ef2be5SMarek Vasut 	}, {
113951ef2be5SMarek Vasut 		.ops		= &isl7998x_ctrl_ops,
114051ef2be5SMarek Vasut 		.id		= V4L2_CID_TEST_PATTERN_CHANNELS,
114151ef2be5SMarek Vasut 		.type		= V4L2_CTRL_TYPE_INTEGER,
114251ef2be5SMarek Vasut 		.name		= "Test Pattern Channels",
114351ef2be5SMarek Vasut 		.min		= 0,
114451ef2be5SMarek Vasut 		.max		= 0xf,
114551ef2be5SMarek Vasut 		.step		= 1,
114651ef2be5SMarek Vasut 		.def		= 0xf,
114751ef2be5SMarek Vasut 		.flags		= 0,
114851ef2be5SMarek Vasut 	}, {
114951ef2be5SMarek Vasut 		.ops		= &isl7998x_ctrl_ops,
115051ef2be5SMarek Vasut 		.id		= V4L2_CID_TEST_PATTERN_COLOR,
115151ef2be5SMarek Vasut 		.type		= V4L2_CTRL_TYPE_MENU,
115251ef2be5SMarek Vasut 		.name		= "Test Pattern Color",
115351ef2be5SMarek Vasut 		.max		= ARRAY_SIZE(isl7998x_test_pattern_colors) - 1,
115451ef2be5SMarek Vasut 		.def		= 0,
115551ef2be5SMarek Vasut 		.qmenu		= isl7998x_test_pattern_colors,
115651ef2be5SMarek Vasut 	},
115751ef2be5SMarek Vasut };
115851ef2be5SMarek Vasut 
115951ef2be5SMarek Vasut #define ISL7998X_REG_DECODER_ACA_READABLE_RANGE(page)			\
116051ef2be5SMarek Vasut 	/* Decoder range */						\
116151ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_INPUT_FMT(page),		\
116251ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HS_DELAY_CTL(page)),	\
116351ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_ANCTL(page),		\
116451ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_CSC_CTL(page)),		\
116551ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_BRIGHT(page),		\
116651ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HUE(page)),		\
116751ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_VERT_PEAK(page),		\
116851ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_CORING(page)),		\
116951ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_SDT(page),			\
117051ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_SDTR(page)),		\
117151ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_CLMPG(page),		\
117251ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_DATA_CONV(page)),		\
117351ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_INTERNAL_TEST(page),	\
117451ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_INTERNAL_TEST(page)),	\
117551ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_H_DELAY_CTL(page),		\
117651ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(page)),	\
117751ef2be5SMarek Vasut 	/* ACA range */							\
117851ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_CTL_1(page),		\
117951ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(page)),	\
118051ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_Y_AVG(page),		\
118151ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_CTL_4(page)),		\
118251ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(page),	\
118351ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_XFER_HIST_HOST(page)),	\
118451ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(page),		\
118551ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(page))
118651ef2be5SMarek Vasut 
118751ef2be5SMarek Vasut #define ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(page)			\
118851ef2be5SMarek Vasut 	/* Decoder range */						\
118951ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_INPUT_FMT(page),		\
119051ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_INPUT_FMT(page)),		\
119151ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_HS_DELAY_CTL(page),	\
119251ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HS_DELAY_CTL(page)),	\
119351ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_ANCTL(page),		\
119451ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_CSC_CTL(page)),		\
119551ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_BRIGHT(page),		\
119651ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HUE(page)),		\
119751ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_VERT_PEAK(page),		\
119851ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_CORING(page)),		\
119951ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_SDT(page),			\
120051ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_SDTR(page)),		\
120151ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_CLMPG(page),		\
120251ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_MISC3(page)),		\
120351ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_CLMD(page),		\
120451ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_DATA_CONV(page)),		\
120551ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_INTERNAL_TEST(page),	\
120651ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_INTERNAL_TEST(page)),	\
120751ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_H_DELAY_CTL(page),		\
120851ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(page)),	\
120951ef2be5SMarek Vasut 	/* ACA range */							\
121051ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_CTL_1(page),		\
121151ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(page)),	\
121251ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_CTL_2(page),		\
121351ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_CTL_4(page)),		\
121451ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(page),	\
121551ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_HIST_DATA_LO(page)),	\
121651ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_XFER_HIST_HOST(page),	\
121751ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_XFER_HIST_HOST(page)),	\
121851ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(page),		\
121951ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(page))
122051ef2be5SMarek Vasut 
122151ef2be5SMarek Vasut #define ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(page)			\
122251ef2be5SMarek Vasut 	/* Decoder range */						\
122351ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_STATUS_1(page),		\
122451ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_STATUS_1(page)),		\
122551ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_SDT(page),			\
122651ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_SDT(page)),		\
122751ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_MVSN(page),		\
122851ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HFREF(page)),		\
122951ef2be5SMarek Vasut 	/* ACA range */							\
123051ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_Y_AVG(page),		\
123151ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_Y_HIGH(page)),		\
123251ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_HIST_DATA_LO(page),	\
123351ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_FLEX_WIN_CR_CLR(page))
123451ef2be5SMarek Vasut 
123551ef2be5SMarek Vasut static const struct regmap_range isl7998x_readable_ranges[] = {
123651ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_PRODUCT_ID_CODE,
123751ef2be5SMarek Vasut 			 ISL7998X_REG_P0_IRQ_SYNC_CTL),
123851ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_INTERRUPT_STATUS,
123951ef2be5SMarek Vasut 			 ISL7998X_REG_P0_CLOCK_DELAY),
124051ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(0),
124151ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(0)),
124251ef2be5SMarek Vasut 
124351ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_READABLE_RANGE(1),
124451ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_READABLE_RANGE(2),
124551ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_READABLE_RANGE(3),
124651ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_READABLE_RANGE(4),
124751ef2be5SMarek Vasut 
124851ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_LI_ENGINE_CTL,
124951ef2be5SMarek Vasut 			 ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL),
125051ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_FIFO_THRSH_CNT_1,
125151ef2be5SMarek Vasut 			 ISL7998X_REG_P5_PLL_ANA),
125251ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1,
125351ef2be5SMarek Vasut 			 ISL7998X_REG_P5_HIST_LINE_CNT_2),
125451ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(5),
125551ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(5)),
125651ef2be5SMarek Vasut };
125751ef2be5SMarek Vasut 
125851ef2be5SMarek Vasut static const struct regmap_range isl7998x_writeable_ranges[] = {
125951ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_SW_RESET_CTL,
126051ef2be5SMarek Vasut 			 ISL7998X_REG_P0_IRQ_SYNC_CTL),
126151ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_CHAN_1_IRQ,
126251ef2be5SMarek Vasut 			 ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN),
126351ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_CLOCK_DELAY,
126451ef2be5SMarek Vasut 			 ISL7998X_REG_P0_CLOCK_DELAY),
126551ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(0),
126651ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(0)),
126751ef2be5SMarek Vasut 
126851ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(1),
126951ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(2),
127051ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(3),
127151ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(4),
127251ef2be5SMarek Vasut 
127351ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_LI_ENGINE_CTL,
127451ef2be5SMarek Vasut 			 ISL7998X_REG_P5_ESC_MODE_TIME_CTL),
127551ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL,
127651ef2be5SMarek Vasut 			 ISL7998X_REG_P5_PLL_ANA),
127751ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1,
127851ef2be5SMarek Vasut 			 ISL7998X_REG_P5_HIST_LINE_CNT_2),
127951ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(5),
128051ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(5)),
128151ef2be5SMarek Vasut 
128251ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(0xf),
128351ef2be5SMarek Vasut };
128451ef2be5SMarek Vasut 
128551ef2be5SMarek Vasut static const struct regmap_range isl7998x_volatile_ranges[] = {
128651ef2be5SMarek Vasut 	/* Product id code register is used to check availability */
128751ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_PRODUCT_ID_CODE,
128851ef2be5SMarek Vasut 			 ISL7998X_REG_P0_PRODUCT_ID_CODE),
128951ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_MPP1_SYNC_CTL,
129051ef2be5SMarek Vasut 			 ISL7998X_REG_P0_IRQ_SYNC_CTL),
129151ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_INTERRUPT_STATUS,
129251ef2be5SMarek Vasut 			 ISL7998X_REG_P0_INTERRUPT_STATUS),
129351ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_CHAN_1_STATUS,
129451ef2be5SMarek Vasut 			 ISL7998X_REG_P0_SHORT_DIAG_STATUS),
129551ef2be5SMarek Vasut 
129651ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(1),
129751ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(2),
129851ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(3),
129951ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(4),
130051ef2be5SMarek Vasut 
130151ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_AUTO_TEST_ERR_DET,
130251ef2be5SMarek Vasut 			 ISL7998X_REG_P5_PIC_HEIGHT_LOW),
130351ef2be5SMarek Vasut };
130451ef2be5SMarek Vasut 
130551ef2be5SMarek Vasut static const struct regmap_access_table isl7998x_readable_table = {
130651ef2be5SMarek Vasut 	.yes_ranges = isl7998x_readable_ranges,
130751ef2be5SMarek Vasut 	.n_yes_ranges = ARRAY_SIZE(isl7998x_readable_ranges),
130851ef2be5SMarek Vasut };
130951ef2be5SMarek Vasut 
131051ef2be5SMarek Vasut static const struct regmap_access_table isl7998x_writeable_table = {
131151ef2be5SMarek Vasut 	.yes_ranges = isl7998x_writeable_ranges,
131251ef2be5SMarek Vasut 	.n_yes_ranges = ARRAY_SIZE(isl7998x_writeable_ranges),
131351ef2be5SMarek Vasut };
131451ef2be5SMarek Vasut 
131551ef2be5SMarek Vasut static const struct regmap_access_table isl7998x_volatile_table = {
131651ef2be5SMarek Vasut 	.yes_ranges = isl7998x_volatile_ranges,
131751ef2be5SMarek Vasut 	.n_yes_ranges = ARRAY_SIZE(isl7998x_volatile_ranges),
131851ef2be5SMarek Vasut };
131951ef2be5SMarek Vasut 
132051ef2be5SMarek Vasut static const struct regmap_range_cfg isl7998x_ranges[] = {
132151ef2be5SMarek Vasut 	{
132251ef2be5SMarek Vasut 		.range_min	= ISL7998X_REG_PN_BASE(0),
132351ef2be5SMarek Vasut 		.range_max	= ISL7998X_REG_PX_ACA_XFER_HIST_HOST(0xf),
132451ef2be5SMarek Vasut 		.selector_reg	= ISL7998X_REG_PX_DEC_PAGE(0),
132551ef2be5SMarek Vasut 		.selector_mask	= ISL7998X_REG_PX_DEC_PAGE_MASK,
132651ef2be5SMarek Vasut 		.window_start	= 0,
132751ef2be5SMarek Vasut 		.window_len	= 256,
132851ef2be5SMarek Vasut 	}
132951ef2be5SMarek Vasut };
133051ef2be5SMarek Vasut 
133151ef2be5SMarek Vasut static const struct regmap_config isl7998x_regmap = {
133251ef2be5SMarek Vasut 	.reg_bits	= 8,
133351ef2be5SMarek Vasut 	.val_bits	= 8,
133451ef2be5SMarek Vasut 	.max_register	= ISL7998X_REG_PX_ACA_XFER_HIST_HOST(0xf),
133551ef2be5SMarek Vasut 	.ranges		= isl7998x_ranges,
133651ef2be5SMarek Vasut 	.num_ranges	= ARRAY_SIZE(isl7998x_ranges),
133751ef2be5SMarek Vasut 	.rd_table	= &isl7998x_readable_table,
133851ef2be5SMarek Vasut 	.wr_table	= &isl7998x_writeable_table,
133951ef2be5SMarek Vasut 	.volatile_table	= &isl7998x_volatile_table,
134051ef2be5SMarek Vasut 	.cache_type	= REGCACHE_RBTREE,
134151ef2be5SMarek Vasut };
134251ef2be5SMarek Vasut 
134351ef2be5SMarek Vasut static int isl7998x_mc_init(struct isl7998x *isl7998x)
134451ef2be5SMarek Vasut {
134551ef2be5SMarek Vasut 	unsigned int i;
134651ef2be5SMarek Vasut 
134751ef2be5SMarek Vasut 	isl7998x->subdev.entity.ops = &isl7998x_entity_ops;
134851ef2be5SMarek Vasut 	isl7998x->subdev.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
134951ef2be5SMarek Vasut 
135051ef2be5SMarek Vasut 	isl7998x->pads[ISL7998X_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE;
135151ef2be5SMarek Vasut 	for (i = ISL7998X_PAD_VIN1; i < ISL7998X_NUM_PADS; i++)
135251ef2be5SMarek Vasut 		isl7998x->pads[i].flags = MEDIA_PAD_FL_SINK;
135351ef2be5SMarek Vasut 
135451ef2be5SMarek Vasut 	return media_entity_pads_init(&isl7998x->subdev.entity,
135551ef2be5SMarek Vasut 				      ISL7998X_NUM_PADS,
135651ef2be5SMarek Vasut 				      isl7998x->pads);
135751ef2be5SMarek Vasut }
135851ef2be5SMarek Vasut 
135951ef2be5SMarek Vasut static int get_link_freq_menu_index(unsigned int lanes,
136051ef2be5SMarek Vasut 				    unsigned int inputs)
136151ef2be5SMarek Vasut {
136251ef2be5SMarek Vasut 	int ret = -EINVAL;
136351ef2be5SMarek Vasut 
136451ef2be5SMarek Vasut 	switch (lanes) {
136551ef2be5SMarek Vasut 	case 1:
136651ef2be5SMarek Vasut 		if (inputs == 1)
136751ef2be5SMarek Vasut 			ret = 0;
136851ef2be5SMarek Vasut 		if (inputs == 2)
136951ef2be5SMarek Vasut 			ret = 1;
137051ef2be5SMarek Vasut 		if (inputs == 4)
137151ef2be5SMarek Vasut 			ret = 2;
137251ef2be5SMarek Vasut 		break;
137351ef2be5SMarek Vasut 	case 2:
137451ef2be5SMarek Vasut 		if (inputs == 2)
137551ef2be5SMarek Vasut 			ret = 0;
137651ef2be5SMarek Vasut 		if (inputs == 4)
137751ef2be5SMarek Vasut 			ret = 1;
137851ef2be5SMarek Vasut 		break;
137951ef2be5SMarek Vasut 	default:
138051ef2be5SMarek Vasut 		break;
138151ef2be5SMarek Vasut 	}
138251ef2be5SMarek Vasut 
138351ef2be5SMarek Vasut 	return ret;
138451ef2be5SMarek Vasut }
138551ef2be5SMarek Vasut 
138651ef2be5SMarek Vasut static void isl7998x_remove_controls(struct isl7998x *isl7998x)
138751ef2be5SMarek Vasut {
138851ef2be5SMarek Vasut 	v4l2_ctrl_handler_free(&isl7998x->ctrl_handler);
138951ef2be5SMarek Vasut 	mutex_destroy(&isl7998x->ctrl_mutex);
139051ef2be5SMarek Vasut }
139151ef2be5SMarek Vasut 
139251ef2be5SMarek Vasut static int isl7998x_init_controls(struct isl7998x *isl7998x)
139351ef2be5SMarek Vasut {
139451ef2be5SMarek Vasut 	struct v4l2_subdev *sd = &isl7998x->subdev;
139551ef2be5SMarek Vasut 	int link_freq_index;
139651ef2be5SMarek Vasut 	unsigned int i;
139751ef2be5SMarek Vasut 	int ret;
139851ef2be5SMarek Vasut 
139951ef2be5SMarek Vasut 	ret = v4l2_ctrl_handler_init(&isl7998x->ctrl_handler,
140051ef2be5SMarek Vasut 				     2 + ARRAY_SIZE(isl7998x_ctrls));
140151ef2be5SMarek Vasut 	if (ret)
140251ef2be5SMarek Vasut 		return ret;
140351ef2be5SMarek Vasut 
140451ef2be5SMarek Vasut 	mutex_init(&isl7998x->ctrl_mutex);
140551ef2be5SMarek Vasut 	isl7998x->ctrl_handler.lock = &isl7998x->ctrl_mutex;
140651ef2be5SMarek Vasut 	link_freq_index = get_link_freq_menu_index(isl7998x->nr_mipi_lanes,
140751ef2be5SMarek Vasut 						   isl7998x->nr_inputs);
140851ef2be5SMarek Vasut 	if (link_freq_index < 0 ||
140951ef2be5SMarek Vasut 	    link_freq_index >= ARRAY_SIZE(link_freq_menu_items)) {
141051ef2be5SMarek Vasut 		dev_err(sd->dev,
141151ef2be5SMarek Vasut 			"failed to find MIPI link freq: %d lanes, %d inputs\n",
141251ef2be5SMarek Vasut 			isl7998x->nr_mipi_lanes, isl7998x->nr_inputs);
141351ef2be5SMarek Vasut 		ret = -EINVAL;
141451ef2be5SMarek Vasut 		goto err;
141551ef2be5SMarek Vasut 	}
141651ef2be5SMarek Vasut 
141751ef2be5SMarek Vasut 	isl7998x->link_freq = v4l2_ctrl_new_int_menu(&isl7998x->ctrl_handler,
141851ef2be5SMarek Vasut 						     &isl7998x_ctrl_ops,
141951ef2be5SMarek Vasut 						     V4L2_CID_LINK_FREQ,
142051ef2be5SMarek Vasut 						     ARRAY_SIZE(link_freq_menu_items) - 1,
142151ef2be5SMarek Vasut 						     link_freq_index,
142251ef2be5SMarek Vasut 						     link_freq_menu_items);
142351ef2be5SMarek Vasut 	if (isl7998x->link_freq)
142451ef2be5SMarek Vasut 		isl7998x->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
142551ef2be5SMarek Vasut 
142651ef2be5SMarek Vasut 	for (i = 0; i < ARRAY_SIZE(isl7998x_ctrls); i++)
142751ef2be5SMarek Vasut 		v4l2_ctrl_new_custom(&isl7998x->ctrl_handler,
142851ef2be5SMarek Vasut 				     &isl7998x_ctrls[i], NULL);
142951ef2be5SMarek Vasut 
143051ef2be5SMarek Vasut 	v4l2_ctrl_new_std_menu_items(&isl7998x->ctrl_handler,
143151ef2be5SMarek Vasut 				     &isl7998x_ctrl_ops,
143251ef2be5SMarek Vasut 				     V4L2_CID_TEST_PATTERN,
143351ef2be5SMarek Vasut 				     ARRAY_SIZE(isl7998x_test_pattern_menu) - 1,
143451ef2be5SMarek Vasut 				     0, 0, isl7998x_test_pattern_menu);
143551ef2be5SMarek Vasut 
143651ef2be5SMarek Vasut 	ret = isl7998x->ctrl_handler.error;
143751ef2be5SMarek Vasut 	if (ret)
143851ef2be5SMarek Vasut 		goto err;
143951ef2be5SMarek Vasut 
144051ef2be5SMarek Vasut 	isl7998x->subdev.ctrl_handler = &isl7998x->ctrl_handler;
144151ef2be5SMarek Vasut 	v4l2_ctrl_handler_setup(&isl7998x->ctrl_handler);
144251ef2be5SMarek Vasut 
144351ef2be5SMarek Vasut 	return 0;
144451ef2be5SMarek Vasut 
144551ef2be5SMarek Vasut err:
144651ef2be5SMarek Vasut 	isl7998x_remove_controls(isl7998x);
144751ef2be5SMarek Vasut 
144851ef2be5SMarek Vasut 	return ret;
144951ef2be5SMarek Vasut }
145051ef2be5SMarek Vasut 
145151ef2be5SMarek Vasut static int isl7998x_probe(struct i2c_client *client)
145251ef2be5SMarek Vasut {
145351ef2be5SMarek Vasut 	struct device *dev = &client->dev;
145451ef2be5SMarek Vasut 	struct v4l2_fwnode_endpoint endpoint = {
145551ef2be5SMarek Vasut 		.bus_type = V4L2_MBUS_CSI2_DPHY,
145651ef2be5SMarek Vasut 	};
145751ef2be5SMarek Vasut 	struct fwnode_handle *ep;
145851ef2be5SMarek Vasut 	struct isl7998x *isl7998x;
145951ef2be5SMarek Vasut 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
146051ef2be5SMarek Vasut 	int nr_inputs;
146151ef2be5SMarek Vasut 	int ret;
146251ef2be5SMarek Vasut 
146351ef2be5SMarek Vasut 	ret = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA);
146451ef2be5SMarek Vasut 	if (!ret) {
146551ef2be5SMarek Vasut 		dev_warn(&adapter->dev,
146651ef2be5SMarek Vasut 			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
146751ef2be5SMarek Vasut 		return -EIO;
146851ef2be5SMarek Vasut 	}
146951ef2be5SMarek Vasut 
147051ef2be5SMarek Vasut 	isl7998x = devm_kzalloc(dev, sizeof(*isl7998x), GFP_KERNEL);
147151ef2be5SMarek Vasut 	if (!isl7998x)
147251ef2be5SMarek Vasut 		return -ENOMEM;
147351ef2be5SMarek Vasut 
147451ef2be5SMarek Vasut 	isl7998x->pd_gpio = devm_gpiod_get_optional(dev, "powerdown",
147551ef2be5SMarek Vasut 						    GPIOD_OUT_HIGH);
147651ef2be5SMarek Vasut 	if (IS_ERR(isl7998x->pd_gpio))
147751ef2be5SMarek Vasut 		return dev_err_probe(dev, PTR_ERR(isl7998x->pd_gpio),
147851ef2be5SMarek Vasut 				     "Failed to retrieve/request PD GPIO\n");
147951ef2be5SMarek Vasut 
148051ef2be5SMarek Vasut 	isl7998x->rstb_gpio = devm_gpiod_get_optional(dev, "reset",
148151ef2be5SMarek Vasut 						      GPIOD_OUT_HIGH);
148251ef2be5SMarek Vasut 	if (IS_ERR(isl7998x->rstb_gpio))
148351ef2be5SMarek Vasut 		return dev_err_probe(dev, PTR_ERR(isl7998x->rstb_gpio),
148451ef2be5SMarek Vasut 				     "Failed to retrieve/request RSTB GPIO\n");
148551ef2be5SMarek Vasut 
148651ef2be5SMarek Vasut 	isl7998x->regmap = devm_regmap_init_i2c(client, &isl7998x_regmap);
148751ef2be5SMarek Vasut 	if (IS_ERR(isl7998x->regmap))
148851ef2be5SMarek Vasut 		return dev_err_probe(dev, PTR_ERR(isl7998x->regmap),
148951ef2be5SMarek Vasut 				     "Failed to allocate register map\n");
149051ef2be5SMarek Vasut 
149151ef2be5SMarek Vasut 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
149251ef2be5SMarek Vasut 					     ISL7998X_PAD_OUT, 0, 0);
149351ef2be5SMarek Vasut 	if (!ep)
149451ef2be5SMarek Vasut 		return dev_err_probe(dev, -EINVAL, "Missing endpoint node\n");
149551ef2be5SMarek Vasut 
149651ef2be5SMarek Vasut 	ret = v4l2_fwnode_endpoint_parse(ep, &endpoint);
149751ef2be5SMarek Vasut 	fwnode_handle_put(ep);
149851ef2be5SMarek Vasut 	if (ret)
149951ef2be5SMarek Vasut 		return dev_err_probe(dev, ret, "Failed to parse endpoint\n");
150051ef2be5SMarek Vasut 
150151ef2be5SMarek Vasut 	if (endpoint.bus.mipi_csi2.num_data_lanes == 0 ||
150251ef2be5SMarek Vasut 	    endpoint.bus.mipi_csi2.num_data_lanes > 2)
150351ef2be5SMarek Vasut 		return dev_err_probe(dev, -EINVAL,
150451ef2be5SMarek Vasut 				     "Invalid number of MIPI lanes\n");
150551ef2be5SMarek Vasut 
150651ef2be5SMarek Vasut 	isl7998x->nr_mipi_lanes = endpoint.bus.mipi_csi2.num_data_lanes;
150751ef2be5SMarek Vasut 
150851ef2be5SMarek Vasut 	nr_inputs = isl7998x_get_nr_inputs(dev->of_node);
150951ef2be5SMarek Vasut 	if (nr_inputs < 0)
151051ef2be5SMarek Vasut 		return dev_err_probe(dev, nr_inputs,
151151ef2be5SMarek Vasut 				     "Invalid number of input ports\n");
151251ef2be5SMarek Vasut 	isl7998x->nr_inputs = nr_inputs;
151351ef2be5SMarek Vasut 
151451ef2be5SMarek Vasut 	v4l2_i2c_subdev_init(&isl7998x->subdev, client, &isl7998x_subdev_ops);
151551ef2be5SMarek Vasut 	isl7998x->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
151651ef2be5SMarek Vasut 
151751ef2be5SMarek Vasut 	ret = isl7998x_mc_init(isl7998x);
151851ef2be5SMarek Vasut 	if (ret < 0)
151951ef2be5SMarek Vasut 		return ret;
152051ef2be5SMarek Vasut 
152151ef2be5SMarek Vasut 	isl7998x->fmt = &isl7998x_colour_fmts[0];
152251ef2be5SMarek Vasut 	isl7998x->norm = V4L2_STD_NTSC;
152351ef2be5SMarek Vasut 	isl7998x->enabled = 0;
152451ef2be5SMarek Vasut 
152551ef2be5SMarek Vasut 	mutex_init(&isl7998x->lock);
152651ef2be5SMarek Vasut 
152751ef2be5SMarek Vasut 	ret = isl7998x_init_controls(isl7998x);
152851ef2be5SMarek Vasut 	if (ret)
152951ef2be5SMarek Vasut 		goto err_entity_cleanup;
153051ef2be5SMarek Vasut 
153151ef2be5SMarek Vasut 	ret = v4l2_async_register_subdev(&isl7998x->subdev);
153251ef2be5SMarek Vasut 	if (ret < 0)
153351ef2be5SMarek Vasut 		goto err_controls_cleanup;
153451ef2be5SMarek Vasut 
153551ef2be5SMarek Vasut 	pm_runtime_enable(dev);
153651ef2be5SMarek Vasut 
153751ef2be5SMarek Vasut 	return 0;
153851ef2be5SMarek Vasut 
153951ef2be5SMarek Vasut err_controls_cleanup:
154051ef2be5SMarek Vasut 	isl7998x_remove_controls(isl7998x);
154151ef2be5SMarek Vasut err_entity_cleanup:
154251ef2be5SMarek Vasut 	media_entity_cleanup(&isl7998x->subdev.entity);
154351ef2be5SMarek Vasut 
154451ef2be5SMarek Vasut 	return ret;
154551ef2be5SMarek Vasut }
154651ef2be5SMarek Vasut 
1547ed5c2f5fSUwe Kleine-König static void isl7998x_remove(struct i2c_client *client)
154851ef2be5SMarek Vasut {
154951ef2be5SMarek Vasut 	struct isl7998x *isl7998x = i2c_to_isl7998x(client);
155051ef2be5SMarek Vasut 
155151ef2be5SMarek Vasut 	pm_runtime_disable(&client->dev);
155251ef2be5SMarek Vasut 	v4l2_async_unregister_subdev(&isl7998x->subdev);
155351ef2be5SMarek Vasut 	isl7998x_remove_controls(isl7998x);
155451ef2be5SMarek Vasut 	media_entity_cleanup(&isl7998x->subdev.entity);
155551ef2be5SMarek Vasut }
155651ef2be5SMarek Vasut 
155751ef2be5SMarek Vasut static const struct of_device_id isl7998x_of_match[] = {
155851ef2be5SMarek Vasut 	{ .compatible = "isil,isl79987", },
155951ef2be5SMarek Vasut 	{ /* sentinel */ },
156051ef2be5SMarek Vasut };
156151ef2be5SMarek Vasut MODULE_DEVICE_TABLE(of, isl7998x_of_match);
156251ef2be5SMarek Vasut 
156351ef2be5SMarek Vasut static const struct i2c_device_id isl7998x_id[] = {
156451ef2be5SMarek Vasut 	{ "isl79987", 0 },
156551ef2be5SMarek Vasut 	{ /* sentinel */ },
156651ef2be5SMarek Vasut };
156751ef2be5SMarek Vasut MODULE_DEVICE_TABLE(i2c, isl7998x_id);
156851ef2be5SMarek Vasut 
156951ef2be5SMarek Vasut static int __maybe_unused isl7998x_runtime_resume(struct device *dev)
157051ef2be5SMarek Vasut {
157151ef2be5SMarek Vasut 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
157251ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
157351ef2be5SMarek Vasut 	int ret;
157451ef2be5SMarek Vasut 
157551ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->rstb_gpio, 1);
157651ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->pd_gpio, 0);
157751ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->rstb_gpio, 0);
157851ef2be5SMarek Vasut 
157951ef2be5SMarek Vasut 	ret = isl7998x_wait_power_on(isl7998x);
158051ef2be5SMarek Vasut 	if (ret)
158151ef2be5SMarek Vasut 		goto err;
158251ef2be5SMarek Vasut 
158351ef2be5SMarek Vasut 	ret = isl7998x_init(isl7998x);
158451ef2be5SMarek Vasut 	if (ret)
158551ef2be5SMarek Vasut 		goto err;
158651ef2be5SMarek Vasut 
158751ef2be5SMarek Vasut 	return 0;
158851ef2be5SMarek Vasut 
158951ef2be5SMarek Vasut err:
159051ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->pd_gpio, 1);
159151ef2be5SMarek Vasut 
159251ef2be5SMarek Vasut 	return ret;
159351ef2be5SMarek Vasut }
159451ef2be5SMarek Vasut 
159551ef2be5SMarek Vasut static int __maybe_unused isl7998x_runtime_suspend(struct device *dev)
159651ef2be5SMarek Vasut {
159751ef2be5SMarek Vasut 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
159851ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
159951ef2be5SMarek Vasut 
160051ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->pd_gpio, 1);
160151ef2be5SMarek Vasut 
160251ef2be5SMarek Vasut 	return 0;
160351ef2be5SMarek Vasut }
160451ef2be5SMarek Vasut 
160551ef2be5SMarek Vasut static const struct dev_pm_ops isl7998x_pm_ops = {
160651ef2be5SMarek Vasut 	SET_RUNTIME_PM_OPS(isl7998x_runtime_suspend,
160751ef2be5SMarek Vasut 			   isl7998x_runtime_resume,
160851ef2be5SMarek Vasut 			   NULL)
160951ef2be5SMarek Vasut };
161051ef2be5SMarek Vasut 
161151ef2be5SMarek Vasut static struct i2c_driver isl7998x_i2c_driver = {
161251ef2be5SMarek Vasut 	.driver = {
161351ef2be5SMarek Vasut 		.name = "isl7998x",
161451ef2be5SMarek Vasut 		.of_match_table = of_match_ptr(isl7998x_of_match),
161551ef2be5SMarek Vasut 		.pm = &isl7998x_pm_ops,
161651ef2be5SMarek Vasut 	},
1617*aaeb31c0SUwe Kleine-König 	.probe		= isl7998x_probe,
161851ef2be5SMarek Vasut 	.remove		= isl7998x_remove,
161951ef2be5SMarek Vasut 	.id_table	= isl7998x_id,
162051ef2be5SMarek Vasut };
162151ef2be5SMarek Vasut 
162251ef2be5SMarek Vasut module_i2c_driver(isl7998x_i2c_driver);
162351ef2be5SMarek Vasut 
162451ef2be5SMarek Vasut MODULE_DESCRIPTION("Intersil ISL7998x Analog to MIPI CSI-2/BT656 decoder");
162551ef2be5SMarek Vasut MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
162651ef2be5SMarek Vasut MODULE_LICENSE("GPL v2");
1627