cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

isl7998x.c (55715B)


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