aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-10-29 14:29:58 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-29 14:29:58 -0700
commit134bf98c5596605af90f104716ef912e8f7eb56b (patch)
treeb41d585cc432100933e790ad8cab21e970e6d8f6
parent044ee890286153a1aefb40cb8b6659921aecb38b (diff)
parent3b796aa60af087f5fec75aee9b17f2130f2b9adc (diff)
download96b-common-134bf98c5596605af90f104716ef912e8f7eb56b.tar.gz
Merge tag 'media/v4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - new dvb frontend driver: lnbh29 - new sensor drivers: imx319 and imx 355 - some old soc_camera driver renames to avoid conflict with new drivers - new i.MX Pixel Pipeline (PXP) mem-to-mem platform driver - a new V4L2 frontend for the FWHT codec - several other improvements, bug fixes, code cleanups, etc * tag 'media/v4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (289 commits) media: rename soc_camera I2C drivers media: cec: forgot to cancel delayed work media: vivid: Support 480p for webcam capture media: v4l2-tpg: fix kernel oops when enabling HFLIP and OSD media: vivid: Add 16-bit bayer to format list media: v4l2-tpg-core: Add 16-bit bayer media: pvrusb2: replace `printk` with `pr_*` media: venus: vdec: fix decoded data size media: cx231xx: fix potential sign-extension overflow on large shift media: dt-bindings: media: rcar_vin: add device tree support for r8a7744 media: isif: fix a NULL pointer dereference bug media: exynos4-is: make const array config_ids static media: cx23885: make const array addr_list static media: ivtv: make const array addr_list static media: bttv-input: make const array addr_list static media: cx18: Don't check for address of video_dev media: dw9807-vcm: Fix probe error handling media: dw9714: Remove useless error message media: dw9714: Fix error handling in probe function media: cec: name for RC passthrough device does not need 'RC for' ...
-rw-r--r--Documentation/devicetree/bindings/media/fsl-pxp.txt26
-rw-r--r--Documentation/devicetree/bindings/media/i2c/adv748x.txt20
-rw-r--r--Documentation/devicetree/bindings/media/i2c/adv7604.txt2
-rw-r--r--Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt (renamed from Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807.txt)0
-rw-r--r--Documentation/devicetree/bindings/media/rcar_vin.txt1
-rw-r--r--Documentation/devicetree/bindings/media/renesas,ceu.txt14
-rw-r--r--Documentation/devicetree/bindings/media/video-interfaces.txt4
-rw-r--r--Documentation/media/kapi/cec-core.rst4
-rw-r--r--Documentation/media/kapi/v4l2-subdev.rst30
-rw-r--r--Documentation/media/uapi/cec/cec-func-poll.rst3
-rw-r--r--Documentation/media/uapi/cec/cec-ioc-receive.rst25
-rw-r--r--Documentation/media/uapi/mediactl/media-ioc-device-info.rst1
-rw-r--r--Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst1
-rw-r--r--Documentation/media/uapi/mediactl/media-ioc-enum-links.rst1
-rw-r--r--Documentation/media/uapi/mediactl/media-ioc-g-topology.rst1
-rw-r--r--Documentation/media/uapi/mediactl/media-ioc-setup-link.rst1
-rw-r--r--Documentation/media/uapi/v4l/biblio.rst10
-rw-r--r--Documentation/media/uapi/v4l/colorspaces-defs.rst8
-rw-r--r--Documentation/media/uapi/v4l/colorspaces-details.rst13
-rw-r--r--Documentation/media/uapi/v4l/func-poll.rst3
-rw-r--r--Documentation/media/uapi/v4l/meta-formats.rst1
-rw-r--r--Documentation/media/uapi/v4l/pixfmt-compressed.rst2
-rw-r--r--Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst210
-rw-r--r--Documentation/media/uapi/v4l/vidioc-cropcap.rst2
-rw-r--r--Documentation/media/uapi/v4l/vidioc-dqevent.rst12
-rw-r--r--Documentation/media/uapi/v4l/vidioc-g-crop.rst2
-rw-r--r--Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst27
-rw-r--r--Documentation/media/videodev2.h.rst.exceptions7
-rw-r--r--MAINTAINERS44
-rw-r--r--arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi4
-rw-r--r--drivers/gpu/ipu-v3/ipu-csi.c6
-rw-r--r--drivers/hid/hid-picolcd_cir.c3
-rw-r--r--drivers/media/cec/Makefile2
-rw-r--r--drivers/media/cec/cec-adap.c107
-rw-r--r--drivers/media/cec/cec-api.c24
-rw-r--r--drivers/media/cec/cec-core.c8
-rw-r--r--drivers/media/cec/cec-edid.c155
-rw-r--r--drivers/media/cec/cec-pin.c20
-rw-r--r--drivers/media/common/b2c2/flexcop-i2c.c12
-rw-r--r--drivers/media/common/cx2341x.c2
-rw-r--r--drivers/media/common/saa7146/saa7146_fops.c2
-rw-r--r--drivers/media/common/saa7146/saa7146_video.c8
-rw-r--r--drivers/media/common/siano/smscoreapi.c4
-rw-r--r--drivers/media/common/siano/smsir.c10
-rw-r--r--drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c262
-rw-r--r--drivers/media/common/v4l2-tpg/v4l2-tpg-core.c41
-rw-r--r--drivers/media/common/videobuf2/videobuf2-core.c9
-rw-r--r--drivers/media/dvb-core/dmxdev.c1
-rw-r--r--drivers/media/dvb-core/dvb_frontend.c2
-rw-r--r--drivers/media/dvb-core/dvb_vb2.c2
-rw-r--r--drivers/media/dvb-core/dvbdev.c23
-rw-r--r--drivers/media/dvb-frontends/Kconfig10
-rw-r--r--drivers/media/dvb-frontends/Makefile1
-rw-r--r--drivers/media/dvb-frontends/au8522_decoder.c10
-rw-r--r--drivers/media/dvb-frontends/au8522_priv.h9
-rw-r--r--drivers/media/dvb-frontends/cx24123.c2
-rw-r--r--drivers/media/dvb-frontends/cxd2099.c3
-rw-r--r--drivers/media/dvb-frontends/cxd2099.h1
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_core.c2
-rw-r--r--drivers/media/dvb-frontends/dibx000_common.c2
-rw-r--r--drivers/media/dvb-frontends/drx39xyj/drxj.c10
-rw-r--r--drivers/media/dvb-frontends/lgdt330x.c2
-rw-r--r--drivers/media/dvb-frontends/lnbh29.c168
-rw-r--r--drivers/media/dvb-frontends/lnbh29.h36
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.c2
-rw-r--r--drivers/media/dvb-frontends/mt312.c9
-rw-r--r--drivers/media/dvb-frontends/mxl5xx.c5
-rw-r--r--drivers/media/dvb-frontends/mxl5xx.h22
-rw-r--r--drivers/media/dvb-frontends/mxl5xx_defs.h1
-rw-r--r--drivers/media/dvb-frontends/mxl5xx_regs.h1
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.c10
-rw-r--r--drivers/media/dvb-frontends/s5h1420.c2
-rw-r--r--drivers/media/dvb-frontends/stv0910.c3
-rw-r--r--drivers/media/dvb-frontends/stv0910.h18
-rw-r--r--drivers/media/dvb-frontends/stv0910_regs.h1
-rw-r--r--drivers/media/dvb-frontends/stv6111.c4
-rw-r--r--drivers/media/dvb-frontends/stv6111.h16
-rw-r--r--drivers/media/dvb-frontends/tc90522.c2
-rw-r--r--drivers/media/dvb-frontends/ts2020.c2
-rw-r--r--drivers/media/dvb-frontends/zd1301_demod.c3
-rw-r--r--drivers/media/dvb-frontends/zl10039.c5
-rw-r--r--drivers/media/firewire/firedtv-fe.c2
-rw-r--r--drivers/media/i2c/Kconfig24
-rw-r--r--drivers/media/i2c/Makefile2
-rw-r--r--drivers/media/i2c/ad5820.c2
-rw-r--r--drivers/media/i2c/adv7180.c13
-rw-r--r--drivers/media/i2c/adv748x/adv748x-afe.c8
-rw-r--r--drivers/media/i2c/adv748x/adv748x-core.c93
-rw-r--r--drivers/media/i2c/adv748x/adv748x-csi2.c35
-rw-r--r--drivers/media/i2c/adv748x/adv748x-hdmi.c8
-rw-r--r--drivers/media/i2c/adv748x/adv748x.h25
-rw-r--r--drivers/media/i2c/adv7511.c6
-rw-r--r--drivers/media/i2c/adv7604.c12
-rw-r--r--drivers/media/i2c/adv7842.c17
-rw-r--r--drivers/media/i2c/ak881x.c1
-rw-r--r--drivers/media/i2c/cs53l32a.c2
-rw-r--r--drivers/media/i2c/cx25840/cx25840-ir.c6
-rw-r--r--drivers/media/i2c/dw9714.c5
-rw-r--r--drivers/media/i2c/dw9807-vcm.c4
-rw-r--r--drivers/media/i2c/imx274.c165
-rw-r--r--drivers/media/i2c/imx319.c2560
-rw-r--r--drivers/media/i2c/imx355.c1860
-rw-r--r--drivers/media/i2c/lm3560.c3
-rw-r--r--drivers/media/i2c/lm3646.c3
-rw-r--r--drivers/media/i2c/m5mols/m5mols_core.c3
-rw-r--r--drivers/media/i2c/max2175.c12
-rw-r--r--drivers/media/i2c/max2175.h12
-rw-r--r--drivers/media/i2c/msp3400-driver.c8
-rw-r--r--drivers/media/i2c/msp3400-driver.h8
-rw-r--r--drivers/media/i2c/mt9m111.c1
-rw-r--r--drivers/media/i2c/mt9t112.c6
-rw-r--r--drivers/media/i2c/mt9v032.c2
-rw-r--r--drivers/media/i2c/noon010pc30.c3
-rw-r--r--drivers/media/i2c/ov13858.c12
-rw-r--r--drivers/media/i2c/ov2640.c1
-rw-r--r--drivers/media/i2c/ov2659.c14
-rw-r--r--drivers/media/i2c/ov2680.c16
-rw-r--r--drivers/media/i2c/ov2685.c2
-rw-r--r--drivers/media/i2c/ov5640.c309
-rw-r--r--drivers/media/i2c/ov5645.c2
-rw-r--r--drivers/media/i2c/ov5647.c2
-rw-r--r--drivers/media/i2c/ov5670.c12
-rw-r--r--drivers/media/i2c/ov5695.c2
-rw-r--r--drivers/media/i2c/ov6650.c1
-rw-r--r--drivers/media/i2c/ov7251.c4
-rw-r--r--drivers/media/i2c/ov7670.c29
-rw-r--r--drivers/media/i2c/ov772x.c194
-rw-r--r--drivers/media/i2c/ov7740.c2
-rw-r--r--drivers/media/i2c/ov9650.c161
-rw-r--r--drivers/media/i2c/rj54n1cb0c.c1
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-core.c9
-rw-r--r--drivers/media/i2c/s5k4ecgx.c3
-rw-r--r--drivers/media/i2c/s5k5baf.c6
-rw-r--r--drivers/media/i2c/s5k6aa.c5
-rw-r--r--drivers/media/i2c/saa7115.c24
-rw-r--r--drivers/media/i2c/saa7127.c4
-rw-r--r--drivers/media/i2c/smiapp/smiapp-core.c48
-rw-r--r--drivers/media/i2c/soc_camera/Makefile18
-rw-r--r--drivers/media/i2c/soc_camera/soc_mt9m001.c (renamed from drivers/media/i2c/soc_camera/mt9m001.c)1
-rw-r--r--drivers/media/i2c/soc_camera/soc_mt9t112.c (renamed from drivers/media/i2c/soc_camera/mt9t112.c)6
-rw-r--r--drivers/media/i2c/soc_camera/soc_mt9v022.c (renamed from drivers/media/i2c/soc_camera/mt9v022.c)1
-rw-r--r--drivers/media/i2c/soc_camera/soc_ov5642.c (renamed from drivers/media/i2c/soc_camera/ov5642.c)3
-rw-r--r--drivers/media/i2c/soc_camera/soc_ov772x.c (renamed from drivers/media/i2c/soc_camera/ov772x.c)1
-rw-r--r--drivers/media/i2c/soc_camera/soc_ov9640.c (renamed from drivers/media/i2c/soc_camera/ov9640.c)1
-rw-r--r--drivers/media/i2c/soc_camera/soc_ov9740.c (renamed from drivers/media/i2c/soc_camera/ov9740.c)1
-rw-r--r--drivers/media/i2c/soc_camera/soc_rj54n1cb0c.c (renamed from drivers/media/i2c/soc_camera/rj54n1cb0c.c)1
-rw-r--r--drivers/media/i2c/soc_camera/soc_tw9910.c (renamed from drivers/media/i2c/soc_camera/tw9910.c)0
-rw-r--r--drivers/media/i2c/sr030pc30.c3
-rw-r--r--drivers/media/i2c/tc358743.c34
-rw-r--r--drivers/media/i2c/tda1997x.c2
-rw-r--r--drivers/media/i2c/tvaudio.c2
-rw-r--r--drivers/media/i2c/tvp514x.c2
-rw-r--r--drivers/media/i2c/tvp5150.c560
-rw-r--r--drivers/media/i2c/tvp5150_reg.h3
-rw-r--r--drivers/media/i2c/tvp7002.c2
-rw-r--r--drivers/media/i2c/video-i2c.c8
-rw-r--r--drivers/media/media-device.c28
-rw-r--r--drivers/media/media-entity.c26
-rw-r--r--drivers/media/pci/bt8xx/bttv-driver.c11
-rw-r--r--drivers/media/pci/bt8xx/bttv-i2c.c6
-rw-r--r--drivers/media/pci/bt8xx/bttv-input.c4
-rw-r--r--drivers/media/pci/bt8xx/dvb-bt8xx.c3
-rw-r--r--drivers/media/pci/cobalt/cobalt-alsa-main.c2
-rw-r--r--drivers/media/pci/cobalt/cobalt-alsa-pcm.c4
-rw-r--r--drivers/media/pci/cobalt/cobalt-v4l2.c23
-rw-r--r--drivers/media/pci/cx18/cx18-alsa-main.c2
-rw-r--r--drivers/media/pci/cx18/cx18-alsa-pcm.c2
-rw-r--r--drivers/media/pci/cx18/cx18-cards.c8
-rw-r--r--drivers/media/pci/cx18/cx18-driver.c4
-rw-r--r--drivers/media/pci/cx18/cx18-i2c.c2
-rw-r--r--drivers/media/pci/cx18/cx18-ioctl.c8
-rw-r--r--drivers/media/pci/cx23885/altera-ci.c10
-rw-r--r--drivers/media/pci/cx23885/cx23885-417.c8
-rw-r--r--drivers/media/pci/cx23885/cx23885-alsa.c4
-rw-r--r--drivers/media/pci/cx23885/cx23885-dvb.c54
-rw-r--r--drivers/media/pci/cx23885/cx23885-i2c.c6
-rw-r--r--drivers/media/pci/cx23885/cx23885-ioctl.c4
-rw-r--r--drivers/media/pci/cx23885/cx23885-video.c15
-rw-r--r--drivers/media/pci/cx23885/cx23888-ir.c6
-rw-r--r--drivers/media/pci/cx25821/cx25821-alsa.c8
-rw-r--r--drivers/media/pci/cx25821/cx25821-i2c.c2
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.c10
-rw-r--r--drivers/media/pci/cx88/cx88-alsa.c6
-rw-r--r--drivers/media/pci/cx88/cx88-blackbird.c6
-rw-r--r--drivers/media/pci/cx88/cx88-cards.c2
-rw-r--r--drivers/media/pci/cx88/cx88-i2c.c4
-rw-r--r--drivers/media/pci/cx88/cx88-input.c7
-rw-r--r--drivers/media/pci/cx88/cx88-video.c12
-rw-r--r--drivers/media/pci/cx88/cx88-vp3054-i2c.c2
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-ci.c4
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-ci.h4
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-core.c6
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-hw.c2
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-hw.h2
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-i2c.c2
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-i2c.h4
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-io.h2
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-main.c4
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-max.c2
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-max.h2
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-regs.h5
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-sx8.c4
-rw-r--r--drivers/media/pci/ddbridge/ddbridge.h5
-rw-r--r--drivers/media/pci/dm1105/dm1105.c5
-rw-r--r--drivers/media/pci/dt3155/dt3155.c8
-rw-r--r--drivers/media/pci/intel/ipu3/ipu3-cio2.c30
-rw-r--r--drivers/media/pci/ivtv/ivtv-alsa-main.c2
-rw-r--r--drivers/media/pci/ivtv/ivtv-alsa-pcm.c2
-rw-r--r--drivers/media/pci/ivtv/ivtv-cards.c12
-rw-r--r--drivers/media/pci/ivtv/ivtv-i2c.c6
-rw-r--r--drivers/media/pci/ivtv/ivtv-ioctl.c42
-rw-r--r--drivers/media/pci/ivtv/ivtv-streams.c9
-rw-r--r--drivers/media/pci/ivtv/ivtv-yuv.c2
-rw-r--r--drivers/media/pci/ivtv/ivtvfb.c2
-rw-r--r--drivers/media/pci/meye/meye.c12
-rw-r--r--drivers/media/pci/ngene/ngene-i2c.c2
-rw-r--r--drivers/media/pci/pluto2/pluto2.c2
-rw-r--r--drivers/media/pci/pt1/pt1.c2
-rw-r--r--drivers/media/pci/pt3/pt3.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-alsa.c8
-rw-r--r--drivers/media/pci/saa7134/saa7134-cards.c15
-rw-r--r--drivers/media/pci/saa7134/saa7134-core.c9
-rw-r--r--drivers/media/pci/saa7134/saa7134-empress.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-go7007.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-i2c.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-input.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-video.c15
-rw-r--r--drivers/media/pci/saa7134/saa7134.h8
-rw-r--r--drivers/media/pci/saa7146/mxb.c2
-rw-r--r--drivers/media/pci/saa7164/saa7164-core.c2
-rw-r--r--drivers/media/pci/saa7164/saa7164-dvb.c10
-rw-r--r--drivers/media/pci/saa7164/saa7164-encoder.c10
-rw-r--r--drivers/media/pci/saa7164/saa7164-i2c.c2
-rw-r--r--drivers/media/pci/saa7164/saa7164-vbi.c4
-rw-r--r--drivers/media/pci/smipcie/smipcie-main.c12
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-g723.c8
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c12
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2.c6
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c6
-rw-r--r--drivers/media/pci/ttpci/av7110.c3
-rw-r--r--drivers/media/pci/ttpci/av7110_av.c58
-rw-r--r--drivers/media/pci/ttpci/av7110_v4l.c2
-rw-r--r--drivers/media/pci/ttpci/budget-core.c6
-rw-r--r--drivers/media/pci/tw5864/tw5864-video.c2
-rw-r--r--drivers/media/pci/tw68/tw68-video.c6
-rw-r--r--drivers/media/pci/tw686x/tw686x-audio.c8
-rw-r--r--drivers/media/pci/tw686x/tw686x-video.c4
-rw-r--r--drivers/media/platform/Kconfig10
-rw-r--r--drivers/media/platform/Makefile2
-rw-r--r--drivers/media/platform/am437x/am437x-vpfe.c93
-rw-r--r--drivers/media/platform/atmel/atmel-isc.c26
-rw-r--r--drivers/media/platform/atmel/atmel-isi.c29
-rw-r--r--drivers/media/platform/cadence/cdns-csi2rx.c32
-rw-r--r--drivers/media/platform/cadence/cdns-csi2tx.c4
-rw-r--r--drivers/media/platform/coda/coda-common.c14
-rw-r--r--drivers/media/platform/davinci/isif.c3
-rw-r--r--drivers/media/platform/davinci/vpbe_display.c10
-rw-r--r--drivers/media/platform/davinci/vpbe_venc.c2
-rw-r--r--drivers/media/platform/davinci/vpfe_capture.c6
-rw-r--r--drivers/media/platform/davinci/vpif_capture.c88
-rw-r--r--drivers/media/platform/davinci/vpif_display.c29
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-core.c2
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-m2m.c4
-rw-r--r--drivers/media/platform/exynos4-is/common.c4
-rw-r--r--drivers/media/platform/exynos4-is/fimc-capture.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-i2c.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp-video.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite.c6
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.c42
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.h1
-rw-r--r--drivers/media/platform/exynos4-is/mipi-csis.c2
-rw-r--r--drivers/media/platform/fsl-viu.c8
-rw-r--r--drivers/media/platform/imx-pxp.c1754
-rw-r--r--drivers/media/platform/imx-pxp.h1685
-rw-r--r--drivers/media/platform/m2m-deinterlace.c8
-rw-r--r--drivers/media/platform/marvell-ccic/cafe-driver.c2
-rw-r--r--drivers/media/platform/marvell-ccic/mcam-core.c16
-rw-r--r--drivers/media/platform/marvell-ccic/mmp-driver.c4
-rw-r--r--drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c4
-rw-r--r--drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c6
-rw-r--r--drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c6
-rw-r--r--drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c6
-rw-r--r--drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c5
-rw-r--r--drivers/media/platform/mtk-vpu/mtk_vpu.c7
-rw-r--r--drivers/media/platform/mx2_emmaprp.c2
-rw-r--r--drivers/media/platform/omap/omap_vout.c10
-rw-r--r--drivers/media/platform/omap3isp/isp.c5
-rw-r--r--drivers/media/platform/omap3isp/ispccdc.c2
-rw-r--r--drivers/media/platform/omap3isp/ispccp2.c2
-rw-r--r--drivers/media/platform/omap3isp/ispcsi2.c2
-rw-r--r--drivers/media/platform/omap3isp/isppreview.c2
-rw-r--r--drivers/media/platform/omap3isp/ispresizer.c2
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c8
-rw-r--r--drivers/media/platform/pxa_camera.c39
-rw-r--r--drivers/media/platform/qcom/camss/camss-video.c8
-rw-r--r--drivers/media/platform/qcom/camss/camss.c91
-rw-r--r--drivers/media/platform/qcom/camss/camss.h3
-rw-r--r--drivers/media/platform/qcom/venus/helpers.c2
-rw-r--r--drivers/media/platform/qcom/venus/vdec.c11
-rw-r--r--drivers/media/platform/qcom/venus/venc.c8
-rw-r--r--drivers/media/platform/rcar-vin/rcar-core.c11
-rw-r--r--drivers/media/platform/rcar-vin/rcar-csi2.c26
-rw-r--r--drivers/media/platform/rcar-vin/rcar-v4l2.c8
-rw-r--r--drivers/media/platform/rcar_drif.c22
-rw-r--r--drivers/media/platform/rcar_fdp1.c6
-rw-r--r--drivers/media/platform/rcar_jpu.c10
-rw-r--r--drivers/media/platform/renesas-ceu.c78
-rw-r--r--drivers/media/platform/rockchip/rga/rga.c6
-rw-r--r--drivers/media/platform/s3c-camif/camif-capture.c10
-rw-r--r--drivers/media/platform/s3c-camif/camif-core.c4
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-core.c10
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_dec.c6
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_enc.c6
-rw-r--r--drivers/media/platform/sh_veu.c9
-rw-r--r--drivers/media/platform/sh_vou.c10
-rw-r--r--drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c6
-rw-r--r--drivers/media/platform/soc_camera/soc_camera.c43
-rw-r--r--drivers/media/platform/soc_camera/soc_camera_platform.c2
-rw-r--r--drivers/media/platform/soc_camera/soc_mediabus.c2
-rw-r--r--drivers/media/platform/soc_camera/soc_scale_crop.c2
-rw-r--r--drivers/media/platform/sti/bdisp/bdisp-v4l2.c4
-rw-r--r--drivers/media/platform/sti/delta/delta-v4l2.c4
-rw-r--r--drivers/media/platform/sti/hva/hva-v4l2.c4
-rw-r--r--drivers/media/platform/stm32/stm32-dcmi.c43
-rw-r--r--drivers/media/platform/ti-vpe/cal.c61
-rw-r--r--drivers/media/platform/via-camera.c10
-rw-r--r--drivers/media/platform/vicodec/Kconfig2
-rw-r--r--drivers/media/platform/vicodec/Makefile2
-rw-r--r--drivers/media/platform/vicodec/codec-fwht.c (renamed from drivers/media/platform/vicodec/vicodec-codec.c)160
-rw-r--r--drivers/media/platform/vicodec/codec-fwht.h (renamed from drivers/media/platform/vicodec/vicodec-codec.h)82
-rw-r--r--drivers/media/platform/vicodec/codec-v4l2-fwht.c332
-rw-r--r--drivers/media/platform/vicodec/codec-v4l2-fwht.h47
-rw-r--r--drivers/media/platform/vicodec/vicodec-core.c520
-rw-r--r--drivers/media/platform/video-mux.c38
-rw-r--r--drivers/media/platform/vim2m.c2
-rw-r--r--drivers/media/platform/vimc/vimc-capture.c6
-rw-r--r--drivers/media/platform/vimc/vimc-common.c2
-rw-r--r--drivers/media/platform/vimc/vimc-core.c4
-rw-r--r--drivers/media/platform/vimc/vimc-sensor.c20
-rw-r--r--drivers/media/platform/vivid/vivid-cec.c4
-rw-r--r--drivers/media/platform/vivid/vivid-core.c4
-rw-r--r--drivers/media/platform/vivid/vivid-core.h2
-rw-r--r--drivers/media/platform/vivid/vivid-ctrls.c6
-rw-r--r--drivers/media/platform/vivid/vivid-osd.c2
-rw-r--r--drivers/media/platform/vivid/vivid-radio-common.c4
-rw-r--r--drivers/media/platform/vivid/vivid-radio-rx.c2
-rw-r--r--drivers/media/platform/vivid/vivid-radio-tx.c2
-rw-r--r--drivers/media/platform/vivid/vivid-rds-gen.c4
-rw-r--r--drivers/media/platform/vivid/vivid-sdr-cap.c4
-rw-r--r--drivers/media/platform/vivid/vivid-vid-cap.c11
-rw-r--r--drivers/media/platform/vivid/vivid-vid-common.c30
-rw-r--r--drivers/media/platform/vivid/vivid-vid-out.c2
-rw-r--r--drivers/media/platform/vsp1/vsp1_brx.c4
-rw-r--r--drivers/media/platform/vsp1/vsp1_drm.c11
-rw-r--r--drivers/media/platform/vsp1/vsp1_drv.c8
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.c2
-rw-r--r--drivers/media/platform/vsp1/vsp1_histo.c4
-rw-r--r--drivers/media/platform/vsp1/vsp1_lif.c29
-rw-r--r--drivers/media/platform/vsp1/vsp1_regs.h2
-rw-r--r--drivers/media/platform/vsp1/vsp1_rpf.c4
-rw-r--r--drivers/media/platform/vsp1/vsp1_sru.c7
-rw-r--r--drivers/media/platform/vsp1/vsp1_uds.c14
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.c13
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c2
-rw-r--r--drivers/media/platform/xilinx/xilinx-dma.c14
-rw-r--r--drivers/media/platform/xilinx/xilinx-tpg.c2
-rw-r--r--drivers/media/platform/xilinx/xilinx-vipp.c175
-rw-r--r--drivers/media/platform/xilinx/xilinx-vipp.h4
-rw-r--r--drivers/media/radio/dsbr100.c9
-rw-r--r--drivers/media/radio/radio-cadet.c12
-rw-r--r--drivers/media/radio/radio-isa.c10
-rw-r--r--drivers/media/radio/radio-keene.c8
-rw-r--r--drivers/media/radio/radio-ma901.c8
-rw-r--r--drivers/media/radio/radio-maxiradio.c2
-rw-r--r--drivers/media/radio/radio-miropcm20.c10
-rw-r--r--drivers/media/radio/radio-mr800.c8
-rw-r--r--drivers/media/radio/radio-raremono.c8
-rw-r--r--drivers/media/radio/radio-sf16fmi.c12
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c6
-rw-r--r--drivers/media/radio/radio-shark.c2
-rw-r--r--drivers/media/radio/radio-shark2.c2
-rw-r--r--drivers/media/radio/radio-si476x.c12
-rw-r--r--drivers/media/radio/radio-tea5764.c6
-rw-r--r--drivers/media/radio/radio-tea5777.c12
-rw-r--r--drivers/media/radio/radio-timb.c8
-rw-r--r--drivers/media/radio/radio-wl1273.c12
-rw-r--r--drivers/media/radio/si470x/radio-si470x-common.c2
-rw-r--r--drivers/media/radio/si470x/radio-si470x-i2c.c4
-rw-r--r--drivers/media/radio/si470x/radio-si470x-usb.c4
-rw-r--r--drivers/media/radio/si4713/radio-platform-si4713.c6
-rw-r--r--drivers/media/radio/si4713/radio-usb-si4713.c6
-rw-r--r--drivers/media/radio/tea575x.c10
-rw-r--r--drivers/media/radio/tef6862.c2
-rw-r--r--drivers/media/radio/wl128x/fmdrv_v4l2.c13
-rw-r--r--drivers/media/rc/ati_remote.c2
-rw-r--r--drivers/media/rc/ene_ir.c12
-rw-r--r--drivers/media/rc/fintek-cir.c3
-rw-r--r--drivers/media/rc/igorplugusb.c2
-rw-r--r--drivers/media/rc/iguanair.c4
-rw-r--r--drivers/media/rc/imon_raw.c2
-rw-r--r--drivers/media/rc/ir-hix5hd2.c2
-rw-r--r--drivers/media/rc/ir-imon-decoder.c62
-rw-r--r--drivers/media/rc/ir-mce_kbd-decoder.c77
-rw-r--r--drivers/media/rc/ir-rc6-decoder.c9
-rw-r--r--drivers/media/rc/ite-cir.c5
-rw-r--r--drivers/media/rc/keymaps/rc-behold.c2
-rw-r--r--drivers/media/rc/keymaps/rc-delock-61959.c2
-rw-r--r--drivers/media/rc/keymaps/rc-imon-rsc.c2
-rw-r--r--drivers/media/rc/keymaps/rc-it913x-v1.c2
-rw-r--r--drivers/media/rc/keymaps/rc-it913x-v2.c2
-rw-r--r--drivers/media/rc/keymaps/rc-msi-digivox-iii.c2
-rw-r--r--drivers/media/rc/keymaps/rc-pixelview-002t.c2
-rw-r--r--drivers/media/rc/keymaps/rc-pixelview-mk12.c2
-rw-r--r--drivers/media/rc/keymaps/rc-reddo.c2
-rw-r--r--drivers/media/rc/keymaps/rc-terratec-slim.c2
-rw-r--r--drivers/media/rc/keymaps/rc-tivo.c2
-rw-r--r--drivers/media/rc/keymaps/rc-total-media-in-hand.c2
-rw-r--r--drivers/media/rc/mceusb.c17
-rw-r--r--drivers/media/rc/meson-ir.c2
-rw-r--r--drivers/media/rc/mtk-cir.c2
-rw-r--r--drivers/media/rc/nuvoton-cir.c2
-rw-r--r--drivers/media/rc/rc-core-priv.h12
-rw-r--r--drivers/media/rc/rc-ir-raw.c12
-rw-r--r--drivers/media/rc/rc-loopback.c2
-rw-r--r--drivers/media/rc/rc-main.c20
-rw-r--r--drivers/media/rc/redrat3.c10
-rw-r--r--drivers/media/rc/serial_ir.c10
-rw-r--r--drivers/media/rc/sir_ir.c2
-rw-r--r--drivers/media/rc/st_rc.c5
-rw-r--r--drivers/media/rc/streamzap.c14
-rw-r--r--drivers/media/rc/sunxi-cir.c2
-rw-r--r--drivers/media/rc/ttusbir.c4
-rw-r--r--drivers/media/rc/winbond-cir.c12
-rw-r--r--drivers/media/tuners/e4000.c2
-rw-r--r--drivers/media/tuners/fc2580.c2
-rw-r--r--drivers/media/tuners/msi001.c2
-rw-r--r--drivers/media/tuners/mt20xx.c2
-rw-r--r--drivers/media/tuners/si2157.c13
-rw-r--r--drivers/media/tuners/si2157_priv.h9
-rw-r--r--drivers/media/tuners/tuner-simple.c2
-rw-r--r--drivers/media/usb/airspy/airspy.c10
-rw-r--r--drivers/media/usb/au0828/au0828-core.c17
-rw-r--r--drivers/media/usb/au0828/au0828-i2c.c2
-rw-r--r--drivers/media/usb/au0828/au0828-input.c5
-rw-r--r--drivers/media/usb/au0828/au0828-video.c22
-rw-r--r--drivers/media/usb/cpia2/cpia2_v4l.c12
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-417.c2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-audio.c8
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-input.c2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-video.c29
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/anysee.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvbsky.c16
-rw-r--r--drivers/media/usb/dvb-usb-v2/gl861.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/lmedm04.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.c8
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.h8
-rw-r--r--drivers/media/usb/dvb-usb-v2/rtl28xxu.c22
-rw-r--r--drivers/media/usb/dvb-usb-v2/zd1301.c2
-rw-r--r--drivers/media/usb/dvb-usb/cxusb.c4
-rw-r--r--drivers/media/usb/dvb-usb/dib0700_devices.c4
-rw-r--r--drivers/media/usb/dvb-usb/dvb-usb-i2c.c2
-rw-r--r--drivers/media/usb/dvb-usb/dw2102.c4
-rw-r--r--drivers/media/usb/dvb-usb/technisat-usb2.c5
-rw-r--r--drivers/media/usb/em28xx/em28xx-audio.c16
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c33
-rw-r--r--drivers/media/usb/em28xx/em28xx-i2c.c3
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c124
-rw-r--r--drivers/media/usb/em28xx/em28xx.h8
-rw-r--r--drivers/media/usb/go7007/go7007-driver.c2
-rw-r--r--drivers/media/usb/go7007/go7007-v4l2.c16
-rw-r--r--drivers/media/usb/go7007/snd-go7007.c8
-rw-r--r--drivers/media/usb/gspca/gspca.c10
-rw-r--r--drivers/media/usb/gspca/sn9c20x.c2
-rw-r--r--drivers/media/usb/gspca/sq930x.c2
-rw-r--r--drivers/media/usb/hackrf/hackrf.c12
-rw-r--r--drivers/media/usb/hdpvr/hdpvr-video.c9
-rw-r--r--drivers/media/usb/msi2500/msi2500.c8
-rw-r--r--drivers/media/usb/pulse8-cec/pulse8-cec.c3
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-debug.h2
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-hdw.c8
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c34
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-main.c4
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-v4l2.c14
-rw-r--r--drivers/media/usb/pwc/pwc-if.c2
-rw-r--r--drivers/media/usb/pwc/pwc-v4l.c12
-rw-r--r--drivers/media/usb/rainshadow-cec/rainshadow-cec.c3
-rw-r--r--drivers/media/usb/s2255/s2255drv.c10
-rw-r--r--drivers/media/usb/stk1160/stk1160-i2c.c2
-rw-r--r--drivers/media/usb/stk1160/stk1160-v4l.c6
-rw-r--r--drivers/media/usb/stkwebcam/stk-webcam.c16
-rw-r--r--drivers/media/usb/tm6000/tm6000-alsa.c6
-rw-r--r--drivers/media/usb/tm6000/tm6000-i2c.c4
-rw-r--r--drivers/media/usb/tm6000/tm6000-video.c13
-rw-r--r--drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c2
-rw-r--r--drivers/media/usb/usbtv/usbtv-audio.c6
-rw-r--r--drivers/media/usb/usbtv/usbtv-video.c14
-rw-r--r--drivers/media/usb/usbvision/usbvision-core.c3
-rw-r--r--drivers/media/usb/usbvision/usbvision-video.c26
-rw-r--r--drivers/media/usb/usbvision/usbvision.h1
-rw-r--r--drivers/media/usb/uvc/uvc_ctrl.c18
-rw-r--r--drivers/media/usb/uvc/uvc_debugfs.c6
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c75
-rw-r--r--drivers/media/usb/uvc/uvc_entity.c2
-rw-r--r--drivers/media/usb/uvc/uvc_metadata.c11
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c10
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h10
-rw-r--r--drivers/media/usb/zr364xx/zr364xx.c10
-rw-r--r--drivers/media/v4l2-core/tuner-core.c54
-rw-r--r--drivers/media/v4l2-core/v4l2-async.c313
-rw-r--r--drivers/media/v4l2-core/v4l2-common.c25
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls.c22
-rw-r--r--drivers/media/v4l2-core/v4l2-device.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-dv-timings.c202
-rw-r--r--drivers/media/v4l2-core/v4l2-flash-led-class.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-fwnode.c845
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c8
-rw-r--r--drivers/media/v4l2-core/v4l2-mc.c147
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c2
-rw-r--r--drivers/staging/media/bcm2048/radio-bcm2048.c4
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipe.c2
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipeif.c2
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_isif.c2
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_resizer.c6
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c3
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.c6
-rw-r--r--drivers/staging/media/imx/TODO29
-rw-r--r--drivers/staging/media/imx/imx-media-capture.c4
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c70
-rw-r--r--drivers/staging/media/imx/imx-media-dev.c163
-rw-r--r--drivers/staging/media/imx/imx-media-internal-sd.c5
-rw-r--r--drivers/staging/media/imx/imx-media-of.c106
-rw-r--r--drivers/staging/media/imx/imx-media-utils.c4
-rw-r--r--drivers/staging/media/imx/imx-media.h6
-rw-r--r--drivers/staging/media/imx/imx6-mipi-csi2.c33
-rw-r--r--drivers/staging/media/imx074/imx074.c3
-rw-r--r--drivers/staging/media/mt9t031/mt9t031.c1
-rw-r--r--drivers/staging/media/omap4iss/Kconfig2
-rw-r--r--drivers/staging/media/omap4iss/Makefile3
-rw-r--r--drivers/staging/media/omap4iss/iss.c8
-rw-r--r--drivers/staging/media/omap4iss/iss.h6
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.c6
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.h6
-rw-r--r--drivers/staging/media/omap4iss/iss_csiphy.c6
-rw-r--r--drivers/staging/media/omap4iss/iss_csiphy.h6
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipe.c8
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipe.h6
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipeif.c8
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipeif.h6
-rw-r--r--drivers/staging/media/omap4iss/iss_regs.h6
-rw-r--r--drivers/staging/media/omap4iss/iss_resizer.c8
-rw-r--r--drivers/staging/media/omap4iss/iss_resizer.h6
-rw-r--r--drivers/staging/media/omap4iss/iss_video.c16
-rw-r--r--drivers/staging/media/omap4iss/iss_video.h6
-rw-r--r--drivers/staging/media/zoran/zoran_card.c6
-rw-r--r--drivers/staging/media/zoran/zoran_driver.c6
-rw-r--r--drivers/video/backlight/as3711_bl.c7
-rw-r--r--drivers/video/fbdev/sh7760fb.c7
-rw-r--r--drivers/video/hdmi.c8
-rw-r--r--fs/compat_ioctl.c131
-rw-r--r--include/linux/hdmi.h4
-rw-r--r--include/media/cec.h154
-rw-r--r--include/media/media-entity.h48
-rw-r--r--include/media/rc-core.h11
-rw-r--r--include/media/rcar-fcp.h6
-rw-r--r--include/media/v4l2-async.h111
-rw-r--r--include/media/v4l2-common.h14
-rw-r--r--include/media/v4l2-ctrls.h26
-rw-r--r--include/media/v4l2-dv-timings.h17
-rw-r--r--include/media/v4l2-fwnode.h141
-rw-r--r--include/media/v4l2-mc.h78
-rw-r--r--include/media/v4l2-mediabus.h40
-rw-r--r--include/media/v4l2-rect.h26
-rw-r--r--include/media/vsp1.h8
-rw-r--r--include/uapi/linux/cec.h3
-rw-r--r--include/uapi/linux/videodev2.h31
578 files changed, 14612 insertions, 4590 deletions
diff --git a/Documentation/devicetree/bindings/media/fsl-pxp.txt b/Documentation/devicetree/bindings/media/fsl-pxp.txt
new file mode 100644
index 000000000000..2477e7f87381
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/fsl-pxp.txt
@@ -0,0 +1,26 @@
+Freescale Pixel Pipeline
+========================
+
+The Pixel Pipeline (PXP) is a memory-to-memory graphics processing engine
+that supports scaling, colorspace conversion, alpha blending, rotation, and
+pixel conversion via lookup table. Different versions are present on various
+i.MX SoCs from i.MX23 to i.MX7.
+
+Required properties:
+- compatible: should be "fsl,<soc>-pxp", where SoC can be one of imx23, imx28,
+ imx6dl, imx6sl, imx6ul, imx6sx, imx6ull, or imx7d.
+- reg: the register base and size for the device registers
+- interrupts: the PXP interrupt, two interrupts for imx6ull and imx7d.
+- clock-names: should be "axi"
+- clocks: the PXP AXI clock
+
+Example:
+
+pxp@21cc000 {
+ compatible = "fsl,imx6ull-pxp";
+ reg = <0x021cc000 0x4000>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "axi";
+ clocks = <&clks IMX6UL_CLK_PXP>;
+};
diff --git a/Documentation/devicetree/bindings/media/i2c/adv748x.txt b/Documentation/devicetree/bindings/media/i2c/adv748x.txt
index 21ffb5ed8183..5dddc95f9cc4 100644
--- a/Documentation/devicetree/bindings/media/i2c/adv748x.txt
+++ b/Documentation/devicetree/bindings/media/i2c/adv748x.txt
@@ -10,7 +10,11 @@ Required Properties:
- "adi,adv7481" for the ADV7481
- "adi,adv7482" for the ADV7482
- - reg: I2C slave address
+ - reg: I2C slave addresses
+ The ADV748x has up to twelve 256-byte maps that can be accessed via the
+ main I2C ports. Each map has it own I2C address and acts as a standard
+ slave device on the I2C bus. The main address is mandatory, others are
+ optional and remain at default values if not specified.
Optional Properties:
@@ -18,6 +22,11 @@ Optional Properties:
"intrq3". All interrupts are optional. The "intrq3" interrupt
is only available on the adv7481
- interrupts: Specify the interrupt lines for the ADV748x
+ - reg-names : Names of maps with programmable addresses.
+ It shall contain all maps needing a non-default address.
+ Possible map names are:
+ "main", "dpll", "cp", "hdmi", "edid", "repeater",
+ "infoframe", "cbus", "cec", "sdp", "txa", "txb"
The device node must contain one 'port' child node per device input and output
port, in accordance with the video interface bindings defined in
@@ -47,7 +56,10 @@ Example:
video-receiver@70 {
compatible = "adi,adv7482";
- reg = <0x70>;
+ reg = <0x70 0x71 0x72 0x73 0x74 0x75
+ 0x60 0x61 0x62 0x63 0x64 0x65>;
+ reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater",
+ "infoframe", "cbus", "cec", "sdp", "txa", "txb";
#address-cells = <1>;
#size-cells = <0>;
@@ -73,7 +85,7 @@ Example:
};
};
- port@10 {
+ port@a {
reg = <10>;
adv7482_txa: endpoint {
@@ -83,7 +95,7 @@ Example:
};
};
- port@11 {
+ port@b {
reg = <11>;
adv7482_txb: endpoint {
diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
index dcf57e7c60eb..b3e688b77a38 100644
--- a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
+++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
@@ -66,7 +66,7 @@ Example:
* other maps will retain their default addresses.
*/
reg = <0x4c>, <0x66>;
- reg-names "main", "edid";
+ reg-names = "main", "edid";
reset-gpios = <&ioexp 0 GPIO_ACTIVE_LOW>;
hpd-gpios = <&ioexp 2 GPIO_ACTIVE_HIGH>;
diff --git a/Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807.txt b/Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt
index c4701f1eaaf6..c4701f1eaaf6 100644
--- a/Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807.txt
+++ b/Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt
diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt
index 2f420050d57f..d329a4e8ac58 100644
--- a/Documentation/devicetree/bindings/media/rcar_vin.txt
+++ b/Documentation/devicetree/bindings/media/rcar_vin.txt
@@ -11,6 +11,7 @@ on Gen3 platforms to a CSI-2 receiver.
- compatible: Must be one or more of the following
- "renesas,vin-r8a7743" for the R8A7743 device
+ - "renesas,vin-r8a7744" for the R8A7744 device
- "renesas,vin-r8a7745" for the R8A7745 device
- "renesas,vin-r8a7778" for the R8A7778 device
- "renesas,vin-r8a7779" for the R8A7779 device
diff --git a/Documentation/devicetree/bindings/media/renesas,ceu.txt b/Documentation/devicetree/bindings/media/renesas,ceu.txt
index 8a7a616e9019..3e2a2652eb19 100644
--- a/Documentation/devicetree/bindings/media/renesas,ceu.txt
+++ b/Documentation/devicetree/bindings/media/renesas,ceu.txt
@@ -17,15 +17,19 @@ Required properties:
The CEU supports a single parallel input and should contain a single 'port'
subnode with a single 'endpoint'. Connection to input devices are modeled
according to the video interfaces OF bindings specified in:
-Documentation/devicetree/bindings/media/video-interfaces.txt
+[1] Documentation/devicetree/bindings/media/video-interfaces.txt
Optional endpoint properties applicable to parallel input bus described in
the above mentioned "video-interfaces.txt" file are supported.
-- hsync-active: Active state of the HSYNC signal, 0/1 for LOW/HIGH respectively.
- If property is not present, default is active high.
-- vsync-active: Active state of the VSYNC signal, 0/1 for LOW/HIGH respectively.
- If property is not present, default is active high.
+- hsync-active: See [1] for description. If property is not present,
+ default is active high.
+- vsync-active: See [1] for description. If property is not present,
+ default is active high.
+- bus-width: See [1] for description. Accepted values are '8' and '16'.
+ If property is not present, default is '8'.
+- field-even-active: See [1] for description. If property is not present,
+ an even field is identified by a logic 0 (active-low signal).
Example:
diff --git a/Documentation/devicetree/bindings/media/video-interfaces.txt b/Documentation/devicetree/bindings/media/video-interfaces.txt
index baf9d9756b3c..f884ada0bffc 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.txt
+++ b/Documentation/devicetree/bindings/media/video-interfaces.txt
@@ -100,10 +100,12 @@ Optional endpoint properties
slave device (data source) by the master device (data sink). In the master
mode the data source device is also the source of the synchronization signals.
- bus-type: data bus type. Possible values are:
- 0 - autodetect based on other properties (MIPI CSI-2 D-PHY, parallel or Bt656)
1 - MIPI CSI-2 C-PHY
2 - MIPI CSI1
3 - CCP2
+ 4 - MIPI CSI-2 D-PHY
+ 5 - Parallel
+ 6 - Bt.656
- bus-width: number of data lines actively used, valid for the parallel busses.
- data-shift: on the parallel data busses, if bus-width is used to specify the
number of data lines, data-shift can be used to specify which data lines are
diff --git a/Documentation/media/kapi/cec-core.rst b/Documentation/media/kapi/cec-core.rst
index 1d989c544370..bca1d9d1d223 100644
--- a/Documentation/media/kapi/cec-core.rst
+++ b/Documentation/media/kapi/cec-core.rst
@@ -268,6 +268,10 @@ to 1, if the hardware does support retry then either set these counters to
0 if the hardware provides no feedback of which errors occurred and how many
times, or fill in the correct values as reported by the hardware.
+Be aware that calling these functions can immediately start a new transmit
+if there is one pending in the queue. So make sure that the hardware is in
+a state where new transmits can be started *before* calling these functions.
+
The cec_transmit_attempt_done() function is a helper for cases where the
hardware never retries, so the transmit is always for just a single
attempt. It will call cec_transmit_done() in turn, filling in 1 for the
diff --git a/Documentation/media/kapi/v4l2-subdev.rst b/Documentation/media/kapi/v4l2-subdev.rst
index e1f0b726e438..1280e05b662b 100644
--- a/Documentation/media/kapi/v4l2-subdev.rst
+++ b/Documentation/media/kapi/v4l2-subdev.rst
@@ -247,20 +247,28 @@ performed using the :c:func:`v4l2_async_unregister_subdev` call. Subdevices
registered this way are stored in a global list of subdevices, ready to be
picked up by bridge drivers.
-Bridge drivers in turn have to register a notifier object with an array of
-subdevice descriptors that the bridge device needs for its operation. This is
+Bridge drivers in turn have to register a notifier object. This is
performed using the :c:func:`v4l2_async_notifier_register` call. To
unregister the notifier the driver has to call
:c:func:`v4l2_async_notifier_unregister`. The former of the two functions
-takes two arguments: a pointer to struct :c:type:`v4l2_device` and a pointer to
-struct :c:type:`v4l2_async_notifier`. The latter contains a pointer to an array
-of pointers to subdevice descriptors of type struct :c:type:`v4l2_async_subdev`
-type. The V4L2 core will then use these descriptors to match asynchronously
-registered
-subdevices to them. If a match is detected the ``.bound()`` notifier callback
-is called. After all subdevices have been located the .complete() callback is
-called. When a subdevice is removed from the system the .unbind() method is
-called. All three callbacks are optional.
+takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
+pointer to struct :c:type:`v4l2_async_notifier`.
+
+Before registering the notifier, bridge drivers must do two things:
+first, the notifier must be initialized using the
+:c:func:`v4l2_async_notifier_init`. Second, bridge drivers can then
+begin to form a list of subdevice descriptors that the bridge device
+needs for its operation. Subdevice descriptors are added to the notifier
+using the :c:func:`v4l2_async_notifier_add_subdev` call. This function
+takes two arguments: a pointer to struct :c:type:`v4l2_async_notifier`,
+and a pointer to the subdevice descripter, which is of type struct
+:c:type:`v4l2_async_subdev`.
+
+The V4L2 core will then use these descriptors to match asynchronously
+registered subdevices to them. If a match is detected the ``.bound()``
+notifier callback is called. After all subdevices have been located the
+.complete() callback is called. When a subdevice is removed from the
+system the .unbind() method is called. All three callbacks are optional.
V4L2 sub-device userspace API
-----------------------------
diff --git a/Documentation/media/uapi/cec/cec-func-poll.rst b/Documentation/media/uapi/cec/cec-func-poll.rst
index d49f1ee0742d..c698c969635c 100644
--- a/Documentation/media/uapi/cec/cec-func-poll.rst
+++ b/Documentation/media/uapi/cec/cec-func-poll.rst
@@ -74,4 +74,5 @@ is returned, and the ``errno`` variable is set appropriately:
The call was interrupted by a signal.
``EINVAL``
- The ``nfds`` argument is greater than ``OPEN_MAX``.
+ The ``nfds`` value exceeds the ``RLIMIT_NOFILE`` value. Use
+ ``getrlimit()`` to obtain this value.
diff --git a/Documentation/media/uapi/cec/cec-ioc-receive.rst b/Documentation/media/uapi/cec/cec-ioc-receive.rst
index e964074cd15b..b25e48afaa08 100644
--- a/Documentation/media/uapi/cec/cec-ioc-receive.rst
+++ b/Documentation/media/uapi/cec/cec-ioc-receive.rst
@@ -16,10 +16,10 @@ CEC_RECEIVE, CEC_TRANSMIT - Receive or transmit a CEC message
Synopsis
========
-.. c:function:: int ioctl( int fd, CEC_RECEIVE, struct cec_msg *argp )
+.. c:function:: int ioctl( int fd, CEC_RECEIVE, struct cec_msg \*argp )
:name: CEC_RECEIVE
-.. c:function:: int ioctl( int fd, CEC_TRANSMIT, struct cec_msg *argp )
+.. c:function:: int ioctl( int fd, CEC_TRANSMIT, struct cec_msg \*argp )
:name: CEC_TRANSMIT
Arguments
@@ -272,6 +272,19 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
- The transmit failed after one or more retries. This status bit is
mutually exclusive with :ref:`CEC_TX_STATUS_OK <CEC-TX-STATUS-OK>`.
Other bits can still be set to explain which failures were seen.
+ * .. _`CEC-TX-STATUS-ABORTED`:
+
+ - ``CEC_TX_STATUS_ABORTED``
+ - 0x40
+ - The transmit was aborted due to an HDMI disconnect, or the adapter
+ was unconfigured, or a transmit was interrupted, or the driver
+ returned an error when attempting to start a transmit.
+ * .. _`CEC-TX-STATUS-TIMEOUT`:
+
+ - ``CEC_TX_STATUS_TIMEOUT``
+ - 0x80
+ - The transmit timed out. This should not normally happen and this
+ indicates a driver problem.
.. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{11.0cm}|
@@ -300,6 +313,14 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
- The message was received successfully but the reply was
``CEC_MSG_FEATURE_ABORT``. This status is only set if this message
was the reply to an earlier transmitted message.
+ * .. _`CEC-RX-STATUS-ABORTED`:
+
+ - ``CEC_RX_STATUS_ABORTED``
+ - 0x08
+ - The wait for a reply to an earlier transmitted message was aborted
+ because the HDMI cable was disconnected, the adapter was unconfigured
+ or the :ref:`CEC_TRANSMIT <CEC_RECEIVE>` that waited for a
+ reply was interrupted.
diff --git a/Documentation/media/uapi/mediactl/media-ioc-device-info.rst b/Documentation/media/uapi/mediactl/media-ioc-device-info.rst
index 649cb3d9e058..c6f224e404b7 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-device-info.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-device-info.rst
@@ -26,6 +26,7 @@ Arguments
File descriptor returned by :ref:`open() <media-func-open>`.
``argp``
+ Pointer to struct :c:type:`media_device_info`.
Description
diff --git a/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst b/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst
index fc2e39c070c9..02738640e34e 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst
@@ -26,6 +26,7 @@ Arguments
File descriptor returned by :ref:`open() <media-func-open>`.
``argp``
+ Pointer to struct :c:type:`media_entity_desc`.
Description
diff --git a/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst b/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst
index f158c134e9b0..b89aaae373df 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst
@@ -26,6 +26,7 @@ Arguments
File descriptor returned by :ref:`open() <media-func-open>`.
``argp``
+ Pointer to struct :c:type:`media_links_enum`.
Description
diff --git a/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst b/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst
index bac128c7eda9..4e1c59238371 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst
@@ -26,6 +26,7 @@ Arguments
File descriptor returned by :ref:`open() <media-func-open>`.
``argp``
+ Pointer to struct :c:type:`media_v2_topology`.
Description
diff --git a/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst b/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst
index ae5194940100..e345e7dc9ad7 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst
@@ -26,6 +26,7 @@ Arguments
File descriptor returned by :ref:`open() <media-func-open>`.
``argp``
+ Pointer to struct :c:type:`media_link_desc`.
Description
diff --git a/Documentation/media/uapi/v4l/biblio.rst b/Documentation/media/uapi/v4l/biblio.rst
index 1cedcfc04327..386d6cf83e9c 100644
--- a/Documentation/media/uapi/v4l/biblio.rst
+++ b/Documentation/media/uapi/v4l/biblio.rst
@@ -226,16 +226,6 @@ xvYCC
:author: International Electrotechnical Commission (http://www.iec.ch)
-.. _adobergb:
-
-AdobeRGB
-========
-
-
-:title: Adobe© RGB (1998) Color Image Encoding Version 2005-05
-
-:author: Adobe Systems Incorporated (http://www.adobe.com)
-
.. _oprgb:
opRGB
diff --git a/Documentation/media/uapi/v4l/colorspaces-defs.rst b/Documentation/media/uapi/v4l/colorspaces-defs.rst
index 410907fe9415..f24615544792 100644
--- a/Documentation/media/uapi/v4l/colorspaces-defs.rst
+++ b/Documentation/media/uapi/v4l/colorspaces-defs.rst
@@ -51,8 +51,8 @@ whole range, 0-255, dividing the angular value by 1.41. The enum
- See :ref:`col-rec709`.
* - ``V4L2_COLORSPACE_SRGB``
- See :ref:`col-srgb`.
- * - ``V4L2_COLORSPACE_ADOBERGB``
- - See :ref:`col-adobergb`.
+ * - ``V4L2_COLORSPACE_OPRGB``
+ - See :ref:`col-oprgb`.
* - ``V4L2_COLORSPACE_BT2020``
- See :ref:`col-bt2020`.
* - ``V4L2_COLORSPACE_DCI_P3``
@@ -90,8 +90,8 @@ whole range, 0-255, dividing the angular value by 1.41. The enum
- Use the Rec. 709 transfer function.
* - ``V4L2_XFER_FUNC_SRGB``
- Use the sRGB transfer function.
- * - ``V4L2_XFER_FUNC_ADOBERGB``
- - Use the AdobeRGB transfer function.
+ * - ``V4L2_XFER_FUNC_OPRGB``
+ - Use the opRGB transfer function.
* - ``V4L2_XFER_FUNC_SMPTE240M``
- Use the SMPTE 240M transfer function.
* - ``V4L2_XFER_FUNC_NONE``
diff --git a/Documentation/media/uapi/v4l/colorspaces-details.rst b/Documentation/media/uapi/v4l/colorspaces-details.rst
index b5d551b9cc8f..09fabf4cd412 100644
--- a/Documentation/media/uapi/v4l/colorspaces-details.rst
+++ b/Documentation/media/uapi/v4l/colorspaces-details.rst
@@ -290,15 +290,14 @@ Y' is clamped to the range [0…1] and Cb and Cr are clamped to the range
170M/BT.601. The Y'CbCr quantization is limited range.
-.. _col-adobergb:
+.. _col-oprgb:
-Colorspace Adobe RGB (V4L2_COLORSPACE_ADOBERGB)
+Colorspace opRGB (V4L2_COLORSPACE_OPRGB)
===============================================
-The :ref:`adobergb` standard defines the colorspace used by computer
-graphics that use the AdobeRGB colorspace. This is also known as the
-:ref:`oprgb` standard. The default transfer function is
-``V4L2_XFER_FUNC_ADOBERGB``. The default Y'CbCr encoding is
+The :ref:`oprgb` standard defines the colorspace used by computer
+graphics that use the opRGB colorspace. The default transfer function is
+``V4L2_XFER_FUNC_OPRGB``. The default Y'CbCr encoding is
``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is limited
range.
@@ -312,7 +311,7 @@ The chromaticities of the primary colors and the white reference are:
.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
-.. flat-table:: Adobe RGB Chromaticities
+.. flat-table:: opRGB Chromaticities
:header-rows: 1
:stub-columns: 0
:widths: 1 1 2
diff --git a/Documentation/media/uapi/v4l/func-poll.rst b/Documentation/media/uapi/v4l/func-poll.rst
index 360bc6523ae2..967fe8920729 100644
--- a/Documentation/media/uapi/v4l/func-poll.rst
+++ b/Documentation/media/uapi/v4l/func-poll.rst
@@ -113,4 +113,5 @@ EINTR
The call was interrupted by a signal.
EINVAL
- The ``nfds`` argument is greater than ``OPEN_MAX``.
+ The ``nfds`` value exceeds the ``RLIMIT_NOFILE`` value. Use
+ ``getrlimit()`` to obtain this value.
diff --git a/Documentation/media/uapi/v4l/meta-formats.rst b/Documentation/media/uapi/v4l/meta-formats.rst
index 0c4e1ecf5879..cf971d5ad9ea 100644
--- a/Documentation/media/uapi/v4l/meta-formats.rst
+++ b/Documentation/media/uapi/v4l/meta-formats.rst
@@ -12,6 +12,7 @@ These formats are used for the :ref:`metadata` interface only.
.. toctree::
:maxdepth: 1
+ pixfmt-meta-d4xx
pixfmt-meta-uvc
pixfmt-meta-vsp1-hgo
pixfmt-meta-vsp1-hgt
diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst
index d382e7a5c38e..d04b18adac33 100644
--- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst
+++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst
@@ -101,4 +101,4 @@ Compressed Formats
- 'FWHT'
- Video elementary stream using a codec based on the Fast Walsh Hadamard
Transform. This codec is implemented by the vicodec ('Virtual Codec')
- driver. See the vicodec-codec.h header for more details.
+ driver. See the codec-fwht.h header for more details.
diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst b/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst
new file mode 100644
index 000000000000..63bf1a2c9116
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst
@@ -0,0 +1,210 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-meta-fmt-d4xx:
+
+*******************************
+V4L2_META_FMT_D4XX ('D4XX')
+*******************************
+
+Intel D4xx UVC Cameras Metadata
+
+
+Description
+===========
+
+Intel D4xx (D435 and other) cameras include per-frame metadata in their UVC
+payload headers, following the Microsoft(R) UVC extension proposal [1_]. That
+means, that the private D4XX metadata, following the standard UVC header, is
+organised in blocks. D4XX cameras implement several standard block types,
+proposed by Microsoft, and several proprietary ones. Supported standard metadata
+types are MetadataId_CaptureStats (ID 3), MetadataId_CameraExtrinsics (ID 4),
+and MetadataId_CameraIntrinsics (ID 5). For their description see [1_]. This
+document describes proprietary metadata types, used by D4xx cameras.
+
+V4L2_META_FMT_D4XX buffers follow the metadata buffer layout of
+V4L2_META_FMT_UVC with the only difference, that it also includes proprietary
+payload header data. D4xx cameras use bulk transfers and only send one payload
+per frame, therefore their headers cannot be larger than 255 bytes.
+
+Below are proprietary Microsoft style metadata types, used by D4xx cameras,
+where all fields are in little endian order:
+
+.. flat-table:: D4xx metadata
+ :widths: 1 4
+ :header-rows: 1
+ :stub-columns: 0
+
+ * - Field
+ - Description
+ * - :cspan:`1` *Depth Control*
+ * - __u32 ID
+ - 0x80000000
+ * - __u32 Size
+ - Size in bytes (currently 56)
+ * - __u32 Version
+ - Version of this structure. The documentation herein corresponds to
+ version xxx. The version number will be incremented when new fields are
+ added.
+ * - __u32 Flags
+ - A bitmask of flags: see [2_] below
+ * - __u32 Gain
+ - Gain value in internal units, same as the V4L2_CID_GAIN control, used to
+ capture the frame
+ * - __u32 Exposure
+ - Exposure time (in microseconds) used to capture the frame
+ * - __u32 Laser power
+ - Power of the laser LED 0-360, used for depth measurement
+ * - __u32 AE mode
+ - 0: manual; 1: automatic exposure
+ * - __u32 Exposure priority
+ - Exposure priority value: 0 - constant frame rate
+ * - __u32 AE ROI left
+ - Left border of the AE Region of Interest (all ROI values are in pixels
+ and lie between 0 and maximum width or height respectively)
+ * - __u32 AE ROI right
+ - Right border of the AE Region of Interest
+ * - __u32 AE ROI top
+ - Top border of the AE Region of Interest
+ * - __u32 AE ROI bottom
+ - Bottom border of the AE Region of Interest
+ * - __u32 Preset
+ - Preset selector value, default: 0, unless changed by the user
+ * - __u32 Laser mode
+ - 0: off, 1: on
+ * - :cspan:`1` *Capture Timing*
+ * - __u32 ID
+ - 0x80000001
+ * - __u32 Size
+ - Size in bytes (currently 40)
+ * - __u32 Version
+ - Version of this structure. The documentation herein corresponds to
+ version xxx. The version number will be incremented when new fields are
+ added.
+ * - __u32 Flags
+ - A bitmask of flags: see [3_] below
+ * - __u32 Frame counter
+ - Monotonically increasing counter
+ * - __u32 Optical time
+ - Time in microseconds from the beginning of a frame till its middle
+ * - __u32 Readout time
+ - Time, used to read out a frame in microseconds
+ * - __u32 Exposure time
+ - Frame exposure time in microseconds
+ * - __u32 Frame interval
+ - In microseconds = 1000000 / framerate
+ * - __u32 Pipe latency
+ - Time in microseconds from start of frame to data in USB buffer
+ * - :cspan:`1` *Configuration*
+ * - __u32 ID
+ - 0x80000002
+ * - __u32 Size
+ - Size in bytes (currently 40)
+ * - __u32 Version
+ - Version of this structure. The documentation herein corresponds to
+ version xxx. The version number will be incremented when new fields are
+ added.
+ * - __u32 Flags
+ - A bitmask of flags: see [4_] below
+ * - __u8 Hardware type
+ - Camera hardware version [5_]
+ * - __u8 SKU ID
+ - Camera hardware configuration [6_]
+ * - __u32 Cookie
+ - Internal synchronisation
+ * - __u16 Format
+ - Image format code [7_]
+ * - __u16 Width
+ - Width in pixels
+ * - __u16 Height
+ - Height in pixels
+ * - __u16 Framerate
+ - Requested frame rate per second
+ * - __u16 Trigger
+ - Byte 0: bit 0: depth and RGB are synchronised, bit 1: external trigger
+
+.. _1:
+
+[1] https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5
+
+.. _2:
+
+[2] Depth Control flags specify which fields are valid: ::
+
+ 0x00000001 Gain
+ 0x00000002 Exposure
+ 0x00000004 Laser power
+ 0x00000008 AE mode
+ 0x00000010 Exposure priority
+ 0x00000020 AE ROI
+ 0x00000040 Preset
+
+.. _3:
+
+[3] Capture Timing flags specify which fields are valid: ::
+
+ 0x00000001 Frame counter
+ 0x00000002 Optical time
+ 0x00000004 Readout time
+ 0x00000008 Exposure time
+ 0x00000010 Frame interval
+ 0x00000020 Pipe latency
+
+.. _4:
+
+[4] Configuration flags specify which fields are valid: ::
+
+ 0x00000001 Hardware type
+ 0x00000002 SKU ID
+ 0x00000004 Cookie
+ 0x00000008 Format
+ 0x00000010 Width
+ 0x00000020 Height
+ 0x00000040 Framerate
+ 0x00000080 Trigger
+ 0x00000100 Cal count
+
+.. _5:
+
+[5] Camera model: ::
+
+ 0 DS5
+ 1 IVCAM2
+
+.. _6:
+
+[6] 8-bit camera hardware configuration bitfield: ::
+
+ [1:0] depthCamera
+ 00: no depth
+ 01: standard depth
+ 10: wide depth
+ 11: reserved
+ [2] depthIsActive - has a laser projector
+ [3] RGB presence
+ [4] Inertial Measurement Unit (IMU) presence
+ [5] projectorType
+ 0: HPTG
+ 1: Princeton
+ [6] 0: a projector, 1: an LED
+ [7] reserved
+
+.. _7:
+
+[7] Image format codes per video streaming interface:
+
+Depth: ::
+
+ 1 Z16
+ 2 Z
+
+Left sensor: ::
+
+ 1 Y8
+ 2 UYVY
+ 3 R8L8
+ 4 Calibration
+ 5 W10
+
+Fish Eye sensor: ::
+
+ 1 RAW8
diff --git a/Documentation/media/uapi/v4l/vidioc-cropcap.rst b/Documentation/media/uapi/v4l/vidioc-cropcap.rst
index a65dbec6b20b..0a7b8287fd38 100644
--- a/Documentation/media/uapi/v4l/vidioc-cropcap.rst
+++ b/Documentation/media/uapi/v4l/vidioc-cropcap.rst
@@ -58,7 +58,7 @@ overlay devices.
- Type of the data stream, set by the application. Only these types
are valid here: ``V4L2_BUF_TYPE_VIDEO_CAPTURE``, ``V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE``,
``V4L2_BUF_TYPE_VIDEO_OUTPUT``, ``V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE`` and
- ``V4L2_BUF_TYPE_VIDEO_OVERLAY``. See :c:type:`v4l2_buf_type` and the note above.
+ ``V4L2_BUF_TYPE_VIDEO_OVERLAY``. See :c:type:`v4l2_buf_type` and the note below.
* - struct :ref:`v4l2_rect <v4l2-rect-crop>`
- ``bounds``
- Defines the window within capturing or output is possible, this
diff --git a/Documentation/media/uapi/v4l/vidioc-dqevent.rst b/Documentation/media/uapi/v4l/vidioc-dqevent.rst
index cb3565f36793..04416b6943c0 100644
--- a/Documentation/media/uapi/v4l/vidioc-dqevent.rst
+++ b/Documentation/media/uapi/v4l/vidioc-dqevent.rst
@@ -379,7 +379,17 @@ call.
- 0x0001
- This event gets triggered when a resolution change is detected at
an input. This can come from an input connector or from a video
- decoder.
+ decoder. Applications will have to query the new resolution (if
+ any, the signal may also have been lost).
+
+ *Important*: even if the new video timings appear identical to the old
+ ones, receiving this event indicates that there was an issue with the
+ video signal and you must stop and restart streaming
+ (:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>`
+ followed by :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`). The reason is
+ that many devices are not able to recover from a temporary loss of
+ signal and so restarting streaming I/O is required in order for the
+ hardware to synchronize to the video signal.
Return Value
diff --git a/Documentation/media/uapi/v4l/vidioc-g-crop.rst b/Documentation/media/uapi/v4l/vidioc-g-crop.rst
index a6ed43ba9ca3..b95ba6743cbd 100644
--- a/Documentation/media/uapi/v4l/vidioc-g-crop.rst
+++ b/Documentation/media/uapi/v4l/vidioc-g-crop.rst
@@ -84,7 +84,7 @@ When cropping is not supported then no parameters are changed and
- Type of the data stream, set by the application. Only these types
are valid here: ``V4L2_BUF_TYPE_VIDEO_CAPTURE``, ``V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE``,
``V4L2_BUF_TYPE_VIDEO_OUTPUT``, ``V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE`` and
- ``V4L2_BUF_TYPE_VIDEO_OVERLAY``. See :c:type:`v4l2_buf_type` and the note above.
+ ``V4L2_BUF_TYPE_VIDEO_OVERLAY``. See :c:type:`v4l2_buf_type` and the note below.
* - struct :c:type:`v4l2_rect`
- ``c``
- Cropping rectangle. The same co-ordinate system as for struct
diff --git a/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst b/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst
index 1a034e825161..35cba2c8d459 100644
--- a/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst
+++ b/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst
@@ -257,14 +257,19 @@ EBUSY
will also be cleared. This is a read-only flag, applications must
not set this.
* - ``V4L2_DV_FL_REDUCED_FPS``
- - CEA-861 specific: only valid for video transmitters, the flag is
- cleared by receivers. It is also only valid for formats with the
- ``V4L2_DV_FL_CAN_REDUCE_FPS`` flag set, for other formats the
- flag will be cleared by the driver. If the application sets this
- flag, then the pixelclock used to set up the transmitter is
- divided by 1.001 to make it compatible with NTSC framerates. If
- the transmitter can't generate such frequencies, then the flag
- will also be cleared.
+ - CEA-861 specific: only valid for video transmitters or video
+ receivers that have the ``V4L2_DV_FL_CAN_DETECT_REDUCED_FPS``
+ set. This flag is cleared otherwise. It is also only valid for
+ formats with the ``V4L2_DV_FL_CAN_REDUCE_FPS`` flag set, for other
+ formats the flag will be cleared by the driver.
+
+ If the application sets this flag for a transmitter, then the
+ pixelclock used to set up the transmitter is divided by 1.001 to
+ make it compatible with NTSC framerates. If the transmitter can't
+ generate such frequencies, then the flag will be cleared.
+
+ If a video receiver detects that the format uses a reduced framerate,
+ then it will set this flag to signal this to the application.
* - ``V4L2_DV_FL_HALF_LINE``
- Specific to interlaced formats: if set, then the vertical
backporch of field 1 (aka the odd field) is really one half-line
@@ -294,3 +299,9 @@ EBUSY
- If set, then the hdmi_vic field is valid and contains the Video
Identification Code as per the HDMI standard (HDMI Vendor Specific
InfoFrame).
+ * - ``V4L2_DV_FL_CAN_DETECT_REDUCED_FPS``
+ - CEA-861 specific: only valid for video receivers, the flag is
+ cleared by transmitters.
+ If set, then the hardware can detect the difference between
+ regular framerates and framerates reduced by 1000/1001. E.g.:
+ 60 vs 59.94 Hz, 30 vs 29.97 Hz or 24 vs 23.976 Hz.
diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions
index ca9f0edc579e..1f4340dd9a37 100644
--- a/Documentation/media/videodev2.h.rst.exceptions
+++ b/Documentation/media/videodev2.h.rst.exceptions
@@ -56,7 +56,8 @@ replace symbol V4L2_MEMORY_USERPTR :c:type:`v4l2_memory`
# Documented enum v4l2_colorspace
replace symbol V4L2_COLORSPACE_470_SYSTEM_BG :c:type:`v4l2_colorspace`
replace symbol V4L2_COLORSPACE_470_SYSTEM_M :c:type:`v4l2_colorspace`
-replace symbol V4L2_COLORSPACE_ADOBERGB :c:type:`v4l2_colorspace`
+replace symbol V4L2_COLORSPACE_OPRGB :c:type:`v4l2_colorspace`
+replace define V4L2_COLORSPACE_ADOBERGB :c:type:`v4l2_colorspace`
replace symbol V4L2_COLORSPACE_BT2020 :c:type:`v4l2_colorspace`
replace symbol V4L2_COLORSPACE_DCI_P3 :c:type:`v4l2_colorspace`
replace symbol V4L2_COLORSPACE_DEFAULT :c:type:`v4l2_colorspace`
@@ -69,7 +70,8 @@ replace symbol V4L2_COLORSPACE_SRGB :c:type:`v4l2_colorspace`
# Documented enum v4l2_xfer_func
replace symbol V4L2_XFER_FUNC_709 :c:type:`v4l2_xfer_func`
-replace symbol V4L2_XFER_FUNC_ADOBERGB :c:type:`v4l2_xfer_func`
+replace symbol V4L2_XFER_FUNC_OPRGB :c:type:`v4l2_xfer_func`
+replace define V4L2_XFER_FUNC_ADOBERGB :c:type:`v4l2_xfer_func`
replace symbol V4L2_XFER_FUNC_DCI_P3 :c:type:`v4l2_xfer_func`
replace symbol V4L2_XFER_FUNC_DEFAULT :c:type:`v4l2_xfer_func`
replace symbol V4L2_XFER_FUNC_NONE :c:type:`v4l2_xfer_func`
@@ -278,6 +280,7 @@ replace define V4L2_DV_BT_STD_SDI dv-bt-standards
replace define V4L2_DV_FL_REDUCED_BLANKING dv-bt-standards
replace define V4L2_DV_FL_CAN_REDUCE_FPS dv-bt-standards
+replace define V4L2_DV_FL_CAN_DETECT_REDUCED_FPS dv-bt-standards
replace define V4L2_DV_FL_REDUCED_FPS dv-bt-standards
replace define V4L2_DV_FL_HALF_LINE dv-bt-standards
replace define V4L2_DV_FL_IS_CE_VIDEO dv-bt-standards
diff --git a/MAINTAINERS b/MAINTAINERS
index c6c9cc1019ad..ea1648fdcfb4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4546,13 +4546,15 @@ L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/i2c/dw9714.c
+F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9714.txt
DONGWOON DW9807 LENS VOICE COIL DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
-F: drivers/media/i2c/dw9807.c
+F: drivers/media/i2c/dw9807-vcm.c
+F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt
DOUBLETALK DRIVER
M: "James R. Van Zandt" <jrv@vanzandt.mv.com>
@@ -9086,11 +9088,10 @@ F: drivers/media/dvb-frontends/cxd2880/*
F: drivers/media/spi/cxd2880*
MEDIA DRIVERS FOR DIGITAL DEVICES PCIE DEVICES
-M: Daniel Scheller <d.scheller.oss@gmail.com>
L: linux-media@vger.kernel.org
W: https://linuxtv.org
T: git git://linuxtv.org/media_tree.git
-S: Maintained
+S: Orphan
F: drivers/media/pci/ddbridge/*
MEDIA DRIVERS FOR FREESCALE IMX
@@ -9105,6 +9106,13 @@ F: drivers/staging/media/imx/
F: include/linux/imx-media.h
F: include/media/imx.h
+MEDIA DRIVER FOR FREESCALE IMX PXP
+M: Philipp Zabel <p.zabel@pengutronix.de>
+L: linux-media@vger.kernel.org
+T: git git://linuxtv.org/media_tree.git
+S: Maintained
+F: drivers/media/platform/imx-pxp.[ch]
+
MEDIA DRIVERS FOR HELENE
M: Abylay Ospan <aospan@netup.ru>
L: linux-media@vger.kernel.org
@@ -9135,11 +9143,10 @@ S: Supported
F: drivers/media/dvb-frontends/lnbh25*
MEDIA DRIVERS FOR MXL5XX TUNER DEMODULATORS
-M: Daniel Scheller <d.scheller.oss@gmail.com>
L: linux-media@vger.kernel.org
W: https://linuxtv.org
T: git git://linuxtv.org/media_tree.git
-S: Maintained
+S: Orphan
F: drivers/media/dvb-frontends/mxl5xx*
MEDIA DRIVERS FOR NETUP PCI UNIVERSAL DVB devices
@@ -9182,7 +9189,7 @@ F: drivers/media/platform/rcar-fcp.c
F: include/media/rcar-fcp.h
MEDIA DRIVERS FOR RENESAS - FDP1
-M: Kieran Bingham <kieran@bingham.xyz>
+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
@@ -9202,6 +9209,7 @@ F: drivers/media/platform/rcar-vin/
MEDIA DRIVERS FOR RENESAS - VSP1
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
@@ -9210,19 +9218,17 @@ F: Documentation/devicetree/bindings/media/renesas,vsp1.txt
F: drivers/media/platform/vsp1/
MEDIA DRIVERS FOR ST STV0910 DEMODULATOR ICs
-M: Daniel Scheller <d.scheller.oss@gmail.com>
L: linux-media@vger.kernel.org
W: https://linuxtv.org
T: git git://linuxtv.org/media_tree.git
-S: Maintained
+S: Orphan
F: drivers/media/dvb-frontends/stv0910*
MEDIA DRIVERS FOR ST STV6111 TUNER ICs
-M: Daniel Scheller <d.scheller.oss@gmail.com>
L: linux-media@vger.kernel.org
W: https://linuxtv.org
T: git git://linuxtv.org/media_tree.git
-S: Maintained
+S: Orphan
F: drivers/media/dvb-frontends/stv6111*
MEDIA DRIVERS FOR STM32 - DCMI
@@ -13719,6 +13725,20 @@ S: Maintained
F: drivers/media/i2c/imx274.c
F: Documentation/devicetree/bindings/media/i2c/imx274.txt
+SONY IMX319 SENSOR DRIVER
+M: Bingbu Cao <bingbu.cao@intel.com>
+L: linux-media@vger.kernel.org
+T: git git://linuxtv.org/media_tree.git
+S: Maintained
+F: drivers/media/i2c/imx319.c
+
+SONY IMX355 SENSOR DRIVER
+M: Tianshu Qiu <tian.shu.qiu@intel.com>
+L: linux-media@vger.kernel.org
+T: git git://linuxtv.org/media_tree.git
+S: Maintained
+F: drivers/media/i2c/imx355.c
+
SONY MEMORYSTICK CARD SUPPORT
M: Alex Dubov <oakad@yahoo.com>
W: http://tifmxx.berlios.de/
@@ -14038,7 +14058,7 @@ F: sound/soc/sti/
STI CEC DRIVER
M: Benjamin Gaignard <benjamin.gaignard@linaro.org>
S: Maintained
-F: drivers/staging/media/st-cec/
+F: drivers/media/platform/sti/cec/
F: Documentation/devicetree/bindings/media/stih-cec.txt
STK1160 USB VIDEO CAPTURE DRIVER
@@ -15697,7 +15717,7 @@ M: Marek Szyprowski <m.szyprowski@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-media@vger.kernel.org
S: Maintained
-F: drivers/media/v4l2-core/videobuf2-*
+F: drivers/media/common/videobuf2/*
F: include/media/videobuf2-*
VIMC VIRTUAL MEDIA CONTROLLER DRIVER
diff --git a/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi b/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi
index e31a9e3c18a2..8d77579807ec 100644
--- a/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi
+++ b/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi
@@ -69,10 +69,6 @@
port {
ceu_in: endpoint {
- hsync-active = <1>;
- vsync-active = <1>;
- bus-width = <8>;
- pclk-sample = <1>;
remote-endpoint = <&mt9v111_out>;
};
};
diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c
index 954eefe144e2..aa0e30a2ba18 100644
--- a/drivers/gpu/ipu-v3/ipu-csi.c
+++ b/drivers/gpu/ipu-v3/ipu-csi.c
@@ -232,7 +232,7 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
case MEDIA_BUS_FMT_BGR565_2X8_LE:
case MEDIA_BUS_FMT_RGB565_2X8_BE:
case MEDIA_BUS_FMT_RGB565_2X8_LE:
- if (mbus_type == V4L2_MBUS_CSI2)
+ if (mbus_type == V4L2_MBUS_CSI2_DPHY)
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
else
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
@@ -359,7 +359,7 @@ static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
else
csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
break;
- case V4L2_MBUS_CSI2:
+ case V4L2_MBUS_CSI2_DPHY:
/*
* MIPI CSI-2 requires non gated clock mode, all other
* parameters are not applicable for MIPI CSI-2 bus.
@@ -611,7 +611,7 @@ int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
if (vc > 3)
return -EINVAL;
- ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2);
+ ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY);
if (ret < 0)
return ret;
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
index 32747b7f917e..bf6f29ca3315 100644
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -45,7 +45,7 @@ int picolcd_raw_cir(struct picolcd_data *data,
{
unsigned long flags;
int i, w, sz;
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
/* ignore if rc_dev is NULL or status is shunned */
spin_lock_irqsave(&data->lock, flags);
@@ -67,7 +67,6 @@ int picolcd_raw_cir(struct picolcd_data *data,
*/
sz = size > 0 ? min((int)raw_data[0], size-1) : 0;
for (i = 0; i+1 < sz; i += 2) {
- init_ir_raw_event(&rawir);
w = (raw_data[i] << 8) | (raw_data[i+1]);
rawir.pulse = !!(w & 0x8000);
rawir.duration = US_TO_NS(rawir.pulse ? (65536 - w) : w);
diff --git a/drivers/media/cec/Makefile b/drivers/media/cec/Makefile
index 29a2ab9e77c5..ad8677d8c896 100644
--- a/drivers/media/cec/Makefile
+++ b/drivers/media/cec/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-cec-objs := cec-core.o cec-adap.o cec-api.o cec-edid.o
+cec-objs := cec-core.o cec-adap.o cec-api.o
ifeq ($(CONFIG_CEC_NOTIFIER),y)
cec-objs += cec-notifier.o
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
index 030b2602faf0..31d1f4ab915e 100644
--- a/drivers/media/cec/cec-adap.c
+++ b/drivers/media/cec/cec-adap.c
@@ -62,6 +62,19 @@ static unsigned int cec_log_addr2dev(const struct cec_adapter *adap, u8 log_addr
return adap->log_addrs.primary_device_type[i < 0 ? 0 : i];
}
+u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
+ unsigned int *offset)
+{
+ unsigned int loc = cec_get_edid_spa_location(edid, size);
+
+ if (offset)
+ *offset = loc;
+ if (loc == 0)
+ return CEC_PHYS_ADDR_INVALID;
+ return (edid[loc] << 8) | edid[loc + 1];
+}
+EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr);
+
/*
* Queue a new event for this filehandle. If ts == 0, then set it
* to the current time.
@@ -341,7 +354,7 @@ static void cec_data_completed(struct cec_data *data)
*
* This function is called with adap->lock held.
*/
-static void cec_data_cancel(struct cec_data *data)
+static void cec_data_cancel(struct cec_data *data, u8 tx_status)
{
/*
* It's either the current transmit, or it is a pending
@@ -356,13 +369,11 @@ static void cec_data_cancel(struct cec_data *data)
}
if (data->msg.tx_status & CEC_TX_STATUS_OK) {
- /* Mark the canceled RX as a timeout */
data->msg.rx_ts = ktime_get_ns();
- data->msg.rx_status = CEC_RX_STATUS_TIMEOUT;
+ data->msg.rx_status = CEC_RX_STATUS_ABORTED;
} else {
- /* Mark the canceled TX as an error */
data->msg.tx_ts = ktime_get_ns();
- data->msg.tx_status |= CEC_TX_STATUS_ERROR |
+ data->msg.tx_status |= tx_status |
CEC_TX_STATUS_MAX_RETRIES;
data->msg.tx_error_cnt++;
data->attempts = 0;
@@ -390,15 +401,15 @@ static void cec_flush(struct cec_adapter *adap)
while (!list_empty(&adap->transmit_queue)) {
data = list_first_entry(&adap->transmit_queue,
struct cec_data, list);
- cec_data_cancel(data);
+ cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
}
if (adap->transmitting)
- cec_data_cancel(adap->transmitting);
+ cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED);
/* Cancel the pending timeout work. */
list_for_each_entry_safe(data, n, &adap->wait_queue, list) {
if (cancel_delayed_work(&data->work))
- cec_data_cancel(data);
+ cec_data_cancel(data, CEC_TX_STATUS_OK);
/*
* If cancel_delayed_work returned false, then
* the cec_wait_timeout function is running,
@@ -474,12 +485,13 @@ int cec_thread_func(void *_adap)
* so much traffic on the bus that the adapter was
* unable to transmit for CEC_XFER_TIMEOUT_MS (2.1s).
*/
- dprintk(1, "%s: message %*ph timed out\n", __func__,
+ pr_warn("cec-%s: message %*ph timed out\n", adap->name,
adap->transmitting->msg.len,
adap->transmitting->msg.msg);
adap->tx_timeouts++;
/* Just give up on this. */
- cec_data_cancel(adap->transmitting);
+ cec_data_cancel(adap->transmitting,
+ CEC_TX_STATUS_TIMEOUT);
goto unlock;
}
@@ -514,9 +526,11 @@ int cec_thread_func(void *_adap)
if (data->attempts) {
/* should be >= 3 data bit periods for a retry */
signal_free_time = CEC_SIGNAL_FREE_TIME_RETRY;
- } else if (data->new_initiator) {
+ } else if (adap->last_initiator !=
+ cec_msg_initiator(&data->msg)) {
/* should be >= 5 data bit periods for new initiator */
signal_free_time = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR;
+ adap->last_initiator = cec_msg_initiator(&data->msg);
} else {
/*
* should be >= 7 data bit periods for sending another
@@ -530,7 +544,7 @@ int cec_thread_func(void *_adap)
/* Tell the adapter to transmit, cancel on error */
if (adap->ops->adap_transmit(adap, data->attempts,
signal_free_time, &data->msg))
- cec_data_cancel(data);
+ cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
unlock:
mutex_unlock(&adap->lock);
@@ -701,9 +715,6 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
struct cec_fh *fh, bool block)
{
struct cec_data *data;
- u8 last_initiator = 0xff;
- unsigned int timeout;
- int res = 0;
msg->rx_ts = 0;
msg->tx_ts = 0;
@@ -813,23 +824,6 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
data->adap = adap;
data->blocking = block;
- /*
- * Determine if this message follows a message from the same
- * initiator. Needed to determine the free signal time later on.
- */
- if (msg->len > 1) {
- if (!(list_empty(&adap->transmit_queue))) {
- const struct cec_data *last;
-
- last = list_last_entry(&adap->transmit_queue,
- const struct cec_data, list);
- last_initiator = cec_msg_initiator(&last->msg);
- } else if (adap->transmitting) {
- last_initiator =
- cec_msg_initiator(&adap->transmitting->msg);
- }
- }
- data->new_initiator = last_initiator != cec_msg_initiator(msg);
init_completion(&data->c);
INIT_DELAYED_WORK(&data->work, cec_wait_timeout);
@@ -846,47 +840,22 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
return 0;
/*
- * If we don't get a completion before this time something is really
- * wrong and we time out.
- */
- timeout = CEC_XFER_TIMEOUT_MS;
- /* Add the requested timeout if we have to wait for a reply as well */
- if (msg->timeout)
- timeout += msg->timeout;
-
- /*
* Release the lock and wait, retake the lock afterwards.
*/
mutex_unlock(&adap->lock);
- res = wait_for_completion_killable_timeout(&data->c,
- msecs_to_jiffies(timeout));
+ wait_for_completion_killable(&data->c);
+ if (!data->completed)
+ cancel_delayed_work_sync(&data->work);
mutex_lock(&adap->lock);
- if (data->completed) {
- /* The transmit completed (possibly with an error) */
- *msg = data->msg;
- kfree(data);
- return 0;
- }
- /*
- * The wait for completion timed out or was interrupted, so mark this
- * as non-blocking and disconnect from the filehandle since it is
- * still 'in flight'. When it finally completes it will just drop the
- * result silently.
- */
- data->blocking = false;
- if (data->fh)
- list_del(&data->xfer_list);
- data->fh = NULL;
+ /* Cancel the transmit if it was interrupted */
+ if (!data->completed)
+ cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
- if (res == 0) { /* timed out */
- /* Check if the reply or the transmit failed */
- if (msg->timeout && (msg->tx_status & CEC_TX_STATUS_OK))
- msg->rx_status = CEC_RX_STATUS_TIMEOUT;
- else
- msg->tx_status = CEC_TX_STATUS_MAX_RETRIES;
- }
- return res > 0 ? 0 : res;
+ /* The transmit completed (possibly with an error) */
+ *msg = data->msg;
+ kfree(data);
+ return 0;
}
/* Helper function to be used by drivers and this framework. */
@@ -1044,6 +1013,8 @@ void cec_received_msg_ts(struct cec_adapter *adap,
mutex_lock(&adap->lock);
dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg);
+ adap->last_initiator = 0xff;
+
/* Check if this message was for us (directed or broadcast). */
if (!cec_msg_is_broadcast(msg))
valid_la = cec_has_log_addr(adap, msg_dest);
@@ -1506,6 +1477,8 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
}
mutex_lock(&adap->devnode.lock);
+ adap->last_initiator = 0xff;
+
if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) &&
adap->ops->adap_enable(adap, true)) {
mutex_unlock(&adap->devnode.lock);
diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c
index b6536bbad530..391b6fd483e1 100644
--- a/drivers/media/cec/cec-api.c
+++ b/drivers/media/cec/cec-api.c
@@ -77,9 +77,9 @@ static long cec_adap_g_caps(struct cec_adapter *adap,
{
struct cec_caps caps = {};
- strlcpy(caps.driver, adap->devnode.dev.parent->driver->name,
+ strscpy(caps.driver, adap->devnode.dev.parent->driver->name,
sizeof(caps.driver));
- strlcpy(caps.name, adap->name, sizeof(caps.name));
+ strscpy(caps.name, adap->name, sizeof(caps.name));
caps.available_log_addrs = adap->available_log_addrs;
caps.capabilities = adap->capabilities;
caps.version = LINUX_VERSION_CODE;
@@ -101,6 +101,23 @@ static long cec_adap_g_phys_addr(struct cec_adapter *adap,
return 0;
}
+static int cec_validate_phys_addr(u16 phys_addr)
+{
+ int i;
+
+ if (phys_addr == CEC_PHYS_ADDR_INVALID)
+ return 0;
+ for (i = 0; i < 16; i += 4)
+ if (phys_addr & (0xf << i))
+ break;
+ if (i == 16)
+ return 0;
+ for (i += 4; i < 16; i += 4)
+ if ((phys_addr & (0xf << i)) == 0)
+ return -EINVAL;
+ return 0;
+}
+
static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh,
bool block, __u16 __user *parg)
{
@@ -112,7 +129,7 @@ static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh,
if (copy_from_user(&phys_addr, parg, sizeof(phys_addr)))
return -EFAULT;
- err = cec_phys_addr_validate(phys_addr, NULL, NULL);
+ err = cec_validate_phys_addr(phys_addr);
if (err)
return err;
mutex_lock(&adap->lock);
@@ -665,6 +682,7 @@ const struct file_operations cec_devnode_fops = {
.owner = THIS_MODULE,
.open = cec_open,
.unlocked_ioctl = cec_ioctl,
+ .compat_ioctl = cec_ioctl,
.release = cec_release,
.poll = cec_poll,
.llseek = no_llseek,
diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c
index b278ab90b387..e4edc930d4ed 100644
--- a/drivers/media/cec/cec-core.c
+++ b/drivers/media/cec/cec-core.c
@@ -264,7 +264,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
adap = kzalloc(sizeof(*adap), GFP_KERNEL);
if (!adap)
return ERR_PTR(-ENOMEM);
- strlcpy(adap->name, name, sizeof(adap->name));
+ strscpy(adap->name, name, sizeof(adap->name));
adap->phys_addr = CEC_PHYS_ADDR_INVALID;
adap->cec_pin_is_high = true;
adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
@@ -307,12 +307,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
return ERR_PTR(-ENOMEM);
}
- snprintf(adap->device_name, sizeof(adap->device_name),
- "RC for %s", name);
snprintf(adap->input_phys, sizeof(adap->input_phys),
- "%s/input0", name);
+ "%s/input0", adap->name);
- adap->rc->device_name = adap->device_name;
+ adap->rc->device_name = adap->name;
adap->rc->input_phys = adap->input_phys;
adap->rc->input_id.bustype = BUS_CEC;
adap->rc->input_id.vendor = 0;
diff --git a/drivers/media/cec/cec-edid.c b/drivers/media/cec/cec-edid.c
deleted file mode 100644
index ec72ac1c0b91..000000000000
--- a/drivers/media/cec/cec-edid.c
+++ /dev/null
@@ -1,155 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * cec-edid - HDMI Consumer Electronics Control EDID & CEC helper functions
- *
- * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <media/cec.h>
-
-/*
- * This EDID is expected to be a CEA-861 compliant, which means that there are
- * at least two blocks and one or more of the extensions blocks are CEA-861
- * blocks.
- *
- * The returned location is guaranteed to be < size - 1.
- */
-static unsigned int cec_get_edid_spa_location(const u8 *edid, unsigned int size)
-{
- unsigned int blocks = size / 128;
- unsigned int block;
- u8 d;
-
- /* Sanity check: at least 2 blocks and a multiple of the block size */
- if (blocks < 2 || size % 128)
- return 0;
-
- /*
- * If there are fewer extension blocks than the size, then update
- * 'blocks'. It is allowed to have more extension blocks than the size,
- * since some hardware can only read e.g. 256 bytes of the EDID, even
- * though more blocks are present. The first CEA-861 extension block
- * should normally be in block 1 anyway.
- */
- if (edid[0x7e] + 1 < blocks)
- blocks = edid[0x7e] + 1;
-
- for (block = 1; block < blocks; block++) {
- unsigned int offset = block * 128;
-
- /* Skip any non-CEA-861 extension blocks */
- if (edid[offset] != 0x02 || edid[offset + 1] != 0x03)
- continue;
-
- /* search Vendor Specific Data Block (tag 3) */
- d = edid[offset + 2] & 0x7f;
- /* Check if there are Data Blocks */
- if (d <= 4)
- continue;
- if (d > 4) {
- unsigned int i = offset + 4;
- unsigned int end = offset + d;
-
- /* Note: 'end' is always < 'size' */
- do {
- u8 tag = edid[i] >> 5;
- u8 len = edid[i] & 0x1f;
-
- if (tag == 3 && len >= 5 && i + len <= end &&
- edid[i + 1] == 0x03 &&
- edid[i + 2] == 0x0c &&
- edid[i + 3] == 0x00)
- return i + 4;
- i += len + 1;
- } while (i < end);
- }
- }
- return 0;
-}
-
-u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
- unsigned int *offset)
-{
- unsigned int loc = cec_get_edid_spa_location(edid, size);
-
- if (offset)
- *offset = loc;
- if (loc == 0)
- return CEC_PHYS_ADDR_INVALID;
- return (edid[loc] << 8) | edid[loc + 1];
-}
-EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr);
-
-void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr)
-{
- unsigned int loc = cec_get_edid_spa_location(edid, size);
- u8 sum = 0;
- unsigned int i;
-
- if (loc == 0)
- return;
- edid[loc] = phys_addr >> 8;
- edid[loc + 1] = phys_addr & 0xff;
- loc &= ~0x7f;
-
- /* update the checksum */
- for (i = loc; i < loc + 127; i++)
- sum += edid[i];
- edid[i] = 256 - sum;
-}
-EXPORT_SYMBOL_GPL(cec_set_edid_phys_addr);
-
-u16 cec_phys_addr_for_input(u16 phys_addr, u8 input)
-{
- /* Check if input is sane */
- if (WARN_ON(input == 0 || input > 0xf))
- return CEC_PHYS_ADDR_INVALID;
-
- if (phys_addr == 0)
- return input << 12;
-
- if ((phys_addr & 0x0fff) == 0)
- return phys_addr | (input << 8);
-
- if ((phys_addr & 0x00ff) == 0)
- return phys_addr | (input << 4);
-
- if ((phys_addr & 0x000f) == 0)
- return phys_addr | input;
-
- /*
- * All nibbles are used so no valid physical addresses can be assigned
- * to the input.
- */
- return CEC_PHYS_ADDR_INVALID;
-}
-EXPORT_SYMBOL_GPL(cec_phys_addr_for_input);
-
-int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
-{
- int i;
-
- if (parent)
- *parent = phys_addr;
- if (port)
- *port = 0;
- if (phys_addr == CEC_PHYS_ADDR_INVALID)
- return 0;
- for (i = 0; i < 16; i += 4)
- if (phys_addr & (0xf << i))
- break;
- if (i == 16)
- return 0;
- if (parent)
- *parent = phys_addr & (0xfff0 << i);
- if (port)
- *port = (phys_addr >> i) & 0xf;
- for (i += 4; i < 16; i += 4)
- if ((phys_addr & (0xf << i)) == 0)
- return -EINVAL;
- return 0;
-}
-EXPORT_SYMBOL_GPL(cec_phys_addr_validate);
diff --git a/drivers/media/cec/cec-pin.c b/drivers/media/cec/cec-pin.c
index 6e311424f0dc..635db8e70ead 100644
--- a/drivers/media/cec/cec-pin.c
+++ b/drivers/media/cec/cec-pin.c
@@ -935,6 +935,17 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
/* Start bit, switch to receive state */
pin->ts = ts;
pin->state = CEC_ST_RX_START_BIT_LOW;
+ /*
+ * If a transmit is pending, then that transmit should
+ * use a signal free time of no more than
+ * CEC_SIGNAL_FREE_TIME_NEW_INITIATOR since it will
+ * have a new initiator due to the receive that is now
+ * starting.
+ */
+ if (pin->tx_msg.len && pin->tx_signal_free_time >
+ CEC_SIGNAL_FREE_TIME_NEW_INITIATOR)
+ pin->tx_signal_free_time =
+ CEC_SIGNAL_FREE_TIME_NEW_INITIATOR;
break;
}
if (ktime_to_ns(pin->ts) == 0)
@@ -1157,6 +1168,15 @@ static int cec_pin_adap_transmit(struct cec_adapter *adap, u8 attempts,
{
struct cec_pin *pin = adap->pin;
+ /*
+ * If a receive is in progress, then this transmit should use
+ * a signal free time of max CEC_SIGNAL_FREE_TIME_NEW_INITIATOR
+ * since when it starts transmitting it will have a new initiator.
+ */
+ if (pin->state != CEC_ST_IDLE &&
+ signal_free_time > CEC_SIGNAL_FREE_TIME_NEW_INITIATOR)
+ signal_free_time = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR;
+
pin->tx_signal_free_time = signal_free_time;
pin->tx_extra_bytes = 0;
pin->tx_msg = *msg;
diff --git a/drivers/media/common/b2c2/flexcop-i2c.c b/drivers/media/common/b2c2/flexcop-i2c.c
index 6675b605eb6f..1f1eaa807811 100644
--- a/drivers/media/common/b2c2/flexcop-i2c.c
+++ b/drivers/media/common/b2c2/flexcop-i2c.c
@@ -226,12 +226,12 @@ int flexcop_i2c_init(struct flexcop_device *fc)
fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
- strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod",
- sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
- strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
- sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
- strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner",
- sizeof(fc->fc_i2c_adap[2].i2c_adap.name));
+ strscpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod",
+ sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
+ strscpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
+ sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
+ strscpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner",
+ sizeof(fc->fc_i2c_adap[2].i2c_adap.name));
i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
diff --git a/drivers/media/common/cx2341x.c b/drivers/media/common/cx2341x.c
index 81dce9a81bd3..1dcc39b87bb7 100644
--- a/drivers/media/common/cx2341x.c
+++ b/drivers/media/common/cx2341x.c
@@ -569,7 +569,7 @@ static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
qctrl->step = step;
qctrl->default_value = def;
qctrl->reserved[0] = qctrl->reserved[1] = 0;
- strlcpy(qctrl->name, name, sizeof(qctrl->name));
+ strscpy(qctrl->name, name, sizeof(qctrl->name));
return 0;
default:
diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c
index d4987fd05d05..c790ae264464 100644
--- a/drivers/media/common/saa7146/saa7146_fops.c
+++ b/drivers/media/common/saa7146/saa7146_fops.c
@@ -606,7 +606,7 @@ int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev,
vfd->tvnorms = 0;
for (i = 0; i < dev->ext_vv_data->num_stds; i++)
vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
- strlcpy(vfd->name, name, sizeof(vfd->name));
+ strscpy(vfd->name, name, sizeof(vfd->name));
video_set_drvdata(vfd, dev);
err = video_register_device(vfd, type, -1);
diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c
index 0dfa0c09d646..f90aa8109663 100644
--- a/drivers/media/common/saa7146/saa7146_video.c
+++ b/drivers/media/common/saa7146/saa7146_video.c
@@ -451,8 +451,8 @@ static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *
struct video_device *vdev = video_devdata(file);
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- strcpy((char *)cap->driver, "saa7146 v4l2");
- strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
+ strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));
+ strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci));
cap->device_caps =
V4L2_CAP_VIDEO_CAPTURE |
@@ -525,8 +525,8 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtd
{
if (f->index >= ARRAY_SIZE(formats))
return -EINVAL;
- strlcpy((char *)f->description, formats[f->index].name,
- sizeof(f->description));
+ strscpy((char *)f->description, formats[f->index].name,
+ sizeof(f->description));
f->pixelformat = formats[f->index].pixelformat;
return 0;
}
diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c
index 3b02cb570a6e..add9d6361914 100644
--- a/drivers/media/common/siano/smscoreapi.c
+++ b/drivers/media/common/siano/smscoreapi.c
@@ -450,7 +450,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (entry) {
entry->mode = default_mode;
- strlcpy(entry->devpath, devpath, sizeof(entry->devpath));
+ strscpy(entry->devpath, devpath, sizeof(entry->devpath));
list_add(&entry->entry, &g_smscore_registry);
} else
pr_err("failed to create smscore_registry.\n");
@@ -735,7 +735,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
dev->postload_handler = params->postload_handler;
dev->device_flags = params->flags;
- strlcpy(dev->devpath, params->devpath, sizeof(dev->devpath));
+ strscpy(dev->devpath, params->devpath, sizeof(dev->devpath));
smscore_registry_settype(dev->devpath, params->device_type);
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
index 56db0a944421..79bd627f84b8 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -26,10 +26,10 @@ void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
const s32 *samples = (const void *)buf;
for (i = 0; i < len >> 2; i++) {
- DEFINE_IR_RAW_EVENT(ev);
-
- ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
- ev.pulse = (samples[i] > 0) ? false : true;
+ struct ir_raw_event ev = {
+ .duration = abs(samples[i]) * 1000, /* Convert to ns */
+ .pulse = (samples[i] > 0) ? false : true
+ };
ir_raw_event_store(coredev->ir.dev, &ev);
}
@@ -55,7 +55,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
snprintf(coredev->ir.name, sizeof(coredev->ir.name),
"SMS IR (%s)", sms_get_board(board_id)->name);
- strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
+ strscpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys));
dev->device_name = coredev->ir.name;
diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c
index 3a3dc23c560c..a4341205c197 100644
--- a/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c
+++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c
@@ -602,14 +602,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SRGB][5] = { 3138, 657, 810 },
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SRGB][6] = { 731, 680, 3048 },
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 },
- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][1] = { 3046, 3054, 886 },
- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][2] = { 0, 3058, 3031 },
- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][3] = { 360, 3079, 877 },
- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][4] = { 3103, 587, 3027 },
- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][5] = { 3116, 723, 861 },
- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][6] = { 789, 744, 3025 },
- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][1] = { 3046, 3054, 886 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][2] = { 0, 3058, 3031 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][3] = { 360, 3079, 877 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][4] = { 3103, 587, 3027 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][5] = { 3116, 723, 861 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][6] = { 789, 744, 3025 },
+ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 },
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2941, 2950, 546 },
[V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE240M][2] = { 0, 2954, 2924 },
@@ -658,14 +658,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SRGB][5] = { 3138, 657, 810 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SRGB][6] = { 731, 680, 3048 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 },
- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][1] = { 3046, 3054, 886 },
- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][2] = { 0, 3058, 3031 },
- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][3] = { 360, 3079, 877 },
- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][4] = { 3103, 587, 3027 },
- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][5] = { 3116, 723, 861 },
- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][6] = { 789, 744, 3025 },
- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][1] = { 3046, 3054, 886 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][2] = { 0, 3058, 3031 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][3] = { 360, 3079, 877 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][4] = { 3103, 587, 3027 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][5] = { 3116, 723, 861 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][6] = { 789, 744, 3025 },
+ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2941, 2950, 546 },
[V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE240M][2] = { 0, 2954, 2924 },
@@ -714,14 +714,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SRGB][5] = { 3056, 800, 800 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3056 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 },
- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 851 },
- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][2] = { 851, 3033, 3033 },
- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][3] = { 851, 3033, 851 },
- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][4] = { 3033, 851, 3033 },
- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][5] = { 3033, 851, 851 },
- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 3033 },
- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 851 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][2] = { 851, 3033, 3033 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][3] = { 851, 3033, 851 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][4] = { 3033, 851, 3033 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][5] = { 3033, 851, 851 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 3033 },
+ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 507 },
[V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE240M][2] = { 507, 2926, 2926 },
@@ -770,14 +770,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE
[V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][5] = { 2599, 901, 909 },
[V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][6] = { 991, 0, 2966 },
[V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][1] = { 2989, 3120, 1180 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][2] = { 1913, 3011, 3009 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][3] = { 1836, 3099, 1105 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][4] = { 2627, 413, 2966 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][5] = { 2576, 943, 951 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][6] = { 1026, 0, 2942 },
- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][1] = { 2989, 3120, 1180 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][2] = { 1913, 3011, 3009 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][3] = { 1836, 3099, 1105 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][4] = { 2627, 413, 2966 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][5] = { 2576, 943, 951 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][6] = { 1026, 0, 2942 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 },
[V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
[V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2879, 3022, 874 },
[V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][2] = { 1688, 2903, 2901 },
@@ -826,14 +826,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SRGB][5] = { 3001, 800, 799 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3071 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 799 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 776 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][2] = { 1068, 3033, 3033 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][3] = { 1068, 3033, 776 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][4] = { 2977, 851, 3048 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][5] = { 2977, 851, 851 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 3048 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 776 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][2] = { 1068, 3033, 3033 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][3] = { 1068, 3033, 776 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][4] = { 2977, 851, 3048 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][5] = { 2977, 851, 851 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 3048 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 423 },
[V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE240M][2] = { 749, 2926, 2926 },
@@ -882,14 +882,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SRGB][5] = { 3056, 800, 800 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3056 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 },
- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 851 },
- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][2] = { 851, 3033, 3033 },
- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][3] = { 851, 3033, 851 },
- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][4] = { 3033, 851, 3033 },
- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][5] = { 3033, 851, 851 },
- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 3033 },
- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 851 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][2] = { 851, 3033, 3033 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][3] = { 851, 3033, 851 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][4] = { 3033, 851, 3033 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][5] = { 3033, 851, 851 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 3033 },
+ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 507 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE240M][2] = { 507, 2926, 2926 },
@@ -922,62 +922,62 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 1812, 886, 886 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 886, 886, 1812 },
[V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 886, 886, 886 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 781 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][2] = { 1622, 2939, 2939 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][3] = { 1622, 2939, 781 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][4] = { 2502, 547, 2881 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][5] = { 2502, 547, 547 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][6] = { 547, 547, 2881 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3056, 3056 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][1] = { 3056, 3056, 1031 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][2] = { 1838, 3056, 3056 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][3] = { 1838, 3056, 1031 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][4] = { 2657, 800, 3002 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][5] = { 2657, 800, 800 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3002 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 1063 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][2] = { 1828, 3033, 3033 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][3] = { 1828, 3033, 1063 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][4] = { 2633, 851, 2979 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][5] = { 2633, 851, 851 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 2979 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 744 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][2] = { 1594, 2926, 2926 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][3] = { 1594, 2926, 744 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][4] = { 2484, 507, 2867 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][5] = { 2484, 507, 507 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][6] = { 507, 507, 2867 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][1] = { 2125, 2125, 212 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][2] = { 698, 2125, 2125 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][3] = { 698, 2125, 212 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][4] = { 1557, 130, 2043 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][5] = { 1557, 130, 130 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2043 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1308 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][2] = { 2069, 3175, 3175 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][3] = { 2069, 3175, 1308 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][4] = { 2816, 1084, 3127 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][5] = { 2816, 1084, 1084 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3127 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 1812, 1812, 1812 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 1812, 1812, 1022 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 1402, 1812, 1812 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 1402, 1812, 1022 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 1692, 886, 1797 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 1692, 886, 886 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 886, 886, 1797 },
- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 886, 886, 886 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 781 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][2] = { 1622, 2939, 2939 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][3] = { 1622, 2939, 781 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][4] = { 2502, 547, 2881 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][5] = { 2502, 547, 547 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][6] = { 547, 547, 2881 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3056, 3056 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][1] = { 3056, 3056, 1031 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][2] = { 1838, 3056, 3056 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][3] = { 1838, 3056, 1031 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][4] = { 2657, 800, 3002 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][5] = { 2657, 800, 800 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3002 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 1063 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][2] = { 1828, 3033, 3033 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][3] = { 1828, 3033, 1063 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][4] = { 2633, 851, 2979 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][5] = { 2633, 851, 851 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 2979 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 744 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][2] = { 1594, 2926, 2926 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][3] = { 1594, 2926, 744 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][4] = { 2484, 507, 2867 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][5] = { 2484, 507, 507 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][6] = { 507, 507, 2867 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][1] = { 2125, 2125, 212 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][2] = { 698, 2125, 2125 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][3] = { 698, 2125, 212 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][4] = { 1557, 130, 2043 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][5] = { 1557, 130, 130 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2043 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1308 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][2] = { 2069, 3175, 3175 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][3] = { 2069, 3175, 1308 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][4] = { 2816, 1084, 3127 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][5] = { 2816, 1084, 1084 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3127 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 1812, 1812, 1812 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 1812, 1812, 1022 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 1402, 1812, 1812 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 1402, 1812, 1022 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 1692, 886, 1797 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 1692, 886, 886 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 886, 886, 1797 },
+ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 886, 886, 886 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][1] = { 2877, 2923, 1058 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][2] = { 1837, 2840, 2916 },
@@ -994,14 +994,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SRGB][5] = { 2517, 1159, 900 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SRGB][6] = { 1042, 870, 2917 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 },
- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][1] = { 2976, 3018, 1315 },
- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][2] = { 2024, 2942, 3011 },
- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][3] = { 1930, 2926, 1256 },
- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][4] = { 2563, 1227, 2916 },
- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][5] = { 2494, 1183, 943 },
- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][6] = { 1073, 916, 2894 },
- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][1] = { 2976, 3018, 1315 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][2] = { 2024, 2942, 3011 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][3] = { 1930, 2926, 1256 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][4] = { 2563, 1227, 2916 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][5] = { 2494, 1183, 943 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][6] = { 1073, 916, 2894 },
+ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE240M][1] = { 2864, 2910, 1024 },
[V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE240M][2] = { 1811, 2826, 2903 },
@@ -1050,14 +1050,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE
[V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][5] = { 2880, 998, 902 },
[V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][6] = { 816, 823, 2940 },
[V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 799 },
- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][1] = { 3029, 3028, 1255 },
- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][2] = { 1406, 2988, 3011 },
- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][3] = { 1398, 2983, 1190 },
- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][4] = { 2860, 1050, 2939 },
- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][5] = { 2857, 1033, 945 },
- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][6] = { 866, 873, 2916 },
- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][1] = { 3029, 3028, 1255 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][2] = { 1406, 2988, 3011 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][3] = { 1398, 2983, 1190 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][4] = { 2860, 1050, 2939 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][5] = { 2857, 1033, 945 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][6] = { 866, 873, 2916 },
+ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 },
[V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 },
[V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][1] = { 2923, 2921, 957 },
[V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][2] = { 1125, 2877, 2902 },
@@ -1128,7 +1128,7 @@ static const double rec709_to_240m[3][3] = {
{ 0.0016327, 0.0044133, 0.9939540 },
};
-static const double rec709_to_adobergb[3][3] = {
+static const double rec709_to_oprgb[3][3] = {
{ 0.7151627, 0.2848373, -0.0000000 },
{ 0.0000000, 1.0000000, 0.0000000 },
{ -0.0000000, 0.0411705, 0.9588295 },
@@ -1195,7 +1195,7 @@ static double transfer_rec709_to_rgb(double v)
return (v < 0.081) ? v / 4.5 : pow((v + 0.099) / 1.099, 1.0 / 0.45);
}
-static double transfer_rgb_to_adobergb(double v)
+static double transfer_rgb_to_oprgb(double v)
{
return pow(v, 1.0 / 2.19921875);
}
@@ -1251,8 +1251,8 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func,
case V4L2_COLORSPACE_470_SYSTEM_M:
mult_matrix(r, g, b, rec709_to_ntsc1953);
break;
- case V4L2_COLORSPACE_ADOBERGB:
- mult_matrix(r, g, b, rec709_to_adobergb);
+ case V4L2_COLORSPACE_OPRGB:
+ mult_matrix(r, g, b, rec709_to_oprgb);
break;
case V4L2_COLORSPACE_BT2020:
mult_matrix(r, g, b, rec709_to_bt2020);
@@ -1284,10 +1284,10 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func,
*g = transfer_rgb_to_srgb(*g);
*b = transfer_rgb_to_srgb(*b);
break;
- case V4L2_XFER_FUNC_ADOBERGB:
- *r = transfer_rgb_to_adobergb(*r);
- *g = transfer_rgb_to_adobergb(*g);
- *b = transfer_rgb_to_adobergb(*b);
+ case V4L2_XFER_FUNC_OPRGB:
+ *r = transfer_rgb_to_oprgb(*r);
+ *g = transfer_rgb_to_oprgb(*g);
+ *b = transfer_rgb_to_oprgb(*b);
break;
case V4L2_XFER_FUNC_DCI_P3:
*r = transfer_rgb_to_dcip3(*r);
@@ -1321,7 +1321,7 @@ int main(int argc, char **argv)
V4L2_COLORSPACE_470_SYSTEM_BG,
0,
V4L2_COLORSPACE_SRGB,
- V4L2_COLORSPACE_ADOBERGB,
+ V4L2_COLORSPACE_OPRGB,
V4L2_COLORSPACE_BT2020,
0,
V4L2_COLORSPACE_DCI_P3,
@@ -1336,7 +1336,7 @@ int main(int argc, char **argv)
"V4L2_COLORSPACE_470_SYSTEM_BG",
"",
"V4L2_COLORSPACE_SRGB",
- "V4L2_COLORSPACE_ADOBERGB",
+ "V4L2_COLORSPACE_OPRGB",
"V4L2_COLORSPACE_BT2020",
"",
"V4L2_COLORSPACE_DCI_P3",
@@ -1345,7 +1345,7 @@ int main(int argc, char **argv)
"",
"V4L2_XFER_FUNC_709",
"V4L2_XFER_FUNC_SRGB",
- "V4L2_XFER_FUNC_ADOBERGB",
+ "V4L2_XFER_FUNC_OPRGB",
"V4L2_XFER_FUNC_SMPTE240M",
"V4L2_XFER_FUNC_NONE",
"V4L2_XFER_FUNC_DCI_P3",
diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
index abd4c788dffd..fa483b95bc5a 100644
--- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
+++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
@@ -202,6 +202,10 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
case V4L2_PIX_FMT_SGBRG12:
case V4L2_PIX_FMT_SGRBG12:
case V4L2_PIX_FMT_SRGGB12:
+ case V4L2_PIX_FMT_SBGGR16:
+ case V4L2_PIX_FMT_SGBRG16:
+ case V4L2_PIX_FMT_SGRBG16:
+ case V4L2_PIX_FMT_SRGGB16:
tpg->interleaved = true;
tpg->vdownsampling[1] = 1;
tpg->hdownsampling[1] = 1;
@@ -235,6 +239,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
case V4L2_PIX_FMT_Y12:
case V4L2_PIX_FMT_Y16:
case V4L2_PIX_FMT_Y16_BE:
+ case V4L2_PIX_FMT_Z16:
tpg->color_enc = TGP_COLOR_ENC_LUMA;
break;
case V4L2_PIX_FMT_YUV444:
@@ -351,6 +356,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
case V4L2_PIX_FMT_Y12:
case V4L2_PIX_FMT_Y16:
case V4L2_PIX_FMT_Y16_BE:
+ case V4L2_PIX_FMT_Z16:
tpg->twopixelsize[0] = 2 * 2;
break;
case V4L2_PIX_FMT_RGB24:
@@ -392,6 +398,10 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
case V4L2_PIX_FMT_SGRBG12:
case V4L2_PIX_FMT_SGBRG12:
case V4L2_PIX_FMT_SBGGR12:
+ case V4L2_PIX_FMT_SRGGB16:
+ case V4L2_PIX_FMT_SGRBG16:
+ case V4L2_PIX_FMT_SGBRG16:
+ case V4L2_PIX_FMT_SBGGR16:
tpg->twopixelsize[0] = 4;
tpg->twopixelsize[1] = 4;
break;
@@ -1062,6 +1072,7 @@ static void gen_twopix(struct tpg_data *tpg,
buf[0][offset+1] = r_y_h >> 4;
break;
case V4L2_PIX_FMT_Y16:
+ case V4L2_PIX_FMT_Z16:
/*
* Ideally both bytes should be set to r_y_h, but then you won't
* be able to detect endian problems. So keep it 0 except for
@@ -1355,6 +1366,22 @@ static void gen_twopix(struct tpg_data *tpg,
buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
break;
+ case V4L2_PIX_FMT_SBGGR16:
+ buf[0][offset] = buf[0][offset + 1] = odd ? g_u_s : b_v;
+ buf[1][offset] = buf[1][offset + 1] = odd ? r_y_h : g_u_s;
+ break;
+ case V4L2_PIX_FMT_SGBRG16:
+ buf[0][offset] = buf[0][offset + 1] = odd ? b_v : g_u_s;
+ buf[1][offset] = buf[1][offset + 1] = odd ? g_u_s : r_y_h;
+ break;
+ case V4L2_PIX_FMT_SGRBG16:
+ buf[0][offset] = buf[0][offset + 1] = odd ? r_y_h : g_u_s;
+ buf[1][offset] = buf[1][offset + 1] = odd ? g_u_s : b_v;
+ break;
+ case V4L2_PIX_FMT_SRGGB16:
+ buf[0][offset] = buf[0][offset + 1] = odd ? g_u_s : r_y_h;
+ buf[1][offset] = buf[1][offset + 1] = odd ? b_v : g_u_s;
+ break;
}
}
@@ -1373,6 +1400,10 @@ unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line)
case V4L2_PIX_FMT_SGBRG12:
case V4L2_PIX_FMT_SGRBG12:
case V4L2_PIX_FMT_SRGGB12:
+ case V4L2_PIX_FMT_SBGGR16:
+ case V4L2_PIX_FMT_SGBRG16:
+ case V4L2_PIX_FMT_SGRBG16:
+ case V4L2_PIX_FMT_SRGGB16:
return buf_line & 1;
default:
return 0;
@@ -1770,7 +1801,7 @@ typedef struct { u16 __; u8 _; } __packed x24;
pos[7] = (chr & (0x01 << 0) ? fg : bg); \
} \
\
- pos += (tpg->hflip ? -8 : 8) / hdiv; \
+ pos += (tpg->hflip ? -8 : 8) / (int)hdiv; \
} \
} \
} while (0)
@@ -2038,8 +2069,12 @@ void tpg_log_status(struct tpg_data *tpg)
tpg->compose.left, tpg->compose.top);
pr_info("tpg colorspace: %d\n", tpg->colorspace);
pr_info("tpg transfer function: %d/%d\n", tpg->xfer_func, tpg->real_xfer_func);
- pr_info("tpg Y'CbCr encoding: %d/%d\n", tpg->ycbcr_enc, tpg->real_ycbcr_enc);
- pr_info("tpg HSV encoding: %d/%d\n", tpg->hsv_enc, tpg->real_hsv_enc);
+ if (tpg->color_enc == TGP_COLOR_ENC_HSV)
+ pr_info("tpg HSV encoding: %d/%d\n",
+ tpg->hsv_enc, tpg->real_hsv_enc);
+ else if (tpg->color_enc == TGP_COLOR_ENC_YCBCR)
+ pr_info("tpg Y'CbCr encoding: %d/%d\n",
+ tpg->ycbcr_enc, tpg->real_ycbcr_enc);
pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization);
pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range);
}
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 5653e8eebe2b..d6d22cf77066 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -661,6 +661,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
{
unsigned int num_buffers, allocated_buffers, num_planes = 0;
unsigned plane_sizes[VB2_MAX_PLANES] = { };
+ unsigned int i;
int ret;
if (q->streaming) {
@@ -718,6 +719,14 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
if (ret)
return ret;
+ /* Check that driver has set sane values */
+ if (WARN_ON(!num_planes))
+ return -EINVAL;
+
+ for (i = 0; i < num_planes; i++)
+ if (WARN_ON(!plane_sizes[i]))
+ return -EINVAL;
+
/* Finally, allocate buffers and video memory */
allocated_buffers =
__vb2_queue_alloc(q, memory, num_buffers, num_planes, plane_sizes);
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index d548f98c7a67..1544e8cef564 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -1265,6 +1265,7 @@ static const struct file_operations dvb_demux_fops = {
.owner = THIS_MODULE,
.read = dvb_demux_read,
.unlocked_ioctl = dvb_demux_ioctl,
+ .compat_ioctl = dvb_demux_ioctl,
.open = dvb_demux_open,
.release = dvb_demux_release,
.poll = dvb_demux_poll,
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index c4e7ebfe4d29..961207cf09eb 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2422,7 +2422,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
struct dvb_frontend_info *info = parg;
memset(info, 0, sizeof(*info));
- strcpy(info->name, fe->ops.info.name);
+ strscpy(info->name, fe->ops.info.name, sizeof(info->name));
info->symbol_rate_min = fe->ops.info.symbol_rate_min;
info->symbol_rate_max = fe->ops.info.symbol_rate_max;
info->symbol_rate_tolerance = fe->ops.info.symbol_rate_tolerance;
diff --git a/drivers/media/dvb-core/dvb_vb2.c b/drivers/media/dvb-core/dvb_vb2.c
index b811adf88afa..c90b1fd94735 100644
--- a/drivers/media/dvb-core/dvb_vb2.c
+++ b/drivers/media/dvb-core/dvb_vb2.c
@@ -194,7 +194,7 @@ int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int nonblocking)
spin_lock_init(&ctx->slock);
INIT_LIST_HEAD(&ctx->dvb_q);
- strlcpy(ctx->name, name, DVB_VB2_NAME_MAX);
+ strscpy(ctx->name, name, DVB_VB2_NAME_MAX);
ctx->nonblocking = nonblocking;
ctx->state = DVB_VB2_STATE_INIT;
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index 3c8778570331..b7171bf094fb 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -621,7 +621,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
unsigned demux_pad = 0;
unsigned dvr_pad = 0;
unsigned ntuner = 0, ndemod = 0;
- int ret;
+ int ret, pad_source, pad_sink;
static const char *connector_name = "Television";
if (!mdev)
@@ -681,7 +681,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
if (ret)
return ret;
- if (!ntuner)
+ if (!ntuner) {
ret = media_create_pad_links(mdev,
MEDIA_ENT_F_CONN_RF,
conn, 0,
@@ -689,22 +689,31 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
demod, 0,
MEDIA_LNK_FL_ENABLED,
false);
- else
+ } else {
+ pad_sink = media_get_pad_index(tuner, true,
+ PAD_SIGNAL_ANALOG);
+ if (pad_sink < 0)
+ return -EINVAL;
ret = media_create_pad_links(mdev,
MEDIA_ENT_F_CONN_RF,
conn, 0,
MEDIA_ENT_F_TUNER,
- tuner, TUNER_PAD_RF_INPUT,
+ tuner, pad_sink,
MEDIA_LNK_FL_ENABLED,
false);
+ }
if (ret)
return ret;
}
if (ntuner && ndemod) {
+ pad_source = media_get_pad_index(tuner, true,
+ PAD_SIGNAL_ANALOG);
+ if (pad_source)
+ return -EINVAL;
ret = media_create_pad_links(mdev,
MEDIA_ENT_F_TUNER,
- tuner, TUNER_PAD_OUTPUT,
+ tuner, pad_source,
MEDIA_ENT_F_DTV_DEMOD,
demod, 0, MEDIA_LNK_FL_ENABLED,
false);
@@ -967,9 +976,9 @@ struct i2c_client *dvb_module_probe(const char *module_name,
return NULL;
if (name)
- strlcpy(board_info->type, name, I2C_NAME_SIZE);
+ strscpy(board_info->type, name, I2C_NAME_SIZE);
else
- strlcpy(board_info->type, module_name, I2C_NAME_SIZE);
+ strscpy(board_info->type, module_name, I2C_NAME_SIZE);
board_info->addr = addr;
board_info->platform_data = platform_data;
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 048285134cdf..847da72d1256 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -791,6 +791,16 @@ config DVB_LNBH25
An SEC control chip.
Say Y when you want to support this chip.
+config DVB_LNBH29
+ tristate "LNBH29 SEC controller"
+ depends on DVB_CORE && I2C
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ LNB power supply and control voltage
+ regulator chip with step-up converter
+ and I2C interface for STMicroelectronics LNBH29.
+ Say Y when you want to support this chip.
+
config DVB_LNBP21
tristate "LNBP21/LNBH24 SEC controllers"
depends on DVB_CORE && I2C
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index 779dfd027b24..e9179162658c 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_DVB_LGDT3306A) += lgdt3306a.o
obj-$(CONFIG_DVB_LG2160) += lg2160.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o
obj-$(CONFIG_DVB_LNBH25) += lnbh25.o
+obj-$(CONFIG_DVB_LNBH29) += lnbh29.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
obj-$(CONFIG_DVB_ISL6405) += isl6405.o
diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c
index f285096a48f0..b2dd20ffd002 100644
--- a/drivers/media/dvb-frontends/au8522_decoder.c
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -718,10 +718,12 @@ static int au8522_probe(struct i2c_client *client,
v4l2_i2c_subdev_init(sd, client, &au8522_ops);
#if defined(CONFIG_MEDIA_CONTROLLER)
- state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
- state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
- state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
- state->pads[DEMOD_PAD_AUDIO_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ state->pads[AU8522_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ state->pads[AU8522_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
+ state->pads[AU8522_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ state->pads[AU8522_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
+ state->pads[AU8522_PAD_AUDIO_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ state->pads[AU8522_PAD_AUDIO_OUT].sig_type = PAD_SIGNAL_AUDIO;
sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(state->pads),
diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h
index 2043c1744753..68299d2705f7 100644
--- a/drivers/media/dvb-frontends/au8522_priv.h
+++ b/drivers/media/dvb-frontends/au8522_priv.h
@@ -40,6 +40,13 @@
#define AU8522_DIGITAL_MODE 1
#define AU8522_SUSPEND_MODE 2
+enum au8522_pads {
+ AU8522_PAD_IF_INPUT,
+ AU8522_PAD_VID_OUT,
+ AU8522_PAD_AUDIO_OUT,
+ AU8522_NUM_PADS
+};
+
struct au8522_state {
struct i2c_client *c;
struct i2c_adapter *i2c;
@@ -71,7 +78,7 @@ struct au8522_state {
struct v4l2_ctrl_handler hdl;
#ifdef CONFIG_MEDIA_CONTROLLER
- struct media_pad pads[DEMOD_NUM_PADS];
+ struct media_pad pads[AU8522_NUM_PADS];
#endif
};
diff --git a/drivers/media/dvb-frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c
index e49215020a93..83dfae78579d 100644
--- a/drivers/media/dvb-frontends/cx24123.c
+++ b/drivers/media/dvb-frontends/cx24123.c
@@ -1087,7 +1087,7 @@ struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
if (config->dont_use_pll)
cx24123_repeater_mode(state, 1, 0);
- strlcpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus",
+ strscpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus",
sizeof(state->tuner_i2c_adapter.name));
state->tuner_i2c_adapter.algo = &cx24123_tuner_i2c_algo;
state->tuner_i2c_adapter.algo_data = NULL;
diff --git a/drivers/media/dvb-frontends/cxd2099.c b/drivers/media/dvb-frontends/cxd2099.c
index 4a0ce3037fd6..5264e873850e 100644
--- a/drivers/media/dvb-frontends/cxd2099.c
+++ b/drivers/media/dvb-frontends/cxd2099.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* cxd2099.c: Driver for the Sony CXD2099AR Common Interface Controller
*
@@ -701,4 +702,4 @@ module_i2c_driver(cxd2099_driver);
MODULE_DESCRIPTION("Sony CXD2099AR Common Interface controller driver");
MODULE_AUTHOR("Ralph Metzler");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/dvb-frontends/cxd2099.h b/drivers/media/dvb-frontends/cxd2099.h
index ec1910dec3f3..0c101bdef01d 100644
--- a/drivers/media/dvb-frontends/cxd2099.h
+++ b/drivers/media/dvb-frontends/cxd2099.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2099.h: Driver for the Sony CXD2099AR Common Interface Controller
*
diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c
index 3e0d8cbd76da..0f0acf98d226 100644
--- a/drivers/media/dvb-frontends/cxd2820r_core.c
+++ b/drivers/media/dvb-frontends/cxd2820r_core.c
@@ -540,7 +540,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *config,
pdata.attach_in_use = true;
memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "cxd2820r", I2C_NAME_SIZE);
+ strscpy(board_info.type, "cxd2820r", I2C_NAME_SIZE);
board_info.addr = config->i2c_address;
board_info.platform_data = &pdata;
client = i2c_new_device(adapter, &board_info);
diff --git a/drivers/media/dvb-frontends/dibx000_common.c b/drivers/media/dvb-frontends/dibx000_common.c
index 70119c79ac2b..dc80a8442e7a 100644
--- a/drivers/media/dvb-frontends/dibx000_common.c
+++ b/drivers/media/dvb-frontends/dibx000_common.c
@@ -424,7 +424,7 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
struct i2c_algorithm *algo, const char *name,
struct dibx000_i2c_master *mst)
{
- strlcpy(i2c_adap->name, name, sizeof(i2c_adap->name));
+ strscpy(i2c_adap->name, name, sizeof(i2c_adap->name));
i2c_adap->algo = algo;
i2c_adap->algo_data = NULL;
i2c_set_adapdata(i2c_adap, mst);
diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c
index 9628d4067fe1..551b7d65fa66 100644
--- a/drivers/media/dvb-frontends/drx39xyj/drxj.c
+++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c
@@ -3555,8 +3555,8 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg
if (!ext_attr->has_smatx)
return -EIO;
switch (uio_cfg->mode) {
- case DRX_UIO_MODE_FIRMWARE_SMA: /* falltrough */
- case DRX_UIO_MODE_FIRMWARE_SAW: /* falltrough */
+ case DRX_UIO_MODE_FIRMWARE_SMA: /* fall through */
+ case DRX_UIO_MODE_FIRMWARE_SAW: /* fall through */
case DRX_UIO_MODE_READWRITE:
ext_attr->uio_sma_tx_mode = uio_cfg->mode;
break;
@@ -3579,7 +3579,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg
if (!ext_attr->has_smarx)
return -EIO;
switch (uio_cfg->mode) {
- case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
+ case DRX_UIO_MODE_FIRMWARE0: /* fall through */
case DRX_UIO_MODE_READWRITE:
ext_attr->uio_sma_rx_mode = uio_cfg->mode;
break;
@@ -3603,7 +3603,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg
if (!ext_attr->has_gpio)
return -EIO;
switch (uio_cfg->mode) {
- case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
+ case DRX_UIO_MODE_FIRMWARE0: /* fall through */
case DRX_UIO_MODE_READWRITE:
ext_attr->uio_gpio_mode = uio_cfg->mode;
break;
@@ -3639,7 +3639,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg
}
ext_attr->uio_irqn_mode = uio_cfg->mode;
break;
- case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
+ case DRX_UIO_MODE_FIRMWARE0: /* fall through */
default:
return -EINVAL;
break;
diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c
index 10d584ce538d..96807e134886 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -929,7 +929,7 @@ struct dvb_frontend *lgdt330x_attach(const struct lgdt330x_config *_config,
struct i2c_board_info board_info = {};
struct lgdt330x_config config = *_config;
- strlcpy(board_info.type, "lgdt330x", sizeof(board_info.type));
+ strscpy(board_info.type, "lgdt330x", sizeof(board_info.type));
board_info.addr = demod_address;
board_info.platform_data = &config;
client = i2c_new_device(i2c, &board_info);
diff --git a/drivers/media/dvb-frontends/lnbh29.c b/drivers/media/dvb-frontends/lnbh29.c
new file mode 100644
index 000000000000..410bae099c32
--- /dev/null
+++ b/drivers/media/dvb-frontends/lnbh29.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Driver for LNB supply and control IC STMicroelectronics LNBH29
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+#include <media/dvb_frontend.h>
+#include "lnbh29.h"
+
+/**
+ * struct lnbh29_priv - LNBH29 driver private data
+ * @i2c: Pointer to the I2C adapter structure
+ * @i2c_address: I2C address of LNBH29 chip
+ * @config: Registers configuration
+ * offset 0: 1st register address, always 0x01 (DATA)
+ * offset 1: DATA register value
+ */
+struct lnbh29_priv {
+ struct i2c_adapter *i2c;
+ u8 i2c_address;
+ u8 config[2];
+};
+
+#define LNBH29_STATUS_OLF BIT(0)
+#define LNBH29_STATUS_OTF BIT(1)
+#define LNBH29_STATUS_VMON BIT(2)
+#define LNBH29_STATUS_PNG BIT(3)
+#define LNBH29_STATUS_PDO BIT(4)
+#define LNBH29_VSEL_MASK GENMASK(2, 0)
+#define LNBH29_VSEL_0 0x00
+/* Min: 13.188V, Typ: 13.667V, Max:14V */
+#define LNBH29_VSEL_13 0x03
+/* Min: 18.158V, Typ: 18.817V, Max:19.475V */
+#define LNBH29_VSEL_18 0x07
+
+static int lnbh29_read_vmon(struct lnbh29_priv *priv)
+{
+ u8 addr = 0x00;
+ u8 status[2];
+ int ret;
+ struct i2c_msg msg[2] = {
+ {
+ .addr = priv->i2c_address,
+ .flags = 0,
+ .len = 1,
+ .buf = &addr
+ }, {
+ .addr = priv->i2c_address,
+ .flags = I2C_M_RD,
+ .len = sizeof(status),
+ .buf = status
+ }
+ };
+
+ ret = i2c_transfer(priv->i2c, msg, 2);
+ if (ret >= 0 && ret != 2)
+ ret = -EIO;
+ if (ret < 0) {
+ dev_dbg(&priv->i2c->dev, "LNBH29 I2C transfer failed (%d)\n",
+ ret);
+ return ret;
+ }
+
+ if (status[0] & (LNBH29_STATUS_OLF | LNBH29_STATUS_VMON)) {
+ dev_err(&priv->i2c->dev,
+ "LNBH29 voltage in failure state, status reg 0x%x\n",
+ status[0]);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int lnbh29_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
+{
+ struct lnbh29_priv *priv = fe->sec_priv;
+ u8 data_reg;
+ int ret;
+ struct i2c_msg msg = {
+ .addr = priv->i2c_address,
+ .flags = 0,
+ .len = sizeof(priv->config),
+ .buf = priv->config
+ };
+
+ switch (voltage) {
+ case SEC_VOLTAGE_OFF:
+ data_reg = LNBH29_VSEL_0;
+ break;
+ case SEC_VOLTAGE_13:
+ data_reg = LNBH29_VSEL_13;
+ break;
+ case SEC_VOLTAGE_18:
+ data_reg = LNBH29_VSEL_18;
+ break;
+ default:
+ return -EINVAL;
+ }
+ priv->config[1] &= ~LNBH29_VSEL_MASK;
+ priv->config[1] |= data_reg;
+
+ ret = i2c_transfer(priv->i2c, &msg, 1);
+ if (ret >= 0 && ret != 1)
+ ret = -EIO;
+ if (ret < 0) {
+ dev_err(&priv->i2c->dev, "LNBH29 I2C transfer error (%d)\n",
+ ret);
+ return ret;
+ }
+
+ /* Soft-start time (Vout 0V to 18V) is Typ. 6ms. */
+ usleep_range(6000, 20000);
+
+ if (voltage == SEC_VOLTAGE_OFF)
+ return 0;
+
+ return lnbh29_read_vmon(priv);
+}
+
+static void lnbh29_release(struct dvb_frontend *fe)
+{
+ lnbh29_set_voltage(fe, SEC_VOLTAGE_OFF);
+ kfree(fe->sec_priv);
+ fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *lnbh29_attach(struct dvb_frontend *fe,
+ struct lnbh29_config *cfg,
+ struct i2c_adapter *i2c)
+{
+ struct lnbh29_priv *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return NULL;
+
+ priv->i2c_address = (cfg->i2c_address >> 1);
+ priv->i2c = i2c;
+ priv->config[0] = 0x01;
+ priv->config[1] = cfg->data_config;
+ fe->sec_priv = priv;
+
+ if (lnbh29_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+ dev_err(&i2c->dev, "no LNBH29 found at I2C addr 0x%02x\n",
+ priv->i2c_address);
+ kfree(priv);
+ fe->sec_priv = NULL;
+ return NULL;
+ }
+
+ fe->ops.release_sec = lnbh29_release;
+ fe->ops.set_voltage = lnbh29_set_voltage;
+
+ dev_info(&i2c->dev, "LNBH29 attached at I2C addr 0x%02x\n",
+ priv->i2c_address);
+
+ return fe;
+}
+EXPORT_SYMBOL(lnbh29_attach);
+
+MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
+MODULE_DESCRIPTION("STMicroelectronics LNBH29 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/dvb-frontends/lnbh29.h b/drivers/media/dvb-frontends/lnbh29.h
new file mode 100644
index 000000000000..6179921520d9
--- /dev/null
+++ b/drivers/media/dvb-frontends/lnbh29.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Driver for LNB supply and control IC STMicroelectronics LNBH29
+ *
+ * Copyright (c) 2018 Socionext Inc.
+ */
+
+#ifndef LNBH29_H
+#define LNBH29_H
+
+#include <linux/i2c.h>
+#include <linux/dvb/frontend.h>
+
+/* Using very low E.S.R. capacitors or ceramic caps */
+#define LNBH29_DATA_COMP BIT(3)
+
+struct lnbh29_config {
+ u8 i2c_address;
+ u8 data_config;
+};
+
+#if IS_REACHABLE(CONFIG_DVB_LNBH29)
+struct dvb_frontend *lnbh29_attach(struct dvb_frontend *fe,
+ struct lnbh29_config *cfg,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *lnbh29_attach(struct dvb_frontend *fe,
+ struct lnbh29_config *cfg,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index dffd2d4bf1c8..123f2a33738b 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -1284,7 +1284,7 @@ struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg,
pdata.attach_in_use = true;
memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
+ strscpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
board_info.addr = cfg->i2c_addr;
board_info.platform_data = &pdata;
client = i2c_new_device(i2c, &board_info);
diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c
index aad07adda37d..03e74a729168 100644
--- a/drivers/media/dvb-frontends/mt312.c
+++ b/drivers/media/dvb-frontends/mt312.c
@@ -815,17 +815,20 @@ struct dvb_frontend *mt312_attach(const struct mt312_config *config,
switch (state->id) {
case ID_VP310:
- strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
+ strscpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S",
+ sizeof(state->frontend.ops.info.name));
state->xtal = MT312_PLL_CLK;
state->freq_mult = 9;
break;
case ID_MT312:
- strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
+ strscpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S",
+ sizeof(state->frontend.ops.info.name));
state->xtal = MT312_PLL_CLK;
state->freq_mult = 6;
break;
case ID_ZL10313:
- strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
+ strscpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S",
+ sizeof(state->frontend.ops.info.name));
state->xtal = MT312_PLL_CLK_10_111;
state->freq_mult = 9;
break;
diff --git a/drivers/media/dvb-frontends/mxl5xx.c b/drivers/media/dvb-frontends/mxl5xx.c
index 295f37d5f10e..6191315f5970 100644
--- a/drivers/media/dvb-frontends/mxl5xx.c
+++ b/drivers/media/dvb-frontends/mxl5xx.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the MaxLinear MxL5xx family of tuners/demods
*
@@ -17,7 +18,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
*/
#include <linux/kernel.h>
@@ -739,6 +739,7 @@ static int get_frontend(struct dvb_frontend *fe,
default:
break;
}
+ /* Fall through */
case SYS_DVBS:
switch ((enum MXL_HYDRA_MODULATION_E)
reg_data[DMD_MODULATION_SCHEME_ADDR]) {
@@ -1893,4 +1894,4 @@ EXPORT_SYMBOL_GPL(mxl5xx_attach);
MODULE_DESCRIPTION("MaxLinear MxL5xx DVB-S/S2 tuner-demodulator driver");
MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/dvb-frontends/mxl5xx.h b/drivers/media/dvb-frontends/mxl5xx.h
index ad4c21846800..706a2f5d8f97 100644
--- a/drivers/media/dvb-frontends/mxl5xx.h
+++ b/drivers/media/dvb-frontends/mxl5xx.h
@@ -1,3 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Driver for the MaxLinear MxL5xx family of tuners/demods
+ *
+ * Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de>
+ * Marcus Metzler <mocm@metzlerbros.de>
+ * developed for Digital Devices GmbH
+ *
+ * based on code:
+ * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
+ * which was released under GPL V2
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
#ifndef _MXL5XX_H_
#define _MXL5XX_H_
diff --git a/drivers/media/dvb-frontends/mxl5xx_defs.h b/drivers/media/dvb-frontends/mxl5xx_defs.h
index fd9e61e0188f..1442af8dc176 100644
--- a/drivers/media/dvb-frontends/mxl5xx_defs.h
+++ b/drivers/media/dvb-frontends/mxl5xx_defs.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Defines for the Maxlinear MX58x family of tuners/demods
*
diff --git a/drivers/media/dvb-frontends/mxl5xx_regs.h b/drivers/media/dvb-frontends/mxl5xx_regs.h
index 5001dafe1ba8..86d5317eba7a 100644
--- a/drivers/media/dvb-frontends/mxl5xx_regs.h
+++ b/drivers/media/dvb-frontends/mxl5xx_regs.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
*
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index d448d9d4879c..8ef91b1598e3 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -439,8 +439,8 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
dev_dbg(&pdev->dev, "\n");
- strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
- strlcpy(cap->card, dev->vdev.name, sizeof(cap->card));
+ strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+ strscpy(cap->card, dev->vdev.name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
@@ -976,7 +976,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
dev_dbg(&pdev->dev, "index=%d type=%d\n", v->index, v->type);
if (v->index == 0) {
- strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name));
+ strscpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name));
v->type = V4L2_TUNER_ADC;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = 300000;
@@ -986,7 +986,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, g_tuner)) {
ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, g_tuner, v);
} else if (v->index == 1) {
- strlcpy(v->name, "RF: <unknown>", sizeof(v->name));
+ strscpy(v->name, "RF: <unknown>", sizeof(v->name));
v->type = V4L2_TUNER_RF;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = 50000000;
@@ -1133,7 +1133,7 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
if (f->index >= dev->num_formats)
return -EINVAL;
- strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+ strscpy(f->description, formats[f->index].name, sizeof(f->description));
f->pixelformat = formats[f->index].pixelformat;
return 0;
diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c
index a65cdf8e8cd9..c63b56f7fc14 100644
--- a/drivers/media/dvb-frontends/s5h1420.c
+++ b/drivers/media/dvb-frontends/s5h1420.c
@@ -912,7 +912,7 @@ struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
state->frontend.demodulator_priv = state;
/* create tuner i2c adapter */
- strlcpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus",
+ strscpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus",
sizeof(state->tuner_i2c_adapter.name));
state->tuner_i2c_adapter.algo = &s5h1420_tuner_i2c_algo;
state->tuner_i2c_adapter.algo_data = NULL;
diff --git a/drivers/media/dvb-frontends/stv0910.c b/drivers/media/dvb-frontends/stv0910.c
index 4c86073f1a8d..fc2440d8af36 100644
--- a/drivers/media/dvb-frontends/stv0910.c
+++ b/drivers/media/dvb-frontends/stv0910.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the ST STV0910 DVB-S/S2 demodulator.
*
@@ -1839,4 +1840,4 @@ EXPORT_SYMBOL_GPL(stv0910_attach);
MODULE_DESCRIPTION("ST STV0910 multistandard frontend driver");
MODULE_AUTHOR("Ralph and Marcus Metzler, Manfred Voelkel");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/dvb-frontends/stv0910.h b/drivers/media/dvb-frontends/stv0910.h
index f37171b7a2de..24ecc6902235 100644
--- a/drivers/media/dvb-frontends/stv0910.h
+++ b/drivers/media/dvb-frontends/stv0910.h
@@ -1,3 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Driver for the ST STV0910 DVB-S/S2 demodulator.
+ *
+ * Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de>
+ * Marcus Metzler <mocm@metzlerbros.de>
+ * developed for Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
#ifndef _STV0910_H_
#define _STV0910_H_
diff --git a/drivers/media/dvb-frontends/stv0910_regs.h b/drivers/media/dvb-frontends/stv0910_regs.h
index f0eb915090bd..448c89b8cd7c 100644
--- a/drivers/media/dvb-frontends/stv0910_regs.h
+++ b/drivers/media/dvb-frontends/stv0910_regs.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* @DVB-S/DVB-S2 STMicroelectronics STV0900 register definitions
* Author Manfred Voelkel, August 2013
diff --git a/drivers/media/dvb-frontends/stv6111.c b/drivers/media/dvb-frontends/stv6111.c
index 0cf460111acb..d5035dac4574 100644
--- a/drivers/media/dvb-frontends/stv6111.c
+++ b/drivers/media/dvb-frontends/stv6111.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the ST STV6111 tuner
*
@@ -11,7 +12,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
*/
#include <linux/kernel.h>
@@ -687,4 +687,4 @@ EXPORT_SYMBOL_GPL(stv6111_attach);
MODULE_DESCRIPTION("ST STV6111 satellite tuner driver");
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/dvb-frontends/stv6111.h b/drivers/media/dvb-frontends/stv6111.h
index 5bc1228dc9bd..49e821ac9954 100644
--- a/drivers/media/dvb-frontends/stv6111.h
+++ b/drivers/media/dvb-frontends/stv6111.h
@@ -1,3 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Driver for the ST STV6111 tuner
+ *
+ * Copyright (C) 2014 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
#ifndef _STV6111_H_
#define _STV6111_H_
diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c
index 2ad81a438d6a..849d63dbc279 100644
--- a/drivers/media/dvb-frontends/tc90522.c
+++ b/drivers/media/dvb-frontends/tc90522.c
@@ -781,7 +781,7 @@ static int tc90522_probe(struct i2c_client *client,
adap->owner = THIS_MODULE;
adap->algo = &tc90522_tuner_i2c_algo;
adap->dev.parent = &client->dev;
- strlcpy(adap->name, "tc90522_sub", sizeof(adap->name));
+ strscpy(adap->name, "tc90522_sub", sizeof(adap->name));
i2c_set_adapdata(adap, state);
ret = i2c_add_adapter(adap);
if (ret < 0)
diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c
index 3e3e40878633..e5cd2cd414f4 100644
--- a/drivers/media/dvb-frontends/ts2020.c
+++ b/drivers/media/dvb-frontends/ts2020.c
@@ -525,7 +525,7 @@ struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe,
pdata.attach_in_use = true;
memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "ts2020", I2C_NAME_SIZE);
+ strscpy(board_info.type, "ts2020", I2C_NAME_SIZE);
board_info.addr = config->tuner_address;
board_info.platform_data = &pdata;
client = i2c_new_device(i2c, &board_info);
diff --git a/drivers/media/dvb-frontends/zd1301_demod.c b/drivers/media/dvb-frontends/zd1301_demod.c
index 84a2b25a574a..212f9328cea8 100644
--- a/drivers/media/dvb-frontends/zd1301_demod.c
+++ b/drivers/media/dvb-frontends/zd1301_demod.c
@@ -499,7 +499,8 @@ static int zd1301_demod_probe(struct platform_device *pdev)
goto err_kfree;
/* Create I2C adapter */
- strlcpy(dev->adapter.name, "ZyDAS ZD1301 demod", sizeof(dev->adapter.name));
+ strscpy(dev->adapter.name, "ZyDAS ZD1301 demod",
+ sizeof(dev->adapter.name));
dev->adapter.algo = &zd1301_demod_i2c_algorithm;
dev->adapter.algo_data = NULL;
dev->adapter.dev.parent = pdev->dev.parent;
diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c
index 6293bd920fa6..333e4a1da13b 100644
--- a/drivers/media/dvb-frontends/zl10039.c
+++ b/drivers/media/dvb-frontends/zl10039.c
@@ -288,8 +288,9 @@ struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
state->id = state->id & 0x0f;
switch (state->id) {
case ID_ZL10039:
- strcpy(fe->ops.tuner_ops.info.name,
- "Zarlink ZL10039 DVB-S tuner");
+ strscpy(fe->ops.tuner_ops.info.name,
+ "Zarlink ZL10039 DVB-S tuner",
+ sizeof(fe->ops.tuner_ops.info.name));
break;
default:
dprintk("Chip ID=%x does not match a known type\n", state->id);
diff --git a/drivers/media/firewire/firedtv-fe.c b/drivers/media/firewire/firedtv-fe.c
index 69087ae6c1d0..683957885ac4 100644
--- a/drivers/media/firewire/firedtv-fe.c
+++ b/drivers/media/firewire/firedtv-fe.c
@@ -247,7 +247,7 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
dev_err(fdtv->device, "no frontend for model type %d\n",
fdtv->type);
}
- strcpy(fi->name, name);
+ strscpy(fi->name, name, sizeof(fi->name));
fdtv->fe.dvb = &fdtv->adapter;
fdtv->fe.sec_priv = fdtv;
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 82af97430e5b..704af210e270 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -614,6 +614,28 @@ config VIDEO_IMX274
This is a V4L2 sensor driver for the Sony IMX274
CMOS image sensor.
+config VIDEO_IMX319
+ tristate "Sony IMX319 sensor support"
+ depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on MEDIA_CAMERA_SUPPORT
+ help
+ This is a Video4Linux2 sensor driver for the Sony
+ IMX319 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called imx319.
+
+config VIDEO_IMX355
+ tristate "Sony IMX355 sensor support"
+ depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on MEDIA_CAMERA_SUPPORT
+ help
+ This is a Video4Linux2 sensor driver for the Sony
+ IMX355 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called imx355.
+
config VIDEO_OV2640
tristate "OmniVision OV2640 sensor support"
depends on VIDEO_V4L2 && I2C
@@ -747,6 +769,7 @@ config VIDEO_OV772X
tristate "OmniVision OV772x sensor support"
depends on I2C && VIDEO_V4L2
depends on MEDIA_CAMERA_SUPPORT
+ select REGMAP_SCCB
---help---
This is a Video4Linux2 sensor driver for the OmniVision
OV772x camera.
@@ -786,6 +809,7 @@ config VIDEO_OV7740
config VIDEO_OV9650
tristate "OmniVision OV9650/OV9652 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ select REGMAP_SCCB
---help---
This is a V4L2 sensor driver for the Omnivision
OV9650 and OV9652 camera sensors.
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index a94eb03d10d4..260d4d9ec2a1 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -108,5 +108,7 @@ obj-$(CONFIG_VIDEO_OV2659) += ov2659.o
obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
obj-$(CONFIG_VIDEO_IMX258) += imx258.o
obj-$(CONFIG_VIDEO_IMX274) += imx274.o
+obj-$(CONFIG_VIDEO_IMX319) += imx319.o
+obj-$(CONFIG_VIDEO_IMX355) += imx355.o
obj-$(CONFIG_SDR_MAX2175) += max2175.o
diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
index 034ebf754007..907323f0ca3b 100644
--- a/drivers/media/i2c/ad5820.c
+++ b/drivers/media/i2c/ad5820.c
@@ -317,7 +317,7 @@ static int ad5820_probe(struct i2c_client *client,
v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
coil->subdev.internal_ops = &ad5820_internal_ops;
- strcpy(coil->subdev.name, "ad5820 focus");
+ strscpy(coil->subdev.name, "ad5820 focus", sizeof(coil->subdev.name));
ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
if (ret < 0)
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index de10367d550b..99697baad2ea 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* adv7180.c Analog Devices ADV7180 video decoder driver
* Copyright (c) 2009 Intel Corporation
* Copyright (C) 2013 Cogent Embedded, Inc.
* Copyright (C) 2013 Renesas Solutions Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -761,7 +752,7 @@ static int adv7180_g_mbus_config(struct v4l2_subdev *sd,
struct adv7180_state *state = to_state(sd);
if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
- cfg->type = V4L2_MBUS_CSI2;
+ cfg->type = V4L2_MBUS_CSI2_DPHY;
cfg->flags = V4L2_MBUS_CSI2_1_LANE |
V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c b/drivers/media/i2c/adv748x/adv748x-afe.c
index edd25e895e5d..71714634efb0 100644
--- a/drivers/media/i2c/adv748x/adv748x-afe.c
+++ b/drivers/media/i2c/adv748x/adv748x-afe.c
@@ -1,13 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for Analog Devices ADV748X 8 channel analog front end (AFE) receiver
* with standard definition processor (SDP)
*
* Copyright (C) 2017 Renesas Electronics Corp.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
*/
#include <linux/delay.h>
@@ -286,7 +282,7 @@ static int adv748x_afe_s_stream(struct v4l2_subdev *sd, int enable)
goto unlock;
}
- ret = adv748x_txb_power(state, enable);
+ ret = adv748x_tx_power(&state->txb, enable);
if (ret)
goto unlock;
diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c
index 6ca88daa0ecd..6854d898fdd1 100644
--- a/drivers/media/i2c/adv748x/adv748x-core.c
+++ b/drivers/media/i2c/adv748x/adv748x-core.c
@@ -1,13 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for Analog Devices ADV748X HDMI receiver with AFE
*
* Copyright (C) 2017 Renesas Electronics Corp.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
* Authors:
* Koji Matsuoka <koji.matsuoka.xm@renesas.com>
* Niklas Söderlund <niklas.soderlund@ragnatech.se>
@@ -285,40 +281,23 @@ static const struct adv748x_reg_value adv748x_power_down_txb_1lane[] = {
{ADV748X_PAGE_TXB, 0x31, 0x82}, /* ADI Required Write */
{ADV748X_PAGE_TXB, 0x1e, 0x00}, /* ADI Required Write */
- {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 4-lane MIPI */
+ {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 1-lane MIPI */
{ADV748X_PAGE_TXB, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
{ADV748X_PAGE_TXB, 0xc1, 0x3b}, /* ADI Required Write */
{ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */
};
-int adv748x_txa_power(struct adv748x_state *state, bool on)
+int adv748x_tx_power(struct adv748x_csi2 *tx, bool on)
{
+ struct adv748x_state *state = tx->state;
+ const struct adv748x_reg_value *reglist;
int val;
- val = txa_read(state, ADV748X_CSI_FS_AS_LS);
- if (val < 0)
- return val;
-
- /*
- * This test against BIT(6) is not documented by the datasheet, but was
- * specified in the downstream driver.
- * Track with a WARN_ONCE to determine if it is ever set by HW.
- */
- WARN_ONCE((on && val & ADV748X_CSI_FS_AS_LS_UNKNOWN),
- "Enabling with unknown bit set");
+ if (!is_tx_enabled(tx))
+ return 0;
- if (on)
- return adv748x_write_regs(state, adv748x_power_up_txa_4lane);
-
- return adv748x_write_regs(state, adv748x_power_down_txa_4lane);
-}
-
-int adv748x_txb_power(struct adv748x_state *state, bool on)
-{
- int val;
-
- val = txb_read(state, ADV748X_CSI_FS_AS_LS);
+ val = tx_read(tx, ADV748X_CSI_FS_AS_LS);
if (val < 0)
return val;
@@ -331,9 +310,13 @@ int adv748x_txb_power(struct adv748x_state *state, bool on)
"Enabling with unknown bit set");
if (on)
- return adv748x_write_regs(state, adv748x_power_up_txb_1lane);
+ reglist = is_txa(tx) ? adv748x_power_up_txa_4lane :
+ adv748x_power_up_txb_1lane;
+ else
+ reglist = is_txa(tx) ? adv748x_power_down_txa_4lane :
+ adv748x_power_down_txb_1lane;
- return adv748x_write_regs(state, adv748x_power_down_txb_1lane);
+ return adv748x_write_regs(state, reglist);
}
/* -----------------------------------------------------------------------------
@@ -399,8 +382,6 @@ static const struct adv748x_reg_value adv748x_init_txa_4lane[] = {
{ADV748X_PAGE_IO, 0x0c, 0xe0}, /* Enable LLC_DLL & Double LLC Timing */
{ADV748X_PAGE_IO, 0x0e, 0xdd}, /* LLC/PIX/SPI PINS TRISTATED AUD */
- /* Outputs Enabled */
- {ADV748X_PAGE_IO, 0x10, 0xa0}, /* Enable 4-lane CSI Tx & Pixel Port */
{ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */
{ADV748X_PAGE_TXA, 0x00, 0xa4}, /* Set Auto DPHY Timing */
@@ -454,10 +435,6 @@ static const struct adv748x_reg_value adv748x_init_txb_1lane[] = {
{ADV748X_PAGE_SDP, 0x31, 0x12}, /* ADI Required Write */
{ADV748X_PAGE_SDP, 0xe6, 0x4f}, /* V bit end pos manually in NTSC */
- /* Enable 1-Lane MIPI Tx, */
- /* enable pixel output and route SD through Pixel port */
- {ADV748X_PAGE_IO, 0x10, 0x70},
-
{ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 1-lane MIPI */
{ADV748X_PAGE_TXB, 0x00, 0xa1}, /* Set Auto DPHY Timing */
{ADV748X_PAGE_TXB, 0xd2, 0x40}, /* ADI Required Write */
@@ -482,6 +459,7 @@ static const struct adv748x_reg_value adv748x_init_txb_1lane[] = {
static int adv748x_reset(struct adv748x_state *state)
{
int ret;
+ u8 regval = 0;
ret = adv748x_write_regs(state, adv748x_sw_reset);
if (ret < 0)
@@ -496,22 +474,24 @@ static int adv748x_reset(struct adv748x_state *state)
if (ret)
return ret;
- adv748x_txa_power(state, 0);
+ adv748x_tx_power(&state->txa, 0);
/* Init and power down TXB */
ret = adv748x_write_regs(state, adv748x_init_txb_1lane);
if (ret)
return ret;
- adv748x_txb_power(state, 0);
+ adv748x_tx_power(&state->txb, 0);
/* Disable chip powerdown & Enable HDMI Rx block */
io_write(state, ADV748X_IO_PD, ADV748X_IO_PD_RX_EN);
- /* Enable 4-lane CSI Tx & Pixel Port */
- io_write(state, ADV748X_IO_10, ADV748X_IO_10_CSI4_EN |
- ADV748X_IO_10_CSI1_EN |
- ADV748X_IO_10_PIX_OUT_EN);
+ /* Conditionally enable TXa and TXb. */
+ if (is_tx_enabled(&state->txa))
+ regval |= ADV748X_IO_10_CSI4_EN;
+ if (is_tx_enabled(&state->txb))
+ regval |= ADV748X_IO_10_CSI1_EN;
+ io_write(state, ADV748X_IO_10, regval);
/* Use vid_std and v_freq as freerun resolution for CP */
cp_clrset(state, ADV748X_CP_CLMP_POS, ADV748X_CP_CLMP_POS_DIS_AUTO,
@@ -569,7 +549,8 @@ static int adv748x_parse_dt(struct adv748x_state *state)
{
struct device_node *ep_np = NULL;
struct of_endpoint ep;
- bool found = false;
+ bool out_found = false;
+ bool in_found = false;
for_each_endpoint_of_node(state->dev->of_node, ep_np) {
of_graph_parse_endpoint(ep_np, &ep);
@@ -592,10 +573,17 @@ static int adv748x_parse_dt(struct adv748x_state *state)
of_node_get(ep_np);
state->endpoints[ep.port] = ep_np;
- found = true;
+ /*
+ * At least one input endpoint and one output endpoint shall
+ * be defined.
+ */
+ if (ep.port < ADV748X_PORT_TXA)
+ in_found = true;
+ else
+ out_found = true;
}
- return found ? 0 : -ENODEV;
+ return in_found && out_found ? 0 : -ENODEV;
}
static void adv748x_dt_cleanup(struct adv748x_state *state)
@@ -627,6 +615,17 @@ static int adv748x_probe(struct i2c_client *client,
state->i2c_clients[ADV748X_PAGE_IO] = client;
i2c_set_clientdata(client, state);
+ /*
+ * We can not use container_of to get back to the state with two TXs;
+ * Initialize the TXs's fields unconditionally on the endpoint
+ * presence to access them later.
+ */
+ state->txa.state = state->txb.state = state;
+ state->txa.page = ADV748X_PAGE_TXA;
+ state->txb.page = ADV748X_PAGE_TXB;
+ state->txa.port = ADV748X_PORT_TXA;
+ state->txb.port = ADV748X_PORT_TXB;
+
/* Discover and process ports declared by the Device tree endpoints */
ret = adv748x_parse_dt(state);
if (ret) {
@@ -755,4 +754,4 @@ module_i2c_driver(adv748x_driver);
MODULE_AUTHOR("Kieran Bingham <kieran.bingham@ideasonboard.com>");
MODULE_DESCRIPTION("ADV748X video decoder");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c
index 469be87a3761..6ce21542ed48 100644
--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
+++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for Analog Devices ADV748X CSI-2 Transmitter
*
* Copyright (C) 2017 Renesas Electronics Corp.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
*/
#include <linux/module.h>
@@ -18,11 +14,6 @@
#include "adv748x.h"
-static bool is_txa(struct adv748x_csi2 *tx)
-{
- return tx == &tx->state->txa;
-}
-
static int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx,
unsigned int vc)
{
@@ -87,15 +78,15 @@ static int adv748x_csi2_registered(struct v4l2_subdev *sd)
*
* Link HDMI->TXA, and AFE->TXB directly.
*/
- if (is_txa(tx)) {
+ if (is_txa(tx) && is_hdmi_enabled(state))
return adv748x_csi2_register_link(tx, sd->v4l2_dev,
&state->hdmi.sd,
ADV748X_HDMI_SOURCE);
- } else {
+ if (!is_txa(tx) && is_afe_enabled(state))
return adv748x_csi2_register_link(tx, sd->v4l2_dev,
&state->afe.sd,
ADV748X_AFE_SOURCE);
- }
+ return 0;
}
static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = {
@@ -266,19 +257,10 @@ static int adv748x_csi2_init_controls(struct adv748x_csi2 *tx)
int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
{
- struct device_node *ep;
int ret;
- /* We can not use container_of to get back to the state with two TXs */
- tx->state = state;
- tx->page = is_txa(tx) ? ADV748X_PAGE_TXA : ADV748X_PAGE_TXB;
-
- ep = state->endpoints[is_txa(tx) ? ADV748X_PORT_TXA : ADV748X_PORT_TXB];
- if (!ep) {
- adv_err(state, "No endpoint found for %s\n",
- is_txa(tx) ? "txa" : "txb");
- return -ENODEV;
- }
+ if (!is_tx_enabled(tx))
+ return 0;
/* Initialise the virtual channel */
adv748x_csi2_set_virtual_channel(tx, 0);
@@ -288,7 +270,7 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
is_txa(tx) ? "txa" : "txb");
/* Ensure that matching is based upon the endpoint fwnodes */
- tx->sd.fwnode = of_fwnode_handle(ep);
+ tx->sd.fwnode = of_fwnode_handle(state->endpoints[tx->port]);
/* Register internal ops for incremental subdev registration */
tx->sd.internal_ops = &adv748x_csi2_internal_ops;
@@ -321,6 +303,9 @@ err_free_media:
void adv748x_csi2_cleanup(struct adv748x_csi2 *tx)
{
+ if (!is_tx_enabled(tx))
+ return;
+
v4l2_async_unregister_subdev(&tx->sd);
media_entity_cleanup(&tx->sd.entity);
v4l2_ctrl_handler_free(&tx->ctrl_hdl);
diff --git a/drivers/media/i2c/adv748x/adv748x-hdmi.c b/drivers/media/i2c/adv748x/adv748x-hdmi.c
index aecc2a84dfec..35d027941482 100644
--- a/drivers/media/i2c/adv748x/adv748x-hdmi.c
+++ b/drivers/media/i2c/adv748x/adv748x-hdmi.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for Analog Devices ADV748X HDMI receiver and Component Processor (CP)
*
* Copyright (C) 2017 Renesas Electronics Corp.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
*/
#include <linux/module.h>
@@ -362,7 +358,7 @@ static int adv748x_hdmi_s_stream(struct v4l2_subdev *sd, int enable)
mutex_lock(&state->mutex);
- ret = adv748x_txa_power(state, enable);
+ ret = adv748x_tx_power(&state->txa, enable);
if (ret)
goto done;
diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h
index 65f83741277e..39c2fdc3b416 100644
--- a/drivers/media/i2c/adv748x/adv748x.h
+++ b/drivers/media/i2c/adv748x/adv748x.h
@@ -1,13 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Driver for Analog Devices ADV748X video decoder and HDMI receiver
*
* Copyright (C) 2017 Renesas Electronics Corp.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
* Authors:
* Koji Matsuoka <koji.matsuoka.xm@renesas.com>
* Niklas Söderlund <niklas.soderlund@ragnatech.se>
@@ -82,6 +78,7 @@ struct adv748x_csi2 {
struct adv748x_state *state;
struct v4l2_mbus_framefmt format;
unsigned int page;
+ unsigned int port;
struct media_pad pads[ADV748X_CSI2_NR_PADS];
struct v4l2_ctrl_handler ctrl_hdl;
@@ -91,6 +88,18 @@ struct adv748x_csi2 {
#define notifier_to_csi2(n) container_of(n, struct adv748x_csi2, notifier)
#define adv748x_sd_to_csi2(sd) container_of(sd, struct adv748x_csi2, sd)
+#define is_tx_enabled(_tx) ((_tx)->state->endpoints[(_tx)->port] != NULL)
+#define is_txa(_tx) ((_tx) == &(_tx)->state->txa)
+#define is_afe_enabled(_state) \
+ ((_state)->endpoints[ADV748X_PORT_AIN0] != NULL || \
+ (_state)->endpoints[ADV748X_PORT_AIN1] != NULL || \
+ (_state)->endpoints[ADV748X_PORT_AIN2] != NULL || \
+ (_state)->endpoints[ADV748X_PORT_AIN3] != NULL || \
+ (_state)->endpoints[ADV748X_PORT_AIN4] != NULL || \
+ (_state)->endpoints[ADV748X_PORT_AIN5] != NULL || \
+ (_state)->endpoints[ADV748X_PORT_AIN6] != NULL || \
+ (_state)->endpoints[ADV748X_PORT_AIN7] != NULL)
+#define is_hdmi_enabled(_state) ((_state)->endpoints[ADV748X_PORT_HDMI] != NULL)
enum adv748x_hdmi_pads {
ADV748X_HDMI_SINK,
@@ -376,9 +385,6 @@ int adv748x_write_block(struct adv748x_state *state, int client_page,
#define cp_write(s, r, v) adv748x_write(s, ADV748X_PAGE_CP, r, v)
#define cp_clrset(s, r, m, v) cp_write(s, r, (cp_read(s, r) & ~m) | v)
-#define txa_read(s, r) adv748x_read(s, ADV748X_PAGE_TXA, r)
-#define txb_read(s, r) adv748x_read(s, ADV748X_PAGE_TXB, r)
-
#define tx_read(t, r) adv748x_read(t->state, t->page, r)
#define tx_write(t, r, v) adv748x_write(t->state, t->page, r, v)
@@ -398,8 +404,7 @@ void adv748x_subdev_init(struct v4l2_subdev *sd, struct adv748x_state *state,
int adv748x_register_subdevs(struct adv748x_state *state,
struct v4l2_device *v4l2_dev);
-int adv748x_txa_power(struct adv748x_state *state, bool on);
-int adv748x_txb_power(struct adv748x_state *state, bool on);
+int adv748x_tx_power(struct adv748x_csi2 *tx, bool on);
int adv748x_afe_init(struct adv748x_afe *afe);
void adv748x_afe_cleanup(struct adv748x_afe *afe);
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index 55c2ea0720d9..f3899cc84e27 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -1355,10 +1355,10 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd,
state->xfer_func = format->format.xfer_func;
switch (format->format.colorspace) {
- case V4L2_COLORSPACE_ADOBERGB:
+ case V4L2_COLORSPACE_OPRGB:
c = HDMI_COLORIMETRY_EXTENDED;
- ec = y ? HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601 :
- HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB;
+ ec = y ? HDMI_EXTENDED_COLORIMETRY_OPYCC_601 :
+ HDMI_EXTENDED_COLORIMETRY_OPRGB;
break;
case V4L2_COLORSPACE_SMPTE170M:
c = y ? HDMI_COLORIMETRY_ITU_601 : HDMI_COLORIMETRY_NONE;
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 668be2bca57a..9eb7c70a7712 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2284,8 +2284,10 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
state->aspect_ratio.numerator = 16;
state->aspect_ratio.denominator = 9;
- if (!state->edid.present)
+ if (!state->edid.present) {
state->edid.blocks = 0;
+ cec_phys_addr_invalidate(state->cec_adap);
+ }
v4l2_dbg(2, debug, sd, "%s: clear EDID pad %d, edid.present = 0x%x\n",
__func__, edid->pad, state->edid.present);
@@ -2295,8 +2297,8 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
edid->blocks = 2;
return -E2BIG;
}
- pa = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, &spa_loc);
- err = cec_phys_addr_validate(pa, &pa, NULL);
+ pa = v4l2_get_edid_phys_addr(edid->edid, edid->blocks * 128, &spa_loc);
+ err = v4l2_phys_addr_validate(pa, &pa, NULL);
if (err)
return err;
@@ -2474,7 +2476,7 @@ static int adv76xx_log_status(struct v4l2_subdev *sd)
"YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)",
"xvYCC Bt.601", "xvYCC Bt.709",
"YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)",
- "sYCC", "Adobe YCC 601", "AdobeRGB", "invalid", "invalid",
+ "sYCC", "opYCC 601", "opRGB", "invalid", "invalid",
"invalid", "invalid", "invalid"
};
static const char * const rgb_quantization_range_txt[] = {
@@ -3093,7 +3095,7 @@ MODULE_DEVICE_TABLE(of, adv76xx_of_id);
static int adv76xx_parse_dt(struct adv76xx_state *state)
{
- struct v4l2_fwnode_endpoint bus_cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct device_node *endpoint;
struct device_node *np;
unsigned int flags;
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 4f8fbdd00e35..4721d49dcf0f 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -786,11 +786,13 @@ static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port)
/* Disable I2C access to internal EDID ram from HDMI DDC ports */
rep_write_and_or(sd, 0x77, 0xf3, 0x00);
- if (!state->hdmi_edid.present)
+ if (!state->hdmi_edid.present) {
+ cec_phys_addr_invalidate(state->cec_adap);
return 0;
+ }
- pa = cec_get_edid_phys_addr(edid, 256, &spa_loc);
- err = cec_phys_addr_validate(pa, &pa, NULL);
+ pa = v4l2_get_edid_phys_addr(edid, 256, &spa_loc);
+ err = v4l2_phys_addr_validate(pa, &pa, NULL);
if (err)
return err;
@@ -1525,6 +1527,7 @@ static void adv7842_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
v4l2_find_dv_timings_cap(timings, adv7842_get_dv_timings_cap(sd),
is_digital_input(sd) ? 250000 : 1000000,
adv7842_check_dv_timings, NULL);
+ timings->bt.flags |= V4L2_DV_FL_CAN_DETECT_REDUCED_FPS;
}
static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
@@ -1596,6 +1599,14 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
bt->il_vbackporch = 0;
}
adv7842_fill_optional_dv_timings_fields(sd, timings);
+ if ((timings->bt.flags & V4L2_DV_FL_CAN_REDUCE_FPS) &&
+ freq < bt->pixelclock) {
+ u32 reduced_freq = ((u32)bt->pixelclock / 1001) * 1000;
+ u32 delta_freq = abs(freq - reduced_freq);
+
+ if (delta_freq < ((u32)bt->pixelclock - reduced_freq) / 2)
+ timings->bt.flags |= V4L2_DV_FL_REDUCED_FPS;
+ }
} else {
/* find format
* Since LCVS values are inaccurate [REF_03, p. 339-340],
diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c
index 16682c8477d1..30f9db1351b9 100644
--- a/drivers/media/i2c/ak881x.c
+++ b/drivers/media/i2c/ak881x.c
@@ -136,7 +136,6 @@ static int ak881x_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = 0;
sel->r.top = 0;
sel->r.width = 720;
diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c
index fd70fe2130a1..ef4bdbae4531 100644
--- a/drivers/media/i2c/cs53l32a.c
+++ b/drivers/media/i2c/cs53l32a.c
@@ -149,7 +149,7 @@ static int cs53l32a_probe(struct i2c_client *client,
return -EIO;
if (!id)
- strlcpy(client->name, "cs53l32a", sizeof(client->name));
+ strscpy(client->name, "cs53l32a", sizeof(client->name));
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c
index ad7f66c7aac8..69cdc09981af 100644
--- a/drivers/media/i2c/cx25840/cx25840-ir.c
+++ b/drivers/media/i2c/cx25840/cx25840-ir.c
@@ -701,10 +701,8 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
if (v > IR_MAX_DURATION)
v = IR_MAX_DURATION;
- init_ir_raw_event(&p->ir_core_data);
- p->ir_core_data.pulse = u;
- p->ir_core_data.duration = v;
- p->ir_core_data.timeout = w;
+ p->ir_core_data = (struct ir_raw_event)
+ { .pulse = u, .duration = v, .timeout = w };
v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns %s %s\n",
v, u ? "mark" : "space", w ? "(timed out)" : "");
diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c
index 91fae01d052b..26d83693a681 100644
--- a/drivers/media/i2c/dw9714.c
+++ b/drivers/media/i2c/dw9714.c
@@ -169,8 +169,9 @@ static int dw9714_probe(struct i2c_client *client)
return 0;
err_cleanup:
- dw9714_subdev_cleanup(dw9714_dev);
- dev_err(&client->dev, "Probe failed: %d\n", rval);
+ v4l2_ctrl_handler_free(&dw9714_dev->ctrls_vcm);
+ media_entity_cleanup(&dw9714_dev->sd.entity);
+
return rval;
}
diff --git a/drivers/media/i2c/dw9807-vcm.c b/drivers/media/i2c/dw9807-vcm.c
index 8ba3920b6e2f..b38a4e6d270d 100644
--- a/drivers/media/i2c/dw9807-vcm.c
+++ b/drivers/media/i2c/dw9807-vcm.c
@@ -218,7 +218,8 @@ static int dw9807_probe(struct i2c_client *client)
return 0;
err_cleanup:
- dw9807_subdev_cleanup(dw9807_dev);
+ v4l2_ctrl_handler_free(&dw9807_dev->ctrls_vcm);
+ media_entity_cleanup(&dw9807_dev->sd.entity);
return rval;
}
@@ -229,7 +230,6 @@ static int dw9807_remove(struct i2c_client *client)
struct dw9807_device *dw9807_dev = sd_to_dw9807_vcm(sd);
pm_runtime_disable(&client->dev);
- pm_runtime_set_suspended(&client->dev);
dw9807_subdev_cleanup(dw9807_dev);
diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c
index f8c70f1a34fe..11c69281692e 100644
--- a/drivers/media/i2c/imx274.c
+++ b/drivers/media/i2c/imx274.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* imx274.c - IMX274 CMOS Image Sensor driver
*
@@ -6,18 +7,6 @@
* Leon Luo <leonl@leopardimaging.com>
* Edwin Zou <edwinz@leopardimaging.com>
* Luca Ceresoli <luca@lucaceresoli.net>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk.h>
@@ -76,7 +65,7 @@
*/
#define IMX274_MIN_EXPOSURE_TIME (4 * 260 / 72)
-#define IMX274_DEFAULT_MODE IMX274_BINNING_OFF
+#define IMX274_DEFAULT_BINNING IMX274_BINNING_OFF
#define IMX274_MAX_WIDTH (3840)
#define IMX274_MAX_HEIGHT (2160)
#define IMX274_MAX_FRAME_RATE (120)
@@ -178,7 +167,7 @@ enum imx274_binning {
* @nocpiop: Number of clocks per internal offset period (see "Integration Time
* in Each Readout Drive Mode (CSI-2)" in the datasheet)
*/
-struct imx274_frmfmt {
+struct imx274_mode {
const struct reg_8 *init_regs;
unsigned int bin_ratio;
int min_frame_len;
@@ -349,20 +338,14 @@ static const struct reg_8 imx274_mode5_1280x720_raw10[] = {
*/
static const struct reg_8 imx274_start_1[] = {
{IMX274_STANDBY_REG, 0x12},
- {IMX274_TABLE_END, 0x00}
-};
-/*
- * imx274 second step register configuration for
- * starting stream
- */
-static const struct reg_8 imx274_start_2[] = {
- {0x3120, 0xF0}, /* clock settings */
- {0x3121, 0x00}, /* clock settings */
- {0x3122, 0x02}, /* clock settings */
- {0x3129, 0x9C}, /* clock settings */
- {0x312A, 0x02}, /* clock settings */
- {0x312D, 0x02}, /* clock settings */
+ /* PLRD: clock settings */
+ {0x3120, 0xF0},
+ {0x3121, 0x00},
+ {0x3122, 0x02},
+ {0x3129, 0x9C},
+ {0x312A, 0x02},
+ {0x312D, 0x02},
{0x310B, 0x00},
@@ -407,20 +390,20 @@ static const struct reg_8 imx274_start_2[] = {
};
/*
- * imx274 third step register configuration for
+ * imx274 second step register configuration for
* starting stream
*/
-static const struct reg_8 imx274_start_3[] = {
+static const struct reg_8 imx274_start_2[] = {
{IMX274_STANDBY_REG, 0x00},
{0x303E, 0x02}, /* SYS_MODE = 2 */
{IMX274_TABLE_END, 0x00}
};
/*
- * imx274 forth step register configuration for
+ * imx274 third step register configuration for
* starting stream
*/
-static const struct reg_8 imx274_start_4[] = {
+static const struct reg_8 imx274_start_3[] = {
{0x30F4, 0x00},
{0x3018, 0xA2}, /* XHS VHS OUTUPT */
{IMX274_TABLE_END, 0x00}
@@ -459,7 +442,7 @@ static const struct reg_8 imx274_tp_regs[] = {
};
/* nocpiop happens to be the same number for the implemented modes */
-static const struct imx274_frmfmt imx274_formats[] = {
+static const struct imx274_mode imx274_modes[] = {
{
/* mode 1, 4K */
.bin_ratio = 1,
@@ -532,7 +515,7 @@ struct stimx274 {
struct regmap *regmap;
struct gpio_desc *reset_gpio;
struct mutex lock; /* mutex lock for operations */
- const struct imx274_frmfmt *mode;
+ const struct imx274_mode *mode;
};
#define IMX274_ROUND(dim, step, flags) \
@@ -666,6 +649,41 @@ static inline int imx274_write_reg(struct stimx274 *priv, u16 addr, u8 val)
}
/**
+ * Read a multibyte register.
+ *
+ * Uses a bulk read where possible.
+ *
+ * @priv: Pointer to device structure
+ * @addr: Address of the LSB register. Other registers must be
+ * consecutive, least-to-most significant.
+ * @val: Pointer to store the register value (cpu endianness)
+ * @nbytes: Number of bytes to read (range: [1..3]).
+ * Other bytes are zet to 0.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int imx274_read_mbreg(struct stimx274 *priv, u16 addr, u32 *val,
+ size_t nbytes)
+{
+ __le32 val_le = 0;
+ int err;
+
+ err = regmap_bulk_read(priv->regmap, addr, &val_le, nbytes);
+ if (err) {
+ dev_err(&priv->client->dev,
+ "%s : i2c bulk read failed, %x (%zu bytes)\n",
+ __func__, addr, nbytes);
+ } else {
+ *val = le32_to_cpu(val_le);
+ dev_dbg(&priv->client->dev,
+ "%s : addr 0x%x, val=0x%x (%zu bytes)\n",
+ __func__, addr, *val, nbytes);
+ }
+
+ return err;
+}
+
+/**
* Write a multibyte register.
*
* Uses a bulk write where possible.
@@ -674,7 +692,7 @@ static inline int imx274_write_reg(struct stimx274 *priv, u16 addr, u8 val)
* @addr: Address of the LSB register. Other registers must be
* consecutive, least-to-most significant.
* @val: Value to be written to the register (cpu endianness)
- * @nbytes: Number of bits to write (range: [1..3])
+ * @nbytes: Number of bytes to write (range: [1..3])
*/
static int imx274_write_mbreg(struct stimx274 *priv, u16 addr, u32 val,
size_t nbytes)
@@ -708,10 +726,6 @@ static int imx274_mode_regs(struct stimx274 *priv)
if (err)
return err;
- err = imx274_write_table(priv, imx274_start_2);
- if (err)
- return err;
-
err = imx274_write_table(priv, priv->mode->init_regs);
return err;
@@ -733,7 +747,7 @@ static int imx274_start_stream(struct stimx274 *priv)
* give it 1 extra ms for margin
*/
msleep_range(11);
- err = imx274_write_table(priv, imx274_start_3);
+ err = imx274_write_table(priv, imx274_start_2);
if (err)
return err;
@@ -743,7 +757,7 @@ static int imx274_start_stream(struct stimx274 *priv)
* give it 1 extra ms for margin
*/
msleep_range(8);
- err = imx274_write_table(priv, imx274_start_4);
+ err = imx274_write_table(priv, imx274_start_3);
if (err)
return err;
@@ -881,7 +895,7 @@ static int __imx274_change_compose(struct stimx274 *imx274,
const struct v4l2_rect *cur_crop;
struct v4l2_mbus_framefmt *tgt_fmt;
unsigned int i;
- const struct imx274_frmfmt *best_mode = &imx274_formats[0];
+ const struct imx274_mode *best_mode = &imx274_modes[0];
int best_goodness = INT_MIN;
if (which == V4L2_SUBDEV_FORMAT_TRY) {
@@ -892,8 +906,8 @@ static int __imx274_change_compose(struct stimx274 *imx274,
tgt_fmt = &imx274->format;
}
- for (i = 0; i < ARRAY_SIZE(imx274_formats); i++) {
- unsigned int ratio = imx274_formats[i].bin_ratio;
+ for (i = 0; i < ARRAY_SIZE(imx274_modes); i++) {
+ unsigned int ratio = imx274_modes[i].bin_ratio;
int goodness = imx274_binning_goodness(
imx274,
@@ -903,7 +917,7 @@ static int __imx274_change_compose(struct stimx274 *imx274,
if (goodness >= best_goodness) {
best_goodness = goodness;
- best_mode = &imx274_formats[i];
+ best_mode = &imx274_modes[i];
}
}
@@ -1323,7 +1337,7 @@ static int imx274_s_stream(struct v4l2_subdev *sd, int on)
dev_dbg(&imx274->client->dev, "%s : %s, mode index = %td\n", __func__,
on ? "Stream Start" : "Stream Stop",
- imx274->mode - &imx274_formats[0]);
+ imx274->mode - &imx274_modes[0]);
mutex_lock(&imx274->lock);
@@ -1387,37 +1401,17 @@ fail:
static int imx274_get_frame_length(struct stimx274 *priv, u32 *val)
{
int err;
- u16 svr;
+ u32 svr;
u32 vmax;
- u8 reg_val[3];
-
- /* svr */
- err = imx274_read_reg(priv, IMX274_SVR_REG_LSB, &reg_val[0]);
- if (err)
- goto fail;
- err = imx274_read_reg(priv, IMX274_SVR_REG_MSB, &reg_val[1]);
+ err = imx274_read_mbreg(priv, IMX274_SVR_REG_LSB, &svr, 2);
if (err)
goto fail;
- svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
-
- /* vmax */
- err = imx274_read_reg(priv, IMX274_VMAX_REG_3, &reg_val[0]);
+ err = imx274_read_mbreg(priv, IMX274_VMAX_REG_3, &vmax, 3);
if (err)
goto fail;
- err = imx274_read_reg(priv, IMX274_VMAX_REG_2, &reg_val[1]);
- if (err)
- goto fail;
-
- err = imx274_read_reg(priv, IMX274_VMAX_REG_1, &reg_val[2]);
- if (err)
- goto fail;
-
- vmax = ((reg_val[2] & IMX274_MASK_LSB_3_BITS) << IMX274_SHIFT_16_BITS)
- + (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
-
*val = vmax * (svr + 1);
return 0;
@@ -1598,8 +1592,7 @@ fail:
static int imx274_set_exposure(struct stimx274 *priv, int val)
{
int err;
- u16 hmax;
- u8 reg_val[2];
+ u32 hmax;
u32 coarse_time; /* exposure time in unit of line (HMAX)*/
dev_dbg(&priv->client->dev,
@@ -1607,14 +1600,10 @@ static int imx274_set_exposure(struct stimx274 *priv, int val)
/* step 1: convert input exposure_time (val) into number of 1[HMAX] */
- /* obtain HMAX value */
- err = imx274_read_reg(priv, IMX274_HMAX_REG_LSB, &reg_val[0]);
- if (err)
- goto fail;
- err = imx274_read_reg(priv, IMX274_HMAX_REG_MSB, &reg_val[1]);
+ err = imx274_read_mbreg(priv, IMX274_HMAX_REG_LSB, &hmax, 2);
if (err)
goto fail;
- hmax = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
+
if (hmax == 0) {
err = -EINVAL;
goto fail;
@@ -1749,9 +1738,8 @@ static int imx274_set_frame_interval(struct stimx274 *priv,
{
int err;
u32 frame_length, req_frame_rate;
- u16 svr;
- u16 hmax;
- u8 reg_val[2];
+ u32 svr;
+ u32 hmax;
dev_dbg(&priv->client->dev, "%s: input frame interval = %d / %d",
__func__, frame_interval.numerator,
@@ -1779,25 +1767,17 @@ static int imx274_set_frame_interval(struct stimx274 *priv,
* frame_length (i.e. VMAX) = (frame_interval) x 72M /(SVR+1) / HMAX
*/
- /* SVR */
- err = imx274_read_reg(priv, IMX274_SVR_REG_LSB, &reg_val[0]);
- if (err)
- goto fail;
- err = imx274_read_reg(priv, IMX274_SVR_REG_MSB, &reg_val[1]);
+ err = imx274_read_mbreg(priv, IMX274_SVR_REG_LSB, &svr, 2);
if (err)
goto fail;
- svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
+
dev_dbg(&priv->client->dev,
"%s : register SVR = %d\n", __func__, svr);
- /* HMAX */
- err = imx274_read_reg(priv, IMX274_HMAX_REG_LSB, &reg_val[0]);
- if (err)
- goto fail;
- err = imx274_read_reg(priv, IMX274_HMAX_REG_MSB, &reg_val[1]);
+ err = imx274_read_mbreg(priv, IMX274_HMAX_REG_LSB, &hmax, 2);
if (err)
goto fail;
- hmax = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
+
dev_dbg(&priv->client->dev,
"%s : register HMAX = %d\n", __func__, hmax);
@@ -1871,7 +1851,7 @@ static int imx274_probe(struct i2c_client *client,
mutex_init(&imx274->lock);
/* initialize format */
- imx274->mode = &imx274_formats[IMX274_DEFAULT_MODE];
+ imx274->mode = &imx274_modes[IMX274_DEFAULT_BINNING];
imx274->crop.width = IMX274_MAX_WIDTH;
imx274->crop.height = IMX274_MAX_HEIGHT;
imx274->format.width = imx274->crop.width / imx274->mode->bin_ratio;
@@ -1895,7 +1875,6 @@ static int imx274_probe(struct i2c_client *client,
imx274->client = client;
sd = &imx274->sd;
v4l2_i2c_subdev_init(sd, client, &imx274_subdev_ops);
- strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name));
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
/* initialize subdev media pad */
diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c
new file mode 100644
index 000000000000..0d3e27812b93
--- /dev/null
+++ b/drivers/media/i2c/imx319.c
@@ -0,0 +1,2560 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Intel Corporation
+
+#include <asm/unaligned.h>
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+
+#define IMX319_REG_MODE_SELECT 0x0100
+#define IMX319_MODE_STANDBY 0x00
+#define IMX319_MODE_STREAMING 0x01
+
+/* Chip ID */
+#define IMX319_REG_CHIP_ID 0x0016
+#define IMX319_CHIP_ID 0x0319
+
+/* V_TIMING internal */
+#define IMX319_REG_FLL 0x0340
+#define IMX319_FLL_MAX 0xffff
+
+/* Exposure control */
+#define IMX319_REG_EXPOSURE 0x0202
+#define IMX319_EXPOSURE_MIN 1
+#define IMX319_EXPOSURE_STEP 1
+#define IMX319_EXPOSURE_DEFAULT 0x04f6
+
+/*
+ * the digital control register for all color control looks like:
+ * +-----------------+------------------+
+ * | [7:0] | [15:8] |
+ * +-----------------+------------------+
+ * | 0x020f | 0x020e |
+ * --------------------------------------
+ * it is used to calculate the digital gain times value(integral + fractional)
+ * the [15:8] bits is the fractional part and [7:0] bits is the integral
+ * calculation equation is:
+ * gain value (unit: times) = REG[15:8] + REG[7:0]/0x100
+ * Only value in 0x0100 ~ 0x0FFF range is allowed.
+ * Analog gain use 10 bits in the registers and allowed range is 0 ~ 960
+ */
+/* Analog gain control */
+#define IMX319_REG_ANALOG_GAIN 0x0204
+#define IMX319_ANA_GAIN_MIN 0
+#define IMX319_ANA_GAIN_MAX 960
+#define IMX319_ANA_GAIN_STEP 1
+#define IMX319_ANA_GAIN_DEFAULT 0
+
+/* Digital gain control */
+#define IMX319_REG_DPGA_USE_GLOBAL_GAIN 0x3ff9
+#define IMX319_REG_DIG_GAIN_GLOBAL 0x020e
+#define IMX319_DGTL_GAIN_MIN 256
+#define IMX319_DGTL_GAIN_MAX 4095
+#define IMX319_DGTL_GAIN_STEP 1
+#define IMX319_DGTL_GAIN_DEFAULT 256
+
+/* Test Pattern Control */
+#define IMX319_REG_TEST_PATTERN 0x0600
+#define IMX319_TEST_PATTERN_DISABLED 0
+#define IMX319_TEST_PATTERN_SOLID_COLOR 1
+#define IMX319_TEST_PATTERN_COLOR_BARS 2
+#define IMX319_TEST_PATTERN_GRAY_COLOR_BARS 3
+#define IMX319_TEST_PATTERN_PN9 4
+
+/* Flip Control */
+#define IMX319_REG_ORIENTATION 0x0101
+
+/* default link frequency and external clock */
+#define IMX319_LINK_FREQ_DEFAULT 482400000
+#define IMX319_EXT_CLK 19200000
+#define IMX319_LINK_FREQ_INDEX 0
+
+struct imx319_reg {
+ u16 address;
+ u8 val;
+};
+
+struct imx319_reg_list {
+ u32 num_of_regs;
+ const struct imx319_reg *regs;
+};
+
+/* Mode : resolution and related config&values */
+struct imx319_mode {
+ /* Frame width */
+ u32 width;
+ /* Frame height */
+ u32 height;
+
+ /* V-timing */
+ u32 fll_def;
+ u32 fll_min;
+
+ /* H-timing */
+ u32 llp;
+
+ /* index of link frequency */
+ u32 link_freq_index;
+
+ /* Default register values */
+ struct imx319_reg_list reg_list;
+};
+
+struct imx319_hwcfg {
+ u32 ext_clk; /* sensor external clk */
+ s64 *link_freqs; /* CSI-2 link frequencies */
+ unsigned int nr_of_link_freqs;
+};
+
+struct imx319 {
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+
+ struct v4l2_ctrl_handler ctrl_handler;
+ /* V4L2 Controls */
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *exposure;
+ struct v4l2_ctrl *vflip;
+ struct v4l2_ctrl *hflip;
+
+ /* Current mode */
+ const struct imx319_mode *cur_mode;
+
+ struct imx319_hwcfg *hwcfg;
+ s64 link_def_freq; /* CSI-2 link default frequency */
+
+ /*
+ * Mutex for serialized access:
+ * Protect sensor set pad format and start/stop streaming safely.
+ * Protect access to sensor v4l2 controls.
+ */
+ struct mutex mutex;
+
+ /* Streaming on/off */
+ bool streaming;
+};
+
+static const struct imx319_reg imx319_global_regs[] = {
+ { 0x0136, 0x13 },
+ { 0x0137, 0x33 },
+ { 0x3c7e, 0x05 },
+ { 0x3c7f, 0x07 },
+ { 0x4d39, 0x0b },
+ { 0x4d41, 0x33 },
+ { 0x4d43, 0x0c },
+ { 0x4d49, 0x89 },
+ { 0x4e05, 0x0b },
+ { 0x4e0d, 0x33 },
+ { 0x4e0f, 0x0c },
+ { 0x4e15, 0x89 },
+ { 0x4e49, 0x2a },
+ { 0x4e51, 0x33 },
+ { 0x4e53, 0x0c },
+ { 0x4e59, 0x89 },
+ { 0x5601, 0x4f },
+ { 0x560b, 0x45 },
+ { 0x562f, 0x0a },
+ { 0x5643, 0x0a },
+ { 0x5645, 0x0c },
+ { 0x56ef, 0x51 },
+ { 0x586f, 0x33 },
+ { 0x5873, 0x89 },
+ { 0x5905, 0x33 },
+ { 0x5907, 0x89 },
+ { 0x590d, 0x33 },
+ { 0x590f, 0x89 },
+ { 0x5915, 0x33 },
+ { 0x5917, 0x89 },
+ { 0x5969, 0x1c },
+ { 0x596b, 0x72 },
+ { 0x5971, 0x33 },
+ { 0x5973, 0x89 },
+ { 0x5975, 0x33 },
+ { 0x5977, 0x89 },
+ { 0x5979, 0x1c },
+ { 0x597b, 0x72 },
+ { 0x5985, 0x33 },
+ { 0x5987, 0x89 },
+ { 0x5999, 0x1c },
+ { 0x599b, 0x72 },
+ { 0x59a5, 0x33 },
+ { 0x59a7, 0x89 },
+ { 0x7485, 0x08 },
+ { 0x7487, 0x0c },
+ { 0x7489, 0xc7 },
+ { 0x748b, 0x8b },
+ { 0x9004, 0x09 },
+ { 0x9200, 0x6a },
+ { 0x9201, 0x22 },
+ { 0x9202, 0x6a },
+ { 0x9203, 0x23 },
+ { 0x9204, 0x5f },
+ { 0x9205, 0x23 },
+ { 0x9206, 0x5f },
+ { 0x9207, 0x24 },
+ { 0x9208, 0x5f },
+ { 0x9209, 0x26 },
+ { 0x920a, 0x5f },
+ { 0x920b, 0x27 },
+ { 0x920c, 0x5f },
+ { 0x920d, 0x29 },
+ { 0x920e, 0x5f },
+ { 0x920f, 0x2a },
+ { 0x9210, 0x5f },
+ { 0x9211, 0x2c },
+ { 0xbc22, 0x1a },
+ { 0xf01f, 0x04 },
+ { 0xf021, 0x03 },
+ { 0xf023, 0x02 },
+ { 0xf03d, 0x05 },
+ { 0xf03f, 0x03 },
+ { 0xf041, 0x02 },
+ { 0xf0af, 0x04 },
+ { 0xf0b1, 0x03 },
+ { 0xf0b3, 0x02 },
+ { 0xf0cd, 0x05 },
+ { 0xf0cf, 0x03 },
+ { 0xf0d1, 0x02 },
+ { 0xf13f, 0x04 },
+ { 0xf141, 0x03 },
+ { 0xf143, 0x02 },
+ { 0xf15d, 0x05 },
+ { 0xf15f, 0x03 },
+ { 0xf161, 0x02 },
+ { 0xf1cf, 0x04 },
+ { 0xf1d1, 0x03 },
+ { 0xf1d3, 0x02 },
+ { 0xf1ed, 0x05 },
+ { 0xf1ef, 0x03 },
+ { 0xf1f1, 0x02 },
+ { 0xf287, 0x04 },
+ { 0xf289, 0x03 },
+ { 0xf28b, 0x02 },
+ { 0xf2a5, 0x05 },
+ { 0xf2a7, 0x03 },
+ { 0xf2a9, 0x02 },
+ { 0xf2b7, 0x04 },
+ { 0xf2b9, 0x03 },
+ { 0xf2bb, 0x02 },
+ { 0xf2d5, 0x05 },
+ { 0xf2d7, 0x03 },
+ { 0xf2d9, 0x02 },
+};
+
+static const struct imx319_reg_list imx319_global_setting = {
+ .num_of_regs = ARRAY_SIZE(imx319_global_regs),
+ .regs = imx319_global_regs,
+};
+
+static const struct imx319_reg mode_3264x2448_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0f },
+ { 0x0343, 0x80 },
+ { 0x0340, 0x0c },
+ { 0x0341, 0xaa },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x09 },
+ { 0x034b, 0x9f },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x11 },
+ { 0x0381, 0x01 },
+ { 0x0383, 0x01 },
+ { 0x0385, 0x01 },
+ { 0x0387, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x0a },
+ { 0x3140, 0x02 },
+ { 0x3141, 0x00 },
+ { 0x3f0d, 0x0a },
+ { 0x3f14, 0x01 },
+ { 0x3f3c, 0x01 },
+ { 0x3f4d, 0x01 },
+ { 0x3f4c, 0x01 },
+ { 0x4254, 0x7f },
+ { 0x0401, 0x00 },
+ { 0x0404, 0x00 },
+ { 0x0405, 0x10 },
+ { 0x0408, 0x00 },
+ { 0x0409, 0x08 },
+ { 0x040a, 0x00 },
+ { 0x040b, 0x08 },
+ { 0x040c, 0x0c },
+ { 0x040d, 0xc0 },
+ { 0x040e, 0x09 },
+ { 0x040f, 0x90 },
+ { 0x034c, 0x0c },
+ { 0x034d, 0xc0 },
+ { 0x034e, 0x09 },
+ { 0x034f, 0x90 },
+ { 0x3261, 0x00 },
+ { 0x3264, 0x00 },
+ { 0x3265, 0x10 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x04 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x01 },
+ { 0x0307, 0x92 },
+ { 0x0309, 0x0a },
+ { 0x030b, 0x02 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0xfa },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x0f },
+ { 0x0821, 0x13 },
+ { 0x0822, 0x33 },
+ { 0x0823, 0x33 },
+ { 0x3e20, 0x01 },
+ { 0x3e37, 0x00 },
+ { 0x3e3b, 0x01 },
+ { 0x38a3, 0x01 },
+ { 0x38a8, 0x00 },
+ { 0x38a9, 0x00 },
+ { 0x38aa, 0x00 },
+ { 0x38ab, 0x00 },
+ { 0x3234, 0x00 },
+ { 0x3fc1, 0x00 },
+ { 0x3235, 0x00 },
+ { 0x3802, 0x00 },
+ { 0x3143, 0x04 },
+ { 0x360a, 0x00 },
+ { 0x0b00, 0x00 },
+ { 0x0106, 0x00 },
+ { 0x0b05, 0x01 },
+ { 0x0b06, 0x01 },
+ { 0x3230, 0x00 },
+ { 0x3602, 0x01 },
+ { 0x3607, 0x01 },
+ { 0x3c00, 0x00 },
+ { 0x3c01, 0x48 },
+ { 0x3c02, 0xc8 },
+ { 0x3c03, 0xaa },
+ { 0x3c04, 0x91 },
+ { 0x3c05, 0x54 },
+ { 0x3c06, 0x26 },
+ { 0x3c07, 0x20 },
+ { 0x3c08, 0x51 },
+ { 0x3d80, 0x00 },
+ { 0x3f50, 0x00 },
+ { 0x3f56, 0x00 },
+ { 0x3f57, 0x30 },
+ { 0x3f78, 0x01 },
+ { 0x3f79, 0x18 },
+ { 0x3f7c, 0x00 },
+ { 0x3f7d, 0x00 },
+ { 0x3fba, 0x00 },
+ { 0x3fbb, 0x00 },
+ { 0xa081, 0x00 },
+ { 0xe014, 0x00 },
+ { 0x0202, 0x0a },
+ { 0x0203, 0x7a },
+ { 0x0224, 0x01 },
+ { 0x0225, 0xf4 },
+ { 0x0204, 0x00 },
+ { 0x0205, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x020e, 0x01 },
+ { 0x020f, 0x00 },
+ { 0x0210, 0x01 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x01 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x01 },
+ { 0x0215, 0x00 },
+ { 0x0218, 0x01 },
+ { 0x0219, 0x00 },
+ { 0x3614, 0x00 },
+ { 0x3616, 0x0d },
+ { 0x3617, 0x56 },
+ { 0xb612, 0x20 },
+ { 0xb613, 0x20 },
+ { 0xb614, 0x20 },
+ { 0xb615, 0x20 },
+ { 0xb616, 0x0a },
+ { 0xb617, 0x0a },
+ { 0xb618, 0x20 },
+ { 0xb619, 0x20 },
+ { 0xb61a, 0x20 },
+ { 0xb61b, 0x20 },
+ { 0xb61c, 0x0a },
+ { 0xb61d, 0x0a },
+ { 0xb666, 0x30 },
+ { 0xb667, 0x30 },
+ { 0xb668, 0x30 },
+ { 0xb669, 0x30 },
+ { 0xb66a, 0x14 },
+ { 0xb66b, 0x14 },
+ { 0xb66c, 0x20 },
+ { 0xb66d, 0x20 },
+ { 0xb66e, 0x20 },
+ { 0xb66f, 0x20 },
+ { 0xb670, 0x10 },
+ { 0xb671, 0x10 },
+ { 0x3237, 0x00 },
+ { 0x3900, 0x00 },
+ { 0x3901, 0x00 },
+ { 0x3902, 0x00 },
+ { 0x3904, 0x00 },
+ { 0x3905, 0x00 },
+ { 0x3906, 0x00 },
+ { 0x3907, 0x00 },
+ { 0x3908, 0x00 },
+ { 0x3909, 0x00 },
+ { 0x3912, 0x00 },
+ { 0x3930, 0x00 },
+ { 0x3931, 0x00 },
+ { 0x3933, 0x00 },
+ { 0x3934, 0x00 },
+ { 0x3935, 0x00 },
+ { 0x3936, 0x00 },
+ { 0x3937, 0x00 },
+ { 0x30ac, 0x00 },
+};
+
+static const struct imx319_reg mode_3280x2464_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0f },
+ { 0x0343, 0x80 },
+ { 0x0340, 0x0c },
+ { 0x0341, 0xaa },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x09 },
+ { 0x034b, 0x9f },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x11 },
+ { 0x0381, 0x01 },
+ { 0x0383, 0x01 },
+ { 0x0385, 0x01 },
+ { 0x0387, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x0a },
+ { 0x3140, 0x02 },
+ { 0x3141, 0x00 },
+ { 0x3f0d, 0x0a },
+ { 0x3f14, 0x01 },
+ { 0x3f3c, 0x01 },
+ { 0x3f4d, 0x01 },
+ { 0x3f4c, 0x01 },
+ { 0x4254, 0x7f },
+ { 0x0401, 0x00 },
+ { 0x0404, 0x00 },
+ { 0x0405, 0x10 },
+ { 0x0408, 0x00 },
+ { 0x0409, 0x00 },
+ { 0x040a, 0x00 },
+ { 0x040b, 0x00 },
+ { 0x040c, 0x0c },
+ { 0x040d, 0xd0 },
+ { 0x040e, 0x09 },
+ { 0x040f, 0xa0 },
+ { 0x034c, 0x0c },
+ { 0x034d, 0xd0 },
+ { 0x034e, 0x09 },
+ { 0x034f, 0xa0 },
+ { 0x3261, 0x00 },
+ { 0x3264, 0x00 },
+ { 0x3265, 0x10 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x04 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x01 },
+ { 0x0307, 0x92 },
+ { 0x0309, 0x0a },
+ { 0x030b, 0x02 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0xfa },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x0f },
+ { 0x0821, 0x13 },
+ { 0x0822, 0x33 },
+ { 0x0823, 0x33 },
+ { 0x3e20, 0x01 },
+ { 0x3e37, 0x00 },
+ { 0x3e3b, 0x01 },
+ { 0x38a3, 0x01 },
+ { 0x38a8, 0x00 },
+ { 0x38a9, 0x00 },
+ { 0x38aa, 0x00 },
+ { 0x38ab, 0x00 },
+ { 0x3234, 0x00 },
+ { 0x3fc1, 0x00 },
+ { 0x3235, 0x00 },
+ { 0x3802, 0x00 },
+ { 0x3143, 0x04 },
+ { 0x360a, 0x00 },
+ { 0x0b00, 0x00 },
+ { 0x0106, 0x00 },
+ { 0x0b05, 0x01 },
+ { 0x0b06, 0x01 },
+ { 0x3230, 0x00 },
+ { 0x3602, 0x01 },
+ { 0x3607, 0x01 },
+ { 0x3c00, 0x00 },
+ { 0x3c01, 0x48 },
+ { 0x3c02, 0xc8 },
+ { 0x3c03, 0xaa },
+ { 0x3c04, 0x91 },
+ { 0x3c05, 0x54 },
+ { 0x3c06, 0x26 },
+ { 0x3c07, 0x20 },
+ { 0x3c08, 0x51 },
+ { 0x3d80, 0x00 },
+ { 0x3f50, 0x00 },
+ { 0x3f56, 0x00 },
+ { 0x3f57, 0x30 },
+ { 0x3f78, 0x01 },
+ { 0x3f79, 0x18 },
+ { 0x3f7c, 0x00 },
+ { 0x3f7d, 0x00 },
+ { 0x3fba, 0x00 },
+ { 0x3fbb, 0x00 },
+ { 0xa081, 0x00 },
+ { 0xe014, 0x00 },
+ { 0x0202, 0x0a },
+ { 0x0203, 0x7a },
+ { 0x0224, 0x01 },
+ { 0x0225, 0xf4 },
+ { 0x0204, 0x00 },
+ { 0x0205, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x020e, 0x01 },
+ { 0x020f, 0x00 },
+ { 0x0210, 0x01 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x01 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x01 },
+ { 0x0215, 0x00 },
+ { 0x0218, 0x01 },
+ { 0x0219, 0x00 },
+ { 0x3614, 0x00 },
+ { 0x3616, 0x0d },
+ { 0x3617, 0x56 },
+ { 0xb612, 0x20 },
+ { 0xb613, 0x20 },
+ { 0xb614, 0x20 },
+ { 0xb615, 0x20 },
+ { 0xb616, 0x0a },
+ { 0xb617, 0x0a },
+ { 0xb618, 0x20 },
+ { 0xb619, 0x20 },
+ { 0xb61a, 0x20 },
+ { 0xb61b, 0x20 },
+ { 0xb61c, 0x0a },
+ { 0xb61d, 0x0a },
+ { 0xb666, 0x30 },
+ { 0xb667, 0x30 },
+ { 0xb668, 0x30 },
+ { 0xb669, 0x30 },
+ { 0xb66a, 0x14 },
+ { 0xb66b, 0x14 },
+ { 0xb66c, 0x20 },
+ { 0xb66d, 0x20 },
+ { 0xb66e, 0x20 },
+ { 0xb66f, 0x20 },
+ { 0xb670, 0x10 },
+ { 0xb671, 0x10 },
+ { 0x3237, 0x00 },
+ { 0x3900, 0x00 },
+ { 0x3901, 0x00 },
+ { 0x3902, 0x00 },
+ { 0x3904, 0x00 },
+ { 0x3905, 0x00 },
+ { 0x3906, 0x00 },
+ { 0x3907, 0x00 },
+ { 0x3908, 0x00 },
+ { 0x3909, 0x00 },
+ { 0x3912, 0x00 },
+ { 0x3930, 0x00 },
+ { 0x3931, 0x00 },
+ { 0x3933, 0x00 },
+ { 0x3934, 0x00 },
+ { 0x3935, 0x00 },
+ { 0x3936, 0x00 },
+ { 0x3937, 0x00 },
+ { 0x30ac, 0x00 },
+};
+
+static const struct imx319_reg mode_1936x1096_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0f },
+ { 0x0343, 0x80 },
+ { 0x0340, 0x0c },
+ { 0x0341, 0xaa },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x02 },
+ { 0x0347, 0xac },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x06 },
+ { 0x034b, 0xf3 },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x11 },
+ { 0x0381, 0x01 },
+ { 0x0383, 0x01 },
+ { 0x0385, 0x01 },
+ { 0x0387, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x0a },
+ { 0x3140, 0x02 },
+ { 0x3141, 0x00 },
+ { 0x3f0d, 0x0a },
+ { 0x3f14, 0x01 },
+ { 0x3f3c, 0x01 },
+ { 0x3f4d, 0x01 },
+ { 0x3f4c, 0x01 },
+ { 0x4254, 0x7f },
+ { 0x0401, 0x00 },
+ { 0x0404, 0x00 },
+ { 0x0405, 0x10 },
+ { 0x0408, 0x02 },
+ { 0x0409, 0xa0 },
+ { 0x040a, 0x00 },
+ { 0x040b, 0x00 },
+ { 0x040c, 0x07 },
+ { 0x040d, 0x90 },
+ { 0x040e, 0x04 },
+ { 0x040f, 0x48 },
+ { 0x034c, 0x07 },
+ { 0x034d, 0x90 },
+ { 0x034e, 0x04 },
+ { 0x034f, 0x48 },
+ { 0x3261, 0x00 },
+ { 0x3264, 0x00 },
+ { 0x3265, 0x10 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x04 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x01 },
+ { 0x0307, 0x92 },
+ { 0x0309, 0x0a },
+ { 0x030b, 0x02 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0xfa },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x0f },
+ { 0x0821, 0x13 },
+ { 0x0822, 0x33 },
+ { 0x0823, 0x33 },
+ { 0x3e20, 0x01 },
+ { 0x3e37, 0x00 },
+ { 0x3e3b, 0x01 },
+ { 0x38a3, 0x01 },
+ { 0x38a8, 0x00 },
+ { 0x38a9, 0x00 },
+ { 0x38aa, 0x00 },
+ { 0x38ab, 0x00 },
+ { 0x3234, 0x00 },
+ { 0x3fc1, 0x00 },
+ { 0x3235, 0x00 },
+ { 0x3802, 0x00 },
+ { 0x3143, 0x04 },
+ { 0x360a, 0x00 },
+ { 0x0b00, 0x00 },
+ { 0x0106, 0x00 },
+ { 0x0b05, 0x01 },
+ { 0x0b06, 0x01 },
+ { 0x3230, 0x00 },
+ { 0x3602, 0x01 },
+ { 0x3607, 0x01 },
+ { 0x3c00, 0x00 },
+ { 0x3c01, 0x48 },
+ { 0x3c02, 0xc8 },
+ { 0x3c03, 0xaa },
+ { 0x3c04, 0x91 },
+ { 0x3c05, 0x54 },
+ { 0x3c06, 0x26 },
+ { 0x3c07, 0x20 },
+ { 0x3c08, 0x51 },
+ { 0x3d80, 0x00 },
+ { 0x3f50, 0x00 },
+ { 0x3f56, 0x00 },
+ { 0x3f57, 0x30 },
+ { 0x3f78, 0x01 },
+ { 0x3f79, 0x18 },
+ { 0x3f7c, 0x00 },
+ { 0x3f7d, 0x00 },
+ { 0x3fba, 0x00 },
+ { 0x3fbb, 0x00 },
+ { 0xa081, 0x00 },
+ { 0xe014, 0x00 },
+ { 0x0202, 0x05 },
+ { 0x0203, 0x34 },
+ { 0x0224, 0x01 },
+ { 0x0225, 0xf4 },
+ { 0x0204, 0x00 },
+ { 0x0205, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x020e, 0x01 },
+ { 0x020f, 0x00 },
+ { 0x0210, 0x01 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x01 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x01 },
+ { 0x0215, 0x00 },
+ { 0x0218, 0x01 },
+ { 0x0219, 0x00 },
+ { 0x3614, 0x00 },
+ { 0x3616, 0x0d },
+ { 0x3617, 0x56 },
+ { 0xb612, 0x20 },
+ { 0xb613, 0x20 },
+ { 0xb614, 0x20 },
+ { 0xb615, 0x20 },
+ { 0xb616, 0x0a },
+ { 0xb617, 0x0a },
+ { 0xb618, 0x20 },
+ { 0xb619, 0x20 },
+ { 0xb61a, 0x20 },
+ { 0xb61b, 0x20 },
+ { 0xb61c, 0x0a },
+ { 0xb61d, 0x0a },
+ { 0xb666, 0x30 },
+ { 0xb667, 0x30 },
+ { 0xb668, 0x30 },
+ { 0xb669, 0x30 },
+ { 0xb66a, 0x14 },
+ { 0xb66b, 0x14 },
+ { 0xb66c, 0x20 },
+ { 0xb66d, 0x20 },
+ { 0xb66e, 0x20 },
+ { 0xb66f, 0x20 },
+ { 0xb670, 0x10 },
+ { 0xb671, 0x10 },
+ { 0x3237, 0x00 },
+ { 0x3900, 0x00 },
+ { 0x3901, 0x00 },
+ { 0x3902, 0x00 },
+ { 0x3904, 0x00 },
+ { 0x3905, 0x00 },
+ { 0x3906, 0x00 },
+ { 0x3907, 0x00 },
+ { 0x3908, 0x00 },
+ { 0x3909, 0x00 },
+ { 0x3912, 0x00 },
+ { 0x3930, 0x00 },
+ { 0x3931, 0x00 },
+ { 0x3933, 0x00 },
+ { 0x3934, 0x00 },
+ { 0x3935, 0x00 },
+ { 0x3936, 0x00 },
+ { 0x3937, 0x00 },
+ { 0x30ac, 0x00 },
+};
+
+static const struct imx319_reg mode_1920x1080_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0f },
+ { 0x0343, 0x80 },
+ { 0x0340, 0x0c },
+ { 0x0341, 0xaa },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x02 },
+ { 0x0347, 0xb4 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x06 },
+ { 0x034b, 0xeb },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x11 },
+ { 0x0381, 0x01 },
+ { 0x0383, 0x01 },
+ { 0x0385, 0x01 },
+ { 0x0387, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x0a },
+ { 0x3140, 0x02 },
+ { 0x3141, 0x00 },
+ { 0x3f0d, 0x0a },
+ { 0x3f14, 0x01 },
+ { 0x3f3c, 0x01 },
+ { 0x3f4d, 0x01 },
+ { 0x3f4c, 0x01 },
+ { 0x4254, 0x7f },
+ { 0x0401, 0x00 },
+ { 0x0404, 0x00 },
+ { 0x0405, 0x10 },
+ { 0x0408, 0x02 },
+ { 0x0409, 0xa8 },
+ { 0x040a, 0x00 },
+ { 0x040b, 0x00 },
+ { 0x040c, 0x07 },
+ { 0x040d, 0x80 },
+ { 0x040e, 0x04 },
+ { 0x040f, 0x38 },
+ { 0x034c, 0x07 },
+ { 0x034d, 0x80 },
+ { 0x034e, 0x04 },
+ { 0x034f, 0x38 },
+ { 0x3261, 0x00 },
+ { 0x3264, 0x00 },
+ { 0x3265, 0x10 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x04 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x01 },
+ { 0x0307, 0x92 },
+ { 0x0309, 0x0a },
+ { 0x030b, 0x02 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0xfa },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x0f },
+ { 0x0821, 0x13 },
+ { 0x0822, 0x33 },
+ { 0x0823, 0x33 },
+ { 0x3e20, 0x01 },
+ { 0x3e37, 0x00 },
+ { 0x3e3b, 0x01 },
+ { 0x38a3, 0x01 },
+ { 0x38a8, 0x00 },
+ { 0x38a9, 0x00 },
+ { 0x38aa, 0x00 },
+ { 0x38ab, 0x00 },
+ { 0x3234, 0x00 },
+ { 0x3fc1, 0x00 },
+ { 0x3235, 0x00 },
+ { 0x3802, 0x00 },
+ { 0x3143, 0x04 },
+ { 0x360a, 0x00 },
+ { 0x0b00, 0x00 },
+ { 0x0106, 0x00 },
+ { 0x0b05, 0x01 },
+ { 0x0b06, 0x01 },
+ { 0x3230, 0x00 },
+ { 0x3602, 0x01 },
+ { 0x3607, 0x01 },
+ { 0x3c00, 0x00 },
+ { 0x3c01, 0x48 },
+ { 0x3c02, 0xc8 },
+ { 0x3c03, 0xaa },
+ { 0x3c04, 0x91 },
+ { 0x3c05, 0x54 },
+ { 0x3c06, 0x26 },
+ { 0x3c07, 0x20 },
+ { 0x3c08, 0x51 },
+ { 0x3d80, 0x00 },
+ { 0x3f50, 0x00 },
+ { 0x3f56, 0x00 },
+ { 0x3f57, 0x30 },
+ { 0x3f78, 0x01 },
+ { 0x3f79, 0x18 },
+ { 0x3f7c, 0x00 },
+ { 0x3f7d, 0x00 },
+ { 0x3fba, 0x00 },
+ { 0x3fbb, 0x00 },
+ { 0xa081, 0x00 },
+ { 0xe014, 0x00 },
+ { 0x0202, 0x05 },
+ { 0x0203, 0x34 },
+ { 0x0224, 0x01 },
+ { 0x0225, 0xf4 },
+ { 0x0204, 0x00 },
+ { 0x0205, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x020e, 0x01 },
+ { 0x020f, 0x00 },
+ { 0x0210, 0x01 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x01 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x01 },
+ { 0x0215, 0x00 },
+ { 0x0218, 0x01 },
+ { 0x0219, 0x00 },
+ { 0x3614, 0x00 },
+ { 0x3616, 0x0d },
+ { 0x3617, 0x56 },
+ { 0xb612, 0x20 },
+ { 0xb613, 0x20 },
+ { 0xb614, 0x20 },
+ { 0xb615, 0x20 },
+ { 0xb616, 0x0a },
+ { 0xb617, 0x0a },
+ { 0xb618, 0x20 },
+ { 0xb619, 0x20 },
+ { 0xb61a, 0x20 },
+ { 0xb61b, 0x20 },
+ { 0xb61c, 0x0a },
+ { 0xb61d, 0x0a },
+ { 0xb666, 0x30 },
+ { 0xb667, 0x30 },
+ { 0xb668, 0x30 },
+ { 0xb669, 0x30 },
+ { 0xb66a, 0x14 },
+ { 0xb66b, 0x14 },
+ { 0xb66c, 0x20 },
+ { 0xb66d, 0x20 },
+ { 0xb66e, 0x20 },
+ { 0xb66f, 0x20 },
+ { 0xb670, 0x10 },
+ { 0xb671, 0x10 },
+ { 0x3237, 0x00 },
+ { 0x3900, 0x00 },
+ { 0x3901, 0x00 },
+ { 0x3902, 0x00 },
+ { 0x3904, 0x00 },
+ { 0x3905, 0x00 },
+ { 0x3906, 0x00 },
+ { 0x3907, 0x00 },
+ { 0x3908, 0x00 },
+ { 0x3909, 0x00 },
+ { 0x3912, 0x00 },
+ { 0x3930, 0x00 },
+ { 0x3931, 0x00 },
+ { 0x3933, 0x00 },
+ { 0x3934, 0x00 },
+ { 0x3935, 0x00 },
+ { 0x3936, 0x00 },
+ { 0x3937, 0x00 },
+ { 0x30ac, 0x00 },
+};
+
+static const struct imx319_reg mode_1640x1232_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x08 },
+ { 0x0343, 0x20 },
+ { 0x0340, 0x18 },
+ { 0x0341, 0x2a },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x09 },
+ { 0x034b, 0x9f },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x11 },
+ { 0x0381, 0x01 },
+ { 0x0383, 0x01 },
+ { 0x0385, 0x01 },
+ { 0x0387, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x0a },
+ { 0x3140, 0x02 },
+ { 0x3141, 0x00 },
+ { 0x3f0d, 0x0a },
+ { 0x3f14, 0x01 },
+ { 0x3f3c, 0x02 },
+ { 0x3f4d, 0x01 },
+ { 0x3f4c, 0x01 },
+ { 0x4254, 0x7f },
+ { 0x0401, 0x00 },
+ { 0x0404, 0x00 },
+ { 0x0405, 0x10 },
+ { 0x0408, 0x00 },
+ { 0x0409, 0x00 },
+ { 0x040a, 0x00 },
+ { 0x040b, 0x00 },
+ { 0x040c, 0x06 },
+ { 0x040d, 0x68 },
+ { 0x040e, 0x04 },
+ { 0x040f, 0xd0 },
+ { 0x034c, 0x06 },
+ { 0x034d, 0x68 },
+ { 0x034e, 0x04 },
+ { 0x034f, 0xd0 },
+ { 0x3261, 0x00 },
+ { 0x3264, 0x00 },
+ { 0x3265, 0x10 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x04 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x01 },
+ { 0x0307, 0x92 },
+ { 0x0309, 0x0a },
+ { 0x030b, 0x02 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0xfa },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x0f },
+ { 0x0821, 0x13 },
+ { 0x0822, 0x33 },
+ { 0x0823, 0x33 },
+ { 0x3e20, 0x01 },
+ { 0x3e37, 0x00 },
+ { 0x3e3b, 0x01 },
+ { 0x38a3, 0x01 },
+ { 0x38a8, 0x00 },
+ { 0x38a9, 0x00 },
+ { 0x38aa, 0x00 },
+ { 0x38ab, 0x00 },
+ { 0x3234, 0x00 },
+ { 0x3fc1, 0x00 },
+ { 0x3235, 0x00 },
+ { 0x3802, 0x00 },
+ { 0x3143, 0x04 },
+ { 0x360a, 0x00 },
+ { 0x0b00, 0x00 },
+ { 0x0106, 0x00 },
+ { 0x0b05, 0x01 },
+ { 0x0b06, 0x01 },
+ { 0x3230, 0x00 },
+ { 0x3602, 0x01 },
+ { 0x3607, 0x01 },
+ { 0x3c00, 0x00 },
+ { 0x3c01, 0xba },
+ { 0x3c02, 0xc8 },
+ { 0x3c03, 0xaa },
+ { 0x3c04, 0x91 },
+ { 0x3c05, 0x54 },
+ { 0x3c06, 0x26 },
+ { 0x3c07, 0x20 },
+ { 0x3c08, 0x51 },
+ { 0x3d80, 0x00 },
+ { 0x3f50, 0x00 },
+ { 0x3f56, 0x00 },
+ { 0x3f57, 0x30 },
+ { 0x3f78, 0x00 },
+ { 0x3f79, 0x34 },
+ { 0x3f7c, 0x00 },
+ { 0x3f7d, 0x00 },
+ { 0x3fba, 0x00 },
+ { 0x3fbb, 0x00 },
+ { 0xa081, 0x04 },
+ { 0xe014, 0x00 },
+ { 0x0202, 0x04 },
+ { 0x0203, 0xf6 },
+ { 0x0224, 0x01 },
+ { 0x0225, 0xf4 },
+ { 0x0204, 0x00 },
+ { 0x0205, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x020e, 0x01 },
+ { 0x020f, 0x00 },
+ { 0x0210, 0x01 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x01 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x01 },
+ { 0x0215, 0x00 },
+ { 0x0218, 0x01 },
+ { 0x0219, 0x00 },
+ { 0x3614, 0x00 },
+ { 0x3616, 0x0d },
+ { 0x3617, 0x56 },
+ { 0xb612, 0x20 },
+ { 0xb613, 0x20 },
+ { 0xb614, 0x20 },
+ { 0xb615, 0x20 },
+ { 0xb616, 0x0a },
+ { 0xb617, 0x0a },
+ { 0xb618, 0x20 },
+ { 0xb619, 0x20 },
+ { 0xb61a, 0x20 },
+ { 0xb61b, 0x20 },
+ { 0xb61c, 0x0a },
+ { 0xb61d, 0x0a },
+ { 0xb666, 0x30 },
+ { 0xb667, 0x30 },
+ { 0xb668, 0x30 },
+ { 0xb669, 0x30 },
+ { 0xb66a, 0x14 },
+ { 0xb66b, 0x14 },
+ { 0xb66c, 0x20 },
+ { 0xb66d, 0x20 },
+ { 0xb66e, 0x20 },
+ { 0xb66f, 0x20 },
+ { 0xb670, 0x10 },
+ { 0xb671, 0x10 },
+ { 0x3237, 0x00 },
+ { 0x3900, 0x00 },
+ { 0x3901, 0x00 },
+ { 0x3902, 0x00 },
+ { 0x3904, 0x00 },
+ { 0x3905, 0x00 },
+ { 0x3906, 0x00 },
+ { 0x3907, 0x00 },
+ { 0x3908, 0x00 },
+ { 0x3909, 0x00 },
+ { 0x3912, 0x00 },
+ { 0x3930, 0x00 },
+ { 0x3931, 0x00 },
+ { 0x3933, 0x00 },
+ { 0x3934, 0x00 },
+ { 0x3935, 0x00 },
+ { 0x3936, 0x00 },
+ { 0x3937, 0x00 },
+ { 0x30ac, 0x00 },
+};
+
+static const struct imx319_reg mode_1640x922_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x08 },
+ { 0x0343, 0x20 },
+ { 0x0340, 0x18 },
+ { 0x0341, 0x2a },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x01 },
+ { 0x0347, 0x30 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x08 },
+ { 0x034b, 0x6f },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x11 },
+ { 0x0381, 0x01 },
+ { 0x0383, 0x01 },
+ { 0x0385, 0x01 },
+ { 0x0387, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x0a },
+ { 0x3140, 0x02 },
+ { 0x3141, 0x00 },
+ { 0x3f0d, 0x0a },
+ { 0x3f14, 0x01 },
+ { 0x3f3c, 0x02 },
+ { 0x3f4d, 0x01 },
+ { 0x3f4c, 0x01 },
+ { 0x4254, 0x7f },
+ { 0x0401, 0x00 },
+ { 0x0404, 0x00 },
+ { 0x0405, 0x10 },
+ { 0x0408, 0x00 },
+ { 0x0409, 0x00 },
+ { 0x040a, 0x00 },
+ { 0x040b, 0x02 },
+ { 0x040c, 0x06 },
+ { 0x040d, 0x68 },
+ { 0x040e, 0x03 },
+ { 0x040f, 0x9a },
+ { 0x034c, 0x06 },
+ { 0x034d, 0x68 },
+ { 0x034e, 0x03 },
+ { 0x034f, 0x9a },
+ { 0x3261, 0x00 },
+ { 0x3264, 0x00 },
+ { 0x3265, 0x10 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x04 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x01 },
+ { 0x0307, 0x92 },
+ { 0x0309, 0x0a },
+ { 0x030b, 0x02 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0xfa },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x0f },
+ { 0x0821, 0x13 },
+ { 0x0822, 0x33 },
+ { 0x0823, 0x33 },
+ { 0x3e20, 0x01 },
+ { 0x3e37, 0x00 },
+ { 0x3e3b, 0x01 },
+ { 0x38a3, 0x01 },
+ { 0x38a8, 0x00 },
+ { 0x38a9, 0x00 },
+ { 0x38aa, 0x00 },
+ { 0x38ab, 0x00 },
+ { 0x3234, 0x00 },
+ { 0x3fc1, 0x00 },
+ { 0x3235, 0x00 },
+ { 0x3802, 0x00 },
+ { 0x3143, 0x04 },
+ { 0x360a, 0x00 },
+ { 0x0b00, 0x00 },
+ { 0x0106, 0x00 },
+ { 0x0b05, 0x01 },
+ { 0x0b06, 0x01 },
+ { 0x3230, 0x00 },
+ { 0x3602, 0x01 },
+ { 0x3607, 0x01 },
+ { 0x3c00, 0x00 },
+ { 0x3c01, 0xba },
+ { 0x3c02, 0xc8 },
+ { 0x3c03, 0xaa },
+ { 0x3c04, 0x91 },
+ { 0x3c05, 0x54 },
+ { 0x3c06, 0x26 },
+ { 0x3c07, 0x20 },
+ { 0x3c08, 0x51 },
+ { 0x3d80, 0x00 },
+ { 0x3f50, 0x00 },
+ { 0x3f56, 0x00 },
+ { 0x3f57, 0x30 },
+ { 0x3f78, 0x00 },
+ { 0x3f79, 0x34 },
+ { 0x3f7c, 0x00 },
+ { 0x3f7d, 0x00 },
+ { 0x3fba, 0x00 },
+ { 0x3fbb, 0x00 },
+ { 0xa081, 0x04 },
+ { 0xe014, 0x00 },
+ { 0x0202, 0x04 },
+ { 0x0203, 0xf6 },
+ { 0x0224, 0x01 },
+ { 0x0225, 0xf4 },
+ { 0x0204, 0x00 },
+ { 0x0205, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x020e, 0x01 },
+ { 0x020f, 0x00 },
+ { 0x0210, 0x01 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x01 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x01 },
+ { 0x0215, 0x00 },
+ { 0x0218, 0x01 },
+ { 0x0219, 0x00 },
+ { 0x3614, 0x00 },
+ { 0x3616, 0x0d },
+ { 0x3617, 0x56 },
+ { 0xb612, 0x20 },
+ { 0xb613, 0x20 },
+ { 0xb614, 0x20 },
+ { 0xb615, 0x20 },
+ { 0xb616, 0x0a },
+ { 0xb617, 0x0a },
+ { 0xb618, 0x20 },
+ { 0xb619, 0x20 },
+ { 0xb61a, 0x20 },
+ { 0xb61b, 0x20 },
+ { 0xb61c, 0x0a },
+ { 0xb61d, 0x0a },
+ { 0xb666, 0x30 },
+ { 0xb667, 0x30 },
+ { 0xb668, 0x30 },
+ { 0xb669, 0x30 },
+ { 0xb66a, 0x14 },
+ { 0xb66b, 0x14 },
+ { 0xb66c, 0x20 },
+ { 0xb66d, 0x20 },
+ { 0xb66e, 0x20 },
+ { 0xb66f, 0x20 },
+ { 0xb670, 0x10 },
+ { 0xb671, 0x10 },
+ { 0x3237, 0x00 },
+ { 0x3900, 0x00 },
+ { 0x3901, 0x00 },
+ { 0x3902, 0x00 },
+ { 0x3904, 0x00 },
+ { 0x3905, 0x00 },
+ { 0x3906, 0x00 },
+ { 0x3907, 0x00 },
+ { 0x3908, 0x00 },
+ { 0x3909, 0x00 },
+ { 0x3912, 0x00 },
+ { 0x3930, 0x00 },
+ { 0x3931, 0x00 },
+ { 0x3933, 0x00 },
+ { 0x3934, 0x00 },
+ { 0x3935, 0x00 },
+ { 0x3936, 0x00 },
+ { 0x3937, 0x00 },
+ { 0x30ac, 0x00 },
+};
+
+static const struct imx319_reg mode_1296x736_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x08 },
+ { 0x0343, 0x20 },
+ { 0x0340, 0x18 },
+ { 0x0341, 0x2a },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x01 },
+ { 0x0347, 0xf0 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x07 },
+ { 0x034b, 0xaf },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x11 },
+ { 0x0381, 0x01 },
+ { 0x0383, 0x01 },
+ { 0x0385, 0x01 },
+ { 0x0387, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x0a },
+ { 0x3140, 0x02 },
+ { 0x3141, 0x00 },
+ { 0x3f0d, 0x0a },
+ { 0x3f14, 0x01 },
+ { 0x3f3c, 0x02 },
+ { 0x3f4d, 0x01 },
+ { 0x3f4c, 0x01 },
+ { 0x4254, 0x7f },
+ { 0x0401, 0x00 },
+ { 0x0404, 0x00 },
+ { 0x0405, 0x10 },
+ { 0x0408, 0x00 },
+ { 0x0409, 0xac },
+ { 0x040a, 0x00 },
+ { 0x040b, 0x00 },
+ { 0x040c, 0x05 },
+ { 0x040d, 0x10 },
+ { 0x040e, 0x02 },
+ { 0x040f, 0xe0 },
+ { 0x034c, 0x05 },
+ { 0x034d, 0x10 },
+ { 0x034e, 0x02 },
+ { 0x034f, 0xe0 },
+ { 0x3261, 0x00 },
+ { 0x3264, 0x00 },
+ { 0x3265, 0x10 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x04 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x01 },
+ { 0x0307, 0x92 },
+ { 0x0309, 0x0a },
+ { 0x030b, 0x02 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0xfa },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x0f },
+ { 0x0821, 0x13 },
+ { 0x0822, 0x33 },
+ { 0x0823, 0x33 },
+ { 0x3e20, 0x01 },
+ { 0x3e37, 0x00 },
+ { 0x3e3b, 0x01 },
+ { 0x38a3, 0x01 },
+ { 0x38a8, 0x00 },
+ { 0x38a9, 0x00 },
+ { 0x38aa, 0x00 },
+ { 0x38ab, 0x00 },
+ { 0x3234, 0x00 },
+ { 0x3fc1, 0x00 },
+ { 0x3235, 0x00 },
+ { 0x3802, 0x00 },
+ { 0x3143, 0x04 },
+ { 0x360a, 0x00 },
+ { 0x0b00, 0x00 },
+ { 0x0106, 0x00 },
+ { 0x0b05, 0x01 },
+ { 0x0b06, 0x01 },
+ { 0x3230, 0x00 },
+ { 0x3602, 0x01 },
+ { 0x3607, 0x01 },
+ { 0x3c00, 0x00 },
+ { 0x3c01, 0xba },
+ { 0x3c02, 0xc8 },
+ { 0x3c03, 0xaa },
+ { 0x3c04, 0x91 },
+ { 0x3c05, 0x54 },
+ { 0x3c06, 0x26 },
+ { 0x3c07, 0x20 },
+ { 0x3c08, 0x51 },
+ { 0x3d80, 0x00 },
+ { 0x3f50, 0x00 },
+ { 0x3f56, 0x00 },
+ { 0x3f57, 0x30 },
+ { 0x3f78, 0x00 },
+ { 0x3f79, 0x34 },
+ { 0x3f7c, 0x00 },
+ { 0x3f7d, 0x00 },
+ { 0x3fba, 0x00 },
+ { 0x3fbb, 0x00 },
+ { 0xa081, 0x04 },
+ { 0xe014, 0x00 },
+ { 0x0202, 0x04 },
+ { 0x0203, 0xf6 },
+ { 0x0224, 0x01 },
+ { 0x0225, 0xf4 },
+ { 0x0204, 0x00 },
+ { 0x0205, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x020e, 0x01 },
+ { 0x020f, 0x00 },
+ { 0x0210, 0x01 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x01 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x01 },
+ { 0x0215, 0x00 },
+ { 0x0218, 0x01 },
+ { 0x0219, 0x00 },
+ { 0x3614, 0x00 },
+ { 0x3616, 0x0d },
+ { 0x3617, 0x56 },
+ { 0xb612, 0x20 },
+ { 0xb613, 0x20 },
+ { 0xb614, 0x20 },
+ { 0xb615, 0x20 },
+ { 0xb616, 0x0a },
+ { 0xb617, 0x0a },
+ { 0xb618, 0x20 },
+ { 0xb619, 0x20 },
+ { 0xb61a, 0x20 },
+ { 0xb61b, 0x20 },
+ { 0xb61c, 0x0a },
+ { 0xb61d, 0x0a },
+ { 0xb666, 0x30 },
+ { 0xb667, 0x30 },
+ { 0xb668, 0x30 },
+ { 0xb669, 0x30 },
+ { 0xb66a, 0x14 },
+ { 0xb66b, 0x14 },
+ { 0xb66c, 0x20 },
+ { 0xb66d, 0x20 },
+ { 0xb66e, 0x20 },
+ { 0xb66f, 0x20 },
+ { 0xb670, 0x10 },
+ { 0xb671, 0x10 },
+ { 0x3237, 0x00 },
+ { 0x3900, 0x00 },
+ { 0x3901, 0x00 },
+ { 0x3902, 0x00 },
+ { 0x3904, 0x00 },
+ { 0x3905, 0x00 },
+ { 0x3906, 0x00 },
+ { 0x3907, 0x00 },
+ { 0x3908, 0x00 },
+ { 0x3909, 0x00 },
+ { 0x3912, 0x00 },
+ { 0x3930, 0x00 },
+ { 0x3931, 0x00 },
+ { 0x3933, 0x00 },
+ { 0x3934, 0x00 },
+ { 0x3935, 0x00 },
+ { 0x3936, 0x00 },
+ { 0x3937, 0x00 },
+ { 0x30ac, 0x00 },
+};
+
+static const struct imx319_reg mode_1280x720_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x08 },
+ { 0x0343, 0x20 },
+ { 0x0340, 0x18 },
+ { 0x0341, 0x2a },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x02 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x07 },
+ { 0x034b, 0x9f },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x11 },
+ { 0x0381, 0x01 },
+ { 0x0383, 0x01 },
+ { 0x0385, 0x01 },
+ { 0x0387, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x0a },
+ { 0x3140, 0x02 },
+ { 0x3141, 0x00 },
+ { 0x3f0d, 0x0a },
+ { 0x3f14, 0x01 },
+ { 0x3f3c, 0x02 },
+ { 0x3f4d, 0x01 },
+ { 0x3f4c, 0x01 },
+ { 0x4254, 0x7f },
+ { 0x0401, 0x00 },
+ { 0x0404, 0x00 },
+ { 0x0405, 0x10 },
+ { 0x0408, 0x00 },
+ { 0x0409, 0xb4 },
+ { 0x040a, 0x00 },
+ { 0x040b, 0x00 },
+ { 0x040c, 0x05 },
+ { 0x040d, 0x00 },
+ { 0x040e, 0x02 },
+ { 0x040f, 0xd0 },
+ { 0x034c, 0x05 },
+ { 0x034d, 0x00 },
+ { 0x034e, 0x02 },
+ { 0x034f, 0xd0 },
+ { 0x3261, 0x00 },
+ { 0x3264, 0x00 },
+ { 0x3265, 0x10 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x04 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x01 },
+ { 0x0307, 0x92 },
+ { 0x0309, 0x0a },
+ { 0x030b, 0x02 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0xfa },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x0f },
+ { 0x0821, 0x13 },
+ { 0x0822, 0x33 },
+ { 0x0823, 0x33 },
+ { 0x3e20, 0x01 },
+ { 0x3e37, 0x00 },
+ { 0x3e3b, 0x01 },
+ { 0x38a3, 0x01 },
+ { 0x38a8, 0x00 },
+ { 0x38a9, 0x00 },
+ { 0x38aa, 0x00 },
+ { 0x38ab, 0x00 },
+ { 0x3234, 0x00 },
+ { 0x3fc1, 0x00 },
+ { 0x3235, 0x00 },
+ { 0x3802, 0x00 },
+ { 0x3143, 0x04 },
+ { 0x360a, 0x00 },
+ { 0x0b00, 0x00 },
+ { 0x0106, 0x00 },
+ { 0x0b05, 0x01 },
+ { 0x0b06, 0x01 },
+ { 0x3230, 0x00 },
+ { 0x3602, 0x01 },
+ { 0x3607, 0x01 },
+ { 0x3c00, 0x00 },
+ { 0x3c01, 0xba },
+ { 0x3c02, 0xc8 },
+ { 0x3c03, 0xaa },
+ { 0x3c04, 0x91 },
+ { 0x3c05, 0x54 },
+ { 0x3c06, 0x26 },
+ { 0x3c07, 0x20 },
+ { 0x3c08, 0x51 },
+ { 0x3d80, 0x00 },
+ { 0x3f50, 0x00 },
+ { 0x3f56, 0x00 },
+ { 0x3f57, 0x30 },
+ { 0x3f78, 0x00 },
+ { 0x3f79, 0x34 },
+ { 0x3f7c, 0x00 },
+ { 0x3f7d, 0x00 },
+ { 0x3fba, 0x00 },
+ { 0x3fbb, 0x00 },
+ { 0xa081, 0x04 },
+ { 0xe014, 0x00 },
+ { 0x0202, 0x04 },
+ { 0x0203, 0xf6 },
+ { 0x0224, 0x01 },
+ { 0x0225, 0xf4 },
+ { 0x0204, 0x00 },
+ { 0x0205, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x020e, 0x01 },
+ { 0x020f, 0x00 },
+ { 0x0210, 0x01 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x01 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x01 },
+ { 0x0215, 0x00 },
+ { 0x0218, 0x01 },
+ { 0x0219, 0x00 },
+ { 0x3614, 0x00 },
+ { 0x3616, 0x0d },
+ { 0x3617, 0x56 },
+ { 0xb612, 0x20 },
+ { 0xb613, 0x20 },
+ { 0xb614, 0x20 },
+ { 0xb615, 0x20 },
+ { 0xb616, 0x0a },
+ { 0xb617, 0x0a },
+ { 0xb618, 0x20 },
+ { 0xb619, 0x20 },
+ { 0xb61a, 0x20 },
+ { 0xb61b, 0x20 },
+ { 0xb61c, 0x0a },
+ { 0xb61d, 0x0a },
+ { 0xb666, 0x30 },
+ { 0xb667, 0x30 },
+ { 0xb668, 0x30 },
+ { 0xb669, 0x30 },
+ { 0xb66a, 0x14 },
+ { 0xb66b, 0x14 },
+ { 0xb66c, 0x20 },
+ { 0xb66d, 0x20 },
+ { 0xb66e, 0x20 },
+ { 0xb66f, 0x20 },
+ { 0xb670, 0x10 },
+ { 0xb671, 0x10 },
+ { 0x3237, 0x00 },
+ { 0x3900, 0x00 },
+ { 0x3901, 0x00 },
+ { 0x3902, 0x00 },
+ { 0x3904, 0x00 },
+ { 0x3905, 0x00 },
+ { 0x3906, 0x00 },
+ { 0x3907, 0x00 },
+ { 0x3908, 0x00 },
+ { 0x3909, 0x00 },
+ { 0x3912, 0x00 },
+ { 0x3930, 0x00 },
+ { 0x3931, 0x00 },
+ { 0x3933, 0x00 },
+ { 0x3934, 0x00 },
+ { 0x3935, 0x00 },
+ { 0x3936, 0x00 },
+ { 0x3937, 0x00 },
+ { 0x30ac, 0x00 },
+};
+
+static const char * const imx319_test_pattern_menu[] = {
+ "Disabled",
+ "100% color bars",
+ "Solid color",
+ "Fade to gray color bars",
+ "PN9"
+};
+
+/* supported link frequencies */
+static const s64 link_freq_menu_items[] = {
+ IMX319_LINK_FREQ_DEFAULT,
+};
+
+/* Mode configs */
+static const struct imx319_mode supported_modes[] = {
+ {
+ .width = 3280,
+ .height = 2464,
+ .fll_def = 3242,
+ .fll_min = 3242,
+ .llp = 3968,
+ .link_freq_index = IMX319_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
+ .regs = mode_3280x2464_regs,
+ },
+ },
+ {
+ .width = 3264,
+ .height = 2448,
+ .fll_def = 3242,
+ .fll_min = 3242,
+ .llp = 3968,
+ .link_freq_index = IMX319_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_3264x2448_regs),
+ .regs = mode_3264x2448_regs,
+ },
+ },
+ {
+ .width = 1936,
+ .height = 1096,
+ .fll_def = 3242,
+ .fll_min = 3242,
+ .llp = 3968,
+ .link_freq_index = IMX319_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1936x1096_regs),
+ .regs = mode_1936x1096_regs,
+ },
+ },
+ {
+ .width = 1920,
+ .height = 1080,
+ .fll_def = 3242,
+ .fll_min = 3242,
+ .llp = 3968,
+ .link_freq_index = IMX319_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),
+ .regs = mode_1920x1080_regs,
+ },
+ },
+ {
+ .width = 1640,
+ .height = 1232,
+ .fll_def = 5146,
+ .fll_min = 5146,
+ .llp = 2500,
+ .link_freq_index = IMX319_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1640x1232_regs),
+ .regs = mode_1640x1232_regs,
+ },
+ },
+ {
+ .width = 1640,
+ .height = 922,
+ .fll_def = 5146,
+ .fll_min = 5146,
+ .llp = 2500,
+ .link_freq_index = IMX319_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1640x922_regs),
+ .regs = mode_1640x922_regs,
+ },
+ },
+ {
+ .width = 1296,
+ .height = 736,
+ .fll_def = 5146,
+ .fll_min = 5146,
+ .llp = 2500,
+ .link_freq_index = IMX319_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1296x736_regs),
+ .regs = mode_1296x736_regs,
+ },
+ },
+ {
+ .width = 1280,
+ .height = 720,
+ .fll_def = 5146,
+ .fll_min = 5146,
+ .llp = 2500,
+ .link_freq_index = IMX319_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
+ .regs = mode_1280x720_regs,
+ },
+ },
+};
+
+static inline struct imx319 *to_imx319(struct v4l2_subdev *_sd)
+{
+ return container_of(_sd, struct imx319, sd);
+}
+
+/* Get bayer order based on flip setting. */
+static u32 imx319_get_format_code(struct imx319 *imx319)
+{
+ /*
+ * Only one bayer order is supported.
+ * It depends on the flip settings.
+ */
+ u32 code;
+ static const u32 codes[2][2] = {
+ { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, },
+ { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, },
+ };
+
+ lockdep_assert_held(&imx319->mutex);
+ code = codes[imx319->vflip->val][imx319->hflip->val];
+
+ return code;
+}
+
+/* Read registers up to 4 at a time */
+static int imx319_read_reg(struct imx319 *imx319, u16 reg, u32 len, u32 *val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
+ struct i2c_msg msgs[2];
+ u8 addr_buf[2];
+ u8 data_buf[4] = { 0 };
+ int ret;
+
+ if (len > 4)
+ return -EINVAL;
+
+ put_unaligned_be16(reg, addr_buf);
+ /* Write register address */
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = ARRAY_SIZE(addr_buf);
+ msgs[0].buf = addr_buf;
+
+ /* Read data from register */
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = len;
+ msgs[1].buf = &data_buf[4 - len];
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret != ARRAY_SIZE(msgs))
+ return -EIO;
+
+ *val = get_unaligned_be32(data_buf);
+
+ return 0;
+}
+
+/* Write registers up to 4 at a time */
+static int imx319_write_reg(struct imx319 *imx319, u16 reg, u32 len, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
+ u8 buf[6];
+
+ if (len > 4)
+ return -EINVAL;
+
+ put_unaligned_be16(reg, buf);
+ put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
+ if (i2c_master_send(client, buf, len + 2) != len + 2)
+ return -EIO;
+
+ return 0;
+}
+
+/* Write a list of registers */
+static int imx319_write_regs(struct imx319 *imx319,
+ const struct imx319_reg *regs, u32 len)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
+ int ret;
+ u32 i;
+
+ for (i = 0; i < len; i++) {
+ ret = imx319_write_reg(imx319, regs[i].address, 1, regs[i].val);
+ if (ret) {
+ dev_err_ratelimited(&client->dev,
+ "write reg 0x%4.4x return err %d",
+ regs[i].address, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/* Open sub-device */
+static int imx319_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ struct imx319 *imx319 = to_imx319(sd);
+ struct v4l2_mbus_framefmt *try_fmt =
+ v4l2_subdev_get_try_format(sd, fh->pad, 0);
+
+ mutex_lock(&imx319->mutex);
+
+ /* Initialize try_fmt */
+ try_fmt->width = imx319->cur_mode->width;
+ try_fmt->height = imx319->cur_mode->height;
+ try_fmt->code = imx319_get_format_code(imx319);
+ try_fmt->field = V4L2_FIELD_NONE;
+
+ mutex_unlock(&imx319->mutex);
+
+ return 0;
+}
+
+static int imx319_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct imx319 *imx319 = container_of(ctrl->handler,
+ struct imx319, ctrl_handler);
+ struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
+ s64 max;
+ int ret;
+
+ /* Propagate change of current control to all related controls */
+ switch (ctrl->id) {
+ case V4L2_CID_VBLANK:
+ /* Update max exposure while meeting expected vblanking */
+ max = imx319->cur_mode->height + ctrl->val - 18;
+ __v4l2_ctrl_modify_range(imx319->exposure,
+ imx319->exposure->minimum,
+ max, imx319->exposure->step, max);
+ break;
+ }
+
+ /*
+ * Applying V4L2 control value only happens
+ * when power is up for streaming
+ */
+ if (!pm_runtime_get_if_in_use(&client->dev))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ANALOGUE_GAIN:
+ /* Analog gain = 1024/(1024 - ctrl->val) times */
+ ret = imx319_write_reg(imx319, IMX319_REG_ANALOG_GAIN, 2,
+ ctrl->val);
+ break;
+ case V4L2_CID_DIGITAL_GAIN:
+ ret = imx319_write_reg(imx319, IMX319_REG_DIG_GAIN_GLOBAL, 2,
+ ctrl->val);
+ break;
+ case V4L2_CID_EXPOSURE:
+ ret = imx319_write_reg(imx319, IMX319_REG_EXPOSURE, 2,
+ ctrl->val);
+ break;
+ case V4L2_CID_VBLANK:
+ /* Update FLL that meets expected vertical blanking */
+ ret = imx319_write_reg(imx319, IMX319_REG_FLL, 2,
+ imx319->cur_mode->height + ctrl->val);
+ break;
+ case V4L2_CID_TEST_PATTERN:
+ ret = imx319_write_reg(imx319, IMX319_REG_TEST_PATTERN,
+ 2, ctrl->val);
+ break;
+ case V4L2_CID_HFLIP:
+ case V4L2_CID_VFLIP:
+ ret = imx319_write_reg(imx319, IMX319_REG_ORIENTATION, 1,
+ imx319->hflip->val |
+ imx319->vflip->val << 1);
+ break;
+ default:
+ ret = -EINVAL;
+ dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled",
+ ctrl->id, ctrl->val);
+ break;
+ }
+
+ pm_runtime_put(&client->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops imx319_ctrl_ops = {
+ .s_ctrl = imx319_set_ctrl,
+};
+
+static int imx319_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct imx319 *imx319 = to_imx319(sd);
+
+ if (code->index > 0)
+ return -EINVAL;
+
+ mutex_lock(&imx319->mutex);
+ code->code = imx319_get_format_code(imx319);
+ mutex_unlock(&imx319->mutex);
+
+ return 0;
+}
+
+static int imx319_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct imx319 *imx319 = to_imx319(sd);
+
+ if (fse->index >= ARRAY_SIZE(supported_modes))
+ return -EINVAL;
+
+ mutex_lock(&imx319->mutex);
+ if (fse->code != imx319_get_format_code(imx319)) {
+ mutex_unlock(&imx319->mutex);
+ return -EINVAL;
+ }
+ mutex_unlock(&imx319->mutex);
+
+ 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 void imx319_update_pad_format(struct imx319 *imx319,
+ const struct imx319_mode *mode,
+ struct v4l2_subdev_format *fmt)
+{
+ fmt->format.width = mode->width;
+ fmt->format.height = mode->height;
+ fmt->format.code = imx319_get_format_code(imx319);
+ fmt->format.field = V4L2_FIELD_NONE;
+}
+
+static int imx319_do_get_pad_format(struct imx319 *imx319,
+ struct v4l2_subdev_pad_config *cfg,
+ 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_get_try_format(sd, cfg, fmt->pad);
+ fmt->format = *framefmt;
+ } else {
+ imx319_update_pad_format(imx319, imx319->cur_mode, fmt);
+ }
+
+ return 0;
+}
+
+static int imx319_get_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
+{
+ struct imx319 *imx319 = to_imx319(sd);
+ int ret;
+
+ mutex_lock(&imx319->mutex);
+ ret = imx319_do_get_pad_format(imx319, cfg, fmt);
+ mutex_unlock(&imx319->mutex);
+
+ return ret;
+}
+
+static int
+imx319_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
+{
+ struct imx319 *imx319 = to_imx319(sd);
+ const struct imx319_mode *mode;
+ struct v4l2_mbus_framefmt *framefmt;
+ s32 vblank_def;
+ s32 vblank_min;
+ s64 h_blank;
+ u64 pixel_rate;
+ u32 height;
+
+ mutex_lock(&imx319->mutex);
+
+ /*
+ * Only one bayer order is supported.
+ * It depends on the flip settings.
+ */
+ fmt->format.code = imx319_get_format_code(imx319);
+
+ mode = v4l2_find_nearest_size(supported_modes,
+ ARRAY_SIZE(supported_modes),
+ width, height,
+ fmt->format.width, fmt->format.height);
+ imx319_update_pad_format(imx319, mode, fmt);
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+ *framefmt = fmt->format;
+ } else {
+ imx319->cur_mode = mode;
+ pixel_rate = imx319->link_def_freq * 2 * 4;
+ do_div(pixel_rate, 10);
+ __v4l2_ctrl_s_ctrl_int64(imx319->pixel_rate, pixel_rate);
+ /* Update limits and set FPS to default */
+ height = imx319->cur_mode->height;
+ vblank_def = imx319->cur_mode->fll_def - height;
+ vblank_min = imx319->cur_mode->fll_min - height;
+ height = IMX319_FLL_MAX - height;
+ __v4l2_ctrl_modify_range(imx319->vblank, vblank_min, height, 1,
+ vblank_def);
+ __v4l2_ctrl_s_ctrl(imx319->vblank, vblank_def);
+ h_blank = mode->llp - imx319->cur_mode->width;
+ /*
+ * Currently hblank is not changeable.
+ * So FPS control is done only by vblank.
+ */
+ __v4l2_ctrl_modify_range(imx319->hblank, h_blank,
+ h_blank, 1, h_blank);
+ }
+
+ mutex_unlock(&imx319->mutex);
+
+ return 0;
+}
+
+/* Start streaming */
+static int imx319_start_streaming(struct imx319 *imx319)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
+ const struct imx319_reg_list *reg_list;
+ int ret;
+
+ /* Global Setting */
+ reg_list = &imx319_global_setting;
+ ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);
+ if (ret) {
+ dev_err(&client->dev, "failed to set global settings");
+ return ret;
+ }
+
+ /* Apply default values of current mode */
+ reg_list = &imx319->cur_mode->reg_list;
+ ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);
+ if (ret) {
+ dev_err(&client->dev, "failed to set mode");
+ return ret;
+ }
+
+ /* set digital gain control to all color mode */
+ ret = imx319_write_reg(imx319, IMX319_REG_DPGA_USE_GLOBAL_GAIN, 1, 1);
+ if (ret)
+ return ret;
+
+ /* Apply customized values from user */
+ ret = __v4l2_ctrl_handler_setup(imx319->sd.ctrl_handler);
+ if (ret)
+ return ret;
+
+ return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT,
+ 1, IMX319_MODE_STREAMING);
+}
+
+/* Stop streaming */
+static int imx319_stop_streaming(struct imx319 *imx319)
+{
+ return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT,
+ 1, IMX319_MODE_STANDBY);
+}
+
+static int imx319_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct imx319 *imx319 = to_imx319(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int ret = 0;
+
+ mutex_lock(&imx319->mutex);
+ if (imx319->streaming == enable) {
+ mutex_unlock(&imx319->mutex);
+ return 0;
+ }
+
+ if (enable) {
+ ret = pm_runtime_get_sync(&client->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(&client->dev);
+ goto err_unlock;
+ }
+
+ /*
+ * Apply default & customized values
+ * and then start streaming.
+ */
+ ret = imx319_start_streaming(imx319);
+ if (ret)
+ goto err_rpm_put;
+ } else {
+ imx319_stop_streaming(imx319);
+ pm_runtime_put(&client->dev);
+ }
+
+ imx319->streaming = enable;
+
+ /* vflip and hflip cannot change during streaming */
+ __v4l2_ctrl_grab(imx319->vflip, enable);
+ __v4l2_ctrl_grab(imx319->hflip, enable);
+
+ mutex_unlock(&imx319->mutex);
+
+ return ret;
+
+err_rpm_put:
+ pm_runtime_put(&client->dev);
+err_unlock:
+ mutex_unlock(&imx319->mutex);
+
+ return ret;
+}
+
+static int __maybe_unused imx319_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct imx319 *imx319 = to_imx319(sd);
+
+ if (imx319->streaming)
+ imx319_stop_streaming(imx319);
+
+ return 0;
+}
+
+static int __maybe_unused imx319_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct imx319 *imx319 = to_imx319(sd);
+ int ret;
+
+ if (imx319->streaming) {
+ ret = imx319_start_streaming(imx319);
+ if (ret)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ imx319_stop_streaming(imx319);
+ imx319->streaming = 0;
+ return ret;
+}
+
+/* Verify chip ID */
+static int imx319_identify_module(struct imx319 *imx319)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
+ int ret;
+ u32 val;
+
+ ret = imx319_read_reg(imx319, IMX319_REG_CHIP_ID, 2, &val);
+ if (ret)
+ return ret;
+
+ if (val != IMX319_CHIP_ID) {
+ dev_err(&client->dev, "chip id mismatch: %x!=%x",
+ IMX319_CHIP_ID, val);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = {
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops imx319_video_ops = {
+ .s_stream = imx319_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops imx319_pad_ops = {
+ .enum_mbus_code = imx319_enum_mbus_code,
+ .get_fmt = imx319_get_pad_format,
+ .set_fmt = imx319_set_pad_format,
+ .enum_frame_size = imx319_enum_frame_size,
+};
+
+static const struct v4l2_subdev_ops imx319_subdev_ops = {
+ .core = &imx319_subdev_core_ops,
+ .video = &imx319_video_ops,
+ .pad = &imx319_pad_ops,
+};
+
+static const struct media_entity_operations imx319_subdev_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static const struct v4l2_subdev_internal_ops imx319_internal_ops = {
+ .open = imx319_open,
+};
+
+/* Initialize control handlers */
+static int imx319_init_controls(struct imx319 *imx319)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
+ struct v4l2_ctrl_handler *ctrl_hdlr;
+ s64 exposure_max;
+ s64 vblank_def;
+ s64 vblank_min;
+ s64 hblank;
+ u64 pixel_rate;
+ const struct imx319_mode *mode;
+ u32 max;
+ int ret;
+
+ ctrl_hdlr = &imx319->ctrl_handler;
+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
+ if (ret)
+ return ret;
+
+ ctrl_hdlr->lock = &imx319->mutex;
+ max = ARRAY_SIZE(link_freq_menu_items) - 1;
+ imx319->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx319_ctrl_ops,
+ V4L2_CID_LINK_FREQ, max, 0,
+ link_freq_menu_items);
+ if (imx319->link_freq)
+ imx319->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
+ pixel_rate = imx319->link_def_freq * 2 * 4;
+ do_div(pixel_rate, 10);
+ /* By default, PIXEL_RATE is read only */
+ imx319->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
+ V4L2_CID_PIXEL_RATE, pixel_rate,
+ pixel_rate, 1, pixel_rate);
+
+ /* Initial vblank/hblank/exposure parameters based on current mode */
+ mode = imx319->cur_mode;
+ vblank_def = mode->fll_def - mode->height;
+ vblank_min = mode->fll_min - mode->height;
+ imx319->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
+ V4L2_CID_VBLANK, vblank_min,
+ IMX319_FLL_MAX - mode->height,
+ 1, vblank_def);
+
+ hblank = mode->llp - mode->width;
+ imx319->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
+ V4L2_CID_HBLANK, hblank, hblank,
+ 1, hblank);
+ if (imx319->hblank)
+ imx319->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ /* fll >= exposure time + adjust parameter (default value is 18) */
+ exposure_max = mode->fll_def - 18;
+ imx319->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ IMX319_EXPOSURE_MIN, exposure_max,
+ IMX319_EXPOSURE_STEP,
+ IMX319_EXPOSURE_DEFAULT);
+
+ imx319->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ imx319->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+ v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+ IMX319_ANA_GAIN_MIN, IMX319_ANA_GAIN_MAX,
+ IMX319_ANA_GAIN_STEP, IMX319_ANA_GAIN_DEFAULT);
+
+ /* Digital gain */
+ v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
+ IMX319_DGTL_GAIN_MIN, IMX319_DGTL_GAIN_MAX,
+ IMX319_DGTL_GAIN_STEP, IMX319_DGTL_GAIN_DEFAULT);
+
+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx319_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(imx319_test_pattern_menu) - 1,
+ 0, 0, imx319_test_pattern_menu);
+ if (ctrl_hdlr->error) {
+ ret = ctrl_hdlr->error;
+ dev_err(&client->dev, "control init failed: %d", ret);
+ goto error;
+ }
+
+ imx319->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+
+error:
+ v4l2_ctrl_handler_free(ctrl_hdlr);
+
+ return ret;
+}
+
+static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev)
+{
+ struct imx319_hwcfg *cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ struct fwnode_handle *ep;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
+ unsigned int i;
+ int ret;
+
+ if (!fwnode)
+ return NULL;
+
+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+ if (!ep)
+ return NULL;
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ if (ret)
+ goto out_err;
+
+ cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL);
+ if (!cfg)
+ goto out_err;
+
+ ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
+ &cfg->ext_clk);
+ if (ret) {
+ dev_err(dev, "can't get clock frequency");
+ goto out_err;
+ }
+
+ dev_dbg(dev, "ext clk: %d", cfg->ext_clk);
+ if (cfg->ext_clk != IMX319_EXT_CLK) {
+ dev_err(dev, "external clock %d is not supported",
+ cfg->ext_clk);
+ goto out_err;
+ }
+
+ dev_dbg(dev, "num of link freqs: %d", bus_cfg.nr_of_link_frequencies);
+ if (!bus_cfg.nr_of_link_frequencies) {
+ dev_warn(dev, "no link frequencies defined");
+ goto out_err;
+ }
+
+ cfg->nr_of_link_freqs = bus_cfg.nr_of_link_frequencies;
+ cfg->link_freqs = devm_kcalloc(dev,
+ bus_cfg.nr_of_link_frequencies + 1,
+ sizeof(*cfg->link_freqs), GFP_KERNEL);
+ if (!cfg->link_freqs)
+ goto out_err;
+
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
+ cfg->link_freqs[i] = bus_cfg.link_frequencies[i];
+ dev_dbg(dev, "link_freq[%d] = %lld", i, cfg->link_freqs[i]);
+ }
+
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+ fwnode_handle_put(ep);
+ return cfg;
+
+out_err:
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+ fwnode_handle_put(ep);
+ return NULL;
+}
+
+static int imx319_probe(struct i2c_client *client)
+{
+ struct imx319 *imx319;
+ int ret;
+ u32 i;
+
+ imx319 = devm_kzalloc(&client->dev, sizeof(*imx319), GFP_KERNEL);
+ if (!imx319)
+ return -ENOMEM;
+
+ mutex_init(&imx319->mutex);
+
+ /* Initialize subdev */
+ v4l2_i2c_subdev_init(&imx319->sd, client, &imx319_subdev_ops);
+
+ /* Check module identity */
+ ret = imx319_identify_module(imx319);
+ if (ret) {
+ dev_err(&client->dev, "failed to find sensor: %d", ret);
+ goto error_probe;
+ }
+
+ imx319->hwcfg = imx319_get_hwcfg(&client->dev);
+ if (!imx319->hwcfg) {
+ dev_err(&client->dev, "failed to get hwcfg");
+ ret = -ENODEV;
+ goto error_probe;
+ }
+
+ imx319->link_def_freq = link_freq_menu_items[IMX319_LINK_FREQ_INDEX];
+ for (i = 0; i < imx319->hwcfg->nr_of_link_freqs; i++) {
+ if (imx319->hwcfg->link_freqs[i] == imx319->link_def_freq) {
+ dev_dbg(&client->dev, "link freq index %d matched", i);
+ break;
+ }
+ }
+
+ if (i == imx319->hwcfg->nr_of_link_freqs) {
+ dev_err(&client->dev, "no link frequency supported");
+ ret = -EINVAL;
+ goto error_probe;
+ }
+
+ /* Set default mode to max resolution */
+ imx319->cur_mode = &supported_modes[0];
+
+ ret = imx319_init_controls(imx319);
+ if (ret) {
+ dev_err(&client->dev, "failed to init controls: %d", ret);
+ goto error_probe;
+ }
+
+ /* Initialize subdev */
+ imx319->sd.internal_ops = &imx319_internal_ops;
+ imx319->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+ V4L2_SUBDEV_FL_HAS_EVENTS;
+ imx319->sd.entity.ops = &imx319_subdev_entity_ops;
+ imx319->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+ /* Initialize source pad */
+ imx319->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&imx319->sd.entity, 1, &imx319->pad);
+ if (ret) {
+ dev_err(&client->dev, "failed to init entity pads: %d", ret);
+ goto error_handler_free;
+ }
+
+ ret = v4l2_async_register_subdev_sensor_common(&imx319->sd);
+ if (ret < 0)
+ goto error_media_entity;
+
+ /*
+ * Device is already turned on by i2c-core with ACPI domain PM.
+ * Enable runtime PM and turn off the device.
+ */
+ pm_runtime_set_active(&client->dev);
+ pm_runtime_enable(&client->dev);
+ pm_runtime_idle(&client->dev);
+
+ return 0;
+
+error_media_entity:
+ media_entity_cleanup(&imx319->sd.entity);
+
+error_handler_free:
+ v4l2_ctrl_handler_free(imx319->sd.ctrl_handler);
+
+error_probe:
+ mutex_destroy(&imx319->mutex);
+
+ return ret;
+}
+
+static int imx319_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct imx319 *imx319 = to_imx319(sd);
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+
+ mutex_destroy(&imx319->mutex);
+
+ return 0;
+}
+
+static const struct dev_pm_ops imx319_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(imx319_suspend, imx319_resume)
+};
+
+static const struct acpi_device_id imx319_acpi_ids[] = {
+ { "SONY319A" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, imx319_acpi_ids);
+
+static struct i2c_driver imx319_i2c_driver = {
+ .driver = {
+ .name = "imx319",
+ .pm = &imx319_pm_ops,
+ .acpi_match_table = ACPI_PTR(imx319_acpi_ids),
+ },
+ .probe_new = imx319_probe,
+ .remove = imx319_remove,
+};
+module_i2c_driver(imx319_i2c_driver);
+
+MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
+MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
+MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
+MODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>");
+MODULE_DESCRIPTION("Sony imx319 sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c
new file mode 100644
index 000000000000..20c8eea5db4b
--- /dev/null
+++ b/drivers/media/i2c/imx355.c
@@ -0,0 +1,1860 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Intel Corporation
+
+#include <asm/unaligned.h>
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+
+#define IMX355_REG_MODE_SELECT 0x0100
+#define IMX355_MODE_STANDBY 0x00
+#define IMX355_MODE_STREAMING 0x01
+
+/* Chip ID */
+#define IMX355_REG_CHIP_ID 0x0016
+#define IMX355_CHIP_ID 0x0355
+
+/* V_TIMING internal */
+#define IMX355_REG_FLL 0x0340
+#define IMX355_FLL_MAX 0xffff
+
+/* Exposure control */
+#define IMX355_REG_EXPOSURE 0x0202
+#define IMX355_EXPOSURE_MIN 1
+#define IMX355_EXPOSURE_STEP 1
+#define IMX355_EXPOSURE_DEFAULT 0x0282
+
+/* Analog gain control */
+#define IMX355_REG_ANALOG_GAIN 0x0204
+#define IMX355_ANA_GAIN_MIN 0
+#define IMX355_ANA_GAIN_MAX 960
+#define IMX355_ANA_GAIN_STEP 1
+#define IMX355_ANA_GAIN_DEFAULT 0
+
+/* Digital gain control */
+#define IMX355_REG_DPGA_USE_GLOBAL_GAIN 0x3070
+#define IMX355_REG_DIG_GAIN_GLOBAL 0x020e
+#define IMX355_DGTL_GAIN_MIN 256
+#define IMX355_DGTL_GAIN_MAX 4095
+#define IMX355_DGTL_GAIN_STEP 1
+#define IMX355_DGTL_GAIN_DEFAULT 256
+
+/* Test Pattern Control */
+#define IMX355_REG_TEST_PATTERN 0x0600
+#define IMX355_TEST_PATTERN_DISABLED 0
+#define IMX355_TEST_PATTERN_SOLID_COLOR 1
+#define IMX355_TEST_PATTERN_COLOR_BARS 2
+#define IMX355_TEST_PATTERN_GRAY_COLOR_BARS 3
+#define IMX355_TEST_PATTERN_PN9 4
+
+/* Flip Control */
+#define IMX355_REG_ORIENTATION 0x0101
+
+/* default link frequency and external clock */
+#define IMX355_LINK_FREQ_DEFAULT 360000000
+#define IMX355_EXT_CLK 19200000
+#define IMX355_LINK_FREQ_INDEX 0
+
+struct imx355_reg {
+ u16 address;
+ u8 val;
+};
+
+struct imx355_reg_list {
+ u32 num_of_regs;
+ const struct imx355_reg *regs;
+};
+
+/* Mode : resolution and related config&values */
+struct imx355_mode {
+ /* Frame width */
+ u32 width;
+ /* Frame height */
+ u32 height;
+
+ /* V-timing */
+ u32 fll_def;
+ u32 fll_min;
+
+ /* H-timing */
+ u32 llp;
+
+ /* index of link frequency */
+ u32 link_freq_index;
+
+ /* Default register values */
+ struct imx355_reg_list reg_list;
+};
+
+struct imx355_hwcfg {
+ u32 ext_clk; /* sensor external clk */
+ s64 *link_freqs; /* CSI-2 link frequencies */
+ unsigned int nr_of_link_freqs;
+};
+
+struct imx355 {
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+
+ struct v4l2_ctrl_handler ctrl_handler;
+ /* V4L2 Controls */
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *exposure;
+ struct v4l2_ctrl *vflip;
+ struct v4l2_ctrl *hflip;
+
+ /* Current mode */
+ const struct imx355_mode *cur_mode;
+
+ struct imx355_hwcfg *hwcfg;
+ s64 link_def_freq; /* CSI-2 link default frequency */
+
+ /*
+ * Mutex for serialized access:
+ * Protect sensor set pad format and start/stop streaming safely.
+ * Protect access to sensor v4l2 controls.
+ */
+ struct mutex mutex;
+
+ /* Streaming on/off */
+ bool streaming;
+};
+
+static const struct imx355_reg imx355_global_regs[] = {
+ { 0x0136, 0x13 },
+ { 0x0137, 0x33 },
+ { 0x304e, 0x03 },
+ { 0x4348, 0x16 },
+ { 0x4350, 0x19 },
+ { 0x4408, 0x0a },
+ { 0x440c, 0x0b },
+ { 0x4411, 0x5f },
+ { 0x4412, 0x2c },
+ { 0x4623, 0x00 },
+ { 0x462c, 0x0f },
+ { 0x462d, 0x00 },
+ { 0x462e, 0x00 },
+ { 0x4684, 0x54 },
+ { 0x480a, 0x07 },
+ { 0x4908, 0x07 },
+ { 0x4909, 0x07 },
+ { 0x490d, 0x0a },
+ { 0x491e, 0x0f },
+ { 0x4921, 0x06 },
+ { 0x4923, 0x28 },
+ { 0x4924, 0x28 },
+ { 0x4925, 0x29 },
+ { 0x4926, 0x29 },
+ { 0x4927, 0x1f },
+ { 0x4928, 0x20 },
+ { 0x4929, 0x20 },
+ { 0x492a, 0x20 },
+ { 0x492c, 0x05 },
+ { 0x492d, 0x06 },
+ { 0x492e, 0x06 },
+ { 0x492f, 0x06 },
+ { 0x4930, 0x03 },
+ { 0x4931, 0x04 },
+ { 0x4932, 0x04 },
+ { 0x4933, 0x05 },
+ { 0x595e, 0x01 },
+ { 0x5963, 0x01 },
+ { 0x3030, 0x01 },
+ { 0x3031, 0x01 },
+ { 0x3045, 0x01 },
+ { 0x4010, 0x00 },
+ { 0x4011, 0x00 },
+ { 0x4012, 0x00 },
+ { 0x4013, 0x01 },
+ { 0x68a8, 0xfe },
+ { 0x68a9, 0xff },
+ { 0x6888, 0x00 },
+ { 0x6889, 0x00 },
+ { 0x68b0, 0x00 },
+ { 0x3058, 0x00 },
+ { 0x305a, 0x00 },
+};
+
+static const struct imx355_reg_list imx355_global_setting = {
+ .num_of_regs = ARRAY_SIZE(imx355_global_regs),
+ .regs = imx355_global_regs,
+};
+
+static const struct imx355_reg mode_3268x2448_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0e },
+ { 0x0343, 0x58 },
+ { 0x0340, 0x0a },
+ { 0x0341, 0x37 },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x08 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x08 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcb },
+ { 0x034a, 0x09 },
+ { 0x034b, 0x97 },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x0c },
+ { 0x034d, 0xc4 },
+ { 0x034e, 0x09 },
+ { 0x034f, 0x90 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_3264x2448_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0e },
+ { 0x0343, 0x58 },
+ { 0x0340, 0x0a },
+ { 0x0341, 0x37 },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x08 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x08 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xc7 },
+ { 0x034a, 0x09 },
+ { 0x034b, 0x97 },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x0c },
+ { 0x034d, 0xc0 },
+ { 0x034e, 0x09 },
+ { 0x034f, 0x90 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_3280x2464_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0e },
+ { 0x0343, 0x58 },
+ { 0x0340, 0x0a },
+ { 0x0341, 0x37 },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x09 },
+ { 0x034b, 0x9f },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x0c },
+ { 0x034d, 0xd0 },
+ { 0x034e, 0x09 },
+ { 0x034f, 0xa0 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1940x1096_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0e },
+ { 0x0343, 0x58 },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x02 },
+ { 0x0345, 0xa0 },
+ { 0x0346, 0x02 },
+ { 0x0347, 0xac },
+ { 0x0348, 0x0a },
+ { 0x0349, 0x33 },
+ { 0x034a, 0x06 },
+ { 0x034b, 0xf3 },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x07 },
+ { 0x034d, 0x94 },
+ { 0x034e, 0x04 },
+ { 0x034f, 0x48 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1936x1096_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0e },
+ { 0x0343, 0x58 },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x02 },
+ { 0x0345, 0xa0 },
+ { 0x0346, 0x02 },
+ { 0x0347, 0xac },
+ { 0x0348, 0x0a },
+ { 0x0349, 0x2f },
+ { 0x034a, 0x06 },
+ { 0x034b, 0xf3 },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x07 },
+ { 0x034d, 0x90 },
+ { 0x034e, 0x04 },
+ { 0x034f, 0x48 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1924x1080_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0e },
+ { 0x0343, 0x58 },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x02 },
+ { 0x0345, 0xa8 },
+ { 0x0346, 0x02 },
+ { 0x0347, 0xb4 },
+ { 0x0348, 0x0a },
+ { 0x0349, 0x2b },
+ { 0x034a, 0x06 },
+ { 0x034b, 0xeb },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x07 },
+ { 0x034d, 0x84 },
+ { 0x034e, 0x04 },
+ { 0x034f, 0x38 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1920x1080_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0e },
+ { 0x0343, 0x58 },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x02 },
+ { 0x0345, 0xa8 },
+ { 0x0346, 0x02 },
+ { 0x0347, 0xb4 },
+ { 0x0348, 0x0a },
+ { 0x0349, 0x27 },
+ { 0x034a, 0x06 },
+ { 0x034b, 0xeb },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x07 },
+ { 0x034d, 0x80 },
+ { 0x034e, 0x04 },
+ { 0x034f, 0x38 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1640x1232_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x07 },
+ { 0x0343, 0x2c },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x09 },
+ { 0x034b, 0x9f },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x06 },
+ { 0x034d, 0x68 },
+ { 0x034e, 0x04 },
+ { 0x034f, 0xd0 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1640x922_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x07 },
+ { 0x0343, 0x2c },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x01 },
+ { 0x0347, 0x30 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x08 },
+ { 0x034b, 0x63 },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x06 },
+ { 0x034d, 0x68 },
+ { 0x034e, 0x03 },
+ { 0x034f, 0x9a },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1300x736_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x07 },
+ { 0x0343, 0x2c },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x01 },
+ { 0x0345, 0x58 },
+ { 0x0346, 0x01 },
+ { 0x0347, 0xf0 },
+ { 0x0348, 0x0b },
+ { 0x0349, 0x7f },
+ { 0x034a, 0x07 },
+ { 0x034b, 0xaf },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x05 },
+ { 0x034d, 0x14 },
+ { 0x034e, 0x02 },
+ { 0x034f, 0xe0 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1296x736_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x07 },
+ { 0x0343, 0x2c },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x01 },
+ { 0x0345, 0x58 },
+ { 0x0346, 0x01 },
+ { 0x0347, 0xf0 },
+ { 0x0348, 0x0b },
+ { 0x0349, 0x77 },
+ { 0x034a, 0x07 },
+ { 0x034b, 0xaf },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x05 },
+ { 0x034d, 0x10 },
+ { 0x034e, 0x02 },
+ { 0x034f, 0xe0 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1284x720_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x07 },
+ { 0x0343, 0x2c },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x01 },
+ { 0x0345, 0x68 },
+ { 0x0346, 0x02 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x0b },
+ { 0x0349, 0x6f },
+ { 0x034a, 0x07 },
+ { 0x034b, 0x9f },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x05 },
+ { 0x034d, 0x04 },
+ { 0x034e, 0x02 },
+ { 0x034f, 0xd0 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_1280x720_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x07 },
+ { 0x0343, 0x2c },
+ { 0x0340, 0x05 },
+ { 0x0341, 0x1a },
+ { 0x0344, 0x01 },
+ { 0x0345, 0x68 },
+ { 0x0346, 0x02 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x0b },
+ { 0x0349, 0x67 },
+ { 0x034a, 0x07 },
+ { 0x034b, 0x9f },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x22 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x05 },
+ { 0x034d, 0x00 },
+ { 0x034e, 0x02 },
+ { 0x034f, 0xd0 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x00 },
+ { 0x0701, 0x10 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const struct imx355_reg mode_820x616_regs[] = {
+ { 0x0112, 0x0a },
+ { 0x0113, 0x0a },
+ { 0x0114, 0x03 },
+ { 0x0342, 0x0e },
+ { 0x0343, 0x58 },
+ { 0x0340, 0x02 },
+ { 0x0341, 0x8c },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x0c },
+ { 0x0349, 0xcf },
+ { 0x034a, 0x09 },
+ { 0x034b, 0x9f },
+ { 0x0220, 0x00 },
+ { 0x0222, 0x01 },
+ { 0x0900, 0x01 },
+ { 0x0901, 0x44 },
+ { 0x0902, 0x00 },
+ { 0x034c, 0x03 },
+ { 0x034d, 0x34 },
+ { 0x034e, 0x02 },
+ { 0x034f, 0x68 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x01 },
+ { 0x0305, 0x02 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x78 },
+ { 0x030b, 0x01 },
+ { 0x030d, 0x02 },
+ { 0x030e, 0x00 },
+ { 0x030f, 0x4b },
+ { 0x0310, 0x00 },
+ { 0x0700, 0x02 },
+ { 0x0701, 0x78 },
+ { 0x0820, 0x0b },
+ { 0x0821, 0x40 },
+ { 0x3088, 0x04 },
+ { 0x6813, 0x02 },
+ { 0x6835, 0x07 },
+ { 0x6836, 0x01 },
+ { 0x6837, 0x04 },
+ { 0x684d, 0x07 },
+ { 0x684e, 0x01 },
+ { 0x684f, 0x04 },
+};
+
+static const char * const imx355_test_pattern_menu[] = {
+ "Disabled",
+ "100% color bars",
+ "Solid color",
+ "Fade to gray color bars",
+ "PN9"
+};
+
+/* supported link frequencies */
+static const s64 link_freq_menu_items[] = {
+ IMX355_LINK_FREQ_DEFAULT,
+};
+
+/* Mode configs */
+static const struct imx355_mode supported_modes[] = {
+ {
+ .width = 3280,
+ .height = 2464,
+ .fll_def = 2615,
+ .fll_min = 2615,
+ .llp = 3672,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
+ .regs = mode_3280x2464_regs,
+ },
+ },
+ {
+ .width = 3268,
+ .height = 2448,
+ .fll_def = 2615,
+ .fll_min = 2615,
+ .llp = 3672,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_3268x2448_regs),
+ .regs = mode_3268x2448_regs,
+ },
+ },
+ {
+ .width = 3264,
+ .height = 2448,
+ .fll_def = 2615,
+ .fll_min = 2615,
+ .llp = 3672,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_3264x2448_regs),
+ .regs = mode_3264x2448_regs,
+ },
+ },
+ {
+ .width = 1940,
+ .height = 1096,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 3672,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1940x1096_regs),
+ .regs = mode_1940x1096_regs,
+ },
+ },
+ {
+ .width = 1936,
+ .height = 1096,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 3672,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1936x1096_regs),
+ .regs = mode_1936x1096_regs,
+ },
+ },
+ {
+ .width = 1924,
+ .height = 1080,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 3672,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1924x1080_regs),
+ .regs = mode_1924x1080_regs,
+ },
+ },
+ {
+ .width = 1920,
+ .height = 1080,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 3672,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),
+ .regs = mode_1920x1080_regs,
+ },
+ },
+ {
+ .width = 1640,
+ .height = 1232,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 1836,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1640x1232_regs),
+ .regs = mode_1640x1232_regs,
+ },
+ },
+ {
+ .width = 1640,
+ .height = 922,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 1836,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1640x922_regs),
+ .regs = mode_1640x922_regs,
+ },
+ },
+ {
+ .width = 1300,
+ .height = 736,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 1836,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1300x736_regs),
+ .regs = mode_1300x736_regs,
+ },
+ },
+ {
+ .width = 1296,
+ .height = 736,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 1836,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1296x736_regs),
+ .regs = mode_1296x736_regs,
+ },
+ },
+ {
+ .width = 1284,
+ .height = 720,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 1836,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1284x720_regs),
+ .regs = mode_1284x720_regs,
+ },
+ },
+ {
+ .width = 1280,
+ .height = 720,
+ .fll_def = 1306,
+ .fll_min = 1306,
+ .llp = 1836,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
+ .regs = mode_1280x720_regs,
+ },
+ },
+ {
+ .width = 820,
+ .height = 616,
+ .fll_def = 652,
+ .fll_min = 652,
+ .llp = 3672,
+ .link_freq_index = IMX355_LINK_FREQ_INDEX,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_820x616_regs),
+ .regs = mode_820x616_regs,
+ },
+ },
+};
+
+static inline struct imx355 *to_imx355(struct v4l2_subdev *_sd)
+{
+ return container_of(_sd, struct imx355, sd);
+}
+
+/* Get bayer order based on flip setting. */
+static u32 imx355_get_format_code(struct imx355 *imx355)
+{
+ /*
+ * Only one bayer order is supported.
+ * It depends on the flip settings.
+ */
+ u32 code;
+ static const u32 codes[2][2] = {
+ { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, },
+ { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, },
+ };
+
+ lockdep_assert_held(&imx355->mutex);
+ code = codes[imx355->vflip->val][imx355->hflip->val];
+
+ return code;
+}
+
+/* Read registers up to 4 at a time */
+static int imx355_read_reg(struct imx355 *imx355, u16 reg, u32 len, u32 *val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);
+ struct i2c_msg msgs[2];
+ u8 addr_buf[2];
+ u8 data_buf[4] = { 0 };
+ int ret;
+
+ if (len > 4)
+ return -EINVAL;
+
+ put_unaligned_be16(reg, addr_buf);
+ /* Write register address */
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = ARRAY_SIZE(addr_buf);
+ msgs[0].buf = addr_buf;
+
+ /* Read data from register */
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = len;
+ msgs[1].buf = &data_buf[4 - len];
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret != ARRAY_SIZE(msgs))
+ return -EIO;
+
+ *val = get_unaligned_be32(data_buf);
+
+ return 0;
+}
+
+/* Write registers up to 4 at a time */
+static int imx355_write_reg(struct imx355 *imx355, u16 reg, u32 len, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);
+ u8 buf[6];
+
+ if (len > 4)
+ return -EINVAL;
+
+ put_unaligned_be16(reg, buf);
+ put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
+ if (i2c_master_send(client, buf, len + 2) != len + 2)
+ return -EIO;
+
+ return 0;
+}
+
+/* Write a list of registers */
+static int imx355_write_regs(struct imx355 *imx355,
+ const struct imx355_reg *regs, u32 len)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);
+ int ret;
+ u32 i;
+
+ for (i = 0; i < len; i++) {
+ ret = imx355_write_reg(imx355, regs[i].address, 1, regs[i].val);
+ if (ret) {
+ dev_err_ratelimited(&client->dev,
+ "write reg 0x%4.4x return err %d",
+ regs[i].address, ret);
+
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/* Open sub-device */
+static int imx355_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ struct imx355 *imx355 = to_imx355(sd);
+ struct v4l2_mbus_framefmt *try_fmt =
+ v4l2_subdev_get_try_format(sd, fh->pad, 0);
+
+ mutex_lock(&imx355->mutex);
+
+ /* Initialize try_fmt */
+ try_fmt->width = imx355->cur_mode->width;
+ try_fmt->height = imx355->cur_mode->height;
+ try_fmt->code = imx355_get_format_code(imx355);
+ try_fmt->field = V4L2_FIELD_NONE;
+
+ mutex_unlock(&imx355->mutex);
+
+ return 0;
+}
+
+static int imx355_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct imx355 *imx355 = container_of(ctrl->handler,
+ struct imx355, ctrl_handler);
+ struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);
+ s64 max;
+ int ret;
+
+ /* Propagate change of current control to all related controls */
+ switch (ctrl->id) {
+ case V4L2_CID_VBLANK:
+ /* Update max exposure while meeting expected vblanking */
+ max = imx355->cur_mode->height + ctrl->val - 10;
+ __v4l2_ctrl_modify_range(imx355->exposure,
+ imx355->exposure->minimum,
+ max, imx355->exposure->step, max);
+ break;
+ }
+
+ /*
+ * Applying V4L2 control value only happens
+ * when power is up for streaming
+ */
+ if (!pm_runtime_get_if_in_use(&client->dev))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ANALOGUE_GAIN:
+ /* Analog gain = 1024/(1024 - ctrl->val) times */
+ ret = imx355_write_reg(imx355, IMX355_REG_ANALOG_GAIN, 2,
+ ctrl->val);
+ break;
+ case V4L2_CID_DIGITAL_GAIN:
+ ret = imx355_write_reg(imx355, IMX355_REG_DIG_GAIN_GLOBAL, 2,
+ ctrl->val);
+ break;
+ case V4L2_CID_EXPOSURE:
+ ret = imx355_write_reg(imx355, IMX355_REG_EXPOSURE, 2,
+ ctrl->val);
+ break;
+ case V4L2_CID_VBLANK:
+ /* Update FLL that meets expected vertical blanking */
+ ret = imx355_write_reg(imx355, IMX355_REG_FLL, 2,
+ imx355->cur_mode->height + ctrl->val);
+ break;
+ case V4L2_CID_TEST_PATTERN:
+ ret = imx355_write_reg(imx355, IMX355_REG_TEST_PATTERN,
+ 2, ctrl->val);
+ break;
+ case V4L2_CID_HFLIP:
+ case V4L2_CID_VFLIP:
+ ret = imx355_write_reg(imx355, IMX355_REG_ORIENTATION, 1,
+ imx355->hflip->val |
+ imx355->vflip->val << 1);
+ break;
+ default:
+ ret = -EINVAL;
+ dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled",
+ ctrl->id, ctrl->val);
+ break;
+ }
+
+ pm_runtime_put(&client->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops imx355_ctrl_ops = {
+ .s_ctrl = imx355_set_ctrl,
+};
+
+static int imx355_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct imx355 *imx355 = to_imx355(sd);
+
+ if (code->index > 0)
+ return -EINVAL;
+
+ mutex_lock(&imx355->mutex);
+ code->code = imx355_get_format_code(imx355);
+ mutex_unlock(&imx355->mutex);
+
+ return 0;
+}
+
+static int imx355_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct imx355 *imx355 = to_imx355(sd);
+
+ if (fse->index >= ARRAY_SIZE(supported_modes))
+ return -EINVAL;
+
+ mutex_lock(&imx355->mutex);
+ if (fse->code != imx355_get_format_code(imx355)) {
+ mutex_unlock(&imx355->mutex);
+ return -EINVAL;
+ }
+ mutex_unlock(&imx355->mutex);
+
+ 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 void imx355_update_pad_format(struct imx355 *imx355,
+ const struct imx355_mode *mode,
+ struct v4l2_subdev_format *fmt)
+{
+ fmt->format.width = mode->width;
+ fmt->format.height = mode->height;
+ fmt->format.code = imx355_get_format_code(imx355);
+ fmt->format.field = V4L2_FIELD_NONE;
+}
+
+static int imx355_do_get_pad_format(struct imx355 *imx355,
+ struct v4l2_subdev_pad_config *cfg,
+ 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_get_try_format(sd, cfg, fmt->pad);
+ fmt->format = *framefmt;
+ } else {
+ imx355_update_pad_format(imx355, imx355->cur_mode, fmt);
+ }
+
+ return 0;
+}
+
+static int imx355_get_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
+{
+ struct imx355 *imx355 = to_imx355(sd);
+ int ret;
+
+ mutex_lock(&imx355->mutex);
+ ret = imx355_do_get_pad_format(imx355, cfg, fmt);
+ mutex_unlock(&imx355->mutex);
+
+ return ret;
+}
+
+static int
+imx355_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
+{
+ struct imx355 *imx355 = to_imx355(sd);
+ const struct imx355_mode *mode;
+ struct v4l2_mbus_framefmt *framefmt;
+ s32 vblank_def;
+ s32 vblank_min;
+ s64 h_blank;
+ u64 pixel_rate;
+ u32 height;
+
+ mutex_lock(&imx355->mutex);
+
+ /*
+ * Only one bayer order is supported.
+ * It depends on the flip settings.
+ */
+ fmt->format.code = imx355_get_format_code(imx355);
+
+ mode = v4l2_find_nearest_size(supported_modes,
+ ARRAY_SIZE(supported_modes),
+ width, height,
+ fmt->format.width, fmt->format.height);
+ imx355_update_pad_format(imx355, mode, fmt);
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+ *framefmt = fmt->format;
+ } else {
+ imx355->cur_mode = mode;
+ pixel_rate = imx355->link_def_freq * 2 * 4;
+ do_div(pixel_rate, 10);
+ __v4l2_ctrl_s_ctrl_int64(imx355->pixel_rate, pixel_rate);
+ /* Update limits and set FPS to default */
+ height = imx355->cur_mode->height;
+ vblank_def = imx355->cur_mode->fll_def - height;
+ vblank_min = imx355->cur_mode->fll_min - height;
+ height = IMX355_FLL_MAX - height;
+ __v4l2_ctrl_modify_range(imx355->vblank, vblank_min, height, 1,
+ vblank_def);
+ __v4l2_ctrl_s_ctrl(imx355->vblank, vblank_def);
+ h_blank = mode->llp - imx355->cur_mode->width;
+ /*
+ * Currently hblank is not changeable.
+ * So FPS control is done only by vblank.
+ */
+ __v4l2_ctrl_modify_range(imx355->hblank, h_blank,
+ h_blank, 1, h_blank);
+ }
+
+ mutex_unlock(&imx355->mutex);
+
+ return 0;
+}
+
+/* Start streaming */
+static int imx355_start_streaming(struct imx355 *imx355)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);
+ const struct imx355_reg_list *reg_list;
+ int ret;
+
+ /* Global Setting */
+ reg_list = &imx355_global_setting;
+ ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs);
+ if (ret) {
+ dev_err(&client->dev, "failed to set global settings");
+ return ret;
+ }
+
+ /* Apply default values of current mode */
+ reg_list = &imx355->cur_mode->reg_list;
+ ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs);
+ if (ret) {
+ dev_err(&client->dev, "failed to set mode");
+ return ret;
+ }
+
+ /* set digital gain control to all color mode */
+ ret = imx355_write_reg(imx355, IMX355_REG_DPGA_USE_GLOBAL_GAIN, 1, 1);
+ if (ret)
+ return ret;
+
+ /* Apply customized values from user */
+ ret = __v4l2_ctrl_handler_setup(imx355->sd.ctrl_handler);
+ if (ret)
+ return ret;
+
+ return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT,
+ 1, IMX355_MODE_STREAMING);
+}
+
+/* Stop streaming */
+static int imx355_stop_streaming(struct imx355 *imx355)
+{
+ return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT,
+ 1, IMX355_MODE_STANDBY);
+}
+
+static int imx355_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct imx355 *imx355 = to_imx355(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int ret = 0;
+
+ mutex_lock(&imx355->mutex);
+ if (imx355->streaming == enable) {
+ mutex_unlock(&imx355->mutex);
+ return 0;
+ }
+
+ if (enable) {
+ ret = pm_runtime_get_sync(&client->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(&client->dev);
+ goto err_unlock;
+ }
+
+ /*
+ * Apply default & customized values
+ * and then start streaming.
+ */
+ ret = imx355_start_streaming(imx355);
+ if (ret)
+ goto err_rpm_put;
+ } else {
+ imx355_stop_streaming(imx355);
+ pm_runtime_put(&client->dev);
+ }
+
+ imx355->streaming = enable;
+
+ /* vflip and hflip cannot change during streaming */
+ __v4l2_ctrl_grab(imx355->vflip, enable);
+ __v4l2_ctrl_grab(imx355->hflip, enable);
+
+ mutex_unlock(&imx355->mutex);
+
+ return ret;
+
+err_rpm_put:
+ pm_runtime_put(&client->dev);
+err_unlock:
+ mutex_unlock(&imx355->mutex);
+
+ return ret;
+}
+
+static int __maybe_unused imx355_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct imx355 *imx355 = to_imx355(sd);
+
+ if (imx355->streaming)
+ imx355_stop_streaming(imx355);
+
+ return 0;
+}
+
+static int __maybe_unused imx355_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct imx355 *imx355 = to_imx355(sd);
+ int ret;
+
+ if (imx355->streaming) {
+ ret = imx355_start_streaming(imx355);
+ if (ret)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ imx355_stop_streaming(imx355);
+ imx355->streaming = 0;
+ return ret;
+}
+
+/* Verify chip ID */
+static int imx355_identify_module(struct imx355 *imx355)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);
+ int ret;
+ u32 val;
+
+ ret = imx355_read_reg(imx355, IMX355_REG_CHIP_ID, 2, &val);
+ if (ret)
+ return ret;
+
+ if (val != IMX355_CHIP_ID) {
+ dev_err(&client->dev, "chip id mismatch: %x!=%x",
+ IMX355_CHIP_ID, val);
+ return -EIO;
+ }
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops imx355_subdev_core_ops = {
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops imx355_video_ops = {
+ .s_stream = imx355_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops imx355_pad_ops = {
+ .enum_mbus_code = imx355_enum_mbus_code,
+ .get_fmt = imx355_get_pad_format,
+ .set_fmt = imx355_set_pad_format,
+ .enum_frame_size = imx355_enum_frame_size,
+};
+
+static const struct v4l2_subdev_ops imx355_subdev_ops = {
+ .core = &imx355_subdev_core_ops,
+ .video = &imx355_video_ops,
+ .pad = &imx355_pad_ops,
+};
+
+static const struct media_entity_operations imx355_subdev_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static const struct v4l2_subdev_internal_ops imx355_internal_ops = {
+ .open = imx355_open,
+};
+
+/* Initialize control handlers */
+static int imx355_init_controls(struct imx355 *imx355)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);
+ struct v4l2_ctrl_handler *ctrl_hdlr;
+ s64 exposure_max;
+ s64 vblank_def;
+ s64 vblank_min;
+ s64 hblank;
+ u64 pixel_rate;
+ const struct imx355_mode *mode;
+ u32 max;
+ int ret;
+
+ ctrl_hdlr = &imx355->ctrl_handler;
+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
+ if (ret)
+ return ret;
+
+ ctrl_hdlr->lock = &imx355->mutex;
+ max = ARRAY_SIZE(link_freq_menu_items) - 1;
+ imx355->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx355_ctrl_ops,
+ V4L2_CID_LINK_FREQ, max, 0,
+ link_freq_menu_items);
+ if (imx355->link_freq)
+ imx355->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
+ pixel_rate = imx355->link_def_freq * 2 * 4;
+ do_div(pixel_rate, 10);
+ /* By default, PIXEL_RATE is read only */
+ imx355->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
+ V4L2_CID_PIXEL_RATE, pixel_rate,
+ pixel_rate, 1, pixel_rate);
+
+ /* Initialize vblank/hblank/exposure parameters based on current mode */
+ mode = imx355->cur_mode;
+ vblank_def = mode->fll_def - mode->height;
+ vblank_min = mode->fll_min - mode->height;
+ imx355->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
+ V4L2_CID_VBLANK, vblank_min,
+ IMX355_FLL_MAX - mode->height,
+ 1, vblank_def);
+
+ hblank = mode->llp - mode->width;
+ imx355->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
+ V4L2_CID_HBLANK, hblank, hblank,
+ 1, hblank);
+ if (imx355->hblank)
+ imx355->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ /* fll >= exposure time + adjust parameter (default value is 10) */
+ exposure_max = mode->fll_def - 10;
+ imx355->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ IMX355_EXPOSURE_MIN, exposure_max,
+ IMX355_EXPOSURE_STEP,
+ IMX355_EXPOSURE_DEFAULT);
+
+ imx355->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ imx355->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+ v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+ IMX355_ANA_GAIN_MIN, IMX355_ANA_GAIN_MAX,
+ IMX355_ANA_GAIN_STEP, IMX355_ANA_GAIN_DEFAULT);
+
+ /* Digital gain */
+ v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
+ IMX355_DGTL_GAIN_MIN, IMX355_DGTL_GAIN_MAX,
+ IMX355_DGTL_GAIN_STEP, IMX355_DGTL_GAIN_DEFAULT);
+
+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx355_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(imx355_test_pattern_menu) - 1,
+ 0, 0, imx355_test_pattern_menu);
+ if (ctrl_hdlr->error) {
+ ret = ctrl_hdlr->error;
+ dev_err(&client->dev, "control init failed: %d", ret);
+ goto error;
+ }
+
+ imx355->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+
+error:
+ v4l2_ctrl_handler_free(ctrl_hdlr);
+
+ return ret;
+}
+
+static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev)
+{
+ struct imx355_hwcfg *cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ struct fwnode_handle *ep;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
+ unsigned int i;
+ int ret;
+
+ if (!fwnode)
+ return NULL;
+
+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+ if (!ep)
+ return NULL;
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ if (ret)
+ goto out_err;
+
+ cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL);
+ if (!cfg)
+ goto out_err;
+
+ ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
+ &cfg->ext_clk);
+ if (ret) {
+ dev_err(dev, "can't get clock frequency");
+ goto out_err;
+ }
+
+ dev_dbg(dev, "ext clk: %d", cfg->ext_clk);
+ if (cfg->ext_clk != IMX355_EXT_CLK) {
+ dev_err(dev, "external clock %d is not supported",
+ cfg->ext_clk);
+ goto out_err;
+ }
+
+ dev_dbg(dev, "num of link freqs: %d", bus_cfg.nr_of_link_frequencies);
+ if (!bus_cfg.nr_of_link_frequencies) {
+ dev_warn(dev, "no link frequencies defined");
+ goto out_err;
+ }
+
+ cfg->nr_of_link_freqs = bus_cfg.nr_of_link_frequencies;
+ cfg->link_freqs = devm_kcalloc(dev,
+ bus_cfg.nr_of_link_frequencies + 1,
+ sizeof(*cfg->link_freqs), GFP_KERNEL);
+ if (!cfg->link_freqs)
+ goto out_err;
+
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
+ cfg->link_freqs[i] = bus_cfg.link_frequencies[i];
+ dev_dbg(dev, "link_freq[%d] = %lld", i, cfg->link_freqs[i]);
+ }
+
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+ fwnode_handle_put(ep);
+ return cfg;
+
+out_err:
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+ fwnode_handle_put(ep);
+ return NULL;
+}
+
+static int imx355_probe(struct i2c_client *client)
+{
+ struct imx355 *imx355;
+ int ret;
+ u32 i;
+
+ imx355 = devm_kzalloc(&client->dev, sizeof(*imx355), GFP_KERNEL);
+ if (!imx355)
+ return -ENOMEM;
+
+ mutex_init(&imx355->mutex);
+
+ /* Initialize subdev */
+ v4l2_i2c_subdev_init(&imx355->sd, client, &imx355_subdev_ops);
+
+ /* Check module identity */
+ ret = imx355_identify_module(imx355);
+ if (ret) {
+ dev_err(&client->dev, "failed to find sensor: %d", ret);
+ goto error_probe;
+ }
+
+ imx355->hwcfg = imx355_get_hwcfg(&client->dev);
+ if (!imx355->hwcfg) {
+ dev_err(&client->dev, "failed to get hwcfg");
+ ret = -ENODEV;
+ goto error_probe;
+ }
+
+ imx355->link_def_freq = link_freq_menu_items[IMX355_LINK_FREQ_INDEX];
+ for (i = 0; i < imx355->hwcfg->nr_of_link_freqs; i++) {
+ if (imx355->hwcfg->link_freqs[i] == imx355->link_def_freq) {
+ dev_dbg(&client->dev, "link freq index %d matched", i);
+ break;
+ }
+ }
+
+ if (i == imx355->hwcfg->nr_of_link_freqs) {
+ dev_err(&client->dev, "no link frequency supported");
+ ret = -EINVAL;
+ goto error_probe;
+ }
+
+ /* Set default mode to max resolution */
+ imx355->cur_mode = &supported_modes[0];
+
+ ret = imx355_init_controls(imx355);
+ if (ret) {
+ dev_err(&client->dev, "failed to init controls: %d", ret);
+ goto error_probe;
+ }
+
+ /* Initialize subdev */
+ imx355->sd.internal_ops = &imx355_internal_ops;
+ imx355->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+ V4L2_SUBDEV_FL_HAS_EVENTS;
+ imx355->sd.entity.ops = &imx355_subdev_entity_ops;
+ imx355->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+ /* Initialize source pad */
+ imx355->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&imx355->sd.entity, 1, &imx355->pad);
+ if (ret) {
+ dev_err(&client->dev, "failed to init entity pads: %d", ret);
+ goto error_handler_free;
+ }
+
+ ret = v4l2_async_register_subdev_sensor_common(&imx355->sd);
+ if (ret < 0)
+ goto error_media_entity;
+
+ /*
+ * Device is already turned on by i2c-core with ACPI domain PM.
+ * Enable runtime PM and turn off the device.
+ */
+ pm_runtime_set_active(&client->dev);
+ pm_runtime_enable(&client->dev);
+ pm_runtime_idle(&client->dev);
+
+ return 0;
+
+error_media_entity:
+ media_entity_cleanup(&imx355->sd.entity);
+
+error_handler_free:
+ v4l2_ctrl_handler_free(imx355->sd.ctrl_handler);
+
+error_probe:
+ mutex_destroy(&imx355->mutex);
+
+ return ret;
+}
+
+static int imx355_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct imx355 *imx355 = to_imx355(sd);
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+
+ mutex_destroy(&imx355->mutex);
+
+ return 0;
+}
+
+static const struct dev_pm_ops imx355_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(imx355_suspend, imx355_resume)
+};
+
+static const struct acpi_device_id imx355_acpi_ids[] = {
+ { "SONY355A" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, imx355_acpi_ids);
+
+static struct i2c_driver imx355_i2c_driver = {
+ .driver = {
+ .name = "imx355",
+ .pm = &imx355_pm_ops,
+ .acpi_match_table = ACPI_PTR(imx355_acpi_ids),
+ },
+ .probe_new = imx355_probe,
+ .remove = imx355_remove,
+};
+module_i2c_driver(imx355_i2c_driver);
+
+MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
+MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
+MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
+MODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>");
+MODULE_DESCRIPTION("Sony imx355 sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
index 49c6644cbba7..f122f03bd6b7 100644
--- a/drivers/media/i2c/lm3560.c
+++ b/drivers/media/i2c/lm3560.c
@@ -362,7 +362,8 @@ static int lm3560_subdev_init(struct lm3560_flash *flash,
v4l2_i2c_subdev_init(&flash->subdev_led[led_no], client, &lm3560_ops);
flash->subdev_led[led_no].flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- strcpy(flash->subdev_led[led_no].name, led_name);
+ strscpy(flash->subdev_led[led_no].name, led_name,
+ sizeof(flash->subdev_led[led_no].name));
rval = lm3560_init_controls(flash, led_no);
if (rval)
goto err_out;
diff --git a/drivers/media/i2c/lm3646.c b/drivers/media/i2c/lm3646.c
index 7e9967af36ec..12ef2653987b 100644
--- a/drivers/media/i2c/lm3646.c
+++ b/drivers/media/i2c/lm3646.c
@@ -278,7 +278,8 @@ static int lm3646_subdev_init(struct lm3646_flash *flash)
v4l2_i2c_subdev_init(&flash->subdev_led, client, &lm3646_ops);
flash->subdev_led.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- strcpy(flash->subdev_led.name, LM3646_NAME);
+ strscpy(flash->subdev_led.name, LM3646_NAME,
+ sizeof(flash->subdev_led.name));
rval = lm3646_init_controls(flash);
if (rval)
goto err_out;
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c
index 12e79f9e32d5..b8b2bf4cbfb2 100644
--- a/drivers/media/i2c/m5mols/m5mols_core.c
+++ b/drivers/media/i2c/m5mols/m5mols_core.c
@@ -987,7 +987,8 @@ static int m5mols_probe(struct i2c_client *client,
sd = &info->sd;
v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
- strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
+ /* Static name; NEVER use in new drivers! */
+ strscpy(sd->name, MODULE_NAME, sizeof(sd->name));
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sd->internal_ops = &m5mols_subdev_internal_ops;
diff --git a/drivers/media/i2c/max2175.c b/drivers/media/i2c/max2175.c
index 008a082cb8ad..7b226fadcdb8 100644
--- a/drivers/media/i2c/max2175.c
+++ b/drivers/media/i2c/max2175.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Maxim Integrated MAX2175 RF to Bits tuner driver
*
@@ -6,15 +7,6 @@
*
* Copyright (C) 2016 Maxim Integrated Products
* Copyright (C) 2017 Renesas Electronics Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/clk.h>
@@ -1165,7 +1157,7 @@ static int max2175_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
if (vt->index > 0)
return -EINVAL;
- strlcpy(vt->name, "RF", sizeof(vt->name));
+ strscpy(vt->name, "RF", sizeof(vt->name));
vt->type = V4L2_TUNER_RF;
vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
vt->rangelow = ctx->bands_rf->rangelow;
diff --git a/drivers/media/i2c/max2175.h b/drivers/media/i2c/max2175.h
index eb43373ce7e2..1ece587c153d 100644
--- a/drivers/media/i2c/max2175.h
+++ b/drivers/media/i2c/max2175.h
@@ -1,4 +1,5 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
* Maxim Integrated MAX2175 RF to Bits tuner driver
*
* This driver & most of the hard coded values are based on the reference
@@ -6,15 +7,6 @@
*
* Copyright (C) 2016 Maxim Integrated Products
* Copyright (C) 2017 Renesas Electronics Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#ifndef __MAX2175_H__
diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c
index 3db966db83eb..c63be01059b2 100644
--- a/drivers/media/i2c/msp3400-driver.c
+++ b/drivers/media/i2c/msp3400-driver.c
@@ -688,7 +688,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
#endif
if (!id)
- strlcpy(client->name, "msp3400", sizeof(client->name));
+ strscpy(client->name, "msp3400", sizeof(client->name));
if (msp_reset(client) == -1) {
dev_dbg_lvl(&client->dev, 1, msp_debug, "msp3400 not found\n");
@@ -703,8 +703,10 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
v4l2_i2c_subdev_init(sd, client, &msp_ops);
#if defined(CONFIG_MEDIA_CONTROLLER)
- state->pads[IF_AUD_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
- state->pads[IF_AUD_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ state->pads[MSP3400_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ state->pads[MSP3400_PAD_IF_INPUT].sig_type = PAD_SIGNAL_AUDIO;
+ state->pads[MSP3400_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ state->pads[MSP3400_PAD_OUT].sig_type = PAD_SIGNAL_AUDIO;
sd->entity.function = MEDIA_ENT_F_IF_AUD_DECODER;
diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h
index b6c7698bce5a..2bb9d5ff1bbd 100644
--- a/drivers/media/i2c/msp3400-driver.h
+++ b/drivers/media/i2c/msp3400-driver.h
@@ -52,6 +52,12 @@ extern int msp_standard;
extern bool msp_dolby;
extern int msp_stereo_thresh;
+enum msp3400_pads {
+ MSP3400_PAD_IF_INPUT,
+ MSP3400_PAD_OUT,
+ MSP3400_NUM_PADS
+};
+
struct msp_state {
struct v4l2_subdev sd;
struct v4l2_ctrl_handler hdl;
@@ -106,7 +112,7 @@ struct msp_state {
unsigned int watch_stereo:1;
#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
- struct media_pad pads[IF_AUD_DEC_PAD_NUM_PADS];
+ struct media_pad pads[MSP3400_NUM_PADS];
#endif
};
diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c
index efda1aa95ca0..1395986a07bb 100644
--- a/drivers/media/i2c/mt9m111.c
+++ b/drivers/media/i2c/mt9m111.c
@@ -445,7 +445,6 @@ static int mt9m111_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = MT9M111_MIN_DARK_COLS;
sel->r.top = MT9M111_MIN_DARK_ROWS;
sel->r.width = MT9M111_MAX_WIDTH;
diff --git a/drivers/media/i2c/mt9t112.c b/drivers/media/i2c/mt9t112.c
index af8cca984215..ef353a244e33 100644
--- a/drivers/media/i2c/mt9t112.c
+++ b/drivers/media/i2c/mt9t112.c
@@ -888,12 +888,6 @@ static int mt9t112_get_selection(struct v4l2_subdev *sd,
sel->r.width = MAX_WIDTH;
sel->r.height = MAX_HEIGHT;
return 0;
- case V4L2_SEL_TGT_CROP_DEFAULT:
- sel->r.left = 0;
- sel->r.top = 0;
- sel->r.width = VGA_WIDTH;
- sel->r.height = VGA_HEIGHT;
- return 0;
case V4L2_SEL_TGT_CROP:
sel->r = priv->frame;
return 0;
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index f74730d24d8f..67f69ad6ecf4 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -989,7 +989,7 @@ static struct mt9v032_platform_data *
mt9v032_get_pdata(struct i2c_client *client)
{
struct mt9v032_platform_data *pdata = NULL;
- struct v4l2_fwnode_endpoint endpoint;
+ struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
struct device_node *np;
struct property *prop;
diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c
index 88c498ad45df..11479e65a9ae 100644
--- a/drivers/media/i2c/noon010pc30.c
+++ b/drivers/media/i2c/noon010pc30.c
@@ -720,7 +720,8 @@ static int noon010_probe(struct i2c_client *client,
mutex_init(&info->lock);
sd = &info->sd;
v4l2_i2c_subdev_init(sd, client, &noon010_ops);
- strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
+ /* Static name; NEVER use in new drivers! */
+ strscpy(sd->name, MODULE_NAME, sizeof(sd->name));
sd->internal_ops = &noon010_subdev_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c
index a66f6201f53c..c8bbc1f52261 100644
--- a/drivers/media/i2c/ov13858.c
+++ b/drivers/media/i2c/ov13858.c
@@ -1230,7 +1230,7 @@ static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl)
* Applying V4L2 control value only happens
* when power is up for streaming
*/
- if (pm_runtime_get_if_in_use(&client->dev) <= 0)
+ if (!pm_runtime_get_if_in_use(&client->dev))
return 0;
ret = 0;
@@ -1735,10 +1735,9 @@ static int ov13858_probe(struct i2c_client *client,
* Device is already turned on by i2c-core with ACPI domain PM.
* Enable runtime PM and turn off the device.
*/
- pm_runtime_get_noresume(&client->dev);
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
- pm_runtime_put(&client->dev);
+ pm_runtime_idle(&client->dev);
return 0;
@@ -1761,14 +1760,7 @@ static int ov13858_remove(struct i2c_client *client)
media_entity_cleanup(&sd->entity);
ov13858_free_controls(ov13858);
- /*
- * Disable runtime PM but keep the device turned on.
- * i2c-core with ACPI domain PM will turn off the device.
- */
- pm_runtime_get_sync(&client->dev);
pm_runtime_disable(&client->dev);
- pm_runtime_set_suspended(&client->dev);
- pm_runtime_put_noidle(&client->dev);
return 0;
}
diff --git a/drivers/media/i2c/ov2640.c b/drivers/media/i2c/ov2640.c
index beb722065152..20a8853ba1e2 100644
--- a/drivers/media/i2c/ov2640.c
+++ b/drivers/media/i2c/ov2640.c
@@ -1010,7 +1010,6 @@ static int ov2640_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP:
sel->r.left = 0;
sel->r.top = 0;
diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c
index 4715edc8ca33..799acce803fe 100644
--- a/drivers/media/i2c/ov2659.c
+++ b/drivers/media/i2c/ov2659.c
@@ -1347,8 +1347,9 @@ static struct ov2659_platform_data *
ov2659_get_pdata(struct i2c_client *client)
{
struct ov2659_platform_data *pdata;
- struct v4l2_fwnode_endpoint *bus_cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct device_node *endpoint;
+ int ret;
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
return client->dev.platform_data;
@@ -1357,8 +1358,9 @@ ov2659_get_pdata(struct i2c_client *client)
if (!endpoint)
return NULL;
- bus_cfg = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(endpoint));
- if (IS_ERR(bus_cfg)) {
+ ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(endpoint),
+ &bus_cfg);
+ if (ret) {
pdata = NULL;
goto done;
}
@@ -1367,17 +1369,17 @@ ov2659_get_pdata(struct i2c_client *client)
if (!pdata)
goto done;
- if (!bus_cfg->nr_of_link_frequencies) {
+ if (!bus_cfg.nr_of_link_frequencies) {
dev_err(&client->dev,
"link-frequencies property not found or too many\n");
pdata = NULL;
goto done;
}
- pdata->link_frequency = bus_cfg->link_frequencies[0];
+ pdata->link_frequency = bus_cfg.link_frequencies[0];
done:
- v4l2_fwnode_endpoint_free(bus_cfg);
+ v4l2_fwnode_endpoint_free(&bus_cfg);
of_node_put(endpoint);
return pdata;
}
diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c
index f753a1c333ef..0e34e15b67b3 100644
--- a/drivers/media/i2c/ov2680.c
+++ b/drivers/media/i2c/ov2680.c
@@ -926,7 +926,7 @@ static int ov2680_mode_init(struct ov2680_dev *sensor)
return 0;
}
-static int ov2680_v4l2_init(struct ov2680_dev *sensor)
+static int ov2680_v4l2_register(struct ov2680_dev *sensor)
{
const struct v4l2_ctrl_ops *ops = &ov2680_ctrl_ops;
struct ov2680_ctrls *ctrls = &sensor->ctrls;
@@ -1088,26 +1088,20 @@ static int ov2680_probe(struct i2c_client *client)
mutex_init(&sensor->lock);
- ret = ov2680_v4l2_init(sensor);
+ ret = ov2680_check_id(sensor);
if (ret < 0)
goto lock_destroy;
- ret = ov2680_check_id(sensor);
+ ret = ov2680_v4l2_register(sensor);
if (ret < 0)
- goto error_cleanup;
+ goto lock_destroy;
dev_info(dev, "ov2680 init correctly\n");
return 0;
-error_cleanup:
- dev_err(dev, "ov2680 init fail: %d\n", ret);
-
- media_entity_cleanup(&sensor->sd.entity);
- v4l2_async_unregister_subdev(&sensor->sd);
- v4l2_ctrl_handler_free(&sensor->ctrls.handler);
-
lock_destroy:
+ dev_err(dev, "ov2680 init fail: %d\n", ret);
mutex_destroy(&sensor->lock);
return ret;
diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c
index 385c1886a947..98a1f2e312b5 100644
--- a/drivers/media/i2c/ov2685.c
+++ b/drivers/media/i2c/ov2685.c
@@ -549,7 +549,7 @@ static int ov2685_set_ctrl(struct v4l2_ctrl *ctrl)
break;
}
- if (pm_runtime_get_if_in_use(&client->dev) <= 0)
+ if (!pm_runtime_get_if_in_use(&client->dev))
return 0;
switch (ctrl->id) {
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 071f4bc240ca..eaefdb58653b 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -223,8 +223,10 @@ struct ov5640_dev {
int power_count;
struct v4l2_mbus_framefmt fmt;
+ bool pending_fmt_change;
const struct ov5640_mode_info *current_mode;
+ const struct ov5640_mode_info *last_mode;
enum ov5640_frame_rate current_fr;
struct v4l2_fract frame_interval;
@@ -255,7 +257,7 @@ static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
* should be identified and removed to speed register load time
* over i2c.
*/
-
+/* YUV422 UYVY VGA@30fps */
static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
{0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
@@ -286,10 +288,10 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
{0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
- {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0},
+ {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0},
{0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
{0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x4837, 0x0a, 0, 0}, {0x3824, 0x02, 0, 0},
{0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
{0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
{0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
@@ -606,7 +608,7 @@ static const struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
{0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
{0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
{0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
- {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
{0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
{0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
};
@@ -908,6 +910,26 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
}
/* download ov5640 settings to sensor through i2c */
+static int ov5640_set_timings(struct ov5640_dev *sensor,
+ const struct ov5640_mode_info *mode)
+{
+ int ret;
+
+ ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact);
+ if (ret < 0)
+ return ret;
+
+ ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact);
+ if (ret < 0)
+ return ret;
+
+ ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot);
+ if (ret < 0)
+ return ret;
+
+ return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot);
+}
+
static int ov5640_load_regs(struct ov5640_dev *sensor,
const struct ov5640_mode_info *mode)
{
@@ -935,7 +957,13 @@ static int ov5640_load_regs(struct ov5640_dev *sensor,
usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
}
- return ret;
+ return ov5640_set_timings(sensor, mode);
+}
+
+static int ov5640_set_autoexposure(struct ov5640_dev *sensor, bool on)
+{
+ return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
+ BIT(0), on ? 0 : BIT(0));
}
/* read exposure, in number of line periods */
@@ -994,6 +1022,18 @@ static int ov5640_get_gain(struct ov5640_dev *sensor)
return gain & 0x3ff;
}
+static int ov5640_set_gain(struct ov5640_dev *sensor, int gain)
+{
+ return ov5640_write_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN,
+ (u16)gain & 0x3ff);
+}
+
+static int ov5640_set_autogain(struct ov5640_dev *sensor, bool on)
+{
+ return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
+ BIT(1), on ? 0 : BIT(1));
+}
+
static int ov5640_set_stream_dvp(struct ov5640_dev *sensor, bool on)
{
int ret;
@@ -1102,12 +1142,25 @@ static int ov5640_set_stream_mipi(struct ov5640_dev *sensor, bool on)
{
int ret;
- ret = ov5640_mod_reg(sensor, OV5640_REG_MIPI_CTRL00, BIT(5),
- on ? 0 : BIT(5));
- if (ret)
- return ret;
- ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00,
- on ? 0x00 : 0x70);
+ /*
+ * Enable/disable the MIPI interface
+ *
+ * 0x300e = on ? 0x45 : 0x40
+ *
+ * FIXME: the sensor manual (version 2.03) reports
+ * [7:5] = 000 : 1 data lane mode
+ * [7:5] = 001 : 2 data lanes mode
+ * But this settings do not work, while the following ones
+ * have been validated for 2 data lanes mode.
+ *
+ * [7:5] = 010 : 2 data lanes mode
+ * [4] = 0 : Power up MIPI HS Tx
+ * [3] = 0 : Power up MIPI LS Rx
+ * [2] = 1/0 : MIPI interface enable/disable
+ * [1:0] = 01/00: FIXME: 'debug'
+ */
+ ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00,
+ on ? 0x45 : 0x40);
if (ret)
return ret;
@@ -1331,7 +1384,7 @@ static int ov5640_set_ae_target(struct ov5640_dev *sensor, int target)
return ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL1F, fast_low);
}
-static int ov5640_binning_on(struct ov5640_dev *sensor)
+static int ov5640_get_binning(struct ov5640_dev *sensor)
{
u8 temp;
int ret;
@@ -1339,8 +1392,8 @@ static int ov5640_binning_on(struct ov5640_dev *sensor)
ret = ov5640_read_reg(sensor, OV5640_REG_TIMING_TC_REG21, &temp);
if (ret)
return ret;
- temp &= 0xfe;
- return temp ? 1 : 0;
+
+ return temp & BIT(0);
}
static int ov5640_set_binning(struct ov5640_dev *sensor, bool enable)
@@ -1385,30 +1438,6 @@ static int ov5640_set_virtual_channel(struct ov5640_dev *sensor)
return ov5640_write_reg(sensor, OV5640_REG_DEBUG_MODE, temp);
}
-static int ov5640_set_timings(struct ov5640_dev *sensor,
- const struct ov5640_mode_info *mode)
-{
- int ret;
-
- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact);
- if (ret < 0)
- return ret;
-
- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact);
- if (ret < 0)
- return ret;
-
- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot);
- if (ret < 0)
- return ret;
-
- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
static const struct ov5640_mode_info *
ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
int width, int height, bool nearest)
@@ -1450,7 +1479,7 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
if (ret < 0)
return ret;
prev_shutter = ret;
- ret = ov5640_binning_on(sensor);
+ ret = ov5640_get_binning(sensor);
if (ret < 0)
return ret;
if (ret && mode->id != OV5640_MODE_720P_1280_720 &&
@@ -1571,7 +1600,7 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
}
/* set capture gain */
- ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.gain, cap_gain16);
+ ret = ov5640_set_gain(sensor, cap_gain16);
if (ret)
return ret;
@@ -1584,7 +1613,7 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
}
/* set exposure */
- return __v4l2_ctrl_s_ctrl(sensor->ctrls.exposure, cap_shutter);
+ return ov5640_set_exposure(sensor, cap_shutter);
}
/*
@@ -1592,53 +1621,45 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
* change mode directly
*/
static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
- const struct ov5640_mode_info *mode,
- s32 exposure)
+ const struct ov5640_mode_info *mode)
{
- int ret;
-
if (!mode->reg_data)
return -EINVAL;
/* Write capture setting */
- ret = ov5640_load_regs(sensor, mode);
- if (ret < 0)
- return ret;
-
- /* turn auto gain/exposure back on for direct mode */
- ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 1);
- if (ret)
- return ret;
-
- return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, exposure);
+ return ov5640_load_regs(sensor, mode);
}
-static int ov5640_set_mode(struct ov5640_dev *sensor,
- const struct ov5640_mode_info *orig_mode)
+static int ov5640_set_mode(struct ov5640_dev *sensor)
{
const struct ov5640_mode_info *mode = sensor->current_mode;
+ const struct ov5640_mode_info *orig_mode = sensor->last_mode;
enum ov5640_downsize_mode dn_mode, orig_dn_mode;
- s32 exposure;
+ bool auto_gain = sensor->ctrls.auto_gain->val == 1;
+ bool auto_exp = sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
int ret;
dn_mode = mode->dn_mode;
orig_dn_mode = orig_mode->dn_mode;
/* auto gain and exposure must be turned off when changing modes */
- ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 0);
- if (ret)
- return ret;
+ if (auto_gain) {
+ ret = ov5640_set_autogain(sensor, false);
+ if (ret)
+ return ret;
+ }
- exposure = sensor->ctrls.auto_exp->val;
- ret = ov5640_set_exposure(sensor, V4L2_EXPOSURE_MANUAL);
- if (ret)
- return ret;
+ if (auto_exp) {
+ ret = ov5640_set_autoexposure(sensor, false);
+ if (ret)
+ goto restore_auto_gain;
+ }
if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
(dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
/*
* change between subsampling and scaling
- * go through exposure calucation
+ * go through exposure calculation
*/
ret = ov5640_set_mode_exposure_calc(sensor, mode);
} else {
@@ -1646,15 +1667,16 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
* change inside subsampling or scaling
* download firmware directly
*/
- ret = ov5640_set_mode_direct(sensor, mode, exposure);
+ ret = ov5640_set_mode_direct(sensor, mode);
}
-
if (ret < 0)
- return ret;
+ goto restore_auto_exp_gain;
- ret = ov5640_set_timings(sensor, mode);
- if (ret < 0)
- return ret;
+ /* restore auto gain and exposure */
+ if (auto_gain)
+ ov5640_set_autogain(sensor, true);
+ if (auto_exp)
+ ov5640_set_autoexposure(sensor, true);
ret = ov5640_set_binning(sensor, dn_mode != SCALING);
if (ret < 0)
@@ -1673,8 +1695,18 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
return ret;
sensor->pending_mode_change = false;
+ sensor->last_mode = mode;
return 0;
+
+restore_auto_exp_gain:
+ if (auto_exp)
+ ov5640_set_autoexposure(sensor, true);
+restore_auto_gain:
+ if (auto_gain)
+ ov5640_set_autogain(sensor, true);
+
+ return ret;
}
static int ov5640_set_framefmt(struct ov5640_dev *sensor,
@@ -1689,6 +1721,7 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor)
ret = ov5640_load_regs(sensor, &ov5640_mode_init_data);
if (ret < 0)
return ret;
+ sensor->last_mode = &ov5640_mode_init_data;
ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
(ilog2(OV5640_SCLK2X_ROOT_DIVIDER_DEFAULT) << 2) |
@@ -1697,7 +1730,7 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor)
return ret;
/* now restore the last capture mode */
- ret = ov5640_set_mode(sensor, &ov5640_mode_init_data);
+ ret = ov5640_set_mode(sensor);
if (ret < 0)
return ret;
@@ -1786,23 +1819,69 @@ static int ov5640_set_power(struct ov5640_dev *sensor, bool on)
if (ret)
goto power_off;
- if (sensor->ep.bus_type == V4L2_MBUS_CSI2) {
- /*
- * start streaming briefly followed by stream off in
- * order to coax the clock lane into LP-11 state.
- */
- ret = ov5640_set_stream_mipi(sensor, true);
- if (ret)
- goto power_off;
- usleep_range(1000, 2000);
- ret = ov5640_set_stream_mipi(sensor, false);
- if (ret)
- goto power_off;
+ /* We're done here for DVP bus, while CSI-2 needs setup. */
+ if (sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
+ return 0;
+
+ /*
+ * Power up MIPI HS Tx and LS Rx; 2 data lanes mode
+ *
+ * 0x300e = 0x40
+ * [7:5] = 010 : 2 data lanes mode (see FIXME note in
+ * "ov5640_set_stream_mipi()")
+ * [4] = 0 : Power up MIPI HS Tx
+ * [3] = 0 : Power up MIPI LS Rx
+ * [2] = 0 : MIPI interface disabled
+ */
+ ret = ov5640_write_reg(sensor,
+ OV5640_REG_IO_MIPI_CTRL00, 0x40);
+ if (ret)
+ goto power_off;
+
+ /*
+ * Gate clock and set LP11 in 'no packets mode' (idle)
+ *
+ * 0x4800 = 0x24
+ * [5] = 1 : Gate clock when 'no packets'
+ * [2] = 1 : MIPI bus in LP11 when 'no packets'
+ */
+ ret = ov5640_write_reg(sensor,
+ OV5640_REG_MIPI_CTRL00, 0x24);
+ if (ret)
+ goto power_off;
+
+ /*
+ * Set data lanes and clock in LP11 when 'sleeping'
+ *
+ * 0x3019 = 0x70
+ * [6] = 1 : MIPI data lane 2 in LP11 when 'sleeping'
+ * [5] = 1 : MIPI data lane 1 in LP11 when 'sleeping'
+ * [4] = 1 : MIPI clock lane in LP11 when 'sleeping'
+ */
+ ret = ov5640_write_reg(sensor,
+ OV5640_REG_PAD_OUTPUT00, 0x70);
+ if (ret)
+ goto power_off;
+
+ /* Give lanes some time to coax into LP11 state. */
+ usleep_range(500, 1000);
+
+ } else {
+ if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY) {
+ /* Reset MIPI bus settings to their default values. */
+ ov5640_write_reg(sensor,
+ OV5640_REG_IO_MIPI_CTRL00, 0x58);
+ ov5640_write_reg(sensor,
+ OV5640_REG_MIPI_CTRL00, 0x04);
+ ov5640_write_reg(sensor,
+ OV5640_REG_PAD_OUTPUT00, 0x00);
}
- return 0;
+ ov5640_set_power_off(sensor);
}
+ return 0;
+
power_off:
ov5640_set_power_off(sensor);
return ret;
@@ -1968,9 +2047,12 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
if (new_mode != sensor->current_mode) {
sensor->current_mode = new_mode;
- sensor->fmt = *mbus_fmt;
sensor->pending_mode_change = true;
}
+ if (mbus_fmt->code != sensor->fmt.code) {
+ sensor->fmt = *mbus_fmt;
+ sensor->pending_fmt_change = true;
+ }
out:
mutex_unlock(&sensor->lock);
return ret;
@@ -2137,20 +2219,20 @@ static int ov5640_set_ctrl_white_balance(struct ov5640_dev *sensor, int awb)
return ret;
}
-static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor, int exp)
+static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor,
+ enum v4l2_exposure_auto_type auto_exposure)
{
struct ov5640_ctrls *ctrls = &sensor->ctrls;
- bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO);
+ bool auto_exp = (auto_exposure == V4L2_EXPOSURE_AUTO);
int ret = 0;
if (ctrls->auto_exp->is_new) {
- ret = ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
- BIT(0), auto_exposure ? 0 : BIT(0));
+ ret = ov5640_set_autoexposure(sensor, auto_exp);
if (ret)
return ret;
}
- if (!auto_exposure && ctrls->exposure->is_new) {
+ if (!auto_exp && ctrls->exposure->is_new) {
u16 max_exp;
ret = ov5640_read_reg16(sensor, OV5640_REG_AEC_PK_VTS,
@@ -2170,25 +2252,19 @@ static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor, int exp)
return ret;
}
-static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, int auto_gain)
+static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, bool auto_gain)
{
struct ov5640_ctrls *ctrls = &sensor->ctrls;
int ret = 0;
if (ctrls->auto_gain->is_new) {
- ret = ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
- BIT(1),
- ctrls->auto_gain->val ? 0 : BIT(1));
+ ret = ov5640_set_autogain(sensor, auto_gain);
if (ret)
return ret;
}
- if (!auto_gain && ctrls->gain->is_new) {
- u16 gain = (u16)ctrls->gain->val;
-
- ret = ov5640_write_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN,
- gain & 0x3ff);
- }
+ if (!auto_gain && ctrls->gain->is_new)
+ ret = ov5640_set_gain(sensor, ctrls->gain->val);
return ret;
}
@@ -2261,16 +2337,12 @@ static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_AUTOGAIN:
- if (!ctrl->val)
- return 0;
val = ov5640_get_gain(sensor);
if (val < 0)
return val;
sensor->ctrls.gain->val = val;
break;
case V4L2_CID_EXPOSURE_AUTO:
- if (ctrl->val == V4L2_EXPOSURE_MANUAL)
- return 0;
val = ov5640_get_exposure(sensor);
if (val < 0)
return val;
@@ -2501,8 +2573,6 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
if (frame_rate < 0)
frame_rate = OV5640_15_FPS;
- sensor->current_fr = frame_rate;
- sensor->frame_interval = fi->interval;
mode = ov5640_find_mode(sensor, frame_rate, mode->hact,
mode->vact, true);
if (!mode) {
@@ -2510,7 +2580,10 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
goto out;
}
- if (mode != sensor->current_mode) {
+ if (mode != sensor->current_mode ||
+ frame_rate != sensor->current_fr) {
+ sensor->current_fr = frame_rate;
+ sensor->frame_interval = fi->interval;
sensor->current_mode = mode;
sensor->pending_mode_change = true;
}
@@ -2541,16 +2614,19 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
if (sensor->streaming == !enable) {
if (enable && sensor->pending_mode_change) {
- ret = ov5640_set_mode(sensor, sensor->current_mode);
+ ret = ov5640_set_mode(sensor);
if (ret)
goto out;
+ }
+ if (enable && sensor->pending_fmt_change) {
ret = ov5640_set_framefmt(sensor, &sensor->fmt);
if (ret)
goto out;
+ sensor->pending_fmt_change = false;
}
- if (sensor->ep.bus_type == V4L2_MBUS_CSI2)
+ if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY)
ret = ov5640_set_stream_mipi(sensor, enable);
else
ret = ov5640_set_stream_dvp(sensor, enable);
@@ -2642,9 +2718,14 @@ static int ov5640_probe(struct i2c_client *client,
return -ENOMEM;
sensor->i2c_client = client;
+
+ /*
+ * default init sequence initialize sensor to
+ * YUV422 UYVY VGA@30fps
+ */
fmt = &sensor->fmt;
- fmt->code = ov5640_formats[0].code;
- fmt->colorspace = ov5640_formats[0].colorspace;
+ fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
@@ -2656,7 +2737,7 @@ static int ov5640_probe(struct i2c_client *client,
sensor->current_fr = OV5640_30_FPS;
sensor->current_mode =
&ov5640_mode_data[OV5640_30_FPS][OV5640_MODE_VGA_640_480];
- sensor->pending_mode_change = true;
+ sensor->last_mode = sensor->current_mode;
sensor->ae_target = 52;
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 1722cdab0daf..5eba8dd7222b 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -1127,7 +1127,7 @@ static int ov5645_probe(struct i2c_client *client,
return ret;
}
- if (ov5645->ep.bus_type != V4L2_MBUS_CSI2) {
+ if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
dev_err(dev, "invalid bus type, must be CSI2\n");
return -EINVAL;
}
diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c
index da39c49de503..4589631798c9 100644
--- a/drivers/media/i2c/ov5647.c
+++ b/drivers/media/i2c/ov5647.c
@@ -532,7 +532,7 @@ static const struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = {
static int ov5647_parse_dt(struct device_node *np)
{
- struct v4l2_fwnode_endpoint bus_cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct device_node *ep;
int ret;
diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c
index 7b7c74d77370..041fcbb4eebd 100644
--- a/drivers/media/i2c/ov5670.c
+++ b/drivers/media/i2c/ov5670.c
@@ -2016,7 +2016,7 @@ static int ov5670_set_ctrl(struct v4l2_ctrl *ctrl)
}
/* V4L2 controls values will be applied only when power is already up */
- if (pm_runtime_get_if_in_use(&client->dev) <= 0)
+ if (!pm_runtime_get_if_in_use(&client->dev))
return 0;
switch (ctrl->id) {
@@ -2504,10 +2504,9 @@ static int ov5670_probe(struct i2c_client *client)
* Device is already turned on by i2c-core with ACPI domain PM.
* Enable runtime PM and turn off the device.
*/
- pm_runtime_get_noresume(&client->dev);
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
- pm_runtime_put(&client->dev);
+ pm_runtime_idle(&client->dev);
return 0;
@@ -2536,14 +2535,7 @@ static int ov5670_remove(struct i2c_client *client)
v4l2_ctrl_handler_free(sd->ctrl_handler);
mutex_destroy(&ov5670->mutex);
- /*
- * Disable runtime PM but keep the device turned on.
- * i2c-core with ACPI domain PM will turn off the device.
- */
- pm_runtime_get_sync(&client->dev);
pm_runtime_disable(&client->dev);
- pm_runtime_set_suspended(&client->dev);
- pm_runtime_put_noidle(&client->dev);
return 0;
}
diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c
index 9a80decd93d3..5d107c53364d 100644
--- a/drivers/media/i2c/ov5695.c
+++ b/drivers/media/i2c/ov5695.c
@@ -1110,7 +1110,7 @@ static int ov5695_set_ctrl(struct v4l2_ctrl *ctrl)
break;
}
- if (pm_runtime_get_if_in_use(&client->dev) <= 0)
+ if (!pm_runtime_get_if_in_use(&client->dev))
return 0;
switch (ctrl->id) {
diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c
index 17a34b4a819d..5d1b218bb7f0 100644
--- a/drivers/media/i2c/ov6650.c
+++ b/drivers/media/i2c/ov6650.c
@@ -449,7 +449,6 @@ static int ov6650_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = DEF_HSTRT << 1;
sel->r.top = DEF_VSTRT << 1;
sel->r.width = W_CIF;
diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c
index d3ebb7529fca..0c10203f822b 100644
--- a/drivers/media/i2c/ov7251.c
+++ b/drivers/media/i2c/ov7251.c
@@ -1279,9 +1279,9 @@ static int ov7251_probe(struct i2c_client *client)
return ret;
}
- if (ov7251->ep.bus_type != V4L2_MBUS_CSI2) {
+ if (ov7251->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
dev_err(dev, "invalid bus type (%u), must be CSI2 (%u)\n",
- ov7251->ep.bus_type, V4L2_MBUS_CSI2);
+ ov7251->ep.bus_type, V4L2_MBUS_CSI2_DPHY);
return -EINVAL;
}
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
index 31bf577b0bd3..bc68a3a5b4ec 100644
--- a/drivers/media/i2c/ov7670.c
+++ b/drivers/media/i2c/ov7670.c
@@ -1728,7 +1728,7 @@ static int ov7670_parse_dt(struct device *dev,
struct ov7670_info *info)
{
struct fwnode_handle *fwnode = dev_fwnode(dev);
- struct v4l2_fwnode_endpoint bus_cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct fwnode_handle *ep;
int ret;
@@ -1808,17 +1808,24 @@ static int ov7670_probe(struct i2c_client *client,
info->pclk_hb_disable = true;
}
- info->clk = devm_clk_get(&client->dev, "xclk");
- if (IS_ERR(info->clk))
- return PTR_ERR(info->clk);
- ret = clk_prepare_enable(info->clk);
- if (ret)
- return ret;
+ info->clk = devm_clk_get(&client->dev, "xclk"); /* optional */
+ if (IS_ERR(info->clk)) {
+ ret = PTR_ERR(info->clk);
+ if (ret == -ENOENT)
+ info->clk = NULL;
+ else
+ return ret;
+ }
+ if (info->clk) {
+ ret = clk_prepare_enable(info->clk);
+ if (ret)
+ return ret;
- info->clock_speed = clk_get_rate(info->clk) / 1000000;
- if (info->clock_speed < 10 || info->clock_speed > 48) {
- ret = -EINVAL;
- goto clk_disable;
+ info->clock_speed = clk_get_rate(info->clk) / 1000000;
+ if (info->clock_speed < 10 || info->clock_speed > 48) {
+ ret = -EINVAL;
+ goto clk_disable;
+ }
}
ret = ov7670_init_gpio(client, info);
diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
index 7158c31d8403..fefff7fd7d68 100644
--- a/drivers/media/i2c/ov772x.c
+++ b/drivers/media/i2c/ov772x.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/v4l2-mediabus.h>
#include <linux/videodev2.h>
@@ -414,6 +415,7 @@ struct ov772x_priv {
struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl;
struct clk *clk;
+ struct regmap *regmap;
struct ov772x_camera_info *info;
struct gpio_desc *pwdn_gpio;
struct gpio_desc *rstb_gpio;
@@ -549,51 +551,18 @@ static struct ov772x_priv *to_ov772x(struct v4l2_subdev *sd)
return container_of(sd, struct ov772x_priv, subdev);
}
-static int ov772x_read(struct i2c_client *client, u8 addr)
-{
- int ret;
- u8 val;
-
- ret = i2c_master_send(client, &addr, 1);
- if (ret < 0)
- return ret;
- ret = i2c_master_recv(client, &val, 1);
- if (ret < 0)
- return ret;
-
- return val;
-}
-
-static inline int ov772x_write(struct i2c_client *client, u8 addr, u8 value)
-{
- return i2c_smbus_write_byte_data(client, addr, value);
-}
-
-static int ov772x_mask_set(struct i2c_client *client, u8 command, u8 mask,
- u8 set)
-{
- s32 val = ov772x_read(client, command);
-
- if (val < 0)
- return val;
-
- val &= ~mask;
- val |= set & mask;
-
- return ov772x_write(client, command, val);
-}
-
-static int ov772x_reset(struct i2c_client *client)
+static int ov772x_reset(struct ov772x_priv *priv)
{
int ret;
- ret = ov772x_write(client, COM7, SCCB_RESET);
+ ret = regmap_write(priv->regmap, COM7, SCCB_RESET);
if (ret < 0)
return ret;
usleep_range(1000, 5000);
- return ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
+ return regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE,
+ SOFT_SLEEP_MODE);
}
/*
@@ -611,8 +580,8 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
if (priv->streaming == enable)
goto done;
- ret = ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE,
- enable ? 0 : SOFT_SLEEP_MODE);
+ ret = regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE,
+ enable ? 0 : SOFT_SLEEP_MODE);
if (ret)
goto done;
@@ -657,7 +626,6 @@ static int ov772x_set_frame_rate(struct ov772x_priv *priv,
const struct ov772x_color_format *cfmt,
const struct ov772x_win_size *win)
{
- struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
unsigned long fin = clk_get_rate(priv->clk);
unsigned int best_diff;
unsigned int fsize;
@@ -723,11 +691,11 @@ static int ov772x_set_frame_rate(struct ov772x_priv *priv,
}
}
- ret = ov772x_write(client, COM4, com4 | COM4_RESERVED);
+ ret = regmap_write(priv->regmap, COM4, com4 | COM4_RESERVED);
if (ret < 0)
return ret;
- ret = ov772x_write(client, CLKRC, clkrc | CLKRC_RESERVED);
+ ret = regmap_write(priv->regmap, CLKRC, clkrc | CLKRC_RESERVED);
if (ret < 0)
return ret;
@@ -788,8 +756,7 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct ov772x_priv *priv = container_of(ctrl->handler,
struct ov772x_priv, hdl);
- struct v4l2_subdev *sd = &priv->subdev;
- struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct regmap *regmap = priv->regmap;
int ret = 0;
u8 val;
@@ -808,27 +775,27 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
val = ctrl->val ? VFLIP_IMG : 0x00;
if (priv->info && (priv->info->flags & OV772X_FLAG_VFLIP))
val ^= VFLIP_IMG;
- return ov772x_mask_set(client, COM3, VFLIP_IMG, val);
+ return regmap_update_bits(regmap, COM3, VFLIP_IMG, val);
case V4L2_CID_HFLIP:
val = ctrl->val ? HFLIP_IMG : 0x00;
if (priv->info && (priv->info->flags & OV772X_FLAG_HFLIP))
val ^= HFLIP_IMG;
- return ov772x_mask_set(client, COM3, HFLIP_IMG, val);
+ return regmap_update_bits(regmap, COM3, HFLIP_IMG, val);
case V4L2_CID_BAND_STOP_FILTER:
if (!ctrl->val) {
/* Switch the filter off, it is on now */
- ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff);
+ ret = regmap_update_bits(regmap, BDBASE, 0xff, 0xff);
if (!ret)
- ret = ov772x_mask_set(client, COM8,
- BNDF_ON_OFF, 0);
+ ret = regmap_update_bits(regmap, COM8,
+ BNDF_ON_OFF, 0);
} else {
/* Switch the filter on, set AEC low limit */
val = 256 - ctrl->val;
- ret = ov772x_mask_set(client, COM8,
- BNDF_ON_OFF, BNDF_ON_OFF);
+ ret = regmap_update_bits(regmap, COM8,
+ BNDF_ON_OFF, BNDF_ON_OFF);
if (!ret)
- ret = ov772x_mask_set(client, BDBASE,
- 0xff, val);
+ ret = regmap_update_bits(regmap, BDBASE,
+ 0xff, val);
}
return ret;
@@ -841,18 +808,19 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
static int ov772x_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov772x_priv *priv = to_ov772x(sd);
int ret;
+ unsigned int val;
reg->size = 1;
if (reg->reg > 0xff)
return -EINVAL;
- ret = ov772x_read(client, reg->reg);
+ ret = regmap_read(priv->regmap, reg->reg, &val);
if (ret < 0)
return ret;
- reg->val = (__u64)ret;
+ reg->val = (__u64)val;
return 0;
}
@@ -860,13 +828,13 @@ static int ov772x_g_register(struct v4l2_subdev *sd,
static int ov772x_s_register(struct v4l2_subdev *sd,
const struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov772x_priv *priv = to_ov772x(sd);
if (reg->reg > 0xff ||
reg->val > 0xff)
return -EINVAL;
- return ov772x_write(client, reg->reg, reg->val);
+ return regmap_write(priv->regmap, reg->reg, reg->val);
}
#endif
@@ -896,6 +864,7 @@ static int ov772x_power_on(struct ov772x_priv *priv)
GPIOD_OUT_LOW);
if (IS_ERR(priv->rstb_gpio)) {
dev_info(&client->dev, "Unable to get GPIO \"reset\"");
+ clk_disable_unprepare(priv->clk);
return PTR_ERR(priv->rstb_gpio);
}
@@ -1004,7 +973,7 @@ static void ov772x_select_params(const struct v4l2_mbus_framefmt *mf,
static int ov772x_edgectrl(struct ov772x_priv *priv)
{
- struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
+ struct regmap *regmap = priv->regmap;
int ret;
if (!priv->info)
@@ -1018,19 +987,19 @@ static int ov772x_edgectrl(struct ov772x_priv *priv)
* Remove it when manual mode.
*/
- ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00);
+ ret = regmap_update_bits(regmap, DSPAUTO, EDGE_ACTRL, 0x00);
if (ret < 0)
return ret;
- ret = ov772x_mask_set(client,
- EDGE_TRSHLD, OV772X_EDGE_THRESHOLD_MASK,
- priv->info->edgectrl.threshold);
+ ret = regmap_update_bits(regmap, EDGE_TRSHLD,
+ OV772X_EDGE_THRESHOLD_MASK,
+ priv->info->edgectrl.threshold);
if (ret < 0)
return ret;
- ret = ov772x_mask_set(client,
- EDGE_STRNGT, OV772X_EDGE_STRENGTH_MASK,
- priv->info->edgectrl.strength);
+ ret = regmap_update_bits(regmap, EDGE_STRNGT,
+ OV772X_EDGE_STRENGTH_MASK,
+ priv->info->edgectrl.strength);
if (ret < 0)
return ret;
@@ -1040,15 +1009,15 @@ static int ov772x_edgectrl(struct ov772x_priv *priv)
*
* Set upper and lower limit.
*/
- ret = ov772x_mask_set(client,
- EDGE_UPPER, OV772X_EDGE_UPPER_MASK,
- priv->info->edgectrl.upper);
+ ret = regmap_update_bits(regmap, EDGE_UPPER,
+ OV772X_EDGE_UPPER_MASK,
+ priv->info->edgectrl.upper);
if (ret < 0)
return ret;
- ret = ov772x_mask_set(client,
- EDGE_LOWER, OV772X_EDGE_LOWER_MASK,
- priv->info->edgectrl.lower);
+ ret = regmap_update_bits(regmap, EDGE_LOWER,
+ OV772X_EDGE_LOWER_MASK,
+ priv->info->edgectrl.lower);
if (ret < 0)
return ret;
}
@@ -1060,12 +1029,11 @@ static int ov772x_set_params(struct ov772x_priv *priv,
const struct ov772x_color_format *cfmt,
const struct ov772x_win_size *win)
{
- struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
int ret;
u8 val;
/* Reset hardware. */
- ov772x_reset(client);
+ ov772x_reset(priv);
/* Edge Ctrl. */
ret = ov772x_edgectrl(priv);
@@ -1073,32 +1041,32 @@ static int ov772x_set_params(struct ov772x_priv *priv,
return ret;
/* Format and window size. */
- ret = ov772x_write(client, HSTART, win->rect.left >> 2);
+ ret = regmap_write(priv->regmap, HSTART, win->rect.left >> 2);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_write(client, HSIZE, win->rect.width >> 2);
+ ret = regmap_write(priv->regmap, HSIZE, win->rect.width >> 2);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_write(client, VSTART, win->rect.top >> 1);
+ ret = regmap_write(priv->regmap, VSTART, win->rect.top >> 1);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_write(client, VSIZE, win->rect.height >> 1);
+ ret = regmap_write(priv->regmap, VSIZE, win->rect.height >> 1);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_write(client, HOUTSIZE, win->rect.width >> 2);
+ ret = regmap_write(priv->regmap, HOUTSIZE, win->rect.width >> 2);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_write(client, VOUTSIZE, win->rect.height >> 1);
+ ret = regmap_write(priv->regmap, VOUTSIZE, win->rect.height >> 1);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_write(client, HREF,
+ ret = regmap_write(priv->regmap, HREF,
((win->rect.top & 1) << HREF_VSTART_SHIFT) |
((win->rect.left & 3) << HREF_HSTART_SHIFT) |
((win->rect.height & 1) << HREF_VSIZE_SHIFT) |
((win->rect.width & 3) << HREF_HSIZE_SHIFT));
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_write(client, EXHCH,
+ ret = regmap_write(priv->regmap, EXHCH,
((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) |
((win->rect.width & 3) << EXHCH_HSIZE_SHIFT));
if (ret < 0)
@@ -1107,15 +1075,14 @@ static int ov772x_set_params(struct ov772x_priv *priv,
/* Set DSP_CTRL3. */
val = cfmt->dsp3;
if (val) {
- ret = ov772x_mask_set(client,
- DSP_CTRL3, UV_MASK, val);
+ ret = regmap_update_bits(priv->regmap, DSP_CTRL3, UV_MASK, val);
if (ret < 0)
goto ov772x_set_fmt_error;
}
/* DSP_CTRL4: AEC reference point and DSP output format. */
if (cfmt->dsp4) {
- ret = ov772x_write(client, DSP_CTRL4, cfmt->dsp4);
+ ret = regmap_write(priv->regmap, DSP_CTRL4, cfmt->dsp4);
if (ret < 0)
goto ov772x_set_fmt_error;
}
@@ -1131,13 +1098,12 @@ static int ov772x_set_params(struct ov772x_priv *priv,
if (priv->hflip_ctrl->val)
val ^= HFLIP_IMG;
- ret = ov772x_mask_set(client,
- COM3, SWAP_MASK | IMG_MASK, val);
+ ret = regmap_update_bits(priv->regmap, COM3, SWAP_MASK | IMG_MASK, val);
if (ret < 0)
goto ov772x_set_fmt_error;
/* COM7: Sensor resolution and output format control. */
- ret = ov772x_write(client, COM7, win->com7_bit | cfmt->com7);
+ ret = regmap_write(priv->regmap, COM7, win->com7_bit | cfmt->com7);
if (ret < 0)
goto ov772x_set_fmt_error;
@@ -1150,10 +1116,11 @@ static int ov772x_set_params(struct ov772x_priv *priv,
if (priv->band_filter_ctrl->val) {
unsigned short band_filter = priv->band_filter_ctrl->val;
- ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, BNDF_ON_OFF);
+ ret = regmap_update_bits(priv->regmap, COM8,
+ BNDF_ON_OFF, BNDF_ON_OFF);
if (!ret)
- ret = ov772x_mask_set(client, BDBASE,
- 0xff, 256 - band_filter);
+ ret = regmap_update_bits(priv->regmap, BDBASE,
+ 0xff, 256 - band_filter);
if (ret < 0)
goto ov772x_set_fmt_error;
}
@@ -1162,7 +1129,7 @@ static int ov772x_set_params(struct ov772x_priv *priv,
ov772x_set_fmt_error:
- ov772x_reset(client);
+ ov772x_reset(priv);
return ret;
}
@@ -1180,7 +1147,6 @@ static int ov772x_get_selection(struct v4l2_subdev *sd,
sel->r.top = 0;
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP:
sel->r.width = priv->win->rect.width;
sel->r.height = priv->win->rect.height;
@@ -1276,12 +1242,12 @@ static int ov772x_video_probe(struct ov772x_priv *priv)
return ret;
/* Check and show product ID and manufacturer ID. */
- pid = ov772x_read(client, PID);
- if (pid < 0)
- return pid;
- ver = ov772x_read(client, VER);
- if (ver < 0)
- return ver;
+ ret = regmap_read(priv->regmap, PID, &pid);
+ if (ret < 0)
+ return ret;
+ ret = regmap_read(priv->regmap, VER, &ver);
+ if (ret < 0)
+ return ret;
switch (VERSION(pid, ver)) {
case OV7720:
@@ -1297,12 +1263,12 @@ static int ov772x_video_probe(struct ov772x_priv *priv)
goto done;
}
- midh = ov772x_read(client, MIDH);
- if (midh < 0)
- return midh;
- midl = ov772x_read(client, MIDL);
- if (midl < 0)
- return midl;
+ ret = regmap_read(priv->regmap, MIDH, &midh);
+ if (ret < 0)
+ return ret;
+ ret = regmap_read(priv->regmap, MIDL, &midl);
+ if (ret < 0)
+ return ret;
dev_info(&client->dev,
"%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
@@ -1386,8 +1352,12 @@ static int ov772x_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct ov772x_priv *priv;
- struct i2c_adapter *adapter = client->adapter;
int ret;
+ static const struct regmap_config ov772x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = DSPAUTO,
+ };
if (!client->dev.of_node && !client->dev.platform_data) {
dev_err(&client->dev,
@@ -1395,16 +1365,16 @@ static int ov772x_probe(struct i2c_client *client,
return -EINVAL;
}
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- dev_err(&adapter->dev,
- "I2C-Adapter doesn't support SMBUS_BYTE_DATA\n");
- return -EIO;
- }
-
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ priv->regmap = devm_regmap_init_sccb(client, &ov772x_regmap_config);
+ if (IS_ERR(priv->regmap)) {
+ dev_err(&client->dev, "Failed to allocate register map\n");
+ return PTR_ERR(priv->regmap);
+ }
+
priv->info = client->dev.platform_data;
mutex_init(&priv->lock);
diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c
index 605f3e25ad82..6e9c233cfbe3 100644
--- a/drivers/media/i2c/ov7740.c
+++ b/drivers/media/i2c/ov7740.c
@@ -510,7 +510,7 @@ static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
int ret;
u8 val = 0;
- if (pm_runtime_get_if_in_use(&client->dev) <= 0)
+ if (!pm_runtime_get_if_in_use(&client->dev))
return 0;
switch (ctrl->id) {
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c
index 5bea31cd41aa..f0587c0c0a72 100644
--- a/drivers/media/i2c/ov9650.c
+++ b/drivers/media/i2c/ov9650.c
@@ -20,6 +20,7 @@
#include <linux/media.h>
#include <linux/module.h>
#include <linux/ratelimit.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/videodev2.h>
@@ -259,7 +260,7 @@ struct ov965x {
/* Protects the struct fields below */
struct mutex lock;
- struct i2c_client *client;
+ struct regmap *regmap;
/* Exposure row interval in us */
unsigned int exp_row_interval;
@@ -424,51 +425,42 @@ static inline struct ov965x *to_ov965x(struct v4l2_subdev *sd)
return container_of(sd, struct ov965x, sd);
}
-static int ov965x_read(struct i2c_client *client, u8 addr, u8 *val)
+static int ov965x_read(struct ov965x *ov965x, u8 addr, u8 *val)
{
- u8 buf = addr;
- struct i2c_msg msg = {
- .addr = client->addr,
- .flags = 0,
- .len = 1,
- .buf = &buf
- };
int ret;
+ unsigned int buf;
- ret = i2c_transfer(client->adapter, &msg, 1);
- if (ret == 1) {
- msg.flags = I2C_M_RD;
- ret = i2c_transfer(client->adapter, &msg, 1);
-
- if (ret == 1)
- *val = buf;
- }
+ ret = regmap_read(ov965x->regmap, addr, &buf);
+ if (!ret)
+ *val = buf;
+ else
+ *val = -1;
- v4l2_dbg(2, debug, client, "%s: 0x%02x @ 0x%02x. (%d)\n",
+ v4l2_dbg(2, debug, &ov965x->sd, "%s: 0x%02x @ 0x%02x. (%d)\n",
__func__, *val, addr, ret);
- return ret == 1 ? 0 : ret;
+ return ret;
}
-static int ov965x_write(struct i2c_client *client, u8 addr, u8 val)
+static int ov965x_write(struct ov965x *ov965x, u8 addr, u8 val)
{
- u8 buf[2] = { addr, val };
+ int ret;
- int ret = i2c_master_send(client, buf, 2);
+ ret = regmap_write(ov965x->regmap, addr, val);
- v4l2_dbg(2, debug, client, "%s: 0x%02x @ 0x%02X (%d)\n",
+ v4l2_dbg(2, debug, &ov965x->sd, "%s: 0x%02x @ 0x%02X (%d)\n",
__func__, val, addr, ret);
- return ret == 2 ? 0 : ret;
+ return ret;
}
-static int ov965x_write_array(struct i2c_client *client,
+static int ov965x_write_array(struct ov965x *ov965x,
const struct i2c_rv *regs)
{
int i, ret = 0;
for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++)
- ret = ov965x_write(client, regs[i].addr, regs[i].value);
+ ret = ov965x_write(ov965x, regs[i].addr, regs[i].value);
return ret;
}
@@ -486,7 +478,7 @@ static int ov965x_set_default_gamma_curve(struct ov965x *ov965x)
unsigned int i;
for (i = 0; i < ARRAY_SIZE(gamma_curve); i++) {
- int ret = ov965x_write(ov965x->client, addr, gamma_curve[i]);
+ int ret = ov965x_write(ov965x, addr, gamma_curve[i]);
if (ret < 0)
return ret;
@@ -506,7 +498,7 @@ static int ov965x_set_color_matrix(struct ov965x *ov965x)
unsigned int i;
for (i = 0; i < ARRAY_SIZE(mtx); i++) {
- int ret = ov965x_write(ov965x->client, addr, mtx[i]);
+ int ret = ov965x_write(ov965x, addr, mtx[i]);
if (ret < 0)
return ret;
@@ -542,16 +534,15 @@ static int __ov965x_set_power(struct ov965x *ov965x, int on)
static int ov965x_s_power(struct v4l2_subdev *sd, int on)
{
struct ov965x *ov965x = to_ov965x(sd);
- struct i2c_client *client = ov965x->client;
int ret = 0;
- v4l2_dbg(1, debug, client, "%s: on: %d\n", __func__, on);
+ v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on);
mutex_lock(&ov965x->lock);
if (ov965x->power == !on) {
ret = __ov965x_set_power(ov965x, on);
if (!ret && on) {
- ret = ov965x_write_array(client,
+ ret = ov965x_write_array(ov965x,
ov965x_init_regs);
ov965x->apply_frame_fmt = 1;
ov965x->ctrls.update = 1;
@@ -609,13 +600,13 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value)
int ret;
u8 reg;
- ret = ov965x_read(ov965x->client, REG_COM8, &reg);
+ ret = ov965x_read(ov965x, REG_COM8, &reg);
if (!ret) {
if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED)
reg &= ~COM8_BFILT;
else
reg |= COM8_BFILT;
- ret = ov965x_write(ov965x->client, REG_COM8, reg);
+ ret = ov965x_write(ov965x, REG_COM8, reg);
}
if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED)
return 0;
@@ -631,7 +622,7 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value)
ov965x->fiv->interval.numerator;
mbd = ((mbd / (light_freq * 2)) + 500) / 1000UL;
- return ov965x_write(ov965x->client, REG_MBD, mbd);
+ return ov965x_write(ov965x, REG_MBD, mbd);
}
static int ov965x_set_white_balance(struct ov965x *ov965x, int awb)
@@ -639,17 +630,17 @@ static int ov965x_set_white_balance(struct ov965x *ov965x, int awb)
int ret;
u8 reg;
- ret = ov965x_read(ov965x->client, REG_COM8, &reg);
+ ret = ov965x_read(ov965x, REG_COM8, &reg);
if (!ret) {
reg = awb ? reg | REG_COM8 : reg & ~REG_COM8;
- ret = ov965x_write(ov965x->client, REG_COM8, reg);
+ ret = ov965x_write(ov965x, REG_COM8, reg);
}
if (!ret && !awb) {
- ret = ov965x_write(ov965x->client, REG_BLUE,
+ ret = ov965x_write(ov965x, REG_BLUE,
ov965x->ctrls.blue_balance->val);
if (ret < 0)
return ret;
- ret = ov965x_write(ov965x->client, REG_RED,
+ ret = ov965x_write(ov965x, REG_RED,
ov965x->ctrls.red_balance->val);
}
return ret;
@@ -677,14 +668,13 @@ static int ov965x_set_brightness(struct ov965x *ov965x, int val)
return -EINVAL;
for (i = 0; i < NUM_BR_REGS && !ret; i++)
- ret = ov965x_write(ov965x->client, regs[0][i],
+ ret = ov965x_write(ov965x, regs[0][i],
regs[val][i]);
return ret;
}
static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain)
{
- struct i2c_client *client = ov965x->client;
struct ov965x_ctrls *ctrls = &ov965x->ctrls;
int ret = 0;
u8 reg;
@@ -693,14 +683,14 @@ static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain)
* gain value in REG_VREF, REG_GAIN is not overwritten.
*/
if (ctrls->auto_gain->is_new) {
- ret = ov965x_read(client, REG_COM8, &reg);
+ ret = ov965x_read(ov965x, REG_COM8, &reg);
if (ret < 0)
return ret;
if (ctrls->auto_gain->val)
reg |= COM8_AGC;
else
reg &= ~COM8_AGC;
- ret = ov965x_write(client, REG_COM8, reg);
+ ret = ov965x_write(ov965x, REG_COM8, reg);
if (ret < 0)
return ret;
}
@@ -719,15 +709,15 @@ static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain)
rgain = (gain - ((1 << m) * 16)) / (1 << m);
rgain |= (((1 << m) - 1) << 4);
- ret = ov965x_write(client, REG_GAIN, rgain & 0xff);
+ ret = ov965x_write(ov965x, REG_GAIN, rgain & 0xff);
if (ret < 0)
return ret;
- ret = ov965x_read(client, REG_VREF, &reg);
+ ret = ov965x_read(ov965x, REG_VREF, &reg);
if (ret < 0)
return ret;
reg &= ~VREF_GAIN_MASK;
reg |= (((rgain >> 8) & 0x3) << 6);
- ret = ov965x_write(client, REG_VREF, reg);
+ ret = ov965x_write(ov965x, REG_VREF, reg);
if (ret < 0)
return ret;
/* Return updated control's value to userspace */
@@ -742,10 +732,10 @@ static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value)
u8 com14, edge;
int ret;
- ret = ov965x_read(ov965x->client, REG_COM14, &com14);
+ ret = ov965x_read(ov965x, REG_COM14, &com14);
if (ret < 0)
return ret;
- ret = ov965x_read(ov965x->client, REG_EDGE, &edge);
+ ret = ov965x_read(ov965x, REG_EDGE, &edge);
if (ret < 0)
return ret;
com14 = value ? com14 | COM14_EDGE_EN : com14 & ~COM14_EDGE_EN;
@@ -756,33 +746,32 @@ static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value)
} else {
com14 &= ~COM14_EEF_X2;
}
- ret = ov965x_write(ov965x->client, REG_COM14, com14);
+ ret = ov965x_write(ov965x, REG_COM14, com14);
if (ret < 0)
return ret;
edge &= ~EDGE_FACTOR_MASK;
edge |= ((u8)value & 0x0f);
- return ov965x_write(ov965x->client, REG_EDGE, edge);
+ return ov965x_write(ov965x, REG_EDGE, edge);
}
static int ov965x_set_exposure(struct ov965x *ov965x, int exp)
{
- struct i2c_client *client = ov965x->client;
struct ov965x_ctrls *ctrls = &ov965x->ctrls;
bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO);
int ret;
u8 reg;
if (ctrls->auto_exp->is_new) {
- ret = ov965x_read(client, REG_COM8, &reg);
+ ret = ov965x_read(ov965x, REG_COM8, &reg);
if (ret < 0)
return ret;
if (auto_exposure)
reg |= (COM8_AEC | COM8_AGC);
else
reg &= ~(COM8_AEC | COM8_AGC);
- ret = ov965x_write(client, REG_COM8, reg);
+ ret = ov965x_write(ov965x, REG_COM8, reg);
if (ret < 0)
return ret;
}
@@ -794,12 +783,12 @@ static int ov965x_set_exposure(struct ov965x *ov965x, int exp)
* Manual exposure value
* [b15:b0] - AECHM (b15:b10), AECH (b9:b2), COM1 (b1:b0)
*/
- ret = ov965x_write(client, REG_COM1, exposure & 0x3);
+ ret = ov965x_write(ov965x, REG_COM1, exposure & 0x3);
if (!ret)
- ret = ov965x_write(client, REG_AECH,
+ ret = ov965x_write(ov965x, REG_AECH,
(exposure >> 2) & 0xff);
if (!ret)
- ret = ov965x_write(client, REG_AECHM,
+ ret = ov965x_write(ov965x, REG_AECHM,
(exposure >> 10) & 0x3f);
/* Update the value to minimize rounding errors */
ctrls->exposure->val = ((exposure * ov965x->exp_row_interval)
@@ -822,7 +811,7 @@ static int ov965x_set_flip(struct ov965x *ov965x)
if (ov965x->ctrls.vflip->val)
mvfp |= MVFP_FLIP;
- return ov965x_write(ov965x->client, REG_MVFP, mvfp);
+ return ov965x_write(ov965x, REG_MVFP, mvfp);
}
#define NUM_SAT_LEVELS 5
@@ -846,7 +835,7 @@ static int ov965x_set_saturation(struct ov965x *ov965x, int val)
return -EINVAL;
for (i = 0; i < NUM_SAT_REGS && !ret; i++)
- ret = ov965x_write(ov965x->client, addr + i, regs[val][i]);
+ ret = ov965x_write(ov965x, addr + i, regs[val][i]);
return ret;
}
@@ -856,16 +845,15 @@ static int ov965x_set_test_pattern(struct ov965x *ov965x, int value)
int ret;
u8 reg;
- ret = ov965x_read(ov965x->client, REG_COM23, &reg);
+ ret = ov965x_read(ov965x, REG_COM23, &reg);
if (ret < 0)
return ret;
reg = value ? reg | COM23_TEST_MODE : reg & ~COM23_TEST_MODE;
- return ov965x_write(ov965x->client, REG_COM23, reg);
+ return ov965x_write(ov965x, REG_COM23, reg);
}
static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
{
- struct i2c_client *client = ov965x->client;
unsigned int exposure, gain, m;
u8 reg0, reg1, reg2;
int ret;
@@ -877,10 +865,10 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
case V4L2_CID_AUTOGAIN:
if (!ctrl->val)
return 0;
- ret = ov965x_read(client, REG_GAIN, &reg0);
+ ret = ov965x_read(ov965x, REG_GAIN, &reg0);
if (ret < 0)
return ret;
- ret = ov965x_read(client, REG_VREF, &reg1);
+ ret = ov965x_read(ov965x, REG_VREF, &reg1);
if (ret < 0)
return ret;
gain = ((reg1 >> 6) << 8) | reg0;
@@ -891,13 +879,13 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->val == V4L2_EXPOSURE_MANUAL)
return 0;
- ret = ov965x_read(client, REG_COM1, &reg0);
+ ret = ov965x_read(ov965x, REG_COM1, &reg0);
if (ret < 0)
return ret;
- ret = ov965x_read(client, REG_AECH, &reg1);
+ ret = ov965x_read(ov965x, REG_AECH, &reg1);
if (ret < 0)
return ret;
- ret = ov965x_read(client, REG_AECHM, &reg2);
+ ret = ov965x_read(ov965x, REG_AECHM, &reg2);
if (ret < 0)
return ret;
exposure = ((reg2 & 0x3f) << 10) | (reg1 << 2) |
@@ -1279,32 +1267,31 @@ static int ov965x_set_frame_size(struct ov965x *ov965x)
int i, ret = 0;
for (i = 0; ret == 0 && i < NUM_FMT_REGS; i++)
- ret = ov965x_write(ov965x->client, frame_size_reg_addr[i],
+ ret = ov965x_write(ov965x, frame_size_reg_addr[i],
ov965x->frame_size->regs[i]);
return ret;
}
static int __ov965x_set_params(struct ov965x *ov965x)
{
- struct i2c_client *client = ov965x->client;
struct ov965x_ctrls *ctrls = &ov965x->ctrls;
int ret = 0;
u8 reg;
if (ov965x->apply_frame_fmt) {
reg = DEF_CLKRC + ov965x->fiv->clkrc_div;
- ret = ov965x_write(client, REG_CLKRC, reg);
+ ret = ov965x_write(ov965x, REG_CLKRC, reg);
if (ret < 0)
return ret;
ret = ov965x_set_frame_size(ov965x);
if (ret < 0)
return ret;
- ret = ov965x_read(client, REG_TSLB, &reg);
+ ret = ov965x_read(ov965x, REG_TSLB, &reg);
if (ret < 0)
return ret;
reg &= ~TSLB_YUYV_MASK;
reg |= ov965x->tslb_reg;
- ret = ov965x_write(client, REG_TSLB, reg);
+ ret = ov965x_write(ov965x, REG_TSLB, reg);
if (ret < 0)
return ret;
}
@@ -1318,10 +1305,10 @@ static int __ov965x_set_params(struct ov965x *ov965x)
* Select manual banding filter, the filter will
* be enabled further if required.
*/
- ret = ov965x_read(client, REG_COM11, &reg);
+ ret = ov965x_read(ov965x, REG_COM11, &reg);
if (!ret)
reg |= COM11_BANDING;
- ret = ov965x_write(client, REG_COM11, reg);
+ ret = ov965x_write(ov965x, REG_COM11, reg);
if (ret < 0)
return ret;
/*
@@ -1333,12 +1320,11 @@ static int __ov965x_set_params(struct ov965x *ov965x)
static int ov965x_s_stream(struct v4l2_subdev *sd, int on)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov965x *ov965x = to_ov965x(sd);
struct ov965x_ctrls *ctrls = &ov965x->ctrls;
int ret = 0;
- v4l2_dbg(1, debug, client, "%s: on: %d\n", __func__, on);
+ v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on);
mutex_lock(&ov965x->lock);
if (ov965x->streaming == !on) {
@@ -1358,7 +1344,7 @@ static int ov965x_s_stream(struct v4l2_subdev *sd, int on)
ctrls->update = 0;
}
if (!ret)
- ret = ov965x_write(client, REG_COM2,
+ ret = ov965x_write(ov965x, REG_COM2,
on ? 0x01 : 0x11);
}
if (!ret)
@@ -1421,6 +1407,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
{
int ret, i;
int gpios[NUM_GPIOS];
+ struct device *dev = regmap_get_device(ov965x->regmap);
gpios[GPIO_PWDN] = pdata->gpio_pwdn;
gpios[GPIO_RST] = pdata->gpio_reset;
@@ -1430,7 +1417,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
if (!gpio_is_valid(gpio))
continue;
- ret = devm_gpio_request_one(&ov965x->client->dev, gpio,
+ ret = devm_gpio_request_one(dev, gpio,
GPIOF_OUT_INIT_HIGH, "OV965X");
if (ret < 0)
return ret;
@@ -1446,7 +1433,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
static int ov965x_configure_gpios(struct ov965x *ov965x)
{
- struct device *dev = &ov965x->client->dev;
+ struct device *dev = regmap_get_device(ov965x->regmap);
ov965x->gpios[GPIO_PWDN] = devm_gpiod_get_optional(dev, "powerdown",
GPIOD_OUT_HIGH);
@@ -1467,7 +1454,6 @@ static int ov965x_configure_gpios(struct ov965x *ov965x)
static int ov965x_detect_sensor(struct v4l2_subdev *sd)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov965x *ov965x = to_ov965x(sd);
u8 pid, ver;
int ret;
@@ -1480,9 +1466,9 @@ static int ov965x_detect_sensor(struct v4l2_subdev *sd)
msleep(25);
/* Check sensor revision */
- ret = ov965x_read(client, REG_PID, &pid);
+ ret = ov965x_read(ov965x, REG_PID, &pid);
if (!ret)
- ret = ov965x_read(client, REG_VER, &ver);
+ ret = ov965x_read(ov965x, REG_VER, &ver);
__ov965x_set_power(ov965x, 0);
@@ -1509,12 +1495,21 @@ static int ov965x_probe(struct i2c_client *client,
struct v4l2_subdev *sd;
struct ov965x *ov965x;
int ret;
+ static const struct regmap_config ov965x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xab,
+ };
ov965x = devm_kzalloc(&client->dev, sizeof(*ov965x), GFP_KERNEL);
if (!ov965x)
return -ENOMEM;
- ov965x->client = client;
+ ov965x->regmap = devm_regmap_init_sccb(client, &ov965x_regmap_config);
+ if (IS_ERR(ov965x->regmap)) {
+ dev_err(&client->dev, "Failed to allocate register map\n");
+ return PTR_ERR(ov965x->regmap);
+ }
if (pdata) {
if (pdata->mclk_frequency == 0) {
@@ -1527,7 +1522,7 @@ static int ov965x_probe(struct i2c_client *client,
if (ret < 0)
return ret;
} else if (dev_fwnode(&client->dev)) {
- ov965x->clk = devm_clk_get(&ov965x->client->dev, NULL);
+ ov965x->clk = devm_clk_get(&client->dev, NULL);
if (IS_ERR(ov965x->clk))
return PTR_ERR(ov965x->clk);
ov965x->mclk_frequency = clk_get_rate(ov965x->clk);
@@ -1546,7 +1541,7 @@ static int ov965x_probe(struct i2c_client *client,
sd = &ov965x->sd;
v4l2_i2c_subdev_init(sd, client, &ov965x_subdev_ops);
- strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name));
+ strscpy(sd->name, DRIVER_NAME, sizeof(sd->name));
sd->internal_ops = &ov965x_sd_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
diff --git a/drivers/media/i2c/rj54n1cb0c.c b/drivers/media/i2c/rj54n1cb0c.c
index 6ad998ad1b16..4cc51e001874 100644
--- a/drivers/media/i2c/rj54n1cb0c.c
+++ b/drivers/media/i2c/rj54n1cb0c.c
@@ -589,7 +589,6 @@ static int rj54n1_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = RJ54N1_COLUMN_SKIP;
sel->r.top = RJ54N1_ROW_SKIP;
sel->r.width = RJ54N1_MAX_WIDTH;
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index ce196b60f917..c461847ddae8 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -1603,7 +1603,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state)
const struct s5c73m3_platform_data *pdata = dev->platform_data;
struct device_node *node = dev->of_node;
struct device_node *node_ep;
- struct v4l2_fwnode_endpoint ep;
+ struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
int ret;
if (!node) {
@@ -1644,7 +1644,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state)
if (ret)
return ret;
- if (ep.bus_type != V4L2_MBUS_CSI2) {
+ if (ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
dev_err(dev, "unsupported bus type\n");
return -EINVAL;
}
@@ -1683,7 +1683,7 @@ static int s5c73m3_probe(struct i2c_client *client,
v4l2_subdev_init(sd, &s5c73m3_subdev_ops);
sd->owner = client->dev.driver->owner;
v4l2_set_subdevdata(sd, state);
- strlcpy(sd->name, "S5C73M3", sizeof(sd->name));
+ strscpy(sd->name, "S5C73M3", sizeof(sd->name));
sd->internal_ops = &s5c73m3_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -1698,7 +1698,8 @@ static int s5c73m3_probe(struct i2c_client *client,
return ret;
v4l2_i2c_subdev_init(oif_sd, client, &oif_subdev_ops);
- strcpy(oif_sd->name, "S5C73M3-OIF");
+ /* Static name; NEVER use in new drivers! */
+ strscpy(oif_sd->name, "S5C73M3-OIF", sizeof(oif_sd->name));
oif_sd->internal_ops = &oif_internal_ops;
oif_sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
index 6ebcf254989a..79aa2740edc4 100644
--- a/drivers/media/i2c/s5k4ecgx.c
+++ b/drivers/media/i2c/s5k4ecgx.c
@@ -954,7 +954,8 @@ static int s5k4ecgx_probe(struct i2c_client *client,
sd = &priv->sd;
/* Registering subdev */
v4l2_i2c_subdev_init(sd, client, &s5k4ecgx_ops);
- strlcpy(sd->name, S5K4ECGX_DRIVER_NAME, sizeof(sd->name));
+ /* Static name; NEVER use in new drivers! */
+ strscpy(sd->name, S5K4ECGX_DRIVER_NAME, sizeof(sd->name));
sd->internal_ops = &s5k4ecgx_subdev_internal_ops;
/* Support v4l2 sub-device user space API */
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 5007c9659342..727db7c0670a 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -766,7 +766,7 @@ static int s5k5baf_hw_set_video_bus(struct s5k5baf *state)
{
u16 en_pkts;
- if (state->bus_type == V4L2_MBUS_CSI2)
+ if (state->bus_type == V4L2_MBUS_CSI2_DPHY)
en_pkts = EN_PACKETS_CSI2;
else
en_pkts = 0;
@@ -1841,7 +1841,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev)
{
struct device_node *node = dev->of_node;
struct device_node *node_ep;
- struct v4l2_fwnode_endpoint ep;
+ struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
int ret;
if (!node) {
@@ -1875,7 +1875,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev)
state->bus_type = ep.bus_type;
switch (state->bus_type) {
- case V4L2_MBUS_CSI2:
+ case V4L2_MBUS_CSI2_DPHY:
state->nlanes = ep.bus.mipi_csi2.num_data_lanes;
break;
case V4L2_MBUS_PARALLEL:
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c
index 13c10b5e2b45..ab26f549d716 100644
--- a/drivers/media/i2c/s5k6aa.c
+++ b/drivers/media/i2c/s5k6aa.c
@@ -688,7 +688,7 @@ static int s5k6aa_configure_video_bus(struct s5k6aa *s5k6aa,
* but there is nothing indicating how to switch between both
* in the datasheet. For now default BT.601 interface is assumed.
*/
- if (bus_type == V4L2_MBUS_CSI2)
+ if (bus_type == V4L2_MBUS_CSI2_DPHY)
cfg = nlanes;
else if (bus_type != V4L2_MBUS_PARALLEL)
return -EINVAL;
@@ -1576,7 +1576,8 @@ static int s5k6aa_probe(struct i2c_client *client,
sd = &s5k6aa->sd;
v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops);
- strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name));
+ /* Static name; NEVER use in new drivers! */
+ strscpy(sd->name, DRIVER_NAME, sizeof(sd->name));
sd->internal_ops = &s5k6aa_subdev_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
index b07114b5efb2..6bc278aa31fc 100644
--- a/drivers/media/i2c/saa7115.c
+++ b/drivers/media/i2c/saa7115.c
@@ -59,10 +59,16 @@ enum saa711x_model {
SAA7118,
};
+enum saa711x_pads {
+ SAA711X_PAD_IF_INPUT,
+ SAA711X_PAD_VID_OUT,
+ SAA711X_NUM_PADS
+};
+
struct saa711x_state {
struct v4l2_subdev sd;
#ifdef CONFIG_MEDIA_CONTROLLER
- struct media_pad pads[DEMOD_NUM_PADS];
+ struct media_pad pads[SAA711X_NUM_PADS];
#endif
struct v4l2_ctrl_handler hdl;
@@ -1765,7 +1771,7 @@ static int saa711x_detect_chip(struct i2c_client *client,
* the lower nibble is a gm7113c.
*/
- strlcpy(name, "gm7113c", CHIP_VER_SIZE);
+ strscpy(name, "gm7113c", CHIP_VER_SIZE);
if (!autodetect && strcmp(name, id->name))
return -EINVAL;
@@ -1779,7 +1785,7 @@ static int saa711x_detect_chip(struct i2c_client *client,
/* Check if it is a CJC7113 */
if (!memcmp(name, "1111111111111111", CHIP_VER_SIZE)) {
- strlcpy(name, "cjc7113", CHIP_VER_SIZE);
+ strscpy(name, "cjc7113", CHIP_VER_SIZE);
if (!autodetect && strcmp(name, id->name))
return -EINVAL;
@@ -1825,7 +1831,7 @@ static int saa711x_probe(struct i2c_client *client,
if (ident < 0)
return ident;
- strlcpy(client->name, name, sizeof(client->name));
+ strscpy(client->name, name, sizeof(client->name));
state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
if (state == NULL)
@@ -1834,13 +1840,15 @@ static int saa711x_probe(struct i2c_client *client,
v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
#if defined(CONFIG_MEDIA_CONTROLLER)
- state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
- state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
- state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ state->pads[SAA711X_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ state->pads[SAA711X_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
+ state->pads[SAA711X_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ state->pads[SAA711X_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
- ret = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, state->pads);
+ ret = media_entity_pads_init(&sd->entity, SAA711X_NUM_PADS,
+ state->pads);
if (ret < 0)
return ret;
#endif
diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c
index e58a150cec5c..a67865b810c0 100644
--- a/drivers/media/i2c/saa7127.c
+++ b/drivers/media/i2c/saa7127.c
@@ -761,10 +761,10 @@ static int saa7127_probe(struct i2c_client *client,
saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2,
read_result);
state->ident = SAA7129;
- strlcpy(client->name, "saa7129", I2C_NAME_SIZE);
+ strscpy(client->name, "saa7129", I2C_NAME_SIZE);
} else {
state->ident = SAA7127;
- strlcpy(client->name, "saa7127", I2C_NAME_SIZE);
+ strscpy(client->name, "saa7127", I2C_NAME_SIZE);
}
}
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 1236683da8f7..58a45c353e27 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -624,7 +624,7 @@ static int smiapp_init_late_controls(struct smiapp_sensor *sensor)
{
unsigned long *valid_link_freqs = &sensor->valid_link_freqs[
sensor->csi_format->compressed - sensor->compressed_min_bpp];
- unsigned int max, i;
+ unsigned int i;
for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) {
int max_value = (1 << sensor->csi_format->width) - 1;
@@ -635,8 +635,6 @@ static int smiapp_init_late_controls(struct smiapp_sensor *sensor)
0, max_value, 1, max_value);
}
- for (max = 0; sensor->hwcfg->op_sys_clock[max + 1]; max++);
-
sensor->link_freq = v4l2_ctrl_new_int_menu(
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs),
@@ -2617,9 +2615,7 @@ static void smiapp_create_subdev(struct smiapp_sensor *sensor,
ssd->npads = num_pads;
ssd->source_pad = num_pads - 1;
- snprintf(ssd->sd.name,
- sizeof(ssd->sd.name), "%s %s %d-%4.4x", sensor->minfo.name,
- name, i2c_adapter_id(client->adapter), client->addr);
+ v4l2_i2c_subdev_set_name(&ssd->sd, client, sensor->minfo.name, name);
smiapp_get_native_size(ssd, &ssd->sink_fmt);
@@ -2761,7 +2757,7 @@ static int __maybe_unused smiapp_resume(struct device *dev)
static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
{
struct smiapp_hwconfig *hwcfg;
- struct v4l2_fwnode_endpoint *bus_cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct fwnode_handle *ep;
struct fwnode_handle *fwnode = dev_fwnode(dev);
u32 rotation;
@@ -2775,27 +2771,33 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
if (!ep)
return NULL;
- bus_cfg = v4l2_fwnode_endpoint_alloc_parse(ep);
- if (IS_ERR(bus_cfg))
+ bus_cfg.bus_type = V4L2_MBUS_CSI2_DPHY;
+ rval = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ if (rval == -ENXIO) {
+ bus_cfg = (struct v4l2_fwnode_endpoint)
+ { .bus_type = V4L2_MBUS_CCP2 };
+ rval = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ }
+ if (rval)
goto out_err;
hwcfg = devm_kzalloc(dev, sizeof(*hwcfg), GFP_KERNEL);
if (!hwcfg)
goto out_err;
- switch (bus_cfg->bus_type) {
- case V4L2_MBUS_CSI2:
+ switch (bus_cfg.bus_type) {
+ case V4L2_MBUS_CSI2_DPHY:
hwcfg->csi_signalling_mode = SMIAPP_CSI_SIGNALLING_MODE_CSI2;
- hwcfg->lanes = bus_cfg->bus.mipi_csi2.num_data_lanes;
+ hwcfg->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
break;
case V4L2_MBUS_CCP2:
- hwcfg->csi_signalling_mode = (bus_cfg->bus.mipi_csi1.strobe) ?
+ hwcfg->csi_signalling_mode = (bus_cfg.bus.mipi_csi1.strobe) ?
SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_STROBE :
SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_CLOCK;
hwcfg->lanes = 1;
break;
default:
- dev_err(dev, "unsupported bus %u\n", bus_cfg->bus_type);
+ dev_err(dev, "unsupported bus %u\n", bus_cfg.bus_type);
goto out_err;
}
@@ -2827,28 +2829,28 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
dev_dbg(dev, "nvm %d, clk %d, mode %d\n",
hwcfg->nvm_size, hwcfg->ext_clk, hwcfg->csi_signalling_mode);
- if (!bus_cfg->nr_of_link_frequencies) {
+ if (!bus_cfg.nr_of_link_frequencies) {
dev_warn(dev, "no link frequencies defined\n");
goto out_err;
}
hwcfg->op_sys_clock = devm_kcalloc(
- dev, bus_cfg->nr_of_link_frequencies + 1 /* guardian */,
+ dev, bus_cfg.nr_of_link_frequencies + 1 /* guardian */,
sizeof(*hwcfg->op_sys_clock), GFP_KERNEL);
if (!hwcfg->op_sys_clock)
goto out_err;
- for (i = 0; i < bus_cfg->nr_of_link_frequencies; i++) {
- hwcfg->op_sys_clock[i] = bus_cfg->link_frequencies[i];
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
+ hwcfg->op_sys_clock[i] = bus_cfg.link_frequencies[i];
dev_dbg(dev, "freq %d: %lld\n", i, hwcfg->op_sys_clock[i]);
}
- v4l2_fwnode_endpoint_free(bus_cfg);
+ v4l2_fwnode_endpoint_free(&bus_cfg);
fwnode_handle_put(ep);
return hwcfg;
out_err:
- v4l2_fwnode_endpoint_free(bus_cfg);
+ v4l2_fwnode_endpoint_free(&bus_cfg);
fwnode_handle_put(ep);
return NULL;
}
@@ -3064,9 +3066,9 @@ static int smiapp_probe(struct i2c_client *client,
if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
sensor->pll.flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
- smiapp_create_subdev(sensor, sensor->scaler, "scaler", 2);
- smiapp_create_subdev(sensor, sensor->binner, "binner", 2);
- smiapp_create_subdev(sensor, sensor->pixel_array, "pixel_array", 1);
+ smiapp_create_subdev(sensor, sensor->scaler, " scaler", 2);
+ smiapp_create_subdev(sensor, sensor->binner, " binner", 2);
+ smiapp_create_subdev(sensor, sensor->pixel_array, " pixel_array", 1);
dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile);
diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile
index 8c7770f62997..09ae483b96ef 100644
--- a/drivers/media/i2c/soc_camera/Makefile
+++ b/drivers/media/i2c/soc_camera/Makefile
@@ -1,10 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
-obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o
-obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
-obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o
-obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o
-obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o
-obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o
-obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o
-obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o
+obj-$(CONFIG_SOC_CAMERA_MT9M001) += soc_mt9m001.o
+obj-$(CONFIG_SOC_CAMERA_MT9T112) += soc_mt9t112.o
+obj-$(CONFIG_SOC_CAMERA_MT9V022) += soc_mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_OV5642) += soc_ov5642.o
+obj-$(CONFIG_SOC_CAMERA_OV772X) += soc_ov772x.o
+obj-$(CONFIG_SOC_CAMERA_OV9640) += soc_ov9640.o
+obj-$(CONFIG_SOC_CAMERA_OV9740) += soc_ov9740.o
+obj-$(CONFIG_SOC_CAMERA_RJ54N1) += soc_rj54n1cb0c.o
+obj-$(CONFIG_SOC_CAMERA_TW9910) += soc_tw9910.o
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/soc_mt9m001.c
index 1bfb0d53059e..a1a85ff838c5 100644
--- a/drivers/media/i2c/soc_camera/mt9m001.c
+++ b/drivers/media/i2c/soc_camera/soc_mt9m001.c
@@ -243,7 +243,6 @@ static int mt9m001_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = MT9M001_COLUMN_SKIP;
sel->r.top = MT9M001_ROW_SKIP;
sel->r.width = MT9M001_MAX_WIDTH;
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/soc_mt9t112.c
index b53c36dfa469..ea1ff270bc2d 100644
--- a/drivers/media/i2c/soc_camera/mt9t112.c
+++ b/drivers/media/i2c/soc_camera/soc_mt9t112.c
@@ -884,12 +884,6 @@ static int mt9t112_get_selection(struct v4l2_subdev *sd,
sel->r.width = MAX_WIDTH;
sel->r.height = MAX_HEIGHT;
return 0;
- case V4L2_SEL_TGT_CROP_DEFAULT:
- sel->r.left = 0;
- sel->r.top = 0;
- sel->r.width = VGA_WIDTH;
- sel->r.height = VGA_HEIGHT;
- return 0;
case V4L2_SEL_TGT_CROP:
sel->r = priv->frame;
return 0;
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/soc_mt9v022.c
index 762f06919329..6d922b17ea94 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/soc_mt9v022.c
@@ -368,7 +368,6 @@ static int mt9v022_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = MT9V022_COLUMN_SKIP;
sel->r.top = MT9V022_ROW_SKIP;
sel->r.width = MT9V022_MAX_WIDTH;
diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/soc_ov5642.c
index 39f420db9c70..0931898c79dd 100644
--- a/drivers/media/i2c/soc_camera/ov5642.c
+++ b/drivers/media/i2c/soc_camera/soc_ov5642.c
@@ -896,7 +896,6 @@ static int ov5642_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = 0;
sel->r.top = 0;
sel->r.width = OV5642_MAX_WIDTH;
@@ -913,7 +912,7 @@ static int ov5642_get_selection(struct v4l2_subdev *sd,
static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
struct v4l2_mbus_config *cfg)
{
- cfg->type = V4L2_MBUS_CSI2;
+ cfg->type = V4L2_MBUS_CSI2_DPHY;
cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/soc_ov772x.c
index 14377af7c888..fafd372527b2 100644
--- a/drivers/media/i2c/soc_camera/ov772x.c
+++ b/drivers/media/i2c/soc_camera/soc_ov772x.c
@@ -862,7 +862,6 @@ static int ov772x_get_selection(struct v4l2_subdev *sd,
sel->r.top = 0;
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.width = OV772X_MAX_WIDTH;
sel->r.height = OV772X_MAX_HEIGHT;
return 0;
diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/soc_ov9640.c
index c63948989688..eb91b8240083 100644
--- a/drivers/media/i2c/soc_camera/ov9640.c
+++ b/drivers/media/i2c/soc_camera/soc_ov9640.c
@@ -554,7 +554,6 @@ static int ov9640_get_selection(struct v4l2_subdev *sd,
sel->r.top = 0;
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP:
sel->r.width = W_SXGA;
sel->r.height = H_SXGA;
diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/soc_ov9740.c
index 755de2289c39..a07d3145d1b4 100644
--- a/drivers/media/i2c/soc_camera/ov9740.c
+++ b/drivers/media/i2c/soc_camera/soc_ov9740.c
@@ -730,7 +730,6 @@ static int ov9740_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP:
sel->r.left = 0;
sel->r.top = 0;
diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/soc_rj54n1cb0c.c
index 02398d0bc649..f0cb49a6167b 100644
--- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c
+++ b/drivers/media/i2c/soc_camera/soc_rj54n1cb0c.c
@@ -591,7 +591,6 @@ static int rj54n1_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = RJ54N1_COLUMN_SKIP;
sel->r.top = RJ54N1_ROW_SKIP;
sel->r.width = RJ54N1_MAX_WIDTH;
diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/soc_tw9910.c
index bdb5e0a431e9..bdb5e0a431e9 100644
--- a/drivers/media/i2c/soc_camera/tw9910.c
+++ b/drivers/media/i2c/soc_camera/soc_tw9910.c
diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c
index 2a4882cddc51..11f6c7a5e0e7 100644
--- a/drivers/media/i2c/sr030pc30.c
+++ b/drivers/media/i2c/sr030pc30.c
@@ -569,7 +569,7 @@ static int sr030pc30_base_config(struct v4l2_subdev *sd)
if (!ret)
ret = sr030pc30_pwr_ctrl(sd, false, false);
- if (!ret && !info->pdata)
+ if (ret)
return ret;
expmin = EXPOS_MIN_MS * info->pdata->clk_rate / (8 * 1000);
@@ -703,7 +703,6 @@ static int sr030pc30_probe(struct i2c_client *client,
return -ENOMEM;
sd = &info->sd;
- strcpy(sd->name, MODULE_NAME);
info->pdata = client->dev.platform_data;
v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops);
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
index 44c41933415a..ca5d92942820 100644
--- a/drivers/media/i2c/tc358743.c
+++ b/drivers/media/i2c/tc358743.c
@@ -1243,9 +1243,9 @@ static int tc358743_log_status(struct v4l2_subdev *sd)
u8 vi_status3 = i2c_rd8(sd, VI_STATUS3);
const int deep_color_mode[4] = { 8, 10, 12, 16 };
static const char * const input_color_space[] = {
- "RGB", "YCbCr 601", "Adobe RGB", "YCbCr 709", "NA (4)",
+ "RGB", "YCbCr 601", "opRGB", "YCbCr 709", "NA (4)",
"xvYCC 601", "NA(6)", "xvYCC 709", "NA(8)", "sYCC601",
- "NA(10)", "NA(11)", "NA(12)", "Adobe YCC 601"};
+ "NA(10)", "NA(11)", "NA(12)", "opYCC 601"};
v4l2_info(sd, "-----Chip status-----\n");
v4l2_info(sd, "Chip ID: 0x%02x\n",
@@ -1607,7 +1607,7 @@ static int tc358743_g_mbus_config(struct v4l2_subdev *sd,
{
struct tc358743_state *state = to_state(sd);
- cfg->type = V4L2_MBUS_CSI2;
+ cfg->type = V4L2_MBUS_CSI2_DPHY;
/* Support for non-continuous CSI-2 clock is missing in the driver */
cfg->flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
@@ -1789,7 +1789,7 @@ static int tc358743_s_edid(struct v4l2_subdev *sd,
return -E2BIG;
}
pa = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, NULL);
- err = cec_phys_addr_validate(pa, &pa, NULL);
+ err = v4l2_phys_addr_validate(pa, &pa, NULL);
if (err)
return err;
@@ -1895,11 +1895,11 @@ static void tc358743_gpio_reset(struct tc358743_state *state)
static int tc358743_probe_of(struct tc358743_state *state)
{
struct device *dev = &state->i2c_client->dev;
- struct v4l2_fwnode_endpoint *endpoint;
+ struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
struct device_node *ep;
struct clk *refclk;
u32 bps_pr_lane;
- int ret = -EINVAL;
+ int ret;
refclk = devm_clk_get(dev, "refclk");
if (IS_ERR(refclk)) {
@@ -1915,26 +1915,28 @@ static int tc358743_probe_of(struct tc358743_state *state)
return -EINVAL;
}
- endpoint = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep));
- if (IS_ERR(endpoint)) {
+ ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint);
+ if (ret) {
dev_err(dev, "failed to parse endpoint\n");
- ret = PTR_ERR(endpoint);
+ ret = ret;
goto put_node;
}
- if (endpoint->bus_type != V4L2_MBUS_CSI2 ||
- endpoint->bus.mipi_csi2.num_data_lanes == 0 ||
- endpoint->nr_of_link_frequencies == 0) {
+ if (endpoint.bus_type != V4L2_MBUS_CSI2_DPHY ||
+ endpoint.bus.mipi_csi2.num_data_lanes == 0 ||
+ endpoint.nr_of_link_frequencies == 0) {
dev_err(dev, "missing CSI-2 properties in endpoint\n");
+ ret = -EINVAL;
goto free_endpoint;
}
- if (endpoint->bus.mipi_csi2.num_data_lanes > 4) {
+ if (endpoint.bus.mipi_csi2.num_data_lanes > 4) {
dev_err(dev, "invalid number of lanes\n");
+ ret = -EINVAL;
goto free_endpoint;
}
- state->bus = endpoint->bus.mipi_csi2;
+ state->bus = endpoint.bus.mipi_csi2;
ret = clk_prepare_enable(refclk);
if (ret) {
@@ -1967,7 +1969,7 @@ static int tc358743_probe_of(struct tc358743_state *state)
* The CSI bps per lane must be between 62.5 Mbps and 1 Gbps.
* The default is 594 Mbps for 4-lane 1080p60 or 2-lane 720p60.
*/
- bps_pr_lane = 2 * endpoint->link_frequencies[0];
+ bps_pr_lane = 2 * endpoint.link_frequencies[0];
if (bps_pr_lane < 62500000U || bps_pr_lane > 1000000000U) {
dev_err(dev, "unsupported bps per lane: %u bps\n", bps_pr_lane);
goto disable_clk;
@@ -2013,7 +2015,7 @@ static int tc358743_probe_of(struct tc358743_state *state)
disable_clk:
clk_disable_unprepare(refclk);
free_endpoint:
- v4l2_fwnode_endpoint_free(endpoint);
+ v4l2_fwnode_endpoint_free(&endpoint);
put_node:
of_node_put(ep);
return ret;
diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c
index d114ac5243ec..c4c2a6134e1e 100644
--- a/drivers/media/i2c/tda1997x.c
+++ b/drivers/media/i2c/tda1997x.c
@@ -2265,7 +2265,7 @@ MODULE_DEVICE_TABLE(of, tda1997x_of_id);
static int tda1997x_parse_dt(struct tda1997x_state *state)
{
struct tda1997x_platform_data *pdata = &state->pdata;
- struct v4l2_fwnode_endpoint bus_cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct device_node *ep;
struct device_node *np;
unsigned int flags;
diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c
index 5919214a56bf..af2da977a685 100644
--- a/drivers/media/i2c/tvaudio.c
+++ b/drivers/media/i2c/tvaudio.c
@@ -1981,7 +1981,7 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id *
/* fill required data structures */
if (!id)
- strlcpy(client->name, desc->name, I2C_NAME_SIZE);
+ strscpy(client->name, desc->name, I2C_NAME_SIZE);
chip->desc = desc;
chip->shadow.count = desc->registers+1;
chip->prevmode = -1;
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index 675b9ae212ab..1cc83cb934e2 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -989,7 +989,7 @@ static struct tvp514x_platform_data *
tvp514x_get_pdata(struct i2c_client *client)
{
struct tvp514x_platform_data *pdata = NULL;
- struct v4l2_fwnode_endpoint bus_cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct device_node *endpoint;
unsigned int flags;
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 76e6bed5a1da..0e91b9949c3a 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -10,8 +10,10 @@
#include <linux/videodev2.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_graph.h>
+#include <linux/regmap.h>
#include <media/v4l2-async.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
@@ -26,6 +28,9 @@
#define TVP5150_MAX_CROP_LEFT 511
#define TVP5150_MAX_CROP_TOP 127
#define TVP5150_CROP_SHIFT 2
+#define TVP5150_MBUS_FMT MEDIA_BUS_FMT_UYVY8_2X8
+#define TVP5150_FIELD V4L2_FIELD_ALTERNATE
+#define TVP5150_COLORSPACE V4L2_COLORSPACE_SMPTE170M
MODULE_DESCRIPTION("Texas Instruments TVP5150A/TVP5150AM1/TVP5151 video decoder driver");
MODULE_AUTHOR("Mauro Carvalho Chehab");
@@ -38,20 +43,31 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
#define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
+enum tvp5150_pads {
+ TVP5150_PAD_IF_INPUT,
+ TVP5150_PAD_VID_OUT,
+ TVP5150_NUM_PADS
+};
+
struct tvp5150 {
struct v4l2_subdev sd;
#ifdef CONFIG_MEDIA_CONTROLLER
- struct media_pad pads[DEMOD_NUM_PADS];
+ struct media_pad pads[TVP5150_NUM_PADS];
struct media_entity input_ent[TVP5150_INPUT_NUM];
struct media_pad input_pad[TVP5150_INPUT_NUM];
#endif
struct v4l2_ctrl_handler hdl;
struct v4l2_rect rect;
+ struct regmap *regmap;
+ int irq;
v4l2_std_id norm; /* Current set standard */
+ v4l2_std_id detected_norm;
u32 input;
u32 output;
+ u32 oe;
int enable;
+ bool lock;
u16 dev_id;
u16 rom_ver;
@@ -71,32 +87,14 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
{
- struct i2c_client *c = v4l2_get_subdevdata(sd);
- int rc;
-
- rc = i2c_smbus_read_byte_data(c, addr);
- if (rc < 0) {
- dev_err(sd->dev, "i2c i/o error: rc == %d\n", rc);
- return rc;
- }
-
- dev_dbg_lvl(sd->dev, 2, debug, "tvp5150: read 0x%02x = %02x\n", addr, rc);
-
- return rc;
-}
-
-static int tvp5150_write(struct v4l2_subdev *sd, unsigned char addr,
- unsigned char value)
-{
- struct i2c_client *c = v4l2_get_subdevdata(sd);
- int rc;
+ struct tvp5150 *decoder = to_tvp5150(sd);
+ int ret, val;
- dev_dbg_lvl(sd->dev, 2, debug, "tvp5150: writing %02x %02x\n", addr, value);
- rc = i2c_smbus_write_byte_data(c, addr, value);
- if (rc < 0)
- dev_err(sd->dev, "i2c i/o error: rc == %d\n", rc);
+ ret = regmap_read(decoder->regmap, addr, &val);
+ if (ret < 0)
+ return ret;
- return rc;
+ return val;
}
static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init,
@@ -262,8 +260,8 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
{
int opmode = 0;
struct tvp5150 *decoder = to_tvp5150(sd);
+ unsigned int mask, val;
int input = 0;
- int val;
/* Only tvp5150am1 and tvp5151 have signal generator support */
if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) ||
@@ -288,8 +286,8 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
decoder->input, decoder->output,
input, opmode);
- tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode);
- tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input);
+ regmap_write(decoder->regmap, TVP5150_OP_MODE_CTL, opmode);
+ regmap_write(decoder->regmap, TVP5150_VD_IN_SRC_SEL_1, input);
/*
* Setup the FID/GLCO/VLK/HVLK and INTREQ/GPCL/VBLK output signals. For
@@ -298,17 +296,12 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
* field indicator (FID) signal on FID/GLCO/VLK/HVLK and set
* INTREQ/GPCL/VBLK to logic 1.
*/
- val = tvp5150_read(sd, TVP5150_MISC_CTL);
- if (val < 0) {
- dev_err(sd->dev, "%s: failed with error = %d\n", __func__, val);
- return;
- }
-
+ mask = TVP5150_MISC_CTL_GPCL | TVP5150_MISC_CTL_HVLK;
if (decoder->input == TVP5150_SVIDEO)
- val = (val & ~TVP5150_MISC_CTL_GPCL) | TVP5150_MISC_CTL_HVLK;
+ val = TVP5150_MISC_CTL_HVLK;
else
- val = (val & ~TVP5150_MISC_CTL_HVLK) | TVP5150_MISC_CTL_GPCL;
- tvp5150_write(sd, TVP5150_MISC_CTL, val);
+ val = TVP5150_MISC_CTL_GPCL;
+ regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
};
struct i2c_reg_value {
@@ -454,9 +447,7 @@ static const struct i2c_reg_value tvp5150_init_default[] = {
/* Default values as sugested at TVP5150AM1 datasheet */
static const struct i2c_reg_value tvp5150_init_enable[] = {
- {
- TVP5150_CONF_SHARED_PIN, 2
- }, { /* Automatic offset and AGC enabled */
+ { /* Automatic offset and AGC enabled */
TVP5150_ANAL_CHL_CTL, 0x15
}, { /* Activate YCrCb output 0x9 or 0xd ? */
TVP5150_MISC_CTL, TVP5150_MISC_CTL_GPCL |
@@ -583,8 +574,10 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = {
static int tvp5150_write_inittab(struct v4l2_subdev *sd,
const struct i2c_reg_value *regs)
{
+ struct tvp5150 *decoder = to_tvp5150(sd);
+
while (regs->reg != 0xff) {
- tvp5150_write(sd, regs->reg, regs->value);
+ regmap_write(decoder->regmap, regs->reg, regs->value);
regs++;
}
return 0;
@@ -592,15 +585,17 @@ static int tvp5150_write_inittab(struct v4l2_subdev *sd,
static int tvp5150_vdp_init(struct v4l2_subdev *sd)
{
+ struct tvp5150 *decoder = to_tvp5150(sd);
+ struct regmap *map = decoder->regmap;
unsigned int i;
int j;
/* Disable Full Field */
- tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
+ regmap_write(map, TVP5150_FULL_FIELD_ENA, 0);
/* Before programming, Line mode should be at 0xff */
for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++)
- tvp5150_write(sd, i, 0xff);
+ regmap_write(map, i, 0xff);
/* Load Ram Table */
for (j = 0; j < ARRAY_SIZE(vbi_ram_default); j++) {
@@ -609,11 +604,12 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd)
if (!regs->type.vbi_type)
continue;
- tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8);
- tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg);
+ regmap_write(map, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8);
+ regmap_write(map, TVP5150_CONF_RAM_ADDR_LOW, regs->reg);
for (i = 0; i < 16; i++)
- tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]);
+ regmap_write(map, TVP5150_VDP_CONF_RAM_DATA,
+ regs->values[i]);
}
return 0;
}
@@ -693,10 +689,10 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd,
reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI;
if (fields & 1)
- tvp5150_write(sd, reg, type);
+ regmap_write(decoder->regmap, reg, type);
if (fields & 2)
- tvp5150_write(sd, reg + 1, type);
+ regmap_write(decoder->regmap, reg + 1, type);
return type;
}
@@ -742,8 +738,6 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
struct tvp5150 *decoder = to_tvp5150(sd);
int fmt = 0;
- decoder->norm = std;
-
/* First tests should be against specific std */
if (std == V4L2_STD_NTSC_443) {
@@ -763,7 +757,16 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
}
dev_dbg_lvl(sd->dev, 1, debug, "Set video std register to %d.\n", fmt);
- tvp5150_write(sd, TVP5150_VIDEO_STD, fmt);
+ regmap_write(decoder->regmap, TVP5150_VIDEO_STD, fmt);
+ return 0;
+}
+
+static int tvp5150_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ struct tvp5150 *decoder = to_tvp5150(sd);
+
+ *std = decoder->norm;
+
return 0;
}
@@ -780,33 +783,166 @@ static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
else
decoder->rect.height = TVP5150_V_MAX_OTHERS;
+ decoder->norm = std;
return tvp5150_set_std(sd, std);
}
+static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
+{
+ int val = tvp5150_read(sd, TVP5150_STATUS_REG_5);
+
+ switch (val & 0x0F) {
+ case 0x01:
+ return V4L2_STD_NTSC;
+ case 0x03:
+ return V4L2_STD_PAL;
+ case 0x05:
+ return V4L2_STD_PAL_M;
+ case 0x07:
+ return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc;
+ case 0x09:
+ return V4L2_STD_NTSC_443;
+ case 0xb:
+ return V4L2_STD_SECAM;
+ default:
+ return V4L2_STD_UNKNOWN;
+ }
+}
+
+static int query_lock(struct v4l2_subdev *sd)
+{
+ struct tvp5150 *decoder = to_tvp5150(sd);
+ int status;
+
+ if (decoder->irq)
+ return decoder->lock;
+
+ regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);
+
+ /* For standard detection, we need the 3 locks */
+ return (status & 0x0e) == 0x0e;
+}
+
+static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
+{
+ *std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
+
+ return 0;
+}
+
+static const struct v4l2_event tvp5150_ev_fmt = {
+ .type = V4L2_EVENT_SOURCE_CHANGE,
+ .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+};
+
+static irqreturn_t tvp5150_isr(int irq, void *dev_id)
+{
+ struct tvp5150 *decoder = dev_id;
+ struct regmap *map = decoder->regmap;
+ unsigned int mask, active = 0, status = 0;
+
+ mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
+ TVP5150_MISC_CTL_CLOCK_OE;
+
+ regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
+ if (status) {
+ regmap_write(map, TVP5150_INT_STATUS_REG_A, status);
+
+ if (status & TVP5150_INT_A_LOCK) {
+ decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS);
+ dev_dbg_lvl(decoder->sd.dev, 1, debug,
+ "sync lo%s signal\n",
+ decoder->lock ? "ck" : "ss");
+ v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
+ regmap_update_bits(map, TVP5150_MISC_CTL, mask,
+ decoder->lock ? decoder->oe : 0);
+ }
+
+ return IRQ_HANDLED;
+ }
+
+ regmap_read(map, TVP5150_INT_ACTIVE_REG_B, &active);
+ if (active) {
+ status = 0;
+ regmap_read(map, TVP5150_INT_STATUS_REG_B, &status);
+ if (status)
+ regmap_write(map, TVP5150_INT_RESET_REG_B, status);
+ }
+
+ return IRQ_HANDLED;
+}
+
static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
{
struct tvp5150 *decoder = to_tvp5150(sd);
+ struct regmap *map = decoder->regmap;
/* Initializes TVP5150 to its default values */
tvp5150_write_inittab(sd, tvp5150_init_default);
+ if (decoder->irq) {
+ /* Configure pins: FID, VSYNC, INTREQ, SCLK */
+ regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x0);
+ /* Set interrupt polarity to active high */
+ regmap_write(map, TVP5150_INT_CONF, TVP5150_VDPOE | 0x1);
+ regmap_write(map, TVP5150_INTT_CONFIG_REG_B, 0x1);
+ } else {
+ /* Configure pins: FID, VSYNC, GPCL/VBLK, SCLK */
+ regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x2);
+ /* Keep interrupt polarity active low */
+ regmap_write(map, TVP5150_INT_CONF, TVP5150_VDPOE);
+ regmap_write(map, TVP5150_INTT_CONFIG_REG_B, 0x0);
+ }
+
/* Initializes VDP registers */
tvp5150_vdp_init(sd);
/* Selects decoder input */
tvp5150_selmux(sd);
+ /* Initialize image preferences */
+ v4l2_ctrl_handler_setup(&decoder->hdl);
+
+ return 0;
+}
+
+static int tvp5150_enable(struct v4l2_subdev *sd)
+{
+ struct tvp5150 *decoder = to_tvp5150(sd);
+ v4l2_std_id std;
+
/* Initializes TVP5150 to stream enabled values */
tvp5150_write_inittab(sd, tvp5150_init_enable);
- /* Initialize image preferences */
- v4l2_ctrl_handler_setup(&decoder->hdl);
+ if (decoder->norm == V4L2_STD_ALL)
+ std = tvp5150_read_std(sd);
+ else
+ std = decoder->norm;
- tvp5150_set_std(sd, decoder->norm);
+ /* Disable autoswitch mode */
+ tvp5150_set_std(sd, std);
- if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
- tvp5150_write(sd, TVP5150_DATA_RATE_SEL, 0x40);
+ /*
+ * Enable the YCbCr and clock outputs. In discrete sync mode
+ * (non-BT.656) additionally enable the the sync outputs.
+ */
+ switch (decoder->mbus_type) {
+ case V4L2_MBUS_PARALLEL:
+ /* 8-bit 4:2:2 YUV with discrete sync output */
+ regmap_update_bits(decoder->regmap, TVP5150_DATA_RATE_SEL,
+ 0x7, 0x0);
+ decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
+ TVP5150_MISC_CTL_CLOCK_OE |
+ TVP5150_MISC_CTL_SYNC_OE;
+ break;
+ case V4L2_MBUS_BT656:
+ decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
+ TVP5150_MISC_CTL_CLOCK_OE;
+ break;
+ default:
+ return -EINVAL;
+ }
return 0;
};
@@ -818,17 +954,18 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
- tvp5150_write(sd, TVP5150_BRIGHT_CTL, ctrl->val);
+ regmap_write(decoder->regmap, TVP5150_BRIGHT_CTL, ctrl->val);
return 0;
case V4L2_CID_CONTRAST:
- tvp5150_write(sd, TVP5150_CONTRAST_CTL, ctrl->val);
+ regmap_write(decoder->regmap, TVP5150_CONTRAST_CTL, ctrl->val);
return 0;
case V4L2_CID_SATURATION:
- tvp5150_write(sd, TVP5150_SATURATION_CTL, ctrl->val);
+ regmap_write(decoder->regmap, TVP5150_SATURATION_CTL,
+ ctrl->val);
return 0;
case V4L2_CID_HUE:
- tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val);
- break;
+ regmap_write(decoder->regmap, TVP5150_HUE_CTL, ctrl->val);
+ return 0;
case V4L2_CID_TEST_PATTERN:
decoder->enable = ctrl->val ? false : true;
tvp5150_selmux(sd);
@@ -837,36 +974,26 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL;
}
-static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
+static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop)
{
- int val = tvp5150_read(sd, TVP5150_STATUS_REG_5);
-
- switch (val & 0x0F) {
- case 0x01:
- return V4L2_STD_NTSC;
- case 0x03:
- return V4L2_STD_PAL;
- case 0x05:
- return V4L2_STD_PAL_M;
- case 0x07:
- return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc;
- case 0x09:
- return V4L2_STD_NTSC_443;
- case 0xb:
- return V4L2_STD_SECAM;
- default:
- return V4L2_STD_UNKNOWN;
- }
+ /* Default is no cropping */
+ crop->top = 0;
+ crop->left = 0;
+ crop->width = TVP5150_H_MAX;
+ if (std & V4L2_STD_525_60)
+ crop->height = TVP5150_V_MAX_525_60;
+ else
+ crop->height = TVP5150_V_MAX_OTHERS;
}
static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *format)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *f;
struct tvp5150 *decoder = to_tvp5150(sd);
- if (!format || (format->pad != DEMOD_PAD_VID_OUT))
+ if (!format || (format->pad != TVP5150_PAD_VID_OUT))
return -EINVAL;
f = &format->format;
@@ -874,12 +1001,12 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
f->width = decoder->rect.width;
f->height = decoder->rect.height / 2;
- f->code = MEDIA_BUS_FMT_UYVY8_2X8;
- f->field = V4L2_FIELD_ALTERNATE;
- f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ f->code = TVP5150_MBUS_FMT;
+ f->field = TVP5150_FIELD;
+ f->colorspace = TVP5150_COLORSPACE;
dev_dbg_lvl(sd->dev, 1, debug, "width = %d, height = %d\n", f->width,
- f->height);
+ f->height);
return 0;
}
@@ -901,9 +1028,6 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd,
/* tvp5150 has some special limits */
rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT);
- rect.width = clamp_t(unsigned int, rect.width,
- TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left,
- TVP5150_H_MAX - rect.left);
rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP);
/* Calculate height based on current standard */
@@ -917,22 +1041,29 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd,
else
hmax = TVP5150_V_MAX_OTHERS;
- rect.height = clamp_t(unsigned int, rect.height,
+ /*
+ * alignments:
+ * - width = 2 due to UYVY colorspace
+ * - height, image = no special alignment
+ */
+ v4l_bound_align_image(&rect.width,
+ TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left,
+ TVP5150_H_MAX - rect.left, 1, &rect.height,
hmax - TVP5150_MAX_CROP_TOP - rect.top,
- hmax - rect.top);
-
- tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top);
- tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP,
- rect.top + rect.height - hmax);
- tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB,
- rect.left >> TVP5150_CROP_SHIFT);
- tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB,
- rect.left | (1 << TVP5150_CROP_SHIFT));
- tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB,
- (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >>
- TVP5150_CROP_SHIFT);
- tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB,
- rect.left + rect.width - TVP5150_MAX_CROP_LEFT);
+ hmax - rect.top, 0, 0);
+
+ regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, rect.top);
+ regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP,
+ rect.top + rect.height - hmax);
+ regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_MSB,
+ rect.left >> TVP5150_CROP_SHIFT);
+ regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_LSB,
+ rect.left | (1 << TVP5150_CROP_SHIFT));
+ regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_MSB,
+ (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >>
+ TVP5150_CROP_SHIFT);
+ regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_LSB,
+ rect.left + rect.width - TVP5150_MAX_CROP_LEFT);
decoder->rect = rect;
@@ -951,7 +1082,6 @@ static int tvp5150_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = 0;
sel->r.top = 0;
sel->r.width = TVP5150_H_MAX;
@@ -989,6 +1119,27 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd,
/****************************************************************************
V4L2 subdev pad ops
****************************************************************************/
+static int tvp5150_init_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg)
+{
+ struct tvp5150 *decoder = to_tvp5150(sd);
+ v4l2_std_id std;
+
+ /*
+ * Reset selection to maximum on subdev_open() if autodetection is on
+ * and a standard change is detected.
+ */
+ if (decoder->norm == V4L2_STD_ALL) {
+ std = tvp5150_read_std(sd);
+ if (std != decoder->detected_norm) {
+ decoder->detected_norm = std;
+ tvp5150_set_default(std, &decoder->rect);
+ }
+ }
+
+ return 0;
+}
+
static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_mbus_code_enum *code)
@@ -996,7 +1147,7 @@ static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd,
if (code->pad || code->index)
return -EINVAL;
- code->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ code->code = TVP5150_MBUS_FMT;
return 0;
}
@@ -1006,10 +1157,10 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
{
struct tvp5150 *decoder = to_tvp5150(sd);
- if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_UYVY8_2X8)
+ if (fse->index >= 8 || fse->code != TVP5150_MBUS_FMT)
return -EINVAL;
- fse->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ fse->code = TVP5150_MBUS_FMT;
fse->min_width = decoder->rect.width;
fse->max_width = decoder->rect.width;
fse->min_height = decoder->rect.height / 2;
@@ -1059,27 +1210,28 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
{
struct tvp5150 *decoder = to_tvp5150(sd);
- int val;
+ unsigned int mask, val = 0, int_val = 0;
- /* Enable or disable the video output signals. */
- val = tvp5150_read(sd, TVP5150_MISC_CTL);
- if (val < 0)
- return val;
-
- val &= ~(TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
- TVP5150_MISC_CTL_CLOCK_OE);
+ mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
+ TVP5150_MISC_CTL_CLOCK_OE;
if (enable) {
- /*
- * Enable the YCbCr and clock outputs. In discrete sync mode
- * (non-BT.656) additionally enable the the sync outputs.
- */
- val |= TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
- if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
- val |= TVP5150_MISC_CTL_SYNC_OE;
+ tvp5150_enable(sd);
+
+ /* Enable outputs if decoder is locked */
+ if (decoder->irq)
+ val = decoder->lock ? decoder->oe : 0;
+ else
+ val = decoder->oe;
+ int_val = TVP5150_INT_A_LOCK;
+ v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
}
- tvp5150_write(sd, TVP5150_MISC_CTL, val);
+ regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
+ if (decoder->irq)
+ /* Enable / Disable lock interrupt */
+ regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
+ TVP5150_INT_A_LOCK, int_val);
return 0;
}
@@ -1103,6 +1255,8 @@ static int tvp5150_s_routing(struct v4l2_subdev *sd,
static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
{
+ struct tvp5150 *decoder = to_tvp5150(sd);
+
/*
* this is for capturing 36 raw vbi lines
* if there's a way to cut off the beginning 2 vbi lines
@@ -1112,16 +1266,18 @@ static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt
*/
if (fmt->sample_format == V4L2_PIX_FMT_GREY)
- tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70);
+ regmap_write(decoder->regmap, TVP5150_LUMA_PROC_CTL_1, 0x70);
if (fmt->count[0] == 18 && fmt->count[1] == 18) {
- tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00);
- tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01);
+ regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START,
+ 0x00);
+ regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP, 0x01);
}
return 0;
}
static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
{
+ struct tvp5150 *decoder = to_tvp5150(sd);
int i;
if (svbi->service_set != 0) {
@@ -1132,17 +1288,17 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
0xf0, i, 3);
}
/* Enables FIFO */
- tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1);
+ regmap_write(decoder->regmap, TVP5150_FIFO_OUT_CTRL, 1);
} else {
/* Disables FIFO*/
- tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 0);
+ regmap_write(decoder->regmap, TVP5150_FIFO_OUT_CTRL, 0);
/* Disable Full Field */
- tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
+ regmap_write(decoder->regmap, TVP5150_FULL_FIELD_ENA, 0);
/* Disable Line modes */
for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++)
- tvp5150_write(sd, i, 0xff);
+ regmap_write(decoder->regmap, i, 0xff);
}
return 0;
}
@@ -1180,7 +1336,9 @@ static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
static int tvp5150_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
{
- return tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff);
+ struct tvp5150 *decoder = to_tvp5150(sd);
+
+ return regmap_write(decoder->regmap, reg->reg & 0xff, reg->val & 0xff);
}
#endif
@@ -1217,7 +1375,7 @@ static int tvp5150_registered(struct v4l2_subdev *sd)
return ret;
ret = media_create_pad_link(input, 0, &sd->entity,
- DEMOD_PAD_IF_INPUT, 0);
+ TVP5150_PAD_IF_INPUT, 0);
if (ret < 0) {
media_device_unregister_entity(input);
return ret;
@@ -1249,6 +1407,8 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
.s_std = tvp5150_s_std,
+ .g_std = tvp5150_g_std,
+ .querystd = tvp5150_querystd,
.s_stream = tvp5150_s_stream,
.s_routing = tvp5150_s_routing,
.g_mbus_config = tvp5150_g_mbus_config,
@@ -1262,6 +1422,7 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
};
static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
+ .init_cfg = tvp5150_init_cfg,
.enum_mbus_code = tvp5150_enum_mbus_code,
.enum_frame_size = tvp5150_enum_frame_size,
.set_fmt = tvp5150_fill_fmt,
@@ -1282,16 +1443,87 @@ static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
.registered = tvp5150_registered,
};
-
/****************************************************************************
I2C Client & Driver
****************************************************************************/
+static const struct regmap_range tvp5150_readable_ranges[] = {
+ {
+ .range_min = TVP5150_VD_IN_SRC_SEL_1,
+ .range_max = TVP5150_AUTOSW_MSK,
+ }, {
+ .range_min = TVP5150_COLOR_KIL_THSH_CTL,
+ .range_max = TVP5150_CONF_SHARED_PIN,
+ }, {
+ .range_min = TVP5150_ACT_VD_CROP_ST_MSB,
+ .range_max = TVP5150_HORIZ_SYNC_START,
+ }, {
+ .range_min = TVP5150_VERT_BLANKING_START,
+ .range_max = TVP5150_INTT_CONFIG_REG_B,
+ }, {
+ .range_min = TVP5150_VIDEO_STD,
+ .range_max = TVP5150_VIDEO_STD,
+ }, {
+ .range_min = TVP5150_CB_GAIN_FACT,
+ .range_max = TVP5150_REV_SELECT,
+ }, {
+ .range_min = TVP5150_MSB_DEV_ID,
+ .range_max = TVP5150_STATUS_REG_5,
+ }, {
+ .range_min = TVP5150_CC_DATA_INI,
+ .range_max = TVP5150_TELETEXT_FIL_ENA,
+ }, {
+ .range_min = TVP5150_INT_STATUS_REG_A,
+ .range_max = TVP5150_FIFO_OUT_CTRL,
+ }, {
+ .range_min = TVP5150_FULL_FIELD_ENA,
+ .range_max = TVP5150_FULL_FIELD_MODE_REG,
+ },
+};
+
+static bool tvp5150_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TVP5150_VERT_LN_COUNT_MSB:
+ case TVP5150_VERT_LN_COUNT_LSB:
+ case TVP5150_INT_STATUS_REG_A:
+ case TVP5150_INT_STATUS_REG_B:
+ case TVP5150_INT_ACTIVE_REG_B:
+ case TVP5150_STATUS_REG_1:
+ case TVP5150_STATUS_REG_2:
+ case TVP5150_STATUS_REG_3:
+ case TVP5150_STATUS_REG_4:
+ case TVP5150_STATUS_REG_5:
+ /* CC, WSS, VPS, VITC data? */
+ case TVP5150_VBI_FIFO_READ_DATA:
+ case TVP5150_VDP_STATUS_REG:
+ case TVP5150_FIFO_WORD_COUNT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_access_table tvp5150_readable_table = {
+ .yes_ranges = tvp5150_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(tvp5150_readable_ranges),
+};
+
+static struct regmap_config tvp5150_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .rd_table = &tvp5150_readable_table,
+ .volatile_reg = tvp5150_volatile_reg,
+};
+
static int tvp5150_detect_version(struct tvp5150 *core)
{
struct v4l2_subdev *sd = &core->sd;
struct i2c_client *c = v4l2_get_subdevdata(sd);
- unsigned int i;
u8 regs[4];
int res;
@@ -1299,11 +1531,10 @@ static int tvp5150_detect_version(struct tvp5150 *core)
* Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID,
* TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER
*/
- for (i = 0; i < 4; i++) {
- res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i);
- if (res < 0)
- return res;
- regs[i] = res;
+ res = regmap_bulk_read(core->regmap, TVP5150_MSB_DEV_ID, regs, 4);
+ if (res < 0) {
+ dev_err(&c->dev, "reading ID registers failed: %d\n", res);
+ return res;
}
core->dev_id = (regs[0] << 8) | regs[1];
@@ -1319,7 +1550,7 @@ static int tvp5150_detect_version(struct tvp5150 *core)
dev_info(sd->dev, "tvp5150am1 detected.\n");
/* ITU-T BT.656.4 timing */
- tvp5150_write(sd, TVP5150_REV_SELECT, 0);
+ regmap_write(core->regmap, TVP5150_REV_SELECT, 0);
} else if (core->dev_id == 0x5151 && core->rom_ver == 0x0100) {
dev_info(sd->dev, "tvp5151 detected.\n");
} else {
@@ -1362,7 +1593,7 @@ static int tvp5150_init(struct i2c_client *c)
static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
{
- struct v4l2_fwnode_endpoint bus_cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct device_node *ep;
#ifdef CONFIG_MEDIA_CONTROLLER
struct device_node *connectors, *child;
@@ -1403,8 +1634,8 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
ret = of_property_read_u32(child, "input", &input_type);
if (ret) {
dev_err(decoder->sd.dev,
- "missing type property in node %s\n",
- child->name);
+ "missing type property in node %pOFn\n",
+ child);
goto err_connector;
}
@@ -1439,8 +1670,8 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
ret = of_property_read_string(child, "label", &name);
if (ret < 0) {
dev_err(decoder->sd.dev,
- "missing label property in node %s\n",
- child->name);
+ "missing label property in node %pOFn\n",
+ child);
goto err_connector;
}
@@ -1466,6 +1697,7 @@ static int tvp5150_probe(struct i2c_client *c,
struct tvp5150 *core;
struct v4l2_subdev *sd;
struct device_node *np = c->dev.of_node;
+ struct regmap *map;
int res;
/* Check if the adapter supports the needed features */
@@ -1481,6 +1713,11 @@ static int tvp5150_probe(struct i2c_client *c,
if (!core)
return -ENOMEM;
+ map = devm_regmap_init_i2c(c, &tvp5150_config);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ core->regmap = map;
sd = &core->sd;
if (IS_ENABLED(CONFIG_OF) && np) {
@@ -1499,13 +1736,14 @@ static int tvp5150_probe(struct i2c_client *c,
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
#if defined(CONFIG_MEDIA_CONTROLLER)
- core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
- core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
- core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ core->pads[TVP5150_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ core->pads[TVP5150_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
+ core->pads[TVP5150_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ core->pads[TVP5150_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
- res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads);
+ res = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, core->pads);
if (res < 0)
return res;
@@ -1517,6 +1755,7 @@ static int tvp5150_probe(struct i2c_client *c,
return res;
core->norm = V4L2_STD_ALL; /* Default is autodetect */
+ core->detected_norm = V4L2_STD_UNKNOWN;
core->input = TVP5150_COMPOSITE1;
core->enable = true;
@@ -1534,7 +1773,7 @@ static int tvp5150_probe(struct i2c_client *c,
27000000, 1, 27000000);
v4l2_ctrl_new_std_menu_items(&core->hdl, &tvp5150_ctrl_ops,
V4L2_CID_TEST_PATTERN,
- ARRAY_SIZE(tvp5150_test_patterns),
+ ARRAY_SIZE(tvp5150_test_patterns) - 1,
0, 0, tvp5150_test_patterns);
sd->ctrl_handler = &core->hdl;
if (core->hdl.error) {
@@ -1542,16 +1781,17 @@ static int tvp5150_probe(struct i2c_client *c,
goto err;
}
- /* Default is no cropping */
- core->rect.top = 0;
- if (tvp5150_read_std(sd) & V4L2_STD_525_60)
- core->rect.height = TVP5150_V_MAX_525_60;
- else
- core->rect.height = TVP5150_V_MAX_OTHERS;
- core->rect.left = 0;
- core->rect.width = TVP5150_H_MAX;
+ tvp5150_set_default(tvp5150_read_std(sd), &core->rect);
+ core->irq = c->irq;
tvp5150_reset(sd, 0); /* Calls v4l2_ctrl_handler_setup() */
+ if (c->irq) {
+ res = devm_request_threaded_irq(&c->dev, c->irq, NULL,
+ tvp5150_isr, IRQF_TRIGGER_HIGH |
+ IRQF_ONESHOT, "tvp5150", core);
+ if (res)
+ return res;
+ }
res = v4l2_async_register_subdev(sd);
if (res < 0)
diff --git a/drivers/media/i2c/tvp5150_reg.h b/drivers/media/i2c/tvp5150_reg.h
index d3a764cae1a0..9088186c24d1 100644
--- a/drivers/media/i2c/tvp5150_reg.h
+++ b/drivers/media/i2c/tvp5150_reg.h
@@ -125,8 +125,11 @@
#define TVP5150_TELETEXT_FIL_ENA 0xbb /* Teletext filter enable */
/* Reserved BCh-BFh */
#define TVP5150_INT_STATUS_REG_A 0xc0 /* Interrupt status register A */
+#define TVP5150_INT_A_LOCK_STATUS BIT(7)
+#define TVP5150_INT_A_LOCK BIT(6)
#define TVP5150_INT_ENABLE_REG_A 0xc1 /* Interrupt enable register A */
#define TVP5150_INT_CONF 0xc2 /* Interrupt configuration */
+#define TVP5150_VDPOE BIT(2)
#define TVP5150_VDP_CONF_RAM_DATA 0xc3 /* VDP configuration RAM data */
#define TVP5150_CONF_RAM_ADDR_LOW 0xc4 /* Configuration RAM address low byte */
#define TVP5150_CONF_RAM_ADDR_HIGH 0xc5 /* Configuration RAM address high byte */
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index 4f5c627579c7..cab2f2bd0aa9 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -889,7 +889,7 @@ static const struct v4l2_subdev_ops tvp7002_ops = {
static struct tvp7002_config *
tvp7002_get_pdata(struct i2c_client *client)
{
- struct v4l2_fwnode_endpoint bus_cfg;
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct tvp7002_config *pdata = NULL;
struct device_node *endpoint;
unsigned int flags;
diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
index 06d29d8f6be8..4d49af86c15e 100644
--- a/drivers/media/i2c/video-i2c.c
+++ b/drivers/media/i2c/video-i2c.c
@@ -352,8 +352,8 @@ static int video_i2c_querycap(struct file *file, void *priv,
struct video_i2c_data *data = video_drvdata(file);
struct i2c_client *client = data->client;
- strlcpy(vcap->driver, data->v4l2_dev.name, sizeof(vcap->driver));
- strlcpy(vcap->card, data->vdev.name, sizeof(vcap->card));
+ strscpy(vcap->driver, data->v4l2_dev.name, sizeof(vcap->driver));
+ strscpy(vcap->card, data->vdev.name, sizeof(vcap->card));
sprintf(vcap->bus_info, "I2C:%d-%d", client->adapter->nr, client->addr);
@@ -378,7 +378,7 @@ static int video_i2c_enum_input(struct file *file, void *fh,
if (vin->index > 0)
return -EINVAL;
- strlcpy(vin->name, "Camera", sizeof(vin->name));
+ strscpy(vin->name, "Camera", sizeof(vin->name));
vin->type = V4L2_INPUT_TYPE_CAMERA;
@@ -534,7 +534,7 @@ static int video_i2c_probe(struct i2c_client *client,
data->client = client;
v4l2_dev = &data->v4l2_dev;
- strlcpy(v4l2_dev->name, VIDEO_I2C_DRIVER, sizeof(v4l2_dev->name));
+ strscpy(v4l2_dev->name, VIDEO_I2C_DRIVER, sizeof(v4l2_dev->name));
ret = v4l2_device_register(&client->dev, v4l2_dev);
if (ret < 0)
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 3bae24b15eaa..4c7190db420e 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -69,14 +69,14 @@ static long media_device_get_info(struct media_device *dev, void *arg)
memset(info, 0, sizeof(*info));
if (dev->driver_name[0])
- strlcpy(info->driver, dev->driver_name, sizeof(info->driver));
+ strscpy(info->driver, dev->driver_name, sizeof(info->driver));
else
- strlcpy(info->driver, dev->dev->driver->name,
+ strscpy(info->driver, dev->dev->driver->name,
sizeof(info->driver));
- strlcpy(info->model, dev->model, sizeof(info->model));
- strlcpy(info->serial, dev->serial, sizeof(info->serial));
- strlcpy(info->bus_info, dev->bus_info, sizeof(info->bus_info));
+ strscpy(info->model, dev->model, sizeof(info->model));
+ strscpy(info->serial, dev->serial, sizeof(info->serial));
+ strscpy(info->bus_info, dev->bus_info, sizeof(info->bus_info));
info->media_version = LINUX_VERSION_CODE;
info->driver_version = info->media_version;
@@ -115,7 +115,7 @@ static long media_device_enum_entities(struct media_device *mdev, void *arg)
entd->id = media_entity_id(ent);
if (ent->name)
- strlcpy(entd->name, ent->name, sizeof(entd->name));
+ strscpy(entd->name, ent->name, sizeof(entd->name));
entd->type = ent->function;
entd->revision = 0; /* Unused */
entd->flags = ent->flags;
@@ -268,7 +268,7 @@ static long media_device_get_topology(struct media_device *mdev, void *arg)
kentity.id = entity->graph_obj.id;
kentity.function = entity->function;
kentity.flags = entity->flags;
- strlcpy(kentity.name, entity->name,
+ strscpy(kentity.name, entity->name,
sizeof(kentity.name));
if (copy_to_user(uentity, &kentity, sizeof(kentity)))
@@ -836,9 +836,9 @@ void media_device_pci_init(struct media_device *mdev,
mdev->dev = &pci_dev->dev;
if (name)
- strlcpy(mdev->model, name, sizeof(mdev->model));
+ strscpy(mdev->model, name, sizeof(mdev->model));
else
- strlcpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model));
+ strscpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model));
sprintf(mdev->bus_info, "PCI:%s", pci_name(pci_dev));
@@ -859,17 +859,17 @@ void __media_device_usb_init(struct media_device *mdev,
mdev->dev = &udev->dev;
if (driver_name)
- strlcpy(mdev->driver_name, driver_name,
+ strscpy(mdev->driver_name, driver_name,
sizeof(mdev->driver_name));
if (board_name)
- strlcpy(mdev->model, board_name, sizeof(mdev->model));
+ strscpy(mdev->model, board_name, sizeof(mdev->model));
else if (udev->product)
- strlcpy(mdev->model, udev->product, sizeof(mdev->model));
+ strscpy(mdev->model, udev->product, sizeof(mdev->model));
else
- strlcpy(mdev->model, "unknown model", sizeof(mdev->model));
+ strscpy(mdev->model, "unknown model", sizeof(mdev->model));
if (udev->serial)
- strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
+ strscpy(mdev->serial, udev->serial, sizeof(mdev->serial));
usb_make_path(udev, mdev->bus_info, sizeof(mdev->bus_info));
mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 3498551e618e..0b1cb3559140 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -662,6 +662,32 @@ static void __media_entity_remove_link(struct media_entity *entity,
kfree(link);
}
+int media_get_pad_index(struct media_entity *entity, bool is_sink,
+ enum media_pad_signal_type sig_type)
+{
+ int i;
+ bool pad_is_sink;
+
+ if (!entity)
+ return -EINVAL;
+
+ for (i = 0; i < entity->num_pads; i++) {
+ if (entity->pads[i].flags == MEDIA_PAD_FL_SINK)
+ pad_is_sink = true;
+ else if (entity->pads[i].flags == MEDIA_PAD_FL_SOURCE)
+ pad_is_sink = false;
+ else
+ continue; /* This is an error! */
+
+ if (pad_is_sink != is_sink)
+ continue;
+ if (entity->pads[i].sig_type == sig_type)
+ return i;
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(media_get_pad_index);
+
int
media_create_pad_link(struct media_entity *source, u16 source_pad,
struct media_entity *sink, u16 sink_pad, u32 flags)
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index cf05e11da01b..b2cfcbb0008e 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2040,7 +2040,6 @@ limit_scaled_size_lock (struct bttv_fh * fh,
max_width = max_width & width_mask;
/* Max. scale factor is 16:1 for frames, 8:1 for fields. */
- min_height = min_height;
/* Min. scale factor is 1:1. */
max_height >>= !V4L2_FIELD_HAS_BOTH(field);
@@ -2473,8 +2472,8 @@ static int bttv_querycap(struct file *file, void *priv,
if (0 == v4l2)
return -EINVAL;
- strlcpy(cap->driver, "bttv", sizeof(cap->driver));
- strlcpy(cap->card, btv->video_dev.name, sizeof(cap->card));
+ strscpy(cap->driver, "bttv", sizeof(cap->driver));
+ strscpy(cap->card, btv->video_dev.name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"PCI:%s", pci_name(btv->c.pci));
cap->capabilities =
@@ -2535,7 +2534,7 @@ static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
return -EINVAL;
f->pixelformat = formats[i].fourcc;
- strlcpy(f->description, formats[i].name, sizeof(f->description));
+ strscpy(f->description, formats[i].name, sizeof(f->description));
return i;
}
@@ -2782,7 +2781,7 @@ static int bttv_g_tuner(struct file *file, void *priv,
t->rxsubchans = V4L2_TUNER_SUB_MONO;
t->capability = V4L2_TUNER_CAP_NORM;
bttv_call_all(btv, tuner, g_tuner, t);
- strcpy(t->name, "Television");
+ strscpy(t->name, "Television", sizeof(t->name));
t->type = V4L2_TUNER_ANALOG_TV;
if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
t->signal = 0xffff;
@@ -3257,7 +3256,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
if (0 != t->index)
return -EINVAL;
- strcpy(t->name, "Radio");
+ strscpy(t->name, "Radio", sizeof(t->name));
t->type = V4L2_TUNER_RADIO;
radio_enable(btv);
diff --git a/drivers/media/pci/bt8xx/bttv-i2c.c b/drivers/media/pci/bt8xx/bttv-i2c.c
index c76823eb399d..15ff7f9d8373 100644
--- a/drivers/media/pci/bt8xx/bttv-i2c.c
+++ b/drivers/media/pci/bt8xx/bttv-i2c.c
@@ -347,13 +347,13 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
/* init + register i2c adapter */
int init_bttv_i2c(struct bttv *btv)
{
- strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
+ strscpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
if (i2c_hw)
btv->use_i2c_hw = 1;
if (btv->use_i2c_hw) {
/* bt878 */
- strlcpy(btv->c.i2c_adap.name, "bt878",
+ strscpy(btv->c.i2c_adap.name, "bt878",
sizeof(btv->c.i2c_adap.name));
btv->c.i2c_adap.algo = &bttv_algo;
} else {
@@ -362,7 +362,7 @@ int init_bttv_i2c(struct bttv *btv)
if (i2c_udelay<5)
i2c_udelay=5;
- strlcpy(btv->c.i2c_adap.name, "bttv",
+ strscpy(btv->c.i2c_adap.name, "bttv",
sizeof(btv->c.i2c_adap.name));
btv->i2c_algo = bttv_i2c_algo_bit_template;
btv->i2c_algo.udelay = i2c_udelay;
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
index 08266b23826e..d34fbaa027c2 100644
--- a/drivers/media/pci/bt8xx/bttv-input.c
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -370,7 +370,7 @@ static int get_key_pv951(struct IR_i2c *ir, enum rc_proto *protocol,
/* Instantiate the I2C IR receiver device, if present */
void init_bttv_i2c_ir(struct bttv *btv)
{
- const unsigned short addr_list[] = {
+ static const unsigned short addr_list[] = {
0x1a, 0x18, 0x64, 0x30, 0x71,
I2C_CLIENT_END
};
@@ -382,7 +382,7 @@ void init_bttv_i2c_ir(struct bttv *btv)
memset(&info, 0, sizeof(struct i2c_board_info));
memset(&btv->init_data, 0, sizeof(btv->init_data));
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ strscpy(info.type, "ir_video", I2C_NAME_SIZE);
switch (btv->c.type) {
case BTTV_BOARD_PV951:
diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c
index 2f810b7130e6..b46fbe557dd9 100644
--- a/drivers/media/pci/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c
@@ -819,7 +819,8 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub)
mutex_init(&card->lock);
card->bttv_nr = sub->core->nr;
- strlcpy(card->card_name, sub->core->v4l2_dev.name, sizeof(card->card_name));
+ strscpy(card->card_name, sub->core->v4l2_dev.name,
+ sizeof(card->card_name));
card->i2c_adapter = &sub->core->i2c_adap;
switch(sub->core->type) {
diff --git a/drivers/media/pci/cobalt/cobalt-alsa-main.c b/drivers/media/pci/cobalt/cobalt-alsa-main.c
index e5022b620856..c57f87a68269 100644
--- a/drivers/media/pci/cobalt/cobalt-alsa-main.c
+++ b/drivers/media/pci/cobalt/cobalt-alsa-main.c
@@ -65,7 +65,7 @@ static int snd_cobalt_card_set_names(struct snd_cobalt_card *cobsc)
struct snd_card *sc = cobsc->sc;
/* sc->driver is used by alsa-lib's configurator: simple, unique */
- strlcpy(sc->driver, "cobalt", sizeof(sc->driver));
+ strscpy(sc->driver, "cobalt", sizeof(sc->driver));
/* sc->shortname is a symlink in /proc/asound: COBALT-M -> cardN */
snprintf(sc->shortname, sizeof(sc->shortname), "cobalt-%d-%d",
diff --git a/drivers/media/pci/cobalt/cobalt-alsa-pcm.c b/drivers/media/pci/cobalt/cobalt-alsa-pcm.c
index f6a7df13cd04..38d00935a292 100644
--- a/drivers/media/pci/cobalt/cobalt-alsa-pcm.c
+++ b/drivers/media/pci/cobalt/cobalt-alsa-pcm.c
@@ -557,7 +557,7 @@ int snd_cobalt_pcm_create(struct snd_cobalt_card *cobsc)
&snd_cobalt_pcm_capture_ops);
sp->info_flags = 0;
sp->private_data = cobsc;
- strlcpy(sp->name, "cobalt", sizeof(sp->name));
+ strscpy(sp->name, "cobalt", sizeof(sp->name));
} else {
cobalt_s_bit_sysctrl(cobalt,
COBALT_SYS_CTRL_AUDIO_OPP_RESETN_BIT, 0);
@@ -581,7 +581,7 @@ int snd_cobalt_pcm_create(struct snd_cobalt_card *cobsc)
&snd_cobalt_pcm_playback_ops);
sp->info_flags = 0;
sp->private_data = cobsc;
- strlcpy(sp->name, "cobalt", sizeof(sp->name));
+ strscpy(sp->name, "cobalt", sizeof(sp->name));
}
return 0;
diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c
index e2a4c705d353..0525f5e1565b 100644
--- a/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -479,8 +479,8 @@ static int cobalt_querycap(struct file *file, void *priv_fh,
struct cobalt_stream *s = video_drvdata(file);
struct cobalt *cobalt = s->cobalt;
- strlcpy(vcap->driver, "cobalt", sizeof(vcap->driver));
- strlcpy(vcap->card, "cobalt", sizeof(vcap->card));
+ strscpy(vcap->driver, "cobalt", sizeof(vcap->driver));
+ strscpy(vcap->card, "cobalt", sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info),
"PCIe:%s", pci_name(cobalt->pci_dev));
vcap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
@@ -693,15 +693,15 @@ static int cobalt_enum_fmt_vid_cap(struct file *file, void *priv_fh,
{
switch (f->index) {
case 0:
- strlcpy(f->description, "YUV 4:2:2", sizeof(f->description));
+ strscpy(f->description, "YUV 4:2:2", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_YUYV;
break;
case 1:
- strlcpy(f->description, "RGB24", sizeof(f->description));
+ strscpy(f->description, "RGB24", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_RGB24;
break;
case 2:
- strlcpy(f->description, "RGB32", sizeof(f->description));
+ strscpy(f->description, "RGB32", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_BGR32;
break;
default:
@@ -898,11 +898,11 @@ static int cobalt_enum_fmt_vid_out(struct file *file, void *priv_fh,
{
switch (f->index) {
case 0:
- strlcpy(f->description, "YUV 4:2:2", sizeof(f->description));
+ strscpy(f->description, "YUV 4:2:2", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_YUYV;
break;
case 1:
- strlcpy(f->description, "RGB32", sizeof(f->description));
+ strscpy(f->description, "RGB32", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_BGR32;
break;
default:
@@ -1064,10 +1064,15 @@ static int cobalt_subscribe_event(struct v4l2_fh *fh,
static int cobalt_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct v4l2_fract fps;
+
if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- a->parm.capture.timeperframe.numerator = 1;
- a->parm.capture.timeperframe.denominator = 60;
+
+ fps = v4l2_calc_timeperframe(&s->timings);
+ a->parm.capture.timeperframe.numerator = fps.numerator;
+ a->parm.capture.timeperframe.denominator = fps.denominator;
a->parm.capture.readbuffers = 3;
return 0;
}
diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c
index 93443d1457c5..687477748fdd 100644
--- a/drivers/media/pci/cx18/cx18-alsa-main.c
+++ b/drivers/media/pci/cx18/cx18-alsa-main.c
@@ -112,7 +112,7 @@ static int snd_cx18_card_set_names(struct snd_cx18_card *cxsc)
struct snd_card *sc = cxsc->sc;
/* sc->driver is used by alsa-lib's configurator: simple, unique */
- strlcpy(sc->driver, "CX23418", sizeof(sc->driver));
+ strscpy(sc->driver, "CX23418", sizeof(sc->driver));
/* sc->shortname is a symlink in /proc/asound: CX18-M -> cardN */
snprintf(sc->shortname, sizeof(sc->shortname), "CX18-%d",
diff --git a/drivers/media/pci/cx18/cx18-alsa-pcm.c b/drivers/media/pci/cx18/cx18-alsa-pcm.c
index 4f31042a442a..3eafc27956c2 100644
--- a/drivers/media/pci/cx18/cx18-alsa-pcm.c
+++ b/drivers/media/pci/cx18/cx18-alsa-pcm.c
@@ -345,7 +345,7 @@ int snd_cx18_pcm_create(struct snd_cx18_card *cxsc)
&snd_cx18_pcm_capture_ops);
sp->info_flags = 0;
sp->private_data = cxsc;
- strlcpy(sp->name, cx->card_name, sizeof(sp->name));
+ strscpy(sp->name, cx->card_name, sizeof(sp->name));
return 0;
diff --git a/drivers/media/pci/cx18/cx18-cards.c b/drivers/media/pci/cx18/cx18-cards.c
index c2cf965d639e..2dcbccfbd60d 100644
--- a/drivers/media/pci/cx18/cx18-cards.c
+++ b/drivers/media/pci/cx18/cx18-cards.c
@@ -602,8 +602,8 @@ int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input)
if (index >= cx->nof_inputs)
return -EINVAL;
input->index = index;
- strlcpy(input->name, input_strs[card_input->video_type - 1],
- sizeof(input->name));
+ strscpy(input->name, input_strs[card_input->video_type - 1],
+ sizeof(input->name));
input->type = (card_input->video_type == CX18_CARD_INPUT_VID_TUNER ?
V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
input->audioset = (1 << cx->nof_audio_inputs) - 1;
@@ -625,8 +625,8 @@ int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *audio)
memset(audio, 0, sizeof(*audio));
if (index >= cx->nof_audio_inputs)
return -EINVAL;
- strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
- sizeof(audio->name));
+ strscpy(audio->name, input_strs[aud_input->audio_type - 1],
+ sizeof(audio->name));
audio->index = index;
audio->capability = V4L2_AUDCAP_STEREO;
return 0;
diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
index 0c389a3fb4e5..a6ba4ca5aa91 100644
--- a/drivers/media/pci/cx18/cx18-driver.c
+++ b/drivers/media/pci/cx18/cx18-driver.c
@@ -328,7 +328,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv)
if (!c)
return;
- strlcpy(c->name, "cx18 tveeprom tmp", sizeof(c->name));
+ strscpy(c->name, "cx18 tveeprom tmp", sizeof(c->name));
c->adapter = &cx->i2c_adap[0];
c->addr = 0xa0 >> 1;
@@ -1252,7 +1252,7 @@ static void cx18_cancel_out_work_orders(struct cx18 *cx)
{
int i;
for (i = 0; i < CX18_MAX_STREAMS; i++)
- if (&cx->streams[i].video_dev)
+ if (cx->streams[i].video_dev.v4l2_dev)
cancel_work_sync(&cx->streams[i].out_work_order);
}
diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c
index f0eb181f2b94..a89c666953f5 100644
--- a/drivers/media/pci/cx18/cx18-i2c.c
+++ b/drivers/media/pci/cx18/cx18-i2c.c
@@ -83,7 +83,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, type, I2C_NAME_SIZE);
+ strscpy(info.type, type, I2C_NAME_SIZE);
/* Our default information for ir-kbd-i2c.c to use */
switch (hw) {
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
index 80b902b12a78..854116375a7c 100644
--- a/drivers/media/pci/cx18/cx18-ioctl.c
+++ b/drivers/media/pci/cx18/cx18-ioctl.c
@@ -397,8 +397,8 @@ static int cx18_querycap(struct file *file, void *fh,
struct cx18_stream *s = video_drvdata(file);
struct cx18 *cx = id->cx;
- strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
- strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
+ strscpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
+ strscpy(vcap->card, cx->card_name, sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info),
"PCI:%s", pci_name(cx->pci_dev));
vcap->capabilities = cx->v4l2_cap; /* capabilities */
@@ -632,9 +632,9 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
cx18_call_all(cx, tuner, g_tuner, vt);
if (vt->type == V4L2_TUNER_RADIO)
- strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
+ strscpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
else
- strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
+ strscpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
return 0;
}
diff --git a/drivers/media/pci/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c
index 62bc8049b320..198c05e83f5c 100644
--- a/drivers/media/pci/cx23885/altera-ci.c
+++ b/drivers/media/pci/cx23885/altera-ci.c
@@ -665,6 +665,10 @@ static int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)
}
temp_int = append_internal(inter);
+ if (!temp_int) {
+ ret = -ENOMEM;
+ goto err;
+ }
inter->filts_used = 1;
inter->dev = config->dev;
inter->fpga_rw = config->fpga_rw;
@@ -699,6 +703,7 @@ err:
__func__, ret);
kfree(pid_filt);
+ kfree(inter);
return ret;
}
@@ -733,6 +738,10 @@ int altera_ci_init(struct altera_ci_config *config, int ci_nr)
}
temp_int = append_internal(inter);
+ if (!temp_int) {
+ ret = -ENOMEM;
+ goto err;
+ }
inter->cis_used = 1;
inter->dev = config->dev;
inter->fpga_rw = config->fpga_rw;
@@ -801,6 +810,7 @@ err:
ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
kfree(state);
+ kfree(inter);
return ret;
}
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index a71f3c7569ce..3083434bb636 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1280,7 +1280,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
return -EINVAL;
if (0 != t->index)
return -EINVAL;
- strcpy(t->name, "Television");
+ strscpy(t->name, "Television", sizeof(t->name));
call_all(dev, tuner, g_tuner, t);
dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
@@ -1329,8 +1329,8 @@ static int vidioc_querycap(struct file *file, void *priv,
struct cx23885_dev *dev = video_drvdata(file);
struct cx23885_tsport *tsport = &dev->ts1;
- strlcpy(cap->driver, dev->name, sizeof(cap->driver));
- strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
+ strscpy(cap->driver, dev->name, sizeof(cap->driver));
+ strscpy(cap->card, cx23885_boards[tsport->dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
@@ -1349,7 +1349,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (f->index != 0)
return -EINVAL;
- strlcpy(f->description, "MPEG", sizeof(f->description));
+ strscpy(f->description, "MPEG", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_MPEG;
return 0;
diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c
index db1e8ff35474..ee9d329c4038 100644
--- a/drivers/media/pci/cx23885/cx23885-alsa.c
+++ b/drivers/media/pci/cx23885/cx23885-alsa.c
@@ -526,7 +526,7 @@ static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device,
if (err < 0)
return err;
pcm->private_data = chip;
- strcpy(pcm->name, name);
+ strscpy(pcm->name, name, sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops);
return 0;
@@ -571,7 +571,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
if (err < 0)
goto error;
- strcpy(card->driver, "CX23885");
+ strscpy(card->driver, "CX23885", sizeof(card->driver));
sprintf(card->shortname, "Conexant CX23885");
sprintf(card->longname, "%s at %s", card->shortname, dev->name);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 7d52173073d6..0d0929c54f93 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -1165,7 +1165,7 @@ static int dvb_register_ci_mac(struct cx23885_tsport *port)
sp2_config.priv = port;
sp2_config.ci_control = cx23885_sp2_ci_ctrl;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "sp2", I2C_NAME_SIZE);
+ strscpy(info.type, "sp2", I2C_NAME_SIZE);
info.addr = 0x40;
info.platform_data = &sp2_config;
request_module(info.type);
@@ -1831,7 +1831,7 @@ static int dvb_register(struct cx23885_tsport *port)
case 1:
/* attach demod + tuner combo */
memset(&info, 0, sizeof(info));
- strlcpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE);
+ strscpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE);
info.addr = 0x05;
info.platform_data = &tda10071_pdata;
request_module("tda10071");
@@ -1848,7 +1848,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach SEC */
a8293_pdata.dvb_frontend = fe0->dvb.frontend;
memset(&info, 0, sizeof(info));
- strlcpy(info.type, "a8293", I2C_NAME_SIZE);
+ strscpy(info.type, "a8293", I2C_NAME_SIZE);
info.addr = 0x0b;
info.platform_data = &a8293_pdata;
request_module("a8293");
@@ -1869,7 +1869,7 @@ static int dvb_register(struct cx23885_tsport *port)
si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL;
si2165_pdata.ref_freq_hz = 16000000;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2165", I2C_NAME_SIZE);
+ strscpy(info.type, "si2165", I2C_NAME_SIZE);
info.addr = 0x64;
info.platform_data = &si2165_pdata;
request_module(info.type);
@@ -1903,7 +1903,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach demod + tuner combo */
memset(&info, 0, sizeof(info));
- strlcpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE);
+ strscpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE);
info.addr = 0x05;
info.platform_data = &tda10071_pdata;
request_module("tda10071");
@@ -1920,7 +1920,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach SEC */
a8293_pdata.dvb_frontend = fe0->dvb.frontend;
memset(&info, 0, sizeof(info));
- strlcpy(info.type, "a8293", I2C_NAME_SIZE);
+ strscpy(info.type, "a8293", I2C_NAME_SIZE);
info.addr = 0x0b;
info.platform_data = &a8293_pdata;
request_module("a8293");
@@ -1953,7 +1953,7 @@ static int dvb_register(struct cx23885_tsport *port)
ts2020_config.fe = fe0->dvb.frontend;
ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "ts2020", I2C_NAME_SIZE);
+ strscpy(info.type, "ts2020", I2C_NAME_SIZE);
info.addr = 0x60;
info.platform_data = &ts2020_config;
request_module(info.type);
@@ -1990,7 +1990,7 @@ static int dvb_register(struct cx23885_tsport *port)
si2168_config.fe = &fe0->dvb.frontend;
si2168_config.ts_mode = SI2168_TS_SERIAL;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ strscpy(info.type, "si2168", I2C_NAME_SIZE);
info.addr = 0x64;
info.platform_data = &si2168_config;
request_module(info.type);
@@ -2009,7 +2009,7 @@ static int dvb_register(struct cx23885_tsport *port)
si2157_config.fe = fe0->dvb.frontend;
si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ strscpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
info.platform_data = &si2157_config;
request_module(info.type);
@@ -2037,7 +2037,7 @@ static int dvb_register(struct cx23885_tsport *port)
si2168_config.fe = &fe0->dvb.frontend;
si2168_config.ts_mode = SI2168_TS_PARALLEL;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ strscpy(info.type, "si2168", I2C_NAME_SIZE);
info.addr = 0x64;
info.platform_data = &si2168_config;
request_module(info.type);
@@ -2055,7 +2055,7 @@ static int dvb_register(struct cx23885_tsport *port)
si2157_con