| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626 |
- // 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>
- #include <linux/gpio/consumer.h>
- #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;
- static const u32 isl7998x_video_in_chan_map[] = { 0x00, 0x11, 0x02, 0x02 };
- 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), ®);
- 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, ®);
- 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) {
- format->format = *v4l2_subdev_state_get_format(sd_state,
- format->pad);
- 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)
- *v4l2_subdev_state_get_format(sd_state, format->pad) = format->format;
- 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,
- .cache_type = REGCACHE_MAPLE,
- };
- 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;
- }
- static void isl7998x_remove(struct i2c_client *client)
- {
- 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" },
- { /* 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",
- .of_match_table = isl7998x_of_match,
- .pm = &isl7998x_pm_ops,
- },
- .probe = isl7998x_probe,
- .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");
|