2022-02-17 16:44:07 +01:00
// SPDX-License-Identifier: GPL-2.0
/*
* Intersil ISL7998x analog to MIPI CSI - 2 or BT .656 decoder driver .
*
* Copyright ( C ) 2018 - 2019 Marek Vasut < marex @ denx . de >
* Copyright ( C ) 2021 Michael Tretter < kernel @ pengutronix . de >
*/
# include <linux/bitfield.h>
# include <linux/delay.h>
2022-08-30 23:11:10 +02:00
# include <linux/gpio/consumer.h>
2022-02-17 16:44:07 +01:00
# include <linux/i2c.h>
# include <linux/module.h>
# include <linux/of_graph.h>
# include <linux/pm_runtime.h>
# include <linux/regmap.h>
# include <linux/slab.h>
# include <linux/v4l2-mediabus.h>
# include <linux/videodev2.h>
# include <media/v4l2-async.h>
# include <media/v4l2-common.h>
# include <media/v4l2-ctrls.h>
# include <media/v4l2-device.h>
# include <media/v4l2-fwnode.h>
# include <media/v4l2-ioctl.h>
/*
* This control allows to activate and deactivate the test pattern on
* selected output channels .
* This value is ISL7998x specific .
*/
# define V4L2_CID_TEST_PATTERN_CHANNELS (V4L2_CID_USER_ISL7998X_BASE + 0)
/*
* This control allows to specify the color of the test pattern .
* This value is ISL7998x specific .
*/
# define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_ISL7998X_BASE + 1)
/*
* This control allows to specify the bar pattern in the test pattern .
* This value is ISL7998x specific .
*/
# define V4L2_CID_TEST_PATTERN_BARS (V4L2_CID_USER_ISL7998X_BASE + 2)
# define ISL7998X_INPUTS 4
# define ISL7998X_REG(page, reg) (((page) << 8) | (reg))
# define ISL7998X_REG_PN_SIZE 256
# define ISL7998X_REG_PN_BASE(n) ((n) * ISL7998X_REG_PN_SIZE)
# define ISL7998X_REG_PX_DEC_PAGE(page) ISL7998X_REG((page), 0xff)
# define ISL7998X_REG_PX_DEC_PAGE_MASK 0xf
# define ISL7998X_REG_P0_PRODUCT_ID_CODE ISL7998X_REG(0, 0x00)
# define ISL7998X_REG_P0_PRODUCT_REV_CODE ISL7998X_REG(0, 0x01)
# define ISL7998X_REG_P0_SW_RESET_CTL ISL7998X_REG(0, 0x02)
# define ISL7998X_REG_P0_IO_BUFFER_CTL ISL7998X_REG(0, 0x03)
# define ISL7998X_REG_P0_IO_BUFFER_CTL_1_1 ISL7998X_REG(0, 0x04)
# define ISL7998X_REG_P0_IO_PAD_PULL_EN_CTL ISL7998X_REG(0, 0x05)
# define ISL7998X_REG_P0_IO_BUFFER_CTL_1_2 ISL7998X_REG(0, 0x06)
# define ISL7998X_REG_P0_VIDEO_IN_CHAN_CTL ISL7998X_REG(0, 0x07)
# define ISL7998X_REG_P0_CLK_CTL_1 ISL7998X_REG(0, 0x08)
# define ISL7998X_REG_P0_CLK_CTL_2 ISL7998X_REG(0, 0x09)
# define ISL7998X_REG_P0_CLK_CTL_3 ISL7998X_REG(0, 0x0a)
# define ISL7998X_REG_P0_CLK_CTL_4 ISL7998X_REG(0, 0x0b)
# define ISL7998X_REG_P0_MPP1_SYNC_CTL ISL7998X_REG(0, 0x0c)
# define ISL7998X_REG_P0_MPP2_SYNC_CTL ISL7998X_REG(0, 0x0d)
# define ISL7998X_REG_P0_IRQ_SYNC_CTL ISL7998X_REG(0, 0x0e)
# define ISL7998X_REG_P0_INTERRUPT_STATUS ISL7998X_REG(0, 0x10)
# define ISL7998X_REG_P0_CHAN_1_IRQ ISL7998X_REG(0, 0x11)
# define ISL7998X_REG_P0_CHAN_2_IRQ ISL7998X_REG(0, 0x12)
# define ISL7998X_REG_P0_CHAN_3_IRQ ISL7998X_REG(0, 0x13)
# define ISL7998X_REG_P0_CHAN_4_IRQ ISL7998X_REG(0, 0x14)
# define ISL7998X_REG_P0_SHORT_DIAG_IRQ ISL7998X_REG(0, 0x15)
# define ISL7998X_REG_P0_CHAN_1_IRQ_EN ISL7998X_REG(0, 0x16)
# define ISL7998X_REG_P0_CHAN_2_IRQ_EN ISL7998X_REG(0, 0x17)
# define ISL7998X_REG_P0_CHAN_3_IRQ_EN ISL7998X_REG(0, 0x18)
# define ISL7998X_REG_P0_CHAN_4_IRQ_EN ISL7998X_REG(0, 0x19)
# define ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN ISL7998X_REG(0, 0x1a)
# define ISL7998X_REG_P0_CHAN_1_STATUS ISL7998X_REG(0, 0x1b)
# define ISL7998X_REG_P0_CHAN_2_STATUS ISL7998X_REG(0, 0x1c)
# define ISL7998X_REG_P0_CHAN_3_STATUS ISL7998X_REG(0, 0x1d)
# define ISL7998X_REG_P0_CHAN_4_STATUS ISL7998X_REG(0, 0x1e)
# define ISL7998X_REG_P0_SHORT_DIAG_STATUS ISL7998X_REG(0, 0x1f)
# define ISL7998X_REG_P0_CLOCK_DELAY ISL7998X_REG(0, 0x20)
# define ISL7998X_REG_PX_DEC_INPUT_FMT(pg) ISL7998X_REG((pg), 0x02)
# define ISL7998X_REG_PX_DEC_STATUS_1(pg) ISL7998X_REG((pg), 0x03)
# define ISL7998X_REG_PX_DEC_STATUS_1_VDLOSS BIT(7)
# define ISL7998X_REG_PX_DEC_STATUS_1_HLOCK BIT(6)
# define ISL7998X_REG_PX_DEC_STATUS_1_VLOCK BIT(3)
# define ISL7998X_REG_PX_DEC_HS_DELAY_CTL(pg) ISL7998X_REG((pg), 0x04)
# define ISL7998X_REG_PX_DEC_ANCTL(pg) ISL7998X_REG((pg), 0x06)
# define ISL7998X_REG_PX_DEC_CROP_HI(pg) ISL7998X_REG((pg), 0x07)
# define ISL7998X_REG_PX_DEC_VDELAY_LO(pg) ISL7998X_REG((pg), 0x08)
# define ISL7998X_REG_PX_DEC_VACTIVE_LO(pg) ISL7998X_REG((pg), 0x09)
# define ISL7998X_REG_PX_DEC_HDELAY_LO(pg) ISL7998X_REG((pg), 0x0a)
# define ISL7998X_REG_PX_DEC_HACTIVE_LO(pg) ISL7998X_REG((pg), 0x0b)
# define ISL7998X_REG_PX_DEC_CNTRL1(pg) ISL7998X_REG((pg), 0x0c)
# define ISL7998X_REG_PX_DEC_CSC_CTL(pg) ISL7998X_REG((pg), 0x0d)
# define ISL7998X_REG_PX_DEC_BRIGHT(pg) ISL7998X_REG((pg), 0x10)
# define ISL7998X_REG_PX_DEC_CONTRAST(pg) ISL7998X_REG((pg), 0x11)
# define ISL7998X_REG_PX_DEC_SHARPNESS(pg) ISL7998X_REG((pg), 0x12)
# define ISL7998X_REG_PX_DEC_SAT_U(pg) ISL7998X_REG((pg), 0x13)
# define ISL7998X_REG_PX_DEC_SAT_V(pg) ISL7998X_REG((pg), 0x14)
# define ISL7998X_REG_PX_DEC_HUE(pg) ISL7998X_REG((pg), 0x15)
# define ISL7998X_REG_PX_DEC_VERT_PEAK(pg) ISL7998X_REG((pg), 0x17)
# define ISL7998X_REG_PX_DEC_CORING(pg) ISL7998X_REG((pg), 0x18)
# define ISL7998X_REG_PX_DEC_SDT(pg) ISL7998X_REG((pg), 0x1c)
# define ISL7998X_REG_PX_DEC_SDT_DET BIT(7)
# define ISL7998X_REG_PX_DEC_SDT_NOW GENMASK(6, 4)
# define ISL7998X_REG_PX_DEC_SDT_STANDARD GENMASK(2, 0)
# define ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_M 0
# define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL 1
# define ISL7998X_REG_PX_DEC_SDT_STANDARD_SECAM 2
# define ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_443 3
# define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_M 4
# define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_CN 5
# define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_60 6
# define ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN 7
# define ISL7998X_REG_PX_DEC_SDTR(pg) ISL7998X_REG((pg), 0x1d)
# define ISL7998X_REG_PX_DEC_SDTR_ATSTART BIT(7)
# define ISL7998X_REG_PX_DEC_CLMPG(pg) ISL7998X_REG((pg), 0x20)
# define ISL7998X_REG_PX_DEC_IAGC(pg) ISL7998X_REG((pg), 0x21)
# define ISL7998X_REG_PX_DEC_AGCGAIN(pg) ISL7998X_REG((pg), 0x22)
# define ISL7998X_REG_PX_DEC_PEAKWT(pg) ISL7998X_REG((pg), 0x23)
# define ISL7998X_REG_PX_DEC_CLMPL(pg) ISL7998X_REG((pg), 0x24)
# define ISL7998X_REG_PX_DEC_SYNCT(pg) ISL7998X_REG((pg), 0x25)
# define ISL7998X_REG_PX_DEC_MISSCNT(pg) ISL7998X_REG((pg), 0x26)
# define ISL7998X_REG_PX_DEC_PCLAMP(pg) ISL7998X_REG((pg), 0x27)
# define ISL7998X_REG_PX_DEC_VERT_CTL_1(pg) ISL7998X_REG((pg), 0x28)
# define ISL7998X_REG_PX_DEC_VERT_CTL_2(pg) ISL7998X_REG((pg), 0x29)
# define ISL7998X_REG_PX_DEC_CLR_KILL_LVL(pg) ISL7998X_REG((pg), 0x2a)
# define ISL7998X_REG_PX_DEC_COMB_FILTER_CTL(pg) ISL7998X_REG((pg), 0x2b)
# define ISL7998X_REG_PX_DEC_LUMA_DELAY(pg) ISL7998X_REG((pg), 0x2c)
# define ISL7998X_REG_PX_DEC_MISC1(pg) ISL7998X_REG((pg), 0x2d)
# define ISL7998X_REG_PX_DEC_MISC2(pg) ISL7998X_REG((pg), 0x2e)
# define ISL7998X_REG_PX_DEC_MISC3(pg) ISL7998X_REG((pg), 0x2f)
# define ISL7998X_REG_PX_DEC_MVSN(pg) ISL7998X_REG((pg), 0x30)
# define ISL7998X_REG_PX_DEC_CSTATUS2(pg) ISL7998X_REG((pg), 0x31)
# define ISL7998X_REG_PX_DEC_HFREF(pg) ISL7998X_REG((pg), 0x32)
# define ISL7998X_REG_PX_DEC_CLMD(pg) ISL7998X_REG((pg), 0x33)
# define ISL7998X_REG_PX_DEC_ID_DET_CTL(pg) ISL7998X_REG((pg), 0x34)
# define ISL7998X_REG_PX_DEC_CLCNTL(pg) ISL7998X_REG((pg), 0x35)
# define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_1(pg) ISL7998X_REG((pg), 0x36)
# define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_2(pg) ISL7998X_REG((pg), 0x37)
# define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_3(pg) ISL7998X_REG((pg), 0x38)
# define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_4(pg) ISL7998X_REG((pg), 0x39)
# define ISL7998X_REG_PX_DEC_SHORT_DET_CTL(pg) ISL7998X_REG((pg), 0x3a)
# define ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(pg) ISL7998X_REG((pg), 0x3b)
# define ISL7998X_REG_PX_DEC_AFE_TST_MUX_CTL(pg) ISL7998X_REG((pg), 0x3c)
# define ISL7998X_REG_PX_DEC_DATA_CONV(pg) ISL7998X_REG((pg), 0x3d)
# define ISL7998X_REG_PX_DEC_INTERNAL_TEST(pg) ISL7998X_REG((pg), 0x3f)
# define ISL7998X_REG_PX_DEC_H_DELAY_CTL(pg) ISL7998X_REG((pg), 0x43)
# define ISL7998X_REG_PX_DEC_H_DELAY_II_HI(pg) ISL7998X_REG((pg), 0x44)
# define ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(pg) ISL7998X_REG((pg), 0x45)
# define ISL7998X_REG_PX_ACA_CTL_1(pg) ISL7998X_REG((pg), 0x80)
# define ISL7998X_REG_PX_ACA_GAIN_CTL(pg) ISL7998X_REG((pg), 0x81)
# define ISL7998X_REG_PX_ACA_Y_AVG_HI_LIMIT(pg) ISL7998X_REG((pg), 0x82)
# define ISL7998X_REG_PX_ACA_Y_AVG_LO_LIMIT(pg) ISL7998X_REG((pg), 0x83)
# define ISL7998X_REG_PX_ACA_Y_DET_THRESHOLD(pg) ISL7998X_REG((pg), 0x84)
# define ISL7998X_REG_PX_ACA_BLACK_LVL(pg) ISL7998X_REG((pg), 0x85)
# define ISL7998X_REG_PX_ACA_CENTER_LVL(pg) ISL7998X_REG((pg), 0x86)
# define ISL7998X_REG_PX_ACA_WHITE_LVL(pg) ISL7998X_REG((pg), 0x87)
# define ISL7998X_REG_PX_ACA_MEAN_OFF_LIMIT(pg) ISL7998X_REG((pg), 0x88)
# define ISL7998X_REG_PX_ACA_MEAN_OFF_UPGAIN(pg) ISL7998X_REG((pg), 0x89)
# define ISL7998X_REG_PX_ACA_MEAN_OFF_SLOPE(pg) ISL7998X_REG((pg), 0x8a)
# define ISL7998X_REG_PX_ACA_MEAN_OFF_DNGAIN(pg) ISL7998X_REG((pg), 0x8b)
# define ISL7998X_REG_PX_ACA_DELTA_CO_THRES(pg) ISL7998X_REG((pg), 0x8c)
# define ISL7998X_REG_PX_ACA_DELTA_SLOPE(pg) ISL7998X_REG((pg), 0x8d)
# define ISL7998X_REG_PX_ACA_LO_HI_AVG_THRES(pg) ISL7998X_REG((pg), 0x8e)
# define ISL7998X_REG_PX_ACA_LO_MAX_LVL_CTL(pg) ISL7998X_REG((pg), 0x8f)
# define ISL7998X_REG_PX_ACA_HI_MAX_LVL_CTL(pg) ISL7998X_REG((pg), 0x90)
# define ISL7998X_REG_PX_ACA_LO_UPGAIN_CTL(pg) ISL7998X_REG((pg), 0x91)
# define ISL7998X_REG_PX_ACA_LO_DNGAIN_CTL(pg) ISL7998X_REG((pg), 0x92)
# define ISL7998X_REG_PX_ACA_HI_UPGAIN_CTL(pg) ISL7998X_REG((pg), 0x93)
# define ISL7998X_REG_PX_ACA_HI_DNGAIN_CTL(pg) ISL7998X_REG((pg), 0x94)
# define ISL7998X_REG_PX_ACA_LOPASS_FLT_COEF(pg) ISL7998X_REG((pg), 0x95)
# define ISL7998X_REG_PX_ACA_PDF_INDEX(pg) ISL7998X_REG((pg), 0x96)
# define ISL7998X_REG_PX_ACA_HIST_WIN_H_STT(pg) ISL7998X_REG((pg), 0x97)
# define ISL7998X_REG_PX_ACA_HIST_WIN_H_SZ1(pg) ISL7998X_REG((pg), 0x98)
# define ISL7998X_REG_PX_ACA_HIST_WIN_H_SZ2(pg) ISL7998X_REG((pg), 0x99)
# define ISL7998X_REG_PX_ACA_HIST_WIN_V_STT(pg) ISL7998X_REG((pg), 0x9a)
# define ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ1(pg) ISL7998X_REG((pg), 0x9b)
# define ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(pg) ISL7998X_REG((pg), 0x9c)
# define ISL7998X_REG_PX_ACA_Y_AVG(pg) ISL7998X_REG((pg), 0xa0)
# define ISL7998X_REG_PX_ACA_Y_AVG_LIM(pg) ISL7998X_REG((pg), 0xa1)
# define ISL7998X_REG_PX_ACA_LO_AVG(pg) ISL7998X_REG((pg), 0xa2)
# define ISL7998X_REG_PX_ACA_HI_AVG(pg) ISL7998X_REG((pg), 0xa3)
# define ISL7998X_REG_PX_ACA_Y_MAX(pg) ISL7998X_REG((pg), 0xa4)
# define ISL7998X_REG_PX_ACA_Y_MIN(pg) ISL7998X_REG((pg), 0xa5)
# define ISL7998X_REG_PX_ACA_MOFFSET(pg) ISL7998X_REG((pg), 0xa6)
# define ISL7998X_REG_PX_ACA_LO_GAIN(pg) ISL7998X_REG((pg), 0xa7)
# define ISL7998X_REG_PX_ACA_HI_GAIN(pg) ISL7998X_REG((pg), 0xa8)
# define ISL7998X_REG_PX_ACA_LL_SLOPE(pg) ISL7998X_REG((pg), 0xa9)
# define ISL7998X_REG_PX_ACA_LH_SLOPE(pg) ISL7998X_REG((pg), 0xaa)
# define ISL7998X_REG_PX_ACA_HL_SLOPE(pg) ISL7998X_REG((pg), 0xab)
# define ISL7998X_REG_PX_ACA_HH_SLOPE(pg) ISL7998X_REG((pg), 0xac)
# define ISL7998X_REG_PX_ACA_X_LOW(pg) ISL7998X_REG((pg), 0xad)
# define ISL7998X_REG_PX_ACA_X_MEAN(pg) ISL7998X_REG((pg), 0xae)
# define ISL7998X_REG_PX_ACA_X_HIGH(pg) ISL7998X_REG((pg), 0xaf)
# define ISL7998X_REG_PX_ACA_Y_LOW(pg) ISL7998X_REG((pg), 0xb0)
# define ISL7998X_REG_PX_ACA_Y_MEAN(pg) ISL7998X_REG((pg), 0xb1)
# define ISL7998X_REG_PX_ACA_Y_HIGH(pg) ISL7998X_REG((pg), 0xb2)
# define ISL7998X_REG_PX_ACA_CTL_2(pg) ISL7998X_REG((pg), 0xb3)
# define ISL7998X_REG_PX_ACA_CTL_3(pg) ISL7998X_REG((pg), 0xb4)
# define ISL7998X_REG_PX_ACA_CTL_4(pg) ISL7998X_REG((pg), 0xb5)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(pg) ISL7998X_REG((pg), 0xc0)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TL_H(pg) ISL7998X_REG((pg), 0xc1)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TL_L(pg) ISL7998X_REG((pg), 0xc2)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TL_H(pg) ISL7998X_REG((pg), 0xc3)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TL_L(pg) ISL7998X_REG((pg), 0xc4)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TR_H(pg) ISL7998X_REG((pg), 0xc5)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TR_L(pg) ISL7998X_REG((pg), 0xc6)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TR_H(pg) ISL7998X_REG((pg), 0xc7)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TR_L(pg) ISL7998X_REG((pg), 0xc8)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BL_H(pg) ISL7998X_REG((pg), 0xc9)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BL_L(pg) ISL7998X_REG((pg), 0xca)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BL_H(pg) ISL7998X_REG((pg), 0xcb)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BL_L(pg) ISL7998X_REG((pg), 0xcc)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BR_H(pg) ISL7998X_REG((pg), 0xcd)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BR_L(pg) ISL7998X_REG((pg), 0xce)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BR_H(pg) ISL7998X_REG((pg), 0xcf)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BR_L(pg) ISL7998X_REG((pg), 0xd0)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_LM_H(pg) ISL7998X_REG((pg), 0xd1)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_LM_L(pg) ISL7998X_REG((pg), 0xd2)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_LM_H(pg) ISL7998X_REG((pg), 0xd3)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_LM_L(pg) ISL7998X_REG((pg), 0xd4)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TM_H(pg) ISL7998X_REG((pg), 0xd5)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TM_L(pg) ISL7998X_REG((pg), 0xd6)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TM_H(pg) ISL7998X_REG((pg), 0xd7)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TM_L(pg) ISL7998X_REG((pg), 0xd8)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BM_H(pg) ISL7998X_REG((pg), 0xd9)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BM_L(pg) ISL7998X_REG((pg), 0xda)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BM_H(pg) ISL7998X_REG((pg), 0xdb)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BM_L(pg) ISL7998X_REG((pg), 0xdc)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_RM_H(pg) ISL7998X_REG((pg), 0xdd)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_X_RM_L(pg) ISL7998X_REG((pg), 0xde)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_RM_H(pg) ISL7998X_REG((pg), 0xdf)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_RM_L(pg) ISL7998X_REG((pg), 0xe0)
# define ISL7998X_REG_PX_ACA_HIST_DATA_LO(pg) ISL7998X_REG((pg), 0xe1)
# define ISL7998X_REG_PX_ACA_HIST_DATA_MID(pg) ISL7998X_REG((pg), 0xe2)
# define ISL7998X_REG_PX_ACA_HIST_DATA_HI(pg) ISL7998X_REG((pg), 0xe3)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_CLR(pg) ISL7998X_REG((pg), 0xe4)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_CB_CLR(pg) ISL7998X_REG((pg), 0xe5)
# define ISL7998X_REG_PX_ACA_FLEX_WIN_CR_CLR(pg) ISL7998X_REG((pg), 0xe6)
# define ISL7998X_REG_PX_ACA_XFER_HIST_HOST(pg) ISL7998X_REG((pg), 0xe7)
# define ISL7998X_REG_P5_LI_ENGINE_CTL ISL7998X_REG(5, 0x00)
# define ISL7998X_REG_P5_LI_ENGINE_LINE_CTL ISL7998X_REG(5, 0x01)
# define ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH ISL7998X_REG(5, 0x02)
# define ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL ISL7998X_REG(5, 0x03)
# define ISL7998X_REG_P5_LI_ENGINE_VC_ASSIGNMENT ISL7998X_REG(5, 0x04)
# define ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL ISL7998X_REG(5, 0x05)
# define ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL ISL7998X_REG(5, 0x06)
# define ISL7998X_REG_P5_MIPI_READ_START_CTL ISL7998X_REG(5, 0x07)
# define ISL7998X_REG_P5_PSEUDO_FRM_FIELD_CTL ISL7998X_REG(5, 0x08)
# define ISL7998X_REG_P5_ONE_FIELD_MODE_CTL ISL7998X_REG(5, 0x09)
# define ISL7998X_REG_P5_MIPI_INT_HW_TST_CTR ISL7998X_REG(5, 0x0a)
# define ISL7998X_REG_P5_TP_GEN_BAR_PATTERN ISL7998X_REG(5, 0x0b)
# define ISL7998X_REG_P5_MIPI_PCNT_PSFRM ISL7998X_REG(5, 0x0c)
# define ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL ISL7998X_REG(5, 0x0d)
# define ISL7998X_REG_P5_MIPI_VBLANK_PSFRM ISL7998X_REG(5, 0x0e)
# define ISL7998X_REG_P5_LI_ENGINE_CTL_2 ISL7998X_REG(5, 0x0f)
# define ISL7998X_REG_P5_MIPI_WCNT_1 ISL7998X_REG(5, 0x10)
# define ISL7998X_REG_P5_MIPI_WCNT_2 ISL7998X_REG(5, 0x11)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_1 ISL7998X_REG(5, 0x12)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_2 ISL7998X_REG(5, 0x13)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_3 ISL7998X_REG(5, 0x14)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_4 ISL7998X_REG(5, 0x15)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_5 ISL7998X_REG(5, 0x16)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_6 ISL7998X_REG(5, 0x17)
# define ISL7998X_REG_P5_MIPI_DPHY_PARAMS_1 ISL7998X_REG(5, 0x18)
# define ISL7998X_REG_P5_MIPI_DPHY_SOT_PERIOD ISL7998X_REG(5, 0x19)
# define ISL7998X_REG_P5_MIPI_DPHY_EOT_PERIOD ISL7998X_REG(5, 0x1a)
# define ISL7998X_REG_P5_MIPI_DPHY_PARAMS_2 ISL7998X_REG(5, 0x1b)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_7 ISL7998X_REG(5, 0x1c)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_8 ISL7998X_REG(5, 0x1d)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_9 ISL7998X_REG(5, 0x1e)
# define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_10 ISL7998X_REG(5, 0x1f)
# define ISL7998X_REG_P5_TP_GEN_MIPI ISL7998X_REG(5, 0x20)
# define ISL7998X_REG_P5_ESC_MODE_TIME_CTL ISL7998X_REG(5, 0x21)
# define ISL7998X_REG_P5_AUTO_TEST_ERR_DET ISL7998X_REG(5, 0x22)
# define ISL7998X_REG_P5_MIPI_TIMING ISL7998X_REG(5, 0x23)
# define ISL7998X_REG_P5_PIC_HEIGHT_HIGH ISL7998X_REG(5, 0x24)
# define ISL7998X_REG_P5_PIC_HEIGHT_LOW ISL7998X_REG(5, 0x25)
# define ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL ISL7998X_REG(5, 0x26)
# define ISL7998X_REG_P5_FIFO_THRSH_CNT_1 ISL7998X_REG(5, 0x28)
# define ISL7998X_REG_P5_FIFO_THRSH_CNT_2 ISL7998X_REG(5, 0x29)
# define ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1 ISL7998X_REG(5, 0x2a)
# define ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2 ISL7998X_REG(5, 0x2b)
# define ISL7998X_REG_P5_PSF_FIELD_END_CTL_1 ISL7998X_REG(5, 0x2c)
# define ISL7998X_REG_P5_PSF_FIELD_END_CTL_2 ISL7998X_REG(5, 0x2d)
# define ISL7998X_REG_P5_PSF_FIELD_END_CTL_3 ISL7998X_REG(5, 0x2e)
# define ISL7998X_REG_P5_PSF_FIELD_END_CTL_4 ISL7998X_REG(5, 0x2f)
# define ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_1 ISL7998X_REG(5, 0x30)
# define ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_2 ISL7998X_REG(5, 0x31)
# define ISL7998X_REG_P5_MIPI_ANA_CLK_CTL ISL7998X_REG(5, 0x32)
# define ISL7998X_REG_P5_PLL_ANA_STATUS ISL7998X_REG(5, 0x33)
# define ISL7998X_REG_P5_PLL_ANA_MISC_CTL ISL7998X_REG(5, 0x34)
# define ISL7998X_REG_P5_MIPI_ANA ISL7998X_REG(5, 0x35)
# define ISL7998X_REG_P5_PLL_ANA ISL7998X_REG(5, 0x36)
# define ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1 ISL7998X_REG(5, 0x38)
# define ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_2 ISL7998X_REG(5, 0x39)
# define ISL7998X_REG_P5_H_LINE_CNT_1 ISL7998X_REG(5, 0x3a)
# define ISL7998X_REG_P5_H_LINE_CNT_2 ISL7998X_REG(5, 0x3b)
# define ISL7998X_REG_P5_HIST_LINE_CNT_1 ISL7998X_REG(5, 0x3c)
# define ISL7998X_REG_P5_HIST_LINE_CNT_2 ISL7998X_REG(5, 0x3d)
static const struct reg_sequence isl7998x_init_seq_1 [ ] = {
{ ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN , 0xff } ,
{ ISL7998X_REG_PX_DEC_SDT ( 0x1 ) , 0x00 } ,
{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1 ( 0x1 ) , 0x03 } ,
{ ISL7998X_REG_PX_DEC_SDT ( 0x2 ) , 0x00 } ,
{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1 ( 0x2 ) , 0x03 } ,
{ ISL7998X_REG_PX_DEC_SDT ( 0x3 ) , 0x00 } ,
{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1 ( 0x3 ) , 0x03 } ,
{ ISL7998X_REG_PX_DEC_SDT ( 0x4 ) , 0x00 } ,
{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1 ( 0x4 ) , 0x03 } ,
{ ISL7998X_REG_P5_LI_ENGINE_CTL , 0x00 } ,
{ ISL7998X_REG_P0_SW_RESET_CTL , 0x1f , 10 } ,
{ ISL7998X_REG_P0_IO_BUFFER_CTL , 0x00 } ,
{ ISL7998X_REG_P0_MPP2_SYNC_CTL , 0xc9 } ,
{ ISL7998X_REG_P0_IRQ_SYNC_CTL , 0xc9 } ,
{ ISL7998X_REG_P0_CHAN_1_IRQ , 0x03 } ,
{ ISL7998X_REG_P0_CHAN_2_IRQ , 0x00 } ,
{ ISL7998X_REG_P0_CHAN_3_IRQ , 0x00 } ,
{ ISL7998X_REG_P0_CHAN_4_IRQ , 0x00 } ,
{ ISL7998X_REG_P5_LI_ENGINE_CTL , 0x02 } ,
{ ISL7998X_REG_P5_LI_ENGINE_LINE_CTL , 0x85 } ,
{ ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH , 0xa0 } ,
{ ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL , 0x18 } ,
{ ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL , 0x40 } ,
{ ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL , 0x40 } ,
{ ISL7998X_REG_P5_MIPI_WCNT_1 , 0x05 } ,
{ ISL7998X_REG_P5_MIPI_WCNT_2 , 0xa0 } ,
{ ISL7998X_REG_P5_TP_GEN_MIPI , 0x00 } ,
{ ISL7998X_REG_P5_ESC_MODE_TIME_CTL , 0x0c } ,
{ ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL , 0x00 } ,
{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1 , 0x00 } ,
{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2 , 0x19 } ,
{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_1 , 0x18 } ,
{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_2 , 0xf1 } ,
{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_3 , 0x00 } ,
{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_4 , 0xf1 } ,
{ ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_1 , 0x00 } ,
{ ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_2 , 0x00 } ,
{ ISL7998X_REG_P5_MIPI_ANA_CLK_CTL , 0x00 } ,
{ ISL7998X_REG_P5_PLL_ANA_STATUS , 0xc0 } ,
{ ISL7998X_REG_P5_PLL_ANA_MISC_CTL , 0x18 } ,
{ ISL7998X_REG_P5_PLL_ANA , 0x00 } ,
{ ISL7998X_REG_P0_SW_RESET_CTL , 0x10 , 10 } ,
/* Page 0xf means write to all of pages 1,2,3,4 */
{ ISL7998X_REG_PX_DEC_VDELAY_LO ( 0xf ) , 0x14 } ,
{ ISL7998X_REG_PX_DEC_MISC3 ( 0xf ) , 0xe6 } ,
{ ISL7998X_REG_PX_DEC_CLMD ( 0xf ) , 0x85 } ,
{ ISL7998X_REG_PX_DEC_H_DELAY_II_LOW ( 0xf ) , 0x11 } ,
{ ISL7998X_REG_PX_ACA_XFER_HIST_HOST ( 0xf ) , 0x00 } ,
{ ISL7998X_REG_P0_CLK_CTL_1 , 0x1f } ,
{ ISL7998X_REG_P0_CLK_CTL_2 , 0x43 } ,
{ ISL7998X_REG_P0_CLK_CTL_3 , 0x4f } ,
} ;
static const struct reg_sequence isl7998x_init_seq_2 [ ] = {
{ ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL , 0x10 } ,
{ ISL7998X_REG_P5_LI_ENGINE_VC_ASSIGNMENT , 0xe4 } ,
{ ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL , 0x00 } ,
{ ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL , 0x60 } ,
{ ISL7998X_REG_P5_MIPI_READ_START_CTL , 0x2b } ,
{ ISL7998X_REG_P5_PSEUDO_FRM_FIELD_CTL , 0x02 } ,
{ ISL7998X_REG_P5_ONE_FIELD_MODE_CTL , 0x00 } ,
{ ISL7998X_REG_P5_MIPI_INT_HW_TST_CTR , 0x62 } ,
{ ISL7998X_REG_P5_TP_GEN_BAR_PATTERN , 0x02 } ,
{ ISL7998X_REG_P5_MIPI_PCNT_PSFRM , 0x36 } ,
{ ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL , 0x00 } ,
{ ISL7998X_REG_P5_MIPI_VBLANK_PSFRM , 0x6c } ,
{ ISL7998X_REG_P5_LI_ENGINE_CTL_2 , 0x00 } ,
{ ISL7998X_REG_P5_MIPI_WCNT_1 , 0x05 } ,
{ ISL7998X_REG_P5_MIPI_WCNT_2 , 0xa0 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_1 , 0x77 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_2 , 0x17 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_3 , 0x08 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_4 , 0x38 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_5 , 0x14 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_6 , 0xf6 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_PARAMS_1 , 0x00 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_SOT_PERIOD , 0x17 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_EOT_PERIOD , 0x0a } ,
{ ISL7998X_REG_P5_MIPI_DPHY_PARAMS_2 , 0x71 } ,
{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_7 , 0x7a } ,
{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_8 , 0x0f } ,
{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_9 , 0x8c } ,
{ ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL , 0x08 } ,
{ ISL7998X_REG_P5_FIFO_THRSH_CNT_1 , 0x01 } ,
{ ISL7998X_REG_P5_FIFO_THRSH_CNT_2 , 0x0e } ,
{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1 , 0x00 } ,
{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2 , 0x00 } ,
{ ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1 , 0x03 } ,
{ ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_2 , 0xc0 } ,
{ ISL7998X_REG_P5_H_LINE_CNT_1 , 0x06 } ,
{ ISL7998X_REG_P5_H_LINE_CNT_2 , 0xb3 } ,
{ ISL7998X_REG_P5_HIST_LINE_CNT_1 , 0x00 } ,
{ ISL7998X_REG_P5_HIST_LINE_CNT_2 , 0xf1 } ,
{ ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL , 0x00 } ,
{ ISL7998X_REG_P5_MIPI_ANA , 0x00 } ,
/*
* Wait a bit after reset so that the chip can capture a frame
* and update internal line counters .
*/
{ ISL7998X_REG_P0_SW_RESET_CTL , 0x00 , 50 } ,
} ;
enum isl7998x_pads {
ISL7998X_PAD_OUT ,
ISL7998X_PAD_VIN1 ,
ISL7998X_PAD_VIN2 ,
ISL7998X_PAD_VIN3 ,
ISL7998X_PAD_VIN4 ,
ISL7998X_NUM_PADS
} ;
struct isl7998x_datafmt {
u32 code ;
enum v4l2_colorspace colorspace ;
} ;
static const struct isl7998x_datafmt isl7998x_colour_fmts [ ] = {
{ MEDIA_BUS_FMT_UYVY8_2X8 , V4L2_COLORSPACE_SRGB } ,
} ;
/* Menu items for LINK_FREQ V4L2 control */
static const s64 link_freq_menu_items [ ] = {
/* 1 channel, 1 lane or 2 channels, 2 lanes */
108000000 ,
/* 2 channels, 1 lane or 4 channels, 2 lanes */
216000000 ,
/* 4 channels, 1 lane */
432000000 ,
} ;
/* Menu items for TEST_PATTERN V4L2 control */
static const char * const isl7998x_test_pattern_menu [ ] = {
" Disabled " ,
" Enabled " ,
} ;
static const char * const isl7998x_test_pattern_bars [ ] = {
" bbbbwb " , " bbbwwb " , " bbwbwb " , " bbwwwb " ,
} ;
static const char * const isl7998x_test_pattern_colors [ ] = {
" Yellow " , " Blue " , " Green " , " Pink " ,
} ;
struct isl7998x_mode {
unsigned int width ;
unsigned int height ;
enum v4l2_field field ;
} ;
static const struct isl7998x_mode supported_modes [ ] = {
{
. width = 720 ,
. height = 576 ,
. field = V4L2_FIELD_SEQ_TB ,
} ,
{
. width = 720 ,
. height = 480 ,
. field = V4L2_FIELD_SEQ_BT ,
} ,
} ;
static const struct isl7998x_video_std {
const v4l2_std_id norm ;
unsigned int id ;
const struct isl7998x_mode * mode ;
} isl7998x_std_res [ ] = {
{ V4L2_STD_NTSC_443 ,
ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_443 ,
& supported_modes [ 1 ] } ,
{ V4L2_STD_PAL_M ,
ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_M ,
& supported_modes [ 1 ] } ,
{ V4L2_STD_PAL_Nc ,
ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_CN ,
& supported_modes [ 0 ] } ,
{ V4L2_STD_PAL_N ,
ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL ,
& supported_modes [ 0 ] } ,
{ V4L2_STD_PAL_60 ,
ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_60 ,
& supported_modes [ 1 ] } ,
{ V4L2_STD_NTSC ,
ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_M ,
& supported_modes [ 1 ] } ,
{ V4L2_STD_PAL ,
ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL ,
& supported_modes [ 0 ] } ,
{ V4L2_STD_SECAM ,
ISL7998X_REG_PX_DEC_SDT_STANDARD_SECAM ,
& supported_modes [ 0 ] } ,
{ V4L2_STD_UNKNOWN ,
ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN ,
& supported_modes [ 1 ] } ,
} ;
struct isl7998x {
struct v4l2_subdev subdev ;
struct regmap * regmap ;
struct gpio_desc * pd_gpio ;
struct gpio_desc * rstb_gpio ;
unsigned int nr_mipi_lanes ;
u32 nr_inputs ;
const struct isl7998x_datafmt * fmt ;
v4l2_std_id norm ;
struct media_pad pads [ ISL7998X_NUM_PADS ] ;
int enabled ;
/* protect fmt, norm, enabled */
struct mutex lock ;
struct v4l2_ctrl_handler ctrl_handler ;
/* protect ctrl_handler */
struct mutex ctrl_mutex ;
/* V4L2 Controls */
struct v4l2_ctrl * link_freq ;
u8 test_pattern ;
u8 test_pattern_bars ;
u8 test_pattern_chans ;
u8 test_pattern_color ;
} ;
static struct isl7998x * sd_to_isl7998x ( struct v4l2_subdev * sd )
{
return container_of ( sd , struct isl7998x , subdev ) ;
}
static struct isl7998x * i2c_to_isl7998x ( const struct i2c_client * client )
{
return sd_to_isl7998x ( i2c_get_clientdata ( client ) ) ;
}
static unsigned int isl7998x_norm_to_val ( v4l2_std_id norm )
{
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( isl7998x_std_res ) ; i + + )
if ( isl7998x_std_res [ i ] . norm & norm )
break ;
if ( i = = ARRAY_SIZE ( isl7998x_std_res ) )
return ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN ;
return isl7998x_std_res [ i ] . id ;
}
static const struct isl7998x_mode * isl7998x_norm_to_mode ( v4l2_std_id norm )
{
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( isl7998x_std_res ) ; i + + )
if ( isl7998x_std_res [ i ] . norm & norm )
break ;
/* Use NTSC default resolution during standard detection */
if ( i = = ARRAY_SIZE ( isl7998x_std_res ) )
return & supported_modes [ 1 ] ;
return isl7998x_std_res [ i ] . mode ;
}
static int isl7998x_get_nr_inputs ( struct device_node * of_node )
{
struct device_node * port ;
unsigned int inputs = 0 ;
unsigned int i ;
if ( of_graph_get_endpoint_count ( of_node ) > ISL7998X_NUM_PADS )
return - EINVAL ;
/*
* The driver does not provide means to remap the input ports . It
* always configures input ports to start from VID1 . Ensure that the
* device tree is correct .
*/
for ( i = ISL7998X_PAD_VIN1 ; i < = ISL7998X_PAD_VIN4 ; i + + ) {
port = of_graph_get_port_by_id ( of_node , i ) ;
if ( ! port )
continue ;
inputs | = BIT ( i ) ;
of_node_put ( port ) ;
}
switch ( inputs ) {
case BIT ( ISL7998X_PAD_VIN1 ) :
return 1 ;
case BIT ( ISL7998X_PAD_VIN1 ) | BIT ( ISL7998X_PAD_VIN2 ) :
return 2 ;
case BIT ( ISL7998X_PAD_VIN1 ) | BIT ( ISL7998X_PAD_VIN2 ) |
BIT ( ISL7998X_PAD_VIN3 ) | BIT ( ISL7998X_PAD_VIN4 ) :
return 4 ;
default :
return - EINVAL ;
}
}
static int isl7998x_wait_power_on ( struct isl7998x * isl7998x )
{
struct device * dev = isl7998x - > subdev . dev ;
u32 chip_id ;
int ret ;
int err ;
ret = read_poll_timeout ( regmap_read , err , ! err , 2000 , 20000 , false ,
isl7998x - > regmap ,
ISL7998X_REG_P0_PRODUCT_ID_CODE , & chip_id ) ;
if ( ret ) {
dev_err ( dev , " timeout while waiting for ISL7998X \n " ) ;
return ret ;
}
dev_dbg ( dev , " Found ISL799%x \n " , chip_id ) ;
return ret ;
}
static int isl7998x_set_standard ( struct isl7998x * isl7998x , v4l2_std_id norm )
{
const struct isl7998x_mode * mode = isl7998x_norm_to_mode ( norm ) ;
unsigned int val = isl7998x_norm_to_val ( norm ) ;
unsigned int width = mode - > width ;
unsigned int i ;
int ret ;
for ( i = 0 ; i < ISL7998X_INPUTS ; i + + ) {
ret = regmap_write_bits ( isl7998x - > regmap ,
ISL7998X_REG_PX_DEC_SDT ( i + 1 ) ,
ISL7998X_REG_PX_DEC_SDT_STANDARD ,
val ) ;
if ( ret )
return ret ;
}
ret = regmap_write ( isl7998x - > regmap ,
ISL7998X_REG_P5_LI_ENGINE_LINE_CTL ,
0x20 | ( ( width > > 7 ) & 0x1f ) ) ;
if ( ret )
return ret ;
ret = regmap_write ( isl7998x - > regmap ,
ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH ,
( width < < 1 ) & 0xff ) ;
if ( ret )
return ret ;
return 0 ;
}
static int isl7998x_init ( struct isl7998x * isl7998x )
{
const unsigned int lanes = isl7998x - > nr_mipi_lanes ;
2022-05-16 10:20:53 +01:00
static const u32 isl7998x_video_in_chan_map [ ] = { 0x00 , 0x11 , 0x02 , 0x02 } ;
2022-02-17 16:44:07 +01:00
const struct reg_sequence isl7998x_init_seq_custom [ ] = {
{ ISL7998X_REG_P0_VIDEO_IN_CHAN_CTL ,
isl7998x_video_in_chan_map [ isl7998x - > nr_inputs - 1 ] } ,
{ ISL7998X_REG_P0_CLK_CTL_4 ,
( lanes = = 1 ) ? 0x40 : 0x41 } ,
{ ISL7998X_REG_P5_LI_ENGINE_CTL ,
( lanes = = 1 ) ? 0x01 : 0x02 } ,
} ;
struct device * dev = isl7998x - > subdev . dev ;
struct regmap * regmap = isl7998x - > regmap ;
int ret ;
dev_dbg ( dev , " configuring %d lanes for %d inputs (norm %s) \n " ,
isl7998x - > nr_mipi_lanes , isl7998x - > nr_inputs ,
v4l2_norm_to_name ( isl7998x - > norm ) ) ;
ret = regmap_register_patch ( regmap , isl7998x_init_seq_1 ,
ARRAY_SIZE ( isl7998x_init_seq_1 ) ) ;
if ( ret )
return ret ;
mutex_lock ( & isl7998x - > lock ) ;
ret = isl7998x_set_standard ( isl7998x , isl7998x - > norm ) ;
mutex_unlock ( & isl7998x - > lock ) ;
if ( ret )
return ret ;
ret = regmap_register_patch ( regmap , isl7998x_init_seq_custom ,
ARRAY_SIZE ( isl7998x_init_seq_custom ) ) ;
if ( ret )
return ret ;
return regmap_register_patch ( regmap , isl7998x_init_seq_2 ,
ARRAY_SIZE ( isl7998x_init_seq_2 ) ) ;
}
static int isl7998x_set_test_pattern ( struct isl7998x * isl7998x )
{
const struct reg_sequence isl7998x_init_seq_tpg_off [ ] = {
{ ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL , 0 } ,
{ ISL7998X_REG_P5_LI_ENGINE_CTL_2 , 0 }
} ;
const struct reg_sequence isl7998x_init_seq_tpg_on [ ] = {
{ ISL7998X_REG_P5_TP_GEN_BAR_PATTERN ,
isl7998x - > test_pattern_bars < < 6 } ,
{ ISL7998X_REG_P5_LI_ENGINE_CTL_2 ,
isl7998x - > norm & V4L2_STD_PAL ? BIT ( 2 ) : 0 } ,
{ ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL ,
( isl7998x - > test_pattern_chans < < 4 ) |
( isl7998x - > test_pattern_color < < 2 ) }
} ;
struct device * dev = isl7998x - > subdev . dev ;
struct regmap * regmap = isl7998x - > regmap ;
int ret ;
if ( pm_runtime_get_if_in_use ( dev ) < = 0 )
return 0 ;
if ( isl7998x - > test_pattern ! = 0 ) {
dev_dbg ( dev , " enabling test pattern: channels 0x%x, %s, %s \n " ,
isl7998x - > test_pattern_chans ,
isl7998x_test_pattern_bars [ isl7998x - > test_pattern_bars ] ,
isl7998x_test_pattern_colors [ isl7998x - > test_pattern_color ] ) ;
ret = regmap_register_patch ( regmap , isl7998x_init_seq_tpg_on ,
ARRAY_SIZE ( isl7998x_init_seq_tpg_on ) ) ;
} else {
ret = regmap_register_patch ( regmap , isl7998x_init_seq_tpg_off ,
ARRAY_SIZE ( isl7998x_init_seq_tpg_off ) ) ;
}
pm_runtime_put ( dev ) ;
return ret ;
}
# ifdef CONFIG_VIDEO_ADV_DEBUG
static int isl7998x_g_register ( struct v4l2_subdev * sd ,
struct v4l2_dbg_register * reg )
{
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
int ret ;
u32 val ;
ret = regmap_read ( isl7998x - > regmap , reg - > reg , & val ) ;
if ( ret )
return ret ;
reg - > size = 1 ;
reg - > val = val ;
return 0 ;
}
static int isl7998x_s_register ( struct v4l2_subdev * sd ,
const struct v4l2_dbg_register * reg )
{
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
return regmap_write ( isl7998x - > regmap , reg - > reg , reg - > val ) ;
}
# endif
static int isl7998x_g_std ( struct v4l2_subdev * sd , v4l2_std_id * norm )
{
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
mutex_lock ( & isl7998x - > lock ) ;
* norm = isl7998x - > norm ;
mutex_unlock ( & isl7998x - > lock ) ;
return 0 ;
}
static int isl7998x_s_std ( struct v4l2_subdev * sd , v4l2_std_id norm )
{
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct device * dev = & client - > dev ;
int ret = 0 ;
mutex_lock ( & isl7998x - > lock ) ;
if ( isl7998x - > enabled ) {
ret = - EBUSY ;
mutex_unlock ( & isl7998x - > lock ) ;
return ret ;
}
isl7998x - > norm = norm ;
mutex_unlock ( & isl7998x - > lock ) ;
if ( pm_runtime_get_if_in_use ( dev ) < = 0 )
return ret ;
ret = isl7998x_set_standard ( isl7998x , norm ) ;
pm_runtime_put ( dev ) ;
return ret ;
}
static int isl7998x_querystd ( struct v4l2_subdev * sd , v4l2_std_id * std )
{
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct device * dev = & client - > dev ;
unsigned int std_id [ ISL7998X_INPUTS ] ;
unsigned int i ;
int ret ;
u32 reg ;
ret = pm_runtime_resume_and_get ( dev ) ;
if ( ret )
return ret ;
dev_dbg ( dev , " starting video standard detection \n " ) ;
mutex_lock ( & isl7998x - > lock ) ;
if ( isl7998x - > enabled ) {
ret = - EBUSY ;
goto out_unlock ;
}
ret = isl7998x_set_standard ( isl7998x , V4L2_STD_UNKNOWN ) ;
if ( ret )
goto out_unlock ;
for ( i = 0 ; i < ISL7998X_INPUTS ; i + + ) {
ret = regmap_write ( isl7998x - > regmap ,
ISL7998X_REG_PX_DEC_SDTR ( i + 1 ) ,
ISL7998X_REG_PX_DEC_SDTR_ATSTART ) ;
if ( ret )
goto out_reset_std ;
}
for ( i = 0 ; i < ISL7998X_INPUTS ; i + + ) {
ret = regmap_read_poll_timeout ( isl7998x - > regmap ,
ISL7998X_REG_PX_DEC_SDT ( i + 1 ) ,
reg ,
! ( reg & ISL7998X_REG_PX_DEC_SDT_DET ) ,
2000 , 500 * USEC_PER_MSEC ) ;
if ( ret )
goto out_reset_std ;
std_id [ i ] = FIELD_GET ( ISL7998X_REG_PX_DEC_SDT_NOW , reg ) ;
}
/*
* According to Renesas FAE , all input cameras must have the
* same standard on this chip .
*/
for ( i = 0 ; i < isl7998x - > nr_inputs ; i + + ) {
dev_dbg ( dev , " input %d: detected %s \n " ,
i , v4l2_norm_to_name ( isl7998x_std_res [ std_id [ i ] ] . norm ) ) ;
if ( std_id [ 0 ] ! = std_id [ i ] )
dev_warn ( dev ,
" incompatible standards: %s on input %d (expected %s) \n " ,
v4l2_norm_to_name ( isl7998x_std_res [ std_id [ i ] ] . norm ) , i ,
v4l2_norm_to_name ( isl7998x_std_res [ std_id [ 0 ] ] . norm ) ) ;
}
* std = isl7998x_std_res [ std_id [ 0 ] ] . norm ;
out_reset_std :
isl7998x_set_standard ( isl7998x , isl7998x - > norm ) ;
out_unlock :
mutex_unlock ( & isl7998x - > lock ) ;
pm_runtime_put ( dev ) ;
return ret ;
}
static int isl7998x_g_tvnorms ( struct v4l2_subdev * sd , v4l2_std_id * std )
{
* std = V4L2_STD_ALL ;
return 0 ;
}
static int isl7998x_g_input_status ( struct v4l2_subdev * sd , u32 * status )
{
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct device * dev = & client - > dev ;
unsigned int i ;
int ret = 0 ;
u32 reg ;
if ( ! pm_runtime_active ( dev ) ) {
* status | = V4L2_IN_ST_NO_POWER ;
return 0 ;
}
for ( i = 0 ; i < isl7998x - > nr_inputs ; i + + ) {
ret = regmap_read ( isl7998x - > regmap ,
ISL7998X_REG_PX_DEC_STATUS_1 ( i + 1 ) , & reg ) ;
if ( ! ret ) {
if ( reg & ISL7998X_REG_PX_DEC_STATUS_1_VDLOSS )
* status | = V4L2_IN_ST_NO_SIGNAL ;
if ( ! ( reg & ISL7998X_REG_PX_DEC_STATUS_1_HLOCK ) )
* status | = V4L2_IN_ST_NO_H_LOCK ;
if ( ! ( reg & ISL7998X_REG_PX_DEC_STATUS_1_VLOCK ) )
* status | = V4L2_IN_ST_NO_V_LOCK ;
}
}
return ret ;
}
static int isl7998x_s_stream ( struct v4l2_subdev * sd , int enable )
{
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct device * dev = & client - > dev ;
int ret = 0 ;
u32 reg ;
dev_dbg ( dev , " stream %s \n " , enable ? " ON " : " OFF " ) ;
mutex_lock ( & isl7998x - > lock ) ;
if ( isl7998x - > enabled = = enable )
goto out ;
isl7998x - > enabled = enable ;
if ( enable ) {
ret = isl7998x_set_test_pattern ( isl7998x ) ;
if ( ret )
goto out ;
}
regmap_read ( isl7998x - > regmap ,
ISL7998X_REG_P5_LI_ENGINE_CTL , & reg ) ;
if ( enable )
reg & = ~ BIT ( 7 ) ;
else
reg | = BIT ( 7 ) ;
ret = regmap_write ( isl7998x - > regmap ,
ISL7998X_REG_P5_LI_ENGINE_CTL , reg ) ;
out :
mutex_unlock ( & isl7998x - > lock ) ;
return ret ;
}
static int isl7998x_pre_streamon ( struct v4l2_subdev * sd , u32 flags )
{
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct device * dev = & client - > dev ;
return pm_runtime_resume_and_get ( dev ) ;
}
static int isl7998x_post_streamoff ( struct v4l2_subdev * sd )
{
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct device * dev = & client - > dev ;
pm_runtime_put ( dev ) ;
return 0 ;
}
static int isl7998x_enum_mbus_code ( struct v4l2_subdev * sd ,
struct v4l2_subdev_state * sd_state ,
struct v4l2_subdev_mbus_code_enum * code )
{
if ( code - > index > = ARRAY_SIZE ( isl7998x_colour_fmts ) )
return - EINVAL ;
code - > code = isl7998x_colour_fmts [ code - > index ] . code ;
return 0 ;
}
static int isl7998x_enum_frame_size ( struct v4l2_subdev * sd ,
struct v4l2_subdev_state * sd_state ,
struct v4l2_subdev_frame_size_enum * fse )
{
if ( fse - > index > = ARRAY_SIZE ( supported_modes ) )
return - EINVAL ;
if ( fse - > code ! = isl7998x_colour_fmts [ 0 ] . code )
return - EINVAL ;
fse - > min_width = supported_modes [ fse - > index ] . width ;
fse - > max_width = fse - > min_width ;
fse - > min_height = supported_modes [ fse - > index ] . height ;
fse - > max_height = fse - > min_height ;
return 0 ;
}
static int isl7998x_get_fmt ( struct v4l2_subdev * sd ,
struct v4l2_subdev_state * sd_state ,
struct v4l2_subdev_format * format )
{
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
struct v4l2_mbus_framefmt * mf = & format - > format ;
const struct isl7998x_mode * mode ;
mutex_lock ( & isl7998x - > lock ) ;
if ( format - > which = = V4L2_SUBDEV_FORMAT_TRY ) {
media: v4l: subdev: Switch to stream-aware state functions
Switch all drivers accessing sub-device state to use the stream-aware
functions. We will soon remove the old ones.
This patch has been generated using the following Coccinelle script:
---------8<------------
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_pad_format(E1, E2, E3)
+ v4l2_subdev_state_get_format(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_pad_crop(E1, E2, E3)
+ v4l2_subdev_state_get_crop(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_pad_compose(E1, E2, E3)
+ v4l2_subdev_state_get_compose(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_try_format(E1, E2, E3)
+ v4l2_subdev_state_get_format(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_try_crop(E1, E2, E3)
+ v4l2_subdev_state_get_crop(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_try_compose(E1, E2, E3)
+ v4l2_subdev_state_get_compose(E2, E3)
---------8<------------
Additionally drivers/media/i2c/s5k5baf.c and
drivers/media/platform/samsung/s3c-camif/camif-capture.c have been
manually changed as Coccinelle didn't. Further local variables have been
removed as they became unused as a result of the other changes.
Also Coccinelle introduced indentation by space in files
drivers/media/i2c/st-mipid02.c and
drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c. This has been also
corrected.
The diff from Coccinelle-generated changes are:
> diff --git b/drivers/media/i2c/imx319.c a/drivers/media/i2c/imx319.c
> index e549692ff478..420984382173 100644
> --- b/drivers/media/i2c/imx319.c
> +++ a/drivers/media/i2c/imx319.c
> @@ -2001,7 +2001,6 @@ static int imx319_do_get_pad_format(struct imx319 *imx319,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &imx319->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/imx355.c a/drivers/media/i2c/imx355.c
> index 96bdde685d65..e1b1d2fc79dd 100644
> --- b/drivers/media/i2c/imx355.c
> +++ a/drivers/media/i2c/imx355.c
> @@ -1299,7 +1299,6 @@ static int imx355_do_get_pad_format(struct imx355 *imx355,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &imx355->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/ov08x40.c a/drivers/media/i2c/ov08x40.c
> index ca799bbcfdb7..abbb0b774d43 100644
> --- b/drivers/media/i2c/ov08x40.c
> +++ a/drivers/media/i2c/ov08x40.c
> @@ -2774,7 +2774,6 @@ static int ov08x40_do_get_pad_format(struct ov08x40 *ov08x,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &ov08x->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/ov13858.c a/drivers/media/i2c/ov13858.c
> index 7816d9787c61..09387e335d80 100644
> --- b/drivers/media/i2c/ov13858.c
> +++ a/drivers/media/i2c/ov13858.c
> @@ -1316,7 +1316,6 @@ static int ov13858_do_get_pad_format(struct ov13858 *ov13858,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &ov13858->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/ov13b10.c a/drivers/media/i2c/ov13b10.c
> index 268cd4b03f9c..c06411d5ee2b 100644
> --- b/drivers/media/i2c/ov13b10.c
> +++ a/drivers/media/i2c/ov13b10.c
> @@ -1001,7 +1001,6 @@ static int ov13b10_do_get_pad_format(struct ov13b10 *ov13b,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &ov13b->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/s5c73m3/s5c73m3-core.c a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> index 47605e36bc60..8f9b5713daf7 100644
> --- b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> +++ a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> @@ -819,7 +819,6 @@ static void s5c73m3_oif_try_format(struct s5c73m3 *state,
> struct v4l2_subdev_format *fmt,
> const struct s5c73m3_frame_size **fs)
> {
> - struct v4l2_subdev *sd = &state->sensor_sd;
> u32 code;
>
> switch (fmt->pad) {
> diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
> index 67da2045f543..03ccfb0e1e11 100644
> --- a/drivers/media/i2c/s5k5baf.c
> +++ b/drivers/media/i2c/s5k5baf.c
> @@ -1472,14 +1472,11 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
>
> if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
> rects = (struct v4l2_rect * []) {
> - &s5k5baf_cis_rect,
> - v4l2_subdev_get_try_crop(sd, sd_state,
> - PAD_CIS),
> - v4l2_subdev_get_try_compose(sd, sd_state,
> - PAD_CIS),
> - v4l2_subdev_get_try_crop(sd, sd_state,
> - PAD_OUT)
> - };
> + &s5k5baf_cis_rect,
> + v4l2_subdev_state_get_crop(sd_state, PAD_CIS),
> + v4l2_subdev_state_get_compose(sd_state, PAD_CIS),
> + v4l2_subdev_state_get_crop(sd_state, PAD_OUT)
> + };
> s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
> return 0;
> }
> diff --git b/drivers/media/platform/samsung/s3c-camif/camif-capture.c a/drivers/media/platform/samsung/s3c-camif/camif-capture.c
> index 295e083f38e8..be58260ea67e 100644
> --- b/drivers/media/platform/samsung/s3c-camif/camif-capture.c
> +++ a/drivers/media/platform/samsung/s3c-camif/camif-capture.c
> @@ -1216,7 +1216,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
> struct v4l2_mbus_framefmt *mf = &fmt->format;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> - mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
> + mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> fmt->format = *mf;
> return 0;
> }
> @@ -1305,7 +1305,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
> __camif_subdev_try_format(camif, mf, fmt->pad);
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> - mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
> + mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> *mf = fmt->format;
> mutex_unlock(&camif->lock);
> return 0;
> diff --git b/drivers/media/platform/ti/cal/cal-camerarx.c a/drivers/media/platform/ti/cal/cal-camerarx.c
> index cea454ed9c20..61433744c6c4 100644
> --- b/drivers/media/platform/ti/cal/cal-camerarx.c
> +++ a/drivers/media/platform/ti/cal/cal-camerarx.c
> @@ -621,8 +621,6 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *state,
> struct v4l2_subdev_mbus_code_enum *code)
> {
> - struct cal_camerarx *phy = to_cal_camerarx(sd);
> -
> /* No transcoding, source and sink codes must match. */
> if (cal_rx_pad_is_source(code->pad)) {
> struct v4l2_mbus_framefmt *fmt;
> diff --git b/drivers/staging/media/imx/imx-ic-prp.c a/drivers/staging/media/imx/imx-ic-prp.c
> index dd558fac6477..61d69f19657e 100644
> --- b/drivers/staging/media/imx/imx-ic-prp.c
> +++ a/drivers/staging/media/imx/imx-ic-prp.c
> @@ -82,8 +82,6 @@ static struct v4l2_mbus_framefmt *
> __prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_state *sd_state,
> unsigned int pad, enum v4l2_subdev_format_whence which)
> {
> - struct imx_ic_priv *ic_priv = priv->ic_priv;
> -
> if (which == V4L2_SUBDEV_FORMAT_TRY)
> return v4l2_subdev_state_get_format(sd_state, pad);
> else
> diff --git b/drivers/staging/media/imx/imx-ic-prpencvf.c a/drivers/staging/media/imx/imx-ic-prpencvf.c
> index 02db7dbb884b..ec73c901079e 100644
> --- b/drivers/staging/media/imx/imx-ic-prpencvf.c
> +++ a/drivers/staging/media/imx/imx-ic-prpencvf.c
> @@ -790,8 +790,6 @@ static struct v4l2_mbus_framefmt *
> __prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_state *sd_state,
> unsigned int pad, enum v4l2_subdev_format_whence which)
> {
> - struct imx_ic_priv *ic_priv = priv->ic_priv;
> -
> if (which == V4L2_SUBDEV_FORMAT_TRY)
> return v4l2_subdev_state_get_format(sd_state, pad);
> else
> diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
> index 9c9361354c00..b08a249b5fdd 100644
> --- a/drivers/media/i2c/st-mipid02.c
> +++ b/drivers/media/i2c/st-mipid02.c
> @@ -751,7 +751,7 @@ static void mipid02_set_fmt_source(struct v4l2_subdev *sd,
> format->format = bridge->fmt;
> else
> format->format = *v4l2_subdev_state_get_format(sd_state,
> - MIPID02_SINK_0);
> + MIPID02_SINK_0);
>
> /* but code may need to be converted */
> format->format.code = serial_to_parallel_code(format->format.code);
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> index 117912d3bfbd..96353648c032 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> @@ -319,7 +319,7 @@ static void rkisp1_isp_start(struct rkisp1_isp *isp,
> rkisp1_write(rkisp1, RKISP1_CIF_ISP_CTRL, val);
>
> src_fmt = v4l2_subdev_state_get_format(sd_state,
> - RKISP1_ISP_PAD_SOURCE_VIDEO);
> + RKISP1_ISP_PAD_SOURCE_VIDEO);
> src_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
>
> if (src_info->pixel_enc != V4L2_PIXEL_ENC_BAYER)
> @@ -475,9 +475,9 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
> sink_fmt = v4l2_subdev_state_get_format(sd_state,
> RKISP1_ISP_PAD_SINK_VIDEO);
> src_fmt = v4l2_subdev_state_get_format(sd_state,
> - RKISP1_ISP_PAD_SOURCE_VIDEO);
> + RKISP1_ISP_PAD_SOURCE_VIDEO);
> src_crop = v4l2_subdev_state_get_crop(sd_state,
> - RKISP1_ISP_PAD_SOURCE_VIDEO);
> + RKISP1_ISP_PAD_SOURCE_VIDEO);
>
> /*
> * Media bus code. The ISP can operate in pass-through mode (Bayer in,
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
2023-10-13 09:37:10 +02:00
format - > format = * v4l2_subdev_state_get_format ( sd_state ,
format - > pad ) ;
2022-02-17 16:44:07 +01:00
goto out ;
}
mode = isl7998x_norm_to_mode ( isl7998x - > norm ) ;
mf - > width = mode - > width ;
mf - > height = mode - > height ;
mf - > code = isl7998x - > fmt - > code ;
mf - > field = mode - > field ;
mf - > colorspace = 0 ;
out :
mutex_unlock ( & isl7998x - > lock ) ;
return 0 ;
}
static int isl7998x_set_fmt ( struct v4l2_subdev * sd ,
struct v4l2_subdev_state * sd_state ,
struct v4l2_subdev_format * format )
{
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
struct v4l2_mbus_framefmt * mf = & format - > format ;
const struct isl7998x_mode * mode ;
mutex_lock ( & isl7998x - > lock ) ;
mode = isl7998x_norm_to_mode ( isl7998x - > norm ) ;
mf - > width = mode - > width ;
mf - > height = mode - > height ;
mf - > code = isl7998x - > fmt - > code ;
mf - > field = mode - > field ;
if ( format - > which = = V4L2_SUBDEV_FORMAT_TRY )
media: v4l: subdev: Switch to stream-aware state functions
Switch all drivers accessing sub-device state to use the stream-aware
functions. We will soon remove the old ones.
This patch has been generated using the following Coccinelle script:
---------8<------------
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_pad_format(E1, E2, E3)
+ v4l2_subdev_state_get_format(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_pad_crop(E1, E2, E3)
+ v4l2_subdev_state_get_crop(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_pad_compose(E1, E2, E3)
+ v4l2_subdev_state_get_compose(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_try_format(E1, E2, E3)
+ v4l2_subdev_state_get_format(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_try_crop(E1, E2, E3)
+ v4l2_subdev_state_get_crop(E2, E3)
@@
expression E1, E2, E3;
@@
- v4l2_subdev_get_try_compose(E1, E2, E3)
+ v4l2_subdev_state_get_compose(E2, E3)
---------8<------------
Additionally drivers/media/i2c/s5k5baf.c and
drivers/media/platform/samsung/s3c-camif/camif-capture.c have been
manually changed as Coccinelle didn't. Further local variables have been
removed as they became unused as a result of the other changes.
Also Coccinelle introduced indentation by space in files
drivers/media/i2c/st-mipid02.c and
drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c. This has been also
corrected.
The diff from Coccinelle-generated changes are:
> diff --git b/drivers/media/i2c/imx319.c a/drivers/media/i2c/imx319.c
> index e549692ff478..420984382173 100644
> --- b/drivers/media/i2c/imx319.c
> +++ a/drivers/media/i2c/imx319.c
> @@ -2001,7 +2001,6 @@ static int imx319_do_get_pad_format(struct imx319 *imx319,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &imx319->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/imx355.c a/drivers/media/i2c/imx355.c
> index 96bdde685d65..e1b1d2fc79dd 100644
> --- b/drivers/media/i2c/imx355.c
> +++ a/drivers/media/i2c/imx355.c
> @@ -1299,7 +1299,6 @@ static int imx355_do_get_pad_format(struct imx355 *imx355,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &imx355->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/ov08x40.c a/drivers/media/i2c/ov08x40.c
> index ca799bbcfdb7..abbb0b774d43 100644
> --- b/drivers/media/i2c/ov08x40.c
> +++ a/drivers/media/i2c/ov08x40.c
> @@ -2774,7 +2774,6 @@ static int ov08x40_do_get_pad_format(struct ov08x40 *ov08x,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &ov08x->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/ov13858.c a/drivers/media/i2c/ov13858.c
> index 7816d9787c61..09387e335d80 100644
> --- b/drivers/media/i2c/ov13858.c
> +++ a/drivers/media/i2c/ov13858.c
> @@ -1316,7 +1316,6 @@ static int ov13858_do_get_pad_format(struct ov13858 *ov13858,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &ov13858->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/ov13b10.c a/drivers/media/i2c/ov13b10.c
> index 268cd4b03f9c..c06411d5ee2b 100644
> --- b/drivers/media/i2c/ov13b10.c
> +++ a/drivers/media/i2c/ov13b10.c
> @@ -1001,7 +1001,6 @@ static int ov13b10_do_get_pad_format(struct ov13b10 *ov13b,
> struct v4l2_subdev_format *fmt)
> {
> struct v4l2_mbus_framefmt *framefmt;
> - struct v4l2_subdev *sd = &ov13b->sd;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> diff --git b/drivers/media/i2c/s5c73m3/s5c73m3-core.c a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> index 47605e36bc60..8f9b5713daf7 100644
> --- b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> +++ a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> @@ -819,7 +819,6 @@ static void s5c73m3_oif_try_format(struct s5c73m3 *state,
> struct v4l2_subdev_format *fmt,
> const struct s5c73m3_frame_size **fs)
> {
> - struct v4l2_subdev *sd = &state->sensor_sd;
> u32 code;
>
> switch (fmt->pad) {
> diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
> index 67da2045f543..03ccfb0e1e11 100644
> --- a/drivers/media/i2c/s5k5baf.c
> +++ b/drivers/media/i2c/s5k5baf.c
> @@ -1472,14 +1472,11 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
>
> if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
> rects = (struct v4l2_rect * []) {
> - &s5k5baf_cis_rect,
> - v4l2_subdev_get_try_crop(sd, sd_state,
> - PAD_CIS),
> - v4l2_subdev_get_try_compose(sd, sd_state,
> - PAD_CIS),
> - v4l2_subdev_get_try_crop(sd, sd_state,
> - PAD_OUT)
> - };
> + &s5k5baf_cis_rect,
> + v4l2_subdev_state_get_crop(sd_state, PAD_CIS),
> + v4l2_subdev_state_get_compose(sd_state, PAD_CIS),
> + v4l2_subdev_state_get_crop(sd_state, PAD_OUT)
> + };
> s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
> return 0;
> }
> diff --git b/drivers/media/platform/samsung/s3c-camif/camif-capture.c a/drivers/media/platform/samsung/s3c-camif/camif-capture.c
> index 295e083f38e8..be58260ea67e 100644
> --- b/drivers/media/platform/samsung/s3c-camif/camif-capture.c
> +++ a/drivers/media/platform/samsung/s3c-camif/camif-capture.c
> @@ -1216,7 +1216,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
> struct v4l2_mbus_framefmt *mf = &fmt->format;
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> - mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
> + mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> fmt->format = *mf;
> return 0;
> }
> @@ -1305,7 +1305,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
> __camif_subdev_try_format(camif, mf, fmt->pad);
>
> if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> - mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
> + mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
> *mf = fmt->format;
> mutex_unlock(&camif->lock);
> return 0;
> diff --git b/drivers/media/platform/ti/cal/cal-camerarx.c a/drivers/media/platform/ti/cal/cal-camerarx.c
> index cea454ed9c20..61433744c6c4 100644
> --- b/drivers/media/platform/ti/cal/cal-camerarx.c
> +++ a/drivers/media/platform/ti/cal/cal-camerarx.c
> @@ -621,8 +621,6 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *state,
> struct v4l2_subdev_mbus_code_enum *code)
> {
> - struct cal_camerarx *phy = to_cal_camerarx(sd);
> -
> /* No transcoding, source and sink codes must match. */
> if (cal_rx_pad_is_source(code->pad)) {
> struct v4l2_mbus_framefmt *fmt;
> diff --git b/drivers/staging/media/imx/imx-ic-prp.c a/drivers/staging/media/imx/imx-ic-prp.c
> index dd558fac6477..61d69f19657e 100644
> --- b/drivers/staging/media/imx/imx-ic-prp.c
> +++ a/drivers/staging/media/imx/imx-ic-prp.c
> @@ -82,8 +82,6 @@ static struct v4l2_mbus_framefmt *
> __prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_state *sd_state,
> unsigned int pad, enum v4l2_subdev_format_whence which)
> {
> - struct imx_ic_priv *ic_priv = priv->ic_priv;
> -
> if (which == V4L2_SUBDEV_FORMAT_TRY)
> return v4l2_subdev_state_get_format(sd_state, pad);
> else
> diff --git b/drivers/staging/media/imx/imx-ic-prpencvf.c a/drivers/staging/media/imx/imx-ic-prpencvf.c
> index 02db7dbb884b..ec73c901079e 100644
> --- b/drivers/staging/media/imx/imx-ic-prpencvf.c
> +++ a/drivers/staging/media/imx/imx-ic-prpencvf.c
> @@ -790,8 +790,6 @@ static struct v4l2_mbus_framefmt *
> __prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_state *sd_state,
> unsigned int pad, enum v4l2_subdev_format_whence which)
> {
> - struct imx_ic_priv *ic_priv = priv->ic_priv;
> -
> if (which == V4L2_SUBDEV_FORMAT_TRY)
> return v4l2_subdev_state_get_format(sd_state, pad);
> else
> diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
> index 9c9361354c00..b08a249b5fdd 100644
> --- a/drivers/media/i2c/st-mipid02.c
> +++ b/drivers/media/i2c/st-mipid02.c
> @@ -751,7 +751,7 @@ static void mipid02_set_fmt_source(struct v4l2_subdev *sd,
> format->format = bridge->fmt;
> else
> format->format = *v4l2_subdev_state_get_format(sd_state,
> - MIPID02_SINK_0);
> + MIPID02_SINK_0);
>
> /* but code may need to be converted */
> format->format.code = serial_to_parallel_code(format->format.code);
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> index 117912d3bfbd..96353648c032 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> @@ -319,7 +319,7 @@ static void rkisp1_isp_start(struct rkisp1_isp *isp,
> rkisp1_write(rkisp1, RKISP1_CIF_ISP_CTRL, val);
>
> src_fmt = v4l2_subdev_state_get_format(sd_state,
> - RKISP1_ISP_PAD_SOURCE_VIDEO);
> + RKISP1_ISP_PAD_SOURCE_VIDEO);
> src_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
>
> if (src_info->pixel_enc != V4L2_PIXEL_ENC_BAYER)
> @@ -475,9 +475,9 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
> sink_fmt = v4l2_subdev_state_get_format(sd_state,
> RKISP1_ISP_PAD_SINK_VIDEO);
> src_fmt = v4l2_subdev_state_get_format(sd_state,
> - RKISP1_ISP_PAD_SOURCE_VIDEO);
> + RKISP1_ISP_PAD_SOURCE_VIDEO);
> src_crop = v4l2_subdev_state_get_crop(sd_state,
> - RKISP1_ISP_PAD_SOURCE_VIDEO);
> + RKISP1_ISP_PAD_SOURCE_VIDEO);
>
> /*
> * Media bus code. The ISP can operate in pass-through mode (Bayer in,
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
2023-10-13 09:37:10 +02:00
* v4l2_subdev_state_get_format ( sd_state , format - > pad ) = format - > format ;
2022-02-17 16:44:07 +01:00
mutex_unlock ( & isl7998x - > lock ) ;
return 0 ;
}
static int isl7998x_set_ctrl ( struct v4l2_ctrl * ctrl )
{
struct isl7998x * isl7998x = container_of ( ctrl - > handler ,
struct isl7998x , ctrl_handler ) ;
int ret = 0 ;
switch ( ctrl - > id ) {
case V4L2_CID_TEST_PATTERN_BARS :
mutex_lock ( & isl7998x - > lock ) ;
isl7998x - > test_pattern_bars = ctrl - > val & 0x3 ;
ret = isl7998x_set_test_pattern ( isl7998x ) ;
mutex_unlock ( & isl7998x - > lock ) ;
break ;
case V4L2_CID_TEST_PATTERN_CHANNELS :
mutex_lock ( & isl7998x - > lock ) ;
isl7998x - > test_pattern_chans = ctrl - > val & 0xf ;
ret = isl7998x_set_test_pattern ( isl7998x ) ;
mutex_unlock ( & isl7998x - > lock ) ;
break ;
case V4L2_CID_TEST_PATTERN_COLOR :
mutex_lock ( & isl7998x - > lock ) ;
isl7998x - > test_pattern_color = ctrl - > val & 0x3 ;
ret = isl7998x_set_test_pattern ( isl7998x ) ;
mutex_unlock ( & isl7998x - > lock ) ;
break ;
case V4L2_CID_TEST_PATTERN :
mutex_lock ( & isl7998x - > lock ) ;
isl7998x - > test_pattern = ctrl - > val ;
ret = isl7998x_set_test_pattern ( isl7998x ) ;
mutex_unlock ( & isl7998x - > lock ) ;
break ;
}
return ret ;
}
static const struct v4l2_subdev_core_ops isl7998x_subdev_core_ops = {
# ifdef CONFIG_VIDEO_ADV_DEBUG
. g_register = isl7998x_g_register ,
. s_register = isl7998x_s_register ,
# endif
} ;
static const struct v4l2_subdev_video_ops isl7998x_subdev_video_ops = {
. g_std = isl7998x_g_std ,
. s_std = isl7998x_s_std ,
. querystd = isl7998x_querystd ,
. g_tvnorms = isl7998x_g_tvnorms ,
. g_input_status = isl7998x_g_input_status ,
. s_stream = isl7998x_s_stream ,
. pre_streamon = isl7998x_pre_streamon ,
. post_streamoff = isl7998x_post_streamoff ,
} ;
static const struct v4l2_subdev_pad_ops isl7998x_subdev_pad_ops = {
. enum_mbus_code = isl7998x_enum_mbus_code ,
. enum_frame_size = isl7998x_enum_frame_size ,
. get_fmt = isl7998x_get_fmt ,
. set_fmt = isl7998x_set_fmt ,
} ;
static const struct v4l2_subdev_ops isl7998x_subdev_ops = {
. core = & isl7998x_subdev_core_ops ,
. video = & isl7998x_subdev_video_ops ,
. pad = & isl7998x_subdev_pad_ops ,
} ;
static const struct media_entity_operations isl7998x_entity_ops = {
. link_validate = v4l2_subdev_link_validate ,
} ;
static const struct v4l2_ctrl_ops isl7998x_ctrl_ops = {
. s_ctrl = isl7998x_set_ctrl ,
} ;
static const struct v4l2_ctrl_config isl7998x_ctrls [ ] = {
{
. ops = & isl7998x_ctrl_ops ,
. id = V4L2_CID_TEST_PATTERN_BARS ,
. type = V4L2_CTRL_TYPE_MENU ,
. name = " Test Pattern Bars " ,
. max = ARRAY_SIZE ( isl7998x_test_pattern_bars ) - 1 ,
. def = 0 ,
. qmenu = isl7998x_test_pattern_bars ,
} , {
. ops = & isl7998x_ctrl_ops ,
. id = V4L2_CID_TEST_PATTERN_CHANNELS ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " Test Pattern Channels " ,
. min = 0 ,
. max = 0xf ,
. step = 1 ,
. def = 0xf ,
. flags = 0 ,
} , {
. ops = & isl7998x_ctrl_ops ,
. id = V4L2_CID_TEST_PATTERN_COLOR ,
. type = V4L2_CTRL_TYPE_MENU ,
. name = " Test Pattern Color " ,
. max = ARRAY_SIZE ( isl7998x_test_pattern_colors ) - 1 ,
. def = 0 ,
. qmenu = isl7998x_test_pattern_colors ,
} ,
} ;
# define ISL7998X_REG_DECODER_ACA_READABLE_RANGE(page) \
/* Decoder range */ \
regmap_reg_range ( ISL7998X_REG_PX_DEC_INPUT_FMT ( page ) , \
ISL7998X_REG_PX_DEC_HS_DELAY_CTL ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_ANCTL ( page ) , \
ISL7998X_REG_PX_DEC_CSC_CTL ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_BRIGHT ( page ) , \
ISL7998X_REG_PX_DEC_HUE ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_VERT_PEAK ( page ) , \
ISL7998X_REG_PX_DEC_CORING ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_SDT ( page ) , \
ISL7998X_REG_PX_DEC_SDTR ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_CLMPG ( page ) , \
ISL7998X_REG_PX_DEC_DATA_CONV ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_INTERNAL_TEST ( page ) , \
ISL7998X_REG_PX_DEC_INTERNAL_TEST ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_H_DELAY_CTL ( page ) , \
ISL7998X_REG_PX_DEC_H_DELAY_II_LOW ( page ) ) , \
/* ACA range */ \
regmap_reg_range ( ISL7998X_REG_PX_ACA_CTL_1 ( page ) , \
ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2 ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_ACA_Y_AVG ( page ) , \
ISL7998X_REG_PX_ACA_CTL_4 ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_ACA_FLEX_WIN_HIST ( page ) , \
ISL7998X_REG_PX_ACA_XFER_HIST_HOST ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_PAGE ( page ) , \
ISL7998X_REG_PX_DEC_PAGE ( page ) )
# define ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(page) \
/* Decoder range */ \
regmap_reg_range ( ISL7998X_REG_PX_DEC_INPUT_FMT ( page ) , \
ISL7998X_REG_PX_DEC_INPUT_FMT ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_HS_DELAY_CTL ( page ) , \
ISL7998X_REG_PX_DEC_HS_DELAY_CTL ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_ANCTL ( page ) , \
ISL7998X_REG_PX_DEC_CSC_CTL ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_BRIGHT ( page ) , \
ISL7998X_REG_PX_DEC_HUE ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_VERT_PEAK ( page ) , \
ISL7998X_REG_PX_DEC_CORING ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_SDT ( page ) , \
ISL7998X_REG_PX_DEC_SDTR ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_CLMPG ( page ) , \
ISL7998X_REG_PX_DEC_MISC3 ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_CLMD ( page ) , \
ISL7998X_REG_PX_DEC_DATA_CONV ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_INTERNAL_TEST ( page ) , \
ISL7998X_REG_PX_DEC_INTERNAL_TEST ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_H_DELAY_CTL ( page ) , \
ISL7998X_REG_PX_DEC_H_DELAY_II_LOW ( page ) ) , \
/* ACA range */ \
regmap_reg_range ( ISL7998X_REG_PX_ACA_CTL_1 ( page ) , \
ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2 ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_ACA_CTL_2 ( page ) , \
ISL7998X_REG_PX_ACA_CTL_4 ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_ACA_FLEX_WIN_HIST ( page ) , \
ISL7998X_REG_PX_ACA_HIST_DATA_LO ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_ACA_XFER_HIST_HOST ( page ) , \
ISL7998X_REG_PX_ACA_XFER_HIST_HOST ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_PAGE ( page ) , \
ISL7998X_REG_PX_DEC_PAGE ( page ) )
# define ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(page) \
/* Decoder range */ \
regmap_reg_range ( ISL7998X_REG_PX_DEC_STATUS_1 ( page ) , \
ISL7998X_REG_PX_DEC_STATUS_1 ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_SDT ( page ) , \
ISL7998X_REG_PX_DEC_SDT ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_DEC_MVSN ( page ) , \
ISL7998X_REG_PX_DEC_HFREF ( page ) ) , \
/* ACA range */ \
regmap_reg_range ( ISL7998X_REG_PX_ACA_Y_AVG ( page ) , \
ISL7998X_REG_PX_ACA_Y_HIGH ( page ) ) , \
regmap_reg_range ( ISL7998X_REG_PX_ACA_HIST_DATA_LO ( page ) , \
ISL7998X_REG_PX_ACA_FLEX_WIN_CR_CLR ( page ) )
static const struct regmap_range isl7998x_readable_ranges [ ] = {
regmap_reg_range ( ISL7998X_REG_P0_PRODUCT_ID_CODE ,
ISL7998X_REG_P0_IRQ_SYNC_CTL ) ,
regmap_reg_range ( ISL7998X_REG_P0_INTERRUPT_STATUS ,
ISL7998X_REG_P0_CLOCK_DELAY ) ,
regmap_reg_range ( ISL7998X_REG_PX_DEC_PAGE ( 0 ) ,
ISL7998X_REG_PX_DEC_PAGE ( 0 ) ) ,
ISL7998X_REG_DECODER_ACA_READABLE_RANGE ( 1 ) ,
ISL7998X_REG_DECODER_ACA_READABLE_RANGE ( 2 ) ,
ISL7998X_REG_DECODER_ACA_READABLE_RANGE ( 3 ) ,
ISL7998X_REG_DECODER_ACA_READABLE_RANGE ( 4 ) ,
regmap_reg_range ( ISL7998X_REG_P5_LI_ENGINE_CTL ,
ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL ) ,
regmap_reg_range ( ISL7998X_REG_P5_FIFO_THRSH_CNT_1 ,
ISL7998X_REG_P5_PLL_ANA ) ,
regmap_reg_range ( ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1 ,
ISL7998X_REG_P5_HIST_LINE_CNT_2 ) ,
regmap_reg_range ( ISL7998X_REG_PX_DEC_PAGE ( 5 ) ,
ISL7998X_REG_PX_DEC_PAGE ( 5 ) ) ,
} ;
static const struct regmap_range isl7998x_writeable_ranges [ ] = {
regmap_reg_range ( ISL7998X_REG_P0_SW_RESET_CTL ,
ISL7998X_REG_P0_IRQ_SYNC_CTL ) ,
regmap_reg_range ( ISL7998X_REG_P0_CHAN_1_IRQ ,
ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN ) ,
regmap_reg_range ( ISL7998X_REG_P0_CLOCK_DELAY ,
ISL7998X_REG_P0_CLOCK_DELAY ) ,
regmap_reg_range ( ISL7998X_REG_PX_DEC_PAGE ( 0 ) ,
ISL7998X_REG_PX_DEC_PAGE ( 0 ) ) ,
ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE ( 1 ) ,
ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE ( 2 ) ,
ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE ( 3 ) ,
ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE ( 4 ) ,
regmap_reg_range ( ISL7998X_REG_P5_LI_ENGINE_CTL ,
ISL7998X_REG_P5_ESC_MODE_TIME_CTL ) ,
regmap_reg_range ( ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL ,
ISL7998X_REG_P5_PLL_ANA ) ,
regmap_reg_range ( ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1 ,
ISL7998X_REG_P5_HIST_LINE_CNT_2 ) ,
regmap_reg_range ( ISL7998X_REG_PX_DEC_PAGE ( 5 ) ,
ISL7998X_REG_PX_DEC_PAGE ( 5 ) ) ,
ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE ( 0xf ) ,
} ;
static const struct regmap_range isl7998x_volatile_ranges [ ] = {
/* Product id code register is used to check availability */
regmap_reg_range ( ISL7998X_REG_P0_PRODUCT_ID_CODE ,
ISL7998X_REG_P0_PRODUCT_ID_CODE ) ,
regmap_reg_range ( ISL7998X_REG_P0_MPP1_SYNC_CTL ,
ISL7998X_REG_P0_IRQ_SYNC_CTL ) ,
regmap_reg_range ( ISL7998X_REG_P0_INTERRUPT_STATUS ,
ISL7998X_REG_P0_INTERRUPT_STATUS ) ,
regmap_reg_range ( ISL7998X_REG_P0_CHAN_1_STATUS ,
ISL7998X_REG_P0_SHORT_DIAG_STATUS ) ,
ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE ( 1 ) ,
ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE ( 2 ) ,
ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE ( 3 ) ,
ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE ( 4 ) ,
regmap_reg_range ( ISL7998X_REG_P5_AUTO_TEST_ERR_DET ,
ISL7998X_REG_P5_PIC_HEIGHT_LOW ) ,
} ;
static const struct regmap_access_table isl7998x_readable_table = {
. yes_ranges = isl7998x_readable_ranges ,
. n_yes_ranges = ARRAY_SIZE ( isl7998x_readable_ranges ) ,
} ;
static const struct regmap_access_table isl7998x_writeable_table = {
. yes_ranges = isl7998x_writeable_ranges ,
. n_yes_ranges = ARRAY_SIZE ( isl7998x_writeable_ranges ) ,
} ;
static const struct regmap_access_table isl7998x_volatile_table = {
. yes_ranges = isl7998x_volatile_ranges ,
. n_yes_ranges = ARRAY_SIZE ( isl7998x_volatile_ranges ) ,
} ;
static const struct regmap_range_cfg isl7998x_ranges [ ] = {
{
. range_min = ISL7998X_REG_PN_BASE ( 0 ) ,
. range_max = ISL7998X_REG_PX_ACA_XFER_HIST_HOST ( 0xf ) ,
. selector_reg = ISL7998X_REG_PX_DEC_PAGE ( 0 ) ,
. selector_mask = ISL7998X_REG_PX_DEC_PAGE_MASK ,
. window_start = 0 ,
. window_len = 256 ,
}
} ;
static const struct regmap_config isl7998x_regmap = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = ISL7998X_REG_PX_ACA_XFER_HIST_HOST ( 0xf ) ,
. ranges = isl7998x_ranges ,
. num_ranges = ARRAY_SIZE ( isl7998x_ranges ) ,
. rd_table = & isl7998x_readable_table ,
. wr_table = & isl7998x_writeable_table ,
. volatile_table = & isl7998x_volatile_table ,
2024-01-17 04:09:10 +01:00
. cache_type = REGCACHE_MAPLE ,
2022-02-17 16:44:07 +01:00
} ;
static int isl7998x_mc_init ( struct isl7998x * isl7998x )
{
unsigned int i ;
isl7998x - > subdev . entity . ops = & isl7998x_entity_ops ;
isl7998x - > subdev . entity . function = MEDIA_ENT_F_VID_IF_BRIDGE ;
isl7998x - > pads [ ISL7998X_PAD_OUT ] . flags = MEDIA_PAD_FL_SOURCE ;
for ( i = ISL7998X_PAD_VIN1 ; i < ISL7998X_NUM_PADS ; i + + )
isl7998x - > pads [ i ] . flags = MEDIA_PAD_FL_SINK ;
return media_entity_pads_init ( & isl7998x - > subdev . entity ,
ISL7998X_NUM_PADS ,
isl7998x - > pads ) ;
}
static int get_link_freq_menu_index ( unsigned int lanes ,
unsigned int inputs )
{
int ret = - EINVAL ;
switch ( lanes ) {
case 1 :
if ( inputs = = 1 )
ret = 0 ;
if ( inputs = = 2 )
ret = 1 ;
if ( inputs = = 4 )
ret = 2 ;
break ;
case 2 :
if ( inputs = = 2 )
ret = 0 ;
if ( inputs = = 4 )
ret = 1 ;
break ;
default :
break ;
}
return ret ;
}
static void isl7998x_remove_controls ( struct isl7998x * isl7998x )
{
v4l2_ctrl_handler_free ( & isl7998x - > ctrl_handler ) ;
mutex_destroy ( & isl7998x - > ctrl_mutex ) ;
}
static int isl7998x_init_controls ( struct isl7998x * isl7998x )
{
struct v4l2_subdev * sd = & isl7998x - > subdev ;
int link_freq_index ;
unsigned int i ;
int ret ;
ret = v4l2_ctrl_handler_init ( & isl7998x - > ctrl_handler ,
2 + ARRAY_SIZE ( isl7998x_ctrls ) ) ;
if ( ret )
return ret ;
mutex_init ( & isl7998x - > ctrl_mutex ) ;
isl7998x - > ctrl_handler . lock = & isl7998x - > ctrl_mutex ;
link_freq_index = get_link_freq_menu_index ( isl7998x - > nr_mipi_lanes ,
isl7998x - > nr_inputs ) ;
if ( link_freq_index < 0 | |
link_freq_index > = ARRAY_SIZE ( link_freq_menu_items ) ) {
dev_err ( sd - > dev ,
" failed to find MIPI link freq: %d lanes, %d inputs \n " ,
isl7998x - > nr_mipi_lanes , isl7998x - > nr_inputs ) ;
ret = - EINVAL ;
goto err ;
}
isl7998x - > link_freq = v4l2_ctrl_new_int_menu ( & isl7998x - > ctrl_handler ,
& isl7998x_ctrl_ops ,
V4L2_CID_LINK_FREQ ,
ARRAY_SIZE ( link_freq_menu_items ) - 1 ,
link_freq_index ,
link_freq_menu_items ) ;
if ( isl7998x - > link_freq )
isl7998x - > link_freq - > flags | = V4L2_CTRL_FLAG_READ_ONLY ;
for ( i = 0 ; i < ARRAY_SIZE ( isl7998x_ctrls ) ; i + + )
v4l2_ctrl_new_custom ( & isl7998x - > ctrl_handler ,
& isl7998x_ctrls [ i ] , NULL ) ;
v4l2_ctrl_new_std_menu_items ( & isl7998x - > ctrl_handler ,
& isl7998x_ctrl_ops ,
V4L2_CID_TEST_PATTERN ,
ARRAY_SIZE ( isl7998x_test_pattern_menu ) - 1 ,
0 , 0 , isl7998x_test_pattern_menu ) ;
ret = isl7998x - > ctrl_handler . error ;
if ( ret )
goto err ;
isl7998x - > subdev . ctrl_handler = & isl7998x - > ctrl_handler ;
v4l2_ctrl_handler_setup ( & isl7998x - > ctrl_handler ) ;
return 0 ;
err :
isl7998x_remove_controls ( isl7998x ) ;
return ret ;
}
static int isl7998x_probe ( struct i2c_client * client )
{
struct device * dev = & client - > dev ;
struct v4l2_fwnode_endpoint endpoint = {
. bus_type = V4L2_MBUS_CSI2_DPHY ,
} ;
struct fwnode_handle * ep ;
struct isl7998x * isl7998x ;
struct i2c_adapter * adapter = to_i2c_adapter ( client - > dev . parent ) ;
int nr_inputs ;
int ret ;
ret = i2c_check_functionality ( adapter , I2C_FUNC_SMBUS_WORD_DATA ) ;
if ( ! ret ) {
dev_warn ( & adapter - > dev ,
" I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD \n " ) ;
return - EIO ;
}
isl7998x = devm_kzalloc ( dev , sizeof ( * isl7998x ) , GFP_KERNEL ) ;
if ( ! isl7998x )
return - ENOMEM ;
isl7998x - > pd_gpio = devm_gpiod_get_optional ( dev , " powerdown " ,
GPIOD_OUT_HIGH ) ;
if ( IS_ERR ( isl7998x - > pd_gpio ) )
return dev_err_probe ( dev , PTR_ERR ( isl7998x - > pd_gpio ) ,
" Failed to retrieve/request PD GPIO \n " ) ;
isl7998x - > rstb_gpio = devm_gpiod_get_optional ( dev , " reset " ,
GPIOD_OUT_HIGH ) ;
if ( IS_ERR ( isl7998x - > rstb_gpio ) )
return dev_err_probe ( dev , PTR_ERR ( isl7998x - > rstb_gpio ) ,
" Failed to retrieve/request RSTB GPIO \n " ) ;
isl7998x - > regmap = devm_regmap_init_i2c ( client , & isl7998x_regmap ) ;
if ( IS_ERR ( isl7998x - > regmap ) )
return dev_err_probe ( dev , PTR_ERR ( isl7998x - > regmap ) ,
" Failed to allocate register map \n " ) ;
ep = fwnode_graph_get_endpoint_by_id ( dev_fwnode ( dev ) ,
ISL7998X_PAD_OUT , 0 , 0 ) ;
if ( ! ep )
return dev_err_probe ( dev , - EINVAL , " Missing endpoint node \n " ) ;
ret = v4l2_fwnode_endpoint_parse ( ep , & endpoint ) ;
fwnode_handle_put ( ep ) ;
if ( ret )
return dev_err_probe ( dev , ret , " Failed to parse endpoint \n " ) ;
if ( endpoint . bus . mipi_csi2 . num_data_lanes = = 0 | |
endpoint . bus . mipi_csi2 . num_data_lanes > 2 )
return dev_err_probe ( dev , - EINVAL ,
" Invalid number of MIPI lanes \n " ) ;
isl7998x - > nr_mipi_lanes = endpoint . bus . mipi_csi2 . num_data_lanes ;
nr_inputs = isl7998x_get_nr_inputs ( dev - > of_node ) ;
if ( nr_inputs < 0 )
return dev_err_probe ( dev , nr_inputs ,
" Invalid number of input ports \n " ) ;
isl7998x - > nr_inputs = nr_inputs ;
v4l2_i2c_subdev_init ( & isl7998x - > subdev , client , & isl7998x_subdev_ops ) ;
isl7998x - > subdev . flags | = V4L2_SUBDEV_FL_HAS_DEVNODE ;
ret = isl7998x_mc_init ( isl7998x ) ;
if ( ret < 0 )
return ret ;
isl7998x - > fmt = & isl7998x_colour_fmts [ 0 ] ;
isl7998x - > norm = V4L2_STD_NTSC ;
isl7998x - > enabled = 0 ;
mutex_init ( & isl7998x - > lock ) ;
ret = isl7998x_init_controls ( isl7998x ) ;
if ( ret )
goto err_entity_cleanup ;
ret = v4l2_async_register_subdev ( & isl7998x - > subdev ) ;
if ( ret < 0 )
goto err_controls_cleanup ;
pm_runtime_enable ( dev ) ;
return 0 ;
err_controls_cleanup :
isl7998x_remove_controls ( isl7998x ) ;
err_entity_cleanup :
media_entity_cleanup ( & isl7998x - > subdev . entity ) ;
return ret ;
}
2022-08-15 10:02:30 +02:00
static void isl7998x_remove ( struct i2c_client * client )
2022-02-17 16:44:07 +01:00
{
struct isl7998x * isl7998x = i2c_to_isl7998x ( client ) ;
pm_runtime_disable ( & client - > dev ) ;
v4l2_async_unregister_subdev ( & isl7998x - > subdev ) ;
isl7998x_remove_controls ( isl7998x ) ;
media_entity_cleanup ( & isl7998x - > subdev . entity ) ;
}
static const struct of_device_id isl7998x_of_match [ ] = {
{ . compatible = " isil,isl79987 " , } ,
{ /* sentinel */ } ,
} ;
MODULE_DEVICE_TABLE ( of , isl7998x_of_match ) ;
static const struct i2c_device_id isl7998x_id [ ] = {
{ " isl79987 " , 0 } ,
{ /* sentinel */ } ,
} ;
MODULE_DEVICE_TABLE ( i2c , isl7998x_id ) ;
static int __maybe_unused isl7998x_runtime_resume ( struct device * dev )
{
struct v4l2_subdev * sd = dev_get_drvdata ( dev ) ;
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
int ret ;
gpiod_set_value ( isl7998x - > rstb_gpio , 1 ) ;
gpiod_set_value ( isl7998x - > pd_gpio , 0 ) ;
gpiod_set_value ( isl7998x - > rstb_gpio , 0 ) ;
ret = isl7998x_wait_power_on ( isl7998x ) ;
if ( ret )
goto err ;
ret = isl7998x_init ( isl7998x ) ;
if ( ret )
goto err ;
return 0 ;
err :
gpiod_set_value ( isl7998x - > pd_gpio , 1 ) ;
return ret ;
}
static int __maybe_unused isl7998x_runtime_suspend ( struct device * dev )
{
struct v4l2_subdev * sd = dev_get_drvdata ( dev ) ;
struct isl7998x * isl7998x = sd_to_isl7998x ( sd ) ;
gpiod_set_value ( isl7998x - > pd_gpio , 1 ) ;
return 0 ;
}
static const struct dev_pm_ops isl7998x_pm_ops = {
SET_RUNTIME_PM_OPS ( isl7998x_runtime_suspend ,
isl7998x_runtime_resume ,
NULL )
} ;
static struct i2c_driver isl7998x_i2c_driver = {
. driver = {
. name = " isl7998x " ,
2023-03-12 14:13:11 +01:00
. of_match_table = isl7998x_of_match ,
2022-02-17 16:44:07 +01:00
. pm = & isl7998x_pm_ops ,
} ,
2023-05-14 14:04:07 +02:00
. probe = isl7998x_probe ,
2022-02-17 16:44:07 +01:00
. remove = isl7998x_remove ,
. id_table = isl7998x_id ,
} ;
module_i2c_driver ( isl7998x_i2c_driver ) ;
MODULE_DESCRIPTION ( " Intersil ISL7998x Analog to MIPI CSI-2/BT656 decoder " ) ;
MODULE_AUTHOR ( " Marek Vasut <marex@denx.de> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;