summaryrefslogtreecommitdiffstats
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)
downloadlinux-134bf98c5596605af90f104716ef912e8f7eb56b.tar.bz2
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_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);
@@ -2085,7 +2085,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);
@@ -2134,7 +2134,7 @@ static int dvb_register(struct cx23885_tsport *port)
}
memset(&info, 0, sizeof(info));
- strlcpy(info.type, "m88ds3103", I2C_NAME_SIZE);
+ strscpy(info.type, "m88ds3103", I2C_NAME_SIZE);
info.addr = 0x68;
info.platform_data = &m88ds3103_pdata;
request_module(info.type);
@@ -2154,7 +2154,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);
@@ -2199,7 +2199,7 @@ static int dvb_register(struct cx23885_tsport *port)
si2168_config.i2c_adapter = &adapter;
si2168_config.fe = &fe0->dvb.frontend;
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);
@@ -2217,7 +2217,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);
@@ -2250,7 +2250,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");
@@ -2267,7 +2267,7 @@ static int dvb_register(struct cx23885_tsport *port)
memset(&m88rs6000t_config, 0, sizeof(m88rs6000t_config));
m88rs6000t_config.fe = fe0->dvb.frontend;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "m88rs6000t", I2C_NAME_SIZE);
+ strscpy(info.type, "m88rs6000t", I2C_NAME_SIZE);
info.addr = 0x21;
info.platform_data = &m88rs6000t_config;
request_module("%s", info.type);
@@ -2292,7 +2292,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("%s", info.type);
@@ -2310,7 +2310,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("%s", info.type);
@@ -2345,7 +2345,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("%s", info.type);
@@ -2363,7 +2363,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("%s", info.type);
@@ -2392,7 +2392,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 = 0x66;
info.platform_data = &si2168_config;
request_module("%s", info.type);
@@ -2410,7 +2410,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 = 0x62;
info.platform_data = &si2157_config;
request_module("%s", info.type);
@@ -2452,7 +2452,7 @@ static int dvb_register(struct cx23885_tsport *port)
si2157_config.if_port = 1;
si2157_config.inversion = 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("%s", info.type);
@@ -2488,7 +2488,7 @@ static int dvb_register(struct cx23885_tsport *port)
si2157_config.if_port = 1;
si2157_config.inversion = 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 = 0x62;
info.platform_data = &si2157_config;
request_module("%s", info.type);
@@ -2528,7 +2528,7 @@ static int dvb_register(struct cx23885_tsport *port)
si2157_config.if_port = 1;
si2157_config.inversion = 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("%s", info.type);
diff --git a/drivers/media/pci/cx23885/cx23885-i2c.c b/drivers/media/pci/cx23885/cx23885-i2c.c
index ef863492c0ac..d0df3dfff694 100644
--- a/drivers/media/pci/cx23885/cx23885-i2c.c
+++ b/drivers/media/pci/cx23885/cx23885-i2c.c
@@ -317,7 +317,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
bus->i2c_client = cx23885_i2c_client_template;
bus->i2c_adap.dev.parent = &dev->pci->dev;
- strlcpy(bus->i2c_adap.name, bus->dev->name,
+ strscpy(bus->i2c_adap.name, bus->dev->name,
sizeof(bus->i2c_adap.name));
bus->i2c_adap.algo_data = bus;
@@ -340,12 +340,12 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
/* Instantiate the IR receiver device, if present */
if (0 == bus->i2c_rc) {
struct i2c_board_info info;
- const unsigned short addr_list[] = {
+ static const unsigned short addr_list[] = {
0x6b, I2C_CLIENT_END
};
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ strscpy(info.type, "ir_video", I2C_NAME_SIZE);
/* Use quick read command for probe, some IR chips don't
* support writes */
i2c_new_probed_device(&bus->i2c_adap, &info, addr_list,
diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c
index d2cdd40f79f5..d162bf4b4800 100644
--- a/drivers/media/pci/cx23885/cx23885-ioctl.c
+++ b/drivers/media/pci/cx23885/cx23885-ioctl.c
@@ -31,9 +31,9 @@ int cx23885_g_chip_info(struct file *file, void *fh,
if (chip->match.addr == 1) {
if (dev->v4l_device == NULL)
return -EINVAL;
- strlcpy(chip->name, "cx23417", sizeof(chip->name));
+ strscpy(chip->name, "cx23417", sizeof(chip->name));
} else {
- strlcpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name));
+ strscpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name));
}
return 0;
}
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index f8a3deadc77a..92d32a733f1b 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -639,8 +639,8 @@ static int vidioc_querycap(struct file *file, void *priv,
struct cx23885_dev *dev = video_drvdata(file);
struct video_device *vdev = video_devdata(file);
- strcpy(cap->driver, "cx23885");
- strlcpy(cap->card, cx23885_boards[dev->board].name,
+ strscpy(cap->driver, "cx23885", sizeof(cap->driver));
+ strscpy(cap->card, cx23885_boards[dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_AUDIO;
@@ -661,7 +661,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (unlikely(f->index >= ARRAY_SIZE(formats)))
return -EINVAL;
- strlcpy(f->description, formats[f->index].name,
+ strscpy(f->description, formats[f->index].name,
sizeof(f->description));
f->pixelformat = formats[f->index].fourcc;
@@ -731,7 +731,7 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
i->index = n;
i->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(i->name, iname[INPUT(n)->type]);
+ strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name));
i->std = CX23885_NORMS;
if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) ||
(CX23885_VMUX_CABLE == INPUT(n)->type)) {
@@ -828,7 +828,7 @@ static int cx23885_query_audinput(struct file *file, void *priv,
memset(i, 0, sizeof(*i));
i->index = n;
- strcpy(i->name, iname[n]);
+ strscpy(i->name, iname[n], sizeof(i->name));
i->capability = V4L2_AUDCAP_STEREO;
return 0;
@@ -887,7 +887,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (0 != t->index)
return -EINVAL;
- strcpy(t->name, "Television");
+ strscpy(t->name, "Television", sizeof(t->name));
call_all(dev, tuner, g_tuner, t);
return 0;
@@ -1186,7 +1186,8 @@ int cx23885_video_register(struct cx23885_dev *dev)
/* Initialize VBI template */
cx23885_vbi_template = cx23885_video_template;
- strcpy(cx23885_vbi_template.name, "cx23885-vbi");
+ strscpy(cx23885_vbi_template.name, "cx23885-vbi",
+ sizeof(cx23885_vbi_template.name));
dev->tvnorm = V4L2_STD_NTSC_M;
dev->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV);
diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c
index 00329f668b59..1d775c90df51 100644
--- a/drivers/media/pci/cx23885/cx23888-ir.c
+++ b/drivers/media/pci/cx23885/cx23888-ir.c
@@ -696,10 +696,8 @@ static int cx23888_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_888_debug, sd, "rx read: %10u ns %s %s\n",
v, u ? "mark" : "space", w ? "(timed out)" : "");
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
index ef6380651c10..0a6c90e92557 100644
--- a/drivers/media/pci/cx25821/cx25821-alsa.c
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -674,7 +674,7 @@ static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device,
}
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, name);
+ strscpy(pcm->name, name, sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops);
return 0;
@@ -725,7 +725,7 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
return err;
}
- strcpy(card->driver, "cx25821");
+ strscpy(card->driver, "cx25821", sizeof(card->driver));
/* Card "creation" */
chip = card->private_data;
@@ -754,10 +754,10 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
goto error;
}
- strcpy(card->shortname, "cx25821");
+ strscpy(card->shortname, "cx25821", sizeof(card->shortname));
sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name,
chip->iobase, chip->irq);
- strcpy(card->mixername, "CX25821");
+ strscpy(card->mixername, "CX25821", sizeof(card->mixername));
pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver,
devno);
diff --git a/drivers/media/pci/cx25821/cx25821-i2c.c b/drivers/media/pci/cx25821/cx25821-i2c.c
index 31479a41f359..67d2f7610011 100644
--- a/drivers/media/pci/cx25821/cx25821-i2c.c
+++ b/drivers/media/pci/cx25821/cx25821-i2c.c
@@ -306,7 +306,7 @@ int cx25821_i2c_register(struct cx25821_i2c *bus)
bus->i2c_client = cx25821_i2c_client_template;
bus->i2c_adap.dev.parent = &dev->pci->dev;
- strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
+ strscpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
bus->i2c_adap.algo_data = bus;
i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index dbaf42ec26cd..3d23c2e64102 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -322,7 +322,7 @@ static int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (unlikely(f->index >= ARRAY_SIZE(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].fourcc;
return 0;
@@ -441,8 +441,8 @@ static int cx25821_vidioc_querycap(struct file *file, void *priv,
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
const u32 cap_output = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE;
- strcpy(cap->driver, "cx25821");
- strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
+ strscpy(cap->driver, "cx25821", sizeof(cap->driver));
+ strscpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
if (chan->id >= VID_CHANNEL_NUM)
cap->device_caps = cap_output;
@@ -486,7 +486,7 @@ static int cx25821_vidioc_enum_input(struct file *file, void *priv,
i->type = V4L2_INPUT_TYPE_CAMERA;
i->std = CX25821_NORMS;
- strcpy(i->name, "Composite");
+ strscpy(i->name, "Composite", sizeof(i->name));
return 0;
}
@@ -534,7 +534,7 @@ static int cx25821_vidioc_enum_output(struct file *file, void *priv,
o->type = V4L2_INPUT_TYPE_CAMERA;
o->std = CX25821_NORMS;
- strcpy(o->name, "Composite");
+ strscpy(o->name, "Composite", sizeof(o->name));
return 0;
}
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index 89a65478ae36..b683cbe13dee 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -616,7 +616,7 @@ static int snd_cx88_pcm(struct cx88_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_cx88_pcm_ops);
return 0;
@@ -968,12 +968,12 @@ static int cx88_audio_initdev(struct pci_dev *pci,
goto error;
}
- strcpy(card->driver, "CX88x");
+ strscpy(card->driver, "CX88x", sizeof(card->driver));
sprintf(card->shortname, "Conexant CX%x", pci->device);
sprintf(card->longname, "%s at %#llx",
card->shortname,
(unsigned long long)pci_resource_start(pci, 0));
- strcpy(card->mixername, "CX88");
+ strscpy(card->mixername, "CX88", sizeof(card->mixername));
dprintk(0, "%s/%i: ALSA support for cx2388x boards\n",
card->driver, devno);
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 7a4876cf9f08..199756547f03 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -803,7 +803,7 @@ static int vidioc_querycap(struct file *file, void *priv,
struct cx8802_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
- strcpy(cap->driver, "cx88_blackbird");
+ strscpy(cap->driver, "cx88_blackbird", sizeof(cap->driver));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
return cx88_querycap(file, core, cap);
}
@@ -814,7 +814,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;
f->flags = V4L2_FMT_FLAG_COMPRESSED;
return 0;
@@ -995,7 +995,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (t->index != 0)
return -EINVAL;
- strcpy(t->name, "Television");
+ strscpy(t->name, "Television", sizeof(t->name));
t->capability = V4L2_TUNER_CAP_NORM;
t->rangehigh = 0xffffffffUL;
call_all(core, tuner, g_tuner, t);
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
index 07e1483e987d..382af90fd4a9 100644
--- a/drivers/media/pci/cx88/cx88-cards.c
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -3693,7 +3693,7 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
core->height = 240;
core->field = V4L2_FIELD_INTERLACED;
- strcpy(core->v4l2_dev.name, core->name);
+ strscpy(core->v4l2_dev.name, core->name, sizeof(core->v4l2_dev.name));
if (v4l2_device_register(NULL, &core->v4l2_dev)) {
kfree(core);
return NULL;
diff --git a/drivers/media/pci/cx88/cx88-i2c.c b/drivers/media/pci/cx88/cx88-i2c.c
index 99f88a05a7c9..48be0b0ad680 100644
--- a/drivers/media/pci/cx88/cx88-i2c.c
+++ b/drivers/media/pci/cx88/cx88-i2c.c
@@ -140,14 +140,14 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
core->i2c_algo = cx8800_i2c_algo_template;
core->i2c_adap.dev.parent = &pci->dev;
- strlcpy(core->i2c_adap.name, core->name, sizeof(core->i2c_adap.name));
+ strscpy(core->i2c_adap.name, core->name, sizeof(core->i2c_adap.name));
core->i2c_adap.owner = THIS_MODULE;
core->i2c_algo.udelay = i2c_udelay;
core->i2c_algo.data = core;
i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev);
core->i2c_adap.algo_data = &core->i2c_algo;
core->i2c_client.adapter = &core->i2c_adap;
- strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE);
+ strscpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE);
cx8800_bit_setscl(core, 1);
cx8800_bit_setsda(core, 1);
diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
index 2f5debce4905..ca76da04b476 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -535,7 +535,7 @@ void cx88_ir_irq(struct cx88_core *core)
struct cx88_IR *ir = core->ir;
u32 samples;
unsigned int todo, bits;
- struct ir_raw_event ev;
+ struct ir_raw_event ev = {};
if (!ir || !ir->sampling)
return;
@@ -550,7 +550,6 @@ void cx88_ir_irq(struct cx88_core *core)
if (samples == 0xff && ir->dev->idle)
return;
- init_ir_raw_event(&ev);
for (todo = 32; todo > 0; todo -= bits) {
ev.pulse = samples & 0x80000000 ? false : true;
bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
@@ -610,7 +609,7 @@ void cx88_i2c_init_ir(struct cx88_core *core)
return;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ strscpy(info.type, "ir_video", I2C_NAME_SIZE);
switch (core->boardnr) {
case CX88_BOARD_LEADTEK_PVR2000:
@@ -635,7 +634,7 @@ void cx88_i2c_init_ir(struct cx88_core *core)
if (*addrp == 0x71) {
/* Hauppauge Z8F0811 */
- strlcpy(info.type, "ir_z8f0811_haup", I2C_NAME_SIZE);
+ strscpy(info.type, "ir_z8f0811_haup", I2C_NAME_SIZE);
core->init_data.name = core->board.name;
core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
core->init_data.type = RC_PROTO_BIT_RC5 |
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 7b113bad70d2..df4e7a0686e0 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -811,7 +811,7 @@ int cx88_querycap(struct file *file, struct cx88_core *core,
{
struct video_device *vdev = video_devdata(file);
- strlcpy(cap->card, core->board.name, sizeof(cap->card));
+ strscpy(cap->card, core->board.name, sizeof(cap->card));
cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
if (core->board.tuner_type != UNSET)
cap->device_caps |= V4L2_CAP_TUNER;
@@ -842,7 +842,7 @@ static int vidioc_querycap(struct file *file, void *priv,
struct cx8800_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
- strcpy(cap->driver, "cx8800");
+ strscpy(cap->driver, "cx8800", sizeof(cap->driver));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
return cx88_querycap(file, core, cap);
}
@@ -853,7 +853,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (unlikely(f->index >= ARRAY_SIZE(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].fourcc;
return 0;
@@ -897,7 +897,7 @@ int cx88_enum_input(struct cx88_core *core, struct v4l2_input *i)
if (!INPUT(n).type)
return -EINVAL;
i->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(i->name, iname[INPUT(n).type]);
+ strscpy(i->name, iname[INPUT(n).type], sizeof(i->name));
if ((INPUT(n).type == CX88_VMUX_TELEVISION) ||
(INPUT(n).type == CX88_VMUX_CABLE))
i->type = V4L2_INPUT_TYPE_TUNER;
@@ -952,7 +952,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (t->index != 0)
return -EINVAL;
- strcpy(t->name, "Television");
+ strscpy(t->name, "Television", sizeof(t->name));
t->capability = V4L2_TUNER_CAP_NORM;
t->rangehigh = 0xffffffffUL;
call_all(core, tuner, g_tuner, t);
@@ -1065,7 +1065,7 @@ static int radio_g_tuner(struct file *file, void *priv,
if (unlikely(t->index > 0))
return -EINVAL;
- strcpy(t->name, "Radio");
+ strscpy(t->name, "Radio", sizeof(t->name));
call_all(core, tuner, g_tuner, t);
return 0;
diff --git a/drivers/media/pci/cx88/cx88-vp3054-i2c.c b/drivers/media/pci/cx88/cx88-vp3054-i2c.c
index 92876de3841c..e4db636e9fad 100644
--- a/drivers/media/pci/cx88/cx88-vp3054-i2c.c
+++ b/drivers/media/pci/cx88/cx88-vp3054-i2c.c
@@ -114,7 +114,7 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
vp3054_i2c->algo = vp3054_i2c_algo_template;
vp3054_i2c->adap.dev.parent = &dev->pci->dev;
- strlcpy(vp3054_i2c->adap.name, core->name,
+ strscpy(vp3054_i2c->adap.name, core->name,
sizeof(vp3054_i2c->adap.name));
vp3054_i2c->adap.owner = THIS_MODULE;
vp3054_i2c->algo.data = dev;
diff --git a/drivers/media/pci/ddbridge/ddbridge-ci.c b/drivers/media/pci/ddbridge/ddbridge-ci.c
index cfe23d02e561..377991095aba 100644
--- a/drivers/media/pci/ddbridge/ddbridge-ci.c
+++ b/drivers/media/pci/ddbridge/ddbridge-ci.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* ddbridge-ci.c: Digital Devices bridge CI (DuoFlex, CI Bridge) support
*
@@ -13,9 +14,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.
- *
- * To obtain the license, point your browser to
- * http://www.gnu.org/copyleft/gpl.html
*/
#include "ddbridge.h"
diff --git a/drivers/media/pci/ddbridge/ddbridge-ci.h b/drivers/media/pci/ddbridge/ddbridge-ci.h
index 35a39182dd83..cc98656af349 100644
--- a/drivers/media/pci/ddbridge/ddbridge-ci.h
+++ b/drivers/media/pci/ddbridge/ddbridge-ci.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* ddbridge-ci.h: Digital Devices bridge CI (DuoFlex, CI Bridge) support
*
@@ -13,9 +14,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.
- *
- * To obtain the license, point your browser to
- * http://www.gnu.org/copyleft/gpl.html
*/
#ifndef __DDBRIDGE_CI_H__
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index c1b982e8e6c9..7a2d19682fe3 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* ddbridge-core.c: Digital Devices bridge core functions
*
@@ -5,19 +6,14 @@
* Marcus Metzler <mocm@metzlerbros.de>
* Ralph Metzler <rjkm@metzlerbros.de>
*
- *
* 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.
- *
- * To obtain the license, point your browser to
- * http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/module.h>
diff --git a/drivers/media/pci/ddbridge/ddbridge-hw.c b/drivers/media/pci/ddbridge/ddbridge-hw.c
index f3cbac07b41f..f9c91bdbd041 100644
--- a/drivers/media/pci/ddbridge/ddbridge-hw.c
+++ b/drivers/media/pci/ddbridge/ddbridge-hw.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* ddbridge-hw.c: Digital Devices bridge hardware maps
*
@@ -13,7 +14,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 "ddbridge.h"
diff --git a/drivers/media/pci/ddbridge/ddbridge-hw.h b/drivers/media/pci/ddbridge/ddbridge-hw.h
index 7c142419419c..e34bd94c266b 100644
--- a/drivers/media/pci/ddbridge/ddbridge-hw.h
+++ b/drivers/media/pci/ddbridge/ddbridge-hw.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* ddbridge-hw.h: Digital Devices bridge hardware maps
*
@@ -13,7 +14,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.
- *
*/
#ifndef _DDBRIDGE_HW_H_
diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c
index 5a28d7611713..aafa6030c8cc 100644
--- a/drivers/media/pci/ddbridge/ddbridge-i2c.c
+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* ddbridge-i2c.c: Digital Devices bridge i2c driver
*
@@ -13,7 +14,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/module.h>
diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.h b/drivers/media/pci/ddbridge/ddbridge-i2c.h
index 7ed220506c05..90830f7b1638 100644
--- a/drivers/media/pci/ddbridge/ddbridge-i2c.h
+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.h
@@ -1,5 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- * ddbridge-i2c.c: Digital Devices bridge i2c driver
+ * ddbridge-i2c.h: Digital Devices bridge i2c driver
*
* Copyright (C) 2010-2017 Digital Devices GmbH
* Ralph Metzler <rjkm@metzlerbros.de>
@@ -13,7 +14,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.
- *
*/
#ifndef __DDBRIDGE_I2C_H__
diff --git a/drivers/media/pci/ddbridge/ddbridge-io.h b/drivers/media/pci/ddbridge/ddbridge-io.h
index b3646c04f1a7..1a5b31b52494 100644
--- a/drivers/media/pci/ddbridge/ddbridge-io.h
+++ b/drivers/media/pci/ddbridge/ddbridge-io.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* ddbridge-io.h: Digital Devices bridge I/O inline functions
*
@@ -13,7 +14,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.
- *
*/
#ifndef __DDBRIDGE_IO_H__
diff --git a/drivers/media/pci/ddbridge/ddbridge-main.c b/drivers/media/pci/ddbridge/ddbridge-main.c
index f4748cfd904b..03dc9924fa2c 100644
--- a/drivers/media/pci/ddbridge/ddbridge-main.c
+++ b/drivers/media/pci/ddbridge/ddbridge-main.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* ddbridge.c: Digital Devices PCIe bridge driver
*
@@ -13,7 +14,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.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -318,5 +318,5 @@ module_exit(module_exit_ddbridge);
MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_VERSION(DDBRIDGE_VERSION);
diff --git a/drivers/media/pci/ddbridge/ddbridge-max.c b/drivers/media/pci/ddbridge/ddbridge-max.c
index 8da1c7b91577..576dd2318e4d 100644
--- a/drivers/media/pci/ddbridge/ddbridge-max.c
+++ b/drivers/media/pci/ddbridge/ddbridge-max.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* ddbridge-max.c: Digital Devices bridge MAX card support
*
@@ -13,7 +14,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/module.h>
diff --git a/drivers/media/pci/ddbridge/ddbridge-max.h b/drivers/media/pci/ddbridge/ddbridge-max.h
index 9838c73973b6..6543dfc77138 100644
--- a/drivers/media/pci/ddbridge/ddbridge-max.h
+++ b/drivers/media/pci/ddbridge/ddbridge-max.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* ddbridge-max.h: Digital Devices bridge MAX card support
*
@@ -13,7 +14,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.
- *
*/
#ifndef _DDBRIDGE_MAX_H_
diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h
index f9e1cbb99b53..2942a7f35099 100644
--- a/drivers/media/pci/ddbridge/ddbridge-regs.h
+++ b/drivers/media/pci/ddbridge/ddbridge-regs.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* ddbridge-regs.h: Digital Devices PCIe bridge driver
*
@@ -7,14 +8,10 @@
* 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.
- *
- * To obtain the license, point your browser to
- * http://www.gnu.org/copyleft/gpl.html
*/
#ifndef __DDBRIDGE_REGS_H__
diff --git a/drivers/media/pci/ddbridge/ddbridge-sx8.c b/drivers/media/pci/ddbridge/ddbridge-sx8.c
index 64f05f5ee039..374fcee94960 100644
--- a/drivers/media/pci/ddbridge/ddbridge-sx8.c
+++ b/drivers/media/pci/ddbridge/ddbridge-sx8.c
@@ -398,9 +398,7 @@ static int set_parameters(struct dvb_frontend *fe)
}
stat = start(fe, 3, mask, ts_config);
} else {
- u32 flags = (iq_mode == 2) ? 1 : 0;
-
- stat = start_iq(fe, flags, 4, ts_config);
+ stat = start_iq(fe, 0, 4, ts_config);
}
if (!stat) {
state->started = 1;
diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h
index 8a354dfb6c22..f137155bf79e 100644
--- a/drivers/media/pci/ddbridge/ddbridge.h
+++ b/drivers/media/pci/ddbridge/ddbridge.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* ddbridge.h: Digital Devices PCIe bridge driver
*
@@ -8,14 +9,10 @@
* 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.
- *
- * To obtain the license, point your browser to
- * http://www.gnu.org/copyleft/gpl.html
*/
#ifndef _DDBRIDGE_H_
diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
index 1ddb0576fb7b..a84c8270ea13 100644
--- a/drivers/media/pci/dm1105/dm1105.c
+++ b/drivers/media/pci/dm1105/dm1105.c
@@ -1046,7 +1046,7 @@ static int dm1105_probe(struct pci_dev *pdev,
/* i2c */
i2c_set_adapdata(&dev->i2c_adap, dev);
- strcpy(dev->i2c_adap.name, DRIVER_NAME);
+ strscpy(dev->i2c_adap.name, DRIVER_NAME, sizeof(dev->i2c_adap.name));
dev->i2c_adap.owner = THIS_MODULE;
dev->i2c_adap.dev.parent = &pdev->dev;
dev->i2c_adap.algo = &dm1105_algo;
@@ -1057,7 +1057,8 @@ static int dm1105_probe(struct pci_dev *pdev,
goto err_dm1105_hw_exit;
i2c_set_adapdata(&dev->i2c_bb_adap, dev);
- strcpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME);
+ strscpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME,
+ sizeof(dev->i2c_bb_adap.name));
dev->i2c_bb_adap.owner = THIS_MODULE;
dev->i2c_bb_adap.dev.parent = &pdev->dev;
dev->i2c_bb_adap.algo_data = &dev->i2c_bit;
diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c
index 1775c36891ae..17d69bd5d7f1 100644
--- a/drivers/media/pci/dt3155/dt3155.c
+++ b/drivers/media/pci/dt3155/dt3155.c
@@ -307,8 +307,8 @@ static int dt3155_querycap(struct file *filp, void *p,
{
struct dt3155_priv *pd = video_drvdata(filp);
- strcpy(cap->driver, DT3155_NAME);
- strcpy(cap->card, DT3155_NAME " frame grabber");
+ strscpy(cap->driver, DT3155_NAME, sizeof(cap->driver));
+ strscpy(cap->card, DT3155_NAME " frame grabber", sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(pd->pdev));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
@@ -322,7 +322,7 @@ static int dt3155_enum_fmt_vid_cap(struct file *filp,
if (f->index)
return -EINVAL;
f->pixelformat = V4L2_PIX_FMT_GREY;
- strcpy(f->description, "8-bit Greyscale");
+ strscpy(f->description, "8-bit Greyscale", sizeof(f->description));
return 0;
}
@@ -378,7 +378,7 @@ static int dt3155_enum_input(struct file *filp, void *p,
snprintf(input->name, sizeof(input->name), "VID%d",
input->index);
else
- strlcpy(input->name, "J2/VID0", sizeof(input->name));
+ strscpy(input->name, "J2/VID0", sizeof(input->name));
input->type = V4L2_INPUT_TYPE_CAMERA;
input->std = V4L2_STD_ALL;
input->status = 0;
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
index 29027159eced..452eb9b42140 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
@@ -218,13 +218,11 @@ static int cio2_fbpt_init(struct cio2_device *cio2, struct cio2_queue *q)
{
struct device *dev = &cio2->pci_dev->dev;
- q->fbpt = dma_alloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr,
- GFP_KERNEL);
+ q->fbpt = dma_zalloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr,
+ GFP_KERNEL);
if (!q->fbpt)
return -ENOMEM;
- memset(q->fbpt, 0, CIO2_FBPT_SIZE);
-
return 0;
}
@@ -1066,8 +1064,8 @@ static int cio2_v4l2_querycap(struct file *file, void *fh,
{
struct cio2_device *cio2 = video_drvdata(file);
- strlcpy(cap->driver, CIO2_NAME, sizeof(cap->driver));
- strlcpy(cap->card, CIO2_DEVICE_NAME, sizeof(cap->card));
+ strscpy(cap->driver, CIO2_NAME, sizeof(cap->driver));
+ strscpy(cap->card, CIO2_DEVICE_NAME, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"PCI:%s", pci_name(cio2->pci_dev));
@@ -1145,7 +1143,7 @@ cio2_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
if (input->index > 0)
return -EINVAL;
- strlcpy(input->name, "camera", sizeof(input->name));
+ strscpy(input->name, "camera", sizeof(input->name));
input->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
@@ -1435,13 +1433,13 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
struct cio2_device *cio2 = container_of(notifier, struct cio2_device,
notifier);
struct sensor_async_subdev *s_asd;
+ struct v4l2_async_subdev *asd;
struct cio2_queue *q;
- unsigned int i, pad;
+ unsigned int pad;
int ret;
- for (i = 0; i < notifier->num_subdevs; i++) {
- s_asd = container_of(cio2->notifier.subdevs[i],
- struct sensor_async_subdev, asd);
+ list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
+ s_asd = container_of(asd, struct sensor_async_subdev, asd);
q = &cio2->queue[s_asd->csi2.port];
for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
@@ -1463,7 +1461,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
if (ret) {
dev_err(&cio2->pci_dev->dev,
"failed to create link for %s\n",
- cio2->queue[i].sensor->name);
+ q->sensor->name);
return ret;
}
}
@@ -1484,7 +1482,7 @@ static int cio2_fwnode_parse(struct device *dev,
struct sensor_async_subdev *s_asd =
container_of(asd, struct sensor_async_subdev, asd);
- if (vep->bus_type != V4L2_MBUS_CSI2) {
+ if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
dev_err(dev, "Only CSI2 bus type is currently supported\n");
return -EINVAL;
}
@@ -1499,6 +1497,8 @@ static int cio2_notifier_init(struct cio2_device *cio2)
{
int ret;
+ v4l2_async_notifier_init(&cio2->notifier);
+
ret = v4l2_async_notifier_parse_fwnode_endpoints(
&cio2->pci_dev->dev, &cio2->notifier,
sizeof(struct sensor_async_subdev),
@@ -1506,7 +1506,7 @@ static int cio2_notifier_init(struct cio2_device *cio2)
if (ret < 0)
return ret;
- if (!cio2->notifier.num_subdevs)
+ if (list_empty(&cio2->notifier.asd_list))
return -ENODEV; /* no endpoint */
cio2->notifier.ops = &cio2_async_ops;
@@ -1785,7 +1785,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
mutex_init(&cio2->lock);
cio2->media_dev.dev = &cio2->pci_dev->dev;
- strlcpy(cio2->media_dev.model, CIO2_DEVICE_NAME,
+ strscpy(cio2->media_dev.model, CIO2_DEVICE_NAME,
sizeof(cio2->media_dev.model));
snprintf(cio2->media_dev.bus_info, sizeof(cio2->media_dev.bus_info),
"PCI:%s", pci_name(cio2->pci_dev));
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c
index c1856f609d2c..0de8a9f5011a 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-main.c
+++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c
@@ -109,7 +109,7 @@ static int snd_ivtv_card_set_names(struct snd_ivtv_card *itvsc)
struct snd_card *sc = itvsc->sc;
/* sc->driver is used by alsa-lib's configurator: simple, unique */
- strlcpy(sc->driver, "CX2341[56]", sizeof(sc->driver));
+ strscpy(sc->driver, "CX2341[56]", sizeof(sc->driver));
/* sc->shortname is a symlink in /proc/asound: IVTV-M -> cardN */
snprintf(sc->shortname, sizeof(sc->shortname), "IVTV-%d",
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
index 5326d86fa375..737c52de7558 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
+++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
@@ -350,7 +350,7 @@ int snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc)
&snd_ivtv_pcm_capture_ops);
sp->info_flags = 0;
sp->private_data = itvsc;
- strlcpy(sp->name, itv->card_name, sizeof(sp->name));
+ strscpy(sp->name, itv->card_name, sizeof(sp->name));
return 0;
diff --git a/drivers/media/pci/ivtv/ivtv-cards.c b/drivers/media/pci/ivtv/ivtv-cards.c
index c63792964a03..4ff46a6d0503 100644
--- a/drivers/media/pci/ivtv/ivtv-cards.c
+++ b/drivers/media/pci/ivtv/ivtv-cards.c
@@ -1317,8 +1317,8 @@ int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input)
if (index >= itv->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 == IVTV_CARD_INPUT_VID_TUNER ?
V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
input->audioset = (1 << itv->nof_audio_inputs) - 1;
@@ -1334,7 +1334,7 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output)
if (index >= itv->card->nof_outputs)
return -EINVAL;
output->index = index;
- strlcpy(output->name, card_output->name, sizeof(output->name));
+ strscpy(output->name, card_output->name, sizeof(output->name));
output->type = V4L2_OUTPUT_TYPE_ANALOG;
output->audioset = 1;
output->std = V4L2_STD_ALL;
@@ -1353,8 +1353,8 @@ int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio)
memset(audio, 0, sizeof(*audio));
if (index >= itv->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;
@@ -1365,6 +1365,6 @@ int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud
memset(aud_output, 0, sizeof(*aud_output));
if (itv->card->video_outputs == NULL || index != 0)
return -EINVAL;
- strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name));
+ strscpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name));
return 0;
}
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c
index e9ce54dd5e01..55ef1385519e 100644
--- a/drivers/media/pci/ivtv/ivtv-i2c.c
+++ b/drivers/media/pci/ivtv/ivtv-i2c.c
@@ -218,7 +218,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
memset(&info, 0, sizeof(struct i2c_board_info));
info.platform_data = init_data;
- strlcpy(info.type, type, I2C_NAME_SIZE);
+ strscpy(info.type, type, I2C_NAME_SIZE);
return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
-1 : 0;
@@ -239,14 +239,14 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv)
* allocations, so this function must be called after all other i2c
* devices we care about are registered.
*/
- const unsigned short addr_list[] = {
+ static const unsigned short addr_list[] = {
0x1a, /* Hauppauge IR external - collides with WM8739 */
0x18, /* Hauppauge IR internal */
I2C_CLIENT_END
};
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ strscpy(info.type, "ir_video", I2C_NAME_SIZE);
return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list, NULL);
}
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
index 4cdc6d2be85d..a66f8b872520 100644
--- a/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -36,6 +36,7 @@
#include <media/tveeprom.h>
#include <media/v4l2-event.h>
#ifdef CONFIG_VIDEO_IVTV_DEPRECATED_IOCTLS
+#include <linux/compat.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/video.h>
#endif
@@ -747,8 +748,8 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc
struct ivtv *itv = id->itv;
struct ivtv_stream *s = &itv->streams[id->type];
- strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
- strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
+ strscpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
+ strscpy(vcap->card, itv->card_name, sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
vcap->device_caps = s->caps;
@@ -1227,9 +1228,9 @@ static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
ivtv_call_all(itv, tuner, g_tuner, vt);
if (vt->type == V4L2_TUNER_RADIO)
- strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
+ strscpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
else
- strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
+ strscpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
return 0;
}
@@ -1627,6 +1628,21 @@ static __inline__ void warn_deprecated_ioctl(const char *name)
pr_warn_once("warning: the %s ioctl is deprecated. Don't use it, as it will be removed soon\n",
name);
}
+
+#ifdef CONFIG_COMPAT
+struct compat_video_event {
+ __s32 type;
+ /* unused, make sure to use atomic time for y2038 if it ever gets used */
+ compat_long_t timestamp;
+ union {
+ video_size_t size;
+ unsigned int frame_rate; /* in frames per 1000sec */
+ unsigned char vsync_field; /* unknown/odd/even/progressive */
+ } u;
+};
+#define VIDEO_GET_EVENT32 _IOR('o', 28, struct compat_video_event)
+#endif
+
#endif
static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
@@ -1749,7 +1765,13 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
return ivtv_video_command(itv, id, dc, try);
}
+#ifdef CONFIG_COMPAT
+ case VIDEO_GET_EVENT32:
+#endif
case VIDEO_GET_EVENT: {
+#ifdef CONFIG_COMPAT
+ struct compat_video_event *ev32 = arg;
+#endif
struct video_event *ev = arg;
DEFINE_WAIT(wait);
@@ -1763,14 +1785,22 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
ev->type = VIDEO_EVENT_DECODER_STOPPED;
else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
+ unsigned char vsync_field;
+
ev->type = VIDEO_EVENT_VSYNC;
- ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
+ vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
if (itv->output_mode == OUT_UDMA_YUV &&
(itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
IVTV_YUV_MODE_PROGRESSIVE) {
- ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
+ vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
}
+#ifdef CONFIG_COMPAT
+ if (cmd == VIDEO_GET_EVENT32)
+ ev32->u.vsync_field = vsync_field;
+ else
+#endif
+ ev->u.vsync_field = vsync_field;
}
if (ev->type)
return 0;
diff --git a/drivers/media/pci/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c
index d27c6df97566..a641f20e3f86 100644
--- a/drivers/media/pci/ivtv/ivtv-streams.c
+++ b/drivers/media/pci/ivtv/ivtv-streams.c
@@ -51,6 +51,9 @@ static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
.write = ivtv_v4l2_write,
.open = ivtv_v4l2_open,
.unlocked_ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = video_ioctl2, /* for ivtv_default() */
+#endif
.release = ivtv_v4l2_close,
.poll = ivtv_v4l2_enc_poll,
};
@@ -61,6 +64,9 @@ static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
.write = ivtv_v4l2_write,
.open = ivtv_v4l2_open,
.unlocked_ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = video_ioctl2, /* for ivtv_default() */
+#endif
.release = ivtv_v4l2_close,
.poll = ivtv_v4l2_dec_poll,
};
@@ -69,6 +75,9 @@ static const struct v4l2_file_operations ivtv_v4l2_radio_fops = {
.owner = THIS_MODULE,
.open = ivtv_v4l2_open,
.unlocked_ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = video_ioctl2, /* for ivtv_default() */
+#endif
.release = ivtv_v4l2_close,
.poll = ivtv_v4l2_enc_poll,
};
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c
index 44936d6d7c39..1380474519f2 100644
--- a/drivers/media/pci/ivtv/ivtv-yuv.c
+++ b/drivers/media/pci/ivtv/ivtv-yuv.c
@@ -935,7 +935,7 @@ static void ivtv_yuv_init(struct ivtv *itv)
}
/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
- yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN);
+ yi->blanking_ptr = kzalloc(720 * 16, GFP_ATOMIC|__GFP_NOWARN);
if (yi->blanking_ptr) {
yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
} else {
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
index 5ddaa8ed11a5..3e02de02ffdd 100644
--- a/drivers/media/pci/ivtv/ivtvfb.c
+++ b/drivers/media/pci/ivtv/ivtvfb.c
@@ -624,7 +624,7 @@ static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
+ strscpy(fix->id, "cx23415 TV out", sizeof(fix->id));
fix->smem_start = oi->video_pbase;
fix->smem_len = oi->video_buffer_size;
fix->type = FB_TYPE_PACKED_PIXELS;
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
index 8001d3e9134e..bd870e60c32b 100644
--- a/drivers/media/pci/meye/meye.c
+++ b/drivers/media/pci/meye/meye.c
@@ -1019,8 +1019,8 @@ static int meyeioc_stilljcapt(int *len)
static int vidioc_querycap(struct file *file, void *fh,
struct v4l2_capability *cap)
{
- strcpy(cap->driver, "meye");
- strcpy(cap->card, "meye");
+ strscpy(cap->driver, "meye", sizeof(cap->driver));
+ strscpy(cap->card, "meye", sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
@@ -1035,7 +1035,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
if (i->index != 0)
return -EINVAL;
- strcpy(i->name, "Camera");
+ strscpy(i->name, "Camera", sizeof(i->name));
i->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
@@ -1118,12 +1118,12 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
if (f->index == 0) {
/* standard YUV 422 capture */
f->flags = 0;
- strcpy(f->description, "YUV422");
+ strscpy(f->description, "YUV422", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_YUYV;
} else {
/* compressed MJPEG capture */
f->flags = V4L2_FMT_FLAG_COMPRESSED;
- strcpy(f->description, "MJPEG");
+ strscpy(f->description, "MJPEG", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_MJPEG;
}
@@ -1460,7 +1460,7 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long page, pos;
mutex_lock(&meye.lock);
- if (size > gbuffers * gbufsize) {
+ if (size > gbuffers * gbufsize || offset > gbuffers * gbufsize - size) {
mutex_unlock(&meye.lock);
return -EINVAL;
}
diff --git a/drivers/media/pci/ngene/ngene-i2c.c b/drivers/media/pci/ngene/ngene-i2c.c
index 092d46c2a3a9..02a06f6c97f8 100644
--- a/drivers/media/pci/ngene/ngene-i2c.c
+++ b/drivers/media/pci/ngene/ngene-i2c.c
@@ -161,7 +161,7 @@ int ngene_i2c_init(struct ngene *dev, int dev_nr)
i2c_set_adapdata(adap, &(dev->channel[dev_nr]));
- strcpy(adap->name, "nGene");
+ strscpy(adap->name, "nGene", sizeof(adap->name));
adap->algo = &ngene_i2c_algo;
adap->algo_data = (void *)&(dev->channel[dev_nr]);
diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c
index 5e6fe686f420..872c796621d2 100644
--- a/drivers/media/pci/pluto2/pluto2.c
+++ b/drivers/media/pci/pluto2/pluto2.c
@@ -633,7 +633,7 @@ static int pluto2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* i2c */
i2c_set_adapdata(&pluto->i2c_adap, pluto);
- strcpy(pluto->i2c_adap.name, DRIVER_NAME);
+ strscpy(pluto->i2c_adap.name, DRIVER_NAME, sizeof(pluto->i2c_adap.name));
pluto->i2c_adap.owner = THIS_MODULE;
pluto->i2c_adap.dev.parent = &pdev->dev;
pluto->i2c_adap.algo_data = &pluto->i2c_bit;
diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c
index 7f878fc41b7e..f4b8030e2369 100644
--- a/drivers/media/pci/pt1/pt1.c
+++ b/drivers/media/pci/pt1/pt1.c
@@ -1354,7 +1354,7 @@ static int pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i2c_adap->algo = &pt1_i2c_algo;
i2c_adap->algo_data = NULL;
i2c_adap->dev.parent = &pdev->dev;
- strcpy(i2c_adap->name, DRIVER_NAME);
+ strscpy(i2c_adap->name, DRIVER_NAME, sizeof(i2c_adap->name));
i2c_set_adapdata(i2c_adap, pt1);
ret = i2c_add_adapter(i2c_adap);
if (ret < 0)
diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c
index 90273b4d772f..7a7afae4c84c 100644
--- a/drivers/media/pci/pt3/pt3.c
+++ b/drivers/media/pci/pt3/pt3.c
@@ -765,7 +765,7 @@ static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i2c->algo = &pt3_i2c_algo;
i2c->algo_data = NULL;
i2c->dev.parent = &pdev->dev;
- strlcpy(i2c->name, DRV_NAME, sizeof(i2c->name));
+ strscpy(i2c->name, DRV_NAME, sizeof(i2c->name));
i2c_set_adapdata(i2c, pt3);
ret = i2c_add_adapter(i2c);
if (ret < 0)
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index b90cfde6e301..dc9cdaaee1fb 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -901,7 +901,7 @@ static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_saa7134_capture_ops);
pcm->private_data = saa7134;
pcm->info_flags = 0;
- strcpy(pcm->name, "SAA7134 PCM");
+ strscpy(pcm->name, "SAA7134 PCM", sizeof(pcm->name));
return 0;
}
@@ -1074,7 +1074,7 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
unsigned int idx;
int err, addr;
- strcpy(card->mixername, "SAA7134 Mixer");
+ strscpy(card->mixername, "SAA7134 Mixer", sizeof(card->mixername));
for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) {
kcontrol = snd_ctl_new1(&snd_saa7134_volume_controls[idx],
@@ -1138,7 +1138,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
if (err < 0)
return err;
- strcpy(card->driver, "SAA7134");
+ strscpy(card->driver, "SAA7134", sizeof(card->driver));
/* Card "creation" */
@@ -1178,7 +1178,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
/* End of "creation" */
- strcpy(card->shortname, "SAA7134");
+ strscpy(card->shortname, "SAA7134", sizeof(card->shortname));
sprintf(card->longname, "%s at 0x%lx irq %d",
chip->dev->name, chip->iobase, chip->irq);
diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
index 9d6688a82b50..40ce033cb884 100644
--- a/drivers/media/pci/saa7134/saa7134-cards.c
+++ b/drivers/media/pci/saa7134/saa7134-cards.c
@@ -3628,6 +3628,21 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 1,
.amux = TV,
.gpio = 0x0200000,
+ },{
+ .type = SAA7134_INPUT_COMPOSITE1,
+ .vmux = 3,
+ .amux = LINE2,
+ .gpio = 0x0200000,
+ },{
+ .type = SAA7134_INPUT_COMPOSITE2,
+ .vmux = 0,
+ .amux = LINE2,
+ .gpio = 0x0200000,
+ },{
+ .type = SAA7134_INPUT_SVIDEO,
+ .vmux = 8,
+ .amux = LINE2,
+ .gpio = 0x0200000,
}},
},
[SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA] = {
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 9e76de2411ae..8984b1bf57a5 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -845,12 +845,13 @@ static void saa7134_create_entities(struct saa7134_dev *dev)
*/
if (!decoder) {
dev->demod.name = "saa713x";
- dev->demod_pad[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
- dev->demod_pad[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
- dev->demod_pad[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ dev->demod_pad[SAA7134_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ dev->demod_pad[SAA7134_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
+ dev->demod_pad[SAA7134_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ dev->demod_pad[SAA7134_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
dev->demod.function = MEDIA_ENT_F_ATV_DECODER;
- ret = media_entity_pads_init(&dev->demod, DEMOD_NUM_PADS,
+ ret = media_entity_pads_init(&dev->demod, SAA7134_NUM_PADS,
dev->demod_pad);
if (ret < 0)
pr_err("failed to initialize demod pad!\n");
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 66acfd35ffc6..747a082229dc 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -100,7 +100,7 @@ static int empress_enum_fmt_vid_cap(struct file *file, void *priv,
if (f->index != 0)
return -EINVAL;
- strlcpy(f->description, "MPEG TS", sizeof(f->description));
+ strscpy(f->description, "MPEG TS", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_MPEG;
f->flags = V4L2_FMT_FLAG_COMPRESSED;
return 0;
diff --git a/drivers/media/pci/saa7134/saa7134-go7007.c b/drivers/media/pci/saa7134/saa7134-go7007.c
index 2799538e2d7e..275c5e151818 100644
--- a/drivers/media/pci/saa7134/saa7134-go7007.c
+++ b/drivers/media/pci/saa7134/saa7134-go7007.c
@@ -435,7 +435,7 @@ static int saa7134_go7007_init(struct saa7134_dev *dev)
go->board_id = GO7007_BOARDID_PCI_VOYAGER;
snprintf(go->bus_info, sizeof(go->bus_info), "PCI:%s", pci_name(dev->pci));
- strlcpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name));
+ strscpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name));
go->hpi_ops = &saa7134_go7007_hpi_ops;
go->hpi_context = saa;
saa->dev = dev;
diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c
index cf1e526de56a..51af3310654c 100644
--- a/drivers/media/pci/saa7134/saa7134-i2c.c
+++ b/drivers/media/pci/saa7134/saa7134-i2c.c
@@ -437,7 +437,7 @@ int saa7134_i2c_register(struct saa7134_dev *dev)
{
dev->i2c_adap = saa7134_adap_template;
dev->i2c_adap.dev.parent = &dev->pci->dev;
- strcpy(dev->i2c_adap.name,dev->name);
+ strscpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
dev->i2c_adap.algo_data = dev;
i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
i2c_add_adapter(&dev->i2c_adap);
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index 0e28c5021ac4..999b2774b220 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -953,7 +953,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
memset(&info, 0, sizeof(struct i2c_board_info));
memset(&dev->init_data, 0, sizeof(dev->init_data));
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ strscpy(info.type, "ir_video", I2C_NAME_SIZE);
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_PCTV_110i:
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 1a50ec9d084f..1a22ae7cbdd9 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1445,7 +1445,8 @@ int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i)
if (card_in(dev, i->index).type == SAA7134_NO_INPUT)
return -EINVAL;
i->index = n;
- strcpy(i->name, saa7134_input_name[card_in(dev, n).type]);
+ strscpy(i->name, saa7134_input_name[card_in(dev, n).type],
+ sizeof(i->name));
switch (card_in(dev, n).type) {
case SAA7134_INPUT_TV:
case SAA7134_INPUT_TV_MONO:
@@ -1502,8 +1503,8 @@ int saa7134_querycap(struct file *file, void *priv,
unsigned int tuner_type = dev->tuner_type;
- strcpy(cap->driver, "saa7134");
- strlcpy(cap->card, saa7134_boards[dev->board].name,
+ strscpy(cap->driver, "saa7134", sizeof(cap->driver));
+ strscpy(cap->card, saa7134_boards[dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
@@ -1747,7 +1748,7 @@ int saa7134_g_tuner(struct file *file, void *priv,
if (n == SAA7134_INPUT_MAX)
return -EINVAL;
if (card_in(dev, n).type != SAA7134_NO_INPUT) {
- strcpy(t->name, "Television");
+ strscpy(t->name, "Television", sizeof(t->name));
t->type = V4L2_TUNER_ANALOG_TV;
saa_call_all(dev, tuner, g_tuner, t);
t->capability = V4L2_TUNER_CAP_NORM |
@@ -1819,7 +1820,7 @@ static int saa7134_enum_fmt_vid_cap(struct file *file, void *priv,
if (f->index >= FORMATS)
return -EINVAL;
- strlcpy(f->description, formats[f->index].name,
+ strscpy(f->description, formats[f->index].name,
sizeof(f->description));
f->pixelformat = formats[f->index].fourcc;
@@ -1838,7 +1839,7 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv,
if ((f->index >= FORMATS) || formats[f->index].planar)
return -EINVAL;
- strlcpy(f->description, formats[f->index].name,
+ strscpy(f->description, formats[f->index].name,
sizeof(f->description));
f->pixelformat = formats[f->index].fourcc;
@@ -1939,7 +1940,7 @@ static int radio_g_tuner(struct file *file, void *priv,
if (0 != t->index)
return -EINVAL;
- strcpy(t->name, "Radio");
+ strscpy(t->name, "Radio", sizeof(t->name));
saa_call_all(dev, tuner, g_tuner, t);
t->audmode &= V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index d99e937a98c1..480228456014 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -547,6 +547,12 @@ struct saa7134_mpeg_ops {
unsigned long status);
};
+enum saa7134_pads {
+ SAA7134_PAD_IF_INPUT,
+ SAA7134_PAD_VID_OUT,
+ SAA7134_NUM_PADS
+};
+
/* global device status */
struct saa7134_dev {
struct list_head devlist;
@@ -674,7 +680,7 @@ struct saa7134_dev {
struct media_pad input_pad[SAA7134_INPUT_MAX + 1];
struct media_entity demod;
- struct media_pad demod_pad[DEMOD_NUM_PADS];
+ struct media_pad demod_pad[SAA7134_NUM_PADS];
struct media_pad video_pad, vbi_pad;
struct media_entity *decoder;
diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c
index 6b5582b7c595..44440c6208df 100644
--- a/drivers/media/pci/saa7146/mxb.c
+++ b/drivers/media/pci/saa7146/mxb.c
@@ -553,7 +553,7 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
memset(t, 0, sizeof(*t));
- strlcpy(t->name, "TV Tuner", sizeof(t->name));
+ strscpy(t->name, "TV Tuner", sizeof(t->name));
t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c
index d697e1ad929c..f33349e16359 100644
--- a/drivers/media/pci/saa7164/saa7164-core.c
+++ b/drivers/media/pci/saa7164/saa7164-core.c
@@ -179,7 +179,7 @@ static void saa7164_histogram_reset(struct saa7164_histogram *hg, char *name)
int i;
memset(hg, 0, sizeof(struct saa7164_histogram));
- strcpy(hg->name, name);
+ strscpy(hg->name, name, sizeof(hg->name));
/* First 30ms x 1ms */
for (i = 0; i < 30; i++)
diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c
index 4f9f03c3b252..dfb118d7d1ec 100644
--- a/drivers/media/pci/saa7164/saa7164-dvb.c
+++ b/drivers/media/pci/saa7164/saa7164-dvb.c
@@ -120,7 +120,7 @@ static int si2157_attach(struct saa7164_port *port, struct i2c_adapter *adapter,
memset(&bi, 0, sizeof(bi));
- strlcpy(bi.type, "si2157", I2C_NAME_SIZE);
+ strscpy(bi.type, "si2157", I2C_NAME_SIZE);
bi.platform_data = cfg;
bi.addr = addr8bit >> 1;
@@ -643,7 +643,7 @@ int saa7164_dvb_register(struct saa7164_port *port)
si2168_config.fe = &port->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 = 0xc8 >> 1;
info.platform_data = &si2168_config;
request_module(info.type);
@@ -663,7 +663,7 @@ int saa7164_dvb_register(struct saa7164_port *port)
si2157_config.if_port = 1;
si2157_config.fe = port->dvb.frontend;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ strscpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0xc0 >> 1;
info.platform_data = &si2157_config;
request_module(info.type);
@@ -688,7 +688,7 @@ int saa7164_dvb_register(struct saa7164_port *port)
si2168_config.fe = &port->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 = 0xcc >> 1;
info.platform_data = &si2168_config;
request_module(info.type);
@@ -708,7 +708,7 @@ int saa7164_dvb_register(struct saa7164_port *port)
si2157_config.fe = port->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 = 0xc0 >> 1;
info.platform_data = &si2157_config;
request_module(info.type);
diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c
index 32136ebe4f61..adec2bab8352 100644
--- a/drivers/media/pci/saa7164/saa7164-encoder.c
+++ b/drivers/media/pci/saa7164/saa7164-encoder.c
@@ -258,7 +258,7 @@ int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i)
if (i->index >= 7)
return -EINVAL;
- strcpy(i->name, inputs[i->index]);
+ strscpy(i->name, inputs[i->index], sizeof(i->name));
if (i->index == 0)
i->type = V4L2_INPUT_TYPE_TUNER;
@@ -325,7 +325,7 @@ int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
if (0 != t->index)
return -EINVAL;
- strcpy(t->name, "tuner");
+ strscpy(t->name, "tuner", sizeof(t->name));
t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
t->rangelow = SAA7164_TV_MIN_FREQ;
t->rangehigh = SAA7164_TV_MAX_FREQ;
@@ -497,8 +497,8 @@ static int vidioc_querycap(struct file *file, void *priv,
struct saa7164_port *port = fh->port;
struct saa7164_dev *dev = port->dev;
- strcpy(cap->driver, dev->name);
- strlcpy(cap->card, saa7164_boards[dev->board].name,
+ strscpy(cap->driver, dev->name, sizeof(cap->driver));
+ strscpy(cap->card, saa7164_boards[dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
@@ -520,7 +520,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/saa7164/saa7164-i2c.c b/drivers/media/pci/saa7164/saa7164-i2c.c
index 6d13cbb9d010..317f48bc6506 100644
--- a/drivers/media/pci/saa7164/saa7164-i2c.c
+++ b/drivers/media/pci/saa7164/saa7164-i2c.c
@@ -99,7 +99,7 @@ int saa7164_i2c_register(struct saa7164_i2c *bus)
bus->i2c_adap.dev.parent = &dev->pci->dev;
- strlcpy(bus->i2c_adap.name, bus->dev->name,
+ strscpy(bus->i2c_adap.name, bus->dev->name,
sizeof(bus->i2c_adap.name));
bus->i2c_adap.algo_data = bus;
diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c
index 221de91a8bae..841c7e94405d 100644
--- a/drivers/media/pci/saa7164/saa7164-vbi.c
+++ b/drivers/media/pci/saa7164/saa7164-vbi.c
@@ -208,8 +208,8 @@ static int vidioc_querycap(struct file *file, void *priv,
struct saa7164_port *port = fh->port;
struct saa7164_dev *dev = port->dev;
- strcpy(cap->driver, dev->name);
- strlcpy(cap->card, saa7164_boards[dev->board].name,
+ strscpy(cap->driver, dev->name, sizeof(cap->driver));
+ strscpy(cap->card, saa7164_boards[dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
diff --git a/drivers/media/pci/smipcie/smipcie-main.c b/drivers/media/pci/smipcie/smipcie-main.c
index 6dbe3b4d09ce..4d5ddbcb3514 100644
--- a/drivers/media/pci/smipcie/smipcie-main.c
+++ b/drivers/media/pci/smipcie/smipcie-main.c
@@ -191,7 +191,7 @@ static int smi_i2c_init(struct smi_dev *dev)
/* i2c bus 0 */
smi_i2c_cfg(dev, I2C_A_SW_CTL);
i2c_set_adapdata(&dev->i2c_bus[0], dev);
- strcpy(dev->i2c_bus[0].name, "SMI-I2C0");
+ strscpy(dev->i2c_bus[0].name, "SMI-I2C0", sizeof(dev->i2c_bus[0].name));
dev->i2c_bus[0].owner = THIS_MODULE;
dev->i2c_bus[0].dev.parent = &dev->pci_dev->dev;
dev->i2c_bus[0].algo_data = &dev->i2c_bit[0];
@@ -213,7 +213,7 @@ static int smi_i2c_init(struct smi_dev *dev)
/* i2c bus 1 */
smi_i2c_cfg(dev, I2C_B_SW_CTL);
i2c_set_adapdata(&dev->i2c_bus[1], dev);
- strcpy(dev->i2c_bus[1].name, "SMI-I2C1");
+ strscpy(dev->i2c_bus[1].name, "SMI-I2C1", sizeof(dev->i2c_bus[1].name));
dev->i2c_bus[1].owner = THIS_MODULE;
dev->i2c_bus[1].dev.parent = &dev->pci_dev->dev;
dev->i2c_bus[1].algo_data = &dev->i2c_bit[1];
@@ -549,7 +549,7 @@ static int smi_dvbsky_m88ds3103_fe_attach(struct smi_port *port)
}
/* attach tuner */
ts2020_config.fe = port->fe;
- strlcpy(tuner_info.type, "ts2020", I2C_NAME_SIZE);
+ strscpy(tuner_info.type, "ts2020", I2C_NAME_SIZE);
tuner_info.addr = 0x60;
tuner_info.platform_data = &ts2020_config;
tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info);
@@ -605,7 +605,7 @@ static int smi_dvbsky_m88rs6000_fe_attach(struct smi_port *port)
}
/* attach tuner */
m88rs6000t_config.fe = port->fe;
- strlcpy(tuner_info.type, "m88rs6000t", I2C_NAME_SIZE);
+ strscpy(tuner_info.type, "m88rs6000t", I2C_NAME_SIZE);
tuner_info.addr = 0x21;
tuner_info.platform_data = &m88rs6000t_config;
tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info);
@@ -647,7 +647,7 @@ static int smi_dvbsky_sit2_fe_attach(struct smi_port *port)
si2168_config.ts_mode = SI2168_TS_PARALLEL;
memset(&client_info, 0, sizeof(struct i2c_board_info));
- strlcpy(client_info.type, "si2168", I2C_NAME_SIZE);
+ strscpy(client_info.type, "si2168", I2C_NAME_SIZE);
client_info.addr = 0x64;
client_info.platform_data = &si2168_config;
@@ -664,7 +664,7 @@ static int smi_dvbsky_sit2_fe_attach(struct smi_port *port)
si2157_config.if_port = 1;
memset(&client_info, 0, sizeof(struct i2c_board_info));
- strlcpy(client_info.type, "si2157", I2C_NAME_SIZE);
+ strscpy(client_info.type, "si2157", I2C_NAME_SIZE);
client_info.addr = 0x60;
client_info.platform_data = &si2157_config;
diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c
index 2ac33b5cc454..2cc05a9d57ac 100644
--- a/drivers/media/pci/solo6x10/solo6x10-g723.c
+++ b/drivers/media/pci/solo6x10/solo6x10-g723.c
@@ -354,7 +354,7 @@ static int solo_snd_pcm_init(struct solo_dev *solo_dev)
snd_pcm_chip(pcm) = solo_dev;
pcm->info_flags = 0;
- strcpy(pcm->name, card->shortname);
+ strscpy(pcm->name, card->shortname, sizeof(pcm->name));
for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
ss; ss = ss->next, i++)
@@ -394,8 +394,8 @@ int solo_g723_init(struct solo_dev *solo_dev)
card = solo_dev->snd_card;
- strcpy(card->driver, SOLO6X10_NAME);
- strcpy(card->shortname, "SOLO-6x10 Audio");
+ strscpy(card->driver, SOLO6X10_NAME, sizeof(card->driver));
+ strscpy(card->shortname, "SOLO-6x10 Audio", sizeof(card->shortname));
sprintf(card->longname, "%s on %s IRQ %d", card->shortname,
pci_name(solo_dev->pdev), solo_dev->pdev->irq);
@@ -404,7 +404,7 @@ int solo_g723_init(struct solo_dev *solo_dev)
goto snd_error;
/* Mixer controls */
- strcpy(card->mixername, "SOLO-6x10");
+ strscpy(card->mixername, "SOLO-6x10", sizeof(card->mixername));
kctl = snd_solo_capture_volume;
kctl.count = solo_dev->nr_chans;
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 25f9f2ebff1d..9d27e7463070 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -775,7 +775,7 @@ static int solo_enc_querycap(struct file *file, void *priv,
struct solo_enc_dev *solo_enc = video_drvdata(file);
struct solo_dev *solo_dev = solo_enc->solo_dev;
- strcpy(cap->driver, SOLO6X10_NAME);
+ strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
solo_enc->ch);
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
@@ -834,17 +834,18 @@ static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
switch (dev_type) {
case SOLO_DEV_6010:
f->pixelformat = V4L2_PIX_FMT_MPEG4;
- strcpy(f->description, "MPEG-4 part 2");
+ strscpy(f->description, "MPEG-4 part 2",
+ sizeof(f->description));
break;
case SOLO_DEV_6110:
f->pixelformat = V4L2_PIX_FMT_H264;
- strcpy(f->description, "H.264");
+ strscpy(f->description, "H.264", sizeof(f->description));
break;
}
break;
case 1:
f->pixelformat = V4L2_PIX_FMT_MJPEG;
- strcpy(f->description, "MJPEG");
+ strscpy(f->description, "MJPEG", sizeof(f->description));
break;
default:
return -EINVAL;
@@ -1126,7 +1127,8 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
solo_enc->md_thresholds->p_new.p_u16);
break;
case V4L2_CID_OSD_TEXT:
- strcpy(solo_enc->osd_text, ctrl->p_new.p_char);
+ strscpy(solo_enc->osd_text, ctrl->p_new.p_char,
+ sizeof(solo_enc->osd_text));
return solo_osd_print(solo_enc);
default:
return -EINVAL;
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
index 99ffd1ed4a73..69fc939fd3d9 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -383,8 +383,8 @@ static int solo_querycap(struct file *file, void *priv,
{
struct solo_dev *solo_dev = video_drvdata(file);
- strcpy(cap->driver, SOLO6X10_NAME);
- strcpy(cap->card, "Softlogic 6x10");
+ strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
+ strscpy(cap->card, "Softlogic 6x10", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
pci_name(solo_dev->pdev));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
@@ -470,7 +470,7 @@ static int solo_enum_fmt_cap(struct file *file, void *priv,
return -EINVAL;
f->pixelformat = V4L2_PIX_FMT_UYVY;
- strlcpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description));
+ strscpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description));
return 0;
}
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 1858efedaf1a..411177ec4d72 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -419,8 +419,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct sta2x11_vip *vip = video_drvdata(file);
- strcpy(cap->driver, KBUILD_MODNAME);
- strcpy(cap->card, KBUILD_MODNAME);
+ strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+ strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
pci_name(vip->pdev));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
@@ -580,7 +580,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (f->index != 0)
return -EINVAL;
- strcpy(f->description, "4:2:2, packed, UYVY");
+ strscpy(f->description, "4:2:2, packed, UYVY", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_UYVY;
f->flags = 0;
return 0;
diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c
index d6816effb878..409defc75c05 100644
--- a/drivers/media/pci/ttpci/av7110.c
+++ b/drivers/media/pci/ttpci/av7110.c
@@ -2482,7 +2482,8 @@ static int av7110_attach(struct saa7146_dev* dev,
get recognized before the main driver is fully loaded */
saa7146_write(dev, GPIO_CTRL, 0x500000);
- strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
+ strscpy(av7110->i2c_adap.name, pci_ext->ext_priv,
+ sizeof(av7110->i2c_adap.name));
saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c
index ef1bc17cdc4d..1073e4671b68 100644
--- a/drivers/media/pci/ttpci/av7110_av.c
+++ b/drivers/media/pci/ttpci/av7110_av.c
@@ -932,7 +932,6 @@ static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event
return 0;
}
-
/******************************************************************************
* DVB device file operations
******************************************************************************/
@@ -1095,6 +1094,42 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len
return 0;
}
+#ifdef CONFIG_COMPAT
+struct compat_video_still_picture {
+ compat_uptr_t iFrame;
+ int32_t size;
+};
+#define VIDEO_STILLPICTURE32 _IOW('o', 30, struct compat_video_still_picture)
+
+struct compat_video_event {
+ __s32 type;
+ /* unused, make sure to use atomic time for y2038 if it ever gets used */
+ compat_long_t timestamp;
+ union {
+ video_size_t size;
+ unsigned int frame_rate; /* in frames per 1000sec */
+ unsigned char vsync_field; /* unknown/odd/even/progressive */
+ } u;
+};
+#define VIDEO_GET_EVENT32 _IOR('o', 28, struct compat_video_event)
+
+static int dvb_compat_video_get_event(struct av7110 *av7110,
+ struct compat_video_event *event, int flags)
+{
+ struct video_event ev;
+ int ret;
+
+ ret = dvb_video_get_event(av7110, &ev, flags);
+
+ *event = (struct compat_video_event) {
+ .type = ev.type,
+ .timestamp = ev.timestamp,
+ .u.size = ev.u.size,
+ };
+
+ return ret;
+}
+#endif
static int dvb_video_ioctl(struct file *file,
unsigned int cmd, void *parg)
@@ -1184,6 +1219,12 @@ static int dvb_video_ioctl(struct file *file,
memcpy(parg, &av7110->videostate, sizeof(struct video_status));
break;
+#ifdef CONFIG_COMPAT
+ case VIDEO_GET_EVENT32:
+ ret = dvb_compat_video_get_event(av7110, parg, file->f_flags);
+ break;
+#endif
+
case VIDEO_GET_EVENT:
ret = dvb_video_get_event(av7110, parg, file->f_flags);
break;
@@ -1226,6 +1267,19 @@ static int dvb_video_ioctl(struct file *file,
1, (u16) arg);
break;
+#ifdef CONFIG_COMPAT
+ case VIDEO_STILLPICTURE32:
+ {
+ struct compat_video_still_picture *pic =
+ (struct compat_video_still_picture *) parg;
+ av7110->videostate.stream_source = VIDEO_SOURCE_MEMORY;
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
+ ret = play_iframe(av7110, compat_ptr(pic->iFrame),
+ pic->size, file->f_flags & O_NONBLOCK);
+ break;
+ }
+#endif
+
case VIDEO_STILLPICTURE:
{
struct video_still_picture *pic =
@@ -1533,6 +1587,7 @@ static const struct file_operations dvb_video_fops = {
.owner = THIS_MODULE,
.write = dvb_video_write,
.unlocked_ioctl = dvb_generic_ioctl,
+ .compat_ioctl = dvb_generic_ioctl,
.open = dvb_video_open,
.release = dvb_video_release,
.poll = dvb_video_poll,
@@ -1552,6 +1607,7 @@ static const struct file_operations dvb_audio_fops = {
.owner = THIS_MODULE,
.write = dvb_audio_write,
.unlocked_ioctl = dvb_generic_ioctl,
+ .compat_ioctl = dvb_generic_ioctl,
.open = dvb_audio_open,
.release = dvb_audio_release,
.poll = dvb_audio_poll,
diff --git a/drivers/media/pci/ttpci/av7110_v4l.c b/drivers/media/pci/ttpci/av7110_v4l.c
index e4cf42c32284..d1fe15365f4a 100644
--- a/drivers/media/pci/ttpci/av7110_v4l.c
+++ b/drivers/media/pci/ttpci/av7110_v4l.c
@@ -332,7 +332,7 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
return -EINVAL;
memset(t, 0, sizeof(*t));
- strcpy((char *)t->name, "Television");
+ strscpy((char *)t->name, "Television", sizeof(t->name));
t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c
index b3dc45b91101..35b696bdb2df 100644
--- a/drivers/media/pci/ttpci/budget-core.c
+++ b/drivers/media/pci/ttpci/budget-core.c
@@ -504,10 +504,12 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
if (bi->type != BUDGET_FS_ACTIVY)
saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */
- strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name));
+ strscpy(budget->i2c_adap.name, budget->card->name,
+ sizeof(budget->i2c_adap.name));
saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120);
- strcpy(budget->i2c_adap.name, budget->card->name);
+ strscpy(budget->i2c_adap.name, budget->card->name,
+ sizeof(budget->i2c_adap.name));
if (i2c_add_adapter(&budget->i2c_adap) < 0) {
ret = -ENOMEM;
diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c
index ff2b7da90c08..5a1f3aa4101a 100644
--- a/drivers/media/pci/tw5864/tw5864-video.c
+++ b/drivers/media/pci/tw5864/tw5864-video.c
@@ -610,7 +610,7 @@ static int tw5864_querycap(struct file *file, void *priv,
{
struct tw5864_input *input = video_drvdata(file);
- strcpy(cap->driver, "tw5864");
+ strscpy(cap->driver, "tw5864", sizeof(cap->driver));
snprintf(cap->card, sizeof(cap->card), "TW5864 Encoder %d",
input->nr);
sprintf(cap->bus_info, "PCI:%s", pci_name(input->root->pci));
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index 8c1f4a049764..d3f727045ae8 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -734,8 +734,8 @@ static int tw68_querycap(struct file *file, void *priv,
{
struct tw68_dev *dev = video_drvdata(file);
- strcpy(cap->driver, "tw68");
- strlcpy(cap->card, "Techwell Capture Card",
+ strscpy(cap->driver, "tw68", sizeof(cap->driver));
+ strscpy(cap->card, "Techwell Capture Card",
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
cap->device_caps =
@@ -789,7 +789,7 @@ static int tw68_enum_fmt_vid_cap(struct file *file, void *priv,
if (f->index >= FORMATS)
return -EINVAL;
- strlcpy(f->description, formats[f->index].name,
+ strscpy(f->description, formats[f->index].name,
sizeof(f->description));
f->pixelformat = formats[f->index].fourcc;
diff --git a/drivers/media/pci/tw686x/tw686x-audio.c b/drivers/media/pci/tw686x/tw686x-audio.c
index 77190768622a..a28329698e20 100644
--- a/drivers/media/pci/tw686x/tw686x-audio.c
+++ b/drivers/media/pci/tw686x/tw686x-audio.c
@@ -295,7 +295,7 @@ static int tw686x_snd_pcm_init(struct tw686x_dev *dev)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &tw686x_pcm_ops);
snd_pcm_chip(pcm) = dev;
pcm->info_flags = 0;
- strlcpy(pcm->name, "tw686x PCM", sizeof(pcm->name));
+ strscpy(pcm->name, "tw686x PCM", sizeof(pcm->name));
for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
ss; ss = ss->next, i++)
@@ -390,9 +390,9 @@ int tw686x_audio_init(struct tw686x_dev *dev)
return err;
dev->snd_card = card;
- strlcpy(card->driver, "tw686x", sizeof(card->driver));
- strlcpy(card->shortname, "tw686x", sizeof(card->shortname));
- strlcpy(card->longname, pci_name(pci_dev), sizeof(card->longname));
+ strscpy(card->driver, "tw686x", sizeof(card->driver));
+ strscpy(card->shortname, "tw686x", sizeof(card->shortname));
+ strscpy(card->longname, pci_name(pci_dev), sizeof(card->longname));
snd_card_set_dev(card, &pci_dev->dev);
for (ch = 0; ch < max_channels(dev); ch++) {
diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c
index 3a06c000f97b..4890b7f1248b 100644
--- a/drivers/media/pci/tw686x/tw686x-video.c
+++ b/drivers/media/pci/tw686x/tw686x-video.c
@@ -765,8 +765,8 @@ static int tw686x_querycap(struct file *file, void *priv,
struct tw686x_video_channel *vc = video_drvdata(file);
struct tw686x_dev *dev = vc->dev;
- strlcpy(cap->driver, "tw686x", sizeof(cap->driver));
- strlcpy(cap->card, dev->name, sizeof(cap->card));
+ strscpy(cap->driver, "tw686x", sizeof(cap->driver));
+ strscpy(cap->card, dev->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"PCI:%s", pci_name(dev->pci_dev));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 54fe90acb5b2..70c4f6c54881 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -58,6 +58,7 @@ config VIDEO_MUX
select MULTIPLEXER
depends on VIDEO_V4L2 && OF && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
select REGMAP
+ select V4L2_FWNODE
help
This driver provides support for N:1 video bus multiplexers.
@@ -181,6 +182,15 @@ config VIDEO_CODA
config VIDEO_IMX_VDOA
def_tristate VIDEO_CODA if SOC_IMX6Q || COMPILE_TEST
+config VIDEO_IMX_PXP
+ tristate "i.MX Pixel Pipeline (PXP)"
+ depends on VIDEO_DEV && VIDEO_V4L2 && (ARCH_MXC || COMPILE_TEST)
+ select VIDEOBUF2_DMA_CONTIG
+ select V4L2_MEM2MEM_DEV
+ help
+ The i.MX Pixel Pipeline is a memory-to-memory engine for scaling,
+ color space conversion, and rotation.
+
config VIDEO_MEDIATEK_JPEG
tristate "Mediatek JPEG Codec driver"
depends on MTK_IOMMU_V1 || COMPILE_TEST
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 41322ab65802..6ab6200dd9c9 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -25,6 +25,8 @@ obj-$(CONFIG_VIDEO_TI_CAL) += ti-vpe/
obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o
obj-$(CONFIG_VIDEO_CODA) += coda/
+obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o
+
obj-$(CONFIG_VIDEO_SH_VEU) += sh_veu.o
obj-$(CONFIG_CEC_GPIO) += cec-gpio/
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index b05738a95e55..e13d2b3a7168 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -1408,8 +1408,8 @@ static int vpfe_querycap(struct file *file, void *priv,
vpfe_dbg(2, vpfe, "vpfe_querycap\n");
- strlcpy(cap->driver, VPFE_MODULE_NAME, sizeof(cap->driver));
- strlcpy(cap->card, "TI AM437x VPFE", sizeof(cap->card));
+ strscpy(cap->driver, VPFE_MODULE_NAME, sizeof(cap->driver));
+ strscpy(cap->card, "TI AM437x VPFE", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:%s", vpfe->v4l2_dev.name);
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
@@ -2386,7 +2386,7 @@ static int vpfe_probe_complete(struct vpfe_device *vpfe)
INIT_LIST_HEAD(&vpfe->dma_queue);
vdev = &vpfe->video_dev;
- strlcpy(vdev->name, VPFE_MODULE_NAME, sizeof(vdev->name));
+ strscpy(vdev->name, VPFE_MODULE_NAME, sizeof(vdev->name));
vdev->release = video_device_release_empty;
vdev->fops = &vpfe_fops;
vdev->ioctl_ops = &vpfe_ioctl_ops;
@@ -2423,30 +2423,32 @@ static const struct v4l2_async_notifier_operations vpfe_async_ops = {
};
static struct vpfe_config *
-vpfe_get_pdata(struct platform_device *pdev)
+vpfe_get_pdata(struct vpfe_device *vpfe)
{
struct device_node *endpoint = NULL;
- struct v4l2_fwnode_endpoint bus_cfg;
+ struct device *dev = vpfe->pdev;
struct vpfe_subdev_info *sdinfo;
struct vpfe_config *pdata;
unsigned int flags;
unsigned int i;
int err;
- dev_dbg(&pdev->dev, "vpfe_get_pdata\n");
+ dev_dbg(dev, "vpfe_get_pdata\n");
- if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node)
- return pdev->dev.platform_data;
+ v4l2_async_notifier_init(&vpfe->notifier);
- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
+ return dev->platform_data;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
for (i = 0; ; i++) {
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct device_node *rem;
- endpoint = of_graph_get_next_endpoint(pdev->dev.of_node,
- endpoint);
+ endpoint = of_graph_get_next_endpoint(dev->of_node, endpoint);
if (!endpoint)
break;
@@ -2455,7 +2457,8 @@ vpfe_get_pdata(struct platform_device *pdev)
/* we only support camera */
sdinfo->inputs[0].index = i;
- strcpy(sdinfo->inputs[0].name, "Camera");
+ strscpy(sdinfo->inputs[0].name, "Camera",
+ sizeof(sdinfo->inputs[0].name));
sdinfo->inputs[0].type = V4L2_INPUT_TYPE_CAMERA;
sdinfo->inputs[0].std = V4L2_STD_ALL;
sdinfo->inputs[0].capabilities = V4L2_IN_CAP_STD;
@@ -2473,16 +2476,16 @@ vpfe_get_pdata(struct platform_device *pdev)
err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
&bus_cfg);
if (err) {
- dev_err(&pdev->dev, "Could not parse the endpoint\n");
- goto done;
+ dev_err(dev, "Could not parse the endpoint\n");
+ goto cleanup;
}
sdinfo->vpfe_param.bus_width = bus_cfg.bus.parallel.bus_width;
if (sdinfo->vpfe_param.bus_width < 8 ||
sdinfo->vpfe_param.bus_width > 16) {
- dev_err(&pdev->dev, "Invalid bus width.\n");
- goto done;
+ dev_err(dev, "Invalid bus width.\n");
+ goto cleanup;
}
flags = bus_cfg.bus.parallel.flags;
@@ -2495,29 +2498,25 @@ vpfe_get_pdata(struct platform_device *pdev)
rem = of_graph_get_remote_port_parent(endpoint);
if (!rem) {
- dev_err(&pdev->dev, "Remote device at %pOF not found\n",
+ dev_err(dev, "Remote device at %pOF not found\n",
endpoint);
- goto done;
+ goto cleanup;
}
- pdata->asd[i] = devm_kzalloc(&pdev->dev,
- sizeof(struct v4l2_async_subdev),
- GFP_KERNEL);
- if (!pdata->asd[i]) {
+ pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev(
+ &vpfe->notifier, of_fwnode_handle(rem),
+ sizeof(struct v4l2_async_subdev));
+ if (IS_ERR(pdata->asd[i])) {
of_node_put(rem);
- pdata = NULL;
- goto done;
+ goto cleanup;
}
-
- pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE;
- pdata->asd[i]->match.fwnode = of_fwnode_handle(rem);
- of_node_put(rem);
}
of_node_put(endpoint);
return pdata;
-done:
+cleanup:
+ v4l2_async_notifier_cleanup(&vpfe->notifier);
of_node_put(endpoint);
return NULL;
}
@@ -2529,34 +2528,39 @@ done:
*/
static int vpfe_probe(struct platform_device *pdev)
{
- struct vpfe_config *vpfe_cfg = vpfe_get_pdata(pdev);
+ struct vpfe_config *vpfe_cfg;
struct vpfe_device *vpfe;
struct vpfe_ccdc *ccdc;
struct resource *res;
int ret;
- if (!vpfe_cfg) {
- dev_err(&pdev->dev, "No platform data\n");
- return -EINVAL;
- }
-
vpfe = devm_kzalloc(&pdev->dev, sizeof(*vpfe), GFP_KERNEL);
if (!vpfe)
return -ENOMEM;
vpfe->pdev = &pdev->dev;
+
+ vpfe_cfg = vpfe_get_pdata(vpfe);
+ if (!vpfe_cfg) {
+ dev_err(&pdev->dev, "No platform data\n");
+ return -EINVAL;
+ }
+
vpfe->cfg = vpfe_cfg;
ccdc = &vpfe->ccdc;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ccdc->ccdc_cfg.base_addr = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(ccdc->ccdc_cfg.base_addr))
- return PTR_ERR(ccdc->ccdc_cfg.base_addr);
+ if (IS_ERR(ccdc->ccdc_cfg.base_addr)) {
+ ret = PTR_ERR(ccdc->ccdc_cfg.base_addr);
+ goto probe_out_cleanup;
+ }
ret = platform_get_irq(pdev, 0);
if (ret <= 0) {
dev_err(&pdev->dev, "No IRQ resource\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto probe_out_cleanup;
}
vpfe->irq = ret;
@@ -2564,14 +2568,15 @@ static int vpfe_probe(struct platform_device *pdev)
"vpfe_capture0", vpfe);
if (ret) {
dev_err(&pdev->dev, "Unable to request interrupt\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto probe_out_cleanup;
}
ret = v4l2_device_register(&pdev->dev, &vpfe->v4l2_dev);
if (ret) {
vpfe_err(vpfe,
"Unable to register v4l2 device.\n");
- return ret;
+ goto probe_out_cleanup;
}
/* set the driver data in platform device */
@@ -2595,11 +2600,8 @@ static int vpfe_probe(struct platform_device *pdev)
goto probe_out_v4l2_unregister;
}
- vpfe->notifier.subdevs = vpfe->cfg->asd;
- vpfe->notifier.num_subdevs = ARRAY_SIZE(vpfe->cfg->asd);
vpfe->notifier.ops = &vpfe_async_ops;
- ret = v4l2_async_notifier_register(&vpfe->v4l2_dev,
- &vpfe->notifier);
+ ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, &vpfe->notifier);
if (ret) {
vpfe_err(vpfe, "Error registering async notifier\n");
ret = -EINVAL;
@@ -2610,6 +2612,8 @@ static int vpfe_probe(struct platform_device *pdev)
probe_out_v4l2_unregister:
v4l2_device_unregister(&vpfe->v4l2_dev);
+probe_out_cleanup:
+ v4l2_async_notifier_cleanup(&vpfe->notifier);
return ret;
}
@@ -2625,6 +2629,7 @@ static int vpfe_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
v4l2_async_notifier_unregister(&vpfe->notifier);
+ v4l2_async_notifier_cleanup(&vpfe->notifier);
v4l2_device_unregister(&vpfe->v4l2_dev);
video_unregister_device(&vpfe->video_dev);
diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c
index d89e14524d42..50178968b8a6 100644
--- a/drivers/media/platform/atmel/atmel-isc.c
+++ b/drivers/media/platform/atmel/atmel-isc.c
@@ -1238,8 +1238,8 @@ static int isc_querycap(struct file *file, void *priv,
{
struct isc_device *isc = video_drvdata(file);
- strcpy(cap->driver, ATMEL_ISC_NAME);
- strcpy(cap->card, "Atmel Image Sensor Controller");
+ strscpy(cap->driver, ATMEL_ISC_NAME, sizeof(cap->driver));
+ strscpy(cap->card, "Atmel Image Sensor Controller", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:%s", isc->v4l2_dev.name);
@@ -1393,7 +1393,7 @@ static int isc_enum_input(struct file *file, void *priv,
inp->type = V4L2_INPUT_TYPE_CAMERA;
inp->std = 0;
- strcpy(inp->name, "Camera");
+ strscpy(inp->name, "Camera", sizeof(inp->name));
return 0;
}
@@ -1951,7 +1951,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
INIT_WORK(&isc->awb_work, isc_awb_work);
/* Register video device */
- strlcpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name));
+ strscpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name));
vdev->release = video_device_release_empty;
vdev->fops = &isc_fops;
vdev->ioctl_ops = &isc_ioctl_ops;
@@ -1983,8 +1983,10 @@ static void isc_subdev_cleanup(struct isc_device *isc)
{
struct isc_subdev_entity *subdev_entity;
- list_for_each_entry(subdev_entity, &isc->subdev_entities, list)
+ list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
v4l2_async_notifier_unregister(&subdev_entity->notifier);
+ v4l2_async_notifier_cleanup(&subdev_entity->notifier);
+ }
INIT_LIST_HEAD(&isc->subdev_entities);
}
@@ -2026,7 +2028,6 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
{
struct device_node *np = dev->of_node;
struct device_node *epn = NULL, *rem;
- struct v4l2_fwnode_endpoint v4l2_epn;
struct isc_subdev_entity *subdev_entity;
unsigned int flags;
int ret;
@@ -2034,6 +2035,8 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
INIT_LIST_HEAD(&isc->subdev_entities);
while (1) {
+ struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 };
+
epn = of_graph_get_next_endpoint(np, epn);
if (!epn)
return 0;
@@ -2201,8 +2204,15 @@ static int atmel_isc_probe(struct platform_device *pdev)
}
list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
- subdev_entity->notifier.subdevs = &subdev_entity->asd;
- subdev_entity->notifier.num_subdevs = 1;
+ v4l2_async_notifier_init(&subdev_entity->notifier);
+
+ ret = v4l2_async_notifier_add_subdev(&subdev_entity->notifier,
+ subdev_entity->asd);
+ if (ret) {
+ fwnode_handle_put(subdev_entity->asd->match.fwnode);
+ goto cleanup_subdev;
+ }
+
subdev_entity->notifier.ops = &isc_async_ops;
ret = v4l2_async_notifier_register(&isc->v4l2_dev,
diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
index e8db4df1e7c4..fdb255e4a956 100644
--- a/drivers/media/platform/atmel/atmel-isi.c
+++ b/drivers/media/platform/atmel/atmel-isi.c
@@ -655,9 +655,9 @@ static int isi_enum_fmt_vid_cap(struct file *file, void *priv,
static int isi_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strlcpy(cap->driver, "atmel-isi", sizeof(cap->driver));
- strlcpy(cap->card, "Atmel Image Sensor Interface", sizeof(cap->card));
- strlcpy(cap->bus_info, "platform:isi", sizeof(cap->bus_info));
+ strscpy(cap->driver, "atmel-isi", sizeof(cap->driver));
+ strscpy(cap->card, "Atmel Image Sensor Interface", sizeof(cap->card));
+ strscpy(cap->bus_info, "platform:isi", sizeof(cap->bus_info));
return 0;
}
@@ -668,7 +668,7 @@ static int isi_enum_input(struct file *file, void *priv,
return -EINVAL;
i->type = V4L2_INPUT_TYPE_CAMERA;
- strlcpy(i->name, "Camera", sizeof(i->name));
+ strscpy(i->name, "Camera", sizeof(i->name));
return 0;
}
@@ -790,7 +790,7 @@ static int atmel_isi_parse_dt(struct atmel_isi *isi,
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct v4l2_fwnode_endpoint ep;
+ struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
int err;
/* Default settings for ISI */
@@ -1124,7 +1124,6 @@ static int isi_graph_parse(struct atmel_isi *isi, struct device_node *node)
static int isi_graph_init(struct atmel_isi *isi)
{
- struct v4l2_async_subdev **subdevs = NULL;
int ret;
/* Parse the graph to extract a list of subdevice DT nodes. */
@@ -1134,23 +1133,20 @@ static int isi_graph_init(struct atmel_isi *isi)
return ret;
}
- /* Register the subdevices notifier. */
- subdevs = devm_kzalloc(isi->dev, sizeof(*subdevs), GFP_KERNEL);
- if (!subdevs) {
+ v4l2_async_notifier_init(&isi->notifier);
+
+ ret = v4l2_async_notifier_add_subdev(&isi->notifier, &isi->entity.asd);
+ if (ret) {
of_node_put(isi->entity.node);
- return -ENOMEM;
+ return ret;
}
- subdevs[0] = &isi->entity.asd;
-
- isi->notifier.subdevs = subdevs;
- isi->notifier.num_subdevs = 1;
isi->notifier.ops = &isi_graph_notify_ops;
ret = v4l2_async_notifier_register(&isi->v4l2_dev, &isi->notifier);
if (ret < 0) {
dev_err(isi->dev, "Notifier registration failed\n");
- of_node_put(isi->entity.node);
+ v4l2_async_notifier_cleanup(&isi->notifier);
return ret;
}
@@ -1202,7 +1198,7 @@ static int atmel_isi_probe(struct platform_device *pdev)
isi->vdev->fops = &isi_fops;
isi->vdev->v4l2_dev = &isi->v4l2_dev;
isi->vdev->queue = &isi->queue;
- strlcpy(isi->vdev->name, KBUILD_MODNAME, sizeof(isi->vdev->name));
+ strscpy(isi->vdev->name, KBUILD_MODNAME, sizeof(isi->vdev->name));
isi->vdev->release = video_device_release;
isi->vdev->ioctl_ops = &isi_ioctl_ops;
isi->vdev->lock = &isi->lock;
@@ -1303,6 +1299,7 @@ static int atmel_isi_remove(struct platform_device *pdev)
isi->fb_descriptors_phys);
pm_runtime_disable(&pdev->dev);
v4l2_async_notifier_unregister(&isi->notifier);
+ v4l2_async_notifier_cleanup(&isi->notifier);
v4l2_device_unregister(&isi->v4l2_dev);
return 0;
diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 43e43c7b3e98..31ace114eda1 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -361,7 +361,7 @@ static int csi2rx_get_resources(struct csi2rx_priv *csi2rx,
static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
{
- struct v4l2_fwnode_endpoint v4l2_ep;
+ struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 };
struct fwnode_handle *fwh;
struct device_node *ep;
int ret;
@@ -378,7 +378,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
return ret;
}
- if (v4l2_ep.bus_type != V4L2_MBUS_CSI2) {
+ if (v4l2_ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
dev_err(csi2rx->dev, "Unsupported media bus type: 0x%x\n",
v4l2_ep.bus_type);
of_node_put(ep);
@@ -399,18 +399,22 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
csi2rx->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
of_node_put(ep);
- csi2rx->notifier.subdevs = devm_kzalloc(csi2rx->dev,
- sizeof(*csi2rx->notifier.subdevs),
- GFP_KERNEL);
- if (!csi2rx->notifier.subdevs)
- return -ENOMEM;
+ v4l2_async_notifier_init(&csi2rx->notifier);
+
+ ret = v4l2_async_notifier_add_subdev(&csi2rx->notifier, &csi2rx->asd);
+ if (ret) {
+ fwnode_handle_put(csi2rx->asd.match.fwnode);
+ return ret;
+ }
- csi2rx->notifier.subdevs[0] = &csi2rx->asd;
- csi2rx->notifier.num_subdevs = 1;
csi2rx->notifier.ops = &csi2rx_notifier_ops;
- return v4l2_async_subdev_notifier_register(&csi2rx->subdev,
- &csi2rx->notifier);
+ ret = v4l2_async_subdev_notifier_register(&csi2rx->subdev,
+ &csi2rx->notifier);
+ if (ret)
+ v4l2_async_notifier_cleanup(&csi2rx->notifier);
+
+ return ret;
}
static int csi2rx_probe(struct platform_device *pdev)
@@ -450,11 +454,11 @@ static int csi2rx_probe(struct platform_device *pdev)
ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
csi2rx->pads);
if (ret)
- goto err_free_priv;
+ goto err_cleanup;
ret = v4l2_async_register_subdev(&csi2rx->subdev);
if (ret < 0)
- goto err_free_priv;
+ goto err_cleanup;
dev_info(&pdev->dev,
"Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
@@ -463,6 +467,8 @@ static int csi2rx_probe(struct platform_device *pdev)
return 0;
+err_cleanup:
+ v4l2_async_notifier_cleanup(&csi2rx->notifier);
err_free_priv:
kfree(csi2rx);
return ret;
diff --git a/drivers/media/platform/cadence/cdns-csi2tx.c b/drivers/media/platform/cadence/cdns-csi2tx.c
index 40d0de690ff4..5042d053b94e 100644
--- a/drivers/media/platform/cadence/cdns-csi2tx.c
+++ b/drivers/media/platform/cadence/cdns-csi2tx.c
@@ -432,7 +432,7 @@ static int csi2tx_get_resources(struct csi2tx_priv *csi2tx,
static int csi2tx_check_lanes(struct csi2tx_priv *csi2tx)
{
- struct v4l2_fwnode_endpoint v4l2_ep;
+ struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 };
struct device_node *ep;
int ret;
@@ -446,7 +446,7 @@ static int csi2tx_check_lanes(struct csi2tx_priv *csi2tx)
goto out;
}
- if (v4l2_ep.bus_type != V4L2_MBUS_CSI2) {
+ if (v4l2_ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
dev_err(csi2tx->dev, "Unsupported media bus type: 0x%x\n",
v4l2_ep.bus_type);
ret = -EINVAL;
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 726b3b93a486..2848ea5f464d 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -376,8 +376,7 @@ static struct vdoa_data *coda_get_vdoa_data(void)
vdoa_data = ERR_PTR(-EPROBE_DEFER);
out:
- if (vdoa_node)
- of_node_put(vdoa_node);
+ of_node_put(vdoa_node);
return vdoa_data;
}
@@ -390,10 +389,10 @@ static int coda_querycap(struct file *file, void *priv,
{
struct coda_ctx *ctx = fh_to_ctx(priv);
- strlcpy(cap->driver, CODA_NAME, sizeof(cap->driver));
- strlcpy(cap->card, coda_product_name(ctx->dev->devtype->product),
+ strscpy(cap->driver, CODA_NAME, sizeof(cap->driver));
+ strscpy(cap->card, coda_product_name(ctx->dev->devtype->product),
sizeof(cap->card));
- strlcpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info));
+ strscpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -1804,7 +1803,8 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
break;
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
/* TODO: switch between baseline and constrained baseline */
- ctx->params.h264_profile_idc = 66;
+ if (ctx->inst_type == CODA_INST_ENCODER)
+ ctx->params.h264_profile_idc = 66;
break;
case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
/* nothing to do, this is set by the encoder */
@@ -2408,7 +2408,7 @@ static int coda_register_device(struct coda_dev *dev, int i)
if (i >= dev->devtype->num_vdevs)
return -EINVAL;
- strlcpy(vfd->name, dev->devtype->vdevs[i]->name, sizeof(vfd->name));
+ strscpy(vfd->name, dev->devtype->vdevs[i]->name, sizeof(vfd->name));
vfd->fops = &coda_fops;
vfd->ioctl_ops = &coda_ioctl_ops;
vfd->release = video_device_release_empty,
diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c
index f924e76e2fbf..340f8218f54d 100644
--- a/drivers/media/platform/davinci/isif.c
+++ b/drivers/media/platform/davinci/isif.c
@@ -1100,7 +1100,8 @@ fail_nobase_res:
while (i >= 0) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
- release_mem_region(res->start, resource_size(res));
+ if (res)
+ release_mem_region(res->start, resource_size(res));
i--;
}
vpfe_unregister_ccdc_device(&isif_hw_dev);
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index b0eb3d899eb4..5c235898af7b 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -521,7 +521,7 @@ vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev,
else if (v_scale == 4)
layer_info->v_zoom = ZOOM_X4;
if (v_exp)
- layer_info->h_exp = V_EXP_6_OVER_5;
+ layer_info->v_exp = V_EXP_6_OVER_5;
} else {
/* no scaling, only cropping. Set display area to crop area */
cfg->ysize = expected_ysize;
@@ -647,7 +647,7 @@ static int vpbe_display_querycap(struct file *file, void *priv,
dev_name(vpbe_dev->pdev));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(vpbe_dev->pdev));
- strlcpy(cap->card, vpbe_dev->cfg->module_name, sizeof(cap->card));
+ strscpy(cap->card, vpbe_dev->cfg->module_name, sizeof(cap->card));
return 0;
}
@@ -816,10 +816,12 @@ static int vpbe_display_enum_fmt(struct file *file, void *priv,
fmt->index = index;
fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
if (index == 0) {
- strcpy(fmt->description, "YUV 4:2:2 - UYVY");
+ strscpy(fmt->description, "YUV 4:2:2 - UYVY",
+ sizeof(fmt->description));
fmt->pixelformat = V4L2_PIX_FMT_UYVY;
} else {
- strcpy(fmt->description, "Y/CbCr 4:2:0");
+ strscpy(fmt->description, "Y/CbCr 4:2:0",
+ sizeof(fmt->description));
fmt->pixelformat = V4L2_PIX_FMT_NV12;
}
diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c
index ddcad7b3e76c..ca78eb29641a 100644
--- a/drivers/media/platform/davinci/vpbe_venc.c
+++ b/drivers/media/platform/davinci/vpbe_venc.c
@@ -616,7 +616,7 @@ struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev,
v4l2_subdev_init(&venc->sd, &venc_ops);
- strcpy(venc->sd.name, venc_name);
+ strscpy(venc->sd.name, venc_name, sizeof(venc->sd.name));
if (v4l2_device_register_subdev(v4l2_dev, &venc->sd) < 0) {
v4l2_err(v4l2_dev,
"vpbe unable to register venc sub device\n");
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
index 8613358ed245..ea3ddd5a42bd 100644
--- a/drivers/media/platform/davinci/vpfe_capture.c
+++ b/drivers/media/platform/davinci/vpfe_capture.c
@@ -889,9 +889,9 @@ static int vpfe_querycap(struct file *file, void *priv,
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
- strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
- strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
- strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
+ strscpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
+ strscpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
+ strscpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
return 0;
}
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index a96f53ce8088..6216b7ac6875 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -949,11 +949,13 @@ static int vpif_enum_fmt_vid_cap(struct file *file, void *priv,
/* Fill in the information about format */
if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) {
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- strcpy(fmt->description, "Raw Mode -Bayer Pattern GrRBGb");
+ strscpy(fmt->description, "Raw Mode -Bayer Pattern GrRBGb",
+ sizeof(fmt->description));
fmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
} else {
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- strcpy(fmt->description, "YCbCr4:2:2 Semi-Planar");
+ strscpy(fmt->description, "YCbCr4:2:2 Semi-Planar",
+ sizeof(fmt->description));
fmt->pixelformat = V4L2_PIX_FMT_NV16;
}
return 0;
@@ -1094,10 +1096,10 @@ static int vpif_querycap(struct file *file, void *priv,
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
- strlcpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver));
+ strscpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(vpif_dev));
- strlcpy(cap->card, config->card_name, sizeof(cap->card));
+ strscpy(cap->card, config->card_name, sizeof(cap->card));
return 0;
}
@@ -1463,7 +1465,7 @@ static int vpif_probe_complete(void)
/* Initialize the video_device structure */
vdev = &ch->video_dev;
- strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name));
+ strscpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name));
vdev->release = video_device_release_empty;
vdev->fops = &vpif_fops;
vdev->ioctl_ops = &vpif_ioctl_ops;
@@ -1509,12 +1511,13 @@ static struct vpif_capture_config *
vpif_capture_get_pdata(struct platform_device *pdev)
{
struct device_node *endpoint = NULL;
- struct v4l2_fwnode_endpoint bus_cfg;
struct vpif_capture_config *pdata;
struct vpif_subdev_info *sdinfo;
struct vpif_capture_chan_config *chan;
unsigned int i;
+ v4l2_async_notifier_init(&vpif_obj.notifier);
+
/*
* DT boot: OF node from parent device contains
* video ports & endpoints data.
@@ -1537,6 +1540,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
return NULL;
for (i = 0; i < VPIF_CAPTURE_NUM_CHANNELS; i++) {
+ struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
struct device_node *rem;
unsigned int flags;
int err;
@@ -1546,14 +1550,25 @@ vpif_capture_get_pdata(struct platform_device *pdev)
if (!endpoint)
break;
+ rem = of_graph_get_remote_port_parent(endpoint);
+ if (!rem) {
+ dev_dbg(&pdev->dev, "Remote device at %pOF not found\n",
+ endpoint);
+ of_node_put(endpoint);
+ goto done;
+ }
+
sdinfo = &pdata->subdev_info[i];
chan = &pdata->chan_config[i];
chan->inputs = devm_kcalloc(&pdev->dev,
VPIF_CAPTURE_NUM_CHANNELS,
sizeof(*chan->inputs),
GFP_KERNEL);
- if (!chan->inputs)
- return NULL;
+ if (!chan->inputs) {
+ of_node_put(rem);
+ of_node_put(endpoint);
+ goto err_cleanup;
+ }
chan->input_count++;
chan->inputs[i].input.type = V4L2_INPUT_TYPE_CAMERA;
@@ -1562,12 +1577,16 @@ vpif_capture_get_pdata(struct platform_device *pdev)
err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
&bus_cfg);
+ of_node_put(endpoint);
if (err) {
dev_err(&pdev->dev, "Could not parse the endpoint\n");
+ of_node_put(rem);
goto done;
}
+
dev_dbg(&pdev->dev, "Endpoint %pOF, bus_width = %d\n",
endpoint, bus_cfg.bus.parallel.bus_width);
+
flags = bus_cfg.bus.parallel.flags;
if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
@@ -1576,39 +1595,29 @@ vpif_capture_get_pdata(struct platform_device *pdev)
if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
chan->vpif_if.vd_pol = 1;
- rem = of_graph_get_remote_port_parent(endpoint);
- if (!rem) {
- dev_dbg(&pdev->dev, "Remote device at %pOF not found\n",
- endpoint);
- goto done;
- }
-
- dev_dbg(&pdev->dev, "Remote device %s, %pOF found\n",
- rem->name, rem);
+ dev_dbg(&pdev->dev, "Remote device %pOF found\n", rem);
sdinfo->name = rem->full_name;
- pdata->asd[i] = devm_kzalloc(&pdev->dev,
- sizeof(struct v4l2_async_subdev),
- GFP_KERNEL);
- if (!pdata->asd[i]) {
+ pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev(
+ &vpif_obj.notifier, of_fwnode_handle(rem),
+ sizeof(struct v4l2_async_subdev));
+ if (IS_ERR(pdata->asd[i])) {
of_node_put(rem);
- pdata = NULL;
- goto done;
+ goto err_cleanup;
}
-
- pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE;
- pdata->asd[i]->match.fwnode = of_fwnode_handle(rem);
- of_node_put(rem);
}
done:
- if (pdata) {
- pdata->asd_sizes[0] = i;
- pdata->subdev_count = i;
- pdata->card_name = "DA850/OMAP-L138 Video Capture";
- }
+ pdata->asd_sizes[0] = i;
+ pdata->subdev_count = i;
+ pdata->card_name = "DA850/OMAP-L138 Video Capture";
return pdata;
+
+err_cleanup:
+ v4l2_async_notifier_cleanup(&vpif_obj.notifier);
+
+ return NULL;
}
/**
@@ -1633,23 +1642,18 @@ static __init int vpif_probe(struct platform_device *pdev)
return -EINVAL;
}
- if (!pdev->dev.platform_data) {
- dev_warn(&pdev->dev, "Missing platform data. Giving up.\n");
- return -EINVAL;
- }
-
vpif_dev = &pdev->dev;
err = initialize_vpif();
if (err) {
v4l2_err(vpif_dev->driver, "Error initializing vpif\n");
- return err;
+ goto cleanup;
}
err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
if (err) {
v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
- return err;
+ goto cleanup;
}
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
@@ -1698,8 +1702,6 @@ static __init int vpif_probe(struct platform_device *pdev)
}
vpif_probe_complete();
} else {
- vpif_obj.notifier.subdevs = vpif_obj.config->asd;
- vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0];
vpif_obj.notifier.ops = &vpif_async_ops;
err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
&vpif_obj.notifier);
@@ -1717,6 +1719,8 @@ probe_subdev_out:
kfree(vpif_obj.sd);
vpif_unregister:
v4l2_device_unregister(&vpif_obj.v4l2_dev);
+cleanup:
+ v4l2_async_notifier_cleanup(&vpif_obj.notifier);
return err;
}
@@ -1732,6 +1736,8 @@ static int vpif_remove(struct platform_device *device)
struct channel_obj *ch;
int i;
+ v4l2_async_notifier_unregister(&vpif_obj.notifier);
+ v4l2_async_notifier_cleanup(&vpif_obj.notifier);
v4l2_device_unregister(&vpif_obj.v4l2_dev);
kfree(vpif_obj.sd);
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 0f324055cc9f..3517487d9760 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -586,10 +586,10 @@ static int vpif_querycap(struct file *file, void *priv,
cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
- strlcpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver));
+ strscpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(vpif_dev));
- strlcpy(cap->card, config->card_name, sizeof(cap->card));
+ strscpy(cap->card, config->card_name, sizeof(cap->card));
return 0;
}
@@ -602,7 +602,8 @@ static int vpif_enum_fmt_vid_out(struct file *file, void *priv,
/* Fill in the information about format */
fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- strcpy(fmt->description, "YCbCr4:2:2 YC Planar");
+ strscpy(fmt->description, "YCbCr4:2:2 YC Planar",
+ sizeof(fmt->description));
fmt->pixelformat = V4L2_PIX_FMT_YUV422P;
fmt->flags = 0;
return 0;
@@ -1209,7 +1210,7 @@ static int vpif_probe_complete(void)
/* Initialize the video_device structure */
vdev = &ch->video_dev;
- strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name));
+ strscpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name));
vdev->release = video_device_release_empty;
vdev->fops = &vpif_fops;
vdev->ioctl_ops = &vpif_ioctl_ops;
@@ -1299,6 +1300,8 @@ static __init int vpif_probe(struct platform_device *pdev)
goto vpif_unregister;
}
+ v4l2_async_notifier_init(&vpif_obj.notifier);
+
if (!vpif_obj.config->asd_sizes) {
i2c_adap = i2c_get_adapter(vpif_obj.config->i2c_adapter_id);
for (i = 0; i < subdev_count; i++) {
@@ -1322,20 +1325,27 @@ static __init int vpif_probe(struct platform_device *pdev)
goto probe_subdev_out;
}
} else {
- vpif_obj.notifier.subdevs = vpif_obj.config->asd;
- vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0];
+ for (i = 0; i < vpif_obj.config->asd_sizes[0]; i++) {
+ err = v4l2_async_notifier_add_subdev(
+ &vpif_obj.notifier, vpif_obj.config->asd[i]);
+ if (err)
+ goto probe_cleanup;
+ }
+
vpif_obj.notifier.ops = &vpif_async_ops;
err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
&vpif_obj.notifier);
if (err) {
vpif_err("Error registering async notifier\n");
err = -EINVAL;
- goto probe_subdev_out;
+ goto probe_cleanup;
}
}
return 0;
+probe_cleanup:
+ v4l2_async_notifier_cleanup(&vpif_obj.notifier);
probe_subdev_out:
kfree(vpif_obj.sd);
vpif_unregister:
@@ -1354,6 +1364,11 @@ static int vpif_remove(struct platform_device *device)
struct channel_obj *ch;
int i;
+ if (vpif_obj.config->asd_sizes) {
+ v4l2_async_notifier_unregister(&vpif_obj.notifier);
+ v4l2_async_notifier_cleanup(&vpif_obj.notifier);
+ }
+
v4l2_device_unregister(&vpif_obj.v4l2_dev);
kfree(vpif_obj.sd);
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
index 17854a379243..838c5c53de37 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.c
+++ b/drivers/media/platform/exynos-gsc/gsc-core.c
@@ -339,7 +339,7 @@ int gsc_enum_fmt_mplane(struct v4l2_fmtdesc *f)
if (!fmt)
return -EINVAL;
- strlcpy(f->description, fmt->name, sizeof(f->description));
+ strscpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->pixelformat;
return 0;
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index c9d2f6c5311a..cc5d690818e1 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -294,8 +294,8 @@ static int gsc_m2m_querycap(struct file *file, void *fh,
struct gsc_ctx *ctx = fh_to_ctx(fh);
struct gsc_dev *gsc = ctx->gsc_dev;
- strlcpy(cap->driver, GSC_MODULE_NAME, sizeof(cap->driver));
- strlcpy(cap->card, GSC_MODULE_NAME " gscaler", sizeof(cap->card));
+ strscpy(cap->driver, GSC_MODULE_NAME, sizeof(cap->driver));
+ strscpy(cap->card, GSC_MODULE_NAME " gscaler", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(&gsc->pdev->dev));
cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
diff --git a/drivers/media/platform/exynos4-is/common.c b/drivers/media/platform/exynos4-is/common.c
index b90f5bb15517..76f557548dfc 100644
--- a/drivers/media/platform/exynos4-is/common.c
+++ b/drivers/media/platform/exynos4-is/common.c
@@ -40,8 +40,8 @@ EXPORT_SYMBOL(fimc_find_remote_sensor);
void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap,
unsigned int caps)
{
- strlcpy(cap->driver, dev->driver->name, sizeof(cap->driver));
- strlcpy(cap->card, dev->driver->name, sizeof(cap->card));
+ strscpy(cap->driver, dev->driver->name, sizeof(cap->driver));
+ strscpy(cap->card, dev->driver->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:%s", dev_name(dev));
cap->device_caps = caps;
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index a3cdac188190..f56220e549bb 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -1087,7 +1087,7 @@ static int fimc_cap_enum_input(struct file *file, void *priv,
fimc_md_graph_unlock(ve);
if (sd)
- strlcpy(i->name, sd->name, sizeof(i->name));
+ strscpy(i->name, sd->name, sizeof(i->name));
return 0;
}
diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
index 70dd4852b2b9..be937caf7645 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c
+++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
@@ -57,7 +57,7 @@ static int fimc_is_i2c_probe(struct platform_device *pdev)
i2c_adap = &isp_i2c->adapter;
i2c_adap->dev.of_node = node;
i2c_adap->dev.parent = &pdev->dev;
- strlcpy(i2c_adap->name, "exynos4x12-isp-i2c", sizeof(i2c_adap->name));
+ strscpy(i2c_adap->name, "exynos4x12-isp-i2c", sizeof(i2c_adap->name));
i2c_adap->owner = THIS_MODULE;
i2c_adap->algo = &fimc_is_i2c_algorithm;
i2c_adap->class = I2C_CLASS_SPD;
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c
index 5ddb2321e9e4..f5fc54de19da 100644
--- a/drivers/media/platform/exynos4-is/fimc-is.c
+++ b/drivers/media/platform/exynos4-is/fimc-is.c
@@ -656,7 +656,7 @@ static int fimc_is_hw_open_sensor(struct fimc_is *is,
int fimc_is_hw_initialize(struct fimc_is *is)
{
- const int config_ids[] = {
+ static const int config_ids[] = {
IS_SC_PREVIEW_STILL, IS_SC_PREVIEW_VIDEO,
IS_SC_CAPTURE_STILL, IS_SC_CAPTURE_VIDEO
};
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
index a920164f53f1..de6bd28f7e31 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
@@ -365,7 +365,7 @@ static int isp_video_enum_fmt_mplane(struct file *file, void *priv,
if (WARN_ON(fmt == NULL))
return -EINVAL;
- strlcpy(f->description, fmt->name, sizeof(f->description));
+ strscpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
return 0;
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index 70d5f5586a5d..96f0a8a0dcae 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -654,8 +654,8 @@ static int fimc_lite_querycap(struct file *file, void *priv,
{
struct fimc_lite *fimc = video_drvdata(file);
- strlcpy(cap->driver, FIMC_LITE_DRV_NAME, sizeof(cap->driver));
- strlcpy(cap->card, FIMC_LITE_DRV_NAME, sizeof(cap->card));
+ strscpy(cap->driver, FIMC_LITE_DRV_NAME, sizeof(cap->driver));
+ strscpy(cap->card, FIMC_LITE_DRV_NAME, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(&fimc->pdev->dev));
@@ -673,7 +673,7 @@ static int fimc_lite_enum_fmt_mplane(struct file *file, void *priv,
return -EINVAL;
fmt = &fimc_lite_formats[f->index];
- strlcpy(f->description, fmt->name, sizeof(f->description));
+ strscpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
return 0;
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index deb499f76412..870501b0f351 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -390,7 +390,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
{
struct fimc_source_info *pd = &fmd->sensor[index].pdata;
struct device_node *rem, *ep, *np;
- struct v4l2_fwnode_endpoint endpoint;
+ struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
int ret;
/* Assume here a port node can have only one endpoint node. */
@@ -457,11 +457,16 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
fmd->sensor[index].asd.match.fwnode = of_fwnode_handle(rem);
- fmd->async_subdevs[index] = &fmd->sensor[index].asd;
+
+ ret = v4l2_async_notifier_add_subdev(&fmd->subdev_notifier,
+ &fmd->sensor[index].asd);
+ if (ret) {
+ of_node_put(rem);
+ return ret;
+ }
fmd->num_sensors++;
- of_node_put(rem);
return 0;
}
@@ -500,7 +505,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
ret = fimc_md_parse_port_node(fmd, port, index);
if (ret < 0) {
of_node_put(node);
- goto rpm_put;
+ goto cleanup;
}
index++;
}
@@ -514,12 +519,18 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
ret = fimc_md_parse_port_node(fmd, node, index);
if (ret < 0) {
of_node_put(node);
- break;
+ goto cleanup;
}
index++;
}
+
rpm_put:
pm_runtime_put(fmd->pmf);
+ return 0;
+
+cleanup:
+ v4l2_async_notifier_cleanup(&fmd->subdev_notifier);
+ pm_runtime_put(fmd->pmf);
return ret;
}
@@ -1204,9 +1215,9 @@ static ssize_t fimc_md_sysfs_show(struct device *dev,
struct fimc_md *fmd = dev_get_drvdata(dev);
if (fmd->user_subdev_api)
- return strlcpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE);
+ return strscpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE);
- return strlcpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
+ return strscpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
}
static ssize_t fimc_md_sysfs_store(struct device *dev,
@@ -1426,7 +1437,7 @@ static int fimc_md_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&fmd->pipelines);
fmd->pdev = pdev;
- strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
+ strscpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
sizeof(fmd->media_dev.model));
fmd->media_dev.ops = &fimc_md_ops;
fmd->media_dev.dev = dev;
@@ -1434,7 +1445,7 @@ static int fimc_md_probe(struct platform_device *pdev)
v4l2_dev = &fmd->v4l2_dev;
v4l2_dev->mdev = &fmd->media_dev;
v4l2_dev->notify = fimc_sensor_notify;
- strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
+ strscpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
fmd->use_isp = fimc_md_is_isp_available(dev->of_node);
fmd->user_subdev_api = true;
@@ -1460,6 +1471,8 @@ static int fimc_md_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, fmd);
+ v4l2_async_notifier_init(&fmd->subdev_notifier);
+
ret = fimc_md_register_platform_entities(fmd, dev->of_node);
if (ret)
goto err_clk;
@@ -1470,7 +1483,7 @@ static int fimc_md_probe(struct platform_device *pdev)
ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
if (ret)
- goto err_m_ent;
+ goto err_cleanup;
/*
* FIMC platform devices need to be registered before the sclk_cam
* clocks provider, as one of these devices needs to be activated
@@ -1483,8 +1496,6 @@ static int fimc_md_probe(struct platform_device *pdev)
}
if (fmd->num_sensors > 0) {
- fmd->subdev_notifier.subdevs = fmd->async_subdevs;
- fmd->subdev_notifier.num_subdevs = fmd->num_sensors;
fmd->subdev_notifier.ops = &subdev_notifier_ops;
fmd->num_sensors = 0;
@@ -1500,10 +1511,12 @@ err_clk_p:
fimc_md_unregister_clk_provider(fmd);
err_attr:
device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
-err_clk:
- fimc_md_put_clocks(fmd);
+err_cleanup:
+ v4l2_async_notifier_cleanup(&fmd->subdev_notifier);
err_m_ent:
fimc_md_unregister_entities(fmd);
+err_clk:
+ fimc_md_put_clocks(fmd);
err_md:
media_device_cleanup(&fmd->media_dev);
v4l2_device_unregister(&fmd->v4l2_dev);
@@ -1519,6 +1532,7 @@ static int fimc_md_remove(struct platform_device *pdev)
fimc_md_unregister_clk_provider(fmd);
v4l2_async_notifier_unregister(&fmd->subdev_notifier);
+ v4l2_async_notifier_cleanup(&fmd->subdev_notifier);
v4l2_device_unregister(&fmd->v4l2_dev);
device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
index 957787a2f480..9f527670395a 100644
--- a/drivers/media/platform/exynos4-is/media-dev.h
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -149,7 +149,6 @@ struct fimc_md {
} clk_provider;
struct v4l2_async_notifier subdev_notifier;
- struct v4l2_async_subdev *async_subdevs[FIMC_MAX_SENSORS];
bool user_subdev_api;
spinlock_t slock;
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
index b4e28a299e26..35cb0162085b 100644
--- a/drivers/media/platform/exynos4-is/mipi-csis.c
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -718,7 +718,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev,
struct csis_state *state)
{
struct device_node *node = pdev->dev.of_node;
- struct v4l2_fwnode_endpoint endpoint;
+ struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
int ret;
if (of_property_read_u32(node, "clock-frequency",
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 0273302aa741..ca6d0317ab42 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -565,9 +565,9 @@ static const struct videobuf_queue_ops viu_video_qops = {
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strcpy(cap->driver, "viu");
- strcpy(cap->card, "viu");
- strcpy(cap->bus_info, "platform:viu");
+ strscpy(cap->driver, "viu", sizeof(cap->driver));
+ strscpy(cap->card, "viu", sizeof(cap->card));
+ strscpy(cap->bus_info, "platform:viu", sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING |
V4L2_CAP_VIDEO_OVERLAY |
@@ -941,7 +941,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
inp->type = V4L2_INPUT_TYPE_CAMERA;
inp->std = fh->dev->vdev->tvnorms;
- strcpy(inp->name, "Camera");
+ strscpy(inp->name, "Camera", sizeof(inp->name));
return 0;
}
diff --git a/drivers/media/platform/imx-pxp.c b/drivers/media/platform/imx-pxp.c
new file mode 100644
index 000000000000..b76cd0e8313c
--- /dev/null
+++ b/drivers/media/platform/imx-pxp.c
@@ -0,0 +1,1754 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * i.MX Pixel Pipeline (PXP) mem-to-mem scaler/CSC/rotator driver
+ *
+ * Copyright (c) 2018 Pengutronix, Philipp Zabel
+ *
+ * based on vim2m
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <linux/platform_device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "imx-pxp.h"
+
+static unsigned int debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+#define MIN_W 8
+#define MIN_H 8
+#define MAX_W 4096
+#define MAX_H 4096
+#define ALIGN_W 3 /* 8x8 pixel blocks */
+#define ALIGN_H 3
+
+/* Flags that indicate a format can be used for capture/output */
+#define MEM2MEM_CAPTURE (1 << 0)
+#define MEM2MEM_OUTPUT (1 << 1)
+
+#define MEM2MEM_NAME "pxp"
+
+/* Flags that indicate processing mode */
+#define MEM2MEM_HFLIP (1 << 0)
+#define MEM2MEM_VFLIP (1 << 1)
+
+#define dprintk(dev, fmt, arg...) \
+ v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
+
+struct pxp_fmt {
+ u32 fourcc;
+ int depth;
+ /* Types the format can be used for */
+ u32 types;
+};
+
+static struct pxp_fmt formats[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_XBGR32,
+ .depth = 32,
+ /* Both capture and output format */
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_ABGR32,
+ .depth = 32,
+ /* Capture-only format */
+ .types = MEM2MEM_CAPTURE,
+ }, {
+ .fourcc = V4L2_PIX_FMT_BGR24,
+ .depth = 24,
+ .types = MEM2MEM_CAPTURE,
+ }, {
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .depth = 16,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_RGB555,
+ .depth = 16,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_RGB444,
+ .depth = 16,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_YUV32,
+ .depth = 32,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .depth = 16,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ /* Output-only format */
+ .types = MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_VYUY,
+ .depth = 16,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_YVYU,
+ .depth = 16,
+ .types = MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_GREY,
+ .depth = 8,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_Y4,
+ .depth = 4,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_NV16,
+ .depth = 16,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .depth = 12,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_NV21,
+ .depth = 12,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_NV61,
+ .depth = 16,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_YUV422P,
+ .depth = 16,
+ .types = MEM2MEM_OUTPUT,
+ }, {
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .depth = 12,
+ .types = MEM2MEM_OUTPUT,
+ },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+/* Per-queue, driver-specific private data */
+struct pxp_q_data {
+ unsigned int width;
+ unsigned int height;
+ unsigned int bytesperline;
+ unsigned int sizeimage;
+ unsigned int sequence;
+ struct pxp_fmt *fmt;
+ enum v4l2_ycbcr_encoding ycbcr_enc;
+ enum v4l2_quantization quant;
+};
+
+enum {
+ V4L2_M2M_SRC = 0,
+ V4L2_M2M_DST = 1,
+};
+
+static struct pxp_fmt *find_format(struct v4l2_format *f)
+{
+ struct pxp_fmt *fmt;
+ unsigned int k;
+
+ for (k = 0; k < NUM_FORMATS; k++) {
+ fmt = &formats[k];
+ if (fmt->fourcc == f->fmt.pix.pixelformat)
+ break;
+ }
+
+ if (k == NUM_FORMATS)
+ return NULL;
+
+ return &formats[k];
+}
+
+struct pxp_dev {
+ struct v4l2_device v4l2_dev;
+ struct video_device vfd;
+
+ struct clk *clk;
+ void __iomem *mmio;
+
+ atomic_t num_inst;
+ struct mutex dev_mutex;
+ spinlock_t irqlock;
+
+ struct v4l2_m2m_dev *m2m_dev;
+};
+
+struct pxp_ctx {
+ struct v4l2_fh fh;
+ struct pxp_dev *dev;
+
+ struct v4l2_ctrl_handler hdl;
+
+ /* Abort requested by m2m */
+ int aborting;
+
+ /* Processing mode */
+ int mode;
+ u8 alpha_component;
+
+ enum v4l2_colorspace colorspace;
+ enum v4l2_xfer_func xfer_func;
+
+ /* Source and destination queue data */
+ struct pxp_q_data q_data[2];
+};
+
+static inline struct pxp_ctx *file2ctx(struct file *file)
+{
+ return container_of(file->private_data, struct pxp_ctx, fh);
+}
+
+static struct pxp_q_data *get_q_data(struct pxp_ctx *ctx,
+ enum v4l2_buf_type type)
+{
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return &ctx->q_data[V4L2_M2M_SRC];
+ else
+ return &ctx->q_data[V4L2_M2M_DST];
+}
+
+static u32 pxp_v4l2_pix_fmt_to_ps_format(u32 v4l2_pix_fmt)
+{
+ switch (v4l2_pix_fmt) {
+ case V4L2_PIX_FMT_XBGR32: return BV_PXP_PS_CTRL_FORMAT__RGB888;
+ case V4L2_PIX_FMT_RGB555: return BV_PXP_PS_CTRL_FORMAT__RGB555;
+ case V4L2_PIX_FMT_RGB444: return BV_PXP_PS_CTRL_FORMAT__RGB444;
+ case V4L2_PIX_FMT_RGB565: return BV_PXP_PS_CTRL_FORMAT__RGB565;
+ case V4L2_PIX_FMT_YUV32: return BV_PXP_PS_CTRL_FORMAT__YUV1P444;
+ case V4L2_PIX_FMT_UYVY: return BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+ case V4L2_PIX_FMT_YUYV: return BM_PXP_PS_CTRL_WB_SWAP |
+ BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+ case V4L2_PIX_FMT_VYUY: return BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+ case V4L2_PIX_FMT_YVYU: return BM_PXP_PS_CTRL_WB_SWAP |
+ BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+ case V4L2_PIX_FMT_GREY: return BV_PXP_PS_CTRL_FORMAT__Y8;
+ default:
+ case V4L2_PIX_FMT_Y4: return BV_PXP_PS_CTRL_FORMAT__Y4;
+ case V4L2_PIX_FMT_NV16: return BV_PXP_PS_CTRL_FORMAT__YUV2P422;
+ case V4L2_PIX_FMT_NV12: return BV_PXP_PS_CTRL_FORMAT__YUV2P420;
+ case V4L2_PIX_FMT_NV21: return BV_PXP_PS_CTRL_FORMAT__YVU2P420;
+ case V4L2_PIX_FMT_NV61: return BV_PXP_PS_CTRL_FORMAT__YVU2P422;
+ case V4L2_PIX_FMT_YUV422P: return BV_PXP_PS_CTRL_FORMAT__YUV422;
+ case V4L2_PIX_FMT_YUV420: return BV_PXP_PS_CTRL_FORMAT__YUV420;
+ }
+}
+
+static u32 pxp_v4l2_pix_fmt_to_out_format(u32 v4l2_pix_fmt)
+{
+ switch (v4l2_pix_fmt) {
+ case V4L2_PIX_FMT_XBGR32: return BV_PXP_OUT_CTRL_FORMAT__RGB888;
+ case V4L2_PIX_FMT_ABGR32: return BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
+ case V4L2_PIX_FMT_BGR24: return BV_PXP_OUT_CTRL_FORMAT__RGB888P;
+ /* Missing V4L2 pixel formats for ARGB1555 and ARGB4444 */
+ case V4L2_PIX_FMT_RGB555: return BV_PXP_OUT_CTRL_FORMAT__RGB555;
+ case V4L2_PIX_FMT_RGB444: return BV_PXP_OUT_CTRL_FORMAT__RGB444;
+ case V4L2_PIX_FMT_RGB565: return BV_PXP_OUT_CTRL_FORMAT__RGB565;
+ case V4L2_PIX_FMT_YUV32: return BV_PXP_OUT_CTRL_FORMAT__YUV1P444;
+ case V4L2_PIX_FMT_UYVY: return BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
+ case V4L2_PIX_FMT_VYUY: return BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
+ case V4L2_PIX_FMT_GREY: return BV_PXP_OUT_CTRL_FORMAT__Y8;
+ default:
+ case V4L2_PIX_FMT_Y4: return BV_PXP_OUT_CTRL_FORMAT__Y4;
+ case V4L2_PIX_FMT_NV16: return BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
+ case V4L2_PIX_FMT_NV12: return BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
+ case V4L2_PIX_FMT_NV61: return BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
+ case V4L2_PIX_FMT_NV21: return BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
+ }
+}
+
+static bool pxp_v4l2_pix_fmt_is_yuv(u32 v4l2_pix_fmt)
+{
+ switch (v4l2_pix_fmt) {
+ case V4L2_PIX_FMT_YUV32:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_GREY:
+ case V4L2_PIX_FMT_Y4:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void pxp_setup_csc(struct pxp_ctx *ctx)
+{
+ struct pxp_dev *dev = ctx->dev;
+ enum v4l2_ycbcr_encoding ycbcr_enc;
+ enum v4l2_quantization quantization;
+
+ if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) &&
+ !pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) {
+ /*
+ * CSC1 YUV/YCbCr to RGB conversion is implemented as follows:
+ *
+ * |R| |C0 0 C1| |Y + Yoffset |
+ * |G| = |C0 C3 C2| * |Cb + UVoffset|
+ * |B| |C0 C4 0 | |Cr + UVoffset|
+ *
+ * Results are clamped to 0..255.
+ *
+ * BT.601 limited range:
+ *
+ * |R| |1.1644 0.0000 1.5960| |Y - 16 |
+ * |G| = |1.1644 -0.3917 -0.8129| * |Cb - 128|
+ * |B| |1.1644 2.0172 0.0000| |Cr - 128|
+ */
+ static const u32 csc1_coef_bt601_lim[3] = {
+ BM_PXP_CSC1_COEF0_YCBCR_MODE |
+ BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */
+ BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+ BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
+ BF_PXP_CSC1_COEF1_C1(0x198) | /* 1.5938 (-0.23 %) */
+ BF_PXP_CSC1_COEF1_C4(0x204), /* 2.0156 (-0.16 %) */
+ BF_PXP_CSC1_COEF2_C2(0x730) | /* -0.8125 (+0.04 %) */
+ BF_PXP_CSC1_COEF2_C3(0x79c), /* -0.3906 (+0.11 %) */
+ };
+ /*
+ * BT.601 full range:
+ *
+ * |R| |1.0000 0.0000 1.4020| |Y + 0 |
+ * |G| = |1.0000 -0.3441 -0.7141| * |Cb - 128|
+ * |B| |1.0000 1.7720 0.0000| |Cr - 128|
+ */
+ static const u32 csc1_coef_bt601_full[3] = {
+ BM_PXP_CSC1_COEF0_YCBCR_MODE |
+ BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */
+ BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+ BF_PXP_CSC1_COEF0_Y_OFFSET(0),
+ BF_PXP_CSC1_COEF1_C1(0x166) | /* 1.3984 (-0.36 %) */
+ BF_PXP_CSC1_COEF1_C4(0x1c5), /* 1.7695 (-0.25 %) */
+ BF_PXP_CSC1_COEF2_C2(0x74a) | /* -0.7109 (+0.32 %) */
+ BF_PXP_CSC1_COEF2_C3(0x7a8), /* -0.3438 (+0.04 %) */
+ };
+ /*
+ * Rec.709 limited range:
+ *
+ * |R| |1.1644 0.0000 1.7927| |Y - 16 |
+ * |G| = |1.1644 -0.2132 -0.5329| * |Cb - 128|
+ * |B| |1.1644 2.1124 0.0000| |Cr - 128|
+ */
+ static const u32 csc1_coef_rec709_lim[3] = {
+ BM_PXP_CSC1_COEF0_YCBCR_MODE |
+ BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */
+ BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+ BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
+ BF_PXP_CSC1_COEF1_C1(0x1ca) | /* 1.7891 (-0.37 %) */
+ BF_PXP_CSC1_COEF1_C4(0x21c), /* 2.1094 (-0.30 %) */
+ BF_PXP_CSC1_COEF2_C2(0x778) | /* -0.5312 (+0.16 %) */
+ BF_PXP_CSC1_COEF2_C3(0x7ca), /* -0.2109 (+0.23 %) */
+ };
+ /*
+ * Rec.709 full range:
+ *
+ * |R| |1.0000 0.0000 1.5748| |Y + 0 |
+ * |G| = |1.0000 -0.1873 -0.4681| * |Cb - 128|
+ * |B| |1.0000 1.8556 0.0000| |Cr - 128|
+ */
+ static const u32 csc1_coef_rec709_full[3] = {
+ BM_PXP_CSC1_COEF0_YCBCR_MODE |
+ BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */
+ BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+ BF_PXP_CSC1_COEF0_Y_OFFSET(0),
+ BF_PXP_CSC1_COEF1_C1(0x193) | /* 1.5742 (-0.06 %) */
+ BF_PXP_CSC1_COEF1_C4(0x1db), /* 1.8555 (-0.01 %) */
+ BF_PXP_CSC1_COEF2_C2(0x789) | /* -0.4648 (+0.33 %) */
+ BF_PXP_CSC1_COEF2_C3(0x7d1), /* -0.1836 (+0.37 %) */
+ };
+ /*
+ * BT.2020 limited range:
+ *
+ * |R| |1.1644 0.0000 1.6787| |Y - 16 |
+ * |G| = |1.1644 -0.1874 -0.6505| * |Cb - 128|
+ * |B| |1.1644 2.1418 0.0000| |Cr - 128|
+ */
+ static const u32 csc1_coef_bt2020_lim[3] = {
+ BM_PXP_CSC1_COEF0_YCBCR_MODE |
+ BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */
+ BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+ BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
+ BF_PXP_CSC1_COEF1_C1(0x1ad) | /* 1.6758 (-0.29 %) */
+ BF_PXP_CSC1_COEF1_C4(0x224), /* 2.1406 (-0.11 %) */
+ BF_PXP_CSC1_COEF2_C2(0x75a) | /* -0.6484 (+0.20 %) */
+ BF_PXP_CSC1_COEF2_C3(0x7d1), /* -0.1836 (+0.38 %) */
+ };
+ /*
+ * BT.2020 full range:
+ *
+ * |R| |1.0000 0.0000 1.4746| |Y + 0 |
+ * |G| = |1.0000 -0.1646 -0.5714| * |Cb - 128|
+ * |B| |1.0000 1.8814 0.0000| |Cr - 128|
+ */
+ static const u32 csc1_coef_bt2020_full[3] = {
+ BM_PXP_CSC1_COEF0_YCBCR_MODE |
+ BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */
+ BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+ BF_PXP_CSC1_COEF0_Y_OFFSET(0),
+ BF_PXP_CSC1_COEF1_C1(0x179) | /* 1.4727 (-0.19 %) */
+ BF_PXP_CSC1_COEF1_C4(0x1e1), /* 1.8789 (-0.25 %) */
+ BF_PXP_CSC1_COEF2_C2(0x76e) | /* -0.5703 (+0.11 %) */
+ BF_PXP_CSC1_COEF2_C3(0x7d6), /* -0.1641 (+0.05 %) */
+ };
+ /*
+ * SMPTE 240m limited range:
+ *
+ * |R| |1.1644 0.0000 1.7937| |Y - 16 |
+ * |G| = |1.1644 -0.2565 -0.5427| * |Cb - 128|
+ * |B| |1.1644 2.0798 0.0000| |Cr - 128|
+ */
+ static const u32 csc1_coef_smpte240m_lim[3] = {
+ BM_PXP_CSC1_COEF0_YCBCR_MODE |
+ BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */
+ BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+ BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
+ BF_PXP_CSC1_COEF1_C1(0x1cb) | /* 1.7930 (-0.07 %) */
+ BF_PXP_CSC1_COEF1_C4(0x214), /* 2.0781 (-0.17 %) */
+ BF_PXP_CSC1_COEF2_C2(0x776) | /* -0.5391 (+0.36 %) */
+ BF_PXP_CSC1_COEF2_C3(0x7bf), /* -0.2539 (+0.26 %) */
+ };
+ /*
+ * SMPTE 240m full range:
+ *
+ * |R| |1.0000 0.0000 1.5756| |Y + 0 |
+ * |G| = |1.0000 -0.2253 -0.4767| * |Cb - 128|
+ * |B| |1.0000 1.8270 0.0000| |Cr - 128|
+ */
+ static const u32 csc1_coef_smpte240m_full[3] = {
+ BM_PXP_CSC1_COEF0_YCBCR_MODE |
+ BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */
+ BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+ BF_PXP_CSC1_COEF0_Y_OFFSET(0),
+ BF_PXP_CSC1_COEF1_C1(0x193) | /* 1.5742 (-0.14 %) */
+ BF_PXP_CSC1_COEF1_C4(0x1d3), /* 1.8242 (-0.28 %) */
+ BF_PXP_CSC1_COEF2_C2(0x786) | /* -0.4766 (+0.01 %) */
+ BF_PXP_CSC1_COEF2_C3(0x7c7), /* -0.2227 (+0.26 %) */
+ };
+ const u32 *csc1_coef;
+
+ ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc;
+ quantization = ctx->q_data[V4L2_M2M_SRC].quant;
+
+ if (ycbcr_enc == V4L2_YCBCR_ENC_601) {
+ if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+ csc1_coef = csc1_coef_bt601_full;
+ else
+ csc1_coef = csc1_coef_bt601_lim;
+ } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) {
+ if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+ csc1_coef = csc1_coef_rec709_full;
+ else
+ csc1_coef = csc1_coef_rec709_lim;
+ } else if (ycbcr_enc == V4L2_YCBCR_ENC_BT2020) {
+ if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+ csc1_coef = csc1_coef_bt2020_full;
+ else
+ csc1_coef = csc1_coef_bt2020_lim;
+ } else {
+ if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+ csc1_coef = csc1_coef_smpte240m_full;
+ else
+ csc1_coef = csc1_coef_smpte240m_lim;
+ }
+
+ writel(csc1_coef[0], dev->mmio + HW_PXP_CSC1_COEF0);
+ writel(csc1_coef[1], dev->mmio + HW_PXP_CSC1_COEF1);
+ writel(csc1_coef[2], dev->mmio + HW_PXP_CSC1_COEF2);
+ } else {
+ writel(BM_PXP_CSC1_COEF0_BYPASS, dev->mmio + HW_PXP_CSC1_COEF0);
+ }
+
+ if (!pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) &&
+ pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) {
+ /*
+ * CSC2 RGB to YUV/YCbCr conversion is implemented as follows:
+ *
+ * |Y | |A1 A2 A3| |R| |D1|
+ * |Cb| = |B1 B2 B3| * |G| + |D2|
+ * |Cr| |C1 C2 C3| |B| |D3|
+ *
+ * Results are clamped to 0..255.
+ *
+ * BT.601 limited range:
+ *
+ * |Y | | 0.2568 0.5041 0.0979| |R| |16 |
+ * |Cb| = |-0.1482 -0.2910 0.4392| * |G| + |128|
+ * |Cr| | 0.4392 0.4392 -0.3678| |B| |128|
+ */
+ static const u32 csc2_coef_bt601_lim[6] = {
+ BF_PXP_CSC2_COEF0_A2(0x081) | /* 0.5039 (-0.02 %) */
+ BF_PXP_CSC2_COEF0_A1(0x041), /* 0.2539 (-0.29 %) */
+ BF_PXP_CSC2_COEF1_B1(0x7db) | /* -0.1445 (+0.37 %) */
+ BF_PXP_CSC2_COEF1_A3(0x019), /* 0.0977 (-0.02 %) */
+ BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */
+ BF_PXP_CSC2_COEF2_B2(0x7b6), /* -0.2891 (+0.20 %) */
+ BF_PXP_CSC2_COEF3_C2(0x7a2) | /* -0.3672 (+0.06 %) */
+ BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */
+ BF_PXP_CSC2_COEF4_D1(16) |
+ BF_PXP_CSC2_COEF4_C3(0x7ee), /* -0.0703 (+0.11 %) */
+ BF_PXP_CSC2_COEF5_D3(128) |
+ BF_PXP_CSC2_COEF5_D2(128),
+ };
+ /*
+ * BT.601 full range:
+ *
+ * |Y | | 0.2990 0.5870 0.1140| |R| |0 |
+ * |Cb| = |-0.1687 -0.3313 0.5000| * |G| + |128|
+ * |Cr| | 0.5000 0.5000 -0.4187| |B| |128|
+ */
+ static const u32 csc2_coef_bt601_full[6] = {
+ BF_PXP_CSC2_COEF0_A2(0x096) | /* 0.5859 (-0.11 %) */
+ BF_PXP_CSC2_COEF0_A1(0x04c), /* 0.2969 (-0.21 %) */
+ BF_PXP_CSC2_COEF1_B1(0x7d5) | /* -0.1680 (+0.07 %) */
+ BF_PXP_CSC2_COEF1_A3(0x01d), /* 0.1133 (-0.07 %) */
+ BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */
+ BF_PXP_CSC2_COEF2_B2(0x7ac), /* -0.3281 (+0.32 %) */
+ BF_PXP_CSC2_COEF3_C2(0x795) | /* -0.4180 (+0.07 %) */
+ BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */
+ BF_PXP_CSC2_COEF4_D1(0) |
+ BF_PXP_CSC2_COEF4_C3(0x7ec), /* -0.0781 (+0.32 %) */
+ BF_PXP_CSC2_COEF5_D3(128) |
+ BF_PXP_CSC2_COEF5_D2(128),
+ };
+ /*
+ * Rec.709 limited range:
+ *
+ * |Y | | 0.1826 0.6142 0.0620| |R| |16 |
+ * |Cb| = |-0.1007 -0.3385 0.4392| * |G| + |128|
+ * |Cr| | 0.4392 0.4392 -0.3990| |B| |128|
+ */
+ static const u32 csc2_coef_rec709_lim[6] = {
+ BF_PXP_CSC2_COEF0_A2(0x09d) | /* 0.6133 (-0.09 %) */
+ BF_PXP_CSC2_COEF0_A1(0x02e), /* 0.1797 (-0.29 %) */
+ BF_PXP_CSC2_COEF1_B1(0x7e7) | /* -0.0977 (+0.30 %) */
+ BF_PXP_CSC2_COEF1_A3(0x00f), /* 0.0586 (-0.34 %) */
+ BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */
+ BF_PXP_CSC2_COEF2_B2(0x7aa), /* -0.3359 (+0.26 %) */
+ BF_PXP_CSC2_COEF3_C2(0x79a) | /* -0.3984 (+0.05 %) */
+ BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */
+ BF_PXP_CSC2_COEF4_D1(16) |
+ BF_PXP_CSC2_COEF4_C3(0x7f6), /* -0.0391 (+0.12 %) */
+ BF_PXP_CSC2_COEF5_D3(128) |
+ BF_PXP_CSC2_COEF5_D2(128),
+ };
+ /*
+ * Rec.709 full range:
+ *
+ * |Y | | 0.2126 0.7152 0.0722| |R| |0 |
+ * |Cb| = |-0.1146 -0.3854 0.5000| * |G| + |128|
+ * |Cr| | 0.5000 0.5000 -0.4542| |B| |128|
+ */
+ static const u32 csc2_coef_rec709_full[6] = {
+ BF_PXP_CSC2_COEF0_A2(0x0b7) | /* 0.7148 (-0.04 %) */
+ BF_PXP_CSC2_COEF0_A1(0x036), /* 0.2109 (-0.17 %) */
+ BF_PXP_CSC2_COEF1_B1(0x7e3) | /* -0.1133 (+0.13 %) */
+ BF_PXP_CSC2_COEF1_A3(0x012), /* 0.0703 (-0.19 %) */
+ BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */
+ BF_PXP_CSC2_COEF2_B2(0x79e), /* -0.3828 (+0.26 %) */
+ BF_PXP_CSC2_COEF3_C2(0x78c) | /* -0.4531 (+0.11 %) */
+ BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */
+ BF_PXP_CSC2_COEF4_D1(0) |
+ BF_PXP_CSC2_COEF4_C3(0x7f5), /* -0.0430 (+0.28 %) */
+ BF_PXP_CSC2_COEF5_D3(128) |
+ BF_PXP_CSC2_COEF5_D2(128),
+ };
+ /*
+ * BT.2020 limited range:
+ *
+ * |Y | | 0.2256 0.5823 0.0509| |R| |16 |
+ * |Cb| = |-0.1226 -0.3166 0.4392| * |G| + |128|
+ * |Cr| | 0.4392 0.4392 -0.4039| |B| |128|
+ */
+ static const u32 csc2_coef_bt2020_lim[6] = {
+ BF_PXP_CSC2_COEF0_A2(0x095) | /* 0.5820 (-0.03 %) */
+ BF_PXP_CSC2_COEF0_A1(0x039), /* 0.2227 (-0.30 %) */
+ BF_PXP_CSC2_COEF1_B1(0x7e1) | /* -0.1211 (+0.15 %) */
+ BF_PXP_CSC2_COEF1_A3(0x00d), /* 0.0508 (-0.01 %) */
+ BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */
+ BF_PXP_CSC2_COEF2_B2(0x7af), /* -0.3164 (+0.02 %) */
+ BF_PXP_CSC2_COEF3_C2(0x799) | /* -0.4023 (+0.16 %) */
+ BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */
+ BF_PXP_CSC2_COEF4_D1(16) |
+ BF_PXP_CSC2_COEF4_C3(0x7f7), /* -0.0352 (+0.02 %) */
+ BF_PXP_CSC2_COEF5_D3(128) |
+ BF_PXP_CSC2_COEF5_D2(128),
+ };
+ /*
+ * BT.2020 full range:
+ *
+ * |Y | | 0.2627 0.6780 0.0593| |R| |0 |
+ * |Cb| = |-0.1396 -0.3604 0.5000| * |G| + |128|
+ * |Cr| | 0.5000 0.5000 -0.4598| |B| |128|
+ */
+ static const u32 csc2_coef_bt2020_full[6] = {
+ BF_PXP_CSC2_COEF0_A2(0x0ad) | /* 0.6758 (-0.22 %) */
+ BF_PXP_CSC2_COEF0_A1(0x043), /* 0.2617 (-0.10 %) */
+ BF_PXP_CSC2_COEF1_B1(0x7dd) | /* -0.1367 (+0.29 %) */
+ BF_PXP_CSC2_COEF1_A3(0x00f), /* 0.0586 (-0.07 %) */
+ BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */
+ BF_PXP_CSC2_COEF2_B2(0x7a4), /* -0.3594 (+0.10 %) */
+ BF_PXP_CSC2_COEF3_C2(0x78b) | /* -0.4570 (+0.28 %) */
+ BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */
+ BF_PXP_CSC2_COEF4_D1(0) |
+ BF_PXP_CSC2_COEF4_C3(0x7f6), /* -0.0391 (+0.11 %) */
+ BF_PXP_CSC2_COEF5_D3(128) |
+ BF_PXP_CSC2_COEF5_D2(128),
+ };
+ /*
+ * SMPTE 240m limited range:
+ *
+ * |Y | | 0.1821 0.6020 0.0747| |R| |16 |
+ * |Cb| = |-0.1019 -0.3373 0.4392| * |G| + |128|
+ * |Cr| | 0.4392 0.4392 -0.3909| |B| |128|
+ */
+ static const u32 csc2_coef_smpte240m_lim[6] = {
+ BF_PXP_CSC2_COEF0_A2(0x09a) | /* 0.6016 (-0.05 %) */
+ BF_PXP_CSC2_COEF0_A1(0x02e), /* 0.1797 (-0.24 %) */
+ BF_PXP_CSC2_COEF1_B1(0x7e6) | /* -0.1016 (+0.03 %) */
+ BF_PXP_CSC2_COEF1_A3(0x013), /* 0.0742 (-0.05 %) */
+ BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */
+ BF_PXP_CSC2_COEF2_B2(0x7aa), /* -0.3359 (+0.14 %) */
+ BF_PXP_CSC2_COEF3_C2(0x79c) | /* -0.3906 (+0.03 %) */
+ BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */
+ BF_PXP_CSC2_COEF4_D1(16) |
+ BF_PXP_CSC2_COEF4_C3(0x7f4), /* -0.0469 (+0.14 %) */
+ BF_PXP_CSC2_COEF5_D3(128) |
+ BF_PXP_CSC2_COEF5_D2(128),
+ };
+ /*
+ * SMPTE 240m full range:
+ *
+ * |Y | | 0.2120 0.7010 0.0870| |R| |0 |
+ * |Cb| = |-0.1160 -0.3840 0.5000| * |G| + |128|
+ * |Cr| | 0.5000 0.5000 -0.4450| |B| |128|
+ */
+ static const u32 csc2_coef_smpte240m_full[6] = {
+ BF_PXP_CSC2_COEF0_A2(0x0b3) | /* 0.6992 (-0.18 %) */
+ BF_PXP_CSC2_COEF0_A1(0x036), /* 0.2109 (-0.11 %) */
+ BF_PXP_CSC2_COEF1_B1(0x7e3) | /* -0.1133 (+0.27 %) */
+ BF_PXP_CSC2_COEF1_A3(0x016), /* 0.0859 (-0.11 %) */
+ BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */
+ BF_PXP_CSC2_COEF2_B2(0x79e), /* -0.3828 (+0.12 %) */
+ BF_PXP_CSC2_COEF3_C2(0x78f) | /* -0.4414 (+0.36 %) */
+ BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */
+ BF_PXP_CSC2_COEF4_D1(0) |
+ BF_PXP_CSC2_COEF4_C3(0x7f2), /* -0.0547 (+0.03 %) */
+ BF_PXP_CSC2_COEF5_D3(128) |
+ BF_PXP_CSC2_COEF5_D2(128),
+ };
+ const u32 *csc2_coef;
+ u32 csc2_ctrl;
+
+ ycbcr_enc = ctx->q_data[V4L2_M2M_DST].ycbcr_enc;
+ quantization = ctx->q_data[V4L2_M2M_DST].quant;
+
+ if (ycbcr_enc == V4L2_YCBCR_ENC_601) {
+ if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+ csc2_coef = csc2_coef_bt601_full;
+ else
+ csc2_coef = csc2_coef_bt601_lim;
+ } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) {
+ if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+ csc2_coef = csc2_coef_rec709_full;
+ else
+ csc2_coef = csc2_coef_rec709_lim;
+ } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) {
+ if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+ csc2_coef = csc2_coef_bt2020_full;
+ else
+ csc2_coef = csc2_coef_bt2020_lim;
+ } else {
+ if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+ csc2_coef = csc2_coef_smpte240m_full;
+ else
+ csc2_coef = csc2_coef_smpte240m_lim;
+ }
+ if (quantization == V4L2_QUANTIZATION_FULL_RANGE) {
+ csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV <<
+ BP_PXP_CSC2_CTRL_CSC_MODE;
+ } else {
+ csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr <<
+ BP_PXP_CSC2_CTRL_CSC_MODE;
+ }
+
+ writel(csc2_ctrl, dev->mmio + HW_PXP_CSC2_CTRL);
+ writel(csc2_coef[0], dev->mmio + HW_PXP_CSC2_COEF0);
+ writel(csc2_coef[1], dev->mmio + HW_PXP_CSC2_COEF1);
+ writel(csc2_coef[2], dev->mmio + HW_PXP_CSC2_COEF2);
+ writel(csc2_coef[3], dev->mmio + HW_PXP_CSC2_COEF3);
+ writel(csc2_coef[4], dev->mmio + HW_PXP_CSC2_COEF4);
+ writel(csc2_coef[5], dev->mmio + HW_PXP_CSC2_COEF5);
+ } else {
+ writel(BM_PXP_CSC2_CTRL_BYPASS, dev->mmio + HW_PXP_CSC2_CTRL);
+ }
+}
+
+static int pxp_start(struct pxp_ctx *ctx, struct vb2_v4l2_buffer *in_vb,
+ struct vb2_v4l2_buffer *out_vb)
+{
+ struct pxp_dev *dev = ctx->dev;
+ struct pxp_q_data *q_data;
+ u32 src_width, src_height, src_stride, src_fourcc;
+ u32 dst_width, dst_height, dst_stride, dst_fourcc;
+ dma_addr_t p_in, p_out;
+ u32 ctrl, out_ctrl, out_buf, out_buf2, out_pitch, out_lrc, out_ps_ulc;
+ u32 out_ps_lrc;
+ u32 ps_ctrl, ps_buf, ps_ubuf, ps_vbuf, ps_pitch, ps_scale, ps_offset;
+ u32 as_ulc, as_lrc;
+ u32 y_size;
+ u32 decx, decy, xscale, yscale;
+
+ q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+ src_width = ctx->q_data[V4L2_M2M_SRC].width;
+ dst_width = ctx->q_data[V4L2_M2M_DST].width;
+ src_height = ctx->q_data[V4L2_M2M_SRC].height;
+ dst_height = ctx->q_data[V4L2_M2M_DST].height;
+ src_stride = ctx->q_data[V4L2_M2M_SRC].bytesperline;
+ dst_stride = ctx->q_data[V4L2_M2M_DST].bytesperline;
+ src_fourcc = ctx->q_data[V4L2_M2M_SRC].fmt->fourcc;
+ dst_fourcc = ctx->q_data[V4L2_M2M_DST].fmt->fourcc;
+
+ p_in = vb2_dma_contig_plane_dma_addr(&in_vb->vb2_buf, 0);
+ p_out = vb2_dma_contig_plane_dma_addr(&out_vb->vb2_buf, 0);
+
+ if (!p_in || !p_out) {
+ v4l2_err(&dev->v4l2_dev,
+ "Acquiring DMA addresses of buffers failed\n");
+ return -EFAULT;
+ }
+
+ out_vb->sequence =
+ get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++;
+ in_vb->sequence = q_data->sequence++;
+ out_vb->vb2_buf.timestamp = in_vb->vb2_buf.timestamp;
+
+ if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE)
+ out_vb->timecode = in_vb->timecode;
+ out_vb->field = in_vb->field;
+ out_vb->flags = in_vb->flags &
+ (V4L2_BUF_FLAG_TIMECODE |
+ V4L2_BUF_FLAG_KEYFRAME |
+ V4L2_BUF_FLAG_PFRAME |
+ V4L2_BUF_FLAG_BFRAME |
+ V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
+
+ /* Rotation disabled, 8x8 block size */
+ ctrl = BF_PXP_CTRL_VFLIP0(!!(ctx->mode & MEM2MEM_VFLIP)) |
+ BF_PXP_CTRL_HFLIP0(!!(ctx->mode & MEM2MEM_HFLIP));
+ /* Always write alpha value as V4L2_CID_ALPHA_COMPONENT */
+ out_ctrl = BF_PXP_OUT_CTRL_ALPHA(ctx->alpha_component) |
+ BF_PXP_OUT_CTRL_ALPHA_OUTPUT(1) |
+ pxp_v4l2_pix_fmt_to_out_format(dst_fourcc);
+ out_buf = p_out;
+ switch (dst_fourcc) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ out_buf2 = out_buf + dst_stride * dst_height;
+ break;
+ default:
+ out_buf2 = 0;
+ }
+
+ out_pitch = BF_PXP_OUT_PITCH_PITCH(dst_stride);
+ out_lrc = BF_PXP_OUT_LRC_X(dst_width - 1) |
+ BF_PXP_OUT_LRC_Y(dst_height - 1);
+ /* PS covers whole output */
+ out_ps_ulc = BF_PXP_OUT_PS_ULC_X(0) | BF_PXP_OUT_PS_ULC_Y(0);
+ out_ps_lrc = BF_PXP_OUT_PS_LRC_X(dst_width - 1) |
+ BF_PXP_OUT_PS_LRC_Y(dst_height - 1);
+ /* no AS */
+ as_ulc = BF_PXP_OUT_AS_ULC_X(1) | BF_PXP_OUT_AS_ULC_Y(1);
+ as_lrc = BF_PXP_OUT_AS_LRC_X(0) | BF_PXP_OUT_AS_LRC_Y(0);
+
+ decx = (src_width <= dst_width) ? 0 : ilog2(src_width / dst_width);
+ decy = (src_height <= dst_height) ? 0 : ilog2(src_height / dst_height);
+ ps_ctrl = BF_PXP_PS_CTRL_DECX(decx) | BF_PXP_PS_CTRL_DECY(decy) |
+ pxp_v4l2_pix_fmt_to_ps_format(src_fourcc);
+ ps_buf = p_in;
+ y_size = src_stride * src_height;
+ switch (src_fourcc) {
+ case V4L2_PIX_FMT_YUV420:
+ ps_ubuf = ps_buf + y_size;
+ ps_vbuf = ps_ubuf + y_size / 4;
+ break;
+ case V4L2_PIX_FMT_YUV422P:
+ ps_ubuf = ps_buf + y_size;
+ ps_vbuf = ps_ubuf + y_size / 2;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ ps_ubuf = ps_buf + y_size;
+ ps_vbuf = 0;
+ break;
+ case V4L2_PIX_FMT_GREY:
+ case V4L2_PIX_FMT_Y4:
+ ps_ubuf = 0;
+ /* In grayscale mode, ps_vbuf contents are reused as CbCr */
+ ps_vbuf = 0x8080;
+ break;
+ default:
+ ps_ubuf = 0;
+ ps_vbuf = 0;
+ break;
+ }
+ ps_pitch = BF_PXP_PS_PITCH_PITCH(src_stride);
+ if (decx) {
+ xscale = (src_width >> decx) * 0x1000 / dst_width;
+ } else {
+ switch (src_fourcc) {
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_YUV420:
+ /*
+ * This avoids sampling past the right edge for
+ * horizontally chroma subsampled formats.
+ */
+ xscale = (src_width - 2) * 0x1000 / (dst_width - 1);
+ break;
+ default:
+ xscale = (src_width - 1) * 0x1000 / (dst_width - 1);
+ break;
+ }
+ }
+ if (decy)
+ yscale = (src_height >> decy) * 0x1000 / dst_height;
+ else
+ yscale = (src_height - 1) * 0x1000 / (dst_height - 1);
+ ps_scale = BF_PXP_PS_SCALE_YSCALE(yscale) |
+ BF_PXP_PS_SCALE_XSCALE(xscale);
+ ps_offset = BF_PXP_PS_OFFSET_YOFFSET(0) | BF_PXP_PS_OFFSET_XOFFSET(0);
+
+ writel(ctrl, dev->mmio + HW_PXP_CTRL);
+ /* skip STAT */
+ writel(out_ctrl, dev->mmio + HW_PXP_OUT_CTRL);
+ writel(out_buf, dev->mmio + HW_PXP_OUT_BUF);
+ writel(out_buf2, dev->mmio + HW_PXP_OUT_BUF2);
+ writel(out_pitch, dev->mmio + HW_PXP_OUT_PITCH);
+ writel(out_lrc, dev->mmio + HW_PXP_OUT_LRC);
+ writel(out_ps_ulc, dev->mmio + HW_PXP_OUT_PS_ULC);
+ writel(out_ps_lrc, dev->mmio + HW_PXP_OUT_PS_LRC);
+ writel(as_ulc, dev->mmio + HW_PXP_OUT_AS_ULC);
+ writel(as_lrc, dev->mmio + HW_PXP_OUT_AS_LRC);
+ writel(ps_ctrl, dev->mmio + HW_PXP_PS_CTRL);
+ writel(ps_buf, dev->mmio + HW_PXP_PS_BUF);
+ writel(ps_ubuf, dev->mmio + HW_PXP_PS_UBUF);
+ writel(ps_vbuf, dev->mmio + HW_PXP_PS_VBUF);
+ writel(ps_pitch, dev->mmio + HW_PXP_PS_PITCH);
+ writel(0x00ffffff, dev->mmio + HW_PXP_PS_BACKGROUND_0);
+ writel(ps_scale, dev->mmio + HW_PXP_PS_SCALE);
+ writel(ps_offset, dev->mmio + HW_PXP_PS_OFFSET);
+ /* disable processed surface color keying */
+ writel(0x00ffffff, dev->mmio + HW_PXP_PS_CLRKEYLOW_0);
+ writel(0x00000000, dev->mmio + HW_PXP_PS_CLRKEYHIGH_0);
+
+ /* disable alpha surface color keying */
+ writel(0x00ffffff, dev->mmio + HW_PXP_AS_CLRKEYLOW_0);
+ writel(0x00000000, dev->mmio + HW_PXP_AS_CLRKEYHIGH_0);
+
+ /* setup CSC */
+ pxp_setup_csc(ctx);
+
+ /* bypass LUT */
+ writel(BM_PXP_LUT_CTRL_BYPASS, dev->mmio + HW_PXP_LUT_CTRL);
+
+ writel(BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(1)|
+ BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(1)|
+ BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(0),
+ dev->mmio + HW_PXP_DATA_PATH_CTRL0);
+ writel(BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(1) |
+ BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(1),
+ dev->mmio + HW_PXP_DATA_PATH_CTRL1);
+
+ writel(0xffff, dev->mmio + HW_PXP_IRQ_MASK);
+
+ /* ungate, enable PS/AS/OUT and PXP operation */
+ writel(BM_PXP_CTRL_IRQ_ENABLE, dev->mmio + HW_PXP_CTRL_SET);
+ writel(BM_PXP_CTRL_ENABLE | BM_PXP_CTRL_ENABLE_CSC2 |
+ BM_PXP_CTRL_ENABLE_LUT | BM_PXP_CTRL_ENABLE_ROTATE0 |
+ BM_PXP_CTRL_ENABLE_PS_AS_OUT, dev->mmio + HW_PXP_CTRL_SET);
+
+ return 0;
+}
+
+static void pxp_job_finish(struct pxp_dev *dev)
+{
+ struct pxp_ctx *curr_ctx;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
+ unsigned long flags;
+
+ curr_ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+
+ if (curr_ctx == NULL) {
+ pr_err("Instance released before the end of transaction\n");
+ return;
+ }
+
+ src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+ dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
+
+ spin_lock_irqsave(&dev->irqlock, flags);
+ v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
+ v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+
+ dprintk(curr_ctx->dev, "Finishing transaction\n");
+ v4l2_m2m_job_finish(dev->m2m_dev, curr_ctx->fh.m2m_ctx);
+}
+
+/*
+ * mem2mem callbacks
+ */
+static void pxp_device_run(void *priv)
+{
+ struct pxp_ctx *ctx = priv;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+ pxp_start(ctx, src_buf, dst_buf);
+}
+
+static int pxp_job_ready(void *priv)
+{
+ struct pxp_ctx *ctx = priv;
+
+ if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < 1 ||
+ v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < 1) {
+ dprintk(ctx->dev, "Not enough buffers available\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static void pxp_job_abort(void *priv)
+{
+ struct pxp_ctx *ctx = priv;
+
+ /* Will cancel the transaction in the next interrupt handler */
+ ctx->aborting = 1;
+}
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t pxp_irq_handler(int irq, void *dev_id)
+{
+ struct pxp_dev *dev = dev_id;
+ u32 stat;
+
+ stat = readl(dev->mmio + HW_PXP_STAT);
+
+ if (stat & BM_PXP_STAT_IRQ0) {
+ /* we expect x = 0, y = height, irq0 = 1 */
+ if (stat & ~(BM_PXP_STAT_BLOCKX | BM_PXP_STAT_BLOCKY |
+ BM_PXP_STAT_IRQ0))
+ dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat);
+ writel(BM_PXP_STAT_IRQ0, dev->mmio + HW_PXP_STAT_CLR);
+
+ pxp_job_finish(dev);
+ } else {
+ u32 irq = readl(dev->mmio + HW_PXP_IRQ);
+
+ dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat);
+ dprintk(dev, "%s: irq = 0x%08x\n", __func__, irq);
+
+ writel(irq, dev->mmio + HW_PXP_IRQ_CLR);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * video ioctls
+ */
+static int pxp_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ strlcpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
+ strlcpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info),
+ "platform:%s", MEM2MEM_NAME);
+ return 0;
+}
+
+static int pxp_enum_fmt(struct v4l2_fmtdesc *f, u32 type)
+{
+ int i, num;
+ struct pxp_fmt *fmt;
+
+ num = 0;
+
+ for (i = 0; i < NUM_FORMATS; ++i) {
+ if (formats[i].types & type) {
+ /* index-th format of type type found ? */
+ if (num == f->index)
+ break;
+ /*
+ * Correct type but haven't reached our index yet,
+ * just increment per-type index
+ */
+ ++num;
+ }
+ }
+
+ if (i < NUM_FORMATS) {
+ /* Format found */
+ fmt = &formats[i];
+ f->pixelformat = fmt->fourcc;
+ return 0;
+ }
+
+ /* Format not found */
+ return -EINVAL;
+}
+
+static int pxp_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ return pxp_enum_fmt(f, MEM2MEM_CAPTURE);
+}
+
+static int pxp_enum_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ return pxp_enum_fmt(f, MEM2MEM_OUTPUT);
+}
+
+static int pxp_g_fmt(struct pxp_ctx *ctx, struct v4l2_format *f)
+{
+ struct vb2_queue *vq;
+ struct pxp_q_data *q_data;
+
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+ if (!vq)
+ return -EINVAL;
+
+ q_data = get_q_data(ctx, f->type);
+
+ f->fmt.pix.width = q_data->width;
+ f->fmt.pix.height = q_data->height;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.pixelformat = q_data->fmt->fourcc;
+ f->fmt.pix.bytesperline = q_data->bytesperline;
+ f->fmt.pix.sizeimage = q_data->sizeimage;
+ f->fmt.pix.colorspace = ctx->colorspace;
+ f->fmt.pix.xfer_func = ctx->xfer_func;
+ f->fmt.pix.ycbcr_enc = q_data->ycbcr_enc;
+ f->fmt.pix.quantization = q_data->quant;
+
+ return 0;
+}
+
+static int pxp_g_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ return pxp_g_fmt(file2ctx(file), f);
+}
+
+static int pxp_g_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ return pxp_g_fmt(file2ctx(file), f);
+}
+
+static inline u32 pxp_bytesperline(struct pxp_fmt *fmt, u32 width)
+{
+ switch (fmt->fourcc) {
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ return width;
+ default:
+ return (width * fmt->depth) >> 3;
+ }
+}
+
+static inline u32 pxp_sizeimage(struct pxp_fmt *fmt, u32 width, u32 height)
+{
+ return (fmt->depth * width * height) >> 3;
+}
+
+static int pxp_try_fmt(struct v4l2_format *f, struct pxp_fmt *fmt)
+{
+ v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, ALIGN_W,
+ &f->fmt.pix.height, MIN_H, MAX_H, ALIGN_H, 0);
+
+ f->fmt.pix.bytesperline = pxp_bytesperline(fmt, f->fmt.pix.width);
+ f->fmt.pix.sizeimage = pxp_sizeimage(fmt, f->fmt.pix.width,
+ f->fmt.pix.height);
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+
+ return 0;
+}
+
+static void
+pxp_fixup_colorimetry_cap(struct pxp_ctx *ctx, u32 dst_fourcc,
+ enum v4l2_ycbcr_encoding *ycbcr_enc,
+ enum v4l2_quantization *quantization)
+{
+ bool dst_is_yuv = pxp_v4l2_pix_fmt_is_yuv(dst_fourcc);
+
+ if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) ==
+ dst_is_yuv) {
+ /*
+ * There is no support for conversion between different YCbCr
+ * encodings or between RGB limited and full range.
+ */
+ *ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc;
+ *quantization = ctx->q_data[V4L2_M2M_SRC].quant;
+ } else {
+ *ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(ctx->colorspace);
+ *quantization = V4L2_MAP_QUANTIZATION_DEFAULT(!dst_is_yuv,
+ ctx->colorspace,
+ *ycbcr_enc);
+ }
+}
+
+static int pxp_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct pxp_fmt *fmt;
+ struct pxp_ctx *ctx = file2ctx(file);
+
+ fmt = find_format(f);
+ if (!fmt) {
+ f->fmt.pix.pixelformat = formats[0].fourcc;
+ fmt = find_format(f);
+ }
+ if (!(fmt->types & MEM2MEM_CAPTURE)) {
+ v4l2_err(&ctx->dev->v4l2_dev,
+ "Fourcc format (0x%08x) invalid.\n",
+ f->fmt.pix.pixelformat);
+ return -EINVAL;
+ }
+
+ f->fmt.pix.colorspace = ctx->colorspace;
+ f->fmt.pix.xfer_func = ctx->xfer_func;
+
+ pxp_fixup_colorimetry_cap(ctx, fmt->fourcc,
+ &f->fmt.pix.ycbcr_enc,
+ &f->fmt.pix.quantization);
+
+ return pxp_try_fmt(f, fmt);
+}
+
+static int pxp_try_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct pxp_fmt *fmt;
+ struct pxp_ctx *ctx = file2ctx(file);
+
+ fmt = find_format(f);
+ if (!fmt) {
+ f->fmt.pix.pixelformat = formats[0].fourcc;
+ fmt = find_format(f);
+ }
+ if (!(fmt->types & MEM2MEM_OUTPUT)) {
+ v4l2_err(&ctx->dev->v4l2_dev,
+ "Fourcc format (0x%08x) invalid.\n",
+ f->fmt.pix.pixelformat);
+ return -EINVAL;
+ }
+
+ if (!f->fmt.pix.colorspace)
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+
+ return pxp_try_fmt(f, fmt);
+}
+
+static int pxp_s_fmt(struct pxp_ctx *ctx, struct v4l2_format *f)
+{
+ struct pxp_q_data *q_data;
+ struct vb2_queue *vq;
+
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+ if (!vq)
+ return -EINVAL;
+
+ q_data = get_q_data(ctx, f->type);
+ if (!q_data)
+ return -EINVAL;
+
+ if (vb2_is_busy(vq)) {
+ v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
+ return -EBUSY;
+ }
+
+ q_data->fmt = find_format(f);
+ q_data->width = f->fmt.pix.width;
+ q_data->height = f->fmt.pix.height;
+ q_data->bytesperline = f->fmt.pix.bytesperline;
+ q_data->sizeimage = f->fmt.pix.sizeimage;
+
+ dprintk(ctx->dev,
+ "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
+ f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
+
+ return 0;
+}
+
+static int pxp_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct pxp_ctx *ctx = file2ctx(file);
+ int ret;
+
+ ret = pxp_try_fmt_vid_cap(file, priv, f);
+ if (ret)
+ return ret;
+
+ ret = pxp_s_fmt(file2ctx(file), f);
+ if (ret)
+ return ret;
+
+ ctx->q_data[V4L2_M2M_DST].ycbcr_enc = f->fmt.pix.ycbcr_enc;
+ ctx->q_data[V4L2_M2M_DST].quant = f->fmt.pix.quantization;
+
+ return 0;
+}
+
+static int pxp_s_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct pxp_ctx *ctx = file2ctx(file);
+ int ret;
+
+ ret = pxp_try_fmt_vid_out(file, priv, f);
+ if (ret)
+ return ret;
+
+ ret = pxp_s_fmt(file2ctx(file), f);
+ if (ret)
+ return ret;
+
+ ctx->colorspace = f->fmt.pix.colorspace;
+ ctx->xfer_func = f->fmt.pix.xfer_func;
+ ctx->q_data[V4L2_M2M_SRC].ycbcr_enc = f->fmt.pix.ycbcr_enc;
+ ctx->q_data[V4L2_M2M_SRC].quant = f->fmt.pix.quantization;
+
+ pxp_fixup_colorimetry_cap(ctx, ctx->q_data[V4L2_M2M_DST].fmt->fourcc,
+ &ctx->q_data[V4L2_M2M_DST].ycbcr_enc,
+ &ctx->q_data[V4L2_M2M_DST].quant);
+
+ return 0;
+}
+
+static int pxp_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct pxp_ctx *ctx =
+ container_of(ctrl->handler, struct pxp_ctx, hdl);
+
+ switch (ctrl->id) {
+ case V4L2_CID_HFLIP:
+ if (ctrl->val)
+ ctx->mode |= MEM2MEM_HFLIP;
+ else
+ ctx->mode &= ~MEM2MEM_HFLIP;
+ break;
+
+ case V4L2_CID_VFLIP:
+ if (ctrl->val)
+ ctx->mode |= MEM2MEM_VFLIP;
+ else
+ ctx->mode &= ~MEM2MEM_VFLIP;
+ break;
+
+ case V4L2_CID_ALPHA_COMPONENT:
+ ctx->alpha_component = ctrl->val;
+ break;
+
+ default:
+ v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops pxp_ctrl_ops = {
+ .s_ctrl = pxp_s_ctrl,
+};
+
+static const struct v4l2_ioctl_ops pxp_ioctl_ops = {
+ .vidioc_querycap = pxp_querycap,
+
+ .vidioc_enum_fmt_vid_cap = pxp_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = pxp_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = pxp_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = pxp_s_fmt_vid_cap,
+
+ .vidioc_enum_fmt_vid_out = pxp_enum_fmt_vid_out,
+ .vidioc_g_fmt_vid_out = pxp_g_fmt_vid_out,
+ .vidioc_try_fmt_vid_out = pxp_try_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = pxp_s_fmt_vid_out,
+
+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+
+ .vidioc_streamon = v4l2_m2m_ioctl_streamon,
+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+/*
+ * Queue operations
+ */
+static int pxp_queue_setup(struct vb2_queue *vq,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], struct device *alloc_devs[])
+{
+ struct pxp_ctx *ctx = vb2_get_drv_priv(vq);
+ struct pxp_q_data *q_data;
+ unsigned int size, count = *nbuffers;
+
+ q_data = get_q_data(ctx, vq->type);
+
+ size = q_data->sizeimage;
+
+ *nbuffers = count;
+
+ if (*nplanes)
+ return sizes[0] < size ? -EINVAL : 0;
+
+ *nplanes = 1;
+ sizes[0] = size;
+
+ dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
+
+ return 0;
+}
+
+static int pxp_buf_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct pxp_dev *dev = ctx->dev;
+ struct pxp_q_data *q_data;
+
+ dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
+
+ q_data = get_q_data(ctx, vb->vb2_queue->type);
+ if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+ if (vbuf->field == V4L2_FIELD_ANY)
+ vbuf->field = V4L2_FIELD_NONE;
+ if (vbuf->field != V4L2_FIELD_NONE) {
+ dprintk(dev, "%s field isn't supported\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
+ dprintk(dev, "%s data will not fit into plane (%lu < %lu)\n",
+ __func__, vb2_plane_size(vb, 0),
+ (long)q_data->sizeimage);
+ return -EINVAL;
+ }
+
+ vb2_set_plane_payload(vb, 0, q_data->sizeimage);
+
+ return 0;
+}
+
+static void pxp_buf_queue(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static int pxp_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct pxp_ctx *ctx = vb2_get_drv_priv(q);
+ struct pxp_q_data *q_data = get_q_data(ctx, q->type);
+
+ q_data->sequence = 0;
+ return 0;
+}
+
+static void pxp_stop_streaming(struct vb2_queue *q)
+{
+ struct pxp_ctx *ctx = vb2_get_drv_priv(q);
+ struct vb2_v4l2_buffer *vbuf;
+ unsigned long flags;
+
+ for (;;) {
+ if (V4L2_TYPE_IS_OUTPUT(q->type))
+ vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ else
+ vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ if (vbuf == NULL)
+ return;
+ spin_lock_irqsave(&ctx->dev->irqlock, flags);
+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+ spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
+ }
+}
+
+static const struct vb2_ops pxp_qops = {
+ .queue_setup = pxp_queue_setup,
+ .buf_prepare = pxp_buf_prepare,
+ .buf_queue = pxp_buf_queue,
+ .start_streaming = pxp_start_streaming,
+ .stop_streaming = pxp_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_vq)
+{
+ struct pxp_ctx *ctx = priv;
+ int ret;
+
+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ src_vq->drv_priv = ctx;
+ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ src_vq->ops = &pxp_qops;
+ src_vq->mem_ops = &vb2_dma_contig_memops;
+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ src_vq->lock = &ctx->dev->dev_mutex;
+ src_vq->dev = ctx->dev->v4l2_dev.dev;
+
+ ret = vb2_queue_init(src_vq);
+ if (ret)
+ return ret;
+
+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ dst_vq->drv_priv = ctx;
+ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ dst_vq->ops = &pxp_qops;
+ dst_vq->mem_ops = &vb2_dma_contig_memops;
+ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ dst_vq->lock = &ctx->dev->dev_mutex;
+ dst_vq->dev = ctx->dev->v4l2_dev.dev;
+
+ return vb2_queue_init(dst_vq);
+}
+
+/*
+ * File operations
+ */
+static int pxp_open(struct file *file)
+{
+ struct pxp_dev *dev = video_drvdata(file);
+ struct pxp_ctx *ctx = NULL;
+ struct v4l2_ctrl_handler *hdl;
+ int rc = 0;
+
+ if (mutex_lock_interruptible(&dev->dev_mutex))
+ return -ERESTARTSYS;
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx) {
+ rc = -ENOMEM;
+ goto open_unlock;
+ }
+
+ v4l2_fh_init(&ctx->fh, video_devdata(file));
+ file->private_data = &ctx->fh;
+ ctx->dev = dev;
+ hdl = &ctx->hdl;
+ v4l2_ctrl_handler_init(hdl, 4);
+ v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+ 0, 255, 1, 255);
+ if (hdl->error) {
+ rc = hdl->error;
+ v4l2_ctrl_handler_free(hdl);
+ kfree(ctx);
+ goto open_unlock;
+ }
+ ctx->fh.ctrl_handler = hdl;
+ v4l2_ctrl_handler_setup(hdl);
+
+ ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
+ ctx->q_data[V4L2_M2M_SRC].width = 640;
+ ctx->q_data[V4L2_M2M_SRC].height = 480;
+ ctx->q_data[V4L2_M2M_SRC].bytesperline =
+ pxp_bytesperline(&formats[0], 640);
+ ctx->q_data[V4L2_M2M_SRC].sizeimage =
+ pxp_sizeimage(&formats[0], 640, 480);
+ ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
+ ctx->colorspace = V4L2_COLORSPACE_REC709;
+
+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
+
+ if (IS_ERR(ctx->fh.m2m_ctx)) {
+ rc = PTR_ERR(ctx->fh.m2m_ctx);
+
+ v4l2_ctrl_handler_free(hdl);
+ v4l2_fh_exit(&ctx->fh);
+ kfree(ctx);
+ goto open_unlock;
+ }
+
+ v4l2_fh_add(&ctx->fh);
+ atomic_inc(&dev->num_inst);
+
+ dprintk(dev, "Created instance: %p, m2m_ctx: %p\n",
+ ctx, ctx->fh.m2m_ctx);
+
+open_unlock:
+ mutex_unlock(&dev->dev_mutex);
+ return rc;
+}
+
+static int pxp_release(struct file *file)
+{
+ struct pxp_dev *dev = video_drvdata(file);
+ struct pxp_ctx *ctx = file2ctx(file);
+
+ dprintk(dev, "Releasing instance %p\n", ctx);
+
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+ v4l2_ctrl_handler_free(&ctx->hdl);
+ mutex_lock(&dev->dev_mutex);
+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+ mutex_unlock(&dev->dev_mutex);
+ kfree(ctx);
+
+ atomic_dec(&dev->num_inst);
+
+ return 0;
+}
+
+static const struct v4l2_file_operations pxp_fops = {
+ .owner = THIS_MODULE,
+ .open = pxp_open,
+ .release = pxp_release,
+ .poll = v4l2_m2m_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = v4l2_m2m_fop_mmap,
+};
+
+static const struct video_device pxp_videodev = {
+ .name = MEM2MEM_NAME,
+ .vfl_dir = VFL_DIR_M2M,
+ .fops = &pxp_fops,
+ .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
+ .ioctl_ops = &pxp_ioctl_ops,
+ .minor = -1,
+ .release = video_device_release_empty,
+};
+
+static const struct v4l2_m2m_ops m2m_ops = {
+ .device_run = pxp_device_run,
+ .job_ready = pxp_job_ready,
+ .job_abort = pxp_job_abort,
+};
+
+static void pxp_soft_reset(struct pxp_dev *dev)
+{
+ int ret;
+ u32 val;
+
+ writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR);
+ writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR);
+
+ writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET);
+
+ ret = readl_poll_timeout(dev->mmio + HW_PXP_CTRL, val,
+ val & BM_PXP_CTRL_CLKGATE, 0, 100);
+ if (ret < 0)
+ pr_err("PXP reset timeout\n");
+
+ writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR);
+ writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR);
+}
+
+static int pxp_probe(struct platform_device *pdev)
+{
+ struct pxp_dev *dev;
+ struct resource *res;
+ struct video_device *vfd;
+ int irq;
+ int ret;
+
+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->clk = devm_clk_get(&pdev->dev, "axi");
+ if (IS_ERR(dev->clk)) {
+ ret = PTR_ERR(dev->clk);
+ dev_err(&pdev->dev, "Failed to get clk: %d\n", ret);
+ return ret;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dev->mmio = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dev->mmio)) {
+ ret = PTR_ERR(dev->mmio);
+ dev_err(&pdev->dev, "Failed to map register space: %d\n", ret);
+ return ret;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Failed to get irq resource: %d\n", irq);
+ return irq;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, pxp_irq_handler,
+ IRQF_ONESHOT, dev_name(&pdev->dev), dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
+ return ret;
+ }
+
+ clk_prepare_enable(dev->clk);
+ pxp_soft_reset(dev);
+
+ spin_lock_init(&dev->irqlock);
+
+ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+ if (ret)
+ goto err_clk;
+
+ atomic_set(&dev->num_inst, 0);
+ mutex_init(&dev->dev_mutex);
+
+ dev->vfd = pxp_videodev;
+ vfd = &dev->vfd;
+ vfd->lock = &dev->dev_mutex;
+ vfd->v4l2_dev = &dev->v4l2_dev;
+
+ video_set_drvdata(vfd, dev);
+ snprintf(vfd->name, sizeof(vfd->name), "%s", pxp_videodev.name);
+ v4l2_info(&dev->v4l2_dev,
+ "Device registered as /dev/video%d\n", vfd->num);
+
+ platform_set_drvdata(pdev, dev);
+
+ dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
+ if (IS_ERR(dev->m2m_dev)) {
+ v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
+ ret = PTR_ERR(dev->m2m_dev);
+ goto err_v4l2;
+ }
+
+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+ if (ret) {
+ v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+ goto err_m2m;
+ }
+
+ return 0;
+
+err_m2m:
+ v4l2_m2m_release(dev->m2m_dev);
+err_v4l2:
+ v4l2_device_unregister(&dev->v4l2_dev);
+err_clk:
+ clk_disable_unprepare(dev->clk);
+
+ return ret;
+}
+
+static int pxp_remove(struct platform_device *pdev)
+{
+ struct pxp_dev *dev = platform_get_drvdata(pdev);
+
+ writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_SET);
+ writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET);
+
+ clk_disable_unprepare(dev->clk);
+
+ v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
+ video_unregister_device(&dev->vfd);
+ v4l2_m2m_release(dev->m2m_dev);
+ v4l2_device_unregister(&dev->v4l2_dev);
+
+ return 0;
+}
+
+static const struct of_device_id pxp_dt_ids[] = {
+ { .compatible = "fsl,imx6ull-pxp", .data = NULL },
+ { },
+};
+MODULE_DEVICE_TABLE(of, pxp_dt_ids);
+
+static struct platform_driver pxp_driver = {
+ .probe = pxp_probe,
+ .remove = pxp_remove,
+ .driver = {
+ .name = MEM2MEM_NAME,
+ .of_match_table = of_match_ptr(pxp_dt_ids),
+ },
+};
+
+module_platform_driver(pxp_driver);
+
+MODULE_DESCRIPTION("i.MX PXP mem2mem scaler/CSC/rotator");
+MODULE_AUTHOR("Philipp Zabel <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/imx-pxp.h b/drivers/media/platform/imx-pxp.h
new file mode 100644
index 000000000000..44f95c749d2e
--- /dev/null
+++ b/drivers/media/platform/imx-pxp.h
@@ -0,0 +1,1685 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Freescale PXP Register Definitions
+ *
+ * based on pxp_dma_v3.h, Xml Revision: 1.77, Template Revision: 1.3
+ *
+ * Copyright 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+#ifndef __IMX_PXP_H__
+#define __IMX_PXP_H__
+
+#define HW_PXP_CTRL (0x00000000)
+#define HW_PXP_CTRL_SET (0x00000004)
+#define HW_PXP_CTRL_CLR (0x00000008)
+#define HW_PXP_CTRL_TOG (0x0000000c)
+
+#define BM_PXP_CTRL_SFTRST 0x80000000
+#define BF_PXP_CTRL_SFTRST(v) \
+ (((v) << 31) & BM_PXP_CTRL_SFTRST)
+#define BM_PXP_CTRL_CLKGATE 0x40000000
+#define BF_PXP_CTRL_CLKGATE(v) \
+ (((v) << 30) & BM_PXP_CTRL_CLKGATE)
+#define BM_PXP_CTRL_RSVD4 0x20000000
+#define BF_PXP_CTRL_RSVD4(v) \
+ (((v) << 29) & BM_PXP_CTRL_RSVD4)
+#define BM_PXP_CTRL_EN_REPEAT 0x10000000
+#define BF_PXP_CTRL_EN_REPEAT(v) \
+ (((v) << 28) & BM_PXP_CTRL_EN_REPEAT)
+#define BM_PXP_CTRL_ENABLE_ROTATE1 0x08000000
+#define BF_PXP_CTRL_ENABLE_ROTATE1(v) \
+ (((v) << 27) & BM_PXP_CTRL_ENABLE_ROTATE1)
+#define BM_PXP_CTRL_ENABLE_ROTATE0 0x04000000
+#define BF_PXP_CTRL_ENABLE_ROTATE0(v) \
+ (((v) << 26) & BM_PXP_CTRL_ENABLE_ROTATE0)
+#define BM_PXP_CTRL_ENABLE_LUT 0x02000000
+#define BF_PXP_CTRL_ENABLE_LUT(v) \
+ (((v) << 25) & BM_PXP_CTRL_ENABLE_LUT)
+#define BM_PXP_CTRL_ENABLE_CSC2 0x01000000
+#define BF_PXP_CTRL_ENABLE_CSC2(v) \
+ (((v) << 24) & BM_PXP_CTRL_ENABLE_CSC2)
+#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000
+#define BF_PXP_CTRL_BLOCK_SIZE(v) \
+ (((v) << 23) & BM_PXP_CTRL_BLOCK_SIZE)
+#define BV_PXP_CTRL_BLOCK_SIZE__8X8 0x0
+#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1
+#define BM_PXP_CTRL_RSVD1 0x00400000
+#define BF_PXP_CTRL_RSVD1(v) \
+ (((v) << 22) & BM_PXP_CTRL_RSVD1)
+#define BM_PXP_CTRL_ENABLE_ALPHA_B 0x00200000
+#define BF_PXP_CTRL_ENABLE_ALPHA_B(v) \
+ (((v) << 21) & BM_PXP_CTRL_ENABLE_ALPHA_B)
+#define BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE 0x00100000
+#define BF_PXP_CTRL_ENABLE_INPUT_FETCH_STORE(v) \
+ (((v) << 20) & BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE)
+#define BM_PXP_CTRL_ENABLE_WFE_B 0x00080000
+#define BF_PXP_CTRL_ENABLE_WFE_B(v) \
+ (((v) << 19) & BM_PXP_CTRL_ENABLE_WFE_B)
+#define BM_PXP_CTRL_ENABLE_WFE_A 0x00040000
+#define BF_PXP_CTRL_ENABLE_WFE_A(v) \
+ (((v) << 18) & BM_PXP_CTRL_ENABLE_WFE_A)
+#define BM_PXP_CTRL_ENABLE_DITHER 0x00020000
+#define BF_PXP_CTRL_ENABLE_DITHER(v) \
+ (((v) << 17) & BM_PXP_CTRL_ENABLE_DITHER)
+#define BM_PXP_CTRL_ENABLE_PS_AS_OUT 0x00010000
+#define BF_PXP_CTRL_ENABLE_PS_AS_OUT(v) \
+ (((v) << 16) & BM_PXP_CTRL_ENABLE_PS_AS_OUT)
+#define BM_PXP_CTRL_VFLIP1 0x00008000
+#define BF_PXP_CTRL_VFLIP1(v) \
+ (((v) << 15) & BM_PXP_CTRL_VFLIP1)
+#define BM_PXP_CTRL_HFLIP1 0x00004000
+#define BF_PXP_CTRL_HFLIP1(v) \
+ (((v) << 14) & BM_PXP_CTRL_HFLIP1)
+#define BP_PXP_CTRL_ROTATE1 12
+#define BM_PXP_CTRL_ROTATE1 0x00003000
+#define BF_PXP_CTRL_ROTATE1(v) \
+ (((v) << 12) & BM_PXP_CTRL_ROTATE1)
+#define BV_PXP_CTRL_ROTATE1__ROT_0 0x0
+#define BV_PXP_CTRL_ROTATE1__ROT_90 0x1
+#define BV_PXP_CTRL_ROTATE1__ROT_180 0x2
+#define BV_PXP_CTRL_ROTATE1__ROT_270 0x3
+#define BM_PXP_CTRL_VFLIP0 0x00000800
+#define BF_PXP_CTRL_VFLIP0(v) \
+ (((v) << 11) & BM_PXP_CTRL_VFLIP0)
+#define BM_PXP_CTRL_HFLIP0 0x00000400
+#define BF_PXP_CTRL_HFLIP0(v) \
+ (((v) << 10) & BM_PXP_CTRL_HFLIP0)
+#define BP_PXP_CTRL_ROTATE0 8
+#define BM_PXP_CTRL_ROTATE0 0x00000300
+#define BF_PXP_CTRL_ROTATE0(v) \
+ (((v) << 8) & BM_PXP_CTRL_ROTATE0)
+#define BV_PXP_CTRL_ROTATE0__ROT_0 0x0
+#define BV_PXP_CTRL_ROTATE0__ROT_90 0x1
+#define BV_PXP_CTRL_ROTATE0__ROT_180 0x2
+#define BV_PXP_CTRL_ROTATE0__ROT_270 0x3
+#define BP_PXP_CTRL_RSVD0 6
+#define BM_PXP_CTRL_RSVD0 0x000000C0
+#define BF_PXP_CTRL_RSVD0(v) \
+ (((v) << 6) & BM_PXP_CTRL_RSVD0)
+#define BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP 0x00000020
+#define BF_PXP_CTRL_HANDSHAKE_ABORT_SKIP(v) \
+ (((v) << 5) & BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP)
+#define BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE 0x00000010
+#define BF_PXP_CTRL_ENABLE_LCD0_HANDSHAKE(v) \
+ (((v) << 4) & BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE)
+#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008
+#define BF_PXP_CTRL_LUT_DMA_IRQ_ENABLE(v) \
+ (((v) << 3) & BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE)
+#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004
+#define BF_PXP_CTRL_NEXT_IRQ_ENABLE(v) \
+ (((v) << 2) & BM_PXP_CTRL_NEXT_IRQ_ENABLE)
+#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002
+#define BF_PXP_CTRL_IRQ_ENABLE(v) \
+ (((v) << 1) & BM_PXP_CTRL_IRQ_ENABLE)
+#define BM_PXP_CTRL_ENABLE 0x00000001
+#define BF_PXP_CTRL_ENABLE(v) \
+ (((v) << 0) & BM_PXP_CTRL_ENABLE)
+
+#define HW_PXP_STAT (0x00000010)
+#define HW_PXP_STAT_SET (0x00000014)
+#define HW_PXP_STAT_CLR (0x00000018)
+#define HW_PXP_STAT_TOG (0x0000001c)
+
+#define BP_PXP_STAT_BLOCKX 24
+#define BM_PXP_STAT_BLOCKX 0xFF000000
+#define BF_PXP_STAT_BLOCKX(v) \
+ (((v) << 24) & BM_PXP_STAT_BLOCKX)
+#define BP_PXP_STAT_BLOCKY 16
+#define BM_PXP_STAT_BLOCKY 0x00FF0000
+#define BF_PXP_STAT_BLOCKY(v) \
+ (((v) << 16) & BM_PXP_STAT_BLOCKY)
+#define BP_PXP_STAT_AXI_ERROR_ID_1 12
+#define BM_PXP_STAT_AXI_ERROR_ID_1 0x0000F000
+#define BF_PXP_STAT_AXI_ERROR_ID_1(v) \
+ (((v) << 12) & BM_PXP_STAT_AXI_ERROR_ID_1)
+#define BM_PXP_STAT_RSVD2 0x00000800
+#define BF_PXP_STAT_RSVD2(v) \
+ (((v) << 11) & BM_PXP_STAT_RSVD2)
+#define BM_PXP_STAT_AXI_READ_ERROR_1 0x00000400
+#define BF_PXP_STAT_AXI_READ_ERROR_1(v) \
+ (((v) << 10) & BM_PXP_STAT_AXI_READ_ERROR_1)
+#define BM_PXP_STAT_AXI_WRITE_ERROR_1 0x00000200
+#define BF_PXP_STAT_AXI_WRITE_ERROR_1(v) \
+ (((v) << 9) & BM_PXP_STAT_AXI_WRITE_ERROR_1)
+#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100
+#define BF_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ(v) \
+ (((v) << 8) & BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ)
+#define BP_PXP_STAT_AXI_ERROR_ID_0 4
+#define BM_PXP_STAT_AXI_ERROR_ID_0 0x000000F0
+#define BF_PXP_STAT_AXI_ERROR_ID_0(v) \
+ (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID_0)
+#define BM_PXP_STAT_NEXT_IRQ 0x00000008
+#define BF_PXP_STAT_NEXT_IRQ(v) \
+ (((v) << 3) & BM_PXP_STAT_NEXT_IRQ)
+#define BM_PXP_STAT_AXI_READ_ERROR_0 0x00000004
+#define BF_PXP_STAT_AXI_READ_ERROR_0(v) \
+ (((v) << 2) & BM_PXP_STAT_AXI_READ_ERROR_0)
+#define BM_PXP_STAT_AXI_WRITE_ERROR_0 0x00000002
+#define BF_PXP_STAT_AXI_WRITE_ERROR_0(v) \
+ (((v) << 1) & BM_PXP_STAT_AXI_WRITE_ERROR_0)
+#define BM_PXP_STAT_IRQ0 0x00000001
+#define BF_PXP_STAT_IRQ0(v) \
+ (((v) << 0) & BM_PXP_STAT_IRQ0)
+
+#define HW_PXP_OUT_CTRL (0x00000020)
+#define HW_PXP_OUT_CTRL_SET (0x00000024)
+#define HW_PXP_OUT_CTRL_CLR (0x00000028)
+#define HW_PXP_OUT_CTRL_TOG (0x0000002c)
+
+#define BP_PXP_OUT_CTRL_ALPHA 24
+#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000
+#define BF_PXP_OUT_CTRL_ALPHA(v) \
+ (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA)
+#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000
+#define BF_PXP_OUT_CTRL_ALPHA_OUTPUT(v) \
+ (((v) << 23) & BM_PXP_OUT_CTRL_ALPHA_OUTPUT)
+#define BP_PXP_OUT_CTRL_RSVD1 10
+#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00
+#define BF_PXP_OUT_CTRL_RSVD1(v) \
+ (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1)
+#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT 8
+#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300
+#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v) \
+ (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT)
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0 0x1
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1 0x2
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED 0x3
+#define BP_PXP_OUT_CTRL_RSVD0 5
+#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0
+#define BF_PXP_OUT_CTRL_RSVD0(v) \
+ (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0)
+#define BP_PXP_OUT_CTRL_FORMAT 0
+#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F
+#define BF_PXP_OUT_CTRL_FORMAT(v) \
+ (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT)
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888 0x0
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888 0x4
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888P 0x5
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555 0x8
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444 0x9
+#define BV_PXP_OUT_CTRL_FORMAT__RGB555 0xC
+#define BV_PXP_OUT_CTRL_FORMAT__RGB444 0xD
+#define BV_PXP_OUT_CTRL_FORMAT__RGB565 0xE
+#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444 0x10
+#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_OUT_CTRL_FORMAT__Y8 0x14
+#define BV_PXP_OUT_CTRL_FORMAT__Y4 0x15
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422 0x18
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420 0x19
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422 0x1A
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420 0x1B
+
+#define HW_PXP_OUT_BUF (0x00000030)
+
+#define BP_PXP_OUT_BUF_ADDR 0
+#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF_ADDR(v) (v)
+
+#define HW_PXP_OUT_BUF2 (0x00000040)
+
+#define BP_PXP_OUT_BUF2_ADDR 0
+#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF2_ADDR(v) (v)
+
+#define HW_PXP_OUT_PITCH (0x00000050)
+
+#define BP_PXP_OUT_PITCH_RSVD 16
+#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_OUT_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_OUT_PITCH_RSVD)
+#define BP_PXP_OUT_PITCH_PITCH 0
+#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_OUT_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_OUT_PITCH_PITCH)
+
+#define HW_PXP_OUT_LRC (0x00000060)
+
+#define BP_PXP_OUT_LRC_RSVD1 30
+#define BM_PXP_OUT_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_LRC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_LRC_RSVD1)
+#define BP_PXP_OUT_LRC_X 16
+#define BM_PXP_OUT_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_LRC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_LRC_X)
+#define BP_PXP_OUT_LRC_RSVD0 14
+#define BM_PXP_OUT_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_LRC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_LRC_RSVD0)
+#define BP_PXP_OUT_LRC_Y 0
+#define BM_PXP_OUT_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_LRC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_LRC_Y)
+
+#define HW_PXP_OUT_PS_ULC (0x00000070)
+
+#define BP_PXP_OUT_PS_ULC_RSVD1 30
+#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_ULC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1)
+#define BP_PXP_OUT_PS_ULC_X 16
+#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_ULC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_PS_ULC_X)
+#define BP_PXP_OUT_PS_ULC_RSVD0 14
+#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_ULC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0)
+#define BP_PXP_OUT_PS_ULC_Y 0
+#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_ULC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_PS_ULC_Y)
+
+#define HW_PXP_OUT_PS_LRC (0x00000080)
+
+#define BP_PXP_OUT_PS_LRC_RSVD1 30
+#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_LRC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1)
+#define BP_PXP_OUT_PS_LRC_X 16
+#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_LRC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_PS_LRC_X)
+#define BP_PXP_OUT_PS_LRC_RSVD0 14
+#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_LRC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0)
+#define BP_PXP_OUT_PS_LRC_Y 0
+#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_LRC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_PS_LRC_Y)
+
+#define HW_PXP_OUT_AS_ULC (0x00000090)
+
+#define BP_PXP_OUT_AS_ULC_RSVD1 30
+#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_ULC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1)
+#define BP_PXP_OUT_AS_ULC_X 16
+#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_ULC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_AS_ULC_X)
+#define BP_PXP_OUT_AS_ULC_RSVD0 14
+#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_ULC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0)
+#define BP_PXP_OUT_AS_ULC_Y 0
+#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_ULC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_AS_ULC_Y)
+
+#define HW_PXP_OUT_AS_LRC (0x000000a0)
+
+#define BP_PXP_OUT_AS_LRC_RSVD1 30
+#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_LRC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1)
+#define BP_PXP_OUT_AS_LRC_X 16
+#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_LRC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_AS_LRC_X)
+#define BP_PXP_OUT_AS_LRC_RSVD0 14
+#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_LRC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0)
+#define BP_PXP_OUT_AS_LRC_Y 0
+#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_LRC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_AS_LRC_Y)
+
+#define HW_PXP_PS_CTRL (0x000000b0)
+#define HW_PXP_PS_CTRL_SET (0x000000b4)
+#define HW_PXP_PS_CTRL_CLR (0x000000b8)
+#define HW_PXP_PS_CTRL_TOG (0x000000bc)
+
+#define BP_PXP_PS_CTRL_RSVD1 12
+#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000
+#define BF_PXP_PS_CTRL_RSVD1(v) \
+ (((v) << 12) & BM_PXP_PS_CTRL_RSVD1)
+#define BP_PXP_PS_CTRL_DECX 10
+#define BM_PXP_PS_CTRL_DECX 0x00000C00
+#define BF_PXP_PS_CTRL_DECX(v) \
+ (((v) << 10) & BM_PXP_PS_CTRL_DECX)
+#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECX__DECX2 0x1
+#define BV_PXP_PS_CTRL_DECX__DECX4 0x2
+#define BV_PXP_PS_CTRL_DECX__DECX8 0x3
+#define BP_PXP_PS_CTRL_DECY 8
+#define BM_PXP_PS_CTRL_DECY 0x00000300
+#define BF_PXP_PS_CTRL_DECY(v) \
+ (((v) << 8) & BM_PXP_PS_CTRL_DECY)
+#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECY__DECY2 0x1
+#define BV_PXP_PS_CTRL_DECY__DECY4 0x2
+#define BV_PXP_PS_CTRL_DECY__DECY8 0x3
+#define BM_PXP_PS_CTRL_RSVD0 0x00000080
+#define BF_PXP_PS_CTRL_RSVD0(v) \
+ (((v) << 7) & BM_PXP_PS_CTRL_RSVD0)
+#define BM_PXP_PS_CTRL_WB_SWAP 0x00000040
+#define BF_PXP_PS_CTRL_WB_SWAP(v) \
+ (((v) << 6) & BM_PXP_PS_CTRL_WB_SWAP)
+#define BP_PXP_PS_CTRL_FORMAT 0
+#define BM_PXP_PS_CTRL_FORMAT 0x0000003F
+#define BF_PXP_PS_CTRL_FORMAT(v) \
+ (((v) << 0) & BM_PXP_PS_CTRL_FORMAT)
+#define BV_PXP_PS_CTRL_FORMAT__RGB888 0x4
+#define BV_PXP_PS_CTRL_FORMAT__RGB555 0xC
+#define BV_PXP_PS_CTRL_FORMAT__RGB444 0xD
+#define BV_PXP_PS_CTRL_FORMAT__RGB565 0xE
+#define BV_PXP_PS_CTRL_FORMAT__YUV1P444 0x10
+#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_PS_CTRL_FORMAT__Y8 0x14
+#define BV_PXP_PS_CTRL_FORMAT__Y4 0x15
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P422 0x18
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P420 0x19
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P422 0x1A
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P420 0x1B
+#define BV_PXP_PS_CTRL_FORMAT__YUV422 0x1E
+#define BV_PXP_PS_CTRL_FORMAT__YUV420 0x1F
+
+#define HW_PXP_PS_BUF (0x000000c0)
+
+#define BP_PXP_PS_BUF_ADDR 0
+#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_BUF_ADDR(v) (v)
+
+#define HW_PXP_PS_UBUF (0x000000d0)
+
+#define BP_PXP_PS_UBUF_ADDR 0
+#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_UBUF_ADDR(v) (v)
+
+#define HW_PXP_PS_VBUF (0x000000e0)
+
+#define BP_PXP_PS_VBUF_ADDR 0
+#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_VBUF_ADDR(v) (v)
+
+#define HW_PXP_PS_PITCH (0x000000f0)
+
+#define BP_PXP_PS_PITCH_RSVD 16
+#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_PS_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_PS_PITCH_RSVD)
+#define BP_PXP_PS_PITCH_PITCH 0
+#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_PS_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_PS_PITCH_PITCH)
+
+#define HW_PXP_PS_BACKGROUND_0 (0x00000100)
+
+#define BP_PXP_PS_BACKGROUND_0_RSVD 24
+#define BM_PXP_PS_BACKGROUND_0_RSVD 0xFF000000
+#define BF_PXP_PS_BACKGROUND_0_RSVD(v) \
+ (((v) << 24) & BM_PXP_PS_BACKGROUND_0_RSVD)
+#define BP_PXP_PS_BACKGROUND_0_COLOR 0
+#define BM_PXP_PS_BACKGROUND_0_COLOR 0x00FFFFFF
+#define BF_PXP_PS_BACKGROUND_0_COLOR(v) \
+ (((v) << 0) & BM_PXP_PS_BACKGROUND_0_COLOR)
+
+#define HW_PXP_PS_SCALE (0x00000110)
+
+#define BM_PXP_PS_SCALE_RSVD2 0x80000000
+#define BF_PXP_PS_SCALE_RSVD2(v) \
+ (((v) << 31) & BM_PXP_PS_SCALE_RSVD2)
+#define BP_PXP_PS_SCALE_YSCALE 16
+#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000
+#define BF_PXP_PS_SCALE_YSCALE(v) \
+ (((v) << 16) & BM_PXP_PS_SCALE_YSCALE)
+#define BM_PXP_PS_SCALE_RSVD1 0x00008000
+#define BF_PXP_PS_SCALE_RSVD1(v) \
+ (((v) << 15) & BM_PXP_PS_SCALE_RSVD1)
+#define BP_PXP_PS_SCALE_XSCALE 0
+#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF
+#define BF_PXP_PS_SCALE_XSCALE(v) \
+ (((v) << 0) & BM_PXP_PS_SCALE_XSCALE)
+
+#define HW_PXP_PS_OFFSET (0x00000120)
+
+#define BP_PXP_PS_OFFSET_RSVD2 28
+#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000
+#define BF_PXP_PS_OFFSET_RSVD2(v) \
+ (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2)
+#define BP_PXP_PS_OFFSET_YOFFSET 16
+#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000
+#define BF_PXP_PS_OFFSET_YOFFSET(v) \
+ (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET)
+#define BP_PXP_PS_OFFSET_RSVD1 12
+#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000
+#define BF_PXP_PS_OFFSET_RSVD1(v) \
+ (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1)
+#define BP_PXP_PS_OFFSET_XOFFSET 0
+#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF
+#define BF_PXP_PS_OFFSET_XOFFSET(v) \
+ (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET)
+
+#define HW_PXP_PS_CLRKEYLOW_0 (0x00000130)
+
+#define BP_PXP_PS_CLRKEYLOW_0_RSVD1 24
+#define BM_PXP_PS_CLRKEYLOW_0_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYLOW_0_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYLOW_0_RSVD1)
+#define BP_PXP_PS_CLRKEYLOW_0_PIXEL 0
+#define BM_PXP_PS_CLRKEYLOW_0_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYLOW_0_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYLOW_0_PIXEL)
+
+#define HW_PXP_PS_CLRKEYHIGH_0 (0x00000140)
+
+#define BP_PXP_PS_CLRKEYHIGH_0_RSVD1 24
+#define BM_PXP_PS_CLRKEYHIGH_0_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYHIGH_0_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_0_RSVD1)
+#define BP_PXP_PS_CLRKEYHIGH_0_PIXEL 0
+#define BM_PXP_PS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYHIGH_0_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_0_PIXEL)
+
+#define HW_PXP_AS_CTRL (0x00000150)
+
+#define BP_PXP_AS_CTRL_RSVD1 22
+#define BM_PXP_AS_CTRL_RSVD1 0xFFC00000
+#define BF_PXP_AS_CTRL_RSVD1(v) \
+ (((v) << 22) & BM_PXP_AS_CTRL_RSVD1)
+#define BM_PXP_AS_CTRL_ALPHA1_INVERT 0x00200000
+#define BF_PXP_AS_CTRL_ALPHA1_INVERT(v) \
+ (((v) << 21) & BM_PXP_AS_CTRL_ALPHA1_INVERT)
+#define BM_PXP_AS_CTRL_ALPHA0_INVERT 0x00100000
+#define BF_PXP_AS_CTRL_ALPHA0_INVERT(v) \
+ (((v) << 20) & BM_PXP_AS_CTRL_ALPHA0_INVERT)
+#define BP_PXP_AS_CTRL_ROP 16
+#define BM_PXP_AS_CTRL_ROP 0x000F0000
+#define BF_PXP_AS_CTRL_ROP(v) \
+ (((v) << 16) & BM_PXP_AS_CTRL_ROP)
+#define BV_PXP_AS_CTRL_ROP__MASKAS 0x0
+#define BV_PXP_AS_CTRL_ROP__MASKNOTAS 0x1
+#define BV_PXP_AS_CTRL_ROP__MASKASNOT 0x2
+#define BV_PXP_AS_CTRL_ROP__MERGEAS 0x3
+#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4
+#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5
+#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS 0x6
+#define BV_PXP_AS_CTRL_ROP__NOT 0x7
+#define BV_PXP_AS_CTRL_ROP__NOTMASKAS 0x8
+#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9
+#define BV_PXP_AS_CTRL_ROP__XORAS 0xA
+#define BV_PXP_AS_CTRL_ROP__NOTXORAS 0xB
+#define BP_PXP_AS_CTRL_ALPHA 8
+#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00
+#define BF_PXP_AS_CTRL_ALPHA(v) \
+ (((v) << 8) & BM_PXP_AS_CTRL_ALPHA)
+#define BP_PXP_AS_CTRL_FORMAT 4
+#define BM_PXP_AS_CTRL_FORMAT 0x000000F0
+#define BF_PXP_AS_CTRL_FORMAT(v) \
+ (((v) << 4) & BM_PXP_AS_CTRL_FORMAT)
+#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0
+#define BV_PXP_AS_CTRL_FORMAT__RGBA8888 0x1
+#define BV_PXP_AS_CTRL_FORMAT__RGB888 0x4
+#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8
+#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9
+#define BV_PXP_AS_CTRL_FORMAT__RGB555 0xC
+#define BV_PXP_AS_CTRL_FORMAT__RGB444 0xD
+#define BV_PXP_AS_CTRL_FORMAT__RGB565 0xE
+#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008
+#define BF_PXP_AS_CTRL_ENABLE_COLORKEY(v) \
+ (((v) << 3) & BM_PXP_AS_CTRL_ENABLE_COLORKEY)
+#define BP_PXP_AS_CTRL_ALPHA_CTRL 1
+#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006
+#define BF_PXP_AS_CTRL_ALPHA_CTRL(v) \
+ (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL)
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs 0x3
+#define BM_PXP_AS_CTRL_RSVD0 0x00000001
+#define BF_PXP_AS_CTRL_RSVD0(v) \
+ (((v) << 0) & BM_PXP_AS_CTRL_RSVD0)
+
+#define HW_PXP_AS_BUF (0x00000160)
+
+#define BP_PXP_AS_BUF_ADDR 0
+#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_AS_BUF_ADDR(v) (v)
+
+#define HW_PXP_AS_PITCH (0x00000170)
+
+#define BP_PXP_AS_PITCH_RSVD 16
+#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_AS_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_AS_PITCH_RSVD)
+#define BP_PXP_AS_PITCH_PITCH 0
+#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_AS_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_AS_PITCH_PITCH)
+
+#define HW_PXP_AS_CLRKEYLOW_0 (0x00000180)
+
+#define BP_PXP_AS_CLRKEYLOW_0_RSVD1 24
+#define BM_PXP_AS_CLRKEYLOW_0_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYLOW_0_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYLOW_0_RSVD1)
+#define BP_PXP_AS_CLRKEYLOW_0_PIXEL 0
+#define BM_PXP_AS_CLRKEYLOW_0_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYLOW_0_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYLOW_0_PIXEL)
+
+#define HW_PXP_AS_CLRKEYHIGH_0 (0x00000190)
+
+#define BP_PXP_AS_CLRKEYHIGH_0_RSVD1 24
+#define BM_PXP_AS_CLRKEYHIGH_0_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYHIGH_0_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_0_RSVD1)
+#define BP_PXP_AS_CLRKEYHIGH_0_PIXEL 0
+#define BM_PXP_AS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYHIGH_0_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_0_PIXEL)
+
+#define HW_PXP_CSC1_COEF0 (0x000001a0)
+
+#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000
+#define BF_PXP_CSC1_COEF0_YCBCR_MODE(v) \
+ (((v) << 31) & BM_PXP_CSC1_COEF0_YCBCR_MODE)
+#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000
+#define BF_PXP_CSC1_COEF0_BYPASS(v) \
+ (((v) << 30) & BM_PXP_CSC1_COEF0_BYPASS)
+#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000
+#define BF_PXP_CSC1_COEF0_RSVD1(v) \
+ (((v) << 29) & BM_PXP_CSC1_COEF0_RSVD1)
+#define BP_PXP_CSC1_COEF0_C0 18
+#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000
+#define BF_PXP_CSC1_COEF0_C0(v) \
+ (((v) << 18) & BM_PXP_CSC1_COEF0_C0)
+#define BP_PXP_CSC1_COEF0_UV_OFFSET 9
+#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00
+#define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \
+ (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET)
+#define BP_PXP_CSC1_COEF0_Y_OFFSET 0
+#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF
+#define BF_PXP_CSC1_COEF0_Y_OFFSET(v) \
+ (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET)
+
+#define HW_PXP_CSC1_COEF1 (0x000001b0)
+
+#define BP_PXP_CSC1_COEF1_RSVD1 27
+#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF1_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1)
+#define BP_PXP_CSC1_COEF1_C1 16
+#define BM_PXP_CSC1_COEF1_C1 0x07FF0000
+#define BF_PXP_CSC1_COEF1_C1(v) \
+ (((v) << 16) & BM_PXP_CSC1_COEF1_C1)
+#define BP_PXP_CSC1_COEF1_RSVD0 11
+#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF1_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0)
+#define BP_PXP_CSC1_COEF1_C4 0
+#define BM_PXP_CSC1_COEF1_C4 0x000007FF
+#define BF_PXP_CSC1_COEF1_C4(v) \
+ (((v) << 0) & BM_PXP_CSC1_COEF1_C4)
+
+#define HW_PXP_CSC1_COEF2 (0x000001c0)
+
+#define BP_PXP_CSC1_COEF2_RSVD1 27
+#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF2_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1)
+#define BP_PXP_CSC1_COEF2_C2 16
+#define BM_PXP_CSC1_COEF2_C2 0x07FF0000
+#define BF_PXP_CSC1_COEF2_C2(v) \
+ (((v) << 16) & BM_PXP_CSC1_COEF2_C2)
+#define BP_PXP_CSC1_COEF2_RSVD0 11
+#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF2_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0)
+#define BP_PXP_CSC1_COEF2_C3 0
+#define BM_PXP_CSC1_COEF2_C3 0x000007FF
+#define BF_PXP_CSC1_COEF2_C3(v) \
+ (((v) << 0) & BM_PXP_CSC1_COEF2_C3)
+
+#define HW_PXP_CSC2_CTRL (0x000001d0)
+
+#define BP_PXP_CSC2_CTRL_RSVD 3
+#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8
+#define BF_PXP_CSC2_CTRL_RSVD(v) \
+ (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD)
+#define BP_PXP_CSC2_CTRL_CSC_MODE 1
+#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006
+#define BF_PXP_CSC2_CTRL_CSC_MODE(v) \
+ (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE)
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB 0x0
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV 0x2
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3
+#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001
+#define BF_PXP_CSC2_CTRL_BYPASS(v) \
+ (((v) << 0) & BM_PXP_CSC2_CTRL_BYPASS)
+
+#define HW_PXP_CSC2_COEF0 (0x000001e0)
+
+#define BP_PXP_CSC2_COEF0_RSVD1 27
+#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF0_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1)
+#define BP_PXP_CSC2_COEF0_A2 16
+#define BM_PXP_CSC2_COEF0_A2 0x07FF0000
+#define BF_PXP_CSC2_COEF0_A2(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF0_A2)
+#define BP_PXP_CSC2_COEF0_RSVD0 11
+#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF0_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0)
+#define BP_PXP_CSC2_COEF0_A1 0
+#define BM_PXP_CSC2_COEF0_A1 0x000007FF
+#define BF_PXP_CSC2_COEF0_A1(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF0_A1)
+
+#define HW_PXP_CSC2_COEF1 (0x000001f0)
+
+#define BP_PXP_CSC2_COEF1_RSVD1 27
+#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF1_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1)
+#define BP_PXP_CSC2_COEF1_B1 16
+#define BM_PXP_CSC2_COEF1_B1 0x07FF0000
+#define BF_PXP_CSC2_COEF1_B1(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF1_B1)
+#define BP_PXP_CSC2_COEF1_RSVD0 11
+#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF1_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0)
+#define BP_PXP_CSC2_COEF1_A3 0
+#define BM_PXP_CSC2_COEF1_A3 0x000007FF
+#define BF_PXP_CSC2_COEF1_A3(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF1_A3)
+
+#define HW_PXP_CSC2_COEF2 (0x00000200)
+
+#define BP_PXP_CSC2_COEF2_RSVD1 27
+#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF2_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1)
+#define BP_PXP_CSC2_COEF2_B3 16
+#define BM_PXP_CSC2_COEF2_B3 0x07FF0000
+#define BF_PXP_CSC2_COEF2_B3(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF2_B3)
+#define BP_PXP_CSC2_COEF2_RSVD0 11
+#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF2_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0)
+#define BP_PXP_CSC2_COEF2_B2 0
+#define BM_PXP_CSC2_COEF2_B2 0x000007FF
+#define BF_PXP_CSC2_COEF2_B2(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF2_B2)
+
+#define HW_PXP_CSC2_COEF3 (0x00000210)
+
+#define BP_PXP_CSC2_COEF3_RSVD1 27
+#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF3_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1)
+#define BP_PXP_CSC2_COEF3_C2 16
+#define BM_PXP_CSC2_COEF3_C2 0x07FF0000
+#define BF_PXP_CSC2_COEF3_C2(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF3_C2)
+#define BP_PXP_CSC2_COEF3_RSVD0 11
+#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF3_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0)
+#define BP_PXP_CSC2_COEF3_C1 0
+#define BM_PXP_CSC2_COEF3_C1 0x000007FF
+#define BF_PXP_CSC2_COEF3_C1(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF3_C1)
+
+#define HW_PXP_CSC2_COEF4 (0x00000220)
+
+#define BP_PXP_CSC2_COEF4_RSVD1 25
+#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF4_RSVD1(v) \
+ (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1)
+#define BP_PXP_CSC2_COEF4_D1 16
+#define BM_PXP_CSC2_COEF4_D1 0x01FF0000
+#define BF_PXP_CSC2_COEF4_D1(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF4_D1)
+#define BP_PXP_CSC2_COEF4_RSVD0 11
+#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF4_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0)
+#define BP_PXP_CSC2_COEF4_C3 0
+#define BM_PXP_CSC2_COEF4_C3 0x000007FF
+#define BF_PXP_CSC2_COEF4_C3(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF4_C3)
+
+#define HW_PXP_CSC2_COEF5 (0x00000230)
+
+#define BP_PXP_CSC2_COEF5_RSVD1 25
+#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF5_RSVD1(v) \
+ (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1)
+#define BP_PXP_CSC2_COEF5_D3 16
+#define BM_PXP_CSC2_COEF5_D3 0x01FF0000
+#define BF_PXP_CSC2_COEF5_D3(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF5_D3)
+#define BP_PXP_CSC2_COEF5_RSVD0 9
+#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00
+#define BF_PXP_CSC2_COEF5_RSVD0(v) \
+ (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0)
+#define BP_PXP_CSC2_COEF5_D2 0
+#define BM_PXP_CSC2_COEF5_D2 0x000001FF
+#define BF_PXP_CSC2_COEF5_D2(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF5_D2)
+
+#define HW_PXP_LUT_CTRL (0x00000240)
+
+#define BM_PXP_LUT_CTRL_BYPASS 0x80000000
+#define BF_PXP_LUT_CTRL_BYPASS(v) \
+ (((v) << 31) & BM_PXP_LUT_CTRL_BYPASS)
+#define BP_PXP_LUT_CTRL_RSVD3 26
+#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000
+#define BF_PXP_LUT_CTRL_RSVD3(v) \
+ (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3)
+#define BP_PXP_LUT_CTRL_LOOKUP_MODE 24
+#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000
+#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v) \
+ (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE)
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565 0x0
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8 0x1
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3
+#define BP_PXP_LUT_CTRL_RSVD2 18
+#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000
+#define BF_PXP_LUT_CTRL_RSVD2(v) \
+ (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2)
+#define BP_PXP_LUT_CTRL_OUT_MODE 16
+#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000
+#define BF_PXP_LUT_CTRL_OUT_MODE(v) \
+ (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE)
+#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED 0x0
+#define BV_PXP_LUT_CTRL_OUT_MODE__Y8 0x1
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888 0x3
+#define BP_PXP_LUT_CTRL_RSVD1 11
+#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800
+#define BF_PXP_LUT_CTRL_RSVD1(v) \
+ (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1)
+#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400
+#define BF_PXP_LUT_CTRL_SEL_8KB(v) \
+ (((v) << 10) & BM_PXP_LUT_CTRL_SEL_8KB)
+#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200
+#define BF_PXP_LUT_CTRL_LRU_UPD(v) \
+ (((v) << 9) & BM_PXP_LUT_CTRL_LRU_UPD)
+#define BM_PXP_LUT_CTRL_INVALID 0x00000100
+#define BF_PXP_LUT_CTRL_INVALID(v) \
+ (((v) << 8) & BM_PXP_LUT_CTRL_INVALID)
+#define BP_PXP_LUT_CTRL_RSVD0 1
+#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE
+#define BF_PXP_LUT_CTRL_RSVD0(v) \
+ (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0)
+#define BM_PXP_LUT_CTRL_DMA_START 0x00000001
+#define BF_PXP_LUT_CTRL_DMA_START(v) \
+ (((v) << 0) & BM_PXP_LUT_CTRL_DMA_START)
+
+#define HW_PXP_LUT_ADDR (0x00000250)
+
+#define BM_PXP_LUT_ADDR_RSVD2 0x80000000
+#define BF_PXP_LUT_ADDR_RSVD2(v) \
+ (((v) << 31) & BM_PXP_LUT_ADDR_RSVD2)
+#define BP_PXP_LUT_ADDR_NUM_BYTES 16
+#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000
+#define BF_PXP_LUT_ADDR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES)
+#define BP_PXP_LUT_ADDR_RSVD1 14
+#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000
+#define BF_PXP_LUT_ADDR_RSVD1(v) \
+ (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1)
+#define BP_PXP_LUT_ADDR_ADDR 0
+#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF
+#define BF_PXP_LUT_ADDR_ADDR(v) \
+ (((v) << 0) & BM_PXP_LUT_ADDR_ADDR)
+
+#define HW_PXP_LUT_DATA (0x00000260)
+
+#define BP_PXP_LUT_DATA_DATA 0
+#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF
+#define BF_PXP_LUT_DATA_DATA(v) (v)
+
+#define HW_PXP_LUT_EXTMEM (0x00000270)
+
+#define BP_PXP_LUT_EXTMEM_ADDR 0
+#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF
+#define BF_PXP_LUT_EXTMEM_ADDR(v) (v)
+
+#define HW_PXP_CFA (0x00000280)
+
+#define BP_PXP_CFA_DATA 0
+#define BM_PXP_CFA_DATA 0xFFFFFFFF
+#define BF_PXP_CFA_DATA(v) (v)
+
+#define HW_PXP_ALPHA_A_CTRL (0x00000290)
+
+#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA 24
+#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA 0xFF000000
+#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA(v) \
+ (((v) << 24) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA 16
+#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA 0x00FF0000
+#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA(v) \
+ (((v) << 16) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_A_CTRL_RSVD0 14
+#define BM_PXP_ALPHA_A_CTRL_RSVD0 0x0000C000
+#define BF_PXP_ALPHA_A_CTRL_RSVD0(v) \
+ (((v) << 14) & BM_PXP_ALPHA_A_CTRL_RSVD0)
+#define BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE 0x00002000
+#define BF_PXP_ALPHA_A_CTRL_S1_COLOR_MODE(v) \
+ (((v) << 13) & BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE 0x00001000
+#define BF_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE(v) \
+ (((v) << 12) & BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE 10
+#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00
+#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE(v) \
+ (((v) << 10) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x0
+#define BP_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE 8
+#define BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE 0x00000300
+#define BF_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE(v) \
+ (((v) << 8) & BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_A_CTRL_RSVD1 0x00000080
+#define BF_PXP_ALPHA_A_CTRL_RSVD1(v) \
+ (((v) << 7) & BM_PXP_ALPHA_A_CTRL_RSVD1)
+#define BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE 0x00000040
+#define BF_PXP_ALPHA_A_CTRL_S0_COLOR_MODE(v) \
+ (((v) << 6) & BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE 0x00000020
+#define BF_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE(v) \
+ (((v) << 5) & BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE 3
+#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018
+#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE(v) \
+ (((v) << 3) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3
+#define BP_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE 1
+#define BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE 0x00000006
+#define BF_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE(v) \
+ (((v) << 1) & BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE 0x00000001
+#define BF_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE(v) \
+ (((v) << 0) & BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE)
+#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__1 0x1
+
+#define HW_PXP_ALPHA_B_CTRL (0x000002a0)
+
+#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA 24
+#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA 0xFF000000
+#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA(v) \
+ (((v) << 24) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA 16
+#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA 0x00FF0000
+#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA(v) \
+ (((v) << 16) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_B_CTRL_RSVD0 14
+#define BM_PXP_ALPHA_B_CTRL_RSVD0 0x0000C000
+#define BF_PXP_ALPHA_B_CTRL_RSVD0(v) \
+ (((v) << 14) & BM_PXP_ALPHA_B_CTRL_RSVD0)
+#define BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE 0x00002000
+#define BF_PXP_ALPHA_B_CTRL_S1_COLOR_MODE(v) \
+ (((v) << 13) & BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE 0x00001000
+#define BF_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE(v) \
+ (((v) << 12) & BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE 10
+#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00
+#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE(v) \
+ (((v) << 10) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x3
+#define BP_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE 8
+#define BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE 0x00000300
+#define BF_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE(v) \
+ (((v) << 8) & BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_B_CTRL_RSVD1 0x00000080
+#define BF_PXP_ALPHA_B_CTRL_RSVD1(v) \
+ (((v) << 7) & BM_PXP_ALPHA_B_CTRL_RSVD1)
+#define BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE 0x00000040
+#define BF_PXP_ALPHA_B_CTRL_S0_COLOR_MODE(v) \
+ (((v) << 6) & BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE 0x00000020
+#define BF_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE(v) \
+ (((v) << 5) & BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE 3
+#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018
+#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE(v) \
+ (((v) << 3) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3
+#define BP_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE 1
+#define BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE 0x00000006
+#define BF_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE(v) \
+ (((v) << 1) & BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE 0x00000001
+#define BF_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE(v) \
+ (((v) << 0) & BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE)
+#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__1 0x1
+
+#define HW_PXP_ALPHA_B_CTRL_1 (0x000002b0)
+
+#define BP_PXP_ALPHA_B_CTRL_1_RSVD0 8
+#define BM_PXP_ALPHA_B_CTRL_1_RSVD0 0xFFFFFF00
+#define BF_PXP_ALPHA_B_CTRL_1_RSVD0(v) \
+ (((v) << 8) & BM_PXP_ALPHA_B_CTRL_1_RSVD0)
+#define BP_PXP_ALPHA_B_CTRL_1_ROP 4
+#define BM_PXP_ALPHA_B_CTRL_1_ROP 0x000000F0
+#define BF_PXP_ALPHA_B_CTRL_1_ROP(v) \
+ (((v) << 4) & BM_PXP_ALPHA_B_CTRL_1_ROP)
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKAS 0x0
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKNOTAS 0x1
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKASNOT 0x2
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEAS 0x3
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGENOTAS 0x4
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEASNOT 0x5
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTCOPYAS 0x6
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOT 0x7
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMASKAS 0x8
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMERGEAS 0x9
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__XORAS 0xA
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTXORAS 0xB
+#define BP_PXP_ALPHA_B_CTRL_1_RSVD1 2
+#define BM_PXP_ALPHA_B_CTRL_1_RSVD1 0x0000000C
+#define BF_PXP_ALPHA_B_CTRL_1_RSVD1(v) \
+ (((v) << 2) & BM_PXP_ALPHA_B_CTRL_1_RSVD1)
+#define BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE 0x00000002
+#define BF_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE(v) \
+ (((v) << 1) & BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE)
+#define BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE 0x00000001
+#define BF_PXP_ALPHA_B_CTRL_1_ROP_ENABLE(v) \
+ (((v) << 0) & BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE)
+
+#define HW_PXP_PS_BACKGROUND_1 (0x000002c0)
+
+#define BP_PXP_PS_BACKGROUND_1_RSVD 24
+#define BM_PXP_PS_BACKGROUND_1_RSVD 0xFF000000
+#define BF_PXP_PS_BACKGROUND_1_RSVD(v) \
+ (((v) << 24) & BM_PXP_PS_BACKGROUND_1_RSVD)
+#define BP_PXP_PS_BACKGROUND_1_COLOR 0
+#define BM_PXP_PS_BACKGROUND_1_COLOR 0x00FFFFFF
+#define BF_PXP_PS_BACKGROUND_1_COLOR(v) \
+ (((v) << 0) & BM_PXP_PS_BACKGROUND_1_COLOR)
+
+#define HW_PXP_PS_CLRKEYLOW_1 (0x000002d0)
+
+#define BP_PXP_PS_CLRKEYLOW_1_RSVD1 24
+#define BM_PXP_PS_CLRKEYLOW_1_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYLOW_1_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYLOW_1_RSVD1)
+#define BP_PXP_PS_CLRKEYLOW_1_PIXEL 0
+#define BM_PXP_PS_CLRKEYLOW_1_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYLOW_1_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYLOW_1_PIXEL)
+
+#define HW_PXP_PS_CLRKEYHIGH_1 (0x000002e0)
+
+#define BP_PXP_PS_CLRKEYHIGH_1_RSVD1 24
+#define BM_PXP_PS_CLRKEYHIGH_1_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYHIGH_1_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_1_RSVD1)
+#define BP_PXP_PS_CLRKEYHIGH_1_PIXEL 0
+#define BM_PXP_PS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYHIGH_1_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_1_PIXEL)
+
+#define HW_PXP_AS_CLRKEYLOW_1 (0x000002f0)
+
+#define BP_PXP_AS_CLRKEYLOW_1_RSVD1 24
+#define BM_PXP_AS_CLRKEYLOW_1_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYLOW_1_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYLOW_1_RSVD1)
+#define BP_PXP_AS_CLRKEYLOW_1_PIXEL 0
+#define BM_PXP_AS_CLRKEYLOW_1_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYLOW_1_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYLOW_1_PIXEL)
+
+#define HW_PXP_AS_CLRKEYHIGH_1 (0x00000300)
+
+#define BP_PXP_AS_CLRKEYHIGH_1_RSVD1 24
+#define BM_PXP_AS_CLRKEYHIGH_1_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYHIGH_1_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_1_RSVD1)
+#define BP_PXP_AS_CLRKEYHIGH_1_PIXEL 0
+#define BM_PXP_AS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYHIGH_1_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_1_PIXEL)
+
+#define HW_PXP_CTRL2 (0x00000310)
+#define HW_PXP_CTRL2_SET (0x00000314)
+#define HW_PXP_CTRL2_CLR (0x00000318)
+#define HW_PXP_CTRL2_TOG (0x0000031c)
+
+#define BP_PXP_CTRL2_RSVD3 28
+#define BM_PXP_CTRL2_RSVD3 0xF0000000
+#define BF_PXP_CTRL2_RSVD3(v) \
+ (((v) << 28) & BM_PXP_CTRL2_RSVD3)
+#define BM_PXP_CTRL2_ENABLE_ROTATE1 0x08000000
+#define BF_PXP_CTRL2_ENABLE_ROTATE1(v) \
+ (((v) << 27) & BM_PXP_CTRL2_ENABLE_ROTATE1)
+#define BM_PXP_CTRL2_ENABLE_ROTATE0 0x04000000
+#define BF_PXP_CTRL2_ENABLE_ROTATE0(v) \
+ (((v) << 26) & BM_PXP_CTRL2_ENABLE_ROTATE0)
+#define BM_PXP_CTRL2_ENABLE_LUT 0x02000000
+#define BF_PXP_CTRL2_ENABLE_LUT(v) \
+ (((v) << 25) & BM_PXP_CTRL2_ENABLE_LUT)
+#define BM_PXP_CTRL2_ENABLE_CSC2 0x01000000
+#define BF_PXP_CTRL2_ENABLE_CSC2(v) \
+ (((v) << 24) & BM_PXP_CTRL2_ENABLE_CSC2)
+#define BM_PXP_CTRL2_BLOCK_SIZE 0x00800000
+#define BF_PXP_CTRL2_BLOCK_SIZE(v) \
+ (((v) << 23) & BM_PXP_CTRL2_BLOCK_SIZE)
+#define BV_PXP_CTRL2_BLOCK_SIZE__8X8 0x0
+#define BV_PXP_CTRL2_BLOCK_SIZE__16X16 0x1
+#define BM_PXP_CTRL2_RSVD2 0x00400000
+#define BF_PXP_CTRL2_RSVD2(v) \
+ (((v) << 22) & BM_PXP_CTRL2_RSVD2)
+#define BM_PXP_CTRL2_ENABLE_ALPHA_B 0x00200000
+#define BF_PXP_CTRL2_ENABLE_ALPHA_B(v) \
+ (((v) << 21) & BM_PXP_CTRL2_ENABLE_ALPHA_B)
+#define BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE 0x00100000
+#define BF_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE(v) \
+ (((v) << 20) & BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE)
+#define BM_PXP_CTRL2_ENABLE_WFE_B 0x00080000
+#define BF_PXP_CTRL2_ENABLE_WFE_B(v) \
+ (((v) << 19) & BM_PXP_CTRL2_ENABLE_WFE_B)
+#define BM_PXP_CTRL2_ENABLE_WFE_A 0x00040000
+#define BF_PXP_CTRL2_ENABLE_WFE_A(v) \
+ (((v) << 18) & BM_PXP_CTRL2_ENABLE_WFE_A)
+#define BM_PXP_CTRL2_ENABLE_DITHER 0x00020000
+#define BF_PXP_CTRL2_ENABLE_DITHER(v) \
+ (((v) << 17) & BM_PXP_CTRL2_ENABLE_DITHER)
+#define BM_PXP_CTRL2_RSVD1 0x00010000
+#define BF_PXP_CTRL2_RSVD1(v) \
+ (((v) << 16) & BM_PXP_CTRL2_RSVD1)
+#define BM_PXP_CTRL2_VFLIP1 0x00008000
+#define BF_PXP_CTRL2_VFLIP1(v) \
+ (((v) << 15) & BM_PXP_CTRL2_VFLIP1)
+#define BM_PXP_CTRL2_HFLIP1 0x00004000
+#define BF_PXP_CTRL2_HFLIP1(v) \
+ (((v) << 14) & BM_PXP_CTRL2_HFLIP1)
+#define BP_PXP_CTRL2_ROTATE1 12
+#define BM_PXP_CTRL2_ROTATE1 0x00003000
+#define BF_PXP_CTRL2_ROTATE1(v) \
+ (((v) << 12) & BM_PXP_CTRL2_ROTATE1)
+#define BV_PXP_CTRL2_ROTATE1__ROT_0 0x0
+#define BV_PXP_CTRL2_ROTATE1__ROT_90 0x1
+#define BV_PXP_CTRL2_ROTATE1__ROT_180 0x2
+#define BV_PXP_CTRL2_ROTATE1__ROT_270 0x3
+#define BM_PXP_CTRL2_VFLIP0 0x00000800
+#define BF_PXP_CTRL2_VFLIP0(v) \
+ (((v) << 11) & BM_PXP_CTRL2_VFLIP0)
+#define BM_PXP_CTRL2_HFLIP0 0x00000400
+#define BF_PXP_CTRL2_HFLIP0(v) \
+ (((v) << 10) & BM_PXP_CTRL2_HFLIP0)
+#define BP_PXP_CTRL2_ROTATE0 8
+#define BM_PXP_CTRL2_ROTATE0 0x00000300
+#define BF_PXP_CTRL2_ROTATE0(v) \
+ (((v) << 8) & BM_PXP_CTRL2_ROTATE0)
+#define BV_PXP_CTRL2_ROTATE0__ROT_0 0x0
+#define BV_PXP_CTRL2_ROTATE0__ROT_90 0x1
+#define BV_PXP_CTRL2_ROTATE0__ROT_180 0x2
+#define BV_PXP_CTRL2_ROTATE0__ROT_270 0x3
+#define BP_PXP_CTRL2_RSVD0 1
+#define BM_PXP_CTRL2_RSVD0 0x000000FE
+#define BF_PXP_CTRL2_RSVD0(v) \
+ (((v) << 1) & BM_PXP_CTRL2_RSVD0)
+#define BM_PXP_CTRL2_ENABLE 0x00000001
+#define BF_PXP_CTRL2_ENABLE(v) \
+ (((v) << 0) & BM_PXP_CTRL2_ENABLE)
+
+#define HW_PXP_POWER_REG0 (0x00000320)
+
+#define BP_PXP_POWER_REG0_CTRL 12
+#define BM_PXP_POWER_REG0_CTRL 0xFFFFF000
+#define BF_PXP_POWER_REG0_CTRL(v) \
+ (((v) << 12) & BM_PXP_POWER_REG0_CTRL)
+#define BP_PXP_POWER_REG0_ROT0_MEM_LP_STATE 9
+#define BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE 0x00000E00
+#define BF_PXP_POWER_REG0_ROT0_MEM_LP_STATE(v) \
+ (((v) << 9) & BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE)
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN 6
+#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN 0x000001C0
+#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN(v) \
+ (((v) << 6) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN)
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__NONE 0x0
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__LS 0x1
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__DS 0x2
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__SD 0x4
+#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN 3
+#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN 0x00000038
+#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN(v) \
+ (((v) << 3) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN)
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__NONE 0x0
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__LS 0x1
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__DS 0x2
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__SD 0x4
+#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0 0
+#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0 0x00000007
+#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0(v) \
+ (((v) << 0) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0)
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__NONE 0x0
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__LS 0x1
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__DS 0x2
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__SD 0x4
+
+#define HW_PXP_POWER_REG1 (0x00000330)
+
+#define BP_PXP_POWER_REG1_RSVD0 24
+#define BM_PXP_POWER_REG1_RSVD0 0xFF000000
+#define BF_PXP_POWER_REG1_RSVD0(v) \
+ (((v) << 24) & BM_PXP_POWER_REG1_RSVD0)
+#define BP_PXP_POWER_REG1_ALU_B_MEM_LP_STATE 21
+#define BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE 0x00E00000
+#define BF_PXP_POWER_REG1_ALU_B_MEM_LP_STATE(v) \
+ (((v) << 21) & BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_ALU_A_MEM_LP_STATE 18
+#define BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE 0x001C0000
+#define BF_PXP_POWER_REG1_ALU_A_MEM_LP_STATE(v) \
+ (((v) << 18) & BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE 15
+#define BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE 0x00038000
+#define BF_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE(v) \
+ (((v) << 15) & BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE 12
+#define BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE 0x00007000
+#define BF_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE(v) \
+ (((v) << 12) & BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE 9
+#define BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE 0x00000E00
+#define BF_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE(v) \
+ (((v) << 9) & BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE 6
+#define BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE 0x000001C0
+#define BF_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE(v) \
+ (((v) << 6) & BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE 3
+#define BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE 0x00000038
+#define BF_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE(v) \
+ (((v) << 3) & BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_ROT1_MEM_LP_STATE 0
+#define BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE 0x00000007
+#define BF_PXP_POWER_REG1_ROT1_MEM_LP_STATE(v) \
+ (((v) << 0) & BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__SD 0x4
+
+#define HW_PXP_DATA_PATH_CTRL0 (0x00000340)
+#define HW_PXP_DATA_PATH_CTRL0_SET (0x00000344)
+#define HW_PXP_DATA_PATH_CTRL0_CLR (0x00000348)
+#define HW_PXP_DATA_PATH_CTRL0_TOG (0x0000034c)
+
+#define BP_PXP_DATA_PATH_CTRL0_MUX15_SEL 30
+#define BM_PXP_DATA_PATH_CTRL0_MUX15_SEL 0xC0000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(v) \
+ (((v) << 30) & BM_PXP_DATA_PATH_CTRL0_MUX15_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX14_SEL 28
+#define BM_PXP_DATA_PATH_CTRL0_MUX14_SEL 0x30000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(v) \
+ (((v) << 28) & BM_PXP_DATA_PATH_CTRL0_MUX14_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX13_SEL 26
+#define BM_PXP_DATA_PATH_CTRL0_MUX13_SEL 0x0C000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(v) \
+ (((v) << 26) & BM_PXP_DATA_PATH_CTRL0_MUX13_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX12_SEL 24
+#define BM_PXP_DATA_PATH_CTRL0_MUX12_SEL 0x03000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(v) \
+ (((v) << 24) & BM_PXP_DATA_PATH_CTRL0_MUX12_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX11_SEL 22
+#define BM_PXP_DATA_PATH_CTRL0_MUX11_SEL 0x00C00000
+#define BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(v) \
+ (((v) << 22) & BM_PXP_DATA_PATH_CTRL0_MUX11_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX10_SEL 20
+#define BM_PXP_DATA_PATH_CTRL0_MUX10_SEL 0x00300000
+#define BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(v) \
+ (((v) << 20) & BM_PXP_DATA_PATH_CTRL0_MUX10_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX9_SEL 18
+#define BM_PXP_DATA_PATH_CTRL0_MUX9_SEL 0x000C0000
+#define BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(v) \
+ (((v) << 18) & BM_PXP_DATA_PATH_CTRL0_MUX9_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX8_SEL 16
+#define BM_PXP_DATA_PATH_CTRL0_MUX8_SEL 0x00030000
+#define BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(v) \
+ (((v) << 16) & BM_PXP_DATA_PATH_CTRL0_MUX8_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX7_SEL 14
+#define BM_PXP_DATA_PATH_CTRL0_MUX7_SEL 0x0000C000
+#define BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(v) \
+ (((v) << 14) & BM_PXP_DATA_PATH_CTRL0_MUX7_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX6_SEL 12
+#define BM_PXP_DATA_PATH_CTRL0_MUX6_SEL 0x00003000
+#define BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(v) \
+ (((v) << 12) & BM_PXP_DATA_PATH_CTRL0_MUX6_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX5_SEL 10
+#define BM_PXP_DATA_PATH_CTRL0_MUX5_SEL 0x00000C00
+#define BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(v) \
+ (((v) << 10) & BM_PXP_DATA_PATH_CTRL0_MUX5_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX4_SEL 8
+#define BM_PXP_DATA_PATH_CTRL0_MUX4_SEL 0x00000300
+#define BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(v) \
+ (((v) << 8) & BM_PXP_DATA_PATH_CTRL0_MUX4_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX3_SEL 6
+#define BM_PXP_DATA_PATH_CTRL0_MUX3_SEL 0x000000C0
+#define BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(v) \
+ (((v) << 6) & BM_PXP_DATA_PATH_CTRL0_MUX3_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX2_SEL 4
+#define BM_PXP_DATA_PATH_CTRL0_MUX2_SEL 0x00000030
+#define BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(v) \
+ (((v) << 4) & BM_PXP_DATA_PATH_CTRL0_MUX2_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX1_SEL 2
+#define BM_PXP_DATA_PATH_CTRL0_MUX1_SEL 0x0000000C
+#define BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(v) \
+ (((v) << 2) & BM_PXP_DATA_PATH_CTRL0_MUX1_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX0_SEL 0
+#define BM_PXP_DATA_PATH_CTRL0_MUX0_SEL 0x00000003
+#define BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(v) \
+ (((v) << 0) & BM_PXP_DATA_PATH_CTRL0_MUX0_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__3 0x3
+
+#define HW_PXP_DATA_PATH_CTRL1 (0x00000350)
+#define HW_PXP_DATA_PATH_CTRL1_SET (0x00000354)
+#define HW_PXP_DATA_PATH_CTRL1_CLR (0x00000358)
+#define HW_PXP_DATA_PATH_CTRL1_TOG (0x0000035c)
+
+#define BP_PXP_DATA_PATH_CTRL1_RSVD0 4
+#define BM_PXP_DATA_PATH_CTRL1_RSVD0 0xFFFFFFF0
+#define BF_PXP_DATA_PATH_CTRL1_RSVD0(v) \
+ (((v) << 4) & BM_PXP_DATA_PATH_CTRL1_RSVD0)
+#define BP_PXP_DATA_PATH_CTRL1_MUX17_SEL 2
+#define BM_PXP_DATA_PATH_CTRL1_MUX17_SEL 0x0000000C
+#define BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(v) \
+ (((v) << 2) & BM_PXP_DATA_PATH_CTRL1_MUX17_SEL)
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL1_MUX16_SEL 0
+#define BM_PXP_DATA_PATH_CTRL1_MUX16_SEL 0x00000003
+#define BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(v) \
+ (((v) << 0) & BM_PXP_DATA_PATH_CTRL1_MUX16_SEL)
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__3 0x3
+
+#define HW_PXP_INIT_MEM_CTRL (0x00000360)
+#define HW_PXP_INIT_MEM_CTRL_SET (0x00000364)
+#define HW_PXP_INIT_MEM_CTRL_CLR (0x00000368)
+#define HW_PXP_INIT_MEM_CTRL_TOG (0x0000036c)
+
+#define BM_PXP_INIT_MEM_CTRL_START 0x80000000
+#define BF_PXP_INIT_MEM_CTRL_START(v) \
+ (((v) << 31) & BM_PXP_INIT_MEM_CTRL_START)
+#define BP_PXP_INIT_MEM_CTRL_SELECT 27
+#define BM_PXP_INIT_MEM_CTRL_SELECT 0x78000000
+#define BF_PXP_INIT_MEM_CTRL_SELECT(v) \
+ (((v) << 27) & BM_PXP_INIT_MEM_CTRL_SELECT)
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_LUT 0x0
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR0 0x1
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR1 0x2
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER1_LUT 0x3
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER2_LUT 0x4
+#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_A 0x5
+#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_B 0x6
+#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_A_FETCH 0x7
+#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_B_FETCH 0x8
+#define BV_PXP_INIT_MEM_CTRL_SELECT__RESERVED 0x15
+#define BP_PXP_INIT_MEM_CTRL_RSVD0 16
+#define BM_PXP_INIT_MEM_CTRL_RSVD0 0x07FF0000
+#define BF_PXP_INIT_MEM_CTRL_RSVD0(v) \
+ (((v) << 16) & BM_PXP_INIT_MEM_CTRL_RSVD0)
+#define BP_PXP_INIT_MEM_CTRL_ADDR 0
+#define BM_PXP_INIT_MEM_CTRL_ADDR 0x0000FFFF
+#define BF_PXP_INIT_MEM_CTRL_ADDR(v) \
+ (((v) << 0) & BM_PXP_INIT_MEM_CTRL_ADDR)
+
+#define HW_PXP_INIT_MEM_DATA (0x00000370)
+
+#define BP_PXP_INIT_MEM_DATA_DATA 0
+#define BM_PXP_INIT_MEM_DATA_DATA 0xFFFFFFFF
+#define BF_PXP_INIT_MEM_DATA_DATA(v) (v)
+
+#define HW_PXP_INIT_MEM_DATA_HIGH (0x00000380)
+
+#define BP_PXP_INIT_MEM_DATA_HIGH_DATA 0
+#define BM_PXP_INIT_MEM_DATA_HIGH_DATA 0xFFFFFFFF
+#define BF_PXP_INIT_MEM_DATA_HIGH_DATA(v) (v)
+
+#define HW_PXP_IRQ_MASK (0x00000390)
+#define HW_PXP_IRQ_MASK_SET (0x00000394)
+#define HW_PXP_IRQ_MASK_CLR (0x00000398)
+#define HW_PXP_IRQ_MASK_TOG (0x0000039c)
+
+#define BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN 0x80000000
+#define BF_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN(v) \
+ (((v) << 31) & BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN)
+#define BP_PXP_IRQ_MASK_RSVD1 16
+#define BM_PXP_IRQ_MASK_RSVD1 0x7FFF0000
+#define BF_PXP_IRQ_MASK_RSVD1(v) \
+ (((v) << 16) & BM_PXP_IRQ_MASK_RSVD1)
+#define BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN 0x00008000
+#define BF_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN(v) \
+ (((v) << 15) & BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN 0x00004000
+#define BF_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN(v) \
+ (((v) << 14) & BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN 0x00002000
+#define BF_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN(v) \
+ (((v) << 13) & BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN 0x00001000
+#define BF_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN(v) \
+ (((v) << 12) & BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN 0x00000800
+#define BF_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN(v) \
+ (((v) << 11) & BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN 0x00000400
+#define BF_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN(v) \
+ (((v) << 10) & BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN 0x00000200
+#define BF_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN(v) \
+ (((v) << 9) & BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN 0x00000100
+#define BF_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN(v) \
+ (((v) << 8) & BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN 0x00000080
+#define BF_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN(v) \
+ (((v) << 7) & BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN 0x00000040
+#define BF_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN(v) \
+ (((v) << 6) & BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN 0x00000020
+#define BF_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN(v) \
+ (((v) << 5) & BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN 0x00000010
+#define BF_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN(v) \
+ (((v) << 4) & BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN 0x00000008
+#define BF_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN(v) \
+ (((v) << 3) & BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN 0x00000004
+#define BF_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN(v) \
+ (((v) << 2) & BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN 0x00000002
+#define BF_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN(v) \
+ (((v) << 1) & BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN 0x00000001
+#define BF_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN(v) \
+ (((v) << 0) & BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN)
+
+#define HW_PXP_IRQ (0x000003a0)
+#define HW_PXP_IRQ_SET (0x000003a4)
+#define HW_PXP_IRQ_CLR (0x000003a8)
+#define HW_PXP_IRQ_TOG (0x000003ac)
+
+#define BM_PXP_IRQ_COMPRESS_DONE_IRQ 0x80000000
+#define BF_PXP_IRQ_COMPRESS_DONE_IRQ(v) \
+ (((v) << 31) & BM_PXP_IRQ_COMPRESS_DONE_IRQ)
+#define BP_PXP_IRQ_RSVD1 16
+#define BM_PXP_IRQ_RSVD1 0x7FFF0000
+#define BF_PXP_IRQ_RSVD1(v) \
+ (((v) << 16) & BM_PXP_IRQ_RSVD1)
+#define BM_PXP_IRQ_WFE_B_STORE_IRQ 0x00008000
+#define BF_PXP_IRQ_WFE_B_STORE_IRQ(v) \
+ (((v) << 15) & BM_PXP_IRQ_WFE_B_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_A_STORE_IRQ 0x00004000
+#define BF_PXP_IRQ_WFE_A_STORE_IRQ(v) \
+ (((v) << 14) & BM_PXP_IRQ_WFE_A_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_STORE_IRQ 0x00002000
+#define BF_PXP_IRQ_DITHER_STORE_IRQ(v) \
+ (((v) << 13) & BM_PXP_IRQ_DITHER_STORE_IRQ)
+#define BM_PXP_IRQ_FIRST_STORE_IRQ 0x00001000
+#define BF_PXP_IRQ_FIRST_STORE_IRQ(v) \
+ (((v) << 12) & BM_PXP_IRQ_FIRST_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ 0x00000800
+#define BF_PXP_IRQ_WFE_B_CH1_STORE_IRQ(v) \
+ (((v) << 11) & BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ 0x00000400
+#define BF_PXP_IRQ_WFE_B_CH0_STORE_IRQ(v) \
+ (((v) << 10) & BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ 0x00000200
+#define BF_PXP_IRQ_WFE_A_CH1_STORE_IRQ(v) \
+ (((v) << 9) & BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ 0x00000100
+#define BF_PXP_IRQ_WFE_A_CH0_STORE_IRQ(v) \
+ (((v) << 8) & BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_CH1_STORE_IRQ 0x00000080
+#define BF_PXP_IRQ_DITHER_CH1_STORE_IRQ(v) \
+ (((v) << 7) & BM_PXP_IRQ_DITHER_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_CH0_STORE_IRQ 0x00000040
+#define BF_PXP_IRQ_DITHER_CH0_STORE_IRQ(v) \
+ (((v) << 6) & BM_PXP_IRQ_DITHER_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ 0x00000020
+#define BF_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ(v) \
+ (((v) << 5) & BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ)
+#define BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ 0x00000010
+#define BF_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ(v) \
+ (((v) << 4) & BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ)
+#define BM_PXP_IRQ_FIRST_CH1_STORE_IRQ 0x00000008
+#define BF_PXP_IRQ_FIRST_CH1_STORE_IRQ(v) \
+ (((v) << 3) & BM_PXP_IRQ_FIRST_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_FIRST_CH0_STORE_IRQ 0x00000004
+#define BF_PXP_IRQ_FIRST_CH0_STORE_IRQ(v) \
+ (((v) << 2) & BM_PXP_IRQ_FIRST_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ 0x00000002
+#define BF_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ(v) \
+ (((v) << 1) & BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ)
+#define BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ 0x00000001
+#define BF_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ(v) \
+ (((v) << 0) & BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ)
+
+#define HW_PXP_NEXT (0x00000400)
+
+#define BP_PXP_NEXT_POINTER 2
+#define BM_PXP_NEXT_POINTER 0xFFFFFFFC
+#define BF_PXP_NEXT_POINTER(v) \
+ (((v) << 2) & BM_PXP_NEXT_POINTER)
+#define BM_PXP_NEXT_RSVD 0x00000002
+#define BF_PXP_NEXT_RSVD(v) \
+ (((v) << 1) & BM_PXP_NEXT_RSVD)
+#define BM_PXP_NEXT_ENABLED 0x00000001
+#define BF_PXP_NEXT_ENABLED(v) \
+ (((v) << 0) & BM_PXP_NEXT_ENABLED)
+
+#define HW_PXP_DEBUGCTRL (0x00000410)
+
+#define BP_PXP_DEBUGCTRL_RSVD 12
+#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000
+#define BF_PXP_DEBUGCTRL_RSVD(v) \
+ (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD)
+#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 8
+#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00
+#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v) \
+ (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT)
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE 0x0
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT 0x2
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT 0x4
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT 0x8
+#define BP_PXP_DEBUGCTRL_SELECT 0
+#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF
+#define BF_PXP_DEBUGCTRL_SELECT(v) \
+ (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT)
+#define BV_PXP_DEBUGCTRL_SELECT__NONE 0x0
+#define BV_PXP_DEBUGCTRL_SELECT__CTRL 0x1
+#define BV_PXP_DEBUGCTRL_SELECT__PSBUF 0x2
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAX 0x3
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAY 0x4
+#define BV_PXP_DEBUGCTRL_SELECT__ASBUF 0x5
+#define BV_PXP_DEBUGCTRL_SELECT__ROTATION 0x6
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0 0x7
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1 0x8
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2 0x9
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT 0x10
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS 0x11
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT 0x12
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT 0x13
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14
+
+#define HW_PXP_DEBUG (0x00000420)
+
+#define BP_PXP_DEBUG_DATA 0
+#define BM_PXP_DEBUG_DATA 0xFFFFFFFF
+#define BF_PXP_DEBUG_DATA(v) (v)
+
+#define HW_PXP_VERSION (0x00000430)
+
+#define BP_PXP_VERSION_MAJOR 24
+#define BM_PXP_VERSION_MAJOR 0xFF000000
+#define BF_PXP_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_PXP_VERSION_MAJOR)
+#define BP_PXP_VERSION_MINOR 16
+#define BM_PXP_VERSION_MINOR 0x00FF0000
+#define BF_PXP_VERSION_MINOR(v) \
+ (((v) << 16) & BM_PXP_VERSION_MINOR)
+#define BP_PXP_VERSION_STEP 0
+#define BM_PXP_VERSION_STEP 0x0000FFFF
+#define BF_PXP_VERSION_STEP(v) \
+ (((v) << 0) & BM_PXP_VERSION_STEP)
+
+#endif /* __IMX_PXP_H__ */
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index 5f84d2aa47ab..c62e598ee7d0 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -438,9 +438,9 @@ static void deinterlace_device_run(void *priv)
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strlcpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
- strlcpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
- strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card));
+ strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
+ strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
+ strscpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card));
/*
* This is only a mem-to-mem video device. The capture and output
* device capability flags are left only for backward compatibility
@@ -474,7 +474,7 @@ static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
if (i < NUM_FORMATS) {
/* Format found */
fmt = &formats[i];
- strlcpy(f->description, fmt->name, sizeof(f->description));
+ strscpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
return 0;
}
diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c
index 57d2c483ad09..2986cb4b88d0 100644
--- a/drivers/media/platform/marvell-ccic/cafe-driver.c
+++ b/drivers/media/platform/marvell-ccic/cafe-driver.c
@@ -341,7 +341,7 @@ static int cafe_smbus_setup(struct cafe_camera *cam)
return -ENOMEM;
adap->owner = THIS_MODULE;
adap->algo = &cafe_smbus_algo;
- strcpy(adap->name, "cafe_ccic");
+ strscpy(adap->name, "cafe_ccic", sizeof(adap->name));
adap->dev.parent = &cam->pdev->dev;
i2c_set_adapdata(adap, cam);
ret = i2c_add_adapter(adap);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index dfdbd4354b74..f1b301810260 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -794,7 +794,7 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
/*
* This field controls the generation of EOF(DVP only)
*/
- if (cam->bus_type != V4L2_MBUS_CSI2)
+ if (cam->bus_type != V4L2_MBUS_CSI2_DPHY)
mcam_reg_set_bit(cam, REG_CTRL0,
C0_EOF_VSYNC | C0_VEDGE_CTRL);
}
@@ -1023,7 +1023,7 @@ static int mcam_read_setup(struct mcam_camera *cam)
cam->calc_dphy(cam);
cam_dbg(cam, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n",
cam->dphy[0], cam->dphy[1], cam->dphy[2]);
- if (cam->bus_type == V4L2_MBUS_CSI2)
+ if (cam->bus_type == V4L2_MBUS_CSI2_DPHY)
mcam_enable_mipi(cam);
else
mcam_disable_mipi(cam);
@@ -1303,9 +1303,9 @@ static int mcam_vidioc_querycap(struct file *file, void *priv,
{
struct mcam_camera *cam = video_drvdata(file);
- strcpy(cap->driver, "marvell_ccic");
- strcpy(cap->card, "marvell_ccic");
- strlcpy(cap->bus_info, cam->bus_info, sizeof(cap->bus_info));
+ strscpy(cap->driver, "marvell_ccic", sizeof(cap->driver));
+ strscpy(cap->card, "marvell_ccic", sizeof(cap->card));
+ strscpy(cap->bus_info, cam->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -1318,8 +1318,8 @@ static int mcam_vidioc_enum_fmt_vid_cap(struct file *filp,
{
if (fmt->index >= N_MCAM_FMTS)
return -EINVAL;
- strlcpy(fmt->description, mcam_formats[fmt->index].desc,
- sizeof(fmt->description));
+ strscpy(fmt->description, mcam_formats[fmt->index].desc,
+ sizeof(fmt->description));
fmt->pixelformat = mcam_formats[fmt->index].pixelformat;
return 0;
}
@@ -1421,7 +1421,7 @@ static int mcam_vidioc_enum_input(struct file *filp, void *priv,
return -EINVAL;
input->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(input->name, "Camera");
+ strscpy(input->name, "Camera", sizeof(input->name));
return 0;
}
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index 6d9f0abb2660..70a2833db0d1 100644
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -362,7 +362,7 @@ static int mmpcam_probe(struct platform_device *pdev)
mcam->mclk_div = pdata->mclk_div;
mcam->bus_type = pdata->bus_type;
mcam->dphy = pdata->dphy;
- if (mcam->bus_type == V4L2_MBUS_CSI2) {
+ if (mcam->bus_type == V4L2_MBUS_CSI2_DPHY) {
cam->mipi_clk = devm_clk_get(mcam->dev, "mipi");
if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0))
return PTR_ERR(cam->mipi_clk);
@@ -371,7 +371,7 @@ static int mmpcam_probe(struct platform_device *pdev)
mcam->lane = pdata->lane;
mcam->chip_id = MCAM_ARMADA610;
mcam->buffer_mode = B_DMA_sg;
- strlcpy(mcam->bus_info, "platform:mmp-camera", sizeof(mcam->bus_info));
+ strscpy(mcam->bus_info, "platform:mmp-camera", sizeof(mcam->bus_info));
spin_lock_init(&mcam->dev_lock);
/*
* Get our I/O memory.
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index 4f24da8afecc..2a5d5002c27e 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -94,8 +94,8 @@ static int mtk_jpeg_querycap(struct file *file, void *priv,
{
struct mtk_jpeg_dev *jpeg = video_drvdata(file);
- strlcpy(cap->driver, MTK_JPEG_NAME " decoder", sizeof(cap->driver));
- strlcpy(cap->card, MTK_JPEG_NAME " decoder", sizeof(cap->card));
+ strscpy(cap->driver, MTK_JPEG_NAME " decoder", sizeof(cap->driver));
+ strscpy(cap->card, MTK_JPEG_NAME " decoder", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(jpeg->dev));
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
index ceffc31cc6eb..51a13466261e 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
@@ -619,9 +619,9 @@ static int mtk_mdp_m2m_querycap(struct file *file, void *fh,
struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
struct mtk_mdp_dev *mdp = ctx->mdp_dev;
- strlcpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver));
- strlcpy(cap->card, mdp->pdev->name, sizeof(cap->card));
- strlcpy(cap->bus_info, "platform:mt8173", sizeof(cap->bus_info));
+ strscpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver));
+ strscpy(cap->card, mdp->pdev->name, sizeof(cap->card));
+ strscpy(cap->bus_info, "platform:mt8173", sizeof(cap->bus_info));
return 0;
}
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
index 0c8a8b4c4e1c..ba619647bc10 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
@@ -613,9 +613,9 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv,
static int vidioc_vdec_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strlcpy(cap->driver, MTK_VCODEC_DEC_NAME, sizeof(cap->driver));
- strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
- strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
+ strscpy(cap->driver, MTK_VCODEC_DEC_NAME, sizeof(cap->driver));
+ strscpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
+ strscpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
return 0;
}
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
index 6ad408514a99..54631ad1c71e 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -222,9 +222,9 @@ static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
static int vidioc_venc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strlcpy(cap->driver, MTK_VCODEC_ENC_NAME, sizeof(cap->driver));
- strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
- strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
+ strscpy(cap->driver, MTK_VCODEC_ENC_NAME, sizeof(cap->driver));
+ strscpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
+ strscpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
return 0;
}
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
index 0c28d0b995cc..e80123cba406 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
@@ -49,16 +49,13 @@ int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data;
struct device *dev = &ctx->dev->plat_dev->dev;
- mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
-
+ mem->va = dma_zalloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
if (!mem->va) {
mtk_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev),
size);
return -ENOMEM;
}
- memset(mem->va, 0, size);
-
mtk_v4l2_debug(3, "[%d] - va = %p", ctx->id, mem->va);
mtk_v4l2_debug(3, "[%d] - dma = 0x%lx", ctx->id,
(unsigned long)mem->dma_addr);
diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c
index f8d35e3ac1dc..616f78b24a79 100644
--- a/drivers/media/platform/mtk-vpu/mtk_vpu.c
+++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c
@@ -480,12 +480,12 @@ EXPORT_SYMBOL_GPL(vpu_get_plat_device);
/* load vpu program/data memory */
static int load_requested_vpu(struct mtk_vpu *vpu,
- const struct firmware *vpu_fw,
u8 fw_type)
{
size_t tcm_size = fw_type ? VPU_DTCM_SIZE : VPU_PTCM_SIZE;
size_t fw_size = fw_type ? VPU_D_FW_SIZE : VPU_P_FW_SIZE;
char *fw_name = fw_type ? VPU_D_FW : VPU_P_FW;
+ const struct firmware *vpu_fw;
size_t dl_size = 0;
size_t extra_fw_size = 0;
void *dest;
@@ -539,7 +539,6 @@ int vpu_load_firmware(struct platform_device *pdev)
struct mtk_vpu *vpu;
struct device *dev = &pdev->dev;
struct vpu_run *run;
- const struct firmware *vpu_fw = NULL;
int ret;
if (!pdev) {
@@ -568,14 +567,14 @@ int vpu_load_firmware(struct platform_device *pdev)
run->signaled = false;
dev_dbg(vpu->dev, "firmware request\n");
/* Downloading program firmware to device*/
- ret = load_requested_vpu(vpu, vpu_fw, P_FW);
+ ret = load_requested_vpu(vpu, P_FW);
if (ret < 0) {
dev_err(dev, "Failed to request %s, %d\n", VPU_P_FW, ret);
goto OUT_LOAD_FW;
}
/* Downloading data firmware to device */
- ret = load_requested_vpu(vpu, vpu_fw, D_FW);
+ ret = load_requested_vpu(vpu, D_FW);
if (ret < 0) {
dev_err(dev, "Failed to request %s, %d\n", VPU_D_FW, ret);
goto OUT_LOAD_FW;
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
index 64195c4ddeaf..27b078cf98e3 100644
--- a/drivers/media/platform/mx2_emmaprp.c
+++ b/drivers/media/platform/mx2_emmaprp.c
@@ -413,7 +413,7 @@ static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
if (i < NUM_FORMATS) {
/* Format found */
fmt = &formats[i];
- strlcpy(f->description, fmt->name, sizeof(f->description) - 1);
+ strscpy(f->description, fmt->name, sizeof(f->description) - 1);
f->pixelformat = fmt->fourcc;
return 0;
}
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index 5700b7818621..f447ae3bb465 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -1041,8 +1041,8 @@ static int vidioc_querycap(struct file *file, void *fh,
{
struct omap_vout_device *vout = fh;
- strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
- strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
+ strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
+ strscpy(cap->card, vout->vfd->name, sizeof(cap->card));
cap->bus_info[0] = '\0';
cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
@@ -1060,8 +1060,8 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *fh,
return -EINVAL;
fmt->flags = omap_formats[index].flags;
- strlcpy(fmt->description, omap_formats[index].description,
- sizeof(fmt->description));
+ strscpy(fmt->description, omap_formats[index].description,
+ sizeof(fmt->description));
fmt->pixelformat = omap_formats[index].pixelformat;
return 0;
@@ -1868,7 +1868,7 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
vfd->release = video_device_release;
vfd->ioctl_ops = &vout_ioctl_ops;
- strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
+ strscpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
vfd->fops = &omap_vout_fops;
vfd->v4l2_dev = &vout->vid_dev->v4l2_dev;
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 842e2235047d..77fb7987b42f 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -1677,7 +1677,7 @@ static int isp_register_entities(struct isp_device *isp)
int ret;
isp->media_dev.dev = isp->dev;
- strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
+ strscpy(isp->media_dev.model, "TI OMAP3 ISP",
sizeof(isp->media_dev.model));
isp->media_dev.hw_revision = isp->revision;
isp->media_dev.ops = &isp_media_ops;
@@ -2054,7 +2054,7 @@ static int isp_fwnode_parse(struct device *dev,
dev_dbg(dev, "CSI-1/CCP-2 configuration\n");
csi1 = true;
break;
- case V4L2_MBUS_CSI2:
+ case V4L2_MBUS_CSI2_DPHY:
dev_dbg(dev, "CSI-2 configuration\n");
csi1 = false;
break;
@@ -2220,6 +2220,7 @@ static int isp_probe(struct platform_device *pdev)
mutex_init(&isp->isp_mutex);
spin_lock_init(&isp->stat_lock);
+ v4l2_async_notifier_init(&isp->notifier);
ret = v4l2_async_notifier_parse_fwnode_endpoints(
&pdev->dev, &isp->notifier, sizeof(struct isp_async_subdev),
diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index 77b73e27a274..14a1c24037c4 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -2641,7 +2641,7 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
v4l2_subdev_init(sd, &ccdc_v4l2_ops);
sd->internal_ops = &ccdc_v4l2_internal_ops;
- strlcpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name));
+ strscpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for isp subdevs */
v4l2_set_subdevdata(sd, ccdc);
sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c
index e062939d0d05..2dea423ffc0e 100644
--- a/drivers/media/platform/omap3isp/ispccp2.c
+++ b/drivers/media/platform/omap3isp/ispccp2.c
@@ -1070,7 +1070,7 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2)
v4l2_subdev_init(sd, &ccp2_sd_ops);
sd->internal_ops = &ccp2_sd_internal_ops;
- strlcpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name));
+ strscpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for isp subdevs */
v4l2_set_subdevdata(sd, ccp2);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c
index a4d3d030e81e..9c180f607bcb 100644
--- a/drivers/media/platform/omap3isp/ispcsi2.c
+++ b/drivers/media/platform/omap3isp/ispcsi2.c
@@ -1234,7 +1234,7 @@ static int csi2_init_entities(struct isp_csi2_device *csi2)
v4l2_subdev_init(sd, &csi2_ops);
sd->internal_ops = &csi2_internal_ops;
- strlcpy(sd->name, "OMAP3 ISP CSI2a", sizeof(sd->name));
+ strscpy(sd->name, "OMAP3 ISP CSI2a", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for isp subdevs */
v4l2_set_subdevdata(sd, csi2);
diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c
index 3195f7c8b8b7..6ea6aeafd751 100644
--- a/drivers/media/platform/omap3isp/isppreview.c
+++ b/drivers/media/platform/omap3isp/isppreview.c
@@ -2267,7 +2267,7 @@ static int preview_init_entities(struct isp_prev_device *prev)
v4l2_subdev_init(sd, &preview_v4l2_ops);
sd->internal_ops = &preview_v4l2_internal_ops;
- strlcpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
+ strscpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for isp subdevs */
v4l2_set_subdevdata(sd, prev);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c
index 0b6a87508584..b281cae036b3 100644
--- a/drivers/media/platform/omap3isp/ispresizer.c
+++ b/drivers/media/platform/omap3isp/ispresizer.c
@@ -1723,7 +1723,7 @@ static int resizer_init_entities(struct isp_res_device *res)
v4l2_subdev_init(sd, &resizer_v4l2_ops);
sd->internal_ops = &resizer_v4l2_internal_ops;
- strlcpy(sd->name, "OMAP3 ISP resizer", sizeof(sd->name));
+ strscpy(sd->name, "OMAP3 ISP resizer", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for isp subdevs */
v4l2_set_subdevdata(sd, res);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index 9d228eac24ea..5658f6a326f7 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -654,9 +654,9 @@ isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
{
struct isp_video *video = video_drvdata(file);
- strlcpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
- strlcpy(cap->card, video->video.name, sizeof(cap->card));
- strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
+ strscpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
+ strscpy(cap->card, video->video.name, sizeof(cap->card));
+ strscpy(cap->bus_info, "media", sizeof(cap->bus_info));
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
| V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
@@ -1251,7 +1251,7 @@ isp_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
if (input->index > 0)
return -EINVAL;
- strlcpy(input->name, "camera", sizeof(input->name));
+ strscpy(input->name, "camera", sizeof(input->name));
input->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c
index b6e9e93bde7a..5f930560eb30 100644
--- a/drivers/media/platform/pxa_camera.c
+++ b/drivers/media/platform/pxa_camera.c
@@ -633,7 +633,7 @@ static unsigned int pxa_mbus_config_compatible(const struct v4l2_mbus_config *cf
mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
return (!hsync || !vsync || !pclk || !data || !mode) ?
0 : common_flags;
- case V4L2_MBUS_CSI2:
+ case V4L2_MBUS_CSI2_DPHY:
mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
@@ -697,7 +697,6 @@ struct pxa_camera_dev {
struct v4l2_pix_format current_pix;
struct v4l2_async_subdev asd;
- struct v4l2_async_subdev *asds[1];
/*
* PXA27x is only supposed to handle one camera on its Quick Capture
@@ -1994,9 +1993,9 @@ static int pxac_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
static int pxac_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strlcpy(cap->bus_info, "platform:pxa-camera", sizeof(cap->bus_info));
- strlcpy(cap->driver, PXA_CAM_DRV_NAME, sizeof(cap->driver));
- strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
+ strscpy(cap->bus_info, "platform:pxa-camera", sizeof(cap->bus_info));
+ strscpy(cap->driver, PXA_CAM_DRV_NAME, sizeof(cap->driver));
+ strscpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -2010,7 +2009,7 @@ static int pxac_vidioc_enum_input(struct file *file, void *priv,
return -EINVAL;
i->type = V4L2_INPUT_TYPE_CAMERA;
- strlcpy(i->name, "Camera", sizeof(i->name));
+ strscpy(i->name, "Camera", sizeof(i->name));
return 0;
}
@@ -2299,7 +2298,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
{
u32 mclk_rate;
struct device_node *remote, *np = dev->of_node;
- struct v4l2_fwnode_endpoint ep;
+ struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
int err = of_property_read_u32(np, "clock-frequency",
&mclk_rate);
if (!err) {
@@ -2352,12 +2351,10 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
remote = of_graph_get_remote_port(np);
- if (remote) {
+ if (remote)
asd->match.fwnode = of_fwnode_handle(remote);
- of_node_put(remote);
- } else {
+ else
dev_notice(dev, "no remote for %pOF\n", np);
- }
out:
of_node_put(np);
@@ -2397,7 +2394,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->res = res;
pcdev->pdata = pdev->dev.platform_data;
- if (&pdev->dev.of_node && !pcdev->pdata) {
+ if (pdev->dev.of_node && !pcdev->pdata) {
err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev, &pcdev->asd);
} else {
pcdev->platform_flags = pcdev->pdata->flags;
@@ -2495,9 +2492,14 @@ static int pxa_camera_probe(struct platform_device *pdev)
if (err)
goto exit_deactivate;
- pcdev->asds[0] = &pcdev->asd;
- pcdev->notifier.subdevs = pcdev->asds;
- pcdev->notifier.num_subdevs = 1;
+ v4l2_async_notifier_init(&pcdev->notifier);
+
+ err = v4l2_async_notifier_add_subdev(&pcdev->notifier, &pcdev->asd);
+ if (err) {
+ fwnode_handle_put(pcdev->asd.match.fwnode);
+ goto exit_free_v4l2dev;
+ }
+
pcdev->notifier.ops = &pxa_camera_sensor_ops;
if (!of_have_populated_dt())
@@ -2505,7 +2507,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
err = pxa_camera_init_videobuf2(pcdev);
if (err)
- goto exit_free_v4l2dev;
+ goto exit_notifier_cleanup;
if (pcdev->mclk) {
v4l2_clk_name_i2c(clk_name, sizeof(clk_name),
@@ -2516,7 +2518,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
clk_name, NULL);
if (IS_ERR(pcdev->mclk_clk)) {
err = PTR_ERR(pcdev->mclk_clk);
- goto exit_free_v4l2dev;
+ goto exit_notifier_cleanup;
}
}
@@ -2527,6 +2529,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
return 0;
exit_free_clk:
v4l2_clk_unregister(pcdev->mclk_clk);
+exit_notifier_cleanup:
+ v4l2_async_notifier_cleanup(&pcdev->notifier);
exit_free_v4l2dev:
v4l2_device_unregister(&pcdev->v4l2_dev);
exit_deactivate:
@@ -2550,6 +2554,7 @@ static int pxa_camera_remove(struct platform_device *pdev)
dma_release_channel(pcdev->dma_chans[2]);
v4l2_async_notifier_unregister(&pcdev->notifier);
+ v4l2_async_notifier_cleanup(&pcdev->notifier);
if (pcdev->mclk_clk) {
v4l2_clk_unregister(pcdev->mclk_clk);
diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c
index c9bb0d023db4..58aebe7114cd 100644
--- a/drivers/media/platform/qcom/camss/camss-video.c
+++ b/drivers/media/platform/qcom/camss/camss-video.c
@@ -521,8 +521,8 @@ static int video_querycap(struct file *file, void *fh,
{
struct camss_video *video = video_drvdata(file);
- strlcpy(cap->driver, "qcom-camss", sizeof(cap->driver));
- strlcpy(cap->card, "Qualcomm Camera Subsystem", sizeof(cap->card));
+ strscpy(cap->driver, "qcom-camss", sizeof(cap->driver));
+ strscpy(cap->card, "Qualcomm Camera Subsystem", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(video->camss->dev));
@@ -683,7 +683,7 @@ static int video_enum_input(struct file *file, void *fh,
if (input->index > 0)
return -EINVAL;
- strlcpy(input->name, "camera", sizeof(input->name));
+ strscpy(input->name, "camera", sizeof(input->name));
input->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
@@ -919,7 +919,7 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev,
vdev->vfl_dir = VFL_DIR_RX;
vdev->queue = &video->vb2_q;
vdev->lock = &video->lock;
- strlcpy(vdev->name, name, sizeof(vdev->name));
+ strscpy(vdev->name, name, sizeof(vdev->name));
ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
if (ret < 0) {
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 669615fff6a0..45978db3b0be 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -462,61 +462,51 @@ static int camss_of_parse_endpoint_node(struct device *dev,
*
* Return number of "port" nodes found in "ports" node
*/
-static int camss_of_parse_ports(struct device *dev,
- struct v4l2_async_notifier *notifier)
+static int camss_of_parse_ports(struct camss *camss)
{
+ struct device *dev = camss->dev;
struct device_node *node = NULL;
struct device_node *remote = NULL;
- unsigned int size, i;
- int ret;
-
- while ((node = of_graph_get_next_endpoint(dev->of_node, node)))
- if (of_device_is_available(node))
- notifier->num_subdevs++;
-
- of_node_put(node);
- size = sizeof(*notifier->subdevs) * notifier->num_subdevs;
- notifier->subdevs = devm_kzalloc(dev, size, GFP_KERNEL);
- if (!notifier->subdevs) {
- dev_err(dev, "Failed to allocate memory\n");
- return -ENOMEM;
- }
+ int ret, num_subdevs = 0;
- i = 0;
- while ((node = of_graph_get_next_endpoint(dev->of_node, node))) {
+ for_each_endpoint_of_node(dev->of_node, node) {
struct camss_async_subdev *csd;
+ struct v4l2_async_subdev *asd;
if (!of_device_is_available(node))
continue;
- csd = devm_kzalloc(dev, sizeof(*csd), GFP_KERNEL);
- if (!csd) {
- of_node_put(node);
- dev_err(dev, "Failed to allocate memory\n");
- return -ENOMEM;
- }
-
- notifier->subdevs[i++] = &csd->asd;
-
- ret = camss_of_parse_endpoint_node(dev, node, csd);
- if (ret < 0) {
- of_node_put(node);
- return ret;
- }
-
remote = of_graph_get_remote_port_parent(node);
if (!remote) {
dev_err(dev, "Cannot get remote parent\n");
- of_node_put(node);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_cleanup;
}
- csd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
- csd->asd.match.fwnode = of_fwnode_handle(remote);
+ asd = v4l2_async_notifier_add_fwnode_subdev(
+ &camss->notifier, of_fwnode_handle(remote),
+ sizeof(*csd));
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ of_node_put(remote);
+ goto err_cleanup;
+ }
+
+ csd = container_of(asd, struct camss_async_subdev, asd);
+
+ ret = camss_of_parse_endpoint_node(dev, node, csd);
+ if (ret < 0)
+ goto err_cleanup;
+
+ num_subdevs++;
}
- of_node_put(node);
- return notifier->num_subdevs;
+ return num_subdevs;
+
+err_cleanup:
+ v4l2_async_notifier_cleanup(&camss->notifier);
+ of_node_put(node);
+ return ret;
}
/*
@@ -823,7 +813,7 @@ static int camss_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct camss *camss;
- int ret;
+ int num_subdevs, ret;
camss = kzalloc(sizeof(*camss), GFP_KERNEL);
if (!camss)
@@ -863,20 +853,22 @@ static int camss_probe(struct platform_device *pdev)
if (!camss->vfe)
return -ENOMEM;
- ret = camss_of_parse_ports(dev, &camss->notifier);
- if (ret < 0)
- return ret;
+ v4l2_async_notifier_init(&camss->notifier);
+
+ num_subdevs = camss_of_parse_ports(camss);
+ if (num_subdevs < 0)
+ return num_subdevs;
ret = camss_init_subdevices(camss);
if (ret < 0)
- return ret;
+ goto err_cleanup;
ret = dma_set_mask_and_coherent(dev, 0xffffffff);
if (ret)
- return ret;
+ goto err_cleanup;
camss->media_dev.dev = camss->dev;
- strlcpy(camss->media_dev.model, "Qualcomm Camera Subsystem",
+ strscpy(camss->media_dev.model, "Qualcomm Camera Subsystem",
sizeof(camss->media_dev.model));
camss->media_dev.ops = &camss_media_ops;
media_device_init(&camss->media_dev);
@@ -885,14 +877,14 @@ static int camss_probe(struct platform_device *pdev)
ret = v4l2_device_register(camss->dev, &camss->v4l2_dev);
if (ret < 0) {
dev_err(dev, "Failed to register V4L2 device: %d\n", ret);
- return ret;
+ goto err_cleanup;
}
ret = camss_register_entities(camss);
if (ret < 0)
goto err_register_entities;
- if (camss->notifier.num_subdevs) {
+ if (num_subdevs) {
camss->notifier.ops = &camss_subdev_notifier_ops;
ret = v4l2_async_notifier_register(&camss->v4l2_dev,
@@ -942,6 +934,8 @@ err_register_subdevs:
camss_unregister_entities(camss);
err_register_entities:
v4l2_device_unregister(&camss->v4l2_dev);
+err_cleanup:
+ v4l2_async_notifier_cleanup(&camss->notifier);
return ret;
}
@@ -978,6 +972,7 @@ static int camss_remove(struct platform_device *pdev)
msm_vfe_stop_streaming(&camss->vfe[i]);
v4l2_async_notifier_unregister(&camss->notifier);
+ v4l2_async_notifier_cleanup(&camss->notifier);
camss_unregister_entities(camss);
if (atomic_read(&camss->ref_count) == 0)
diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
index 418996d8dad8..57b269ca93fd 100644
--- a/drivers/media/platform/qcom/camss/camss.h
+++ b/drivers/media/platform/qcom/camss/camss.h
@@ -17,7 +17,6 @@
#include <media/v4l2-subdev.h>
#include <media/media-device.h>
#include <media/media-entity.h>
-#include <linux/device.h>
#include "camss-csid.h"
#include "camss-csiphy.h"
@@ -92,8 +91,8 @@ struct camss_camera_interface {
};
struct camss_async_subdev {
+ struct v4l2_async_subdev asd; /* must be first */
struct camss_camera_interface interface;
- struct v4l2_async_subdev asd;
};
struct camss_clock {
diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c
index cd3b96e6f24b..e436385bc5ab 100644
--- a/drivers/media/platform/qcom/venus/helpers.c
+++ b/drivers/media/platform/qcom/venus/helpers.c
@@ -472,7 +472,7 @@ static bool is_dynamic_bufmode(struct venus_inst *inst)
caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
if (!caps)
- return 0;
+ return false;
return caps->cap_bufs_mode_dynamic;
}
diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c
index dfbbbf0f746f..189ec975c6bb 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -341,9 +341,9 @@ vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
static int
vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
{
- strlcpy(cap->driver, "qcom-venus", sizeof(cap->driver));
- strlcpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card));
- strlcpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
+ strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
+ strscpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card));
+ strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
return 0;
}
@@ -888,8 +888,7 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
unsigned int opb_sz = venus_helper_get_opb_size(inst);
vb = &vbuf->vb2_buf;
- vb->planes[0].bytesused =
- max_t(unsigned int, opb_sz, bytesused);
+ vb2_set_plane_payload(vb, 0, bytesused ? : opb_sz);
vb->planes[0].data_offset = data_offset;
vb->timestamp = timestamp_us * NSEC_PER_USEC;
vbuf->sequence = inst->sequence_cap++;
@@ -1153,7 +1152,7 @@ static int vdec_probe(struct platform_device *pdev)
if (!vdev)
return -ENOMEM;
- strlcpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name));
+ strscpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name));
vdev->release = video_device_release;
vdev->fops = &vdec_fops;
vdev->ioctl_ops = &vdec_ioctl_ops;
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index 41249d1443fa..ce85962b6adc 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -273,9 +273,9 @@ static int venc_v4l2_to_hfi(int id, int value)
static int
venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
{
- strlcpy(cap->driver, "qcom-venus", sizeof(cap->driver));
- strlcpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card));
- strlcpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
+ strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
+ strscpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card));
+ strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
return 0;
}
@@ -1257,7 +1257,7 @@ static int venc_probe(struct platform_device *pdev)
if (!vdev)
return -ENOMEM;
- strlcpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name));
+ strscpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name));
vdev->release = video_device_release;
vdev->fops = &venc_fops;
vdev->ioctl_ops = &venc_ioctl_ops;
diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index ce09799976ef..a3f135364474 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -170,7 +170,6 @@ static int rvin_group_link_notify(struct media_link *link, u32 flags,
if (csi_id == -ENODEV) {
struct v4l2_subdev *sd;
- unsigned int i;
/*
* Make sure the source entity subdevice is registered as
@@ -268,8 +267,8 @@ static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)
match = of_match_node(vin->dev->driver->of_match_table,
vin->dev->of_node);
- strlcpy(mdev->driver_name, KBUILD_MODNAME, sizeof(mdev->driver_name));
- strlcpy(mdev->model, match->compatible, sizeof(mdev->model));
+ strscpy(mdev->driver_name, KBUILD_MODNAME, sizeof(mdev->driver_name));
+ strscpy(mdev->model, match->compatible, sizeof(mdev->model));
snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
dev_name(mdev->dev));
@@ -611,6 +610,8 @@ static int rvin_parallel_init(struct rvin_dev *vin)
{
int ret;
+ v4l2_async_notifier_init(&vin->notifier);
+
ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
vin->dev, &vin->notifier, sizeof(struct rvin_parallel_entity),
0, rvin_parallel_parse_v4l2);
@@ -803,6 +804,8 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
return 0;
}
+ v4l2_async_notifier_init(&vin->group->notifier);
+
/*
* Have all VIN's look for CSI-2 subdevices. Some subdevices will
* overlap but the parser function can handle it, so each subdevice
@@ -824,7 +827,7 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
mutex_unlock(&vin->group->lock);
- if (!vin->group->notifier.num_subdevs)
+ if (list_empty(&vin->group->notifier.asd_list))
return 0;
vin->group->notifier.ops = &rvin_group_notify_ops;
diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
index dc5ae8025832..b0044a08e71e 100644
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -714,7 +714,7 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv,
if (vep->base.port || vep->base.id)
return -ENOTCONN;
- if (vep->bus_type != V4L2_MBUS_CSI2) {
+ if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type);
return -EINVAL;
}
@@ -743,7 +743,7 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv,
static int rcsi2_parse_dt(struct rcar_csi2 *priv)
{
struct device_node *ep;
- struct v4l2_fwnode_endpoint v4l2_ep;
+ struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 };
int ret;
ep = of_graph_get_endpoint_by_regs(priv->dev->of_node, 0, 0);
@@ -771,21 +771,25 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv)
of_node_put(ep);
- priv->notifier.subdevs = devm_kzalloc(priv->dev,
- sizeof(*priv->notifier.subdevs),
- GFP_KERNEL);
- if (!priv->notifier.subdevs)
- return -ENOMEM;
+ v4l2_async_notifier_init(&priv->notifier);
+
+ ret = v4l2_async_notifier_add_subdev(&priv->notifier, &priv->asd);
+ if (ret) {
+ fwnode_handle_put(priv->asd.match.fwnode);
+ return ret;
+ }
- priv->notifier.num_subdevs = 1;
- priv->notifier.subdevs[0] = &priv->asd;
priv->notifier.ops = &rcar_csi2_notify_ops;
dev_dbg(priv->dev, "Found '%pOF'\n",
to_of_node(priv->asd.match.fwnode));
- return v4l2_async_subdev_notifier_register(&priv->subdev,
- &priv->notifier);
+ ret = v4l2_async_subdev_notifier_register(&priv->subdev,
+ &priv->notifier);
+ if (ret)
+ v4l2_async_notifier_cleanup(&priv->notifier);
+
+ return ret;
}
/* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 5a54779cfc27..dc77682b4785 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -238,8 +238,8 @@ static int rvin_querycap(struct file *file, void *priv,
{
struct rvin_dev *vin = video_drvdata(file);
- strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
- strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
+ strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+ strscpy(cap->card, "R_Car_VIN", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(vin->dev));
return 0;
@@ -440,7 +440,7 @@ static int rvin_enum_input(struct file *file, void *priv,
i->std = vin->vdev.tvnorms;
}
- strlcpy(i->name, "Camera", sizeof(i->name));
+ strscpy(i->name, "Camera", sizeof(i->name));
return 0;
}
@@ -714,7 +714,7 @@ static int rvin_mc_enum_input(struct file *file, void *priv,
return -EINVAL;
i->type = V4L2_INPUT_TYPE_CAMERA;
- strlcpy(i->name, "Camera", sizeof(i->name));
+ strscpy(i->name, "Camera", sizeof(i->name));
return 0;
}
diff --git a/drivers/media/platform/rcar_drif.c b/drivers/media/platform/rcar_drif.c
index 81413ab52475..8483dc36715d 100644
--- a/drivers/media/platform/rcar_drif.c
+++ b/drivers/media/platform/rcar_drif.c
@@ -870,8 +870,8 @@ static int rcar_drif_querycap(struct file *file, void *fh,
{
struct rcar_drif_sdr *sdr = video_drvdata(file);
- strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
- strlcpy(cap->card, sdr->vdev->name, sizeof(cap->card));
+ strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+ strscpy(cap->card, sdr->vdev->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
sdr->vdev->name);
@@ -1213,18 +1213,15 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
{
struct v4l2_async_notifier *notifier = &sdr->notifier;
struct fwnode_handle *fwnode, *ep;
+ int ret;
- notifier->subdevs = devm_kzalloc(sdr->dev, sizeof(*notifier->subdevs),
- GFP_KERNEL);
- if (!notifier->subdevs)
- return -ENOMEM;
+ v4l2_async_notifier_init(notifier);
ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(sdr->dev->of_node),
NULL);
if (!ep)
return 0;
- notifier->subdevs[notifier->num_subdevs] = &sdr->ep.asd;
fwnode = fwnode_graph_get_remote_port_parent(ep);
if (!fwnode) {
dev_warn(sdr->dev, "bad remote port parent\n");
@@ -1234,7 +1231,11 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
sdr->ep.asd.match.fwnode = fwnode;
sdr->ep.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
- notifier->num_subdevs++;
+ ret = v4l2_async_notifier_add_subdev(notifier, &sdr->ep.asd);
+ if (ret) {
+ fwnode_handle_put(fwnode);
+ return ret;
+ }
/* Get the endpoint properties */
rcar_drif_get_ep_properties(sdr, ep);
@@ -1356,11 +1357,13 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr)
ret = v4l2_async_notifier_register(&sdr->v4l2_dev, &sdr->notifier);
if (ret < 0) {
dev_err(sdr->dev, "failed: notifier register ret %d\n", ret);
- goto error;
+ goto cleanup;
}
return ret;
+cleanup:
+ v4l2_async_notifier_cleanup(&sdr->notifier);
error:
v4l2_device_unregister(&sdr->v4l2_dev);
@@ -1371,6 +1374,7 @@ error:
static void rcar_drif_sdr_remove(struct rcar_drif_sdr *sdr)
{
v4l2_async_notifier_unregister(&sdr->notifier);
+ v4l2_async_notifier_cleanup(&sdr->notifier);
v4l2_device_unregister(&sdr->v4l2_dev);
}
diff --git a/drivers/media/platform/rcar_fdp1.c b/drivers/media/platform/rcar_fdp1.c
index 2a15b7cca338..6bda1eee9170 100644
--- a/drivers/media/platform/rcar_fdp1.c
+++ b/drivers/media/platform/rcar_fdp1.c
@@ -1359,8 +1359,8 @@ static void device_frame_end(struct fdp1_dev *fdp1,
static int fdp1_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strlcpy(cap->driver, DRIVER_NAME, sizeof(cap->driver));
- strlcpy(cap->card, DRIVER_NAME, sizeof(cap->card));
+ strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver));
+ strscpy(cap->card, DRIVER_NAME, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:%s", DRIVER_NAME);
return 0;
@@ -2339,7 +2339,7 @@ static int fdp1_probe(struct platform_device *pdev)
vfd->lock = &fdp1->dev_mutex;
vfd->v4l2_dev = &fdp1->v4l2_dev;
video_set_drvdata(vfd, fdp1);
- strlcpy(vfd->name, fdp1_videodev.name, sizeof(vfd->name));
+ strscpy(vfd->name, fdp1_videodev.name, sizeof(vfd->name));
ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
if (ret) {
diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c
index e5c882423f57..1dfd2eb65920 100644
--- a/drivers/media/platform/rcar_jpu.c
+++ b/drivers/media/platform/rcar_jpu.c
@@ -664,11 +664,11 @@ static int jpu_querycap(struct file *file, void *priv,
struct jpu_ctx *ctx = fh_to_ctx(priv);
if (ctx->encoder)
- strlcpy(cap->card, DRV_NAME " encoder", sizeof(cap->card));
+ strscpy(cap->card, DRV_NAME " encoder", sizeof(cap->card));
else
- strlcpy(cap->card, DRV_NAME " decoder", sizeof(cap->card));
+ strscpy(cap->card, DRV_NAME " decoder", sizeof(cap->card));
- strlcpy(cap->driver, DRV_NAME, sizeof(cap->driver));
+ strscpy(cap->driver, DRV_NAME, sizeof(cap->driver));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(ctx->jpu->dev));
cap->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
@@ -1654,7 +1654,7 @@ static int jpu_probe(struct platform_device *pdev)
for (i = 0; i < JPU_MAX_QUALITY; i++)
jpu_generate_hdr(i, (unsigned char *)jpeg_hdrs[i]);
- strlcpy(jpu->vfd_encoder.name, DRV_NAME, sizeof(jpu->vfd_encoder.name));
+ strscpy(jpu->vfd_encoder.name, DRV_NAME, sizeof(jpu->vfd_encoder.name));
jpu->vfd_encoder.fops = &jpu_fops;
jpu->vfd_encoder.ioctl_ops = &jpu_ioctl_ops;
jpu->vfd_encoder.minor = -1;
@@ -1671,7 +1671,7 @@ static int jpu_probe(struct platform_device *pdev)
video_set_drvdata(&jpu->vfd_encoder, jpu);
- strlcpy(jpu->vfd_decoder.name, DRV_NAME, sizeof(jpu->vfd_decoder.name));
+ strscpy(jpu->vfd_decoder.name, DRV_NAME, sizeof(jpu->vfd_decoder.name));
jpu->vfd_decoder.fops = &jpu_fops;
jpu->vfd_decoder.ioctl_ops = &jpu_ioctl_ops;
jpu->vfd_decoder.minor = -1;
diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c
index ad782901cd7a..150196f7cf96 100644
--- a/drivers/media/platform/renesas-ceu.c
+++ b/drivers/media/platform/renesas-ceu.c
@@ -189,8 +189,6 @@ struct ceu_device {
/* async subdev notification helpers */
struct v4l2_async_notifier notifier;
- /* pointers to "struct ceu_subdevice -> asd" */
- struct v4l2_async_subdev **asds;
/* vb2 queue, capture buffer list and active buffer pointer */
struct vb2_queue vb2_vq;
@@ -1137,8 +1135,8 @@ static int ceu_querycap(struct file *file, void *priv,
{
struct ceu_device *ceudev = video_drvdata(file);
- strlcpy(cap->card, "Renesas CEU", sizeof(cap->card));
- strlcpy(cap->driver, DRIVER_NAME, sizeof(cap->driver));
+ strscpy(cap->card, "Renesas CEU", sizeof(cap->card));
+ strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:renesas-ceu-%s", dev_name(ceudev->dev));
@@ -1440,7 +1438,7 @@ static int ceu_notify_complete(struct v4l2_async_notifier *notifier)
return ret;
/* Register the video device. */
- strlcpy(vdev->name, DRIVER_NAME, sizeof(vdev->name));
+ strscpy(vdev->name, DRIVER_NAME, sizeof(vdev->name));
vdev->v4l2_dev = v4l2_dev;
vdev->lock = &ceudev->mlock;
vdev->queue = &ceudev->vb2_vq;
@@ -1482,15 +1480,6 @@ static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd)
if (!ceudev->subdevs)
return -ENOMEM;
- /*
- * Reserve memory for 'n_sd' pointers to async_subdevices.
- * ceudev->asds members will point to &ceu_subdev.asd
- */
- ceudev->asds = devm_kcalloc(ceudev->dev, n_sd,
- sizeof(*ceudev->asds), GFP_KERNEL);
- if (!ceudev->asds)
- return -ENOMEM;
-
ceudev->sd = NULL;
ceudev->sd_index = 0;
ceudev->num_sd = 0;
@@ -1518,6 +1507,7 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
return ret;
for (i = 0; i < pdata->num_subdevs; i++) {
+
/* Setup the ceu subdevice and the async subdevice. */
async_sd = &pdata->subdevs[i];
ceu_sd = &ceudev->subdevs[i];
@@ -1529,7 +1519,12 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id;
ceu_sd->asd.match.i2c.address = async_sd->i2c_address;
- ceudev->asds[i] = &ceu_sd->asd;
+ ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
+ &ceu_sd->asd);
+ if (ret) {
+ v4l2_async_notifier_cleanup(&ceudev->notifier);
+ return ret;
+ }
}
return pdata->num_subdevs;
@@ -1541,9 +1536,8 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
static int ceu_parse_dt(struct ceu_device *ceudev)
{
struct device_node *of = ceudev->dev->of_node;
- struct v4l2_fwnode_endpoint fw_ep;
+ struct device_node *ep, *remote;
struct ceu_subdev *ceu_sd;
- struct device_node *ep;
unsigned int i;
int num_ep;
int ret;
@@ -1557,45 +1551,55 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
return ret;
for (i = 0; i < num_ep; i++) {
+ struct v4l2_fwnode_endpoint fw_ep = {
+ .bus_type = V4L2_MBUS_PARALLEL,
+ .bus = {
+ .parallel = {
+ .flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+ V4L2_MBUS_VSYNC_ACTIVE_HIGH,
+ .bus_width = 8,
+ },
+ },
+ };
+
ep = of_graph_get_endpoint_by_regs(of, 0, i);
if (!ep) {
dev_err(ceudev->dev,
"No subdevice connected on endpoint %u.\n", i);
ret = -ENODEV;
- goto error_put_node;
+ goto error_cleanup;
}
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &fw_ep);
if (ret) {
dev_err(ceudev->dev,
- "Unable to parse endpoint #%u.\n", i);
- goto error_put_node;
- }
-
- if (fw_ep.bus_type != V4L2_MBUS_PARALLEL) {
- dev_err(ceudev->dev,
- "Only parallel input supported.\n");
- ret = -EINVAL;
- goto error_put_node;
+ "Unable to parse endpoint #%u: %d.\n", i, ret);
+ goto error_cleanup;
}
/* Setup the ceu subdevice and the async subdevice. */
ceu_sd = &ceudev->subdevs[i];
INIT_LIST_HEAD(&ceu_sd->asd.list);
+ remote = of_graph_get_remote_port_parent(ep);
ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
- ceu_sd->asd.match.fwnode =
- fwnode_graph_get_remote_port_parent(
- of_fwnode_handle(ep));
+ ceu_sd->asd.match.fwnode = of_fwnode_handle(remote);
+
+ ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
+ &ceu_sd->asd);
+ if (ret) {
+ of_node_put(remote);
+ goto error_cleanup;
+ }
- ceudev->asds[i] = &ceu_sd->asd;
of_node_put(ep);
}
return num_ep;
-error_put_node:
+error_cleanup:
+ v4l2_async_notifier_cleanup(&ceudev->notifier);
of_node_put(ep);
return ret;
}
@@ -1674,6 +1678,8 @@ static int ceu_probe(struct platform_device *pdev)
if (ret)
goto error_pm_disable;
+ v4l2_async_notifier_init(&ceudev->notifier);
+
if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
ceu_data = of_match_device(ceu_of_match, dev)->data;
num_subdevs = ceu_parse_dt(ceudev);
@@ -1693,18 +1699,18 @@ static int ceu_probe(struct platform_device *pdev)
ceudev->irq_mask = ceu_data->irq_mask;
ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev;
- ceudev->notifier.subdevs = ceudev->asds;
- ceudev->notifier.num_subdevs = num_subdevs;
ceudev->notifier.ops = &ceu_notify_ops;
ret = v4l2_async_notifier_register(&ceudev->v4l2_dev,
&ceudev->notifier);
if (ret)
- goto error_v4l2_unregister;
+ goto error_cleanup;
dev_info(dev, "Renesas Capture Engine Unit %s\n", dev_name(dev));
return 0;
+error_cleanup:
+ v4l2_async_notifier_cleanup(&ceudev->notifier);
error_v4l2_unregister:
v4l2_device_unregister(&ceudev->v4l2_dev);
error_pm_disable:
@@ -1723,6 +1729,8 @@ static int ceu_remove(struct platform_device *pdev)
v4l2_async_notifier_unregister(&ceudev->notifier);
+ v4l2_async_notifier_cleanup(&ceudev->notifier);
+
v4l2_device_unregister(&ceudev->v4l2_dev);
video_unregister_device(&ceudev->vdev);
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index ab5a6f95044a..9cc9db083870 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -447,9 +447,9 @@ static const struct v4l2_file_operations rga_fops = {
static int
vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
{
- strlcpy(cap->driver, RGA_NAME, sizeof(cap->driver));
- strlcpy(cap->card, "rockchip-rga", sizeof(cap->card));
- strlcpy(cap->bus_info, "platform:rga", sizeof(cap->bus_info));
+ strscpy(cap->driver, RGA_NAME, sizeof(cap->driver));
+ strscpy(cap->card, "rockchip-rga", sizeof(cap->card));
+ strscpy(cap->bus_info, "platform:rga", sizeof(cap->bus_info));
return 0;
}
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index c02dce8b4c6c..23b008d1a47b 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -640,8 +640,8 @@ static int s3c_camif_vidioc_querycap(struct file *file, void *priv,
{
struct camif_vp *vp = video_drvdata(file);
- strlcpy(cap->driver, S3C_CAMIF_DRIVER_NAME, sizeof(cap->driver));
- strlcpy(cap->card, S3C_CAMIF_DRIVER_NAME, sizeof(cap->card));
+ strscpy(cap->driver, S3C_CAMIF_DRIVER_NAME, sizeof(cap->driver));
+ strscpy(cap->card, S3C_CAMIF_DRIVER_NAME, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s.%d",
dev_name(vp->camif->dev), vp->id);
@@ -661,7 +661,7 @@ static int s3c_camif_vidioc_enum_input(struct file *file, void *priv,
return -EINVAL;
input->type = V4L2_INPUT_TYPE_CAMERA;
- strlcpy(input->name, sensor->name, sizeof(input->name));
+ strscpy(input->name, sensor->name, sizeof(input->name));
return 0;
}
@@ -688,7 +688,7 @@ static int s3c_camif_vidioc_enum_fmt(struct file *file, void *priv,
if (!fmt)
return -EINVAL;
- strlcpy(f->description, fmt->name, sizeof(f->description));
+ strscpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
pr_debug("fmt(%d): %s\n", f->index, f->description);
@@ -1555,7 +1555,7 @@ int s3c_camif_create_subdev(struct camif_dev *camif)
v4l2_subdev_init(sd, &s3c_camif_subdev_ops);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- strlcpy(sd->name, "S3C-CAMIF", sizeof(sd->name));
+ strscpy(sd->name, "S3C-CAMIF", sizeof(sd->name));
camif->pads[CAMIF_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
camif->pads[CAMIF_SD_PAD_SOURCE_C].flags = MEDIA_PAD_FL_SOURCE;
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
index 79bc0ef6bb41..31759f16458e 100644
--- a/drivers/media/platform/s3c-camif/camif-core.c
+++ b/drivers/media/platform/s3c-camif/camif-core.c
@@ -316,12 +316,12 @@ static int camif_media_dev_init(struct camif_dev *camif)
memset(md, 0, sizeof(*md));
snprintf(md->model, sizeof(md->model), "SAMSUNG S3C%s CAMIF",
ip_rev == S3C6410_CAMIF_IP_REV ? "6410" : "244X");
- strlcpy(md->bus_info, "platform", sizeof(md->bus_info));
+ strscpy(md->bus_info, "platform", sizeof(md->bus_info));
md->hw_revision = ip_rev;
md->dev = camif->dev;
- strlcpy(v4l2_dev->name, "s3c-camif", sizeof(v4l2_dev->name));
+ strscpy(v4l2_dev->name, "s3c-camif", sizeof(v4l2_dev->name));
v4l2_dev->mdev = md;
media_device_init(md);
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 04fd2e0493c0..3f9000b70385 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -1276,14 +1276,14 @@ static int s5p_jpeg_querycap(struct file *file, void *priv,
struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
if (ctx->mode == S5P_JPEG_ENCODE) {
- strlcpy(cap->driver, S5P_JPEG_M2M_NAME,
+ strscpy(cap->driver, S5P_JPEG_M2M_NAME,
sizeof(cap->driver));
- strlcpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
+ strscpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
sizeof(cap->card));
} else {
- strlcpy(cap->driver, S5P_JPEG_M2M_NAME,
+ strscpy(cap->driver, S5P_JPEG_M2M_NAME,
sizeof(cap->driver));
- strlcpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
+ strscpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
sizeof(cap->card));
}
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
@@ -1314,7 +1314,7 @@ static int enum_fmt(struct s5p_jpeg_fmt *sjpeg_formats, int n,
if (i >= n)
return -EINVAL;
- strlcpy(f->description, sjpeg_formats[i].name, sizeof(f->description));
+ strscpy(f->description, sjpeg_formats[i].name, sizeof(f->description));
f->pixelformat = sjpeg_formats[i].fourcc;
return 0;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 6a3cc4f86c5d..670ca869babb 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -271,8 +271,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct s5p_mfc_dev *dev = video_drvdata(file);
- strlcpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));
- strlcpy(cap->card, dev->vfd_dec->name, sizeof(cap->card));
+ strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));
+ strscpy(cap->card, dev->vfd_dec->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(&dev->plat_dev->dev));
/*
@@ -308,7 +308,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,
if (i == ARRAY_SIZE(formats))
return -EINVAL;
fmt = &formats[i];
- strlcpy(f->description, fmt->name, sizeof(f->description));
+ strscpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
return 0;
}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 3ad4f5073002..7037d48bdc2c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -1313,8 +1313,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct s5p_mfc_dev *dev = video_drvdata(file);
- strlcpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));
- strlcpy(cap->card, dev->vfd_enc->name, sizeof(cap->card));
+ strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));
+ strscpy(cap->card, dev->vfd_enc->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(&dev->plat_dev->dev));
/*
@@ -1344,7 +1344,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,
if (j == f->index) {
fmt = &formats[i];
- strlcpy(f->description, fmt->name,
+ strscpy(f->description, fmt->name,
sizeof(f->description));
f->pixelformat = fmt->fourcc;
return 0;
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index 1d274c64de09..09ae64a0004c 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -345,9 +345,9 @@ static int sh_veu_context_init(struct sh_veu_dev *veu)
static int sh_veu_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strlcpy(cap->driver, "sh-veu", sizeof(cap->driver));
- strlcpy(cap->card, "sh-mobile VEU", sizeof(cap->card));
- strlcpy(cap->bus_info, "platform:sh-veu", sizeof(cap->bus_info));
+ strscpy(cap->driver, "sh-veu", sizeof(cap->driver));
+ strscpy(cap->card, "sh-mobile VEU", sizeof(cap->card));
+ strscpy(cap->bus_info, "platform:sh-veu", sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -359,7 +359,8 @@ static int sh_veu_enum_fmt(struct v4l2_fmtdesc *f, const int *fmt, int fmt_num)
if (f->index >= fmt_num)
return -EINVAL;
- strlcpy(f->description, sh_veu_fmt[fmt[f->index]].name, sizeof(f->description));
+ strscpy(f->description, sh_veu_fmt[fmt[f->index]].name,
+ sizeof(f->description));
f->pixelformat = sh_veu_fmt[fmt[f->index]].fourcc;
return 0;
}
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index 6135e13e24d4..cee58b125548 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -378,9 +378,9 @@ static int sh_vou_querycap(struct file *file, void *priv,
dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
- strlcpy(cap->card, "SuperH VOU", sizeof(cap->card));
- strlcpy(cap->driver, "sh-vou", sizeof(cap->driver));
- strlcpy(cap->bus_info, "platform:sh-vou", sizeof(cap->bus_info));
+ strscpy(cap->card, "SuperH VOU", sizeof(cap->card));
+ strscpy(cap->driver, "sh-vou", sizeof(cap->driver));
+ strscpy(cap->bus_info, "platform:sh-vou", sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -399,7 +399,7 @@ static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv,
dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- strlcpy(fmt->description, vou_fmt[fmt->index].desc,
+ strscpy(fmt->description, vou_fmt[fmt->index].desc,
sizeof(fmt->description));
fmt->pixelformat = vou_fmt[fmt->index].pfmt;
@@ -790,7 +790,7 @@ static int sh_vou_enum_output(struct file *file, void *fh,
if (a->index)
return -EINVAL;
- strlcpy(a->name, "Video Out", sizeof(a->name));
+ strscpy(a->name, "Video Out", sizeof(a->name));
a->type = V4L2_OUTPUT_TYPE_ANALOG;
a->std = vou_dev->vdev.tvnorms;
return 0;
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 0a2c0daaffef..6803f744e307 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -1564,9 +1564,9 @@ static __poll_t sh_mobile_ceu_poll(struct file *file, poll_table *pt)
static int sh_mobile_ceu_querycap(struct soc_camera_host *ici,
struct v4l2_capability *cap)
{
- strlcpy(cap->card, "SuperH_Mobile_CEU", sizeof(cap->card));
- strlcpy(cap->driver, "sh_mobile_ceu", sizeof(cap->driver));
- strlcpy(cap->bus_info, "platform:sh_mobile_ceu", sizeof(cap->bus_info));
+ strscpy(cap->card, "SuperH_Mobile_CEU", sizeof(cap->card));
+ strscpy(cap->driver, "sh_mobile_ceu", sizeof(cap->driver));
+ strscpy(cap->bus_info, "platform:sh_mobile_ceu", sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 66d613629167..0a70fb67c401 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -312,7 +312,7 @@ static int soc_camera_enum_input(struct file *file, void *priv,
/* default is camera */
inp->type = V4L2_INPUT_TYPE_CAMERA;
inp->std = icd->vdev->tvnorms;
- strcpy(inp->name, "Camera");
+ strscpy(inp->name, "Camera", sizeof(inp->name));
return 0;
}
@@ -874,7 +874,7 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
format = icd->user_formats[f->index].host_fmt;
if (format->name)
- strlcpy(f->description, format->name, sizeof(f->description));
+ strscpy(f->description, format->name, sizeof(f->description));
f->pixelformat = format->fourcc;
return 0;
}
@@ -910,7 +910,7 @@ static int soc_camera_querycap(struct file *file, void *priv,
WARN_ON(priv != file->private_data);
- strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver));
+ strscpy(cap->driver, ici->drv_name, sizeof(cap->driver));
return ici->ops->querycap(ici, cap);
}
@@ -1442,8 +1442,14 @@ static int scan_async_group(struct soc_camera_host *ici,
goto eaddpdev;
}
- sasc->notifier.subdevs = asd;
- sasc->notifier.num_subdevs = size;
+ v4l2_async_notifier_init(&sasc->notifier);
+
+ for (i = 0; i < size; i++) {
+ ret = v4l2_async_notifier_add_subdev(&sasc->notifier, asd[i]);
+ if (ret)
+ goto eaddasd;
+ }
+
sasc->notifier.ops = &soc_camera_async_ops;
icd->sasc = sasc;
@@ -1466,6 +1472,8 @@ static int scan_async_group(struct soc_camera_host *ici,
v4l2_clk_unregister(icd->clk);
eclkreg:
icd->clk = NULL;
+eaddasd:
+ v4l2_async_notifier_cleanup(&sasc->notifier);
platform_device_del(sasc->pdev);
eaddpdev:
platform_device_put(sasc->pdev);
@@ -1540,8 +1548,14 @@ static int soc_of_bind(struct soc_camera_host *ici,
goto eaddpdev;
}
- sasc->notifier.subdevs = &info->subdev;
- sasc->notifier.num_subdevs = 1;
+ v4l2_async_notifier_init(&sasc->notifier);
+
+ ret = v4l2_async_notifier_add_subdev(&sasc->notifier, info->subdev);
+ if (ret) {
+ of_node_put(remote);
+ goto eaddasd;
+ }
+
sasc->notifier.ops = &soc_camera_async_ops;
icd->sasc = sasc;
@@ -1568,6 +1582,8 @@ static int soc_of_bind(struct soc_camera_host *ici,
v4l2_clk_unregister(icd->clk);
eclkreg:
icd->clk = NULL;
+eaddasd:
+ v4l2_async_notifier_cleanup(&sasc->notifier);
platform_device_del(sasc->pdev);
eaddpdev:
platform_device_put(sasc->pdev);
@@ -1582,7 +1598,7 @@ static void scan_of_host(struct soc_camera_host *ici)
{
struct device *dev = ici->v4l2_dev.dev;
struct device_node *np = dev->of_node;
- struct device_node *epn = NULL, *ren;
+ struct device_node *epn = NULL, *rem;
unsigned int i;
for (i = 0; ; i++) {
@@ -1590,17 +1606,15 @@ static void scan_of_host(struct soc_camera_host *ici)
if (!epn)
break;
- ren = of_graph_get_remote_port(epn);
- if (!ren) {
+ rem = of_graph_get_remote_port_parent(epn);
+ if (!rem) {
dev_notice(dev, "no remote for %pOF\n", epn);
continue;
}
/* so we now have a remote node to connect */
if (!i)
- soc_of_bind(ici, epn, ren->parent);
-
- of_node_put(ren);
+ soc_of_bind(ici, epn, rem);
if (i) {
dev_err(dev, "multiple subdevices aren't supported yet!\n");
@@ -1926,6 +1940,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
list_for_each_entry(sasc, &notifiers, list) {
/* Must call unlocked to avoid AB-BA dead-lock */
v4l2_async_notifier_unregister(&sasc->notifier);
+ v4l2_async_notifier_cleanup(&sasc->notifier);
put_device(&sasc->pdev->dev);
}
@@ -2026,7 +2041,7 @@ static int video_dev_create(struct soc_camera_device *icd)
if (!vdev)
return -ENOMEM;
- strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
+ strscpy(vdev->name, ici->drv_name, sizeof(vdev->name));
vdev->v4l2_dev = &ici->v4l2_dev;
vdev->fops = &soc_camera_fops;
diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c
index 6745a6e3f464..79fbe1fea95f 100644
--- a/drivers/media/platform/soc_camera/soc_camera_platform.c
+++ b/drivers/media/platform/soc_camera/soc_camera_platform.c
@@ -156,7 +156,7 @@ static int soc_camera_platform_probe(struct platform_device *pdev)
v4l2_subdev_init(&priv->subdev, &platform_subdev_ops);
v4l2_set_subdevdata(&priv->subdev, p);
- strlcpy(priv->subdev.name, dev_name(&pdev->dev),
+ strscpy(priv->subdev.name, dev_name(&pdev->dev),
sizeof(priv->subdev.name));
return v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev);
diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c
index 0ad4b28266e4..be74008ec0ca 100644
--- a/drivers/media/platform/soc_camera/soc_mediabus.c
+++ b/drivers/media/platform/soc_camera/soc_mediabus.c
@@ -503,7 +503,7 @@ unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
return (!hsync || !vsync || !pclk || !data || !mode) ?
0 : common_flags;
- case V4L2_MBUS_CSI2:
+ case V4L2_MBUS_CSI2_DPHY:
mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c
index 6164102e6f9f..8d25ca0490f7 100644
--- a/drivers/media/platform/soc_camera/soc_scale_crop.c
+++ b/drivers/media/platform/soc_camera/soc_scale_crop.c
@@ -52,7 +52,7 @@ int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect)
return ret;
}
- sdsel.target = V4L2_SEL_TGT_CROP_DEFAULT;
+ sdsel.target = V4L2_SEL_TGT_CROP_BOUNDS;
ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel);
if (!ret)
*rect = sdsel.r;
diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
index 66b64096f5de..79f7db1a9d18 100644
--- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
+++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
@@ -688,8 +688,8 @@ static int bdisp_querycap(struct file *file, void *fh,
struct bdisp_ctx *ctx = fh_to_ctx(fh);
struct bdisp_dev *bdisp = ctx->bdisp_dev;
- strlcpy(cap->driver, bdisp->pdev->name, sizeof(cap->driver));
- strlcpy(cap->card, bdisp->pdev->name, sizeof(cap->card));
+ strscpy(cap->driver, bdisp->pdev->name, sizeof(cap->driver));
+ strscpy(cap->card, bdisp->pdev->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d",
BDISP_NAME, bdisp->id);
diff --git a/drivers/media/platform/sti/delta/delta-v4l2.c b/drivers/media/platform/sti/delta/delta-v4l2.c
index 0b42acd4e3a6..91369fb3ffaa 100644
--- a/drivers/media/platform/sti/delta/delta-v4l2.c
+++ b/drivers/media/platform/sti/delta/delta-v4l2.c
@@ -385,8 +385,8 @@ static int delta_querycap(struct file *file, void *priv,
struct delta_ctx *ctx = to_ctx(file->private_data);
struct delta_dev *delta = ctx->dev;
- strlcpy(cap->driver, DELTA_NAME, sizeof(cap->driver));
- strlcpy(cap->card, delta->vdev->name, sizeof(cap->card));
+ strscpy(cap->driver, DELTA_NAME, sizeof(cap->driver));
+ strscpy(cap->card, delta->vdev->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
delta->pdev->name);
diff --git a/drivers/media/platform/sti/hva/hva-v4l2.c b/drivers/media/platform/sti/hva/hva-v4l2.c
index 5a807c7c5e79..c42623dccfd6 100644
--- a/drivers/media/platform/sti/hva/hva-v4l2.c
+++ b/drivers/media/platform/sti/hva/hva-v4l2.c
@@ -257,8 +257,8 @@ static int hva_querycap(struct file *file, void *priv,
struct hva_ctx *ctx = fh_to_ctx(file->private_data);
struct hva_dev *hva = ctx_to_hdev(ctx);
- strlcpy(cap->driver, HVA_NAME, sizeof(cap->driver));
- strlcpy(cap->card, hva->vdev->name, sizeof(cap->card));
+ strscpy(cap->driver, HVA_NAME, sizeof(cap->driver));
+ strscpy(cap->card, hva->vdev->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
hva->pdev->name);
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index 721564176d8c..6732874114cf 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -659,7 +659,10 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
}
/* Enable interruptions */
- reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
+ if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG)
+ reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
+ else
+ reg_set(dcmi->regs, DCMI_IER, IT_OVR | IT_ERR);
return 0;
@@ -1147,10 +1150,10 @@ static int dcmi_s_selection(struct file *file, void *priv,
static int dcmi_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strlcpy(cap->driver, DRV_NAME, sizeof(cap->driver));
- strlcpy(cap->card, "STM32 Camera Memory Interface",
+ strscpy(cap->driver, DRV_NAME, sizeof(cap->driver));
+ strscpy(cap->card, "STM32 Camera Memory Interface",
sizeof(cap->card));
- strlcpy(cap->bus_info, "platform:dcmi", sizeof(cap->bus_info));
+ strscpy(cap->bus_info, "platform:dcmi", sizeof(cap->bus_info));
return 0;
}
@@ -1161,7 +1164,7 @@ static int dcmi_enum_input(struct file *file, void *priv,
return -EINVAL;
i->type = V4L2_INPUT_TYPE_CAMERA;
- strlcpy(i->name, "Camera", sizeof(i->name));
+ strscpy(i->name, "Camera", sizeof(i->name));
return 0;
}
@@ -1587,7 +1590,6 @@ static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node)
static int dcmi_graph_init(struct stm32_dcmi *dcmi)
{
- struct v4l2_async_subdev **subdevs = NULL;
int ret;
/* Parse the graph to extract a list of subdevice DT nodes. */
@@ -1597,23 +1599,21 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi)
return ret;
}
- /* Register the subdevices notifier. */
- subdevs = devm_kzalloc(dcmi->dev, sizeof(*subdevs), GFP_KERNEL);
- if (!subdevs) {
+ v4l2_async_notifier_init(&dcmi->notifier);
+
+ ret = v4l2_async_notifier_add_subdev(&dcmi->notifier,
+ &dcmi->entity.asd);
+ if (ret) {
of_node_put(dcmi->entity.node);
- return -ENOMEM;
+ return ret;
}
- subdevs[0] = &dcmi->entity.asd;
-
- dcmi->notifier.subdevs = subdevs;
- dcmi->notifier.num_subdevs = 1;
dcmi->notifier.ops = &dcmi_graph_notify_ops;
ret = v4l2_async_notifier_register(&dcmi->v4l2_dev, &dcmi->notifier);
if (ret < 0) {
dev_err(dcmi->dev, "Notifier registration failed\n");
- of_node_put(dcmi->entity.node);
+ v4l2_async_notifier_cleanup(&dcmi->notifier);
return ret;
}
@@ -1624,7 +1624,7 @@ static int dcmi_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match = NULL;
- struct v4l2_fwnode_endpoint ep;
+ struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
struct stm32_dcmi *dcmi;
struct vb2_queue *q;
struct dma_chan *chan;
@@ -1663,7 +1663,7 @@ static int dcmi_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (ep.bus_type == V4L2_MBUS_CSI2) {
+ if (ep.bus_type == V4L2_MBUS_CSI2_DPHY) {
dev_err(&pdev->dev, "CSI bus not supported\n");
return -ENODEV;
}
@@ -1736,7 +1736,7 @@ static int dcmi_probe(struct platform_device *pdev)
dcmi->vdev->fops = &dcmi_fops;
dcmi->vdev->v4l2_dev = &dcmi->v4l2_dev;
dcmi->vdev->queue = &dcmi->queue;
- strlcpy(dcmi->vdev->name, KBUILD_MODNAME, sizeof(dcmi->vdev->name));
+ strscpy(dcmi->vdev->name, KBUILD_MODNAME, sizeof(dcmi->vdev->name));
dcmi->vdev->release = video_device_release;
dcmi->vdev->ioctl_ops = &dcmi_ioctl_ops;
dcmi->vdev->lock = &dcmi->lock;
@@ -1770,7 +1770,7 @@ static int dcmi_probe(struct platform_device *pdev)
ret = reset_control_assert(dcmi->rstc);
if (ret) {
dev_err(&pdev->dev, "Failed to assert the reset line\n");
- goto err_device_release;
+ goto err_cleanup;
}
usleep_range(3000, 5000);
@@ -1778,7 +1778,7 @@ static int dcmi_probe(struct platform_device *pdev)
ret = reset_control_deassert(dcmi->rstc);
if (ret) {
dev_err(&pdev->dev, "Failed to deassert the reset line\n");
- goto err_device_release;
+ goto err_cleanup;
}
dev_info(&pdev->dev, "Probe done\n");
@@ -1789,6 +1789,8 @@ static int dcmi_probe(struct platform_device *pdev)
return 0;
+err_cleanup:
+ v4l2_async_notifier_cleanup(&dcmi->notifier);
err_device_release:
video_device_release(dcmi->vdev);
err_device_unregister:
@@ -1806,6 +1808,7 @@ static int dcmi_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
v4l2_async_notifier_unregister(&dcmi->notifier);
+ v4l2_async_notifier_cleanup(&dcmi->notifier);
v4l2_device_unregister(&dcmi->v4l2_dev);
dma_release_channel(dcmi->dma_chan);
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index d1febe5baa6d..95a093f41905 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -270,7 +270,6 @@ struct cal_ctx {
struct v4l2_fwnode_endpoint endpoint;
struct v4l2_async_subdev asd;
- struct v4l2_async_subdev *asd_list[1];
struct v4l2_fh fh;
struct cal_dev *dev;
@@ -912,8 +911,8 @@ static int cal_querycap(struct file *file, void *priv,
{
struct cal_ctx *ctx = video_drvdata(file);
- strlcpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver));
- strlcpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card));
+ strscpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver));
+ strscpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:%s", ctx->v4l2_dev.name);
@@ -1711,9 +1710,9 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
}
v4l2_fwnode_endpoint_parse(of_fwnode_handle(remote_ep), endpoint);
- if (endpoint->bus_type != V4L2_MBUS_CSI2) {
- ctx_err(ctx, "Port:%d sub-device %s is not a CSI2 device\n",
- inst, sensor_node->name);
+ if (endpoint->bus_type != V4L2_MBUS_CSI2_DPHY) {
+ ctx_err(ctx, "Port:%d sub-device %pOFn is not a CSI2 device\n",
+ inst, sensor_node);
goto cleanup_exit;
}
@@ -1732,29 +1731,38 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
endpoint->bus.mipi_csi2.data_lanes[lane]);
ctx_dbg(3, ctx, "\t>\n");
- ctx_dbg(1, ctx, "Port: %d found sub-device %s\n",
- inst, sensor_node->name);
+ ctx_dbg(1, ctx, "Port: %d found sub-device %pOFn\n",
+ inst, sensor_node);
+
+ v4l2_async_notifier_init(&ctx->notifier);
+
+ ret = v4l2_async_notifier_add_subdev(&ctx->notifier, asd);
+ if (ret) {
+ ctx_err(ctx, "Error adding asd\n");
+ goto cleanup_exit;
+ }
- ctx->asd_list[0] = asd;
- ctx->notifier.subdevs = ctx->asd_list;
- ctx->notifier.num_subdevs = 1;
ctx->notifier.ops = &cal_async_ops;
ret = v4l2_async_notifier_register(&ctx->v4l2_dev,
&ctx->notifier);
if (ret) {
ctx_err(ctx, "Error registering async notifier\n");
+ v4l2_async_notifier_cleanup(&ctx->notifier);
ret = -EINVAL;
}
+ /*
+ * On success we need to keep reference on sensor_node, or
+ * if notifier_cleanup was called above, sensor_node was
+ * already put.
+ */
+ sensor_node = NULL;
+
cleanup_exit:
- if (remote_ep)
- of_node_put(remote_ep);
- if (sensor_node)
- of_node_put(sensor_node);
- if (ep_node)
- of_node_put(ep_node);
- if (port)
- of_node_put(port);
+ of_node_put(remote_ep);
+ of_node_put(sensor_node);
+ of_node_put(ep_node);
+ of_node_put(port);
return ret;
}
@@ -1810,15 +1818,17 @@ err_exit:
static int cal_probe(struct platform_device *pdev)
{
struct cal_dev *dev;
+ struct cal_ctx *ctx;
int ret;
int irq;
+ int i;
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
/* set pseudo v4l2 device name so we can use v4l2_printk */
- strlcpy(dev->v4l2_dev.name, CAL_MODULE_NAME,
+ strscpy(dev->v4l2_dev.name, CAL_MODULE_NAME,
sizeof(dev->v4l2_dev.name));
/* save pdev pointer */
@@ -1879,6 +1889,16 @@ static int cal_probe(struct platform_device *pdev)
runtime_disable:
pm_runtime_disable(&pdev->dev);
+ for (i = 0; i < CAL_NUM_CONTEXT; i++) {
+ ctx = dev->ctx[i];
+ if (ctx) {
+ v4l2_async_notifier_unregister(&ctx->notifier);
+ v4l2_async_notifier_cleanup(&ctx->notifier);
+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+ v4l2_device_unregister(&ctx->v4l2_dev);
+ }
+ }
+
return ret;
}
@@ -1900,6 +1920,7 @@ static int cal_remove(struct platform_device *pdev)
video_device_node_name(&ctx->vdev));
camerarx_phy_disable(ctx);
v4l2_async_notifier_unregister(&ctx->notifier);
+ v4l2_async_notifier_cleanup(&ctx->notifier);
v4l2_ctrl_handler_free(&ctx->ctrl_handler);
v4l2_device_unregister(&ctx->v4l2_dev);
video_unregister_device(&ctx->vdev);
diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c
index c8bb82fe0b9d..24d5759501a5 100644
--- a/drivers/media/platform/via-camera.c
+++ b/drivers/media/platform/via-camera.c
@@ -812,7 +812,7 @@ static int viacam_enum_input(struct file *filp, void *priv,
input->type = V4L2_INPUT_TYPE_CAMERA;
input->std = V4L2_STD_ALL; /* Not sure what should go here */
- strcpy(input->name, "Camera");
+ strscpy(input->name, "Camera", sizeof(input->name));
return 0;
}
@@ -860,8 +860,8 @@ static int viacam_enum_fmt_vid_cap(struct file *filp, void *priv,
{
if (fmt->index >= N_VIA_FMTS)
return -EINVAL;
- strlcpy(fmt->description, via_formats[fmt->index].desc,
- sizeof(fmt->description));
+ strscpy(fmt->description, via_formats[fmt->index].desc,
+ sizeof(fmt->description));
fmt->pixelformat = via_formats[fmt->index].pixelformat;
return 0;
}
@@ -990,8 +990,8 @@ out:
static int viacam_querycap(struct file *filp, void *priv,
struct v4l2_capability *cap)
{
- strcpy(cap->driver, "via-camera");
- strcpy(cap->card, "via-camera");
+ strscpy(cap->driver, "via-camera", sizeof(cap->driver));
+ strscpy(cap->card, "via-camera", sizeof(cap->card));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
diff --git a/drivers/media/platform/vicodec/Kconfig b/drivers/media/platform/vicodec/Kconfig
index 2503bcb1529f..ad13329e3461 100644
--- a/drivers/media/platform/vicodec/Kconfig
+++ b/drivers/media/platform/vicodec/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_VICODEC
tristate "Virtual Codec Driver"
- depends on VIDEO_DEV && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_DEV && VIDEO_V4L2
select VIDEOBUF2_VMALLOC
select V4L2_MEM2MEM_DEV
default n
diff --git a/drivers/media/platform/vicodec/Makefile b/drivers/media/platform/vicodec/Makefile
index 197229428953..01bf7e9308a6 100644
--- a/drivers/media/platform/vicodec/Makefile
+++ b/drivers/media/platform/vicodec/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-vicodec-objs := vicodec-core.o vicodec-codec.o
+vicodec-objs := vicodec-core.o codec-fwht.o codec-v4l2-fwht.o
obj-$(CONFIG_VIDEO_VICODEC) += vicodec.o
diff --git a/drivers/media/platform/vicodec/vicodec-codec.c b/drivers/media/platform/vicodec/codec-fwht.c
index 2d047646f614..36656031b295 100644
--- a/drivers/media/platform/vicodec/vicodec-codec.c
+++ b/drivers/media/platform/vicodec/codec-fwht.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: LGPL-2.1+
/*
* Copyright 2016 Tom aan de Wiel
* Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
@@ -10,10 +10,20 @@
*/
#include <linux/string.h>
-#include "vicodec-codec.h"
+#include "codec-fwht.h"
+
+/*
+ * Note: bit 0 of the header must always be 0. Otherwise it cannot
+ * be guaranteed that the magic 8 byte sequence (see below) can
+ * never occur in the rlc output.
+ */
+#define PFRAME_BIT BIT(15)
+#define DUPS_MASK 0x1ffe
+
+#define PBLOCK 0
+#define IBLOCK 1
#define ALL_ZEROS 15
-#define DEADZONE_WIDTH 20
static const uint8_t zigzag[64] = {
0,
@@ -164,7 +174,7 @@ static const int quant_table_p[] = {
3, 3, 3, 6, 6, 9, 9, 10,
};
-static void quantize_intra(s16 *coeff, s16 *de_coeff)
+static void quantize_intra(s16 *coeff, s16 *de_coeff, u16 qp)
{
const int *quant = quant_table;
int i, j;
@@ -172,8 +182,7 @@ static void quantize_intra(s16 *coeff, s16 *de_coeff)
for (j = 0; j < 8; j++) {
for (i = 0; i < 8; i++, quant++, coeff++, de_coeff++) {
*coeff >>= *quant;
- if (*coeff >= -DEADZONE_WIDTH &&
- *coeff <= DEADZONE_WIDTH)
+ if (*coeff >= -qp && *coeff <= qp)
*coeff = *de_coeff = 0;
else
*de_coeff = *coeff << *quant;
@@ -191,7 +200,7 @@ static void dequantize_intra(s16 *coeff)
*coeff <<= *quant;
}
-static void quantize_inter(s16 *coeff, s16 *de_coeff)
+static void quantize_inter(s16 *coeff, s16 *de_coeff, u16 qp)
{
const int *quant = quant_table_p;
int i, j;
@@ -199,8 +208,7 @@ static void quantize_inter(s16 *coeff, s16 *de_coeff)
for (j = 0; j < 8; j++) {
for (i = 0; i < 8; i++, quant++, coeff++, de_coeff++) {
*coeff >>= *quant;
- if (*coeff >= -DEADZONE_WIDTH &&
- *coeff <= DEADZONE_WIDTH)
+ if (*coeff >= -qp && *coeff <= qp)
*coeff = *de_coeff = 0;
else
*de_coeff = *coeff << *quant;
@@ -232,7 +240,8 @@ static void fwht(const u8 *block, s16 *output_block, unsigned int stride,
stride *= input_step;
for (i = 0; i < 8; i++, tmp += stride, out += 8) {
- if (input_step == 1) {
+ switch (input_step) {
+ case 1:
workspace1[0] = tmp[0] + tmp[1] - add;
workspace1[1] = tmp[0] - tmp[1];
@@ -244,7 +253,8 @@ static void fwht(const u8 *block, s16 *output_block, unsigned int stride,
workspace1[6] = tmp[6] + tmp[7] - add;
workspace1[7] = tmp[6] - tmp[7];
- } else {
+ break;
+ case 2:
workspace1[0] = tmp[0] + tmp[2] - add;
workspace1[1] = tmp[0] - tmp[2];
@@ -256,6 +266,33 @@ static void fwht(const u8 *block, s16 *output_block, unsigned int stride,
workspace1[6] = tmp[12] + tmp[14] - add;
workspace1[7] = tmp[12] - tmp[14];
+ break;
+ case 3:
+ workspace1[0] = tmp[0] + tmp[3] - add;
+ workspace1[1] = tmp[0] - tmp[3];
+
+ workspace1[2] = tmp[6] + tmp[9] - add;
+ workspace1[3] = tmp[6] - tmp[9];
+
+ workspace1[4] = tmp[12] + tmp[15] - add;
+ workspace1[5] = tmp[12] - tmp[15];
+
+ workspace1[6] = tmp[18] + tmp[21] - add;
+ workspace1[7] = tmp[18] - tmp[21];
+ break;
+ default:
+ workspace1[0] = tmp[0] + tmp[4] - add;
+ workspace1[1] = tmp[0] - tmp[4];
+
+ workspace1[2] = tmp[8] + tmp[12] - add;
+ workspace1[3] = tmp[8] - tmp[12];
+
+ workspace1[4] = tmp[16] + tmp[20] - add;
+ workspace1[5] = tmp[16] - tmp[20];
+
+ workspace1[6] = tmp[24] + tmp[28] - add;
+ workspace1[7] = tmp[24] - tmp[28];
+ break;
}
/* stage 2 */
@@ -588,8 +625,14 @@ static void fill_decoder_block(u8 *dst, const s16 *input, int stride)
int i, j;
for (i = 0; i < 8; i++) {
- for (j = 0; j < 8; j++)
- *dst++ = *input++;
+ for (j = 0; j < 8; j++, input++, dst++) {
+ if (*input < 0)
+ *dst = 0;
+ else if (*input > 255)
+ *dst = 255;
+ else
+ *dst = *input;
+ }
dst += stride - 8;
}
}
@@ -616,7 +659,7 @@ static void add_deltas(s16 *deltas, const u8 *ref, int stride)
}
static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
- struct cframe *cf, u32 height, u32 width,
+ struct fwht_cframe *cf, u32 height, u32 width,
unsigned int input_step,
bool is_intra, bool next_is_intra)
{
@@ -637,15 +680,16 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
if (!is_intra)
blocktype = decide_blocktype(input, refp,
deltablock, width, input_step);
- if (is_intra || blocktype == IBLOCK) {
+ if (blocktype == IBLOCK) {
fwht(input, cf->coeffs, width, input_step, 1);
- quantize_intra(cf->coeffs, cf->de_coeffs);
- blocktype = IBLOCK;
+ quantize_intra(cf->coeffs, cf->de_coeffs,
+ cf->i_frame_qp);
} else {
/* inter code */
- encoding |= FRAME_PCODED;
+ encoding |= FWHT_FRAME_PCODED;
fwht16(deltablock, cf->coeffs, 8, 0);
- quantize_inter(cf->coeffs, cf->de_coeffs);
+ quantize_inter(cf->coeffs, cf->de_coeffs,
+ cf->p_frame_qp);
}
if (!next_is_intra) {
ifwht(cf->de_coeffs, cf->de_fwht, blocktype);
@@ -658,9 +702,6 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
input += 8 * input_step;
refp += 8 * 8;
- if (encoding & FRAME_UNENCODED)
- continue;
-
size = rlc(cf->coeffs, *rlco, blocktype);
if (last_size == size &&
!memcmp(*rlco + 1, *rlco - size + 1, 2 * size - 2)) {
@@ -675,13 +716,17 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
} else {
*rlco += size;
}
- if (*rlco >= rlco_max)
- encoding |= FRAME_UNENCODED;
+ if (*rlco >= rlco_max) {
+ encoding |= FWHT_FRAME_UNENCODED;
+ goto exit_loop;
+ }
last_size = size;
}
input += width * 7 * input_step;
}
- if (encoding & FRAME_UNENCODED) {
+
+exit_loop:
+ if (encoding & FWHT_FRAME_UNENCODED) {
u8 *out = (u8 *)rlco_start;
input = input_start;
@@ -694,44 +739,50 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
for (i = 0; i < height * width; i++, input += input_step)
*out++ = (*input == 0xff) ? 0xfe : *input;
*rlco = (__be16 *)out;
+ encoding &= ~FWHT_FRAME_PCODED;
}
return encoding;
}
-u32 encode_frame(struct raw_frame *frm, struct raw_frame *ref_frm,
- struct cframe *cf, bool is_intra, bool next_is_intra)
+u32 fwht_encode_frame(struct fwht_raw_frame *frm,
+ struct fwht_raw_frame *ref_frm,
+ struct fwht_cframe *cf,
+ bool is_intra, bool next_is_intra)
{
unsigned int size = frm->height * frm->width;
__be16 *rlco = cf->rlc_data;
__be16 *rlco_max;
u32 encoding;
+ u32 chroma_h = frm->height / frm->height_div;
+ u32 chroma_w = frm->width / frm->width_div;
+ unsigned int chroma_size = chroma_h * chroma_w;
rlco_max = rlco + size / 2 - 256;
encoding = encode_plane(frm->luma, ref_frm->luma, &rlco, rlco_max, cf,
- frm->height, frm->width,
- 1, is_intra, next_is_intra);
- if (encoding & FRAME_UNENCODED)
- encoding |= LUMA_UNENCODED;
- encoding &= ~FRAME_UNENCODED;
- rlco_max = rlco + size / 8 - 256;
+ frm->height, frm->width,
+ frm->luma_step, is_intra, next_is_intra);
+ if (encoding & FWHT_FRAME_UNENCODED)
+ encoding |= FWHT_LUMA_UNENCODED;
+ encoding &= ~FWHT_FRAME_UNENCODED;
+ rlco_max = rlco + chroma_size / 2 - 256;
encoding |= encode_plane(frm->cb, ref_frm->cb, &rlco, rlco_max, cf,
- frm->height / 2, frm->width / 2,
- frm->chroma_step, is_intra, next_is_intra);
- if (encoding & FRAME_UNENCODED)
- encoding |= CB_UNENCODED;
- encoding &= ~FRAME_UNENCODED;
- rlco_max = rlco + size / 8 - 256;
+ chroma_h, chroma_w,
+ frm->chroma_step, is_intra, next_is_intra);
+ if (encoding & FWHT_FRAME_UNENCODED)
+ encoding |= FWHT_CB_UNENCODED;
+ encoding &= ~FWHT_FRAME_UNENCODED;
+ rlco_max = rlco + chroma_size / 2 - 256;
encoding |= encode_plane(frm->cr, ref_frm->cr, &rlco, rlco_max, cf,
- frm->height / 2, frm->width / 2,
- frm->chroma_step, is_intra, next_is_intra);
- if (encoding & FRAME_UNENCODED)
- encoding |= CR_UNENCODED;
- encoding &= ~FRAME_UNENCODED;
+ chroma_h, chroma_w,
+ frm->chroma_step, is_intra, next_is_intra);
+ if (encoding & FWHT_FRAME_UNENCODED)
+ encoding |= FWHT_CR_UNENCODED;
+ encoding &= ~FWHT_FRAME_UNENCODED;
cf->size = (rlco - cf->rlc_data) * sizeof(*rlco);
return encoding;
}
-static void decode_plane(struct cframe *cf, const __be16 **rlco, u8 *ref,
+static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref,
u32 height, u32 width, bool uncompressed)
{
unsigned int copies = 0;
@@ -784,14 +835,21 @@ static void decode_plane(struct cframe *cf, const __be16 **rlco, u8 *ref,
}
}
-void decode_frame(struct cframe *cf, struct raw_frame *ref, u32 hdr_flags)
+void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
+ u32 hdr_flags)
{
const __be16 *rlco = cf->rlc_data;
+ u32 h = cf->height / 2;
+ u32 w = cf->width / 2;
+ if (hdr_flags & FWHT_FL_CHROMA_FULL_HEIGHT)
+ h *= 2;
+ if (hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH)
+ w *= 2;
decode_plane(cf, &rlco, ref->luma, cf->height, cf->width,
- hdr_flags & VICODEC_FL_LUMA_IS_UNCOMPRESSED);
- decode_plane(cf, &rlco, ref->cb, cf->height / 2, cf->width / 2,
- hdr_flags & VICODEC_FL_CB_IS_UNCOMPRESSED);
- decode_plane(cf, &rlco, ref->cr, cf->height / 2, cf->width / 2,
- hdr_flags & VICODEC_FL_CR_IS_UNCOMPRESSED);
+ hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED);
+ decode_plane(cf, &rlco, ref->cb, h, w,
+ hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED);
+ decode_plane(cf, &rlco, ref->cr, h, w,
+ hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED);
}
diff --git a/drivers/media/platform/vicodec/vicodec-codec.h b/drivers/media/platform/vicodec/codec-fwht.h
index cdfad1332a3e..3e9391fec5fe 100644
--- a/drivers/media/platform/vicodec/vicodec-codec.h
+++ b/drivers/media/platform/vicodec/codec-fwht.h
@@ -1,18 +1,18 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright 2016 Tom aan de Wiel
* Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/
-#ifndef VICODEC_RLC_H
-#define VICODEC_RLC_H
+#ifndef CODEC_FWHT_H
+#define CODEC_FWHT_H
#include <linux/types.h>
#include <linux/bitops.h>
#include <asm/byteorder.h>
/*
- * The compressed format consists of a cframe_hdr struct followed by the
+ * The compressed format consists of a fwht_cframe_hdr struct followed by the
* compressed frame data. The header contains the size of that data.
* Each Y, Cb and Cr plane is compressed separately. If the compressed
* size of each plane becomes larger than the uncompressed size, then
@@ -35,7 +35,7 @@
*
* All 16 and 32 bit values are stored in big-endian (network) order.
*
- * Each cframe_hdr starts with an 8 byte magic header that is
+ * Each fwht_cframe_hdr starts with an 8 byte magic header that is
* guaranteed not to occur in the compressed frame data. This header
* can be used to sync to the next frame.
*
@@ -47,48 +47,36 @@
*/
/*
- * Note: bit 0 of the header must always be 0. Otherwise it cannot
- * be guaranteed that the magic 8 byte sequence (see below) can
- * never occur in the rlc output.
- */
-#define PFRAME_BIT (1 << 15)
-#define DUPS_MASK 0x1ffe
-
-/*
* This is a sequence of 8 bytes with the low 4 bits set to 0xf.
*
* This sequence cannot occur in the encoded data
+ *
+ * Note that these two magic values are symmetrical so endian issues here.
*/
-#define VICODEC_MAGIC1 0x4f4f4f4f
-#define VICODEC_MAGIC2 0xffffffff
-
-#define VICODEC_VERSION 1
-
-#define VICODEC_MAX_WIDTH 3840
-#define VICODEC_MAX_HEIGHT 2160
-#define VICODEC_MIN_WIDTH 640
-#define VICODEC_MIN_HEIGHT 480
+#define FWHT_MAGIC1 0x4f4f4f4f
+#define FWHT_MAGIC2 0xffffffff
-#define PBLOCK 0
-#define IBLOCK 1
+#define FWHT_VERSION 1
/* Set if this is an interlaced format */
-#define VICODEC_FL_IS_INTERLACED BIT(0)
+#define FWHT_FL_IS_INTERLACED BIT(0)
/* Set if this is a bottom-first (NTSC) interlaced format */
-#define VICODEC_FL_IS_BOTTOM_FIRST BIT(1)
+#define FWHT_FL_IS_BOTTOM_FIRST BIT(1)
/* Set if each 'frame' contains just one field */
-#define VICODEC_FL_IS_ALTERNATE BIT(2)
+#define FWHT_FL_IS_ALTERNATE BIT(2)
/*
- * If VICODEC_FL_IS_ALTERNATE was set, then this is set if this
+ * If FWHT_FL_IS_ALTERNATE was set, then this is set if this
* 'frame' is the bottom field, else it is the top field.
*/
-#define VICODEC_FL_IS_BOTTOM_FIELD BIT(3)
+#define FWHT_FL_IS_BOTTOM_FIELD BIT(3)
/* Set if this frame is uncompressed */
-#define VICODEC_FL_LUMA_IS_UNCOMPRESSED BIT(4)
-#define VICODEC_FL_CB_IS_UNCOMPRESSED BIT(5)
-#define VICODEC_FL_CR_IS_UNCOMPRESSED BIT(6)
+#define FWHT_FL_LUMA_IS_UNCOMPRESSED BIT(4)
+#define FWHT_FL_CB_IS_UNCOMPRESSED BIT(5)
+#define FWHT_FL_CR_IS_UNCOMPRESSED BIT(6)
+#define FWHT_FL_CHROMA_FULL_HEIGHT BIT(7)
+#define FWHT_FL_CHROMA_FULL_WIDTH BIT(8)
-struct cframe_hdr {
+struct fwht_cframe_hdr {
u32 magic1;
u32 magic2;
__be32 version;
@@ -101,8 +89,10 @@ struct cframe_hdr {
__be32 size;
};
-struct cframe {
+struct fwht_cframe {
unsigned int width, height;
+ u16 i_frame_qp;
+ u16 p_frame_qp;
__be16 *rlc_data;
s16 coeffs[8 * 8];
s16 de_coeffs[8 * 8];
@@ -110,20 +100,26 @@ struct cframe {
u32 size;
};
-struct raw_frame {
+struct fwht_raw_frame {
unsigned int width, height;
+ unsigned int width_div;
+ unsigned int height_div;
+ unsigned int luma_step;
unsigned int chroma_step;
u8 *luma, *cb, *cr;
};
-#define FRAME_PCODED BIT(0)
-#define FRAME_UNENCODED BIT(1)
-#define LUMA_UNENCODED BIT(2)
-#define CB_UNENCODED BIT(3)
-#define CR_UNENCODED BIT(4)
+#define FWHT_FRAME_PCODED BIT(0)
+#define FWHT_FRAME_UNENCODED BIT(1)
+#define FWHT_LUMA_UNENCODED BIT(2)
+#define FWHT_CB_UNENCODED BIT(3)
+#define FWHT_CR_UNENCODED BIT(4)
-u32 encode_frame(struct raw_frame *frm, struct raw_frame *ref_frm,
- struct cframe *cf, bool is_intra, bool next_is_intra);
-void decode_frame(struct cframe *cf, struct raw_frame *ref, u32 hdr_flags);
+u32 fwht_encode_frame(struct fwht_raw_frame *frm,
+ struct fwht_raw_frame *ref_frm,
+ struct fwht_cframe *cf,
+ bool is_intra, bool next_is_intra);
+void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
+ u32 hdr_flags);
#endif
diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c
new file mode 100644
index 000000000000..e5b68fb38aac
--- /dev/null
+++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.c
@@ -0,0 +1,332 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * A V4L2 frontend for the FWHT codec
+ *
+ * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ */
+
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/videodev2.h>
+#include "codec-v4l2-fwht.h"
+
+static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = {
+ { V4L2_PIX_FMT_YUV420, 1, 3, 2, 1, 1, 2, 2 },
+ { V4L2_PIX_FMT_YVU420, 1, 3, 2, 1, 1, 2, 2 },
+ { V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1 },
+ { V4L2_PIX_FMT_NV12, 1, 3, 2, 1, 2, 2, 2 },
+ { V4L2_PIX_FMT_NV21, 1, 3, 2, 1, 2, 2, 2 },
+ { V4L2_PIX_FMT_NV16, 1, 2, 1, 1, 2, 2, 1 },
+ { V4L2_PIX_FMT_NV61, 1, 2, 1, 1, 2, 2, 1 },
+ { V4L2_PIX_FMT_NV24, 1, 3, 1, 1, 2, 1, 1 },
+ { V4L2_PIX_FMT_NV42, 1, 3, 1, 1, 2, 1, 1 },
+ { V4L2_PIX_FMT_YUYV, 2, 2, 1, 2, 4, 2, 1 },
+ { V4L2_PIX_FMT_YVYU, 2, 2, 1, 2, 4, 2, 1 },
+ { V4L2_PIX_FMT_UYVY, 2, 2, 1, 2, 4, 2, 1 },
+ { V4L2_PIX_FMT_VYUY, 2, 2, 1, 2, 4, 2, 1 },
+ { V4L2_PIX_FMT_BGR24, 3, 3, 1, 3, 3, 1, 1 },
+ { V4L2_PIX_FMT_RGB24, 3, 3, 1, 3, 3, 1, 1 },
+ { V4L2_PIX_FMT_HSV24, 3, 3, 1, 3, 3, 1, 1 },
+ { V4L2_PIX_FMT_BGR32, 4, 4, 1, 4, 4, 1, 1 },
+ { V4L2_PIX_FMT_XBGR32, 4, 4, 1, 4, 4, 1, 1 },
+ { V4L2_PIX_FMT_RGB32, 4, 4, 1, 4, 4, 1, 1 },
+ { V4L2_PIX_FMT_XRGB32, 4, 4, 1, 4, 4, 1, 1 },
+ { V4L2_PIX_FMT_HSV32, 4, 4, 1, 4, 4, 1, 1 },
+};
+
+const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(v4l2_fwht_pixfmts); i++)
+ if (v4l2_fwht_pixfmts[i].id == pixelformat)
+ return v4l2_fwht_pixfmts + i;
+ return NULL;
+}
+
+const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx)
+{
+ if (idx >= ARRAY_SIZE(v4l2_fwht_pixfmts))
+ return NULL;
+ return v4l2_fwht_pixfmts + idx;
+}
+
+int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
+{
+ unsigned int size = state->width * state->height;
+ const struct v4l2_fwht_pixfmt_info *info = state->info;
+ struct fwht_cframe_hdr *p_hdr;
+ struct fwht_cframe cf;
+ struct fwht_raw_frame rf;
+ u32 encoding;
+ u32 flags = 0;
+
+ if (!info)
+ return -EINVAL;
+ rf.width = state->width;
+ rf.height = state->height;
+ rf.luma = p_in;
+ rf.width_div = info->width_div;
+ rf.height_div = info->height_div;
+ rf.luma_step = info->luma_step;
+ rf.chroma_step = info->chroma_step;
+
+ switch (info->id) {
+ case V4L2_PIX_FMT_YUV420:
+ rf.cb = rf.luma + size;
+ rf.cr = rf.cb + size / 4;
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ rf.cr = rf.luma + size;
+ rf.cb = rf.cr + size / 4;
+ break;
+ case V4L2_PIX_FMT_YUV422P:
+ rf.cb = rf.luma + size;
+ rf.cr = rf.cb + size / 2;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV24:
+ rf.cb = rf.luma + size;
+ rf.cr = rf.cb + 1;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV42:
+ rf.cr = rf.luma + size;
+ rf.cb = rf.cr + 1;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ rf.cb = rf.luma + 1;
+ rf.cr = rf.cb + 2;
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ rf.cr = rf.luma + 1;
+ rf.cb = rf.cr + 2;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ rf.cb = rf.luma;
+ rf.cr = rf.cb + 2;
+ rf.luma++;
+ break;
+ case V4L2_PIX_FMT_VYUY:
+ rf.cr = rf.luma;
+ rf.cb = rf.cr + 2;
+ rf.luma++;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_HSV24:
+ rf.cr = rf.luma;
+ rf.cb = rf.cr + 2;
+ rf.luma++;
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ rf.cb = rf.luma;
+ rf.cr = rf.cb + 2;
+ rf.luma++;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_XRGB32:
+ case V4L2_PIX_FMT_HSV32:
+ rf.cr = rf.luma + 1;
+ rf.cb = rf.cr + 2;
+ rf.luma += 2;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ case V4L2_PIX_FMT_XBGR32:
+ rf.cb = rf.luma;
+ rf.cr = rf.cb + 2;
+ rf.luma++;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cf.width = state->width;
+ cf.height = state->height;
+ cf.i_frame_qp = state->i_frame_qp;
+ cf.p_frame_qp = state->p_frame_qp;
+ cf.rlc_data = (__be16 *)(p_out + sizeof(*p_hdr));
+
+ encoding = fwht_encode_frame(&rf, &state->ref_frame, &cf,
+ !state->gop_cnt,
+ state->gop_cnt == state->gop_size - 1);
+ if (!(encoding & FWHT_FRAME_PCODED))
+ state->gop_cnt = 0;
+ if (++state->gop_cnt >= state->gop_size)
+ state->gop_cnt = 0;
+
+ p_hdr = (struct fwht_cframe_hdr *)p_out;
+ p_hdr->magic1 = FWHT_MAGIC1;
+ p_hdr->magic2 = FWHT_MAGIC2;
+ p_hdr->version = htonl(FWHT_VERSION);
+ p_hdr->width = htonl(cf.width);
+ p_hdr->height = htonl(cf.height);
+ if (encoding & FWHT_LUMA_UNENCODED)
+ flags |= FWHT_FL_LUMA_IS_UNCOMPRESSED;
+ if (encoding & FWHT_CB_UNENCODED)
+ flags |= FWHT_FL_CB_IS_UNCOMPRESSED;
+ if (encoding & FWHT_CR_UNENCODED)
+ flags |= FWHT_FL_CR_IS_UNCOMPRESSED;
+ if (rf.height_div == 1)
+ flags |= FWHT_FL_CHROMA_FULL_HEIGHT;
+ if (rf.width_div == 1)
+ flags |= FWHT_FL_CHROMA_FULL_WIDTH;
+ p_hdr->flags = htonl(flags);
+ p_hdr->colorspace = htonl(state->colorspace);
+ p_hdr->xfer_func = htonl(state->xfer_func);
+ p_hdr->ycbcr_enc = htonl(state->ycbcr_enc);
+ p_hdr->quantization = htonl(state->quantization);
+ p_hdr->size = htonl(cf.size);
+ state->ref_frame.width = cf.width;
+ state->ref_frame.height = cf.height;
+ return cf.size + sizeof(*p_hdr);
+}
+
+int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
+{
+ unsigned int size = state->width * state->height;
+ unsigned int chroma_size = size;
+ unsigned int i;
+ u32 flags;
+ struct fwht_cframe_hdr *p_hdr;
+ struct fwht_cframe cf;
+ u8 *p;
+
+ if (!state->info)
+ return -EINVAL;
+
+ p_hdr = (struct fwht_cframe_hdr *)p_in;
+ cf.width = ntohl(p_hdr->width);
+ cf.height = ntohl(p_hdr->height);
+ flags = ntohl(p_hdr->flags);
+ state->colorspace = ntohl(p_hdr->colorspace);
+ state->xfer_func = ntohl(p_hdr->xfer_func);
+ state->ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
+ state->quantization = ntohl(p_hdr->quantization);
+ cf.rlc_data = (__be16 *)(p_in + sizeof(*p_hdr));
+
+ if (p_hdr->magic1 != FWHT_MAGIC1 ||
+ p_hdr->magic2 != FWHT_MAGIC2 ||
+ ntohl(p_hdr->version) != FWHT_VERSION ||
+ (cf.width & 7) || (cf.height & 7))
+ return -EINVAL;
+
+ /* TODO: support resolution changes */
+ if (cf.width != state->width || cf.height != state->height)
+ return -EINVAL;
+
+ if (!(flags & FWHT_FL_CHROMA_FULL_WIDTH))
+ chroma_size /= 2;
+ if (!(flags & FWHT_FL_CHROMA_FULL_HEIGHT))
+ chroma_size /= 2;
+
+ fwht_decode_frame(&cf, &state->ref_frame, flags);
+
+ switch (state->info->id) {
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YUV422P:
+ memcpy(p_out, state->ref_frame.luma, size);
+ p_out += size;
+ memcpy(p_out, state->ref_frame.cb, chroma_size);
+ p_out += chroma_size;
+ memcpy(p_out, state->ref_frame.cr, chroma_size);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ memcpy(p_out, state->ref_frame.luma, size);
+ p_out += size;
+ memcpy(p_out, state->ref_frame.cr, chroma_size);
+ p_out += chroma_size;
+ memcpy(p_out, state->ref_frame.cb, chroma_size);
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV24:
+ memcpy(p_out, state->ref_frame.luma, size);
+ p_out += size;
+ for (i = 0, p = p_out; i < chroma_size; i++) {
+ *p++ = state->ref_frame.cb[i];
+ *p++ = state->ref_frame.cr[i];
+ }
+ break;
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV42:
+ memcpy(p_out, state->ref_frame.luma, size);
+ p_out += size;
+ for (i = 0, p = p_out; i < chroma_size; i++) {
+ *p++ = state->ref_frame.cr[i];
+ *p++ = state->ref_frame.cb[i];
+ }
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ for (i = 0, p = p_out; i < size; i += 2) {
+ *p++ = state->ref_frame.luma[i];
+ *p++ = state->ref_frame.cb[i / 2];
+ *p++ = state->ref_frame.luma[i + 1];
+ *p++ = state->ref_frame.cr[i / 2];
+ }
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ for (i = 0, p = p_out; i < size; i += 2) {
+ *p++ = state->ref_frame.luma[i];
+ *p++ = state->ref_frame.cr[i / 2];
+ *p++ = state->ref_frame.luma[i + 1];
+ *p++ = state->ref_frame.cb[i / 2];
+ }
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ for (i = 0, p = p_out; i < size; i += 2) {
+ *p++ = state->ref_frame.cb[i / 2];
+ *p++ = state->ref_frame.luma[i];
+ *p++ = state->ref_frame.cr[i / 2];
+ *p++ = state->ref_frame.luma[i + 1];
+ }
+ break;
+ case V4L2_PIX_FMT_VYUY:
+ for (i = 0, p = p_out; i < size; i += 2) {
+ *p++ = state->ref_frame.cr[i / 2];
+ *p++ = state->ref_frame.luma[i];
+ *p++ = state->ref_frame.cb[i / 2];
+ *p++ = state->ref_frame.luma[i + 1];
+ }
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_HSV24:
+ for (i = 0, p = p_out; i < size; i++) {
+ *p++ = state->ref_frame.cr[i];
+ *p++ = state->ref_frame.luma[i];
+ *p++ = state->ref_frame.cb[i];
+ }
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ for (i = 0, p = p_out; i < size; i++) {
+ *p++ = state->ref_frame.cb[i];
+ *p++ = state->ref_frame.luma[i];
+ *p++ = state->ref_frame.cr[i];
+ }
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_XRGB32:
+ case V4L2_PIX_FMT_HSV32:
+ for (i = 0, p = p_out; i < size; i++) {
+ *p++ = 0;
+ *p++ = state->ref_frame.cr[i];
+ *p++ = state->ref_frame.luma[i];
+ *p++ = state->ref_frame.cb[i];
+ }
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ case V4L2_PIX_FMT_XBGR32:
+ for (i = 0, p = p_out; i < size; i++) {
+ *p++ = state->ref_frame.cb[i];
+ *p++ = state->ref_frame.luma[i];
+ *p++ = state->ref_frame.cr[i];
+ *p++ = 0;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.h b/drivers/media/platform/vicodec/codec-v4l2-fwht.h
new file mode 100644
index 000000000000..162465b78067
--- /dev/null
+++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ */
+
+#ifndef CODEC_V4L2_FWHT_H
+#define CODEC_V4L2_FWHT_H
+
+#include "codec-fwht.h"
+
+struct v4l2_fwht_pixfmt_info {
+ u32 id;
+ unsigned int bytesperline_mult;
+ unsigned int sizeimage_mult;
+ unsigned int sizeimage_div;
+ unsigned int luma_step;
+ unsigned int chroma_step;
+ /* Chroma plane subsampling */
+ unsigned int width_div;
+ unsigned int height_div;
+};
+
+struct v4l2_fwht_state {
+ const struct v4l2_fwht_pixfmt_info *info;
+ unsigned int width;
+ unsigned int height;
+ unsigned int gop_size;
+ unsigned int gop_cnt;
+ u16 i_frame_qp;
+ u16 p_frame_qp;
+
+ enum v4l2_colorspace colorspace;
+ enum v4l2_ycbcr_encoding ycbcr_enc;
+ enum v4l2_xfer_func xfer_func;
+ enum v4l2_quantization quantization;
+
+ struct fwht_raw_frame ref_frame;
+ u8 *compressed_frame;
+};
+
+const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat);
+const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx);
+
+int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out);
+int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out);
+
+#endif
diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c
index 408cd55d3580..1eb9132bfc85 100644
--- a/drivers/media/platform/vicodec/vicodec-core.c
+++ b/drivers/media/platform/vicodec/vicodec-core.c
@@ -23,7 +23,7 @@
#include <media/v4l2-event.h>
#include <media/videobuf2-vmalloc.h>
-#include "vicodec-codec.h"
+#include "codec-v4l2-fwht.h"
MODULE_DESCRIPTION("Virtual codec device");
MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
@@ -48,6 +48,22 @@ MODULE_PARM_DESC(debug, " activates debug info");
v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
+struct pixfmt_info {
+ u32 id;
+ unsigned int bytesperline_mult;
+ unsigned int sizeimage_mult;
+ unsigned int sizeimage_div;
+ unsigned int luma_step;
+ unsigned int chroma_step;
+ /* Chroma plane subsampling */
+ unsigned int width_div;
+ unsigned int height_div;
+};
+
+static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = {
+ V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1
+};
+
static void vicodec_dev_release(struct device *dev)
{
}
@@ -61,10 +77,9 @@ static struct platform_device vicodec_pdev = {
struct vicodec_q_data {
unsigned int width;
unsigned int height;
- unsigned int flags;
unsigned int sizeimage;
unsigned int sequence;
- u32 fourcc;
+ const struct v4l2_fwht_pixfmt_info *info;
};
enum {
@@ -96,24 +111,14 @@ struct vicodec_ctx {
spinlock_t *lock;
struct v4l2_ctrl_handler hdl;
- struct v4l2_ctrl *ctrl_gop_size;
- unsigned int gop_size;
- unsigned int gop_cnt;
- /* Abort requested by m2m */
- int aborting;
struct vb2_v4l2_buffer *last_src_buf;
struct vb2_v4l2_buffer *last_dst_buf;
- enum v4l2_colorspace colorspace;
- enum v4l2_ycbcr_encoding ycbcr_enc;
- enum v4l2_xfer_func xfer_func;
- enum v4l2_quantization quantization;
-
/* Source and destination queue data */
struct vicodec_q_data q_data[2];
- struct raw_frame ref_frame;
- u8 *compressed_frame;
+ struct v4l2_fwht_state state;
+
u32 cur_buf_offset;
u32 comp_max_size;
u32 comp_size;
@@ -123,13 +128,6 @@ struct vicodec_ctx {
bool comp_has_next_frame;
};
-static const u32 pixfmts_yuv[] = {
- V4L2_PIX_FMT_YUV420,
- V4L2_PIX_FMT_YVU420,
- V4L2_PIX_FMT_NV12,
- V4L2_PIX_FMT_NV21,
-};
-
static inline struct vicodec_ctx *file2ctx(struct file *file)
{
return container_of(file->private_data, struct vicodec_ctx, fh);
@@ -152,156 +150,21 @@ static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx,
return NULL;
}
-static void encode(struct vicodec_ctx *ctx,
- struct vicodec_q_data *q_data,
- u8 *p_in, u8 *p_out)
-{
- unsigned int size = q_data->width * q_data->height;
- struct cframe_hdr *p_hdr;
- struct cframe cf;
- struct raw_frame rf;
- u32 encoding;
-
- rf.width = q_data->width;
- rf.height = q_data->height;
- rf.luma = p_in;
-
- switch (q_data->fourcc) {
- case V4L2_PIX_FMT_YUV420:
- rf.cb = rf.luma + size;
- rf.cr = rf.cb + size / 4;
- rf.chroma_step = 1;
- break;
- case V4L2_PIX_FMT_YVU420:
- rf.cr = rf.luma + size;
- rf.cb = rf.cr + size / 4;
- rf.chroma_step = 1;
- break;
- case V4L2_PIX_FMT_NV12:
- rf.cb = rf.luma + size;
- rf.cr = rf.cb + 1;
- rf.chroma_step = 2;
- break;
- case V4L2_PIX_FMT_NV21:
- rf.cr = rf.luma + size;
- rf.cb = rf.cr + 1;
- rf.chroma_step = 2;
- break;
- }
-
- cf.width = q_data->width;
- cf.height = q_data->height;
- cf.rlc_data = (__be16 *)(p_out + sizeof(*p_hdr));
-
- encoding = encode_frame(&rf, &ctx->ref_frame, &cf, !ctx->gop_cnt,
- ctx->gop_cnt == ctx->gop_size - 1);
- if (encoding != FRAME_PCODED)
- ctx->gop_cnt = 0;
- if (++ctx->gop_cnt == ctx->gop_size)
- ctx->gop_cnt = 0;
-
- p_hdr = (struct cframe_hdr *)p_out;
- p_hdr->magic1 = VICODEC_MAGIC1;
- p_hdr->magic2 = VICODEC_MAGIC2;
- p_hdr->version = htonl(VICODEC_VERSION);
- p_hdr->width = htonl(cf.width);
- p_hdr->height = htonl(cf.height);
- p_hdr->flags = htonl(q_data->flags);
- if (encoding & LUMA_UNENCODED)
- p_hdr->flags |= htonl(VICODEC_FL_LUMA_IS_UNCOMPRESSED);
- if (encoding & CB_UNENCODED)
- p_hdr->flags |= htonl(VICODEC_FL_CB_IS_UNCOMPRESSED);
- if (encoding & CR_UNENCODED)
- p_hdr->flags |= htonl(VICODEC_FL_CR_IS_UNCOMPRESSED);
- p_hdr->colorspace = htonl(ctx->colorspace);
- p_hdr->xfer_func = htonl(ctx->xfer_func);
- p_hdr->ycbcr_enc = htonl(ctx->ycbcr_enc);
- p_hdr->quantization = htonl(ctx->quantization);
- p_hdr->size = htonl(cf.size);
- ctx->ref_frame.width = cf.width;
- ctx->ref_frame.height = cf.height;
-}
-
-static int decode(struct vicodec_ctx *ctx,
- struct vicodec_q_data *q_data,
- u8 *p_in, u8 *p_out)
-{
- unsigned int size = q_data->width * q_data->height;
- unsigned int i;
- struct cframe_hdr *p_hdr;
- struct cframe cf;
- u8 *p;
-
- p_hdr = (struct cframe_hdr *)p_in;
- cf.width = ntohl(p_hdr->width);
- cf.height = ntohl(p_hdr->height);
- q_data->flags = ntohl(p_hdr->flags);
- ctx->colorspace = ntohl(p_hdr->colorspace);
- ctx->xfer_func = ntohl(p_hdr->xfer_func);
- ctx->ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
- ctx->quantization = ntohl(p_hdr->quantization);
- cf.rlc_data = (__be16 *)(p_in + sizeof(*p_hdr));
-
- if (p_hdr->magic1 != VICODEC_MAGIC1 ||
- p_hdr->magic2 != VICODEC_MAGIC2 ||
- ntohl(p_hdr->version) != VICODEC_VERSION ||
- cf.width < VICODEC_MIN_WIDTH ||
- cf.width > VICODEC_MAX_WIDTH ||
- cf.height < VICODEC_MIN_HEIGHT ||
- cf.height > VICODEC_MAX_HEIGHT ||
- (cf.width & 7) || (cf.height & 7))
- return -EINVAL;
-
- /* TODO: support resolution changes */
- if (cf.width != q_data->width || cf.height != q_data->height)
- return -EINVAL;
-
- decode_frame(&cf, &ctx->ref_frame, q_data->flags);
- memcpy(p_out, ctx->ref_frame.luma, size);
- p_out += size;
-
- switch (q_data->fourcc) {
- case V4L2_PIX_FMT_YUV420:
- memcpy(p_out, ctx->ref_frame.cb, size / 4);
- p_out += size / 4;
- memcpy(p_out, ctx->ref_frame.cr, size / 4);
- break;
- case V4L2_PIX_FMT_YVU420:
- memcpy(p_out, ctx->ref_frame.cr, size / 4);
- p_out += size / 4;
- memcpy(p_out, ctx->ref_frame.cb, size / 4);
- break;
- case V4L2_PIX_FMT_NV12:
- for (i = 0, p = p_out; i < size / 4; i++, p += 2)
- *p = ctx->ref_frame.cb[i];
- for (i = 0, p = p_out + 1; i < size / 4; i++, p += 2)
- *p = ctx->ref_frame.cr[i];
- break;
- case V4L2_PIX_FMT_NV21:
- for (i = 0, p = p_out; i < size / 4; i++, p += 2)
- *p = ctx->ref_frame.cr[i];
- for (i = 0, p = p_out + 1; i < size / 4; i++, p += 2)
- *p = ctx->ref_frame.cb[i];
- break;
- }
- return 0;
-}
-
static int device_process(struct vicodec_ctx *ctx,
struct vb2_v4l2_buffer *in_vb,
struct vb2_v4l2_buffer *out_vb)
{
struct vicodec_dev *dev = ctx->dev;
- struct vicodec_q_data *q_out, *q_cap;
+ struct vicodec_q_data *q_cap;
+ struct v4l2_fwht_state *state = &ctx->state;
u8 *p_in, *p_out;
int ret;
- q_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
q_cap = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
if (ctx->is_enc)
p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0);
else
- p_in = ctx->compressed_frame;
+ p_in = state->compressed_frame;
p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0);
if (!p_in || !p_out) {
v4l2_err(&dev->v4l2_dev,
@@ -310,17 +173,20 @@ static int device_process(struct vicodec_ctx *ctx,
}
if (ctx->is_enc) {
- struct cframe_hdr *p_hdr = (struct cframe_hdr *)p_out;
+ struct vicodec_q_data *q_out;
- encode(ctx, q_out, p_in, p_out);
- vb2_set_plane_payload(&out_vb->vb2_buf, 0,
- sizeof(*p_hdr) + ntohl(p_hdr->size));
+ q_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ state->info = q_out->info;
+ ret = v4l2_fwht_encode(state, p_in, p_out);
+ if (ret < 0)
+ return ret;
+ vb2_set_plane_payload(&out_vb->vb2_buf, 0, ret);
} else {
- ret = decode(ctx, q_cap, p_in, p_out);
- if (ret)
+ state->info = q_cap->info;
+ ret = v4l2_fwht_decode(state, p_in, p_out);
+ if (ret < 0)
return ret;
- vb2_set_plane_payload(&out_vb->vb2_buf, 0,
- q_cap->width * q_cap->height * 3 / 2);
+ vb2_set_plane_payload(&out_vb->vb2_buf, 0, q_cap->sizeimage);
}
out_vb->sequence = q_cap->sequence++;
@@ -446,10 +312,11 @@ restart:
copy = sizeof(magic) - ctx->comp_magic_cnt;
if (p_out + sz - p < copy)
copy = p_out + sz - p;
- memcpy(ctx->compressed_frame + ctx->comp_magic_cnt,
+ memcpy(ctx->state.compressed_frame + ctx->comp_magic_cnt,
p, copy);
ctx->comp_magic_cnt += copy;
- if (!memcmp(ctx->compressed_frame, magic, ctx->comp_magic_cnt)) {
+ if (!memcmp(ctx->state.compressed_frame, magic,
+ ctx->comp_magic_cnt)) {
p += copy;
state = VB2_BUF_STATE_DONE;
break;
@@ -462,17 +329,18 @@ restart:
}
ctx->comp_size = sizeof(magic);
}
- if (ctx->comp_size < sizeof(struct cframe_hdr)) {
- struct cframe_hdr *p_hdr = (struct cframe_hdr *)ctx->compressed_frame;
- u32 copy = sizeof(struct cframe_hdr) - ctx->comp_size;
+ if (ctx->comp_size < sizeof(struct fwht_cframe_hdr)) {
+ struct fwht_cframe_hdr *p_hdr =
+ (struct fwht_cframe_hdr *)ctx->state.compressed_frame;
+ u32 copy = sizeof(struct fwht_cframe_hdr) - ctx->comp_size;
if (copy > p_out + sz - p)
copy = p_out + sz - p;
- memcpy(ctx->compressed_frame + ctx->comp_size,
+ memcpy(ctx->state.compressed_frame + ctx->comp_size,
p, copy);
p += copy;
ctx->comp_size += copy;
- if (ctx->comp_size < sizeof(struct cframe_hdr)) {
+ if (ctx->comp_size < sizeof(struct fwht_cframe_hdr)) {
job_remove_out_buf(ctx, state);
goto restart;
}
@@ -485,7 +353,7 @@ restart:
if (copy > p_out + sz - p)
copy = p_out + sz - p;
- memcpy(ctx->compressed_frame + ctx->comp_size,
+ memcpy(ctx->state.compressed_frame + ctx->comp_size,
p, copy);
p += copy;
ctx->comp_size += copy;
@@ -497,8 +365,8 @@ restart:
ctx->cur_buf_offset = p - p_out;
ctx->comp_has_frame = true;
ctx->comp_has_next_frame = false;
- if (sz - ctx->cur_buf_offset >= sizeof(struct cframe_hdr)) {
- struct cframe_hdr *p_hdr = (struct cframe_hdr *)p;
+ if (sz - ctx->cur_buf_offset >= sizeof(struct fwht_cframe_hdr)) {
+ struct fwht_cframe_hdr *p_hdr = (struct fwht_cframe_hdr *)p;
u32 frame_size = ntohl(p_hdr->size);
u32 remaining = sz - ctx->cur_buf_offset - sizeof(*p_hdr);
@@ -508,26 +376,18 @@ restart:
return 1;
}
-static void job_abort(void *priv)
-{
- struct vicodec_ctx *ctx = priv;
-
- /* Will cancel the transaction in the next interrupt handler */
- ctx->aborting = 1;
-}
-
/*
* video ioctls
*/
-static u32 find_fmt(u32 fmt)
+static const struct v4l2_fwht_pixfmt_info *find_fmt(u32 fmt)
{
- unsigned int i;
+ const struct v4l2_fwht_pixfmt_info *info =
+ v4l2_fwht_find_pixfmt(fmt);
- for (i = 0; i < ARRAY_SIZE(pixfmts_yuv); i++)
- if (pixfmts_yuv[i] == fmt)
- return fmt;
- return pixfmts_yuv[0];
+ if (!info)
+ info = v4l2_fwht_get_pixfmt(0);
+ return info;
}
static int vidioc_querycap(struct file *file, void *priv,
@@ -547,19 +407,25 @@ static int vidioc_querycap(struct file *file, void *priv,
static int enum_fmt(struct v4l2_fmtdesc *f, bool is_enc, bool is_out)
{
- bool is_yuv = (is_enc && is_out) || (!is_enc && !is_out);
+ bool is_uncomp = (is_enc && is_out) || (!is_enc && !is_out);
if (V4L2_TYPE_IS_MULTIPLANAR(f->type) && !multiplanar)
return -EINVAL;
if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && multiplanar)
return -EINVAL;
- if (f->index >= (is_yuv ? ARRAY_SIZE(pixfmts_yuv) : 1))
- return -EINVAL;
- if (is_yuv)
- f->pixelformat = pixfmts_yuv[f->index];
- else
+ if (is_uncomp) {
+ const struct v4l2_fwht_pixfmt_info *info =
+ v4l2_fwht_get_pixfmt(f->index);
+
+ if (!info)
+ return -EINVAL;
+ f->pixelformat = info->id;
+ } else {
+ if (f->index)
+ return -EINVAL;
f->pixelformat = V4L2_PIX_FMT_FWHT;
+ }
return 0;
}
@@ -585,12 +451,14 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
struct vicodec_q_data *q_data;
struct v4l2_pix_format_mplane *pix_mp;
struct v4l2_pix_format *pix;
+ const struct v4l2_fwht_pixfmt_info *info;
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
if (!vq)
return -EINVAL;
q_data = get_q_data(ctx, f->type);
+ info = q_data->info;
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -601,16 +469,13 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
pix->width = q_data->width;
pix->height = q_data->height;
pix->field = V4L2_FIELD_NONE;
- pix->pixelformat = q_data->fourcc;
- if (q_data->fourcc == V4L2_PIX_FMT_FWHT)
- pix->bytesperline = 0;
- else
- pix->bytesperline = q_data->width;
+ pix->pixelformat = info->id;
+ pix->bytesperline = q_data->width * info->bytesperline_mult;
pix->sizeimage = q_data->sizeimage;
- pix->colorspace = ctx->colorspace;
- pix->xfer_func = ctx->xfer_func;
- pix->ycbcr_enc = ctx->ycbcr_enc;
- pix->quantization = ctx->quantization;
+ pix->colorspace = ctx->state.colorspace;
+ pix->xfer_func = ctx->state.xfer_func;
+ pix->ycbcr_enc = ctx->state.ycbcr_enc;
+ pix->quantization = ctx->state.quantization;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
@@ -621,17 +486,15 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
pix_mp->width = q_data->width;
pix_mp->height = q_data->height;
pix_mp->field = V4L2_FIELD_NONE;
- pix_mp->pixelformat = q_data->fourcc;
+ pix_mp->pixelformat = info->id;
pix_mp->num_planes = 1;
- if (q_data->fourcc == V4L2_PIX_FMT_FWHT)
- pix_mp->plane_fmt[0].bytesperline = 0;
- else
- pix_mp->plane_fmt[0].bytesperline = q_data->width;
+ pix_mp->plane_fmt[0].bytesperline =
+ q_data->width * info->bytesperline_mult;
pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage;
- pix_mp->colorspace = ctx->colorspace;
- pix_mp->xfer_func = ctx->xfer_func;
- pix_mp->ycbcr_enc = ctx->ycbcr_enc;
- pix_mp->quantization = ctx->quantization;
+ pix_mp->colorspace = ctx->state.colorspace;
+ pix_mp->xfer_func = ctx->state.xfer_func;
+ pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
+ pix_mp->quantization = ctx->state.quantization;
memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
memset(pix_mp->plane_fmt[0].reserved, 0,
sizeof(pix_mp->plane_fmt[0].reserved));
@@ -658,40 +521,44 @@ static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
{
struct v4l2_pix_format_mplane *pix_mp;
struct v4l2_pix_format *pix;
+ struct v4l2_plane_pix_format *plane;
+ const struct v4l2_fwht_pixfmt_info *info = &pixfmt_fwht;
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
pix = &f->fmt.pix;
+ if (pix->pixelformat != V4L2_PIX_FMT_FWHT)
+ info = find_fmt(pix->pixelformat);
pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7;
pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7;
- pix->bytesperline = pix->width;
- pix->sizeimage = pix->width * pix->height * 3 / 2;
pix->field = V4L2_FIELD_NONE;
- if (pix->pixelformat == V4L2_PIX_FMT_FWHT) {
- pix->bytesperline = 0;
- pix->sizeimage += sizeof(struct cframe_hdr);
- }
+ pix->bytesperline =
+ pix->width * info->bytesperline_mult;
+ pix->sizeimage = pix->width * pix->height *
+ info->sizeimage_mult / info->sizeimage_div;
+ if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
+ pix->sizeimage += sizeof(struct fwht_cframe_hdr);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
pix_mp = &f->fmt.pix_mp;
+ plane = pix_mp->plane_fmt;
+ if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT)
+ info = find_fmt(pix_mp->pixelformat);
+ pix_mp->num_planes = 1;
pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH) & ~7;
pix_mp->height =
clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT) & ~7;
- pix_mp->plane_fmt[0].bytesperline = pix_mp->width;
- pix_mp->plane_fmt[0].sizeimage =
- pix_mp->width * pix_mp->height * 3 / 2;
pix_mp->field = V4L2_FIELD_NONE;
- pix_mp->num_planes = 1;
- if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT) {
- pix_mp->plane_fmt[0].bytesperline = 0;
- pix_mp->plane_fmt[0].sizeimage +=
- sizeof(struct cframe_hdr);
- }
+ plane->bytesperline =
+ pix_mp->width * info->bytesperline_mult;
+ plane->sizeimage = pix_mp->width * pix_mp->height *
+ info->sizeimage_mult / info->sizeimage_div;
+ if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
+ plane->sizeimage += sizeof(struct fwht_cframe_hdr);
memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
- memset(pix_mp->plane_fmt[0].reserved, 0,
- sizeof(pix_mp->plane_fmt[0].reserved));
+ memset(plane->reserved, 0, sizeof(plane->reserved));
break;
default:
return -EINVAL;
@@ -713,25 +580,22 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
pix = &f->fmt.pix;
pix->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
- find_fmt(f->fmt.pix.pixelformat);
- pix->colorspace = ctx->colorspace;
- pix->xfer_func = ctx->xfer_func;
- pix->ycbcr_enc = ctx->ycbcr_enc;
- pix->quantization = ctx->quantization;
+ find_fmt(f->fmt.pix.pixelformat)->id;
+ pix->colorspace = ctx->state.colorspace;
+ pix->xfer_func = ctx->state.xfer_func;
+ pix->ycbcr_enc = ctx->state.ycbcr_enc;
+ pix->quantization = ctx->state.quantization;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (!multiplanar)
return -EINVAL;
pix_mp = &f->fmt.pix_mp;
pix_mp->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
- find_fmt(pix_mp->pixelformat);
- pix_mp->colorspace = ctx->colorspace;
- pix_mp->xfer_func = ctx->xfer_func;
- pix_mp->ycbcr_enc = ctx->ycbcr_enc;
- pix_mp->quantization = ctx->quantization;
- memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
- memset(pix_mp->plane_fmt[0].reserved, 0,
- sizeof(pix_mp->plane_fmt[0].reserved));
+ find_fmt(pix_mp->pixelformat)->id;
+ pix_mp->colorspace = ctx->state.colorspace;
+ pix_mp->xfer_func = ctx->state.xfer_func;
+ pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
+ pix_mp->quantization = ctx->state.quantization;
break;
default:
return -EINVAL;
@@ -753,7 +617,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
return -EINVAL;
pix = &f->fmt.pix;
pix->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT :
- find_fmt(pix->pixelformat);
+ find_fmt(pix->pixelformat)->id;
if (!pix->colorspace)
pix->colorspace = V4L2_COLORSPACE_REC709;
break;
@@ -762,7 +626,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
return -EINVAL;
pix_mp = &f->fmt.pix_mp;
pix_mp->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT :
- find_fmt(pix_mp->pixelformat);
+ find_fmt(pix_mp->pixelformat)->id;
if (!pix_mp->colorspace)
pix_mp->colorspace = V4L2_COLORSPACE_REC709;
break;
@@ -795,14 +659,17 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
pix = &f->fmt.pix;
if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
fmt_changed =
- q_data->fourcc != pix->pixelformat ||
+ q_data->info->id != pix->pixelformat ||
q_data->width != pix->width ||
q_data->height != pix->height;
if (vb2_is_busy(vq) && fmt_changed)
return -EBUSY;
- q_data->fourcc = pix->pixelformat;
+ if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
+ q_data->info = &pixfmt_fwht;
+ else
+ q_data->info = find_fmt(pix->pixelformat);
q_data->width = pix->width;
q_data->height = pix->height;
q_data->sizeimage = pix->sizeimage;
@@ -812,14 +679,17 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
pix_mp = &f->fmt.pix_mp;
if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
fmt_changed =
- q_data->fourcc != pix_mp->pixelformat ||
+ q_data->info->id != pix_mp->pixelformat ||
q_data->width != pix_mp->width ||
q_data->height != pix_mp->height;
if (vb2_is_busy(vq) && fmt_changed)
return -EBUSY;
- q_data->fourcc = pix_mp->pixelformat;
+ if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
+ q_data->info = &pixfmt_fwht;
+ else
+ q_data->info = find_fmt(pix_mp->pixelformat);
q_data->width = pix_mp->width;
q_data->height = pix_mp->height;
q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage;
@@ -830,7 +700,7 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
dprintk(ctx->dev,
"Setting format for type %d, wxh: %dx%d, fourcc: %08x\n",
- f->type, q_data->width, q_data->height, q_data->fourcc);
+ f->type, q_data->width, q_data->height, q_data->info->id);
return 0;
}
@@ -865,18 +735,18 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
pix = &f->fmt.pix;
- ctx->colorspace = pix->colorspace;
- ctx->xfer_func = pix->xfer_func;
- ctx->ycbcr_enc = pix->ycbcr_enc;
- ctx->quantization = pix->quantization;
+ ctx->state.colorspace = pix->colorspace;
+ ctx->state.xfer_func = pix->xfer_func;
+ ctx->state.ycbcr_enc = pix->ycbcr_enc;
+ ctx->state.quantization = pix->quantization;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
pix_mp = &f->fmt.pix_mp;
- ctx->colorspace = pix_mp->colorspace;
- ctx->xfer_func = pix_mp->xfer_func;
- ctx->ycbcr_enc = pix_mp->ycbcr_enc;
- ctx->quantization = pix_mp->quantization;
+ ctx->state.colorspace = pix_mp->colorspace;
+ ctx->state.xfer_func = pix_mp->xfer_func;
+ ctx->state.ycbcr_enc = pix_mp->ycbcr_enc;
+ ctx->state.quantization = pix_mp->quantization;
break;
default:
break;
@@ -962,7 +832,7 @@ static int vicodec_enum_framesizes(struct file *file, void *fh,
case V4L2_PIX_FMT_FWHT:
break;
default:
- if (find_fmt(fsize->pixel_format) == fsize->pixel_format)
+ if (find_fmt(fsize->pixel_format)->id == fsize->pixel_format)
break;
return -EINVAL;
}
@@ -1119,30 +989,35 @@ static int vicodec_start_streaming(struct vb2_queue *q,
{
struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
struct vicodec_q_data *q_data = get_q_data(ctx, q->type);
+ struct v4l2_fwht_state *state = &ctx->state;
unsigned int size = q_data->width * q_data->height;
+ const struct v4l2_fwht_pixfmt_info *info = q_data->info;
+ unsigned int chroma_div = info->width_div * info->height_div;
q_data->sequence = 0;
if (!V4L2_TYPE_IS_OUTPUT(q->type))
return 0;
- ctx->ref_frame.width = ctx->ref_frame.height = 0;
- ctx->ref_frame.luma = kvmalloc(size * 3 / 2, GFP_KERNEL);
- ctx->comp_max_size = size * 3 / 2 + sizeof(struct cframe_hdr);
- ctx->compressed_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
- if (!ctx->ref_frame.luma || !ctx->compressed_frame) {
- kvfree(ctx->ref_frame.luma);
- kvfree(ctx->compressed_frame);
+ state->width = q_data->width;
+ state->height = q_data->height;
+ state->ref_frame.width = state->ref_frame.height = 0;
+ state->ref_frame.luma = kvmalloc(size + 2 * size / chroma_div,
+ GFP_KERNEL);
+ ctx->comp_max_size = size + 2 * size / chroma_div +
+ sizeof(struct fwht_cframe_hdr);
+ state->compressed_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
+ if (!state->ref_frame.luma || !state->compressed_frame) {
+ kvfree(state->ref_frame.luma);
+ kvfree(state->compressed_frame);
vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
return -ENOMEM;
}
- ctx->ref_frame.cb = ctx->ref_frame.luma + size;
- ctx->ref_frame.cr = ctx->ref_frame.cb + size / 4;
+ state->ref_frame.cb = state->ref_frame.luma + size;
+ state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
ctx->last_src_buf = NULL;
ctx->last_dst_buf = NULL;
- v4l2_ctrl_grab(ctx->ctrl_gop_size, true);
- ctx->gop_size = v4l2_ctrl_g_ctrl(ctx->ctrl_gop_size);
- ctx->gop_cnt = 0;
+ state->gop_cnt = 0;
ctx->cur_buf_offset = 0;
ctx->comp_size = 0;
ctx->comp_magic_cnt = 0;
@@ -1160,9 +1035,8 @@ static void vicodec_stop_streaming(struct vb2_queue *q)
if (!V4L2_TYPE_IS_OUTPUT(q->type))
return;
- kvfree(ctx->ref_frame.luma);
- kvfree(ctx->compressed_frame);
- v4l2_ctrl_grab(ctx->ctrl_gop_size, false);
+ kvfree(ctx->state.ref_frame.luma);
+ kvfree(ctx->state.compressed_frame);
}
static const struct vb2_ops vicodec_qops = {
@@ -1211,6 +1085,55 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
return vb2_queue_init(dst_vq);
}
+#define VICODEC_CID_CUSTOM_BASE (V4L2_CID_MPEG_BASE | 0xf000)
+#define VICODEC_CID_I_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 0)
+#define VICODEC_CID_P_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 1)
+
+static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct vicodec_ctx *ctx = container_of(ctrl->handler,
+ struct vicodec_ctx, hdl);
+
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+ ctx->state.gop_size = ctrl->val;
+ return 0;
+ case VICODEC_CID_I_FRAME_QP:
+ ctx->state.i_frame_qp = ctrl->val;
+ return 0;
+ case VICODEC_CID_P_FRAME_QP:
+ ctx->state.p_frame_qp = ctrl->val;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static struct v4l2_ctrl_ops vicodec_ctrl_ops = {
+ .s_ctrl = vicodec_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config vicodec_ctrl_i_frame = {
+ .ops = &vicodec_ctrl_ops,
+ .id = VICODEC_CID_I_FRAME_QP,
+ .name = "FWHT I-Frame QP Value",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 1,
+ .max = 31,
+ .def = 20,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config vicodec_ctrl_p_frame = {
+ .ops = &vicodec_ctrl_ops,
+ .id = VICODEC_CID_P_FRAME_QP,
+ .name = "FWHT P-Frame QP Value",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 1,
+ .max = 31,
+ .def = 20,
+ .step = 1,
+};
+
/*
* File operations
*/
@@ -1239,9 +1162,10 @@ static int vicodec_open(struct file *file)
ctx->dev = dev;
hdl = &ctx->hdl;
v4l2_ctrl_handler_init(hdl, 4);
- ctx->ctrl_gop_size = v4l2_ctrl_new_std(hdl, NULL,
- V4L2_CID_MPEG_VIDEO_GOP_SIZE,
- 1, 16, 1, 10);
+ v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+ 1, 16, 1, 10);
+ v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_i_frame, NULL);
+ v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_p_frame, NULL);
if (hdl->error) {
rc = hdl->error;
v4l2_ctrl_handler_free(hdl);
@@ -1251,25 +1175,34 @@ static int vicodec_open(struct file *file)
ctx->fh.ctrl_handler = hdl;
v4l2_ctrl_handler_setup(hdl);
- ctx->q_data[V4L2_M2M_SRC].fourcc =
- ctx->is_enc ? V4L2_PIX_FMT_YUV420 : V4L2_PIX_FMT_FWHT;
+ ctx->q_data[V4L2_M2M_SRC].info =
+ ctx->is_enc ? v4l2_fwht_get_pixfmt(0) : &pixfmt_fwht;
ctx->q_data[V4L2_M2M_SRC].width = 1280;
ctx->q_data[V4L2_M2M_SRC].height = 720;
- size = 1280 * 720 * 3 / 2;
- ctx->q_data[V4L2_M2M_SRC].sizeimage = size;
+ size = 1280 * 720 * ctx->q_data[V4L2_M2M_SRC].info->sizeimage_mult /
+ ctx->q_data[V4L2_M2M_SRC].info->sizeimage_div;
+ if (ctx->is_enc)
+ ctx->q_data[V4L2_M2M_SRC].sizeimage = size;
+ else
+ ctx->q_data[V4L2_M2M_SRC].sizeimage =
+ size + sizeof(struct fwht_cframe_hdr);
ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
- ctx->q_data[V4L2_M2M_DST].fourcc =
- ctx->is_enc ? V4L2_PIX_FMT_FWHT : V4L2_PIX_FMT_YUV420;
- ctx->colorspace = V4L2_COLORSPACE_REC709;
+ ctx->q_data[V4L2_M2M_DST].info =
+ ctx->is_enc ? &pixfmt_fwht : v4l2_fwht_get_pixfmt(0);
+ size = 1280 * 720 * ctx->q_data[V4L2_M2M_DST].info->sizeimage_mult /
+ ctx->q_data[V4L2_M2M_DST].info->sizeimage_div;
+ if (ctx->is_enc)
+ ctx->q_data[V4L2_M2M_DST].sizeimage =
+ size + sizeof(struct fwht_cframe_hdr);
+ else
+ ctx->q_data[V4L2_M2M_DST].sizeimage = size;
+ ctx->state.colorspace = V4L2_COLORSPACE_REC709;
- size += sizeof(struct cframe_hdr);
if (ctx->is_enc) {
- ctx->q_data[V4L2_M2M_DST].sizeimage = size;
ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->enc_dev, ctx,
&queue_init);
ctx->lock = &dev->enc_lock;
} else {
- ctx->q_data[V4L2_M2M_SRC].sizeimage = size;
ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->dec_dev, ctx,
&queue_init);
ctx->lock = &dev->dec_lock;
@@ -1327,7 +1260,6 @@ static const struct video_device vicodec_videodev = {
static const struct v4l2_m2m_ops m2m_ops = {
.device_run = device_run,
- .job_abort = job_abort,
.job_ready = job_ready,
};
@@ -1350,7 +1282,7 @@ static int vicodec_probe(struct platform_device *pdev)
#ifdef CONFIG_MEDIA_CONTROLLER
dev->mdev.dev = &pdev->dev;
- strlcpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model));
+ strscpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model));
media_device_init(&dev->mdev);
dev->v4l2_dev.mdev = &dev->mdev;
#endif
@@ -1378,7 +1310,7 @@ static int vicodec_probe(struct platform_device *pdev)
vfd = &dev->enc_vfd;
vfd->lock = &dev->enc_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
- strlcpy(vfd->name, "vicodec-enc", sizeof(vfd->name));
+ strscpy(vfd->name, "vicodec-enc", sizeof(vfd->name));
v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
video_set_drvdata(vfd, dev);
@@ -1395,7 +1327,7 @@ static int vicodec_probe(struct platform_device *pdev)
vfd = &dev->dec_vfd;
vfd->lock = &dev->dec_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
- strlcpy(vfd->name, "vicodec-dec", sizeof(vfd->name));
+ strscpy(vfd->name, "vicodec-dec", sizeof(vfd->name));
v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
video_set_drvdata(vfd, dev);
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
index c01e1592ad0a..c33900e3c23e 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -21,8 +21,10 @@
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <media/v4l2-async.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
struct video_mux {
@@ -316,6 +318,38 @@ static const struct v4l2_subdev_ops video_mux_subdev_ops = {
.video = &video_mux_subdev_video_ops,
};
+static int video_mux_parse_endpoint(struct device *dev,
+ struct v4l2_fwnode_endpoint *vep,
+ struct v4l2_async_subdev *asd)
+{
+ /*
+ * it's not an error if remote is missing on a video-mux
+ * input port, return -ENOTCONN to skip this endpoint with
+ * no error.
+ */
+ return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN;
+}
+
+static int video_mux_async_register(struct video_mux *vmux,
+ unsigned int num_input_pads)
+{
+ unsigned int i, *ports;
+ int ret;
+
+ ports = kcalloc(num_input_pads, sizeof(*ports), GFP_KERNEL);
+ if (!ports)
+ return -ENOMEM;
+ for (i = 0; i < num_input_pads; i++)
+ ports[i] = i;
+
+ ret = v4l2_async_register_fwnode_subdev(
+ &vmux->subdev, sizeof(struct v4l2_async_subdev),
+ ports, num_input_pads, video_mux_parse_endpoint);
+
+ kfree(ports);
+ return ret;
+}
+
static int video_mux_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -333,7 +367,7 @@ static int video_mux_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, vmux);
v4l2_subdev_init(&vmux->subdev, &video_mux_subdev_ops);
- snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%s", np->name);
+ snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%pOFn", np);
vmux->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
vmux->subdev.dev = dev;
@@ -383,7 +417,7 @@ static int video_mux_probe(struct platform_device *pdev)
vmux->subdev.entity.ops = &video_mux_ops;
- return v4l2_async_register_subdev(&vmux->subdev);
+ return video_mux_async_register(vmux, num_pads - 1);
}
static int video_mux_remove(struct platform_device *pdev)
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 462099a141e4..60c522ee2e03 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -1038,7 +1038,7 @@ static int vim2m_probe(struct platform_device *pdev)
#ifdef CONFIG_MEDIA_CONTROLLER
dev->mdev.dev = &pdev->dev;
- strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
+ strscpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
media_device_init(&dev->mdev);
dev->v4l2_dev.mdev = &dev->mdev;
diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c
index ec68feaac378..3f7e9ed56633 100644
--- a/drivers/media/platform/vimc/vimc-capture.c
+++ b/drivers/media/platform/vimc/vimc-capture.c
@@ -71,8 +71,8 @@ static int vimc_cap_querycap(struct file *file, void *priv,
{
struct vimc_cap_device *vcap = video_drvdata(file);
- strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
- strlcpy(cap->card, KBUILD_MODNAME, sizeof(cap->card));
+ strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+ strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:%s", vcap->vdev.v4l2_dev->name);
@@ -476,7 +476,7 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master,
vdev->queue = q;
vdev->v4l2_dev = v4l2_dev;
vdev->vfl_dir = VFL_DIR_RX;
- strlcpy(vdev->name, pdata->entity_name, sizeof(vdev->name));
+ strscpy(vdev->name, pdata->entity_name, sizeof(vdev->name));
video_set_drvdata(vdev, &vcap->ved);
/* Register the video_device with the v4l2 and the media framework */
diff --git a/drivers/media/platform/vimc/vimc-common.c b/drivers/media/platform/vimc/vimc-common.c
index 617415c224fe..dee1b9dfc4f6 100644
--- a/drivers/media/platform/vimc/vimc-common.c
+++ b/drivers/media/platform/vimc/vimc-common.c
@@ -430,7 +430,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved,
sd->entity.function = function;
sd->entity.ops = &vimc_ent_sd_mops;
sd->owner = THIS_MODULE;
- strlcpy(sd->name, name, sizeof(sd->name));
+ strscpy(sd->name, name, sizeof(sd->name));
v4l2_set_subdevdata(sd, ved);
/* Expose this subdev to user space */
diff --git a/drivers/media/platform/vimc/vimc-core.c b/drivers/media/platform/vimc/vimc-core.c
index 9246f265de31..ce809d2e3d53 100644
--- a/drivers/media/platform/vimc/vimc-core.c
+++ b/drivers/media/platform/vimc/vimc-core.c
@@ -259,7 +259,7 @@ static struct component_match *vimc_add_subdevs(struct vimc_device *vimc)
dev_dbg(&vimc->pdev.dev, "new pdev for %s\n",
vimc->pipe_cfg->ents[i].drv);
- strlcpy(pdata.entity_name, vimc->pipe_cfg->ents[i].name,
+ strscpy(pdata.entity_name, vimc->pipe_cfg->ents[i].name,
sizeof(pdata.entity_name));
vimc->subdevs[i] = platform_device_register_data(&vimc->pdev.dev,
@@ -317,7 +317,7 @@ static int vimc_probe(struct platform_device *pdev)
vimc->v4l2_dev.mdev = &vimc->mdev;
/* Initialize media device */
- strlcpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME,
+ strscpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME,
sizeof(vimc->mdev.model));
vimc->mdev.dev = &pdev->dev;
media_device_init(&vimc->mdev);
diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c
index b2b89315e7ba..edf4c85ae63d 100644
--- a/drivers/media/platform/vimc/vimc-sensor.c
+++ b/drivers/media/platform/vimc/vimc-sensor.c
@@ -317,6 +317,18 @@ static int vimc_sen_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_VFLIP:
tpg_s_vflip(&vsen->tpg, ctrl->val);
break;
+ case V4L2_CID_BRIGHTNESS:
+ tpg_s_brightness(&vsen->tpg, ctrl->val);
+ break;
+ case V4L2_CID_CONTRAST:
+ tpg_s_contrast(&vsen->tpg, ctrl->val);
+ break;
+ case V4L2_CID_HUE:
+ tpg_s_hue(&vsen->tpg, ctrl->val);
+ break;
+ case V4L2_CID_SATURATION:
+ tpg_s_saturation(&vsen->tpg, ctrl->val);
+ break;
default:
return -EINVAL;
}
@@ -378,6 +390,14 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master,
V4L2_CID_VFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+ v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 255, 1, 128);
+ v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
+ V4L2_CID_HUE, -128, 127, 1, 0);
+ v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
+ V4L2_CID_SATURATION, 0, 255, 1, 128);
vsen->sd.ctrl_handler = &vsen->hdl;
if (vsen->hdl.error) {
ret = vsen->hdl.error;
diff --git a/drivers/media/platform/vivid/vivid-cec.c b/drivers/media/platform/vivid/vivid-cec.c
index 71105fa4c5f9..4d822dbed972 100644
--- a/drivers/media/platform/vivid/vivid-cec.c
+++ b/drivers/media/platform/vivid/vivid-cec.c
@@ -241,11 +241,11 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg)
cec_ops_set_osd_string(msg, &disp_ctl, osd);
switch (disp_ctl) {
case CEC_OP_DISP_CTL_DEFAULT:
- strcpy(dev->osd, osd);
+ strscpy(dev->osd, osd, sizeof(dev->osd));
dev->osd_jiffies = jiffies;
break;
case CEC_OP_DISP_CTL_UNTIL_CLEARED:
- strcpy(dev->osd, osd);
+ strscpy(dev->osd, osd, sizeof(dev->osd));
dev->osd_jiffies = 0;
break;
case CEC_OP_DISP_CTL_CLEAR:
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index 31db363602e5..06961e7d8036 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -197,8 +197,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct vivid_dev *dev = video_drvdata(file);
- strcpy(cap->driver, "vivid");
- strcpy(cap->card, "vivid");
+ strscpy(cap->driver, "vivid", sizeof(cap->driver));
+ strscpy(cap->card, "vivid", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:%s", dev->v4l2_dev.name);
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 477c80a4d44c..cd4c8230563c 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -111,7 +111,7 @@ enum vivid_colorspace {
VIVID_CS_170M,
VIVID_CS_709,
VIVID_CS_SRGB,
- VIVID_CS_ADOBERGB,
+ VIVID_CS_OPRGB,
VIVID_CS_2020,
VIVID_CS_DCI_P3,
VIVID_CS_240M,
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 5429193fbb91..999aa101b150 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -348,7 +348,7 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
V4L2_COLORSPACE_SMPTE170M,
V4L2_COLORSPACE_REC709,
V4L2_COLORSPACE_SRGB,
- V4L2_COLORSPACE_ADOBERGB,
+ V4L2_COLORSPACE_OPRGB,
V4L2_COLORSPACE_BT2020,
V4L2_COLORSPACE_DCI_P3,
V4L2_COLORSPACE_SMPTE240M,
@@ -729,7 +729,7 @@ static const char * const vivid_ctrl_colorspace_strings[] = {
"SMPTE 170M",
"Rec. 709",
"sRGB",
- "AdobeRGB",
+ "opRGB",
"BT.2020",
"DCI-P3",
"SMPTE 240M",
@@ -752,7 +752,7 @@ static const char * const vivid_ctrl_xfer_func_strings[] = {
"Default",
"Rec. 709",
"sRGB",
- "AdobeRGB",
+ "opRGB",
"SMPTE 240M",
"None",
"DCI-P3",
diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c
index bbbc1b6938a5..1a89593b0c86 100644
--- a/drivers/media/platform/vivid/vivid-osd.c
+++ b/drivers/media/platform/vivid/vivid-osd.c
@@ -110,7 +110,7 @@ static int vivid_fb_get_fix(struct vivid_dev *dev, struct fb_fix_screeninfo *fix
{
dprintk(dev, 1, "vivid_fb_get_fix\n");
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strlcpy(fix->id, "vioverlay fb", sizeof(fix->id));
+ strscpy(fix->id, "vioverlay fb", sizeof(fix->id));
fix->smem_start = dev->video_pbase;
fix->smem_len = dev->video_buffer_size;
fix->type = FB_TYPE_PACKED_PIXELS;
diff --git a/drivers/media/platform/vivid/vivid-radio-common.c b/drivers/media/platform/vivid/vivid-radio-common.c
index 7c8efe38ff5b..138c7bce68b1 100644
--- a/drivers/media/platform/vivid/vivid-radio-common.c
+++ b/drivers/media/platform/vivid/vivid-radio-common.c
@@ -76,10 +76,10 @@ void vivid_radio_rds_init(struct vivid_dev *dev)
rds->ta = dev->radio_tx_rds_ta->cur.val;
rds->tp = dev->radio_tx_rds_tp->cur.val;
rds->ms = dev->radio_tx_rds_ms->cur.val;
- strlcpy(rds->psname,
+ strscpy(rds->psname,
dev->radio_tx_rds_psname->p_cur.p_char,
sizeof(rds->psname));
- strlcpy(rds->radiotext,
+ strscpy(rds->radiotext,
dev->radio_tx_rds_radiotext->p_cur.p_char + alt * 64,
sizeof(rds->radiotext));
v4l2_ctrl_unlock(dev->radio_tx_rds_pi);
diff --git a/drivers/media/platform/vivid/vivid-radio-rx.c b/drivers/media/platform/vivid/vivid-radio-rx.c
index 1f86d7d4f72f..232cab508f48 100644
--- a/drivers/media/platform/vivid/vivid-radio-rx.c
+++ b/drivers/media/platform/vivid/vivid-radio-rx.c
@@ -223,7 +223,7 @@ int vivid_radio_rx_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
if (vt->index > 0)
return -EINVAL;
- strlcpy(vt->name, "AM/FM/SW Receiver", sizeof(vt->name));
+ strscpy(vt->name, "AM/FM/SW Receiver", sizeof(vt->name));
vt->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_RDS |
(dev->radio_rx_rds_controls ?
diff --git a/drivers/media/platform/vivid/vivid-radio-tx.c b/drivers/media/platform/vivid/vivid-radio-tx.c
index 1a3749ba5e7e..049d40b948bb 100644
--- a/drivers/media/platform/vivid/vivid-radio-tx.c
+++ b/drivers/media/platform/vivid/vivid-radio-tx.c
@@ -103,7 +103,7 @@ int vidioc_g_modulator(struct file *file, void *fh, struct v4l2_modulator *a)
if (a->index > 0)
return -EINVAL;
- strlcpy(a->name, "AM/FM/SW Transmitter", sizeof(a->name));
+ strscpy(a->name, "AM/FM/SW Transmitter", sizeof(a->name));
a->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_RDS |
(dev->radio_tx_rds_controls ?
diff --git a/drivers/media/platform/vivid/vivid-rds-gen.c b/drivers/media/platform/vivid/vivid-rds-gen.c
index 39ca9a56448c..b5b104ee64c9 100644
--- a/drivers/media/platform/vivid/vivid-rds-gen.c
+++ b/drivers/media/platform/vivid/vivid-rds-gen.c
@@ -147,11 +147,11 @@ void vivid_rds_gen_fill(struct vivid_rds_gen *rds, unsigned freq,
snprintf(rds->psname, sizeof(rds->psname), "%6d.%1d",
freq / 16, ((freq & 0xf) * 10) / 16);
if (alt)
- strlcpy(rds->radiotext,
+ strscpy(rds->radiotext,
" The Radio Data System can switch between different Radio Texts ",
sizeof(rds->radiotext));
else
- strlcpy(rds->radiotext,
+ strscpy(rds->radiotext,
"An example of Radio Text as transmitted by the Radio Data System",
sizeof(rds->radiotext));
}
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index cfb7cb4d37a8..200b789a3f21 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -396,7 +396,7 @@ int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
{
switch (vt->index) {
case 0:
- strlcpy(vt->name, "ADC", sizeof(vt->name));
+ strscpy(vt->name, "ADC", sizeof(vt->name));
vt->type = V4L2_TUNER_ADC;
vt->capability =
V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
@@ -404,7 +404,7 @@ int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
vt->rangehigh = bands_adc[2].rangehigh;
return 0;
case 1:
- 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;
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 1599159f2574..6cf910a60ecf 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -51,7 +51,7 @@ static const struct vivid_fmt formats_ovl[] = {
};
/* The number of discrete webcam framesizes */
-#define VIVID_WEBCAM_SIZES 5
+#define VIVID_WEBCAM_SIZES 6
/* The number of discrete webcam frameintervals */
#define VIVID_WEBCAM_IVALS (VIVID_WEBCAM_SIZES * 2)
@@ -59,6 +59,7 @@ static const struct vivid_fmt formats_ovl[] = {
static const struct v4l2_frmsize_discrete webcam_sizes[VIVID_WEBCAM_SIZES] = {
{ 320, 180 },
{ 640, 360 },
+ { 640, 480 },
{ 1280, 720 },
{ 1920, 1080 },
{ 3840, 2160 },
@@ -74,9 +75,11 @@ static const struct v4l2_fract webcam_intervals[VIVID_WEBCAM_IVALS] = {
{ 1, 4 },
{ 1, 5 },
{ 1, 10 },
+ { 2, 25 },
{ 1, 15 },
{ 1, 25 },
{ 1, 30 },
+ { 1, 40 },
{ 1, 50 },
{ 1, 60 },
};
@@ -1505,7 +1508,7 @@ int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
break;
}
}
- strlcpy(vt->name, "TV Tuner", sizeof(vt->name));
+ strscpy(vt->name, "TV Tuner", sizeof(vt->name));
return 0;
}
@@ -1722,7 +1725,7 @@ int vidioc_s_edid(struct file *file, void *_fh,
return -E2BIG;
}
phys_addr = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, NULL);
- ret = cec_phys_addr_validate(phys_addr, &phys_addr, NULL);
+ ret = v4l2_phys_addr_validate(phys_addr, &phys_addr, NULL);
if (ret)
return ret;
@@ -1738,7 +1741,7 @@ set_phys_addr:
for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
cec_s_phys_addr(dev->cec_tx_adap[i],
- cec_phys_addr_for_input(phys_addr, i + 1),
+ v4l2_phys_addr_for_input(phys_addr, i + 1),
false);
return 0;
}
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index be531caa2cdf..9645a91b8782 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -450,6 +450,34 @@ struct vivid_fmt vivid_formats[] = {
.buffers = 1,
},
{
+ .fourcc = V4L2_PIX_FMT_SBGGR16, /* Bayer BG/GR */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGBRG16, /* Bayer GB/RG */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG16, /* Bayer GR/BG */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB16, /* Bayer RG/GB */
+ .vdownsampling = { 1 },
+ .bit_depth = { 16 },
+ .planes = 1,
+ .buffers = 1,
+ },
+ {
.fourcc = V4L2_PIX_FMT_HSV24, /* HSV 24bits */
.color_enc = TGP_COLOR_ENC_HSV,
.vdownsampling = { 1 },
@@ -863,7 +891,7 @@ int vidioc_g_edid(struct file *file, void *_fh,
if (edid->blocks > dev->edid_blocks - edid->start_block)
edid->blocks = dev->edid_blocks - edid->start_block;
if (adap)
- cec_set_edid_phys_addr(dev->edid, dev->edid_blocks * 128, adap->phys_addr);
+ v4l2_set_edid_phys_addr(dev->edid, dev->edid_blocks * 128, adap->phys_addr);
memcpy(edid->edid, dev->edid + edid->start_block * 128, edid->blocks * 128);
return 0;
}
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index 51fec66d8d45..50248e2176a0 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -413,7 +413,7 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
} else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M &&
mp->colorspace != V4L2_COLORSPACE_REC709 &&
- mp->colorspace != V4L2_COLORSPACE_ADOBERGB &&
+ mp->colorspace != V4L2_COLORSPACE_OPRGB &&
mp->colorspace != V4L2_COLORSPACE_BT2020 &&
mp->colorspace != V4L2_COLORSPACE_SRGB) {
mp->colorspace = V4L2_COLORSPACE_REC709;
diff --git a/drivers/media/platform/vsp1/vsp1_brx.c b/drivers/media/platform/vsp1/vsp1_brx.c
index 359917b5d842..5e50178b057d 100644
--- a/drivers/media/platform/vsp1/vsp1_brx.c
+++ b/drivers/media/platform/vsp1/vsp1_brx.c
@@ -153,7 +153,7 @@ static int brx_set_format(struct v4l2_subdev *subdev,
format = vsp1_entity_get_pad_format(&brx->entity, config, fmt->pad);
*format = fmt->format;
- /* Reset the compose rectangle */
+ /* Reset the compose rectangle. */
if (fmt->pad != brx->entity.source_pad) {
struct v4l2_rect *compose;
@@ -164,7 +164,7 @@ static int brx_set_format(struct v4l2_subdev *subdev,
compose->height = format->height;
}
- /* Propagate the format code to all pads */
+ /* Propagate the format code to all pads. */
if (fmt->pad == BRX_PAD_SINK(0)) {
unsigned int i;
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index b9c0f695d002..8d86f618ec77 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -770,6 +770,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
struct vsp1_device *vsp1 = dev_get_drvdata(dev);
struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
const struct vsp1_format_info *fmtinfo;
+ unsigned int chroma_hsub;
struct vsp1_rwpf *rpf;
if (rpf_index >= vsp1->info->rpf_count)
@@ -810,10 +811,18 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
return -EINVAL;
}
+ /*
+ * Only formats with three planes can affect the chroma planes pitch.
+ * All formats with two planes have a horizontal subsampling value of 2,
+ * but combine U and V in a single chroma plane, which thus results in
+ * the luma plane and chroma plane having the same pitch.
+ */
+ chroma_hsub = (fmtinfo->planes == 3) ? fmtinfo->hsub : 1;
+
rpf->fmtinfo = fmtinfo;
rpf->format.num_planes = fmtinfo->planes;
rpf->format.plane_fmt[0].bytesperline = cfg->pitch;
- rpf->format.plane_fmt[1].bytesperline = cfg->pitch;
+ rpf->format.plane_fmt[1].bytesperline = cfg->pitch / chroma_hsub;
rpf->alpha = cfg->alpha;
rpf->mem.addr[0] = cfg->mem[0];
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index b6619c9c18bb..c650e45bb0ad 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -242,7 +242,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
mdev->dev = vsp1->dev;
mdev->hw_revision = vsp1->version;
- strlcpy(mdev->model, vsp1->info->model, sizeof(mdev->model));
+ strscpy(mdev->model, vsp1->info->model, sizeof(mdev->model));
snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
dev_name(mdev->dev));
media_device_init(mdev);
@@ -802,7 +802,7 @@ static int vsp1_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, vsp1);
- /* I/O and IRQ resources (clock managed by the clock PM domain) */
+ /* I/O and IRQ resources (clock managed by the clock PM domain). */
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
vsp1->mmio = devm_ioremap_resource(&pdev->dev, io);
if (IS_ERR(vsp1->mmio))
@@ -821,7 +821,7 @@ static int vsp1_probe(struct platform_device *pdev)
return ret;
}
- /* FCP (optional) */
+ /* FCP (optional). */
fcp_node = of_parse_phandle(pdev->dev.of_node, "renesas,fcp", 0);
if (fcp_node) {
vsp1->fcp = rcar_fcp_get(fcp_node);
@@ -869,7 +869,7 @@ static int vsp1_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "IP version 0x%08x\n", vsp1->version);
- /* Instanciate entities */
+ /* Instantiate entities. */
ret = vsp1_create_entities(vsp1);
if (ret < 0) {
dev_err(&pdev->dev, "failed to create entities\n");
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 36a29e13109e..a54ab528b060 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -404,7 +404,7 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
format = vsp1_entity_get_pad_format(entity, config, entity->source_pad);
*format = fmt->format;
- /* Reset the crop and compose rectangles */
+ /* Reset the crop and compose rectangles. */
selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad,
V4L2_SEL_TGT_CROP);
selection->left = 0;
diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c
index 5e15c8ff88d9..8b01e99acd20 100644
--- a/drivers/media/platform/vsp1/vsp1_histo.c
+++ b/drivers/media/platform/vsp1/vsp1_histo.c
@@ -429,8 +429,8 @@ static int histo_v4l2_querycap(struct file *file, void *fh,
cap->device_caps = V4L2_CAP_META_CAPTURE
| V4L2_CAP_STREAMING;
- strlcpy(cap->driver, "vsp1", sizeof(cap->driver));
- strlcpy(cap->card, histo->video.name, sizeof(cap->card));
+ strscpy(cap->driver, "vsp1", sizeof(cap->driver));
+ strscpy(cap->card, histo->video.name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(histo->entity.vsp1->dev));
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index 0cb63244b21a..0b18f0bd7419 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -88,14 +88,35 @@ static void lif_configure_stream(struct vsp1_entity *entity,
{
const struct v4l2_mbus_framefmt *format;
struct vsp1_lif *lif = to_lif(&entity->subdev);
- unsigned int hbth = 1300;
- unsigned int obth = 400;
- unsigned int lbth = 200;
+ unsigned int hbth;
+ unsigned int obth;
+ unsigned int lbth;
format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config,
LIF_PAD_SOURCE);
- obth = min(obth, (format->width + 1) / 2 * format->height - 4);
+ switch (entity->vsp1->version & VI6_IP_VERSION_SOC_MASK) {
+ case VI6_IP_VERSION_MODEL_VSPD_GEN2:
+ case VI6_IP_VERSION_MODEL_VSPD_V2H:
+ hbth = 1536;
+ obth = min(128U, (format->width + 1) / 2 * format->height - 4);
+ lbth = 1520;
+ break;
+
+ case VI6_IP_VERSION_MODEL_VSPDL_GEN3:
+ case VI6_IP_VERSION_MODEL_VSPD_V3:
+ hbth = 0;
+ obth = 1500;
+ lbth = 0;
+ break;
+
+ case VI6_IP_VERSION_MODEL_VSPD_GEN3:
+ default:
+ hbth = 0;
+ obth = 3000;
+ lbth = 0;
+ break;
+ }
vsp1_lif_write(lif, dlb, VI6_LIF_CSBTH,
(hbth << VI6_LIF_CSBTH_HBTH_SHIFT) |
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 3738ff2f7b85..f6e4157095cc 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* vsp1_regs.h -- R-Car VSP1 Registers Definitions
*
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index f8005b60b9d2..616afa7e165f 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -108,7 +108,7 @@ static void rpf_configure_stream(struct vsp1_entity *entity,
vsp1_rpf_write(rpf, dlb, VI6_RPF_INFMT, infmt);
vsp1_rpf_write(rpf, dlb, VI6_RPF_DSWAP, fmtinfo->swap);
- /* Output location */
+ /* Output location. */
if (pipe->brx) {
const struct v4l2_rect *compose;
@@ -309,7 +309,7 @@ static void rpf_configure_partition(struct vsp1_entity *entity,
/*
* Interlaced pipelines will use the extended pre-cmd to process
- * SRCM_ADDR_{Y,C0,C1}
+ * SRCM_ADDR_{Y,C0,C1}.
*/
if (pipe->interlaced) {
vsp1_rpf_configure_autofld(rpf, dl);
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index 04e4e05af6ae..b1617cb1f2b9 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -312,6 +312,11 @@ static unsigned int sru_max_width(struct vsp1_entity *entity,
output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
SRU_PAD_SOURCE);
+ /*
+ * The maximum input width of the SRU is 288 input pixels, but 32
+ * pixels are reserved to support overlapping partition windows when
+ * scaling.
+ */
if (input->width != output->width)
return 512;
else
@@ -333,7 +338,7 @@ static void sru_partition(struct vsp1_entity *entity,
output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
SRU_PAD_SOURCE);
- /* Adapt if SRUx2 is enabled */
+ /* Adapt if SRUx2 is enabled. */
if (input->width != output->width) {
window->width /= 2;
window->left /= 2;
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index c20c84b54936..27012af973b2 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -314,13 +314,13 @@ static void uds_configure_partition(struct vsp1_entity *entity,
output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
UDS_PAD_SOURCE);
- /* Input size clipping */
+ /* Input size clipping. */
vsp1_uds_write(uds, dlb, VI6_UDS_HSZCLIP, VI6_UDS_HSZCLIP_HCEN |
(0 << VI6_UDS_HSZCLIP_HCL_OFST_SHIFT) |
(partition->uds_sink.width
<< VI6_UDS_HSZCLIP_HCL_SIZE_SHIFT));
- /* Output size clipping */
+ /* Output size clipping. */
vsp1_uds_write(uds, dlb, VI6_UDS_CLIP_SIZE,
(partition->uds_source.width
<< VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
@@ -342,6 +342,14 @@ static unsigned int uds_max_width(struct vsp1_entity *entity,
UDS_PAD_SOURCE);
hscale = output->width / input->width;
+ /*
+ * The maximum width of the UDS is 304 pixels. These are input pixels
+ * in the event of up-scaling, and output pixels in the event of
+ * downscaling.
+ *
+ * To support overlapping partition windows we clamp at units of 256 and
+ * the remaining pixels are reserved.
+ */
if (hscale <= 2)
return 256;
else if (hscale <= 4)
@@ -366,7 +374,7 @@ static void uds_partition(struct vsp1_entity *entity,
const struct v4l2_mbus_framefmt *output;
const struct v4l2_mbus_framefmt *input;
- /* Initialise the partition state */
+ /* Initialise the partition state. */
partition->uds_sink = *window;
partition->uds_source = *window;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 81d47a09d7bc..771dfe1f7c20 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -38,9 +38,7 @@
#define VSP1_VIDEO_DEF_WIDTH 1024
#define VSP1_VIDEO_DEF_HEIGHT 768
-#define VSP1_VIDEO_MIN_WIDTH 2U
#define VSP1_VIDEO_MAX_WIDTH 8190U
-#define VSP1_VIDEO_MIN_HEIGHT 2U
#define VSP1_VIDEO_MAX_HEIGHT 8190U
/* -----------------------------------------------------------------------------
@@ -136,9 +134,8 @@ static int __vsp1_video_try_format(struct vsp1_video *video,
height = round_down(height, info->vsub);
/* Clamp the width and height. */
- pix->width = clamp(width, VSP1_VIDEO_MIN_WIDTH, VSP1_VIDEO_MAX_WIDTH);
- pix->height = clamp(height, VSP1_VIDEO_MIN_HEIGHT,
- VSP1_VIDEO_MAX_HEIGHT);
+ pix->width = clamp(width, info->hsub, VSP1_VIDEO_MAX_WIDTH);
+ pix->height = clamp(height, info->vsub, VSP1_VIDEO_MAX_HEIGHT);
/*
* Compute and clamp the stride and image size. While not documented in
@@ -867,7 +864,7 @@ static void vsp1_video_cleanup_pipeline(struct vsp1_pipeline *pipe)
pipe->stream_config = NULL;
pipe->configured = false;
- /* Release our partition table allocation */
+ /* Release our partition table allocation. */
kfree(pipe->part_table);
pipe->part_table = NULL;
}
@@ -976,8 +973,8 @@ vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
cap->device_caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE
| V4L2_CAP_STREAMING;
- strlcpy(cap->driver, "vsp1", sizeof(cap->driver));
- strlcpy(cap->card, video->video.name, sizeof(cap->card));
+ strscpy(cap->driver, "vsp1", sizeof(cap->driver));
+ strscpy(cap->card, video->video.name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(video->vsp1->dev));
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index c2a1a7f97e26..32bb207b2007 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -317,7 +317,7 @@ static void wpf_configure_stream(struct vsp1_entity *entity,
vsp1_wpf_write(wpf, dlb, VI6_WPF_SRCRPF, srcrpf);
- /* Enable interrupts */
+ /* Enable interrupts. */
vsp1_dl_body_write(dlb, VI6_WPF_IRQ_STA(wpf->entity.index), 0);
vsp1_dl_body_write(dlb, VI6_WPF_IRQ_ENB(wpf->entity.index),
VI6_WFP_IRQ_ENB_DFEE);
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
index d041f94be832..4ae9d38c9433 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -504,10 +504,10 @@ xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS
| dma->xdev->v4l2_caps;
- strlcpy(cap->driver, "xilinx-vipp", sizeof(cap->driver));
- strlcpy(cap->card, dma->video.name, sizeof(cap->card));
- snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s:%u",
- dma->xdev->dev->of_node->name, dma->port);
+ strscpy(cap->driver, "xilinx-vipp", sizeof(cap->driver));
+ strscpy(cap->card, dma->video.name, sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%pOFn:%u",
+ dma->xdev->dev->of_node, dma->port);
return 0;
}
@@ -527,7 +527,7 @@ xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f)
return -EINVAL;
f->pixelformat = dma->format.pixelformat;
- strlcpy(f->description, dma->fmtinfo->description,
+ strscpy(f->description, dma->fmtinfo->description,
sizeof(f->description));
return 0;
@@ -693,8 +693,8 @@ int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma,
dma->video.fops = &xvip_dma_fops;
dma->video.v4l2_dev = &xdev->v4l2_dev;
dma->video.queue = &dma->queue;
- snprintf(dma->video.name, sizeof(dma->video.name), "%s %s %u",
- xdev->dev->of_node->name,
+ snprintf(dma->video.name, sizeof(dma->video.name), "%pOFn %s %u",
+ xdev->dev->of_node,
type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? "output" : "input",
port);
dma->video.vfl_type = VFL_TYPE_GRABBER;
diff --git a/drivers/media/platform/xilinx/xilinx-tpg.c b/drivers/media/platform/xilinx/xilinx-tpg.c
index 9c49d1d10bee..851d20dcd550 100644
--- a/drivers/media/platform/xilinx/xilinx-tpg.c
+++ b/drivers/media/platform/xilinx/xilinx-tpg.c
@@ -833,7 +833,7 @@ static int xtpg_probe(struct platform_device *pdev)
v4l2_subdev_init(subdev, &xtpg_ops);
subdev->dev = &pdev->dev;
subdev->internal_ops = &xtpg_internal_ops;
- strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+ strscpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
v4l2_set_subdevdata(subdev, xtpg);
subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
subdev->entity.ops = &xtpg_media_ops;
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index 6d95ec1e9a6b..99e016d35d91 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -32,33 +32,36 @@
/**
* struct xvip_graph_entity - Entity in the video graph
- * @list: list entry in a graph entities list
- * @node: the entity's DT node
- * @entity: media entity, from the corresponding V4L2 subdev
* @asd: subdev asynchronous registration information
+ * @entity: media entity, from the corresponding V4L2 subdev
* @subdev: V4L2 subdev
*/
struct xvip_graph_entity {
- struct list_head list;
- struct device_node *node;
+ struct v4l2_async_subdev asd; /* must be first */
struct media_entity *entity;
-
- struct v4l2_async_subdev asd;
struct v4l2_subdev *subdev;
};
+static inline struct xvip_graph_entity *
+to_xvip_entity(struct v4l2_async_subdev *asd)
+{
+ return container_of(asd, struct xvip_graph_entity, asd);
+}
+
/* -----------------------------------------------------------------------------
* Graph Management
*/
static struct xvip_graph_entity *
xvip_graph_find_entity(struct xvip_composite_device *xdev,
- const struct device_node *node)
+ const struct fwnode_handle *fwnode)
{
struct xvip_graph_entity *entity;
+ struct v4l2_async_subdev *asd;
- list_for_each_entry(entity, &xdev->entities, list) {
- if (entity->node == node)
+ list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
+ entity = to_xvip_entity(asd);
+ if (entity->asd.match.fwnode == fwnode)
return entity;
}
@@ -75,22 +78,23 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
struct media_pad *remote_pad;
struct xvip_graph_entity *ent;
struct v4l2_fwnode_link link;
- struct device_node *ep = NULL;
+ struct fwnode_handle *ep = NULL;
int ret = 0;
dev_dbg(xdev->dev, "creating links for entity %s\n", local->name);
while (1) {
/* Get the next endpoint and parse its link. */
- ep = of_graph_get_next_endpoint(entity->node, ep);
+ ep = fwnode_graph_get_next_endpoint(entity->asd.match.fwnode,
+ ep);
if (ep == NULL)
break;
- dev_dbg(xdev->dev, "processing endpoint %pOF\n", ep);
+ dev_dbg(xdev->dev, "processing endpoint %p\n", ep);
- ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link);
+ ret = v4l2_fwnode_parse_link(ep, &link);
if (ret < 0) {
- dev_err(xdev->dev, "failed to parse link for %pOF\n",
+ dev_err(xdev->dev, "failed to parse link for %p\n",
ep);
continue;
}
@@ -99,9 +103,8 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
* the link.
*/
if (link.local_port >= local->num_pads) {
- dev_err(xdev->dev, "invalid port number %u for %pOF\n",
- link.local_port,
- to_of_node(link.local_node));
+ dev_err(xdev->dev, "invalid port number %u for %p\n",
+ link.local_port, link.local_node);
v4l2_fwnode_put_link(&link);
ret = -EINVAL;
break;
@@ -110,28 +113,25 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
local_pad = &local->pads[link.local_port];
if (local_pad->flags & MEDIA_PAD_FL_SINK) {
- dev_dbg(xdev->dev, "skipping sink port %pOF:%u\n",
- to_of_node(link.local_node),
- link.local_port);
+ dev_dbg(xdev->dev, "skipping sink port %p:%u\n",
+ link.local_node, link.local_port);
v4l2_fwnode_put_link(&link);
continue;
}
/* Skip DMA engines, they will be processed separately. */
if (link.remote_node == of_fwnode_handle(xdev->dev->of_node)) {
- dev_dbg(xdev->dev, "skipping DMA port %pOF:%u\n",
- to_of_node(link.local_node),
- link.local_port);
+ dev_dbg(xdev->dev, "skipping DMA port %p:%u\n",
+ link.local_node, link.local_port);
v4l2_fwnode_put_link(&link);
continue;
}
/* Find the remote entity. */
- ent = xvip_graph_find_entity(xdev,
- to_of_node(link.remote_node));
+ ent = xvip_graph_find_entity(xdev, link.remote_node);
if (ent == NULL) {
- dev_err(xdev->dev, "no entity found for %pOF\n",
- to_of_node(link.remote_node));
+ dev_err(xdev->dev, "no entity found for %p\n",
+ link.remote_node);
v4l2_fwnode_put_link(&link);
ret = -ENODEV;
break;
@@ -140,8 +140,8 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
remote = ent->entity;
if (link.remote_port >= remote->num_pads) {
- dev_err(xdev->dev, "invalid port number %u on %pOF\n",
- link.remote_port, to_of_node(link.remote_node));
+ dev_err(xdev->dev, "invalid port number %u on %p\n",
+ link.remote_port, link.remote_node);
v4l2_fwnode_put_link(&link);
ret = -EINVAL;
break;
@@ -168,7 +168,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
}
}
- of_node_put(ep);
+ fwnode_handle_put(ep);
return ret;
}
@@ -230,8 +230,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
dma->video.name);
/* Find the remote entity. */
- ent = xvip_graph_find_entity(xdev,
- to_of_node(link.remote_node));
+ ent = xvip_graph_find_entity(xdev, link.remote_node);
if (ent == NULL) {
dev_err(xdev->dev, "no entity found for %pOF\n",
to_of_node(link.remote_node));
@@ -289,12 +288,14 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
struct xvip_composite_device *xdev =
container_of(notifier, struct xvip_composite_device, notifier);
struct xvip_graph_entity *entity;
+ struct v4l2_async_subdev *asd;
int ret;
dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
/* Create links for every entity. */
- list_for_each_entry(entity, &xdev->entities, list) {
+ list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
+ entity = to_xvip_entity(asd);
ret = xvip_graph_build_one(xdev, entity);
if (ret < 0)
return ret;
@@ -314,22 +315,25 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *subdev,
- struct v4l2_async_subdev *asd)
+ struct v4l2_async_subdev *unused)
{
struct xvip_composite_device *xdev =
container_of(notifier, struct xvip_composite_device, notifier);
struct xvip_graph_entity *entity;
+ struct v4l2_async_subdev *asd;
/* Locate the entity corresponding to the bound subdev and store the
* subdev pointer.
*/
- list_for_each_entry(entity, &xdev->entities, list) {
- if (entity->node != subdev->dev->of_node)
+ list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
+ entity = to_xvip_entity(asd);
+
+ if (entity->asd.match.fwnode != subdev->fwnode)
continue;
if (entity->subdev) {
- dev_err(xdev->dev, "duplicate subdev for node %pOF\n",
- entity->node);
+ dev_err(xdev->dev, "duplicate subdev for node %p\n",
+ entity->asd.match.fwnode);
return -EINVAL;
}
@@ -349,56 +353,60 @@ static const struct v4l2_async_notifier_operations xvip_graph_notify_ops = {
};
static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
- struct device_node *node)
+ struct fwnode_handle *fwnode)
{
- struct xvip_graph_entity *entity;
- struct device_node *remote;
- struct device_node *ep = NULL;
+ struct fwnode_handle *remote;
+ struct fwnode_handle *ep = NULL;
int ret = 0;
- dev_dbg(xdev->dev, "parsing node %pOF\n", node);
+ dev_dbg(xdev->dev, "parsing node %p\n", fwnode);
while (1) {
- ep = of_graph_get_next_endpoint(node, ep);
+ struct v4l2_async_subdev *asd;
+
+ ep = fwnode_graph_get_next_endpoint(fwnode, ep);
if (ep == NULL)
break;
- dev_dbg(xdev->dev, "handling endpoint %pOF\n", ep);
+ dev_dbg(xdev->dev, "handling endpoint %p\n", ep);
- remote = of_graph_get_remote_port_parent(ep);
+ remote = fwnode_graph_get_remote_port_parent(ep);
if (remote == NULL) {
ret = -EINVAL;
- break;
+ goto err_notifier_cleanup;
}
+ fwnode_handle_put(ep);
+
/* Skip entities that we have already processed. */
- if (remote == xdev->dev->of_node ||
+ if (remote == of_fwnode_handle(xdev->dev->of_node) ||
xvip_graph_find_entity(xdev, remote)) {
- of_node_put(remote);
+ fwnode_handle_put(remote);
continue;
}
- entity = devm_kzalloc(xdev->dev, sizeof(*entity), GFP_KERNEL);
- if (entity == NULL) {
- of_node_put(remote);
- ret = -ENOMEM;
- break;
+ asd = v4l2_async_notifier_add_fwnode_subdev(
+ &xdev->notifier, remote,
+ sizeof(struct xvip_graph_entity));
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ fwnode_handle_put(remote);
+ goto err_notifier_cleanup;
}
-
- entity->node = remote;
- entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
- entity->asd.match.fwnode = of_fwnode_handle(remote);
- list_add_tail(&entity->list, &xdev->entities);
- xdev->num_subdevs++;
}
- of_node_put(ep);
+ return 0;
+
+err_notifier_cleanup:
+ v4l2_async_notifier_cleanup(&xdev->notifier);
+ fwnode_handle_put(ep);
return ret;
}
static int xvip_graph_parse(struct xvip_composite_device *xdev)
{
struct xvip_graph_entity *entity;
+ struct v4l2_async_subdev *asd;
int ret;
/*
@@ -407,14 +415,17 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev)
* loop will handle entities added at the end of the list while walking
* the links.
*/
- ret = xvip_graph_parse_one(xdev, xdev->dev->of_node);
+ ret = xvip_graph_parse_one(xdev, of_fwnode_handle(xdev->dev->of_node));
if (ret < 0)
return 0;
- list_for_each_entry(entity, &xdev->entities, list) {
- ret = xvip_graph_parse_one(xdev, entity->node);
- if (ret < 0)
+ list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
+ entity = to_xvip_entity(asd);
+ ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
+ if (ret < 0) {
+ v4l2_async_notifier_cleanup(&xdev->notifier);
break;
+ }
}
return ret;
@@ -485,17 +496,11 @@ static int xvip_graph_dma_init(struct xvip_composite_device *xdev)
static void xvip_graph_cleanup(struct xvip_composite_device *xdev)
{
- struct xvip_graph_entity *entityp;
- struct xvip_graph_entity *entity;
struct xvip_dma *dmap;
struct xvip_dma *dma;
v4l2_async_notifier_unregister(&xdev->notifier);
-
- list_for_each_entry_safe(entity, entityp, &xdev->entities, list) {
- of_node_put(entity->node);
- list_del(&entity->list);
- }
+ v4l2_async_notifier_cleanup(&xdev->notifier);
list_for_each_entry_safe(dma, dmap, &xdev->dmas, list) {
xvip_dma_cleanup(dma);
@@ -505,10 +510,6 @@ static void xvip_graph_cleanup(struct xvip_composite_device *xdev)
static int xvip_graph_init(struct xvip_composite_device *xdev)
{
- struct xvip_graph_entity *entity;
- struct v4l2_async_subdev **subdevs = NULL;
- unsigned int num_subdevs;
- unsigned int i;
int ret;
/* Init the DMA channels. */
@@ -525,26 +526,12 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
goto done;
}
- if (!xdev->num_subdevs) {
+ if (list_empty(&xdev->notifier.asd_list)) {
dev_err(xdev->dev, "no subdev found in graph\n");
goto done;
}
/* Register the subdevices notifier. */
- num_subdevs = xdev->num_subdevs;
- subdevs = devm_kcalloc(xdev->dev, num_subdevs, sizeof(*subdevs),
- GFP_KERNEL);
- if (subdevs == NULL) {
- ret = -ENOMEM;
- goto done;
- }
-
- i = 0;
- list_for_each_entry(entity, &xdev->entities, list)
- subdevs[i++] = &entity->asd;
-
- xdev->notifier.subdevs = subdevs;
- xdev->notifier.num_subdevs = num_subdevs;
xdev->notifier.ops = &xvip_graph_notify_ops;
ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier);
@@ -578,7 +565,7 @@ static int xvip_composite_v4l2_init(struct xvip_composite_device *xdev)
int ret;
xdev->media_dev.dev = xdev->dev;
- strlcpy(xdev->media_dev.model, "Xilinx Video Composite Device",
+ strscpy(xdev->media_dev.model, "Xilinx Video Composite Device",
sizeof(xdev->media_dev.model));
xdev->media_dev.hw_revision = 0;
@@ -610,8 +597,8 @@ static int xvip_composite_probe(struct platform_device *pdev)
return -ENOMEM;
xdev->dev = &pdev->dev;
- INIT_LIST_HEAD(&xdev->entities);
INIT_LIST_HEAD(&xdev->dmas);
+ v4l2_async_notifier_init(&xdev->notifier);
ret = xvip_composite_v4l2_init(xdev);
if (ret < 0)
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.h b/drivers/media/platform/xilinx/xilinx-vipp.h
index faf6b6e80b3b..7e9c4cff33b4 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.h
+++ b/drivers/media/platform/xilinx/xilinx-vipp.h
@@ -28,8 +28,6 @@
* @media_dev: media device
* @dev: (OF) device
* @notifier: V4L2 asynchronous subdevs notifier
- * @entities: entities in the graph as a list of xvip_graph_entity
- * @num_subdevs: number of subdevs in the pipeline
* @dmas: list of DMA channels at the pipeline output and input
* @v4l2_caps: V4L2 capabilities of the whole device (see VIDIOC_QUERYCAP)
*/
@@ -39,8 +37,6 @@ struct xvip_composite_device {
struct device *dev;
struct v4l2_async_notifier notifier;
- struct list_head entities;
- unsigned int num_subdevs;
struct list_head dmas;
u32 v4l2_caps;
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 8521bb2825e8..c9d51a5f2838 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -174,8 +174,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct dsbr100_device *radio = video_drvdata(file);
- strlcpy(v->driver, "dsbr100", sizeof(v->driver));
- strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
+ strscpy(v->driver, "dsbr100", sizeof(v->driver));
+ strscpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -191,7 +191,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
return -EINVAL;
dsbr100_getstat(radio);
- strcpy(v->name, "FM");
+ strscpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
v->rangelow = FREQ_MIN * FREQ_MUL;
v->rangehigh = FREQ_MAX * FREQ_MUL;
@@ -379,7 +379,8 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
goto err_reg_ctrl;
}
mutex_init(&radio->v4l2_lock);
- strlcpy(radio->videodev.name, v4l2_dev->name, sizeof(radio->videodev.name));
+ strscpy(radio->videodev.name, v4l2_dev->name,
+ sizeof(radio->videodev.name));
radio->videodev.v4l2_dev = v4l2_dev;
radio->videodev.fops = &usb_dsbr100_fops;
radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops;
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 5b82e63885cd..d12e07e32546 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -353,9 +353,9 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
{
- strlcpy(v->driver, "ADS Cadet", sizeof(v->driver));
- strlcpy(v->card, "ADS Cadet", sizeof(v->card));
- strlcpy(v->bus_info, "ISA:radio-cadet", sizeof(v->bus_info));
+ strscpy(v->driver, "ADS Cadet", sizeof(v->driver));
+ strscpy(v->card, "ADS Cadet", sizeof(v->card));
+ strscpy(v->bus_info, "ISA:radio-cadet", sizeof(v->bus_info));
v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO |
V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -370,7 +370,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (v->index)
return -EINVAL;
v->type = V4L2_TUNER_RADIO;
- strlcpy(v->name, "Radio", sizeof(v->name));
+ strscpy(v->name, "Radio", sizeof(v->name));
v->capability = bands[0].capability | bands[1].capability;
v->rangelow = bands[0].rangelow; /* 520 kHz (start of AM band) */
v->rangehigh = bands[1].rangehigh; /* 108.0 MHz (end of FM band) */
@@ -595,7 +595,7 @@ static int __init cadet_init(void)
struct v4l2_ctrl_handler *hdl;
int res = -ENODEV;
- strlcpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name));
+ strscpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name));
mutex_init(&dev->lock);
/* If a probe was requested then probe ISAPnP first (safest) */
@@ -639,7 +639,7 @@ static int __init cadet_init(void)
dev->is_fm_band = true;
dev->curfreq = bands[dev->is_fm_band].rangelow;
cadet_setfreq(dev, dev->curfreq);
- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+ strscpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
dev->vdev.v4l2_dev = v4l2_dev;
dev->vdev.fops = &cadet_fops;
dev->vdev.ioctl_ops = &cadet_ioctl_ops;
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index 7312e469e850..551de8a45b95 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -42,8 +42,8 @@ static int radio_isa_querycap(struct file *file, void *priv,
{
struct radio_isa_card *isa = video_drvdata(file);
- strlcpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver));
- strlcpy(v->card, isa->drv->card, sizeof(v->card));
+ strscpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver));
+ strscpy(v->card, isa->drv->card, sizeof(v->card));
snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
@@ -60,7 +60,7 @@ static int radio_isa_g_tuner(struct file *file, void *priv,
if (v->index > 0)
return -EINVAL;
- strlcpy(v->name, "FM", sizeof(v->name));
+ strscpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
v->rangelow = FREQ_LOW;
v->rangehigh = FREQ_HIGH;
@@ -198,7 +198,7 @@ static struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv,
dev_set_drvdata(pdev, isa);
isa->drv = drv;
v4l2_dev = &isa->v4l2_dev;
- strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name));
+ strscpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name));
return isa;
}
@@ -243,7 +243,7 @@ static int radio_isa_common_probe(struct radio_isa_card *isa,
mutex_init(&isa->lock);
isa->vdev.lock = &isa->lock;
- strlcpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name));
+ strscpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name));
isa->vdev.v4l2_dev = v4l2_dev;
isa->vdev.fops = &radio_isa_fops;
isa->vdev.ioctl_ops = &radio_isa_ioctl_ops;
diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c
index f2ea8bc5f5ee..e9484b013073 100644
--- a/drivers/media/radio/radio-keene.c
+++ b/drivers/media/radio/radio-keene.c
@@ -174,8 +174,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct keene_device *radio = video_drvdata(file);
- strlcpy(v->driver, "radio-keene", sizeof(v->driver));
- strlcpy(v->card, "Keene FM Transmitter", sizeof(v->card));
+ strscpy(v->driver, "radio-keene", sizeof(v->driver));
+ strscpy(v->card, "Keene FM Transmitter", sizeof(v->card));
usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_MODULATOR;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -190,7 +190,7 @@ static int vidioc_g_modulator(struct file *file, void *priv,
if (v->index > 0)
return -EINVAL;
- strlcpy(v->name, "FM", sizeof(v->name));
+ strscpy(v->name, "FM", sizeof(v->name));
v->rangelow = FREQ_MIN * FREQ_MUL;
v->rangehigh = FREQ_MAX * FREQ_MUL;
v->txsubchans = radio->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
@@ -362,7 +362,7 @@ static int usb_keene_probe(struct usb_interface *intf,
radio->v4l2_dev.ctrl_handler = hdl;
radio->v4l2_dev.release = usb_keene_video_device_release;
- strlcpy(radio->vdev.name, radio->v4l2_dev.name,
+ strscpy(radio->vdev.name, radio->v4l2_dev.name,
sizeof(radio->vdev.name));
radio->vdev.v4l2_dev = &radio->v4l2_dev;
radio->vdev.fops = &usb_keene_fops;
diff --git a/drivers/media/radio/radio-ma901.c b/drivers/media/radio/radio-ma901.c
index fdc481257efd..5cb153727841 100644
--- a/drivers/media/radio/radio-ma901.c
+++ b/drivers/media/radio/radio-ma901.c
@@ -197,8 +197,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct ma901radio_device *radio = video_drvdata(file);
- strlcpy(v->driver, "radio-ma901", sizeof(v->driver));
- strlcpy(v->card, "Masterkit MA901 USB FM Radio", sizeof(v->card));
+ strscpy(v->driver, "radio-ma901", sizeof(v->driver));
+ strscpy(v->card, "Masterkit MA901 USB FM Radio", sizeof(v->card));
usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -222,7 +222,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
* retval = ma901radio_get_stat(radio, &is_stereo, &v->signal);
*/
- strcpy(v->name, "FM");
+ strscpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
v->rangelow = FREQ_MIN * FREQ_MUL;
v->rangehigh = FREQ_MAX * FREQ_MUL;
@@ -400,7 +400,7 @@ static int usb_ma901radio_probe(struct usb_interface *intf,
radio->v4l2_dev.ctrl_handler = &radio->hdl;
radio->v4l2_dev.release = usb_ma901radio_release;
- strlcpy(radio->vdev.name, radio->v4l2_dev.name,
+ strscpy(radio->vdev.name, radio->v4l2_dev.name,
sizeof(radio->vdev.name));
radio->vdev.v4l2_dev = &radio->v4l2_dev;
radio->vdev.fops = &usb_ma901radio_fops;
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index e4e758739246..1b97ad2ce7d0 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -142,7 +142,7 @@ static int maxiradio_probe(struct pci_dev *pdev,
dev->tea.cannot_read_data = true;
dev->tea.v4l2_dev = v4l2_dev;
dev->tea.radio_nr = radio_nr;
- strlcpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card));
+ strscpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card));
snprintf(dev->tea.bus_info, sizeof(dev->tea.bus_info),
"PCI:%s", pci_name(pdev));
diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c
index 7b35e633118d..b626567b75c5 100644
--- a/drivers/media/radio/radio-miropcm20.c
+++ b/drivers/media/radio/radio-miropcm20.c
@@ -200,8 +200,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct pcm20 *dev = video_drvdata(file);
- strlcpy(v->driver, "Miro PCM20", sizeof(v->driver));
- strlcpy(v->card, "Miro PCM20", sizeof(v->card));
+ strscpy(v->driver, "Miro PCM20", sizeof(v->driver));
+ strscpy(v->card, "Miro PCM20", sizeof(v->card));
snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", dev->v4l2_dev.name);
v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -231,7 +231,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (v->index)
return -EINVAL;
- strlcpy(v->name, "FM", sizeof(v->name));
+ strscpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
v->rangelow = 87*16000;
v->rangehigh = 108*16000;
@@ -443,7 +443,7 @@ static int __init pcm20_init(void)
"you must load the snd-miro driver first!\n");
return -ENODEV;
}
- strlcpy(v4l2_dev->name, "radio-miropcm20", sizeof(v4l2_dev->name));
+ strscpy(v4l2_dev->name, "radio-miropcm20", sizeof(v4l2_dev->name));
mutex_init(&dev->lock);
res = v4l2_device_register(NULL, v4l2_dev);
@@ -474,7 +474,7 @@ static int __init pcm20_init(void)
v4l2_err(v4l2_dev, "Could not register control\n");
goto err_hdl;
}
- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+ strscpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
dev->vdev.v4l2_dev = v4l2_dev;
dev->vdev.fops = &pcm20_fops;
dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index 0f292c6ba338..ab1324f68199 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -266,8 +266,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct amradio_device *radio = video_drvdata(file);
- strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
- strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
+ strscpy(v->driver, "radio-mr800", sizeof(v->driver));
+ strscpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER |
V4L2_CAP_HW_FREQ_SEEK;
@@ -291,7 +291,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (retval)
return retval;
- strcpy(v->name, "FM");
+ strscpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
v->rangelow = FREQ_MIN * FREQ_MUL;
v->rangehigh = FREQ_MAX * FREQ_MUL;
@@ -547,7 +547,7 @@ static int usb_amradio_probe(struct usb_interface *intf,
radio->v4l2_dev.ctrl_handler = &radio->hdl;
radio->v4l2_dev.release = usb_amradio_release;
- strlcpy(radio->vdev.name, radio->v4l2_dev.name,
+ strscpy(radio->vdev.name, radio->v4l2_dev.name,
sizeof(radio->vdev.name));
radio->vdev.v4l2_dev = &radio->v4l2_dev;
radio->vdev.fops = &usb_amradio_fops;
diff --git a/drivers/media/radio/radio-raremono.c b/drivers/media/radio/radio-raremono.c
index 9a5079d64c4a..5e782b3c2fa9 100644
--- a/drivers/media/radio/radio-raremono.c
+++ b/drivers/media/radio/radio-raremono.c
@@ -181,8 +181,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct raremono_device *radio = video_drvdata(file);
- strlcpy(v->driver, "radio-raremono", sizeof(v->driver));
- strlcpy(v->card, "Thanko's Raremono", sizeof(v->card));
+ strscpy(v->driver, "radio-raremono", sizeof(v->driver));
+ strscpy(v->card, "Thanko's Raremono", sizeof(v->card));
usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -212,7 +212,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (v->index > 0)
return -EINVAL;
- strlcpy(v->name, "AM/FM/SW", sizeof(v->name));
+ strscpy(v->name, "AM/FM/SW", sizeof(v->name));
v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = AM_FREQ_RANGE_LOW * 16;
@@ -338,7 +338,7 @@ static int usb_raremono_probe(struct usb_interface *intf,
mutex_init(&radio->lock);
- strlcpy(radio->vdev.name, radio->v4l2_dev.name,
+ strscpy(radio->vdev.name, radio->v4l2_dev.name,
sizeof(radio->vdev.name));
radio->vdev.v4l2_dev = &radio->v4l2_dev;
radio->vdev.fops = &usb_raremono_fops;
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 4f9b97edd9eb..a8fedc963614 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -129,9 +129,9 @@ static void fmi_set_freq(struct fmi *fmi)
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
{
- strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver));
- strlcpy(v->card, "SF16-FMI/FMP/FMD radio", sizeof(v->card));
- strlcpy(v->bus_info, "ISA:radio-sf16fmi", sizeof(v->bus_info));
+ strscpy(v->driver, "radio-sf16fmi", sizeof(v->driver));
+ strscpy(v->card, "SF16-FMI/FMP/FMD radio", sizeof(v->card));
+ strscpy(v->bus_info, "ISA:radio-sf16fmi", sizeof(v->bus_info));
v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
@@ -145,7 +145,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (v->index > 0)
return -EINVAL;
- strlcpy(v->name, "FM", sizeof(v->name));
+ strscpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
v->rangelow = RSF16_MINFREQ;
v->rangehigh = RSF16_MAXFREQ;
@@ -315,7 +315,7 @@ static int __init fmi_init(void)
return -ENODEV;
}
- strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name));
+ strscpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name));
fmi->io = io;
res = v4l2_device_register(NULL, v4l2_dev);
@@ -339,7 +339,7 @@ static int __init fmi_init(void)
return res;
}
- strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name));
+ strscpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name));
fmi->vdev.v4l2_dev = v4l2_dev;
fmi->vdev.fops = &fmi_fops;
fmi->vdev.ioctl_ops = &fmi_ioctl_ops;
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 7b07d42a9909..ca8a1c263eac 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -213,8 +213,8 @@ static int fmr2_probe(struct fmr2 *fmr2, struct device *pdev, int io)
if (io == fmr2_cards[i]->io)
return -EBUSY;
- strlcpy(fmr2->v4l2_dev.name, "radio-sf16fmr2",
- sizeof(fmr2->v4l2_dev.name)),
+ strscpy(fmr2->v4l2_dev.name, "radio-sf16fmr2",
+ sizeof(fmr2->v4l2_dev.name)),
fmr2->io = io;
if (!request_region(fmr2->io, 2, fmr2->v4l2_dev.name)) {
@@ -234,7 +234,7 @@ static int fmr2_probe(struct fmr2 *fmr2, struct device *pdev, int io)
fmr2->tea.radio_nr = radio_nr[num_fmr2_cards];
fmr2->tea.ops = &fmr2_tea_ops;
fmr2->tea.ext_init = fmr2_tea_ext_init;
- strlcpy(fmr2->tea.card, card_name, sizeof(fmr2->tea.card));
+ strscpy(fmr2->tea.card, card_name, sizeof(fmr2->tea.card));
snprintf(fmr2->tea.bus_info, sizeof(fmr2->tea.bus_info), "%s:%s",
fmr2->is_fmd2 ? "PnP" : "ISA", dev_name(pdev));
diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c
index 22f3466af2b1..8230da828d0e 100644
--- a/drivers/media/radio/radio-shark.c
+++ b/drivers/media/radio/radio-shark.c
@@ -345,7 +345,7 @@ static int usb_shark_probe(struct usb_interface *intf,
shark->tea.ops = &shark_tea_ops;
shark->tea.cannot_mute = true;
shark->tea.has_am = true;
- strlcpy(shark->tea.card, "Griffin radioSHARK",
+ strscpy(shark->tea.card, "Griffin radioSHARK",
sizeof(shark->tea.card));
usb_make_path(shark->usbdev, shark->tea.bus_info,
sizeof(shark->tea.bus_info));
diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c
index 4d1a4b3d669c..d150f12382c6 100644
--- a/drivers/media/radio/radio-shark2.c
+++ b/drivers/media/radio/radio-shark2.c
@@ -310,7 +310,7 @@ static int usb_shark_probe(struct usb_interface *intf,
shark->tea.ops = &shark_tea_ops;
shark->tea.has_am = true;
shark->tea.write_before_read = true;
- strlcpy(shark->tea.card, "Griffin radioSHARK2",
+ strscpy(shark->tea.card, "Griffin radioSHARK2",
sizeof(shark->tea.card));
usb_make_path(shark->usbdev, shark->tea.bus_info,
sizeof(shark->tea.bus_info));
diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c
index b52e678c6901..269971145f88 100644
--- a/drivers/media/radio/radio-si476x.c
+++ b/drivers/media/radio/radio-si476x.c
@@ -340,9 +340,9 @@ static int si476x_radio_querycap(struct file *file, void *priv,
{
struct si476x_radio *radio = video_drvdata(file);
- strlcpy(capability->driver, radio->v4l2dev.name,
+ strscpy(capability->driver, radio->v4l2dev.name,
sizeof(capability->driver));
- strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
+ strscpy(capability->card, DRIVER_CARD, sizeof(capability->card));
snprintf(capability->bus_info, sizeof(capability->bus_info),
"platform:%s", radio->v4l2dev.name);
@@ -428,15 +428,15 @@ static int si476x_radio_g_tuner(struct file *file, void *priv,
si476x_core_lock(radio->core);
if (si476x_core_is_a_secondary_tuner(radio->core)) {
- strlcpy(tuner->name, "FM (secondary)", sizeof(tuner->name));
+ strscpy(tuner->name, "FM (secondary)", sizeof(tuner->name));
tuner->rxsubchans = 0;
tuner->rangelow = si476x_bands[SI476X_BAND_FM].rangelow;
} else if (si476x_core_has_am(radio->core)) {
if (si476x_core_is_a_primary_tuner(radio->core))
- strlcpy(tuner->name, "AM/FM (primary)",
+ strscpy(tuner->name, "AM/FM (primary)",
sizeof(tuner->name));
else
- strlcpy(tuner->name, "AM/FM", sizeof(tuner->name));
+ strscpy(tuner->name, "AM/FM", sizeof(tuner->name));
tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO
| V4L2_TUNER_SUB_RDS;
@@ -446,7 +446,7 @@ static int si476x_radio_g_tuner(struct file *file, void *priv,
tuner->rangelow = si476x_bands[SI476X_BAND_AM].rangelow;
} else {
- strlcpy(tuner->name, "FM", sizeof(tuner->name));
+ strscpy(tuner->name, "FM", sizeof(tuner->name));
tuner->rxsubchans = V4L2_TUNER_SUB_RDS;
tuner->capability |= V4L2_TUNER_CAP_RDS
| V4L2_TUNER_CAP_RDS_BLOCK_IO
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index afb763256fd6..6632be648cea 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -287,8 +287,8 @@ static int vidioc_querycap(struct file *file, void *priv,
struct tea5764_device *radio = video_drvdata(file);
struct video_device *dev = &radio->vdev;
- strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver));
- strlcpy(v->card, dev->name, sizeof(v->card));
+ strscpy(v->driver, dev->dev.driver->name, sizeof(v->driver));
+ strscpy(v->card, dev->name, sizeof(v->card));
snprintf(v->bus_info, sizeof(v->bus_info),
"I2C:%s", dev_name(&dev->dev));
v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
@@ -305,7 +305,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (v->index > 0)
return -EINVAL;
- strlcpy(v->name, "FM", sizeof(v->name));
+ strscpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
tea5764_i2c_read(radio);
v->rangelow = FREQ_MIN * FREQ_MUL;
diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c
index 04ed1a5d1177..61f751cf1aa4 100644
--- a/drivers/media/radio/radio-tea5777.c
+++ b/drivers/media/radio/radio-tea5777.c
@@ -266,10 +266,10 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct radio_tea5777 *tea = video_drvdata(file);
- strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
- strlcpy(v->card, tea->card, sizeof(v->card));
+ strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
+ strscpy(v->card, tea->card, sizeof(v->card));
strlcat(v->card, " TEA5777", sizeof(v->card));
- strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
+ strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
v->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -304,9 +304,9 @@ static int vidioc_g_tuner(struct file *file, void *priv,
memset(v, 0, sizeof(*v));
if (tea->has_am)
- strlcpy(v->name, "AM/FM", sizeof(v->name));
+ strscpy(v->name, "AM/FM", sizeof(v->name));
else
- strlcpy(v->name, "FM", sizeof(v->name));
+ strscpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_FREQ_BANDS |
@@ -560,7 +560,7 @@ int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner)
tea->vd = tea575x_radio;
video_set_drvdata(&tea->vd, tea);
mutex_init(&tea->mutex);
- strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name));
+ strscpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name));
tea->vd.lock = &tea->mutex;
tea->vd.v4l2_dev = tea->v4l2_dev;
tea->fops = tea575x_fops;
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index fc4d9a73ab17..0eda863124e9 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -39,8 +39,8 @@ struct timbradio {
static int timbradio_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
{
- strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver));
- strlcpy(v->card, "Timberdale Radio", sizeof(v->card));
+ strscpy(v->driver, DRIVER_NAME, sizeof(v->driver));
+ strscpy(v->card, "Timberdale Radio", sizeof(v->card));
snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME);
v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -115,7 +115,7 @@ static int timbradio_probe(struct platform_device *pdev)
tr->pdata = *pdata;
mutex_init(&tr->lock);
- strlcpy(tr->video_dev.name, "Timberdale Radio",
+ strscpy(tr->video_dev.name, "Timberdale Radio",
sizeof(tr->video_dev.name));
tr->video_dev.fops = &timbradio_fops;
tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;
@@ -123,7 +123,7 @@ static int timbradio_probe(struct platform_device *pdev)
tr->video_dev.minor = -1;
tr->video_dev.lock = &tr->lock;
- strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
+ strscpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
err = v4l2_device_register(NULL, &tr->v4l2_dev);
if (err)
goto err;
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index 11aa94f189cb..b95704f3cb8b 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -1286,11 +1286,11 @@ static int wl1273_fm_vidioc_querycap(struct file *file, void *priv,
dev_dbg(radio->dev, "%s\n", __func__);
- strlcpy(capability->driver, WL1273_FM_DRIVER_NAME,
+ strscpy(capability->driver, WL1273_FM_DRIVER_NAME,
sizeof(capability->driver));
- strlcpy(capability->card, "Texas Instruments Wl1273 FM Radio",
+ strscpy(capability->card, "Texas Instruments Wl1273 FM Radio",
sizeof(capability->card));
- strlcpy(capability->bus_info, radio->bus_type,
+ strscpy(capability->bus_info, radio->bus_type,
sizeof(capability->bus_info));
capability->device_caps = V4L2_CAP_HW_FREQ_SEEK |
@@ -1488,7 +1488,7 @@ static int wl1273_fm_vidioc_g_audio(struct file *file, void *priv,
if (audio->index > 1)
return -EINVAL;
- strlcpy(audio->name, "Radio", sizeof(audio->name));
+ strscpy(audio->name, "Radio", sizeof(audio->name));
audio->capability = V4L2_AUDCAP_STEREO;
return 0;
@@ -1523,7 +1523,7 @@ static int wl1273_fm_vidioc_g_tuner(struct file *file, void *priv,
if (tuner->index > 0)
return -EINVAL;
- strlcpy(tuner->name, WL1273_FM_DRIVER_NAME, sizeof(tuner->name));
+ strscpy(tuner->name, WL1273_FM_DRIVER_NAME, sizeof(tuner->name));
tuner->type = V4L2_TUNER_RADIO;
tuner->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW);
@@ -1781,7 +1781,7 @@ static int wl1273_fm_vidioc_g_modulator(struct file *file, void *priv,
dev_dbg(radio->dev, "%s\n", __func__);
- strlcpy(modulator->name, WL1273_FM_DRIVER_NAME,
+ strscpy(modulator->name, WL1273_FM_DRIVER_NAME,
sizeof(modulator->name));
modulator->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW);
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c
index c40e1753f34b..1d7ab5462c77 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -622,7 +622,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
}
/* driver constants */
- strcpy(tuner->name, "FM");
+ strscpy(tuner->name, "FM", sizeof(tuner->name));
tuner->type = V4L2_TUNER_RADIO;
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO |
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c
index e3b3ecd14a4d..9751ea1d80be 100644
--- a/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -229,8 +229,8 @@ static int si470x_fops_release(struct file *file)
static int si470x_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *capability)
{
- strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
- strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
+ strscpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
+ strscpy(capability->card, DRIVER_CARD, sizeof(capability->card));
capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE |
V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c
index 313a95f195a2..91d6ef5579f7 100644
--- a/drivers/media/radio/si470x/radio-si470x-usb.c
+++ b/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -519,8 +519,8 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
{
struct si470x_device *radio = video_drvdata(file);
- strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
- strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
+ strscpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
+ strscpy(capability->card, DRIVER_CARD, sizeof(capability->card));
usb_make_path(radio->usbdev, capability->bus_info,
sizeof(capability->bus_info));
capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE |
diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c
index 27339ec495f6..733fcf3933e4 100644
--- a/drivers/media/radio/si4713/radio-platform-si4713.c
+++ b/drivers/media/radio/si4713/radio-platform-si4713.c
@@ -67,10 +67,10 @@ static const struct v4l2_file_operations radio_si4713_fops = {
static int radio_si4713_querycap(struct file *file, void *priv,
struct v4l2_capability *capability)
{
- strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
- strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
+ strscpy(capability->driver, "radio-si4713", sizeof(capability->driver));
+ strscpy(capability->card, "Silicon Labs Si4713 Modulator",
sizeof(capability->card));
- strlcpy(capability->bus_info, "platform:radio-si4713",
+ strscpy(capability->bus_info, "platform:radio-si4713",
sizeof(capability->bus_info));
capability->device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;
diff --git a/drivers/media/radio/si4713/radio-usb-si4713.c b/drivers/media/radio/si4713/radio-usb-si4713.c
index 1ebbf0217142..23065ecce979 100644
--- a/drivers/media/radio/si4713/radio-usb-si4713.c
+++ b/drivers/media/radio/si4713/radio-usb-si4713.c
@@ -67,8 +67,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct si4713_usb_device *radio = video_drvdata(file);
- strlcpy(v->driver, "radio-usb-si4713", sizeof(v->driver));
- strlcpy(v->card, "Si4713 FM Transmitter", sizeof(v->card));
+ strscpy(v->driver, "radio-usb-si4713", sizeof(v->driver));
+ strscpy(v->card, "Si4713 FM Transmitter", sizeof(v->card));
usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
v->device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -467,7 +467,7 @@ static int usb_si4713_probe(struct usb_interface *intf,
radio->vdev.ctrl_handler = sd->ctrl_handler;
radio->v4l2_dev.release = usb_si4713_video_device_release;
- strlcpy(radio->vdev.name, radio->v4l2_dev.name,
+ strscpy(radio->vdev.name, radio->v4l2_dev.name,
sizeof(radio->vdev.name));
radio->vdev.v4l2_dev = &radio->v4l2_dev;
radio->vdev.fops = &usb_si4713_fops;
diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c
index 7412fe1b10c6..f89f83e04741 100644
--- a/drivers/media/radio/tea575x.c
+++ b/drivers/media/radio/tea575x.c
@@ -233,10 +233,10 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct snd_tea575x *tea = video_drvdata(file);
- strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
- strlcpy(v->card, tea->card, sizeof(v->card));
+ strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
+ strscpy(v->card, tea->card, sizeof(v->card));
strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card));
- strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
+ strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
if (!tea->cannot_read_data)
v->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
@@ -296,7 +296,7 @@ int snd_tea575x_g_tuner(struct snd_tea575x *tea, struct v4l2_tuner *v)
snd_tea575x_enum_freq_bands(tea, &band_fm);
memset(v, 0, sizeof(*v));
- strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name));
+ strscpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
v->capability = band_fm.capability;
v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow;
@@ -537,7 +537,7 @@ int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner)
tea->vd = tea575x_radio;
video_set_drvdata(&tea->vd, tea);
mutex_init(&tea->mutex);
- strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name));
+ strscpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name));
tea->vd.lock = &tea->mutex;
tea->vd.v4l2_dev = tea->v4l2_dev;
tea->fops = tea575x_fops;
diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c
index ed210f4c476a..a76ff2978dfb 100644
--- a/drivers/media/radio/tef6862.c
+++ b/drivers/media/radio/tef6862.c
@@ -79,7 +79,7 @@ static int tef6862_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
return -EINVAL;
/* only support FM for now */
- strlcpy(v->name, "FM", sizeof(v->name));
+ strscpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
v->rangelow = TEF6862_LO_FREQ;
v->rangehigh = TEF6862_HI_FREQ;
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index dccdf6558e6a..e25fd4d4d280 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -190,9 +190,9 @@ release_unlock:
static int fm_v4l2_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *capability)
{
- strlcpy(capability->driver, FM_DRV_NAME, sizeof(capability->driver));
- strlcpy(capability->card, FM_DRV_CARD_SHORT_NAME,
- sizeof(capability->card));
+ strscpy(capability->driver, FM_DRV_NAME, sizeof(capability->driver));
+ strscpy(capability->card, FM_DRV_CARD_SHORT_NAME,
+ sizeof(capability->card));
sprintf(capability->bus_info, "UART");
capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
V4L2_CAP_RADIO | V4L2_CAP_MODULATOR |
@@ -249,7 +249,7 @@ static int fm_v4l2_vidioc_g_audio(struct file *file, void *priv,
struct v4l2_audio *audio)
{
memset(audio, 0, sizeof(*audio));
- strcpy(audio->name, "Radio");
+ strscpy(audio->name, "Radio", sizeof(audio->name));
audio->capability = V4L2_AUDCAP_STEREO;
return 0;
@@ -293,7 +293,7 @@ static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
if (ret != 0)
return ret;
- strcpy(tuner->name, "FM");
+ strscpy(tuner->name, "FM", sizeof(tuner->name));
tuner->type = V4L2_TUNER_RADIO;
/* Store rangelow and rangehigh freq in unit of 62.5 Hz */
tuner->rangelow = bottom_freq * 16;
@@ -531,7 +531,8 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
struct v4l2_ctrl *ctrl;
int ret;
- strlcpy(fmdev->v4l2_dev.name, FM_DRV_NAME, sizeof(fmdev->v4l2_dev.name));
+ strscpy(fmdev->v4l2_dev.name, FM_DRV_NAME,
+ sizeof(fmdev->v4l2_dev.name));
ret = v4l2_device_register(NULL, &fmdev->v4l2_dev);
if (ret < 0)
return ret;
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 8e82610ffaad..265e91a2a70d 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -862,7 +862,7 @@ static int ati_remote_probe(struct usb_interface *interface,
ati_remote->interface = interface;
usb_make_path(udev, ati_remote->rc_phys, sizeof(ati_remote->rc_phys));
- strlcpy(ati_remote->mouse_phys, ati_remote->rc_phys,
+ strscpy(ati_remote->mouse_phys, ati_remote->rc_phys,
sizeof(ati_remote->mouse_phys));
strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys));
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index 71b8c9bbf6c4..dd2fd307ef85 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -326,8 +326,6 @@ static int ene_rx_get_sample_reg(struct ene_device *dev)
/* Sense current received carrier */
static void ene_rx_sense_carrier(struct ene_device *dev)
{
- DEFINE_IR_RAW_EVENT(ev);
-
int carrier, duty_cycle;
int period = ene_read_reg(dev, ENE_CIRCAR_PRD);
int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD);
@@ -348,9 +346,11 @@ static void ene_rx_sense_carrier(struct ene_device *dev)
dbg("RX: sensed carrier = %d Hz, duty cycle %d%%",
carrier, duty_cycle);
if (dev->carrier_detect_enabled) {
- ev.carrier_report = true;
- ev.carrier = carrier;
- ev.duty_cycle = duty_cycle;
+ struct ir_raw_event ev = {
+ .carrier_report = true,
+ .carrier = carrier,
+ .duty_cycle = duty_cycle
+ };
ir_raw_event_store(dev->rdev, &ev);
}
}
@@ -733,7 +733,7 @@ static irqreturn_t ene_isr(int irq, void *data)
unsigned long flags;
irqreturn_t retval = IRQ_NONE;
struct ene_device *dev = (struct ene_device *)data;
- DEFINE_IR_RAW_EVENT(ev);
+ struct ir_raw_event ev = {};
spin_lock_irqsave(&dev->hw_lock, flags);
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index f2639d0c2fca..601944666b71 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -282,7 +282,7 @@ static int fintek_cmdsize(u8 cmd, u8 subcmd)
/* process ir data stored in driver buffer */
static void fintek_process_rx_ir_data(struct fintek_dev *fintek)
{
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
u8 sample;
bool event = false;
int i;
@@ -314,7 +314,6 @@ static void fintek_process_rx_ir_data(struct fintek_dev *fintek)
break;
case PARSE_IRDATA:
fintek->rem--;
- init_ir_raw_event(&rawir);
rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
rawir.duration = US_TO_NS((sample & BUF_SAMPLE_MASK)
* CIR_SAMPLE_PERIOD);
diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c
index f563ddd7f739..ba3f95a97f14 100644
--- a/drivers/media/rc/igorplugusb.c
+++ b/drivers/media/rc/igorplugusb.c
@@ -56,7 +56,7 @@ static void igorplugusb_cmd(struct igorplugusb *ir, int cmd);
static void igorplugusb_irdata(struct igorplugusb *ir, unsigned len)
{
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
unsigned i, start, overflow;
dev_dbg(ir->dev, "irdata: %*ph (len=%u)", len, ir->buf_in, len);
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index 7daac8bab83b..fbacb13b614b 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -129,12 +129,10 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
break;
}
} else if (len >= 7) {
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
unsigned i;
bool event = false;
- init_ir_raw_event(&rawir);
-
for (i = 0; i < 7; i++) {
if (ir->buf_in[i] == 0x80) {
rawir.pulse = false;
diff --git a/drivers/media/rc/imon_raw.c b/drivers/media/rc/imon_raw.c
index 32709f96de14..7796098d9c30 100644
--- a/drivers/media/rc/imon_raw.c
+++ b/drivers/media/rc/imon_raw.c
@@ -28,7 +28,7 @@ static inline int is_bit_set(const u8 *buf, int bit)
static void imon_ir_data(struct imon *imon)
{
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
int offset = 0, size = 5 * 8;
int bit;
diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
index 700ab4c563d0..abc4d6c1b323 100644
--- a/drivers/media/rc/ir-hix5hd2.c
+++ b/drivers/media/rc/ir-hix5hd2.c
@@ -175,7 +175,7 @@ static irqreturn_t hix5hd2_ir_rx_interrupt(int irq, void *data)
}
if ((irq_sr & INTMS_SYMBRCV) || (irq_sr & INTMS_TIMEOUT)) {
- DEFINE_IR_RAW_EVENT(ev);
+ struct ir_raw_event ev = {};
symb_num = readl_relaxed(priv->base + IR_DATAH);
for (i = 0; i < symb_num; i++) {
diff --git a/drivers/media/rc/ir-imon-decoder.c b/drivers/media/rc/ir-imon-decoder.c
index 67c1b0c15aae..a0efe2605393 100644
--- a/drivers/media/rc/ir-imon-decoder.c
+++ b/drivers/media/rc/ir-imon-decoder.c
@@ -70,24 +70,13 @@ static void ir_imon_decode_scancode(struct rc_dev *dev)
}
if (!imon->stick_keyboard) {
- struct lirc_scancode lsc = {
- .scancode = imon->bits,
- .rc_proto = RC_PROTO_IMON,
- };
+ input_report_rel(dev->input_dev, REL_X, rel_x);
+ input_report_rel(dev->input_dev, REL_Y, rel_y);
- ir_lirc_scancode_event(dev, &lsc);
-
- input_event(imon->idev, EV_MSC, MSC_SCAN, imon->bits);
-
- input_report_rel(imon->idev, REL_X, rel_x);
- input_report_rel(imon->idev, REL_Y, rel_y);
-
- input_report_key(imon->idev, BTN_LEFT,
+ input_report_key(dev->input_dev, BTN_LEFT,
(imon->bits & 0x00010000) != 0);
- input_report_key(imon->idev, BTN_RIGHT,
+ input_report_key(dev->input_dev, BTN_RIGHT,
(imon->bits & 0x00040000) != 0);
- input_sync(imon->idev);
- return;
}
}
@@ -243,62 +232,19 @@ static int ir_imon_encode(enum rc_proto protocol, u32 scancode,
static int ir_imon_register(struct rc_dev *dev)
{
- struct input_dev *idev;
struct imon_dec *imon = &dev->raw->imon;
- int ret;
-
- idev = input_allocate_device();
- if (!idev)
- return -ENOMEM;
-
- snprintf(imon->name, sizeof(imon->name),
- "iMON PAD Stick (%s)", dev->device_name);
- idev->name = imon->name;
- idev->phys = dev->input_phys;
-
- /* Mouse bits */
- set_bit(EV_REL, idev->evbit);
- set_bit(EV_KEY, idev->evbit);
- set_bit(REL_X, idev->relbit);
- set_bit(REL_Y, idev->relbit);
- set_bit(BTN_LEFT, idev->keybit);
- set_bit(BTN_RIGHT, idev->keybit);
-
- /* Report scancodes too */
- set_bit(EV_MSC, idev->evbit);
- set_bit(MSC_SCAN, idev->mscbit);
-
- input_set_drvdata(idev, imon);
-
- ret = input_register_device(idev);
- if (ret < 0) {
- input_free_device(idev);
- return -EIO;
- }
- imon->idev = idev;
imon->stick_keyboard = false;
return 0;
}
-static int ir_imon_unregister(struct rc_dev *dev)
-{
- struct imon_dec *imon = &dev->raw->imon;
-
- input_unregister_device(imon->idev);
- imon->idev = NULL;
-
- return 0;
-}
-
static struct ir_raw_handler imon_handler = {
.protocols = RC_PROTO_BIT_IMON,
.decode = ir_imon_decode,
.encode = ir_imon_encode,
.carrier = 38000,
.raw_register = ir_imon_register,
- .raw_unregister = ir_imon_unregister,
.min_timeout = IMON_UNIT * IMON_BITS * 2,
};
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 64ea42927669..67f1c179c713 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -129,13 +129,14 @@ static void mce_kbd_rx_timeout(struct timer_list *t)
if (time_is_before_eq_jiffies(raw->mce_kbd.rx_timeout.expires)) {
for (i = 0; i < 7; i++) {
maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
- input_report_key(raw->mce_kbd.idev, maskcode, 0);
+ input_report_key(raw->dev->input_dev, maskcode, 0);
}
for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
- input_report_key(raw->mce_kbd.idev, kbd_keycodes[i], 0);
+ input_report_key(raw->dev->input_dev, kbd_keycodes[i],
+ 0);
- input_sync(raw->mce_kbd.idev);
+ input_sync(raw->dev->input_dev);
}
spin_unlock_irqrestore(&raw->mce_kbd.keylock, flags);
}
@@ -154,7 +155,6 @@ static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
static void ir_mce_kbd_process_keyboard_data(struct rc_dev *dev, u32 scancode)
{
- struct mce_kbd_dec *data = &dev->raw->mce_kbd;
u8 keydata1 = (scancode >> 8) & 0xff;
u8 keydata2 = (scancode >> 16) & 0xff;
u8 shiftmask = scancode & 0xff;
@@ -170,23 +170,22 @@ static void ir_mce_kbd_process_keyboard_data(struct rc_dev *dev, u32 scancode)
keystate = 1;
else
keystate = 0;
- input_report_key(data->idev, maskcode, keystate);
+ input_report_key(dev->input_dev, maskcode, keystate);
}
if (keydata1)
- input_report_key(data->idev, kbd_keycodes[keydata1], 1);
+ input_report_key(dev->input_dev, kbd_keycodes[keydata1], 1);
if (keydata2)
- input_report_key(data->idev, kbd_keycodes[keydata2], 1);
+ input_report_key(dev->input_dev, kbd_keycodes[keydata2], 1);
if (!keydata1 && !keydata2) {
for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
- input_report_key(data->idev, kbd_keycodes[i], 0);
+ input_report_key(dev->input_dev, kbd_keycodes[i], 0);
}
}
static void ir_mce_kbd_process_mouse_data(struct rc_dev *dev, u32 scancode)
{
- struct mce_kbd_dec *data = &dev->raw->mce_kbd;
/* raw mouse coordinates */
u8 xdata = (scancode >> 7) & 0x7f;
u8 ydata = (scancode >> 14) & 0x7f;
@@ -208,11 +207,11 @@ static void ir_mce_kbd_process_mouse_data(struct rc_dev *dev, u32 scancode)
dev_dbg(&dev->dev, "mouse: x = %d, y = %d, btns = %s%s\n",
x, y, left ? "L" : "", right ? "R" : "");
- input_report_rel(data->idev, REL_X, x);
- input_report_rel(data->idev, REL_Y, y);
+ input_report_rel(dev->input_dev, REL_X, x);
+ input_report_rel(dev->input_dev, REL_Y, y);
- input_report_key(data->idev, BTN_LEFT, left);
- input_report_key(data->idev, BTN_RIGHT, right);
+ input_report_key(dev->input_dev, BTN_LEFT, left);
+ input_report_key(dev->input_dev, BTN_RIGHT, right);
}
/**
@@ -355,8 +354,8 @@ again:
lsc.scancode = scancode;
ir_lirc_scancode_event(dev, &lsc);
data->state = STATE_INACTIVE;
- input_event(data->idev, EV_MSC, MSC_SCAN, scancode);
- input_sync(data->idev);
+ input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
+ input_sync(dev->input_dev);
return 0;
}
@@ -370,66 +369,18 @@ out:
static int ir_mce_kbd_register(struct rc_dev *dev)
{
struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
- struct input_dev *idev;
- int i, ret;
-
- idev = input_allocate_device();
- if (!idev)
- return -ENOMEM;
-
- snprintf(mce_kbd->name, sizeof(mce_kbd->name),
- "MCE IR Keyboard/Mouse (%s)", dev->driver_name);
- strlcat(mce_kbd->phys, "/input0", sizeof(mce_kbd->phys));
-
- idev->name = mce_kbd->name;
- idev->phys = mce_kbd->phys;
-
- /* Keyboard bits */
- set_bit(EV_KEY, idev->evbit);
- set_bit(EV_REP, idev->evbit);
- for (i = 0; i < sizeof(kbd_keycodes); i++)
- set_bit(kbd_keycodes[i], idev->keybit);
-
- /* Mouse bits */
- set_bit(EV_REL, idev->evbit);
- set_bit(REL_X, idev->relbit);
- set_bit(REL_Y, idev->relbit);
- set_bit(BTN_LEFT, idev->keybit);
- set_bit(BTN_RIGHT, idev->keybit);
-
- /* Report scancodes too */
- set_bit(EV_MSC, idev->evbit);
- set_bit(MSC_SCAN, idev->mscbit);
timer_setup(&mce_kbd->rx_timeout, mce_kbd_rx_timeout, 0);
spin_lock_init(&mce_kbd->keylock);
- input_set_drvdata(idev, mce_kbd);
-
-#if 0
- /* Adding this reference means two input devices are associated with
- * this rc-core device, which ir-keytable doesn't cope with yet */
- idev->dev.parent = &dev->dev;
-#endif
-
- ret = input_register_device(idev);
- if (ret < 0) {
- input_free_device(idev);
- return -EIO;
- }
-
- mce_kbd->idev = idev;
-
return 0;
}
static int ir_mce_kbd_unregister(struct rc_dev *dev)
{
struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
- struct input_dev *idev = mce_kbd->idev;
del_timer_sync(&mce_kbd->rx_timeout);
- input_unregister_device(idev);
return 0;
}
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 68487ce9f79b..d96aed1343e4 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -40,6 +40,7 @@
#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
#define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */
#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */
+#define RC6_6A_KATHREIN_CC 0x80460000 /* Kathrein RCU-676 customer code */
#ifndef CHAR_BIT
#define CHAR_BIT 8 /* Normally in <limits.h> */
#endif
@@ -242,13 +243,17 @@ again:
toggle = 0;
break;
case 32:
- if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
+ switch (scancode & RC6_6A_LCC_MASK) {
+ case RC6_6A_MCE_CC:
+ case RC6_6A_KATHREIN_CC:
protocol = RC_PROTO_RC6_MCE;
toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
- } else {
+ break;
+ default:
protocol = RC_PROTO_RC6_6A_32;
toggle = 0;
+ break;
}
break;
default:
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index de77d22c30a7..cd3c60ba8519 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -173,7 +173,7 @@ static void ite_decode_bytes(struct ite_dev *dev, const u8 * data, int
u32 sample_period;
unsigned long *ldata;
unsigned int next_one, next_zero, size;
- DEFINE_IR_RAW_EVENT(ev);
+ struct ir_raw_event ev = {};
if (length == 0)
return;
@@ -1507,9 +1507,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
/* initialize spinlocks */
spin_lock_init(&itdev->lock);
- /* initialize raw event */
- init_ir_raw_event(&itdev->rawir);
-
/* set driver data into the pnp device */
pnp_set_drvdata(pdev, itdev);
itdev->pdev = pdev;
diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c
index 9b1b57e3c875..e1b2c8e26883 100644
--- a/drivers/media/rc/keymaps/rc-behold.c
+++ b/drivers/media/rc/keymaps/rc-behold.c
@@ -115,7 +115,7 @@ static struct rc_map_list behold_map = {
.map = {
.scan = behold,
.size = ARRAY_SIZE(behold),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_BEHOLD,
}
};
diff --git a/drivers/media/rc/keymaps/rc-delock-61959.c b/drivers/media/rc/keymaps/rc-delock-61959.c
index 62de69d78d92..da21d6d6d79f 100644
--- a/drivers/media/rc/keymaps/rc-delock-61959.c
+++ b/drivers/media/rc/keymaps/rc-delock-61959.c
@@ -60,7 +60,7 @@ static struct rc_map_list delock_61959_map = {
.map = {
.scan = delock_61959,
.size = ARRAY_SIZE(delock_61959),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_DELOCK_61959,
}
};
diff --git a/drivers/media/rc/keymaps/rc-imon-rsc.c b/drivers/media/rc/keymaps/rc-imon-rsc.c
index 83e4564aaa22..6f7ee4859682 100644
--- a/drivers/media/rc/keymaps/rc-imon-rsc.c
+++ b/drivers/media/rc/keymaps/rc-imon-rsc.c
@@ -59,7 +59,7 @@ static struct rc_map_list imon_rsc_map = {
.map = {
.scan = imon_rsc,
.size = ARRAY_SIZE(imon_rsc),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_IMON_RSC,
}
};
diff --git a/drivers/media/rc/keymaps/rc-it913x-v1.c b/drivers/media/rc/keymaps/rc-it913x-v1.c
index 908d14848ae8..f1b5c52953ad 100644
--- a/drivers/media/rc/keymaps/rc-it913x-v1.c
+++ b/drivers/media/rc/keymaps/rc-it913x-v1.c
@@ -73,7 +73,7 @@ static struct rc_map_list it913x_v1_map = {
.map = {
.scan = it913x_v1_rc,
.size = ARRAY_SIZE(it913x_v1_rc),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_IT913X_V1,
}
};
diff --git a/drivers/media/rc/keymaps/rc-it913x-v2.c b/drivers/media/rc/keymaps/rc-it913x-v2.c
index 05ab7fa4f90b..be5dfb4fae46 100644
--- a/drivers/media/rc/keymaps/rc-it913x-v2.c
+++ b/drivers/media/rc/keymaps/rc-it913x-v2.c
@@ -72,7 +72,7 @@ static struct rc_map_list it913x_v2_map = {
.map = {
.scan = it913x_v2_rc,
.size = ARRAY_SIZE(it913x_v2_rc),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_IT913X_V2,
}
};
diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
index 8fec0c1dcb12..d50e741c73b7 100644
--- a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
+++ b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
@@ -64,7 +64,7 @@ static struct rc_map_list msi_digivox_iii_map = {
.map = {
.scan = msi_digivox_iii,
.size = ARRAY_SIZE(msi_digivox_iii),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_MSI_DIGIVOX_III,
}
};
diff --git a/drivers/media/rc/keymaps/rc-pixelview-002t.c b/drivers/media/rc/keymaps/rc-pixelview-002t.c
index 4ed85f61d0ee..c0550e09f255 100644
--- a/drivers/media/rc/keymaps/rc-pixelview-002t.c
+++ b/drivers/media/rc/keymaps/rc-pixelview-002t.c
@@ -51,7 +51,7 @@ static struct rc_map_list pixelview_map = {
.map = {
.scan = pixelview_002t,
.size = ARRAY_SIZE(pixelview_002t),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_PIXELVIEW_002T,
}
};
diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c
index 6ded64b732a5..864c8ea5d8e3 100644
--- a/drivers/media/rc/keymaps/rc-pixelview-mk12.c
+++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c
@@ -57,7 +57,7 @@ static struct rc_map_list pixelview_map = {
.map = {
.scan = pixelview_mk12,
.size = ARRAY_SIZE(pixelview_mk12),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_PIXELVIEW_MK12,
}
};
diff --git a/drivers/media/rc/keymaps/rc-reddo.c b/drivers/media/rc/keymaps/rc-reddo.c
index 3b37acc7b144..b73223e8c238 100644
--- a/drivers/media/rc/keymaps/rc-reddo.c
+++ b/drivers/media/rc/keymaps/rc-reddo.c
@@ -64,7 +64,7 @@ static struct rc_map_list reddo_map = {
.map = {
.scan = reddo,
.size = ARRAY_SIZE(reddo),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_REDDO,
}
};
diff --git a/drivers/media/rc/keymaps/rc-terratec-slim.c b/drivers/media/rc/keymaps/rc-terratec-slim.c
index 628272c58d65..58a209811d12 100644
--- a/drivers/media/rc/keymaps/rc-terratec-slim.c
+++ b/drivers/media/rc/keymaps/rc-terratec-slim.c
@@ -58,7 +58,7 @@ static struct rc_map_list terratec_slim_map = {
.map = {
.scan = terratec_slim,
.size = ARRAY_SIZE(terratec_slim),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_TERRATEC_SLIM,
}
};
diff --git a/drivers/media/rc/keymaps/rc-tivo.c b/drivers/media/rc/keymaps/rc-tivo.c
index 1962e33c8f4e..20268f8b18fd 100644
--- a/drivers/media/rc/keymaps/rc-tivo.c
+++ b/drivers/media/rc/keymaps/rc-tivo.c
@@ -77,7 +77,7 @@ static struct rc_map_list tivo_map = {
.map = {
.scan = tivo,
.size = ARRAY_SIZE(tivo),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NEC32,
.name = RC_MAP_TIVO,
}
};
diff --git a/drivers/media/rc/keymaps/rc-total-media-in-hand.c b/drivers/media/rc/keymaps/rc-total-media-in-hand.c
index bc73bee309d8..c34e8f5a88b6 100644
--- a/drivers/media/rc/keymaps/rc-total-media-in-hand.c
+++ b/drivers/media/rc/keymaps/rc-total-media-in-hand.c
@@ -64,7 +64,7 @@ static struct rc_map_list total_media_in_hand_map = {
.map = {
.scan = total_media_in_hand,
.size = ARRAY_SIZE(total_media_in_hand),
- .rc_proto = RC_PROTO_NEC,
+ .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_TOTAL_MEDIA_IN_HAND,
}
};
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 4c0c8008872a..c9293696dc2d 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1078,7 +1078,7 @@ static int mceusb_set_rx_carrier_report(struct rc_dev *dev, int enable)
*/
static void mceusb_handle_command(struct mceusb_dev *ir, int index)
{
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
u8 hi = ir->buf_in[index + 1] & 0xff;
u8 lo = ir->buf_in[index + 2] & 0xff;
u32 carrier_cycles;
@@ -1152,7 +1152,7 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index)
static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
{
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
bool event = false;
int i = 0;
@@ -1175,7 +1175,6 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
break;
case PARSE_IRDATA:
ir->rem--;
- init_ir_raw_event(&rawir);
rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK);
if (unlikely(!rawir.duration)) {
@@ -1215,11 +1214,13 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
if (ir->rem) {
ir->parser_state = PARSE_IRDATA;
} else {
- init_ir_raw_event(&rawir);
- rawir.timeout = 1;
- rawir.duration = ir->rc->timeout;
+ struct ir_raw_event ev = {
+ .timeout = 1,
+ .duration = ir->rc->timeout
+ };
+
if (ir_raw_event_store_with_filter(ir->rc,
- &rawir))
+ &ev))
event = true;
ir->pulse_tunit = 0;
ir->pulse_count = 0;
@@ -1603,7 +1604,7 @@ static int mceusb_dev_probe(struct usb_interface *intf,
if (dev->descriptor.iManufacturer
&& usb_string(dev, dev->descriptor.iManufacturer,
buf, sizeof(buf)) > 0)
- strlcpy(name, buf, sizeof(name));
+ strscpy(name, buf, sizeof(name));
if (dev->descriptor.iProduct
&& usb_string(dev, dev->descriptor.iProduct,
buf, sizeof(buf)) > 0)
diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index f449b35d25e7..9914c83fecb9 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -86,7 +86,7 @@ static irqreturn_t meson_ir_irq(int irqno, void *dev_id)
{
struct meson_ir *ir = dev_id;
u32 duration, status;
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
spin_lock(&ir->lock);
diff --git a/drivers/media/rc/mtk-cir.c b/drivers/media/rc/mtk-cir.c
index e42efd9d382e..31b7bb431497 100644
--- a/drivers/media/rc/mtk-cir.c
+++ b/drivers/media/rc/mtk-cir.c
@@ -212,7 +212,7 @@ static irqreturn_t mtk_ir_irq(int irqno, void *dev_id)
struct mtk_ir *ir = dev_id;
u8 wid = 0;
u32 i, j, val;
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
/*
* Reset decoder state machine explicitly is required
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index b8299c9a9744..5c2cd8d2d155 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -737,7 +737,7 @@ static void nvt_dump_rx_buf(struct nvt_dev *nvt)
*/
static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
{
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
u8 sample;
int i;
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index e847bdad5c51..c2cbe7f6266c 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -110,12 +110,9 @@ struct ir_raw_event_ctrl {
unsigned int pulse_len;
} sharp;
struct mce_kbd_dec {
- struct input_dev *idev;
/* locks key up timer */
spinlock_t keylock;
struct timer_list rx_timeout;
- char name[64];
- char phys[64];
int state;
u8 header;
u32 body;
@@ -133,8 +130,6 @@ struct ir_raw_event_ctrl {
int last_chk;
unsigned int bits;
bool stick_keyboard;
- struct input_dev *idev;
- char name[64];
} imon;
};
@@ -181,9 +176,10 @@ static inline void init_ir_raw_event_duration(struct ir_raw_event *ev,
unsigned int pulse,
u32 duration)
{
- init_ir_raw_event(ev);
- ev->duration = duration;
- ev->pulse = pulse;
+ *ev = (struct ir_raw_event) {
+ .duration = duration,
+ .pulse = pulse
+ };
}
/**
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index e7948908e78c..e10b4644a442 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -102,7 +102,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store);
int ir_raw_event_store_edge(struct rc_dev *dev, bool pulse)
{
ktime_t now;
- DEFINE_IR_RAW_EVENT(ev);
+ struct ir_raw_event ev = {};
if (!dev->raw)
return -EINVAL;
@@ -210,7 +210,7 @@ void ir_raw_event_set_idle(struct rc_dev *dev, bool idle)
if (idle) {
dev->raw->this_ev.timeout = true;
ir_raw_event_store(dev, &dev->raw->this_ev);
- init_ir_raw_event(&dev->raw->this_ev);
+ dev->raw->this_ev = (struct ir_raw_event) {};
}
if (dev->s_idle)
@@ -562,10 +562,10 @@ static void ir_raw_edge_handle(struct timer_list *t)
spin_lock_irqsave(&dev->raw->edge_spinlock, flags);
interval = ktime_sub(ktime_get(), dev->raw->last_event);
if (ktime_to_ns(interval) >= dev->timeout) {
- DEFINE_IR_RAW_EVENT(ev);
-
- ev.timeout = true;
- ev.duration = ktime_to_ns(interval);
+ struct ir_raw_event ev = {
+ .timeout = true,
+ .duration = ktime_to_ns(interval)
+ };
ir_raw_event_store(dev, &ev);
} else {
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index 3822d9ebcb46..b9f9325b8db1 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -103,7 +103,7 @@ static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
struct loopback_dev *lodev = dev->priv;
u32 rxmask;
unsigned i;
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
if (lodev->txcarrier < lodev->rxcarriermin ||
lodev->txcarrier > lodev->rxcarriermax) {
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index ca68e1d2b2f9..552bbe82a160 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -274,7 +274,6 @@ static unsigned int ir_update_mapping(struct rc_dev *dev,
unsigned int new_keycode)
{
int old_keycode = rc_map->scan[index].keycode;
- int i;
/* Did the user wish to remove the mapping? */
if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
@@ -289,20 +288,9 @@ static unsigned int ir_update_mapping(struct rc_dev *dev,
old_keycode == KEY_RESERVED ? "New" : "Replacing",
rc_map->scan[index].scancode, new_keycode);
rc_map->scan[index].keycode = new_keycode;
- __set_bit(new_keycode, dev->input_dev->keybit);
}
if (old_keycode != KEY_RESERVED) {
- /* A previous mapping was updated... */
- __clear_bit(old_keycode, dev->input_dev->keybit);
- /* ... but another scancode might use the same keycode */
- for (i = 0; i < rc_map->len; i++) {
- if (rc_map->scan[i].keycode == old_keycode) {
- __set_bit(old_keycode, dev->input_dev->keybit);
- break;
- }
- }
-
/* Possibly shrink the keytable, failure is not a problem */
ir_resize_table(dev, rc_map, GFP_ATOMIC);
}
@@ -1755,10 +1743,18 @@ static int rc_prepare_rx_device(struct rc_dev *dev)
dev->enabled_protocols = rc_proto;
}
+ /* Keyboard events */
set_bit(EV_KEY, dev->input_dev->evbit);
set_bit(EV_REP, dev->input_dev->evbit);
set_bit(EV_MSC, dev->input_dev->evbit);
set_bit(MSC_SCAN, dev->input_dev->mscbit);
+ bitmap_fill(dev->input_dev->keybit, KEY_CNT);
+
+ /* Pointer/mouse events */
+ set_bit(EV_REL, dev->input_dev->evbit);
+ set_bit(REL_X, dev->input_dev->relbit);
+ set_bit(REL_Y, dev->input_dev->relbit);
+
if (dev->open)
dev->input_dev->open = ir_open;
if (dev->close)
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 6bfc24885b5c..08c51ffd74a0 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -348,7 +348,7 @@ static u32 redrat3_us_to_len(u32 microsec)
static void redrat3_process_ir_data(struct redrat3_dev *rr3)
{
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
struct device *dev;
unsigned int i, sig_size, single_len, offset, val;
u32 mod_freq;
@@ -358,10 +358,10 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
dev_dbg(dev, "Got mod_freq of %u\n", mod_freq);
if (mod_freq && rr3->wideband) {
- DEFINE_IR_RAW_EVENT(ev);
-
- ev.carrier_report = 1;
- ev.carrier = mod_freq;
+ struct ir_raw_event ev = {
+ .carrier_report = 1,
+ .carrier = mod_freq
+ };
ir_raw_event_store(rr3->rc, &ev);
}
diff --git a/drivers/media/rc/serial_ir.c b/drivers/media/rc/serial_ir.c
index 8bf5637b3a69..ffe2c672d105 100644
--- a/drivers/media/rc/serial_ir.c
+++ b/drivers/media/rc/serial_ir.c
@@ -273,7 +273,7 @@ static void frbwrite(unsigned int l, bool is_pulse)
{
/* simple noise filter */
static unsigned int ptr, pulse, space;
- DEFINE_IR_RAW_EVENT(ev);
+ struct ir_raw_event ev = {};
if (ptr > 0 && is_pulse) {
pulse += l;
@@ -472,10 +472,10 @@ static int hardware_init_port(void)
static void serial_ir_timeout(struct timer_list *unused)
{
- DEFINE_IR_RAW_EVENT(ev);
-
- ev.timeout = true;
- ev.duration = serial_ir.rcdev->timeout;
+ struct ir_raw_event ev = {
+ .timeout = true,
+ .duration = serial_ir.rcdev->timeout
+ };
ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
ir_raw_event_handle(serial_ir.rcdev);
}
diff --git a/drivers/media/rc/sir_ir.c b/drivers/media/rc/sir_ir.c
index 9ee2c9196b4d..c8951650a368 100644
--- a/drivers/media/rc/sir_ir.c
+++ b/drivers/media/rc/sir_ir.c
@@ -96,7 +96,7 @@ static int sir_tx_ir(struct rc_dev *dev, unsigned int *tx_buf,
static void add_read_queue(int flag, unsigned long val)
{
- DEFINE_IR_RAW_EVENT(ev);
+ struct ir_raw_event ev = {};
pr_debug("add flag %d with val %lu\n", flag, val);
diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
index c855b177103c..15de3ae166a2 100644
--- a/drivers/media/rc/st_rc.c
+++ b/drivers/media/rc/st_rc.c
@@ -67,8 +67,7 @@ struct st_rc_device {
static void st_rc_send_lirc_timeout(struct rc_dev *rdev)
{
- DEFINE_IR_RAW_EVENT(ev);
- ev.timeout = true;
+ struct ir_raw_event ev = { .timeout = true, .duration = rdev->timeout };
ir_raw_event_store(rdev, &ev);
}
@@ -101,7 +100,7 @@ static irqreturn_t st_rc_rx_interrupt(int irq, void *data)
struct st_rc_device *dev = data;
int last_symbol = 0;
u32 status, int_status;
- DEFINE_IR_RAW_EVENT(ev);
+ struct ir_raw_event ev = {};
if (dev->irq_wake)
pm_wakeup_event(dev->dev, 0);
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index c9a70fda88a8..a490d26bd170 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -130,7 +130,7 @@ static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
static void sz_push_full_pulse(struct streamzap_ir *sz,
unsigned char value)
{
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
if (sz->idle) {
int delta;
@@ -175,7 +175,7 @@ static void sz_push_half_pulse(struct streamzap_ir *sz,
static void sz_push_full_space(struct streamzap_ir *sz,
unsigned char value)
{
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
rawir.pulse = false;
rawir.duration = ((int) value) * SZ_RESOLUTION;
@@ -249,10 +249,10 @@ static void streamzap_callback(struct urb *urb)
break;
case FullSpace:
if (sz->buf_in[i] == SZ_TIMEOUT) {
- DEFINE_IR_RAW_EVENT(rawir);
-
- rawir.pulse = false;
- rawir.duration = sz->rdev->timeout;
+ struct ir_raw_event rawir = {
+ .pulse = false,
+ .duration = sz->rdev->timeout
+ };
sz->idle = true;
if (sz->timeout_enabled)
sz_push(sz, rawir);
@@ -396,7 +396,7 @@ static int streamzap_probe(struct usb_interface *intf,
if (usbdev->descriptor.iManufacturer
&& usb_string(usbdev, usbdev->descriptor.iManufacturer,
buf, sizeof(buf)) > 0)
- strlcpy(name, buf, sizeof(name));
+ strscpy(name, buf, sizeof(name));
if (usbdev->descriptor.iProduct
&& usb_string(usbdev, usbdev->descriptor.iProduct,
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
index f500cea228a9..307e44714ea0 100644
--- a/drivers/media/rc/sunxi-cir.c
+++ b/drivers/media/rc/sunxi-cir.c
@@ -99,7 +99,7 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id)
unsigned char dt;
unsigned int cnt, rc;
struct sunxi_ir *ir = dev_id;
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
spin_lock(&ir->ir_lock);
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
index aafea3c5170b..8d4b56d057ae 100644
--- a/drivers/media/rc/ttusbir.c
+++ b/drivers/media/rc/ttusbir.c
@@ -117,12 +117,10 @@ static void ttusbir_bulk_complete(struct urb *urb)
*/
static void ttusbir_process_ir_data(struct ttusbir *tt, uint8_t *buf)
{
- struct ir_raw_event rawir;
+ struct ir_raw_event rawir = {};
unsigned i, v, b;
bool event = false;
- init_ir_raw_event(&rawir);
-
for (i = 0; i < 128; i++) {
v = buf[i] & 0xfe;
switch (v) {
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 851acba9b436..0f07a2c384fa 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -322,11 +322,11 @@ wbcir_carrier_report(struct wbcir_data *data)
inb(data->ebase + WBCIR_REG_ECEIR_CNT_HI) << 8;
if (counter > 0 && counter < 0xffff) {
- DEFINE_IR_RAW_EVENT(ev);
-
- ev.carrier_report = 1;
- ev.carrier = DIV_ROUND_CLOSEST(counter * 1000000u,
- data->pulse_duration);
+ struct ir_raw_event ev = {
+ .carrier_report = 1,
+ .carrier = DIV_ROUND_CLOSEST(counter * 1000000u,
+ data->pulse_duration)
+ };
ir_raw_event_store(data->dev, &ev);
}
@@ -362,7 +362,7 @@ static void
wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device)
{
u8 irdata;
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
unsigned duration;
/* Since RXHDLEV is set, at least 8 bytes are in the FIFO */
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index fbec1a13dc6a..91956fb55b75 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -312,7 +312,7 @@ static int e4000_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
dev_dbg(&client->dev, "index=%d\n", v->index);
- strlcpy(v->name, "Elonics E4000", sizeof(v->name));
+ strscpy(v->name, "Elonics E4000", sizeof(v->name));
v->type = V4L2_TUNER_RF;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = bands[0].rangelow;
diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index db26892aac84..dd88cf7148d0 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -405,7 +405,7 @@ static int fc2580_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
dev_dbg(&client->dev, "index=%d\n", v->index);
- strlcpy(v->name, "FCI FC2580", sizeof(v->name));
+ strscpy(v->name, "FCI FC2580", sizeof(v->name));
v->type = V4L2_TUNER_RF;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = bands[0].rangelow;
diff --git a/drivers/media/tuners/msi001.c b/drivers/media/tuners/msi001.c
index 5de6ed728708..331c198c00bb 100644
--- a/drivers/media/tuners/msi001.c
+++ b/drivers/media/tuners/msi001.c
@@ -305,7 +305,7 @@ static int msi001_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
dev_dbg(&spi->dev, "index=%d\n", v->index);
- strlcpy(v->name, "Mirics MSi001", sizeof(v->name));
+ strscpy(v->name, "Mirics MSi001", sizeof(v->name));
v->type = V4L2_TUNER_RF;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = 49000000;
diff --git a/drivers/media/tuners/mt20xx.c b/drivers/media/tuners/mt20xx.c
index 129bf8e1aff8..8b4ce84b6914 100644
--- a/drivers/media/tuners/mt20xx.c
+++ b/drivers/media/tuners/mt20xx.c
@@ -636,7 +636,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
return NULL;
}
- strlcpy(fe->ops.tuner_ops.info.name, name,
+ strscpy(fe->ops.tuner_ops.info.name, name,
sizeof(fe->ops.tuner_ops.info.name));
tuner_info("microtune %s found, OK\n",name);
return fe;
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index a08d8fe2bb1b..d389f1fc237a 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -468,11 +468,14 @@ static int si2157_probe(struct i2c_client *client,
dev->ent.name = KBUILD_MODNAME;
dev->ent.function = MEDIA_ENT_F_TUNER;
- dev->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
- dev->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
- dev->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
-
- ret = media_entity_pads_init(&dev->ent, TUNER_NUM_PADS,
+ dev->pad[SI2157_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ dev->pad[SI2157_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
+ dev->pad[SI2157_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ dev->pad[SI2157_PAD_VID_OUT].sig_type = PAD_SIGNAL_ANALOG;
+ dev->pad[SI2157_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ dev->pad[SI2157_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO;
+
+ ret = media_entity_pads_init(&dev->ent, SI2157_NUM_PADS,
&dev->pad[0]);
if (ret)
diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h
index e6436f74abaa..50f86300d965 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -21,6 +21,13 @@
#include <media/v4l2-mc.h>
#include "si2157.h"
+enum si2157_pads {
+ SI2157_PAD_RF_INPUT,
+ SI2157_PAD_VID_OUT,
+ SI2157_PAD_AUD_OUT,
+ SI2157_NUM_PADS
+};
+
/* state struct */
struct si2157_dev {
struct mutex i2c_mutex;
@@ -35,7 +42,7 @@ struct si2157_dev {
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_device *mdev;
struct media_entity ent;
- struct media_pad pad[TUNER_NUM_PADS];
+ struct media_pad pad[SI2157_NUM_PADS];
#endif
};
diff --git a/drivers/media/tuners/tuner-simple.c b/drivers/media/tuners/tuner-simple.c
index 29c1473f2e9f..d2169bb3111a 100644
--- a/drivers/media/tuners/tuner-simple.c
+++ b/drivers/media/tuners/tuner-simple.c
@@ -1130,7 +1130,7 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
priv->nr, dtv_input[priv->nr]);
}
- strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name,
+ strscpy(fe->ops.tuner_ops.info.name, priv->tun->name,
sizeof(fe->ops.tuner_ops.info.name));
return fe;
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index e70c9e2f3798..41fa0f93143d 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -619,8 +619,8 @@ static int airspy_querycap(struct file *file, void *fh,
{
struct airspy *s = video_drvdata(file);
- strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
- strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
+ strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+ strscpy(cap->card, s->vdev.name, sizeof(cap->card));
usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
@@ -635,7 +635,7 @@ static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv,
if (f->index >= 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;
@@ -720,14 +720,14 @@ static int airspy_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
int ret;
if (v->index == 0) {
- strlcpy(v->name, "AirSpy ADC", sizeof(v->name));
+ strscpy(v->name, "AirSpy ADC", sizeof(v->name));
v->type = V4L2_TUNER_ADC;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = bands[0].rangelow;
v->rangehigh = bands[0].rangehigh;
ret = 0;
} else if (v->index == 1) {
- strlcpy(v->name, "AirSpy RF", sizeof(v->name));
+ strscpy(v->name, "AirSpy RF", sizeof(v->name));
v->type = V4L2_TUNER_RF;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = bands_rf[0].rangelow;
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index cd363a2100d4..1fdb1601dc65 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -266,11 +266,13 @@ static void au0828_media_graph_notify(struct media_entity *new,
create_link:
if (decoder && mixer) {
- ret = media_create_pad_link(decoder,
- DEMOD_PAD_AUDIO_OUT,
- mixer, 0,
- MEDIA_LNK_FL_ENABLED);
- if (ret)
+ ret = media_get_pad_index(decoder, false,
+ PAD_SIGNAL_AUDIO);
+ if (ret >= 0)
+ ret = media_create_pad_link(decoder, ret,
+ mixer, 0,
+ MEDIA_LNK_FL_ENABLED);
+ if (ret < 0)
dev_err(&dev->usbdev->dev,
"Mixer Pad Link Create Error: %d\n", ret);
}
@@ -626,17 +628,16 @@ static int au0828_usb_probe(struct usb_interface *interface,
/* Analog TV */
retval = au0828_analog_register(dev, interface);
if (retval) {
- pr_err("%s() au0282_dev_register failed to register on V4L2\n",
+ pr_err("%s() au0828_analog_register failed to register on V4L2\n",
__func__);
mutex_unlock(&dev->lock);
- kfree(dev);
goto done;
}
/* Digital TV */
retval = au0828_dvb_register(dev);
if (retval)
- pr_err("%s() au0282_dev_register failed\n",
+ pr_err("%s() au0828_dvb_register failed\n",
__func__);
/* Remote controller */
diff --git a/drivers/media/usb/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c
index 1b8ec5d9e7ab..92df5b5463af 100644
--- a/drivers/media/usb/au0828/au0828-i2c.c
+++ b/drivers/media/usb/au0828/au0828-i2c.c
@@ -378,7 +378,7 @@ int au0828_i2c_register(struct au0828_dev *dev)
dev->i2c_adap.dev.parent = &dev->usbdev->dev;
- strlcpy(dev->i2c_adap.name, KBUILD_MODNAME,
+ strscpy(dev->i2c_adap.name, KBUILD_MODNAME,
sizeof(dev->i2c_adap.name));
dev->i2c_adap.algo = &dev->i2c_algo;
diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c
index 832ed9f25784..4befa920246c 100644
--- a/drivers/media/usb/au0828/au0828-input.c
+++ b/drivers/media/usb/au0828/au0828-input.c
@@ -113,7 +113,7 @@ static int au8522_rc_andor(struct au0828_rc *ir, u16 reg, u8 mask, u8 value)
static int au0828_get_key_au8522(struct au0828_rc *ir)
{
unsigned char buf[40];
- DEFINE_IR_RAW_EVENT(rawir);
+ struct ir_raw_event rawir = {};
int i, j, rc;
int prv_bit, bit, width;
bool first = true;
@@ -167,7 +167,6 @@ static int au0828_get_key_au8522(struct au0828_rc *ir)
if (first) {
first = false;
- init_ir_raw_event(&rawir);
rawir.pulse = true;
if (width > NEC_START_SPACE - 2 &&
width < NEC_START_SPACE + 2) {
@@ -186,7 +185,6 @@ static int au0828_get_key_au8522(struct au0828_rc *ir)
ir_raw_event_store(ir->rc, &rawir);
}
- init_ir_raw_event(&rawir);
rawir.pulse = prv_bit ? false : true;
rawir.duration = AU8522_UNIT * width;
dprintk(16, "Storing %s with duration %d",
@@ -199,7 +197,6 @@ static int au0828_get_key_au8522(struct au0828_rc *ir)
}
}
- init_ir_raw_event(&rawir);
rawir.pulse = prv_bit ? false : true;
rawir.duration = AU8522_UNIT * width;
dprintk(16, "Storing end %s with duration %d",
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 62b45062b1e6..efbf210147c7 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -1191,8 +1191,8 @@ static int vidioc_querycap(struct file *file, void *priv,
dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state);
- strlcpy(cap->driver, "au0828", sizeof(cap->driver));
- strlcpy(cap->card, dev->board.name, sizeof(cap->card));
+ strscpy(cap->driver, "au0828", sizeof(cap->driver));
+ strscpy(cap->card, dev->board.name, sizeof(cap->card));
usb_make_path(dev->usbdev, cap->bus_info, sizeof(cap->bus_info));
/* set the device capabilities */
@@ -1218,7 +1218,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
dprintk(1, "%s called\n", __func__);
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- strcpy(f->description, "Packed YUV2");
+ strscpy(f->description, "Packed YUV2", sizeof(f->description));
f->flags = 0;
f->pixelformat = V4L2_PIX_FMT_UYVY;
@@ -1349,7 +1349,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
return -EINVAL;
input->index = tmp;
- strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
+ strscpy(input->name, inames[AUVI_INPUT(tmp).type], sizeof(input->name));
if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
(AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) {
input->type |= V4L2_INPUT_TYPE_TUNER;
@@ -1465,9 +1465,9 @@ static int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *a)
dprintk(1, "%s called\n", __func__);
if (a->index == 0)
- strcpy(a->name, "Television");
+ strscpy(a->name, "Television", sizeof(a->name));
else
- strcpy(a->name, "Line in");
+ strscpy(a->name, "Line in", sizeof(a->name));
a->capability = V4L2_AUDCAP_STEREO;
return 0;
@@ -1482,9 +1482,9 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
a->index = dev->ctrl_ainput;
if (a->index == 0)
- strcpy(a->name, "Television");
+ strscpy(a->name, "Television", sizeof(a->name));
else
- strcpy(a->name, "Line in");
+ strscpy(a->name, "Line in", sizeof(a->name));
a->capability = V4L2_AUDCAP_STEREO;
return 0;
@@ -1518,7 +1518,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state);
- strcpy(t->name, "Auvitek tuner");
+ strscpy(t->name, "Auvitek tuner", sizeof(t->name));
au0828_init_tuner(dev);
i2c_gate_ctrl(dev, 1);
@@ -1978,7 +1978,7 @@ int au0828_analog_register(struct au0828_dev *dev,
dev->vdev.lock = &dev->lock;
dev->vdev.queue = &dev->vb_vidq;
dev->vdev.queue->lock = &dev->vb_queue_lock;
- strcpy(dev->vdev.name, "au0828a video");
+ strscpy(dev->vdev.name, "au0828a video", sizeof(dev->vdev.name));
/* Setup the VBI device */
dev->vbi_dev = au0828_video_template;
@@ -1986,7 +1986,7 @@ int au0828_analog_register(struct au0828_dev *dev,
dev->vbi_dev.lock = &dev->lock;
dev->vbi_dev.queue = &dev->vb_vbiq;
dev->vbi_dev.queue->lock = &dev->vb_vbi_queue_lock;
- strcpy(dev->vbi_dev.name, "au0828a vbi");
+ strscpy(dev->vbi_dev.name, "au0828a vbi", sizeof(dev->vbi_dev.name));
/* Init entities at the Media Controller */
au0828_analog_create_entities(dev);
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c
index 99f106b13280..aa7f3c307b22 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -219,12 +219,12 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v
{
struct camera_data *cam = video_drvdata(file);
- strcpy(vc->driver, "cpia2");
+ strscpy(vc->driver, "cpia2", sizeof(vc->driver));
if (cam->params.pnp_id.product == 0x151)
- strcpy(vc->card, "QX5 Microscope");
+ strscpy(vc->card, "QX5 Microscope", sizeof(vc->card));
else
- strcpy(vc->card, "CPiA2 Camera");
+ strscpy(vc->card, "CPiA2 Camera", sizeof(vc->card));
switch (cam->params.pnp_id.device_type) {
case DEVICE_STV_672:
strcat(vc->card, " (672/");
@@ -281,7 +281,7 @@ static int cpia2_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
if (i->index)
return -EINVAL;
- strcpy(i->name, "Camera");
+ strscpy(i->name, "Camera", sizeof(i->name));
i->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
}
@@ -319,11 +319,11 @@ static int cpia2_enum_fmt_vid_cap(struct file *file, void *fh,
f->flags = V4L2_FMT_FLAG_COMPRESSED;
switch(index) {
case 0:
- strcpy(f->description, "MJPEG");
+ strscpy(f->description, "MJPEG", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_MJPEG;
break;
case 1:
- strcpy(f->description, "JPEG");
+ strscpy(f->description, "JPEG", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_JPEG;
break;
default:
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
index 2f3b0564d676..f700ec35b7f3 100644
--- a/drivers/media/usb/cx231xx/cx231xx-417.c
+++ b/drivers/media/usb/cx231xx/cx231xx-417.c
@@ -1583,7 +1583,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/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c
index 32ee7b3f21c9..77f2c65eb79a 100644
--- a/drivers/media/usb/cx231xx/cx231xx-audio.c
+++ b/drivers/media/usb/cx231xx/cx231xx-audio.c
@@ -679,10 +679,10 @@ static int cx231xx_audio_init(struct cx231xx *dev)
&snd_cx231xx_pcm_capture);
pcm->info_flags = 0;
pcm->private_data = dev;
- strcpy(pcm->name, "Conexant cx231xx Capture");
- strcpy(card->driver, "Cx231xx-Audio");
- strcpy(card->shortname, "Cx231xx Audio");
- strcpy(card->longname, "Conexant cx231xx Audio");
+ strscpy(pcm->name, "Conexant cx231xx Capture", sizeof(pcm->name));
+ strscpy(card->driver, "Cx231xx-Audio", sizeof(card->driver));
+ strscpy(card->shortname, "Cx231xx Audio", sizeof(card->shortname));
+ strscpy(card->longname, "Conexant cx231xx Audio", sizeof(card->longname));
INIT_WORK(&dev->wq_trigger, audio_trigger);
diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c
index 3e9b73a6b7c9..9f88c640ec2b 100644
--- a/drivers/media/usb/cx231xx/cx231xx-input.c
+++ b/drivers/media/usb/cx231xx/cx231xx-input.c
@@ -67,7 +67,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
dev->init_data.name = cx231xx_boards[dev->model].name;
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ strscpy(info.type, "ir_video", I2C_NAME_SIZE);
info.platform_data = &dev->init_data;
/*
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
index f7fcd733a2ca..f2f034c5cd62 100644
--- a/drivers/media/usb/cx231xx/cx231xx-video.c
+++ b/drivers/media/usb/cx231xx/cx231xx-video.c
@@ -1169,7 +1169,7 @@ int cx231xx_enum_input(struct file *file, void *priv,
i->index = n;
i->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(i->name, iname[INPUT(n)->type]);
+ strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name));
if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) ||
(CX231XX_VMUX_CABLE == INPUT(n)->type))
@@ -1244,7 +1244,7 @@ int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
if (0 != t->index)
return -EINVAL;
- strcpy(t->name, "Tuner");
+ strscpy(t->name, "Tuner", sizeof(t->name));
t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM;
@@ -1354,22 +1354,22 @@ int cx231xx_g_chip_info(struct file *file, void *fh,
case 0: /* Cx231xx - internal registers */
return 0;
case 1: /* AFE - read byte */
- strlcpy(chip->name, "AFE (byte)", sizeof(chip->name));
+ strscpy(chip->name, "AFE (byte)", sizeof(chip->name));
return 0;
case 2: /* Video Block - read byte */
- strlcpy(chip->name, "Video (byte)", sizeof(chip->name));
+ strscpy(chip->name, "Video (byte)", sizeof(chip->name));
return 0;
case 3: /* I2S block - read byte */
- strlcpy(chip->name, "I2S (byte)", sizeof(chip->name));
+ strscpy(chip->name, "I2S (byte)", sizeof(chip->name));
return 0;
case 4: /* AFE - read dword */
- strlcpy(chip->name, "AFE (dword)", sizeof(chip->name));
+ strscpy(chip->name, "AFE (dword)", sizeof(chip->name));
return 0;
case 5: /* Video Block - read dword */
- strlcpy(chip->name, "Video (dword)", sizeof(chip->name));
+ strscpy(chip->name, "Video (dword)", sizeof(chip->name));
return 0;
case 6: /* I2S Block - read dword */
- strlcpy(chip->name, "I2S (dword)", sizeof(chip->name));
+ strscpy(chip->name, "I2S (dword)", sizeof(chip->name));
return 0;
}
return -EINVAL;
@@ -1389,7 +1389,7 @@ int cx231xx_g_register(struct file *file, void *priv,
ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
(u16)reg->reg, value, 4);
reg->val = value[0] | value[1] << 8 |
- value[2] << 16 | value[3] << 24;
+ value[2] << 16 | (u32)value[3] << 24;
reg->size = 4;
break;
case 1: /* AFE - read byte */
@@ -1553,8 +1553,8 @@ int cx231xx_querycap(struct file *file, void *priv,
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
- strlcpy(cap->driver, "cx231xx", sizeof(cap->driver));
- strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
+ strscpy(cap->driver, "cx231xx", sizeof(cap->driver));
+ strscpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
if (vdev->vfl_type == VFL_TYPE_RADIO)
@@ -1583,7 +1583,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (unlikely(f->index >= ARRAY_SIZE(format)))
return -EINVAL;
- strlcpy(f->description, format[f->index].name, sizeof(f->description));
+ strscpy(f->description, format[f->index].name, sizeof(f->description));
f->pixelformat = format[f->index].fourcc;
return 0;
@@ -1716,7 +1716,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
if (t->index)
return -EINVAL;
- strcpy(t->name, "Radio");
+ strscpy(t->name, "Radio", sizeof(t->name));
call_all(dev, tuner, g_tuner, t);
@@ -2242,7 +2242,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
/* Initialize VBI template */
cx231xx_vbi_template = cx231xx_video_template;
- strcpy(cx231xx_vbi_template.name, "cx231xx-vbi");
+ strscpy(cx231xx_vbi_template.name, "cx231xx-vbi",
+ sizeof(cx231xx_vbi_template.name));
/* Allocate and fill vbi video_device struct */
cx231xx_vdev_init(dev, &dev->vbi_dev, &cx231xx_vbi_template, "vbi");
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 1f6c1eefe389..80d3bd3a0f24 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -204,7 +204,7 @@ static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type,
.platform_data = platform_data,
};
- strlcpy(board_info.type, type, I2C_NAME_SIZE);
+ strscpy(board_info.type, type, I2C_NAME_SIZE);
/* find first free client */
for (num = 0; num < AF9035_I2C_CLIENT_MAX; num++) {
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index 20ee7eea2a91..0df7ad69e6c7 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -638,7 +638,7 @@ static int anysee_add_i2c_dev(struct dvb_usb_device *d, const char *type,
.platform_data = platform_data,
};
- strlcpy(board_info.type, type, I2C_NAME_SIZE);
+ strscpy(board_info.type, type, I2C_NAME_SIZE);
/* find first free client */
for (num = 0; num < ANYSEE_I2C_CLIENT_MAX; num++) {
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index 955318ab7f5e..3b8f7931b730 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -74,7 +74,7 @@ static int dvb_usbv2_i2c_init(struct dvb_usb_device *d)
if (!d->props->i2c_algo)
return 0;
- strlcpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name));
+ strscpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name));
d->i2c_adap.algo = d->props->i2c_algo;
d->i2c_adap.dev.parent = &d->udev->dev;
i2c_set_adapdata(&d->i2c_adap, d);
diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c
index 1aa88d94e57f..e28bd8836751 100644
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -31,6 +31,7 @@ MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver.");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
struct dvbsky_state {
+ struct mutex stream_mutex;
u8 ibuf[DVBSKY_BUF_LEN];
u8 obuf[DVBSKY_BUF_LEN];
u8 last_lock;
@@ -67,17 +68,18 @@ static int dvbsky_usb_generic_rw(struct dvb_usb_device *d,
static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff)
{
+ struct dvbsky_state *state = d_to_priv(d);
int ret;
- static u8 obuf_pre[3] = { 0x37, 0, 0 };
- static u8 obuf_post[3] = { 0x36, 3, 0 };
+ u8 obuf_pre[3] = { 0x37, 0, 0 };
+ u8 obuf_post[3] = { 0x36, 3, 0 };
- mutex_lock(&d->usb_mutex);
- ret = dvb_usbv2_generic_rw_locked(d, obuf_pre, 3, NULL, 0);
+ mutex_lock(&state->stream_mutex);
+ ret = dvbsky_usb_generic_rw(d, obuf_pre, 3, NULL, 0);
if (!ret && onoff) {
msleep(20);
- ret = dvb_usbv2_generic_rw_locked(d, obuf_post, 3, NULL, 0);
+ ret = dvbsky_usb_generic_rw(d, obuf_post, 3, NULL, 0);
}
- mutex_unlock(&d->usb_mutex);
+ mutex_unlock(&state->stream_mutex);
return ret;
}
@@ -606,6 +608,8 @@ static int dvbsky_init(struct dvb_usb_device *d)
if (ret)
return ret;
*/
+ mutex_init(&state->stream_mutex);
+
state->last_lock = 0;
return 0;
diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
index 3338b21d8b25..0559417c8af4 100644
--- a/drivers/media/usb/dvb-usb-v2/gl861.c
+++ b/drivers/media/usb/dvb-usb-v2/gl861.c
@@ -507,7 +507,7 @@ static int friio_frontend_attach(struct dvb_usb_adapter *adap)
priv->i2c_client_demod = cl;
priv->tuner_adap.algo = &friio_tuner_i2c_algo;
priv->tuner_adap.dev.parent = &d->udev->dev;
- strlcpy(priv->tuner_adap.name, d->name, sizeof(priv->tuner_adap.name));
+ strscpy(priv->tuner_adap.name, d->name, sizeof(priv->tuner_adap.name));
strlcat(priv->tuner_adap.name, "-tuner", sizeof(priv->tuner_adap.name));
priv->demod_sub_i2c = &priv->tuner_adap;
i2c_set_adapdata(&priv->tuner_adap, d);
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index 0750a975bcb8..f109c04f05ae 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -1004,7 +1004,7 @@ static int lme_name(struct dvb_usb_adapter *adap)
" SHARP:BS2F7HZ0194", " RS2000"};
char *name = adap->fe[0]->ops.info.name;
- strlcpy(name, desc, 128);
+ strscpy(name, desc, 128);
strlcat(name, fe_name[st->tuner_config], 128);
return 0;
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index 4713ba65e1c2..85cdf593a9ad 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -892,11 +892,13 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
state->tuner.function = MEDIA_ENT_F_TUNER;
state->tuner.name = "mxl111sf tuner";
- state->tuner_pads[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
- state->tuner_pads[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
+ state->tuner_pads[MXL111SF_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ state->tuner_pads[MXL111SF_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
+ state->tuner_pads[MXL111SF_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
+ state->tuner_pads[MXL111SF_PAD_OUTPUT].sig_type = PAD_SIGNAL_ANALOG;
ret = media_entity_pads_init(&state->tuner,
- TUNER_NUM_PADS, state->tuner_pads);
+ MXL111SF_NUM_PADS, state->tuner_pads);
if (ret)
return ret;
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
index 22253d4908eb..ed98654ba7fd 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
@@ -52,6 +52,12 @@ struct mxl111sf_adap_state {
int (*fe_sleep)(struct dvb_frontend *);
};
+enum mxl111sf_pads {
+ MXL111SF_PAD_RF_INPUT,
+ MXL111SF_PAD_OUTPUT,
+ MXL111SF_NUM_PADS
+};
+
struct mxl111sf_state {
struct dvb_usb_device *d;
@@ -94,7 +100,7 @@ struct mxl111sf_state {
struct mutex msg_lock;
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
struct media_entity tuner;
- struct media_pad tuner_pads[2];
+ struct media_pad tuner_pads[MXL111SF_NUM_PADS];
#endif
};
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index a970224a94bd..8a83b10e50e0 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -687,7 +687,7 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
/* attach demodulator */
memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "rtl2830", I2C_NAME_SIZE);
+ strscpy(board_info.type, "rtl2830", I2C_NAME_SIZE);
board_info.addr = 0x10;
board_info.platform_data = pdata;
request_module("%s", board_info.type);
@@ -908,7 +908,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
/* attach demodulator */
memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "rtl2832", I2C_NAME_SIZE);
+ strscpy(board_info.type, "rtl2832", I2C_NAME_SIZE);
board_info.addr = 0x10;
board_info.platform_data = pdata;
request_module("%s", board_info.type);
@@ -947,7 +947,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
mn88472_config.fe = &adap->fe[1];
mn88472_config.i2c_wr_max = 22,
- strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
+ strscpy(info.type, "mn88472", I2C_NAME_SIZE);
mn88472_config.xtal = 20500000;
mn88472_config.ts_mode = SERIAL_TS_MODE;
mn88472_config.ts_clock = VARIABLE_TS_CLOCK;
@@ -972,7 +972,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
mn88473_config.fe = &adap->fe[1];
mn88473_config.i2c_wr_max = 22,
- strlcpy(info.type, "mn88473", I2C_NAME_SIZE);
+ strscpy(info.type, "mn88473", I2C_NAME_SIZE);
info.addr = 0x18;
info.platform_data = &mn88473_config;
request_module(info.type);
@@ -998,7 +998,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
si2168_config.ts_mode = SI2168_TS_SERIAL;
si2168_config.ts_clock_inv = false;
si2168_config.ts_clock_gapped = true;
- 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);
@@ -1189,7 +1189,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
.clock = 28800000,
};
- strlcpy(info.type, "e4000", I2C_NAME_SIZE);
+ strscpy(info.type, "e4000", I2C_NAME_SIZE);
info.addr = 0x64;
info.platform_data = &e4000_config;
@@ -1213,7 +1213,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
};
struct i2c_board_info board_info = {};
- strlcpy(board_info.type, "fc2580", I2C_NAME_SIZE);
+ strscpy(board_info.type, "fc2580", I2C_NAME_SIZE);
board_info.addr = 0x56;
board_info.platform_data = &fc2580_pdata;
request_module("fc2580");
@@ -1244,7 +1244,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
if (ret)
goto err;
- strlcpy(board_info.type, "tua9001", I2C_NAME_SIZE);
+ strscpy(board_info.type, "tua9001", I2C_NAME_SIZE);
board_info.addr = 0x60;
board_info.platform_data = &tua9001_pdata;
request_module("tua9001");
@@ -1289,7 +1289,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
.inversion = false,
};
- 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);
@@ -1685,7 +1685,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
{
int ret, i, len;
struct rtl28xxu_dev *dev = d->priv;
- struct ir_raw_event ev;
+ struct ir_raw_event ev = {};
u8 buf[128];
static const struct rtl28xxu_reg_val_mask refresh_tab[] = {
{IR_RX_IF, 0x03, 0xff},
@@ -1751,8 +1751,6 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
}
/* pass data to Kernel IR decoder */
- init_ir_raw_event(&ev);
-
for (i = 0; i < len; i++) {
ev.pulse = buf[i] >> 7;
ev.duration = 50800 * (buf[i] & 0x7f);
diff --git a/drivers/media/usb/dvb-usb-v2/zd1301.c b/drivers/media/usb/dvb-usb-v2/zd1301.c
index d1eb4b7bc051..7a41d744ff58 100644
--- a/drivers/media/usb/dvb-usb-v2/zd1301.c
+++ b/drivers/media/usb/dvb-usb-v2/zd1301.c
@@ -177,7 +177,7 @@ static int zd1301_frontend_attach(struct dvb_usb_adapter *adap)
dev->mt2060_pdata.i2c_write_max = 9;
dev->mt2060_pdata.dvb_frontend = frontend;
memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "mt2060", I2C_NAME_SIZE);
+ strscpy(board_info.type, "mt2060", I2C_NAME_SIZE);
board_info.addr = 0x60;
board_info.platform_data = &dev->mt2060_pdata;
request_module("%s", "mt2060");
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index 5b51ed7d6243..a51a45c60233 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -1196,7 +1196,7 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap)
si2168_config.ts_mode = SI2168_TS_PARALLEL;
si2168_config.ts_clock_inv = 1;
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);
@@ -1216,7 +1216,7 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap)
si2157_config.fe = adap->fe_adap[0].fe;
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);
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index 091389fdf89e..7551dce96f64 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -3763,7 +3763,7 @@ static int xbox_one_attach(struct dvb_usb_adapter *adap)
mn88472_config.ts_mode = PARALLEL_TS_MODE;
mn88472_config.ts_clock = FIXED_TS_CLOCK;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
+ strscpy(info.type, "mn88472", I2C_NAME_SIZE);
info.addr = 0x18;
info.platform_data = &mn88472_config;
request_module(info.type);
@@ -3790,7 +3790,7 @@ static int xbox_one_attach(struct dvb_usb_adapter *adap)
tda18250_config.fe = adap->fe_adap[0].fe;
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "tda18250", I2C_NAME_SIZE);
+ strscpy(info.type, "tda18250", I2C_NAME_SIZE);
info.addr = 0x60;
info.platform_data = &tda18250_config;
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c
index ca0b734e009b..2e07106f4680 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c
@@ -20,7 +20,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
return -EINVAL;
}
- strlcpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
+ strscpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
d->i2c_adap.algo = d->props.i2c_algo;
d->i2c_adap.algo_data = NULL;
d->i2c_adap.dev.parent = &d->udev->dev;
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 9ce8b4d79d1f..eefe2867815c 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -1589,7 +1589,7 @@ static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap)
m88ds3103_pdata.lnb_hv_pol = 1;
m88ds3103_pdata.lnb_en_pol = 0;
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 = 0x68;
board_info.platform_data = &m88ds3103_pdata;
request_module("m88ds3103");
@@ -1608,7 +1608,7 @@ static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap)
/* attach tuner */
ts2020_config.fe = adap->fe_adap[0].fe;
memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "ts2022", I2C_NAME_SIZE);
+ strscpy(board_info.type, "ts2022", I2C_NAME_SIZE);
board_info.addr = 0x60;
board_info.platform_data = &ts2020_config;
request_module("ts2020");
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c
index 18d0f8f5283f..c659e18b358b 100644
--- a/drivers/media/usb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/usb/dvb-usb/technisat-usb2.c
@@ -566,8 +566,9 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage;
/* if everything was successful assign a nice name to the frontend */
- strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name,
- sizeof(a->fe_adap[0].fe->ops.info.name));
+ strscpy(a->fe_adap[0].fe->ops.info.name,
+ a->dev->desc->name,
+ sizeof(a->fe_adap[0].fe->ops.info.name));
} else {
dvb_frontend_detach(a->fe_adap[0].fe);
a->fe_adap[0].fe = NULL;
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c
index 67481fc82445..49c9b70b632b 100644
--- a/drivers/media/usb/em28xx/em28xx-audio.c
+++ b/drivers/media/usb/em28xx/em28xx-audio.c
@@ -843,11 +843,11 @@ static int em28xx_audio_urb_init(struct em28xx *dev)
dev->adev.transfer_buffer = kcalloc(num_urb,
sizeof(*dev->adev.transfer_buffer),
- GFP_ATOMIC);
+ GFP_KERNEL);
if (!dev->adev.transfer_buffer)
return -ENOMEM;
- dev->adev.urb = kcalloc(num_urb, sizeof(*dev->adev.urb), GFP_ATOMIC);
+ dev->adev.urb = kcalloc(num_urb, sizeof(*dev->adev.urb), GFP_KERNEL);
if (!dev->adev.urb) {
kfree(dev->adev.transfer_buffer);
return -ENOMEM;
@@ -860,14 +860,14 @@ static int em28xx_audio_urb_init(struct em28xx *dev)
int j, k;
void *buf;
- urb = usb_alloc_urb(npackets, GFP_ATOMIC);
+ urb = usb_alloc_urb(npackets, GFP_KERNEL);
if (!urb) {
em28xx_audio_free_urb(dev);
return -ENOMEM;
}
dev->adev.urb[i] = urb;
- buf = usb_alloc_coherent(udev, npackets * ep_size, GFP_ATOMIC,
+ buf = usb_alloc_coherent(udev, npackets * ep_size, GFP_KERNEL,
&urb->transfer_dma);
if (!buf) {
dev_err(&dev->intf->dev,
@@ -939,11 +939,11 @@ static int em28xx_audio_init(struct em28xx *dev)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture);
pcm->info_flags = 0;
pcm->private_data = dev;
- strcpy(pcm->name, "Empia 28xx Capture");
+ strscpy(pcm->name, "Empia 28xx Capture", sizeof(pcm->name));
- strcpy(card->driver, "Em28xx-Audio");
- strcpy(card->shortname, "Em28xx Audio");
- strcpy(card->longname, "Empia Em28xx Audio");
+ strscpy(card->driver, "Em28xx-Audio", sizeof(card->driver));
+ strscpy(card->shortname, "Em28xx Audio", sizeof(card->shortname));
+ strscpy(card->longname, "Empia Em28xx Audio", sizeof(card->longname));
INIT_WORK(&adev->wq_trigger, audio_trigger);
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 71c829f31d3b..87b887b7604e 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -2141,13 +2141,13 @@ const struct em28xx_board em28xx_boards[] = {
.input = { {
.type = EM28XX_VMUX_COMPOSITE,
.vmux = TVP5150_COMPOSITE1,
- .amux = EM28XX_AUDIO_SRC_LINE,
+ .amux = EM28XX_AMUX_LINE_IN,
.gpio = terratec_av350_unmute_gpio,
}, {
.type = EM28XX_VMUX_SVIDEO,
.vmux = TVP5150_SVIDEO,
- .amux = EM28XX_AUDIO_SRC_LINE,
+ .amux = EM28XX_AMUX_LINE_IN,
.gpio = terratec_av350_unmute_gpio,
} },
},
@@ -3039,6 +3039,9 @@ static int em28xx_hint_board(struct em28xx *dev)
static void em28xx_card_setup(struct em28xx *dev)
{
+ int i, j, idx;
+ bool duplicate_entry;
+
/*
* If the device can be a webcam, seek for a sensor.
* If sensor is not found, then it isn't a webcam.
@@ -3195,6 +3198,32 @@ static void em28xx_card_setup(struct em28xx *dev)
/* Allow override tuner type by a module parameter */
if (tuner >= 0)
dev->tuner_type = tuner;
+
+ /*
+ * Dynamically generate a list of valid audio inputs for this
+ * specific board, mapping them via enum em28xx_amux.
+ */
+
+ idx = 0;
+ for (i = 0; i < MAX_EM28XX_INPUT; i++) {
+ if (!INPUT(i)->type)
+ continue;
+
+ /* Skip already mapped audio inputs */
+ duplicate_entry = false;
+ for (j = 0; j < idx; j++) {
+ if (INPUT(i)->amux == dev->amux_map[j]) {
+ duplicate_entry = true;
+ break;
+ }
+ }
+ if (duplicate_entry)
+ continue;
+
+ dev->amux_map[idx++] = INPUT(i)->amux;
+ }
+ for (; idx < MAX_EM28XX_INPUT; idx++)
+ dev->amux_map[idx] = EM28XX_AMUX_UNUSED;
}
void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index e19d6342e0d0..02c13d71e6c1 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -985,7 +985,8 @@ int em28xx_i2c_register(struct em28xx *dev, unsigned int bus,
dev->i2c_adap[bus] = em28xx_adap_template;
dev->i2c_adap[bus].dev.parent = &dev->intf->dev;
- strcpy(dev->i2c_adap[bus].name, dev_name(&dev->intf->dev));
+ strscpy(dev->i2c_adap[bus].name, dev_name(&dev->intf->dev),
+ sizeof(dev->i2c_adap[bus].name));
dev->i2c_bus[bus].bus = bus;
dev->i2c_bus[bus].algo_type = algo_type;
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 68571bf36d28..f43717ea831d 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -1093,6 +1093,8 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
em28xx_videodbg("%s\n", __func__);
+ dev->v4l2->field_count = 0;
+
/*
* Make sure streaming is not already in progress for this type
* of filehandle (e.g. video, vbi)
@@ -1471,9 +1473,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
if (!fmt) {
- em28xx_videodbg("Fourcc format (%08x) invalid.\n",
- f->fmt.pix.pixelformat);
- return -EINVAL;
+ fmt = &format[0];
+ em28xx_videodbg("Fourcc format (%08x) invalid. Using default (%08x).\n",
+ f->fmt.pix.pixelformat, fmt->fourcc);
}
if (dev->board.is_em2800) {
@@ -1666,6 +1668,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
{
struct em28xx *dev = video_drvdata(file);
unsigned int n;
+ int j;
n = i->index;
if (n >= MAX_EM28XX_INPUT)
@@ -1675,7 +1678,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
i->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(i->name, iname[INPUT(n)->type]);
+ strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name));
if (INPUT(n)->type == EM28XX_VMUX_TELEVISION)
i->type = V4L2_INPUT_TYPE_TUNER;
@@ -1685,6 +1688,12 @@ static int vidioc_enum_input(struct file *file, void *priv,
if (dev->is_webcam)
i->capabilities = 0;
+ /* Dynamically generates an audioset bitmask */
+ i->audioset = 0;
+ for (j = 0; j < MAX_EM28XX_INPUT; j++)
+ if (dev->amux_map[j] != EM28XX_AMUX_UNUSED)
+ i->audioset |= 1 << j;
+
return 0;
}
@@ -1710,61 +1719,121 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
return 0;
}
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+static int em28xx_fill_audio_input(struct em28xx *dev,
+ const char *s,
+ struct v4l2_audio *a,
+ unsigned int index)
{
- struct em28xx *dev = video_drvdata(file);
+ unsigned int idx = dev->amux_map[index];
+
+ /*
+ * With msp3400, almost all mappings use the default (amux = 0).
+ * The only one may use a different value is WinTV USB2, where it
+ * can also be SCART1 input.
+ * As it is very doubtful that we would see new boards with msp3400,
+ * let's just reuse the existing switch.
+ */
+ if (dev->has_msp34xx && idx != EM28XX_AMUX_UNUSED)
+ idx = EM28XX_AMUX_LINE_IN;
- switch (a->index) {
+ switch (idx) {
case EM28XX_AMUX_VIDEO:
- strcpy(a->name, "Television");
+ strscpy(a->name, "Television", sizeof(a->name));
break;
case EM28XX_AMUX_LINE_IN:
- strcpy(a->name, "Line In");
+ strscpy(a->name, "Line In", sizeof(a->name));
break;
case EM28XX_AMUX_VIDEO2:
- strcpy(a->name, "Television alt");
+ strscpy(a->name, "Television alt", sizeof(a->name));
break;
case EM28XX_AMUX_PHONE:
- strcpy(a->name, "Phone");
+ strscpy(a->name, "Phone", sizeof(a->name));
break;
case EM28XX_AMUX_MIC:
- strcpy(a->name, "Mic");
+ strscpy(a->name, "Mic", sizeof(a->name));
break;
case EM28XX_AMUX_CD:
- strcpy(a->name, "CD");
+ strscpy(a->name, "CD", sizeof(a->name));
break;
case EM28XX_AMUX_AUX:
- strcpy(a->name, "Aux");
+ strscpy(a->name, "Aux", sizeof(a->name));
break;
case EM28XX_AMUX_PCM_OUT:
- strcpy(a->name, "PCM");
+ strscpy(a->name, "PCM", sizeof(a->name));
break;
+ case EM28XX_AMUX_UNUSED:
default:
return -EINVAL;
}
-
- a->index = dev->ctl_ainput;
+ a->index = index;
a->capability = V4L2_AUDCAP_STEREO;
+ em28xx_videodbg("%s: audio input index %d is '%s'\n",
+ s, a->index, a->name);
+
return 0;
}
+static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+ struct em28xx *dev = video_drvdata(file);
+
+ if (a->index >= MAX_EM28XX_INPUT)
+ return -EINVAL;
+
+ return em28xx_fill_audio_input(dev, __func__, a, a->index);
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+ struct em28xx *dev = video_drvdata(file);
+ int i;
+
+ for (i = 0; i < MAX_EM28XX_INPUT; i++)
+ if (dev->ctl_ainput == dev->amux_map[i])
+ return em28xx_fill_audio_input(dev, __func__, a, i);
+
+ /* Should never happen! */
+ return -EINVAL;
+}
+
static int vidioc_s_audio(struct file *file, void *priv,
const struct v4l2_audio *a)
{
struct em28xx *dev = video_drvdata(file);
+ int idx, i;
if (a->index >= MAX_EM28XX_INPUT)
return -EINVAL;
- if (!INPUT(a->index)->type)
+
+ idx = dev->amux_map[a->index];
+
+ if (idx == EM28XX_AMUX_UNUSED)
return -EINVAL;
- dev->ctl_ainput = INPUT(a->index)->amux;
- dev->ctl_aoutput = INPUT(a->index)->aout;
+ dev->ctl_ainput = idx;
+
+ /*
+ * FIXME: This is wrong, as different inputs at em28xx_cards
+ * may have different audio outputs. So, the right thing
+ * to do is to implement VIDIOC_G_AUDOUT/VIDIOC_S_AUDOUT.
+ * With the current board definitions, this would work fine,
+ * as, currently, all boards fit.
+ */
+ for (i = 0; i < MAX_EM28XX_INPUT; i++)
+ if (idx == dev->amux_map[i])
+ break;
+ if (i == MAX_EM28XX_INPUT)
+ return -EINVAL;
+
+ dev->ctl_aoutput = INPUT(i)->aout;
if (!dev->ctl_aoutput)
dev->ctl_aoutput = EM28XX_AOUT_MASTER;
+ em28xx_videodbg("%s: set audio input to %d\n", __func__,
+ dev->ctl_ainput);
+
return 0;
}
@@ -1776,7 +1845,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (t->index != 0)
return -EINVAL;
- strcpy(t->name, "Tuner");
+ strscpy(t->name, "Tuner", sizeof(t->name));
v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
return 0;
@@ -1833,9 +1902,9 @@ static int vidioc_g_chip_info(struct file *file, void *priv,
if (chip->match.addr > 1)
return -EINVAL;
if (chip->match.addr == 1)
- strlcpy(chip->name, "ac97", sizeof(chip->name));
+ strscpy(chip->name, "ac97", sizeof(chip->name));
else
- strlcpy(chip->name,
+ strscpy(chip->name,
dev->v4l2->v4l2_dev.name, sizeof(chip->name));
return 0;
}
@@ -1920,8 +1989,8 @@ static int vidioc_querycap(struct file *file, void *priv,
struct em28xx_v4l2 *v4l2 = dev->v4l2;
struct usb_device *udev = interface_to_usbdev(dev->intf);
- strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
- strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
+ strscpy(cap->driver, "em28xx", sizeof(cap->driver));
+ strscpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
usb_make_path(udev, cap->bus_info, sizeof(cap->bus_info));
if (vdev->vfl_type == VFL_TYPE_GRABBER)
@@ -1954,7 +2023,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (unlikely(f->index >= ARRAY_SIZE(format)))
return -EINVAL;
- strlcpy(f->description, format[f->index].name, sizeof(f->description));
+ strscpy(f->description, format[f->index].name, sizeof(f->description));
f->pixelformat = format[f->index].fourcc;
return 0;
@@ -2045,7 +2114,7 @@ static int radio_g_tuner(struct file *file, void *priv,
if (unlikely(t->index > 0))
return -EINVAL;
- strcpy(t->name, "Radio");
+ strscpy(t->name, "Radio", sizeof(t->name));
v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
@@ -2302,6 +2371,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
.vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
.vidioc_enum_framesizes = vidioc_enum_framesizes,
+ .vidioc_enumaudio = vidioc_enumaudio,
.vidioc_g_audio = vidioc_g_audio,
.vidioc_s_audio = vidioc_s_audio,
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 953caac025f2..a551072e62ed 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -335,6 +335,9 @@ enum em28xx_usb_audio_type {
/**
* em28xx_amux - describes the type of audio input used by em28xx
*
+ * @EM28XX_AMUX_UNUSED:
+ * Used only on em28xx dev->map field, in order to mark an entry
+ * as unused.
* @EM28XX_AMUX_VIDEO:
* On devices without AC97, this is the only value that it is currently
* allowed.
@@ -369,7 +372,8 @@ enum em28xx_usb_audio_type {
* same time, via the alsa mux.
*/
enum em28xx_amux {
- EM28XX_AMUX_VIDEO,
+ EM28XX_AMUX_UNUSED = -1,
+ EM28XX_AMUX_VIDEO = 0,
EM28XX_AMUX_LINE_IN,
/* Some less-common mixer setups */
@@ -692,6 +696,8 @@ struct em28xx {
unsigned int ctl_input; // selected input
unsigned int ctl_ainput;// selected audio input
unsigned int ctl_aoutput;// selected audio output
+ enum em28xx_amux amux_map[MAX_EM28XX_INPUT];
+
int mute;
int volume;
diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c
index 62aeebcdd7f7..59cf50355b4e 100644
--- a/drivers/media/usb/go7007/go7007-driver.c
+++ b/drivers/media/usb/go7007/go7007-driver.c
@@ -208,7 +208,7 @@ static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *con
struct i2c_board_info info;
memset(&info, 0, sizeof(info));
- strlcpy(info.type, i2c->type, sizeof(info.type));
+ strscpy(info.type, i2c->type, sizeof(info.type));
info.addr = i2c->addr;
info.flags = i2c->flags;
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index c55c82f70e54..7a2781fa83e7 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -284,9 +284,9 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct go7007 *go = video_drvdata(file);
- strlcpy(cap->driver, "go7007", sizeof(cap->driver));
- strlcpy(cap->card, go->name, sizeof(cap->card));
- strlcpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info));
+ strscpy(cap->driver, "go7007", sizeof(cap->driver));
+ strscpy(cap->card, go->name, sizeof(cap->card));
+ strscpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
@@ -634,8 +634,8 @@ static int vidioc_enum_input(struct file *file, void *priv,
if (inp->index >= go->board_info->num_inputs)
return -EINVAL;
- strlcpy(inp->name, go->board_info->inputs[inp->index].name,
- sizeof(inp->name));
+ strscpy(inp->name, go->board_info->inputs[inp->index].name,
+ sizeof(inp->name));
/* If this board has a tuner, it will be the first input */
if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
@@ -673,7 +673,7 @@ static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
if (a->index >= go->board_info->num_aud_inputs)
return -EINVAL;
- strlcpy(a->name, go->board_info->aud_inputs[a->index].name,
+ strscpy(a->name, go->board_info->aud_inputs[a->index].name,
sizeof(a->name));
a->capability = V4L2_AUDCAP_STEREO;
return 0;
@@ -684,7 +684,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
struct go7007 *go = video_drvdata(file);
a->index = go->aud_input;
- strlcpy(a->name, go->board_info->aud_inputs[go->aud_input].name,
+ strscpy(a->name, go->board_info->aud_inputs[go->aud_input].name,
sizeof(a->name));
a->capability = V4L2_AUDCAP_STEREO;
return 0;
@@ -742,7 +742,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (t->index != 0)
return -EINVAL;
- strlcpy(t->name, "Tuner", sizeof(t->name));
+ strscpy(t->name, "Tuner", sizeof(t->name));
return call_all(&go->v4l2_dev, tuner, g_tuner, t);
}
diff --git a/drivers/media/usb/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c
index 137fc253b122..fc84b37d5587 100644
--- a/drivers/media/usb/go7007/snd-go7007.c
+++ b/drivers/media/usb/go7007/snd-go7007.c
@@ -260,10 +260,10 @@ int go7007_snd_init(struct go7007 *go)
kfree(gosnd);
return ret;
}
- strlcpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver));
- strlcpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver));
- strlcpy(gosnd->card->longname, gosnd->card->shortname,
- sizeof(gosnd->card->longname));
+ strscpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver));
+ strscpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver));
+ strscpy(gosnd->card->longname, gosnd->card->shortname,
+ sizeof(gosnd->card->longname));
gosnd->pcm->private_data = go;
snd_pcm_set_ops(gosnd->pcm, SNDRV_PCM_STREAM_CAPTURE,
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index 57aa521e16b1..fce9d6f4b7c9 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -1193,11 +1193,11 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct gspca_dev *gspca_dev = video_drvdata(file);
- strlcpy((char *) cap->driver, gspca_dev->sd_desc->name,
- sizeof cap->driver);
+ strscpy((char *)cap->driver, gspca_dev->sd_desc->name,
+ sizeof(cap->driver));
if (gspca_dev->dev->product != NULL) {
- strlcpy((char *) cap->card, gspca_dev->dev->product,
- sizeof cap->card);
+ strscpy((char *)cap->card, gspca_dev->dev->product,
+ sizeof(cap->card));
} else {
snprintf((char *) cap->card, sizeof cap->card,
"USB Camera (%04x:%04x)",
@@ -1222,7 +1222,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
return -EINVAL;
input->type = V4L2_INPUT_TYPE_CAMERA;
input->status = gspca_dev->cam.input_flags;
- strlcpy(input->name, gspca_dev->sd_desc->name,
+ strscpy(input->name, gspca_dev->sd_desc->name,
sizeof input->name);
return 0;
}
diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c
index cfa2a04d9f3f..5984bb12bcff 100644
--- a/drivers/media/usb/gspca/sn9c20x.c
+++ b/drivers/media/usb/gspca/sn9c20x.c
@@ -1601,7 +1601,7 @@ static int sd_chip_info(struct gspca_dev *gspca_dev,
if (chip->match.addr > 1)
return -EINVAL;
if (chip->match.addr == 1)
- strlcpy(chip->name, "sensor", sizeof(chip->name));
+ strscpy(chip->name, "sensor", sizeof(chip->name));
return 0;
}
#endif
diff --git a/drivers/media/usb/gspca/sq930x.c b/drivers/media/usb/gspca/sq930x.c
index d7cbcf2b3947..e15b45f022e1 100644
--- a/drivers/media/usb/gspca/sq930x.c
+++ b/drivers/media/usb/gspca/sq930x.c
@@ -1044,7 +1044,7 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev)
v4l2_ctrl_g_ctrl(sd->gain));
gspca_dev->cam.bulk_nurbs = 1;
- ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC);
+ ret = usb_submit_urb(gspca_dev->urb[0], GFP_KERNEL);
if (ret < 0)
pr_err("sd_dq_callback() err %d\n", ret);
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index 34085a0b15a1..d43785206622 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -918,8 +918,8 @@ static int hackrf_querycap(struct file *file, void *fh,
cap->capabilities = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR |
V4L2_CAP_DEVICE_CAPS | cap->device_caps;
- strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
- strlcpy(cap->card, dev->rx_vdev.name, sizeof(cap->card));
+ strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+ strscpy(cap->card, dev->rx_vdev.name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
return 0;
@@ -1041,14 +1041,14 @@ static int hackrf_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
dev_dbg(dev->dev, "index=%d\n", v->index);
if (v->index == 0) {
- strlcpy(v->name, "HackRF ADC", sizeof(v->name));
+ strscpy(v->name, "HackRF ADC", sizeof(v->name));
v->type = V4L2_TUNER_SDR;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = bands_adc_dac[0].rangelow;
v->rangehigh = bands_adc_dac[0].rangehigh;
ret = 0;
} else if (v->index == 1) {
- strlcpy(v->name, "HackRF RF", sizeof(v->name));
+ strscpy(v->name, "HackRF RF", sizeof(v->name));
v->type = V4L2_TUNER_RF;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = bands_rx_tx[0].rangelow;
@@ -1080,14 +1080,14 @@ static int hackrf_g_modulator(struct file *file, void *fh,
dev_dbg(dev->dev, "index=%d\n", a->index);
if (a->index == 0) {
- strlcpy(a->name, "HackRF DAC", sizeof(a->name));
+ strscpy(a->name, "HackRF DAC", sizeof(a->name));
a->type = V4L2_TUNER_SDR;
a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
a->rangelow = bands_adc_dac[0].rangelow;
a->rangehigh = bands_adc_dac[0].rangehigh;
ret = 0;
} else if (a->index == 1) {
- strlcpy(a->name, "HackRF RF", sizeof(a->name));
+ strscpy(a->name, "HackRF RF", sizeof(a->name));
a->type = V4L2_TUNER_RF;
a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
a->rangelow = bands_rx_tx[0].rangelow;
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
index 1b89c77bad66..e082086428a4 100644
--- a/drivers/media/usb/hdpvr/hdpvr-video.c
+++ b/drivers/media/usb/hdpvr/hdpvr-video.c
@@ -578,8 +578,8 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct hdpvr_device *dev = video_drvdata(file);
- strcpy(cap->driver, "hdpvr");
- strcpy(cap->card, "Hauppauge HD PVR");
+ strscpy(cap->driver, "hdpvr", sizeof(cap->driver));
+ strscpy(cap->card, "Hauppauge HD PVR", sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO |
V4L2_CAP_READWRITE;
@@ -873,7 +873,7 @@ static int vidioc_g_audio(struct file *file, void *private_data,
audio->index = dev->options.audio_input;
audio->capability = V4L2_AUDCAP_STEREO;
- strlcpy(audio->name, audio_iname[audio->index], sizeof(audio->name));
+ strscpy(audio->name, audio_iname[audio->index], sizeof(audio->name));
audio->name[sizeof(audio->name) - 1] = '\0';
return 0;
}
@@ -1238,7 +1238,8 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
/* setup and register video device */
dev->video_dev = hdpvr_video_template;
- strcpy(dev->video_dev.name, "Hauppauge HD PVR");
+ strscpy(dev->video_dev.name, "Hauppauge HD PVR",
+ sizeof(dev->video_dev.name));
dev->video_dev.v4l2_dev = &dev->v4l2_dev;
video_set_drvdata(&dev->video_dev, dev);
diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c
index 65ef755adfdc..0fc4076c6d16 100644
--- a/drivers/media/usb/msi2500/msi2500.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -604,8 +604,8 @@ static int msi2500_querycap(struct file *file, void *fh,
dev_dbg(dev->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;
@@ -916,7 +916,7 @@ static int msi2500_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;
@@ -1017,7 +1017,7 @@ static int msi2500_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
dev_dbg(dev->dev, "index=%d\n", v->index);
if (v->index == 0) {
- strlcpy(v->name, "Mirics MSi2500", sizeof(v->name));
+ strscpy(v->name, "Mirics MSi2500", sizeof(v->name));
v->type = V4L2_TUNER_ADC;
v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
v->rangelow = 1200000;
diff --git a/drivers/media/usb/pulse8-cec/pulse8-cec.c b/drivers/media/usb/pulse8-cec/pulse8-cec.c
index 350635826aae..365c78b748dd 100644
--- a/drivers/media/usb/pulse8-cec/pulse8-cec.c
+++ b/drivers/media/usb/pulse8-cec/pulse8-cec.c
@@ -571,7 +571,8 @@ static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
memset(osd_str + osd_len, ' ', 4 - osd_len);
osd_len = 4;
osd_str[osd_len] = '\0';
- strcpy(adap->log_addrs.osd_name, osd_str);
+ strscpy(adap->log_addrs.osd_name, osd_str,
+ sizeof(adap->log_addrs.osd_name));
}
err = pulse8_send_and_wait(pulse8, cmd, 1 + osd_len,
MSGCODE_COMMAND_ACCEPTED, 0);
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-debug.h b/drivers/media/usb/pvrusb2/pvrusb2-debug.h
index 5cd16292e2fa..1323f949f454 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-debug.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-debug.h
@@ -17,7 +17,7 @@
extern int pvrusb2_debug;
-#define pvr2_trace(msk, fmt, arg...) do {if(msk & pvrusb2_debug) printk(KERN_INFO "pvrusb2: " fmt "\n", ##arg); } while (0)
+#define pvr2_trace(msk, fmt, arg...) do {if (msk & pvrusb2_debug) pr_info("pvrusb2: " fmt "\n", ##arg); } while (0)
/* These are listed in *rough* order of decreasing usefulness and
increasing noise level. */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index a8519da0020b..7702285c1519 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -3293,12 +3293,12 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
int nr = pvr2_hdw_get_unit_number(hdw);
LOCK_TAKE(hdw->big_lock);
do {
- printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr);
+ pr_info("pvrusb2: ================= START STATUS CARD #%d =================\n", nr);
v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status);
pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
pvr2_hdw_state_log_state(hdw);
- printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr);
+ pr_info("pvrusb2: ================== END STATUS CARD #%d ==================\n", nr);
} while (0);
LOCK_GIVE(hdw->big_lock);
}
@@ -4851,7 +4851,7 @@ static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw)
for (idx = 0; ; idx++) {
ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf));
if (!ccnt) break;
- printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf);
+ pr_info("%s %.*s\n", hdw->name, ccnt, buf);
}
ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf));
if (ccnt >= sizeof(buf))
@@ -4863,7 +4863,7 @@ static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw)
while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) {
lcnt++;
}
- printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt);
+ pr_info("%s %.*s\n", hdw->name, lcnt, buf + ucnt);
ucnt += lcnt + 1;
}
}
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
index f3003ca05f4b..8f023085c2d9 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
@@ -478,8 +478,7 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
unsigned int idx,offs,cnt;
for (idx = 0; idx < num; idx++) {
cnt = msgs[idx].len;
- printk(KERN_INFO
- "pvrusb2 i2c xfer %u/%u: addr=0x%x len=%d %s",
+ pr_info("pvrusb2 i2c xfer %u/%u: addr=0x%x len=%d %s",
idx+1,num,
msgs[idx].addr,
cnt,
@@ -487,22 +486,21 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
"read" : "write"));
if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) {
if (cnt > 8) cnt = 8;
- printk(KERN_CONT " [");
+ pr_cont(" [");
for (offs = 0; offs < cnt; offs++) {
- if (offs) printk(KERN_CONT " ");
- printk(KERN_CONT "%02x",msgs[idx].buf[offs]);
+ if (offs) pr_cont(" ");
+ pr_cont("%02x", msgs[idx].buf[offs]);
}
- if (offs < cnt) printk(KERN_CONT " ...");
- printk(KERN_CONT "]");
+ if (offs < cnt) pr_cont(" ...");
+ pr_cont("]");
}
if (idx+1 == num) {
- printk(KERN_CONT " result=%d",ret);
+ pr_cont(" result=%d", ret);
}
- printk(KERN_CONT "\n");
+ pr_cont("\n");
}
if (!num) {
- printk(KERN_INFO
- "pvrusb2 i2c xfer null transfer result=%d\n",
+ pr_info("pvrusb2 i2c xfer null transfer result=%d\n",
ret);
}
}
@@ -542,14 +540,14 @@ static int do_i2c_probe(struct pvr2_hdw *hdw, int addr)
static void do_i2c_scan(struct pvr2_hdw *hdw)
{
int i;
- printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name);
+ pr_info("%s: i2c scan beginning\n", hdw->name);
for (i = 0; i < 128; i++) {
if (do_i2c_probe(hdw, i)) {
- printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n",
+ pr_info("%s: i2c scan: found device @ 0x%x\n",
hdw->name, i);
}
}
- printk(KERN_INFO "%s: i2c scan done.\n", hdw->name);
+ pr_info("%s: i2c scan done.\n", hdw->name);
}
static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
@@ -573,7 +571,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
/* IR Receiver */
info.addr = 0x18;
info.platform_data = init_data;
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ strscpy(info.type, "ir_video", I2C_NAME_SIZE);
pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
info.type, info.addr);
i2c_new_device(&hdw->i2c_adap, &info);
@@ -588,7 +586,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
/* IR Transceiver */
info.addr = 0x71;
info.platform_data = init_data;
- strlcpy(info.type, "ir_z8f0811_haup", I2C_NAME_SIZE);
+ strscpy(info.type, "ir_z8f0811_haup", I2C_NAME_SIZE);
pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
info.type, info.addr);
i2c_new_device(&hdw->i2c_adap, &info);
@@ -612,7 +610,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
/* However, deal with various special cases for 24xxx hardware. */
if (ir_mode[hdw->unit_number] == 0) {
- printk(KERN_INFO "%s: IR disabled\n",hdw->name);
+ pr_info("%s: IR disabled\n", hdw->name);
hdw->i2c_func[0x18] = i2c_black_hole;
} else if (ir_mode[hdw->unit_number] == 1) {
if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) {
@@ -631,7 +629,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
// Configure the adapter and set up everything else related to it.
hdw->i2c_adap = pvr2_i2c_adap_template;
hdw->i2c_algo = pvr2_i2c_algo_template;
- strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name));
+ strscpy(hdw->i2c_adap.name, hdw->name, sizeof(hdw->i2c_adap.name));
hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
hdw->i2c_adap.algo = &hdw->i2c_algo;
hdw->i2c_adap.algo_data = hdw;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-main.c b/drivers/media/usb/pvrusb2/pvrusb2-main.c
index cbe2c3a22458..23672dd352f5 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-main.c
@@ -132,10 +132,10 @@ static int __init pvr_init(void)
ret = usb_register(&pvr_driver);
if (ret == 0)
- printk(KERN_INFO "pvrusb2: " DRIVER_VERSION ":"
+ pr_info("pvrusb2: " DRIVER_VERSION ":"
DRIVER_DESC "\n");
if (pvrusb2_debug)
- printk(KERN_INFO "pvrusb2: Debug mask is %d (0x%x)\n",
+ pr_info("pvrusb2: Debug mask is %d (0x%x)\n",
pvrusb2_debug,pvrusb2_debug);
pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
index e53a80b589a1..97a93ed4bcda 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
@@ -121,10 +121,10 @@ static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
- strlcpy(cap->driver, "pvrusb2", sizeof(cap->driver));
- strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
- sizeof(cap->bus_info));
- strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
+ strscpy(cap->driver, "pvrusb2", sizeof(cap->driver));
+ strscpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
+ sizeof(cap->bus_info));
+ strscpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS;
@@ -545,7 +545,7 @@ static int pvr2_queryctrl(struct file *file, void *priv,
"QUERYCTRL id=0x%x mapping name=%s (%s)",
vc->id, pvr2_ctrl_get_name(cptr),
pvr2_ctrl_get_desc(cptr));
- strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
+ strscpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
vc->flags = pvr2_ctrl_get_v4lflags(cptr);
pvr2_ctrl_get_def(cptr, &val);
vc->default_value = val;
@@ -869,7 +869,7 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
are gone. */
video_unregister_device(&dip->devbase);
- printk(KERN_INFO "%s\n", msg);
+ pr_info("%s\n", msg);
}
@@ -1260,7 +1260,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
": Failed to register pvrusb2 v4l device\n");
}
- printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
+ pr_info("pvrusb2: registered device %s [%s]\n",
video_device_node_name(&dip->devbase),
pvr2_config_get_name(dip->config));
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index 54b036d39c5b..72704f4d5330 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -1027,7 +1027,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
/* Init video_device structure */
pdev->vdev = pwc_template;
- strcpy(pdev->vdev.name, name);
+ strscpy(pdev->vdev.name, name, sizeof(pdev->vdev.name));
pdev->vdev.queue = &pdev->vb_queue;
pdev->vdev.queue->lock = &pdev->vb_queue_lock;
video_set_drvdata(&pdev->vdev, pdev);
diff --git a/drivers/media/usb/pwc/pwc-v4l.c b/drivers/media/usb/pwc/pwc-v4l.c
index 043b2b97cee6..bef6e4ef8a7e 100644
--- a/drivers/media/usb/pwc/pwc-v4l.c
+++ b/drivers/media/usb/pwc/pwc-v4l.c
@@ -492,8 +492,8 @@ static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap
{
struct pwc_device *pdev = video_drvdata(file);
- strcpy(cap->driver, PWC_NAME);
- strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card));
+ strscpy(cap->driver, PWC_NAME, sizeof(cap->driver));
+ strscpy(cap->card, pdev->vdev.name, sizeof(cap->card));
usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
V4L2_CAP_READWRITE;
@@ -506,7 +506,7 @@ static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
if (i->index) /* Only one INPUT is supported */
return -EINVAL;
- strlcpy(i->name, "Camera", sizeof(i->name));
+ strscpy(i->name, "Camera", sizeof(i->name));
i->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
}
@@ -889,11 +889,13 @@ static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc
/* RAW format */
f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2;
f->flags = V4L2_FMT_FLAG_COMPRESSED;
- strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description));
+ strscpy(f->description, "Raw Philips Webcam",
+ sizeof(f->description));
break;
case 1:
f->pixelformat = V4L2_PIX_FMT_YUV420;
- strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description));
+ strscpy(f->description, "4:2:0, planar, Y-Cb-Cr",
+ sizeof(f->description));
break;
default:
return -EINVAL;
diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
index cecdcbcd400c..d9964da05976 100644
--- a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
+++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
@@ -141,7 +141,8 @@ static void rain_irq_work_handler(struct work_struct *work)
!memcmp(rain->cmd, "STA", 3)) {
rain_process_msg(rain);
} else {
- strcpy(rain->cmd_reply, rain->cmd);
+ strscpy(rain->cmd_reply, rain->cmd,
+ sizeof(rain->cmd_reply));
complete(&rain->cmd_done);
}
rain->cmd_idx = 0;
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index 82927eb334c4..5b3e54b76e9a 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -730,8 +730,8 @@ static int vidioc_querycap(struct file *file, void *priv,
struct s2255_vc *vc = video_drvdata(file);
struct s2255_dev *dev = vc->dev;
- strlcpy(cap->driver, "s2255", sizeof(cap->driver));
- strlcpy(cap->card, "s2255", sizeof(cap->card));
+ strscpy(cap->driver, "s2255", sizeof(cap->driver));
+ strscpy(cap->card, "s2255", sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
V4L2_CAP_READWRITE;
@@ -749,7 +749,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) ||
(formats[index].fourcc == V4L2_PIX_FMT_MJPEG)))
return -EINVAL;
- strlcpy(f->description, formats[index].name, sizeof(f->description));
+ strscpy(f->description, formats[index].name, sizeof(f->description));
f->pixelformat = formats[index].fourcc;
return 0;
}
@@ -1195,10 +1195,10 @@ static int vidioc_enum_input(struct file *file, void *priv,
switch (dev->pid) {
case 0x2255:
default:
- strlcpy(inp->name, "Composite", sizeof(inp->name));
+ strscpy(inp->name, "Composite", sizeof(inp->name));
break;
case 0x2257:
- strlcpy(inp->name, (vc->idx < 2) ? "Composite" : "S-Video",
+ strscpy(inp->name, (vc->idx < 2) ? "Composite" : "S-Video",
sizeof(inp->name));
break;
}
diff --git a/drivers/media/usb/stk1160/stk1160-i2c.c b/drivers/media/usb/stk1160/stk1160-i2c.c
index 62a12d5356ad..c3a15564e5cb 100644
--- a/drivers/media/usb/stk1160/stk1160-i2c.c
+++ b/drivers/media/usb/stk1160/stk1160-i2c.c
@@ -260,7 +260,7 @@ int stk1160_i2c_register(struct stk1160 *dev)
dev->i2c_adap = adap_template;
dev->i2c_adap.dev.parent = dev->dev;
- strcpy(dev->i2c_adap.name, "stk1160");
+ strscpy(dev->i2c_adap.name, "stk1160", sizeof(dev->i2c_adap.name));
dev->i2c_adap.algo_data = dev;
i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index 504e413edcd2..701ed3d4afe6 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -344,8 +344,8 @@ static int vidioc_querycap(struct file *file,
{
struct stk1160 *dev = video_drvdata(file);
- strcpy(cap->driver, "stk1160");
- strcpy(cap->card, "stk1160");
+ strscpy(cap->driver, "stk1160", sizeof(cap->driver));
+ strscpy(cap->card, "stk1160", sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps =
V4L2_CAP_VIDEO_CAPTURE |
@@ -361,7 +361,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (f->index != 0)
return -EINVAL;
- strlcpy(f->description, format[f->index].name, sizeof(f->description));
+ strscpy(f->description, format[f->index].name, sizeof(f->description));
f->pixelformat = format[f->index].fourcc;
return 0;
}
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index 5accb5241072..e11d5d5b7c26 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -793,8 +793,8 @@ static int stk_vidioc_querycap(struct file *filp,
{
struct stk_camera *dev = video_drvdata(filp);
- strcpy(cap->driver, "stk");
- strcpy(cap->card, "stk");
+ strscpy(cap->driver, "stk", sizeof(cap->driver));
+ strscpy(cap->card, "stk", sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
@@ -809,7 +809,7 @@ static int stk_vidioc_enum_input(struct file *filp,
if (input->index != 0)
return -EINVAL;
- strcpy(input->name, "Syntek USB Camera");
+ strscpy(input->name, "Syntek USB Camera", sizeof(input->name));
input->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
}
@@ -859,23 +859,23 @@ static int stk_vidioc_enum_fmt_vid_cap(struct file *filp,
switch (fmtd->index) {
case 0:
fmtd->pixelformat = V4L2_PIX_FMT_RGB565;
- strcpy(fmtd->description, "r5g6b5");
+ strscpy(fmtd->description, "r5g6b5", sizeof(fmtd->description));
break;
case 1:
fmtd->pixelformat = V4L2_PIX_FMT_RGB565X;
- strcpy(fmtd->description, "r5g6b5BE");
+ strscpy(fmtd->description, "r5g6b5BE", sizeof(fmtd->description));
break;
case 2:
fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
- strcpy(fmtd->description, "yuv4:2:2");
+ strscpy(fmtd->description, "yuv4:2:2", sizeof(fmtd->description));
break;
case 3:
fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8;
- strcpy(fmtd->description, "Raw bayer");
+ strscpy(fmtd->description, "Raw bayer", sizeof(fmtd->description));
break;
case 4:
fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
- strcpy(fmtd->description, "yuv4:2:2");
+ strscpy(fmtd->description, "yuv4:2:2", sizeof(fmtd->description));
break;
default:
return -EINVAL;
diff --git a/drivers/media/usb/tm6000/tm6000-alsa.c b/drivers/media/usb/tm6000/tm6000-alsa.c
index f18cffae4c85..b965931793b5 100644
--- a/drivers/media/usb/tm6000/tm6000-alsa.c
+++ b/drivers/media/usb/tm6000/tm6000-alsa.c
@@ -429,8 +429,8 @@ static int tm6000_audio_init(struct tm6000_core *dev)
snd_printk(KERN_ERR "cannot create card instance %d\n", devnr);
return rc;
}
- strcpy(card->driver, "tm6000-alsa");
- strcpy(card->shortname, "TM5600/60x0");
+ strscpy(card->driver, "tm6000-alsa", sizeof(card->driver));
+ strscpy(card->shortname, "TM5600/60x0", sizeof(card->shortname));
sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d",
dev->udev->bus->busnum, dev->udev->devnum);
@@ -456,7 +456,7 @@ static int tm6000_audio_init(struct tm6000_core *dev)
pcm->info_flags = 0;
pcm->private_data = chip;
- strcpy(pcm->name, "Trident TM5600/60x0");
+ strscpy(pcm->name, "Trident TM5600/60x0", sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops);
diff --git a/drivers/media/usb/tm6000/tm6000-i2c.c b/drivers/media/usb/tm6000/tm6000-i2c.c
index ccd1adf862b1..8c0476dfe54f 100644
--- a/drivers/media/usb/tm6000/tm6000-i2c.c
+++ b/drivers/media/usb/tm6000/tm6000-i2c.c
@@ -292,7 +292,7 @@ int tm6000_i2c_register(struct tm6000_core *dev)
dev->i2c_adap.owner = THIS_MODULE;
dev->i2c_adap.algo = &tm6000_algo;
dev->i2c_adap.dev.parent = &dev->udev->dev;
- strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
+ strscpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
dev->i2c_adap.algo_data = dev;
i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
rc = i2c_add_adapter(&dev->i2c_adap);
@@ -300,7 +300,7 @@ int tm6000_i2c_register(struct tm6000_core *dev)
return rc;
dev->i2c_client.adapter = &dev->i2c_adap;
- strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
+ strscpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
tm6000_i2c_eeprom(dev);
return 0;
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index 7d268f2404e1..6c992f197255 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -856,8 +856,9 @@ static int vidioc_querycap(struct file *file, void *priv,
struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
struct video_device *vdev = video_devdata(file);
- strlcpy(cap->driver, "tm6000", sizeof(cap->driver));
- strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card));
+ strscpy(cap->driver, "tm6000", sizeof(cap->driver));
+ strscpy(cap->card, "Trident TVMaster TM5600/6000/6010",
+ sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
if (dev->tuner_type != TUNER_ABSENT)
cap->device_caps |= V4L2_CAP_TUNER;
@@ -879,7 +880,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (f->index >= ARRAY_SIZE(format))
return -EINVAL;
- strlcpy(f->description, format[f->index].name, sizeof(f->description));
+ strscpy(f->description, format[f->index].name, sizeof(f->description));
f->pixelformat = format[f->index].fourcc;
return 0;
}
@@ -1091,7 +1092,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
else
i->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(i->name, iname[dev->vinput[n].type]);
+ strscpy(i->name, iname[dev->vinput[n].type], sizeof(i->name));
i->std = TM6000_STD;
@@ -1188,7 +1189,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (0 != t->index)
return -EINVAL;
- strcpy(t->name, "Television");
+ strscpy(t->name, "Television", sizeof(t->name));
t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
t->rangehigh = 0xffffffffUL;
@@ -1268,7 +1269,7 @@ static int radio_g_tuner(struct file *file, void *priv,
return -EINVAL;
memset(t, 0, sizeof(*t));
- strcpy(t->name, "Radio");
+ strscpy(t->name, "Radio", sizeof(t->name));
t->type = V4L2_TUNER_RADIO;
t->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
t->rxsubchans = V4L2_TUNER_SUB_STEREO;
diff --git a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
index eed56895c2b9..6eb84cf007b4 100644
--- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
@@ -1686,7 +1686,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
/* i2c */
memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter));
- strcpy(ttusb->i2c_adap.name, "TTUSB DEC");
+ strscpy(ttusb->i2c_adap.name, "TTUSB DEC", sizeof(ttusb->i2c_adap.name));
i2c_set_adapdata(&ttusb->i2c_adap, ttusb);
diff --git a/drivers/media/usb/usbtv/usbtv-audio.c b/drivers/media/usb/usbtv/usbtv-audio.c
index 4ce38246ed64..6f108996142d 100644
--- a/drivers/media/usb/usbtv/usbtv-audio.c
+++ b/drivers/media/usb/usbtv/usbtv-audio.c
@@ -358,8 +358,8 @@ int usbtv_audio_init(struct usbtv *usbtv)
if (rv < 0)
return rv;
- strlcpy(card->driver, usbtv->dev->driver->name, sizeof(card->driver));
- strlcpy(card->shortname, "usbtv", sizeof(card->shortname));
+ strscpy(card->driver, usbtv->dev->driver->name, sizeof(card->driver));
+ strscpy(card->shortname, "usbtv", sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname),
"USBTV Audio at bus %d device %d", usbtv->udev->bus->busnum,
usbtv->udev->devnum);
@@ -372,7 +372,7 @@ int usbtv_audio_init(struct usbtv *usbtv)
if (rv < 0)
goto err;
- strlcpy(pcm->name, "USBTV Audio Input", sizeof(pcm->name));
+ strscpy(pcm->name, "USBTV Audio Input", sizeof(pcm->name));
pcm->info_flags = 0;
pcm->private_data = usbtv;
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index 36a9a4017185..4a1eab711bdc 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -600,8 +600,8 @@ static int usbtv_querycap(struct file *file, void *priv,
{
struct usbtv *dev = video_drvdata(file);
- strlcpy(cap->driver, "usbtv", sizeof(cap->driver));
- strlcpy(cap->card, "usbtv", sizeof(cap->card));
+ strscpy(cap->driver, "usbtv", sizeof(cap->driver));
+ strscpy(cap->card, "usbtv", sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE;
cap->device_caps |= V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
@@ -616,10 +616,10 @@ static int usbtv_enum_input(struct file *file, void *priv,
switch (i->index) {
case USBTV_COMPOSITE_INPUT:
- strlcpy(i->name, "Composite", sizeof(i->name));
+ strscpy(i->name, "Composite", sizeof(i->name));
break;
case USBTV_SVIDEO_INPUT:
- strlcpy(i->name, "S-Video", sizeof(i->name));
+ strscpy(i->name, "S-Video", sizeof(i->name));
break;
default:
return -EINVAL;
@@ -636,8 +636,8 @@ static int usbtv_enum_fmt_vid_cap(struct file *file, void *priv,
if (f->index > 0)
return -EINVAL;
- strlcpy(f->description, "16 bpp YUY2, 4:2:2, packed",
- sizeof(f->description));
+ strscpy(f->description, "16 bpp YUY2, 4:2:2, packed",
+ sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_YUYV;
return 0;
}
@@ -934,7 +934,7 @@ int usbtv_video_init(struct usbtv *usbtv)
}
/* Video structure */
- strlcpy(usbtv->vdev.name, "usbtv", sizeof(usbtv->vdev.name));
+ strscpy(usbtv->vdev.name, "usbtv", sizeof(usbtv->vdev.name));
usbtv->vdev.v4l2_dev = &usbtv->v4l2_dev;
usbtv->vdev.release = video_device_release_empty;
usbtv->vdev.fops = &usbtv_fops;
diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c
index 7138c2b606cc..31e0e98d6daf 100644
--- a/drivers/media/usb/usbvision/usbvision-core.c
+++ b/drivers/media/usb/usbvision/usbvision-core.c
@@ -1272,7 +1272,6 @@ static void usbvision_isoc_irq(struct urb *urb)
int len;
struct usb_usbvision *usbvision = urb->context;
int i;
- unsigned long start_time = jiffies;
struct usbvision_frame **f;
/* We don't want to do anything if we are about to be removed! */
@@ -1324,8 +1323,6 @@ static void usbvision_isoc_irq(struct urb *urb)
scratch_reset(usbvision);
}
- usbvision->time_in_irq += jiffies - start_time;
-
for (i = 0; i < USBVISION_URB_FRAMES; i++) {
urb->iso_frame_desc[i].status = 0;
urb->iso_frame_desc[i].actual_length = 0;
diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
index f29d1bef0293..dd2ff8ed6c6a 100644
--- a/drivers/media/usb/usbvision/usbvision-video.c
+++ b/drivers/media/usb/usbvision/usbvision-video.c
@@ -467,8 +467,8 @@ static int vidioc_querycap(struct file *file, void *priv,
struct usb_usbvision *usbvision = video_drvdata(file);
struct video_device *vdev = video_devdata(file);
- strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
- strlcpy(vc->card,
+ strscpy(vc->driver, "USBVision", sizeof(vc->driver));
+ strscpy(vc->card,
usbvision_device_data[usbvision->dev_model].model_string,
sizeof(vc->card));
usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
@@ -504,9 +504,9 @@ static int vidioc_enum_input(struct file *file, void *priv,
switch (chan) {
case 0:
if (usbvision_device_data[usbvision->dev_model].video_channels == 4) {
- strcpy(vi->name, "White Video Input");
+ strscpy(vi->name, "White Video Input", sizeof(vi->name));
} else {
- strcpy(vi->name, "Television");
+ strscpy(vi->name, "Television", sizeof(vi->name));
vi->type = V4L2_INPUT_TYPE_TUNER;
vi->tuner = chan;
vi->std = USBVISION_NORMS;
@@ -515,22 +515,23 @@ static int vidioc_enum_input(struct file *file, void *priv,
case 1:
vi->type = V4L2_INPUT_TYPE_CAMERA;
if (usbvision_device_data[usbvision->dev_model].video_channels == 4)
- strcpy(vi->name, "Green Video Input");
+ strscpy(vi->name, "Green Video Input", sizeof(vi->name));
else
- strcpy(vi->name, "Composite Video Input");
+ strscpy(vi->name, "Composite Video Input",
+ sizeof(vi->name));
vi->std = USBVISION_NORMS;
break;
case 2:
vi->type = V4L2_INPUT_TYPE_CAMERA;
if (usbvision_device_data[usbvision->dev_model].video_channels == 4)
- strcpy(vi->name, "Yellow Video Input");
+ strscpy(vi->name, "Yellow Video Input", sizeof(vi->name));
else
- strcpy(vi->name, "S-Video Input");
+ strscpy(vi->name, "S-Video Input", sizeof(vi->name));
vi->std = USBVISION_NORMS;
break;
case 3:
vi->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(vi->name, "Red Video Input");
+ strscpy(vi->name, "Red Video Input", sizeof(vi->name));
vi->std = USBVISION_NORMS;
break;
}
@@ -589,9 +590,9 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (vt->index) /* Only tuner 0 */
return -EINVAL;
if (vt->type == V4L2_TUNER_RADIO)
- strcpy(vt->name, "Radio");
+ strscpy(vt->name, "Radio", sizeof(vt->name));
else
- strcpy(vt->name, "Television");
+ strscpy(vt->name, "Television", sizeof(vt->name));
/* Let clients fill in the remainder of this struct */
call_all(usbvision, tuner, g_tuner, vt);
@@ -814,7 +815,8 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
{
if (vfd->index >= USBVISION_SUPPORTED_PALETTES - 1)
return -EINVAL;
- strcpy(vfd->description, usbvision_v4l2_format[vfd->index].desc);
+ strscpy(vfd->description, usbvision_v4l2_format[vfd->index].desc,
+ sizeof(vfd->description));
vfd->pixelformat = usbvision_v4l2_format[vfd->index].format;
return 0;
}
diff --git a/drivers/media/usb/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h
index 6ecdcd58248f..017e7baf5747 100644
--- a/drivers/media/usb/usbvision/usbvision.h
+++ b/drivers/media/usb/usbvision/usbvision.h
@@ -447,7 +447,6 @@ struct usb_usbvision {
unsigned long isoc_skip_count; /* How many empty ISO packets received */
unsigned long isoc_err_count; /* How many bad ISO packets received */
unsigned long isoc_packet_count; /* How many packets we totally got */
- unsigned long time_in_irq; /* How long do we need for interrupt */
int isoc_measure_bandwidth_count;
int frame_num; /* How many video frames we send to user */
int max_strip_len; /* How big is the biggest strip */
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index c2ad102bd693..d45415cbe6e7 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -38,7 +38,7 @@
* Controls
*/
-static struct uvc_control_info uvc_ctrls[] = {
+static const struct uvc_control_info uvc_ctrls[] = {
{
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_BRIGHTNESS_CONTROL,
@@ -354,13 +354,13 @@ static struct uvc_control_info uvc_ctrls[] = {
},
};
-static struct uvc_menu_info power_line_frequency_controls[] = {
+static const struct uvc_menu_info power_line_frequency_controls[] = {
{ 0, "Disabled" },
{ 1, "50 Hz" },
{ 2, "60 Hz" },
};
-static struct uvc_menu_info exposure_auto_controls[] = {
+static const struct uvc_menu_info exposure_auto_controls[] = {
{ 2, "Auto Mode" },
{ 1, "Manual Mode" },
{ 4, "Shutter Priority Mode" },
@@ -421,7 +421,7 @@ static void uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping,
data[first+1] = min_t(int, abs(value), 0xff);
}
-static struct uvc_control_mapping uvc_ctrl_mappings[] = {
+static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
{
.id = V4L2_CID_BRIGHTNESS,
.name = "Brightness",
@@ -978,7 +978,7 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping,
s32 value = mapping->get(mapping, UVC_GET_CUR, data);
if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
- struct uvc_menu_info *menu = mapping->menu_info;
+ const struct uvc_menu_info *menu = mapping->menu_info;
unsigned int i;
for (i = 0; i < mapping->menu_count; ++i, ++menu) {
@@ -1025,13 +1025,13 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
{
struct uvc_control_mapping *master_map = NULL;
struct uvc_control *master_ctrl = NULL;
- struct uvc_menu_info *menu;
+ const struct uvc_menu_info *menu;
unsigned int i;
memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl));
v4l2_ctrl->id = mapping->id;
v4l2_ctrl->type = mapping->v4l2_type;
- strlcpy(v4l2_ctrl->name, mapping->name, sizeof(v4l2_ctrl->name));
+ strscpy(v4l2_ctrl->name, mapping->name, sizeof(v4l2_ctrl->name));
v4l2_ctrl->flags = 0;
if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR))
@@ -1145,7 +1145,7 @@ done:
int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
struct v4l2_querymenu *query_menu)
{
- struct uvc_menu_info *menu_info;
+ const struct uvc_menu_info *menu_info;
struct uvc_control_mapping *mapping;
struct uvc_control *ctrl;
u32 index = query_menu->index;
@@ -1191,7 +1191,7 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
}
}
- strlcpy(query_menu->name, menu_info->name, sizeof(query_menu->name));
+ strscpy(query_menu->name, menu_info->name, sizeof(query_menu->name));
done:
mutex_unlock(&chain->ctrl_mutex);
diff --git a/drivers/media/usb/uvc/uvc_debugfs.c b/drivers/media/usb/uvc/uvc_debugfs.c
index 368f8f8dfcb5..77e7c2419b9b 100644
--- a/drivers/media/usb/uvc/uvc_debugfs.c
+++ b/drivers/media/usb/uvc/uvc_debugfs.c
@@ -106,9 +106,6 @@ void uvc_debugfs_init_stream(struct uvc_streaming *stream)
void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream)
{
- if (stream->debugfs_dir == NULL)
- return;
-
debugfs_remove_recursive(stream->debugfs_dir);
stream->debugfs_dir = NULL;
}
@@ -128,6 +125,5 @@ void uvc_debugfs_init(void)
void uvc_debugfs_cleanup(void)
{
- if (uvc_debugfs_root_dir != NULL)
- debugfs_remove_recursive(uvc_debugfs_root_dir);
+ debugfs_remove_recursive(uvc_debugfs_root_dir);
}
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index d46dc432456c..bc369a0934a3 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -427,7 +427,7 @@ static int uvc_parse_format(struct uvc_device *dev,
fmtdesc = uvc_format_by_guid(&buffer[5]);
if (fmtdesc != NULL) {
- strlcpy(format->name, fmtdesc->name,
+ strscpy(format->name, fmtdesc->name,
sizeof(format->name));
format->fcc = fmtdesc->fcc;
} else {
@@ -445,7 +445,7 @@ static int uvc_parse_format(struct uvc_device *dev,
*/
if (dev->quirks & UVC_QUIRK_FORCE_Y8) {
if (format->fcc == V4L2_PIX_FMT_YUYV) {
- strlcpy(format->name, "Greyscale 8-bit (Y8 )",
+ strscpy(format->name, "Greyscale 8-bit (Y8 )",
sizeof(format->name));
format->fcc = V4L2_PIX_FMT_GREY;
format->bpp = 8;
@@ -471,7 +471,7 @@ static int uvc_parse_format(struct uvc_device *dev,
return -EINVAL;
}
- strlcpy(format->name, "MJPEG", sizeof(format->name));
+ strscpy(format->name, "MJPEG", sizeof(format->name));
format->fcc = V4L2_PIX_FMT_MJPEG;
format->flags = UVC_FMT_FLAG_COMPRESSED;
format->bpp = 0;
@@ -489,13 +489,13 @@ static int uvc_parse_format(struct uvc_device *dev,
switch (buffer[8] & 0x7f) {
case 0:
- strlcpy(format->name, "SD-DV", sizeof(format->name));
+ strscpy(format->name, "SD-DV", sizeof(format->name));
break;
case 1:
- strlcpy(format->name, "SDL-DV", sizeof(format->name));
+ strscpy(format->name, "SDL-DV", sizeof(format->name));
break;
case 2:
- strlcpy(format->name, "HD-DV", sizeof(format->name));
+ strscpy(format->name, "HD-DV", sizeof(format->name));
break;
default:
uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
@@ -914,7 +914,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
unsigned int size;
unsigned int i;
- extra_size = ALIGN(extra_size, sizeof(*entity->pads));
+ extra_size = roundup(extra_size, sizeof(*entity->pads));
num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads
+ num_inputs;
@@ -1932,7 +1932,7 @@ int uvc_register_video_device(struct uvc_device *dev,
break;
}
- strlcpy(vdev->name, dev->name, sizeof(vdev->name));
+ strscpy(vdev->name, dev->name, sizeof(vdev->name));
/*
* Set the driver data before calling video_register_device, otherwise
@@ -2027,10 +2027,9 @@ static int uvc_register_chains(struct uvc_device *dev)
#ifdef CONFIG_MEDIA_CONTROLLER
ret = uvc_mc_register_entities(chain);
- if (ret < 0) {
- uvc_printk(KERN_INFO, "Failed to register entites "
- "(%d).\n", ret);
- }
+ if (ret < 0)
+ uvc_printk(KERN_INFO,
+ "Failed to register entities (%d).\n", ret);
#endif
}
@@ -2041,10 +2040,7 @@ static int uvc_register_chains(struct uvc_device *dev)
* USB probe, disconnect, suspend and resume
*/
-struct uvc_device_info {
- u32 quirks;
- u32 meta_format;
-};
+static const struct uvc_device_info uvc_quirk_none = { 0 };
static int uvc_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -2053,7 +2049,6 @@ static int uvc_probe(struct usb_interface *intf,
struct uvc_device *dev;
const struct uvc_device_info *info =
(const struct uvc_device_info *)id->driver_info;
- u32 quirks = info ? info->quirks : 0;
int function;
int ret;
@@ -2080,13 +2075,12 @@ static int uvc_probe(struct usb_interface *intf,
dev->udev = usb_get_dev(udev);
dev->intf = usb_get_intf(intf);
dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
- dev->quirks = (uvc_quirks_param == -1)
- ? quirks : uvc_quirks_param;
- if (info)
- dev->meta_format = info->meta_format;
+ dev->info = info ? info : &uvc_quirk_none;
+ dev->quirks = uvc_quirks_param == -1
+ ? dev->info->quirks : uvc_quirks_param;
if (udev->product != NULL)
- strlcpy(dev->name, udev->product, sizeof(dev->name));
+ strscpy(dev->name, udev->product, sizeof(dev->name));
else
snprintf(dev->name, sizeof(dev->name),
"UVC Camera (%04x:%04x)",
@@ -2124,7 +2118,7 @@ static int uvc_probe(struct usb_interface *intf,
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct));
- if (dev->quirks != quirks) {
+ if (dev->quirks != dev->info->quirks) {
uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module "
"parameter for testing purpose.\n", dev->quirks);
uvc_printk(KERN_INFO, "Please report required quirks to the "
@@ -2134,11 +2128,11 @@ static int uvc_probe(struct usb_interface *intf,
/* Initialize the media device and register the V4L2 device. */
#ifdef CONFIG_MEDIA_CONTROLLER
dev->mdev.dev = &intf->dev;
- strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
+ strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
if (udev->serial)
- strlcpy(dev->mdev.serial, udev->serial,
+ strscpy(dev->mdev.serial, udev->serial,
sizeof(dev->mdev.serial));
- strcpy(dev->mdev.bus_info, udev->devpath);
+ strscpy(dev->mdev.bus_info, udev->devpath, sizeof(dev->mdev.bus_info));
dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
media_device_init(&dev->mdev);
@@ -2344,7 +2338,9 @@ static const struct uvc_device_info uvc_quirk_force_y8 = {
.quirks = UVC_QUIRK_FORCE_Y8,
};
-#define UVC_QUIRK_INFO(q) (kernel_ulong_t)&(struct uvc_device_info){.quirks = q}
+#define UVC_INFO_QUIRK(q) (kernel_ulong_t)&(struct uvc_device_info){.quirks = q}
+#define UVC_INFO_META(m) (kernel_ulong_t)&(struct uvc_device_info) \
+ {.meta_format = m}
/*
* The Logitech cameras listed below have their interface class set to
@@ -2453,7 +2449,7 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) },
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) },
/* Chicony CNF7129 (Asus EEE 100HE) */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2462,7 +2458,7 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_RESTRICT_FRAME_RATE) },
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_RESTRICT_FRAME_RATE) },
/* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2525,7 +2521,7 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_BUILTIN_ISIGHT) },
/* Apple Built-In iSight via iBridge */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
@@ -2607,7 +2603,7 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_PROBE_DEF) },
/* IMC Networks (Medion Akoya) */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
@@ -2707,7 +2703,7 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_PROBE_EXTRAFIELDS) },
/* Aveo Technology USB 2.0 Camera (Tasco USB Microscope) */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
@@ -2725,7 +2721,7 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_EXTRAFIELDS) },
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_EXTRAFIELDS) },
/* Manta MM-353 Plako */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2771,7 +2767,7 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_STATUS_INTERVAL) },
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_STATUS_INTERVAL) },
/* MSI StarCam 370i */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2798,7 +2794,7 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_IGNORE_SELECTOR_UNIT) },
/* Oculus VR Positional Tracker DK2 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
@@ -2818,6 +2814,15 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = (kernel_ulong_t)&uvc_quirk_force_y8 },
+ /* Intel RealSense D4M */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x8086,
+ .idProduct = 0x0b03,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
index 554063c07d7a..06bffdf8828b 100644
--- a/drivers/media/usb/uvc/uvc_entity.c
+++ b/drivers/media/usb/uvc/uvc_entity.c
@@ -79,7 +79,7 @@ static int uvc_mc_init_entity(struct uvc_video_chain *chain,
if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) {
v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops);
- strlcpy(entity->subdev.name, entity->name,
+ strscpy(entity->subdev.name, entity->name,
sizeof(entity->subdev.name));
ret = media_entity_pads_init(&entity->subdev.entity,
diff --git a/drivers/media/usb/uvc/uvc_metadata.c b/drivers/media/usb/uvc/uvc_metadata.c
index cd1aec19cc5b..5f535b515c23 100644
--- a/drivers/media/usb/uvc/uvc_metadata.c
+++ b/drivers/media/usb/uvc/uvc_metadata.c
@@ -33,8 +33,8 @@ static int uvc_meta_v4l2_querycap(struct file *file, void *fh,
struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
struct uvc_video_chain *chain = stream->chain;
- strlcpy(cap->driver, "uvcvideo", sizeof(cap->driver));
- strlcpy(cap->card, vfh->vdev->name, sizeof(cap->card));
+ strscpy(cap->driver, "uvcvideo", sizeof(cap->driver));
+ strscpy(cap->card, vfh->vdev->name, sizeof(cap->card));
usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
| chain->caps;
@@ -74,7 +74,8 @@ static int uvc_meta_v4l2_try_format(struct file *file, void *fh,
memset(fmt, 0, sizeof(*fmt));
- fmt->dataformat = fmeta == dev->meta_format ? fmeta : V4L2_META_FMT_UVC;
+ fmt->dataformat = fmeta == dev->info->meta_format
+ ? fmeta : V4L2_META_FMT_UVC;
fmt->buffersize = UVC_METATADA_BUF_SIZE;
return 0;
@@ -118,14 +119,14 @@ static int uvc_meta_v4l2_enum_formats(struct file *file, void *fh,
u32 index = fdesc->index;
if (fdesc->type != vfh->vdev->queue->type ||
- index > 1U || (index && !dev->meta_format))
+ index > 1U || (index && !dev->info->meta_format))
return -EINVAL;
memset(fdesc, 0, sizeof(*fdesc));
fdesc->type = vfh->vdev->queue->type;
fdesc->index = index;
- fdesc->pixelformat = index ? dev->meta_format : V4L2_META_FMT_UVC;
+ fdesc->pixelformat = index ? dev->info->meta_format : V4L2_META_FMT_UVC;
return 0;
}
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 18a7384b50ee..b26182ce7462 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -591,8 +591,8 @@ static int uvc_ioctl_querycap(struct file *file, void *fh,
struct uvc_video_chain *chain = handle->chain;
struct uvc_streaming *stream = handle->stream;
- strlcpy(cap->driver, "uvcvideo", sizeof(cap->driver));
- strlcpy(cap->card, vdev->name, sizeof(cap->card));
+ strscpy(cap->driver, "uvcvideo", sizeof(cap->driver));
+ strscpy(cap->card, vdev->name, sizeof(cap->card));
usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
| chain->caps;
@@ -618,7 +618,7 @@ static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream,
fmt->flags = 0;
if (format->flags & UVC_FMT_FLAG_COMPRESSED)
fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
- strlcpy(fmt->description, format->name, sizeof(fmt->description));
+ strscpy(fmt->description, format->name, sizeof(fmt->description));
fmt->description[sizeof(fmt->description) - 1] = 0;
fmt->pixelformat = format->fcc;
return 0;
@@ -859,7 +859,7 @@ static int uvc_ioctl_enum_input(struct file *file, void *fh,
memset(input, 0, sizeof(*input));
input->index = index;
- strlcpy(input->name, iterm->name, sizeof(input->name));
+ strscpy(input->name, iterm->name, sizeof(input->name));
if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
input->type = V4L2_INPUT_TYPE_CAMERA;
@@ -939,7 +939,7 @@ static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh,
qec->id = qc.id;
qec->type = qc.type;
- strlcpy(qec->name, qc.name, sizeof(qec->name));
+ strscpy(qec->name, qc.name, sizeof(qec->name));
qec->minimum = qc.minimum;
qec->maximum = qc.maximum;
qec->step = qc.step;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index e5f5d84f1d1d..591eae3d0b0d 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -234,7 +234,7 @@ struct uvc_control_mapping {
enum v4l2_ctrl_type v4l2_type;
u32 data_type;
- struct uvc_menu_info *menu_info;
+ const struct uvc_menu_info *menu_info;
u32 menu_count;
u32 master_id;
@@ -572,15 +572,21 @@ struct uvc_streaming {
} clock;
};
+struct uvc_device_info {
+ u32 quirks;
+ u32 meta_format;
+};
+
struct uvc_device {
struct usb_device *udev;
struct usb_interface *intf;
unsigned long warnings;
u32 quirks;
- u32 meta_format;
int intfnum;
char name[32];
+ const struct uvc_device_info *info;
+
struct mutex lock; /* Protects users */
unsigned int users;
atomic_t nmappings;
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
index b8886102c5ed..ab35554cbffa 100644
--- a/drivers/media/usb/zr364xx/zr364xx.c
+++ b/drivers/media/usb/zr364xx/zr364xx.c
@@ -702,9 +702,9 @@ static int zr364xx_vidioc_querycap(struct file *file, void *priv,
{
struct zr364xx_camera *cam = video_drvdata(file);
- strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
- strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
- strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
+ strscpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
+ strscpy(cap->card, cam->udev->product, sizeof(cap->card));
+ strscpy(cap->bus_info, dev_name(&cam->udev->dev),
sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
@@ -719,7 +719,7 @@ static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
{
if (i->index != 0)
return -EINVAL;
- strcpy(i->name, DRIVER_DESC " Camera");
+ strscpy(i->name, DRIVER_DESC " Camera", sizeof(i->name));
i->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
}
@@ -765,7 +765,7 @@ static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
if (f->index > 0)
return -EINVAL;
f->flags = V4L2_FMT_FLAG_COMPRESSED;
- strcpy(f->description, formats[0].name);
+ strscpy(f->description, formats[0].name, sizeof(f->description));
f->pixelformat = formats[0].fourcc;
return 0;
}
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index 7f858c39753c..03a340cb5a9b 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -94,9 +94,56 @@ static const struct v4l2_subdev_ops tuner_ops;
} while (0)
/*
- * Internal struct used inside the driver
+ * Internal enums/struct used inside the driver
*/
+/**
+ * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER
+ *
+ * @TUNER_PAD_RF_INPUT:
+ * Radiofrequency (RF) sink pad, usually linked to a RF connector entity.
+ * @TUNER_PAD_OUTPUT:
+ * tuner video output source pad. Contains the video chrominance
+ * and luminance or the hole bandwidth of the signal converted to
+ * an Intermediate Frequency (IF) or to baseband (on zero-IF tuners).
+ * @TUNER_PAD_AUD_OUT:
+ * Tuner audio output source pad. Tuners used to decode analog TV
+ * signals have an extra pad for audio output. Old tuners use an
+ * analog stage with a saw filter for the audio IF frequency. The
+ * output of the pad is, in this case, the audio IF, with should be
+ * decoded either by the bridge chipset (that's the case of cx2388x
+ * chipsets) or may require an external IF sound processor, like
+ * msp34xx. On modern silicon tuners, the audio IF decoder is usually
+ * incorporated at the tuner. On such case, the output of this pad
+ * is an audio sampled data.
+ * @TUNER_NUM_PADS:
+ * Number of pads of the tuner.
+ */
+enum tuner_pad_index {
+ TUNER_PAD_RF_INPUT,
+ TUNER_PAD_OUTPUT,
+ TUNER_PAD_AUD_OUT,
+ TUNER_NUM_PADS
+};
+
+/**
+ * enum if_vid_dec_pad_index - video IF-PLL pad index
+ * for MEDIA_ENT_F_IF_VID_DECODER
+ *
+ * @IF_VID_DEC_PAD_IF_INPUT:
+ * video Intermediate Frequency (IF) sink pad
+ * @IF_VID_DEC_PAD_OUT:
+ * IF-PLL video output source pad. Contains the video chrominance
+ * and luminance IF signals.
+ * @IF_VID_DEC_PAD_NUM_PADS:
+ * Number of pads of the video IF-PLL.
+ */
+enum if_vid_dec_pad_index {
+ IF_VID_DEC_PAD_IF_INPUT,
+ IF_VID_DEC_PAD_OUT,
+ IF_VID_DEC_PAD_NUM_PADS
+};
+
struct tuner {
/* device */
struct dvb_frontend fe;
@@ -685,15 +732,20 @@ register_client:
*/
if (t->type == TUNER_TDA9887) {
t->pad[IF_VID_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ t->pad[IF_VID_DEC_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
t->pad[IF_VID_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ t->pad[IF_VID_DEC_PAD_OUT].sig_type = PAD_SIGNAL_ANALOG;
ret = media_entity_pads_init(&t->sd.entity,
IF_VID_DEC_PAD_NUM_PADS,
&t->pad[0]);
t->sd.entity.function = MEDIA_ENT_F_IF_VID_DECODER;
} else {
t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ t->pad[TUNER_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
+ t->pad[TUNER_PAD_OUTPUT].sig_type = PAD_SIGNAL_ANALOG;
t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+ t->pad[TUNER_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO;
ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS,
&t->pad[0]);
t->sd.entity.function = MEDIA_ENT_F_TUNER;
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 2b08d03b251d..a6d91370838d 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -57,6 +57,7 @@ static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
{
#if IS_ENABLED(CONFIG_I2C)
struct i2c_client *client = i2c_verify_client(sd->dev);
+
return client &&
asd->match.i2c.adapter_id == client->adapter->nr &&
asd->match.i2c.address == client->addr;
@@ -89,10 +90,11 @@ static LIST_HEAD(subdev_list);
static LIST_HEAD(notifier_list);
static DEFINE_MUTEX(list_lock);
-static struct v4l2_async_subdev *v4l2_async_find_match(
- struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd)
+static struct v4l2_async_subdev *
+v4l2_async_find_match(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd)
{
- bool (*match)(struct v4l2_subdev *, struct v4l2_async_subdev *);
+ bool (*match)(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd);
struct v4l2_async_subdev *asd;
list_for_each_entry(asd, &notifier->waiting, list) {
@@ -124,9 +126,34 @@ static struct v4l2_async_subdev *v4l2_async_find_match(
return NULL;
}
+/* Compare two async sub-device descriptors for equivalence */
+static bool asd_equal(struct v4l2_async_subdev *asd_x,
+ struct v4l2_async_subdev *asd_y)
+{
+ if (asd_x->match_type != asd_y->match_type)
+ return false;
+
+ switch (asd_x->match_type) {
+ case V4L2_ASYNC_MATCH_DEVNAME:
+ return strcmp(asd_x->match.device_name,
+ asd_y->match.device_name) == 0;
+ case V4L2_ASYNC_MATCH_I2C:
+ return asd_x->match.i2c.adapter_id ==
+ asd_y->match.i2c.adapter_id &&
+ asd_x->match.i2c.address ==
+ asd_y->match.i2c.address;
+ case V4L2_ASYNC_MATCH_FWNODE:
+ return asd_x->match.fwnode == asd_y->match.fwnode;
+ default:
+ break;
+ }
+
+ return false;
+}
+
/* Find the sub-device notifier registered by a sub-device driver. */
-static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
- struct v4l2_subdev *sd)
+static struct v4l2_async_notifier *
+v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd)
{
struct v4l2_async_notifier *n;
@@ -138,8 +165,8 @@ static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
}
/* Get v4l2_device related to the notifier if one can be found. */
-static struct v4l2_device *v4l2_async_notifier_find_v4l2_dev(
- struct v4l2_async_notifier *notifier)
+static struct v4l2_device *
+v4l2_async_notifier_find_v4l2_dev(struct v4l2_async_notifier *notifier)
{
while (notifier->parent)
notifier = notifier->parent;
@@ -150,8 +177,8 @@ static struct v4l2_device *v4l2_async_notifier_find_v4l2_dev(
/*
* Return true if all child sub-device notifiers are complete, false otherwise.
*/
-static bool v4l2_async_notifier_can_complete(
- struct v4l2_async_notifier *notifier)
+static bool
+v4l2_async_notifier_can_complete(struct v4l2_async_notifier *notifier)
{
struct v4l2_subdev *sd;
@@ -174,8 +201,8 @@ static bool v4l2_async_notifier_can_complete(
* Complete the master notifier if possible. This is done when all async
* sub-devices have been bound; v4l2_device is also available then.
*/
-static int v4l2_async_notifier_try_complete(
- struct v4l2_async_notifier *notifier)
+static int
+v4l2_async_notifier_try_complete(struct v4l2_async_notifier *notifier)
{
/* Quick check whether there are still more sub-devices here. */
if (!list_empty(&notifier->waiting))
@@ -196,8 +223,8 @@ static int v4l2_async_notifier_try_complete(
return v4l2_async_notifier_call_complete(notifier);
}
-static int v4l2_async_notifier_try_all_subdevs(
- struct v4l2_async_notifier *notifier);
+static int
+v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier *notifier);
static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
struct v4l2_device *v4l2_dev,
@@ -243,8 +270,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
}
/* Test all async sub-devices in a notifier for a match. */
-static int v4l2_async_notifier_try_all_subdevs(
- struct v4l2_async_notifier *notifier)
+static int
+v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier *notifier)
{
struct v4l2_device *v4l2_dev =
v4l2_async_notifier_find_v4l2_dev(notifier);
@@ -281,14 +308,17 @@ again:
static void v4l2_async_cleanup(struct v4l2_subdev *sd)
{
v4l2_device_unregister_subdev(sd);
- /* Subdevice driver will reprobe and put the subdev back onto the list */
+ /*
+ * Subdevice driver will reprobe and put the subdev back
+ * onto the list
+ */
list_del_init(&sd->async_list);
sd->asd = NULL;
}
/* Unbind all sub-devices in the notifier tree. */
-static void v4l2_async_notifier_unbind_all_subdevs(
- struct v4l2_async_notifier *notifier)
+static void
+v4l2_async_notifier_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
{
struct v4l2_subdev *sd, *tmp;
@@ -308,29 +338,23 @@ static void v4l2_async_notifier_unbind_all_subdevs(
notifier->parent = NULL;
}
-/* See if an fwnode can be found in a notifier's lists. */
-static bool __v4l2_async_notifier_fwnode_has_async_subdev(
- struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode)
+/* See if an async sub-device can be found in a notifier's lists. */
+static bool
+__v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
+ struct v4l2_async_subdev *asd)
{
- struct v4l2_async_subdev *asd;
+ struct v4l2_async_subdev *asd_y;
struct v4l2_subdev *sd;
- list_for_each_entry(asd, &notifier->waiting, list) {
- if (asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
- continue;
-
- if (asd->match.fwnode == fwnode)
+ list_for_each_entry(asd_y, &notifier->waiting, list)
+ if (asd_equal(asd, asd_y))
return true;
- }
list_for_each_entry(sd, &notifier->done, async_list) {
if (WARN_ON(!sd->asd))
continue;
- if (sd->asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
- continue;
-
- if (sd->asd->match.fwnode == fwnode)
+ if (asd_equal(asd, sd->asd))
return true;
}
@@ -338,76 +362,91 @@ static bool __v4l2_async_notifier_fwnode_has_async_subdev(
}
/*
- * Find out whether an async sub-device was set up for an fwnode already or
+ * Find out whether an async sub-device was set up already or
* whether it exists in a given notifier before @this_index.
+ * If @this_index < 0, search the notifier's entire @asd_list.
*/
-static bool v4l2_async_notifier_fwnode_has_async_subdev(
- struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode,
- unsigned int this_index)
+static bool
+v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
+ struct v4l2_async_subdev *asd,
+ int this_index)
{
- unsigned int j;
+ struct v4l2_async_subdev *asd_y;
+ int j = 0;
lockdep_assert_held(&list_lock);
- /* Check that an fwnode is not being added more than once. */
- for (j = 0; j < this_index; j++) {
- struct v4l2_async_subdev *asd = notifier->subdevs[this_index];
- struct v4l2_async_subdev *other_asd = notifier->subdevs[j];
-
- if (other_asd->match_type == V4L2_ASYNC_MATCH_FWNODE &&
- asd->match.fwnode ==
- other_asd->match.fwnode)
+ /* Check that an asd is not being added more than once. */
+ list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
+ if (this_index >= 0 && j++ >= this_index)
+ break;
+ if (asd_equal(asd, asd_y))
return true;
}
- /* Check than an fwnode did not exist in other notifiers. */
+ /* Check that an asd does not exist in other notifiers. */
list_for_each_entry(notifier, &notifier_list, list)
- if (__v4l2_async_notifier_fwnode_has_async_subdev(
- notifier, fwnode))
+ if (__v4l2_async_notifier_has_async_subdev(notifier, asd))
return true;
return false;
}
-static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
+static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier *notifier,
+ struct v4l2_async_subdev *asd,
+ int this_index)
{
struct device *dev =
notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL;
- struct v4l2_async_subdev *asd;
- int ret;
- int i;
- if (notifier->num_subdevs > V4L2_MAX_SUBDEVS)
+ if (!asd)
+ return -EINVAL;
+
+ switch (asd->match_type) {
+ case V4L2_ASYNC_MATCH_CUSTOM:
+ case V4L2_ASYNC_MATCH_DEVNAME:
+ case V4L2_ASYNC_MATCH_I2C:
+ case V4L2_ASYNC_MATCH_FWNODE:
+ if (v4l2_async_notifier_has_async_subdev(notifier, asd,
+ this_index)) {
+ dev_dbg(dev, "subdev descriptor already listed in this or other notifiers\n");
+ return -EEXIST;
+ }
+ break;
+ default:
+ dev_err(dev, "Invalid match type %u on %p\n",
+ asd->match_type, asd);
return -EINVAL;
+ }
+
+ return 0;
+}
+
+void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier)
+{
+ mutex_lock(&list_lock);
+
+ INIT_LIST_HEAD(&notifier->asd_list);
+
+ mutex_unlock(&list_lock);
+}
+EXPORT_SYMBOL(v4l2_async_notifier_init);
+
+static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
+{
+ struct v4l2_async_subdev *asd;
+ int ret, i = 0;
INIT_LIST_HEAD(&notifier->waiting);
INIT_LIST_HEAD(&notifier->done);
mutex_lock(&list_lock);
- for (i = 0; i < notifier->num_subdevs; i++) {
- asd = notifier->subdevs[i];
-
- switch (asd->match_type) {
- case V4L2_ASYNC_MATCH_CUSTOM:
- case V4L2_ASYNC_MATCH_DEVNAME:
- case V4L2_ASYNC_MATCH_I2C:
- break;
- case V4L2_ASYNC_MATCH_FWNODE:
- if (v4l2_async_notifier_fwnode_has_async_subdev(
- notifier, asd->match.fwnode, i)) {
- dev_err(dev,
- "fwnode has already been registered or in notifier's subdev list\n");
- ret = -EEXIST;
- goto err_unlock;
- }
- break;
- default:
- dev_err(dev, "Invalid match type %u on %p\n",
- asd->match_type, asd);
- ret = -EINVAL;
+ list_for_each_entry(asd, &notifier->asd_list, asd_list) {
+ ret = v4l2_async_notifier_asd_valid(notifier, asd, i++);
+ if (ret)
goto err_unlock;
- }
+
list_add_tail(&asd->list, &notifier->waiting);
}
@@ -474,8 +513,8 @@ int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd,
}
EXPORT_SYMBOL(v4l2_async_subdev_notifier_register);
-static void __v4l2_async_notifier_unregister(
- struct v4l2_async_notifier *notifier)
+static void
+__v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
{
if (!notifier || (!notifier->v4l2_dev && !notifier->sd))
return;
@@ -498,36 +537,132 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
}
EXPORT_SYMBOL(v4l2_async_notifier_unregister);
-void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
+static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
{
- unsigned int i;
+ struct v4l2_async_subdev *asd, *tmp;
- if (!notifier || !notifier->max_subdevs)
+ if (!notifier)
return;
- for (i = 0; i < notifier->num_subdevs; i++) {
- struct v4l2_async_subdev *asd = notifier->subdevs[i];
-
+ list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
switch (asd->match_type) {
case V4L2_ASYNC_MATCH_FWNODE:
fwnode_handle_put(asd->match.fwnode);
break;
default:
- WARN_ON_ONCE(true);
break;
}
+ list_del(&asd->asd_list);
kfree(asd);
}
+}
- notifier->max_subdevs = 0;
- notifier->num_subdevs = 0;
+void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
+{
+ mutex_lock(&list_lock);
+
+ __v4l2_async_notifier_cleanup(notifier);
- kvfree(notifier->subdevs);
- notifier->subdevs = NULL;
+ mutex_unlock(&list_lock);
}
EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
+int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
+ struct v4l2_async_subdev *asd)
+{
+ int ret;
+
+ mutex_lock(&list_lock);
+
+ ret = v4l2_async_notifier_asd_valid(notifier, asd, -1);
+ if (ret)
+ goto unlock;
+
+ list_add_tail(&asd->asd_list, &notifier->asd_list);
+
+unlock:
+ mutex_unlock(&list_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev);
+
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
+ struct fwnode_handle *fwnode,
+ unsigned int asd_struct_size)
+{
+ struct v4l2_async_subdev *asd;
+ int ret;
+
+ asd = kzalloc(asd_struct_size, GFP_KERNEL);
+ if (!asd)
+ return ERR_PTR(-ENOMEM);
+
+ asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
+ asd->match.fwnode = fwnode;
+
+ ret = v4l2_async_notifier_add_subdev(notifier, asd);
+ if (ret) {
+ kfree(asd);
+ return ERR_PTR(ret);
+ }
+
+ return asd;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev);
+
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
+ int adapter_id, unsigned short address,
+ unsigned int asd_struct_size)
+{
+ struct v4l2_async_subdev *asd;
+ int ret;
+
+ asd = kzalloc(asd_struct_size, GFP_KERNEL);
+ if (!asd)
+ return ERR_PTR(-ENOMEM);
+
+ asd->match_type = V4L2_ASYNC_MATCH_I2C;
+ asd->match.i2c.adapter_id = adapter_id;
+ asd->match.i2c.address = address;
+
+ ret = v4l2_async_notifier_add_subdev(notifier, asd);
+ if (ret) {
+ kfree(asd);
+ return ERR_PTR(ret);
+ }
+
+ return asd;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_i2c_subdev);
+
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
+ const char *device_name,
+ unsigned int asd_struct_size)
+{
+ struct v4l2_async_subdev *asd;
+ int ret;
+
+ asd = kzalloc(asd_struct_size, GFP_KERNEL);
+ if (!asd)
+ return ERR_PTR(-ENOMEM);
+
+ asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
+ asd->match.device_name = device_name;
+
+ ret = v4l2_async_notifier_add_subdev(notifier, asd);
+ if (ret) {
+ kfree(asd);
+ return ERR_PTR(ret);
+ }
+
+ return asd;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_devname_subdev);
+
int v4l2_async_register_subdev(struct v4l2_subdev *sd)
{
struct v4l2_async_notifier *subdev_notifier;
@@ -601,7 +736,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
mutex_lock(&list_lock);
__v4l2_async_notifier_unregister(sd->subdev_notifier);
- v4l2_async_notifier_cleanup(sd->subdev_notifier);
+ __v4l2_async_notifier_cleanup(sd->subdev_notifier);
kfree(sd->subdev_notifier);
sd->subdev_notifier = NULL;
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index b518b92d6d96..50763fb42a1b 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -100,7 +100,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _
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;
}
EXPORT_SYMBOL(v4l2_ctrl_query_fill);
@@ -109,6 +109,19 @@ EXPORT_SYMBOL(v4l2_ctrl_query_fill);
#if IS_ENABLED(CONFIG_I2C)
+void v4l2_i2c_subdev_set_name(struct v4l2_subdev *sd, struct i2c_client *client,
+ const char *devname, const char *postfix)
+{
+ if (!devname)
+ devname = client->dev.driver->name;
+ if (!postfix)
+ postfix = "";
+
+ snprintf(sd->name, sizeof(sd->name), "%s%s %d-%04x", devname, postfix,
+ i2c_adapter_id(client->adapter), client->addr);
+}
+EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_set_name);
+
void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
const struct v4l2_subdev_ops *ops)
{
@@ -120,10 +133,7 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
/* i2c_client and v4l2_subdev point to one another */
v4l2_set_subdevdata(sd, client);
i2c_set_clientdata(client, sd);
- /* initialize name */
- snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
- client->dev.driver->name, i2c_adapter_id(client->adapter),
- client->addr);
+ v4l2_i2c_subdev_set_name(sd, client, NULL, NULL);
}
EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);
@@ -186,7 +196,7 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
/* Setup the i2c board info with the device type and
the device address. */
memset(&info, 0, sizeof(info));
- strlcpy(info.type, client_type, sizeof(info.type));
+ strscpy(info.type, client_type, sizeof(info.type));
info.addr = addr;
return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs);
@@ -255,7 +265,8 @@ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
v4l2_set_subdevdata(sd, spi);
spi_set_drvdata(spi, sd);
/* initialize name */
- strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name));
+ snprintf(sd->name, sizeof(sd->name), "%s %s",
+ spi->dev.driver->name, dev_name(&spi->dev));
}
EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 599c1cbff3b9..4c0ecf29d278 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -2511,20 +2511,15 @@ void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active)
}
EXPORT_SYMBOL(v4l2_ctrl_activate);
-/* Grab/ungrab a control.
- Typically used when streaming starts and you want to grab controls,
- preventing the user from changing them.
-
- Just call this and the framework will block any attempts to change
- these controls. */
-void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)
+void __v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)
{
bool old;
if (ctrl == NULL)
return;
- v4l2_ctrl_lock(ctrl);
+ lockdep_assert_held(ctrl->handler->lock);
+
if (grabbed)
/* set V4L2_CTRL_FLAG_GRABBED */
old = test_and_set_bit(1, &ctrl->flags);
@@ -2533,9 +2528,8 @@ void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)
old = test_and_clear_bit(1, &ctrl->flags);
if (old != grabbed)
send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS);
- v4l2_ctrl_unlock(ctrl);
}
-EXPORT_SYMBOL(v4l2_ctrl_grab);
+EXPORT_SYMBOL(__v4l2_ctrl_grab);
/* Log the control name and value */
static void log_ctrl(const struct v4l2_ctrl *ctrl,
@@ -2722,7 +2716,7 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr
qc->id = id;
else
qc->id = ctrl->id;
- strlcpy(qc->name, ctrl->name, sizeof(qc->name));
+ strscpy(qc->name, ctrl->name, sizeof(qc->name));
qc->flags = user_flags(ctrl);
qc->type = ctrl->type;
qc->elem_size = ctrl->elem_size;
@@ -2754,7 +2748,7 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
qc->id = qec.id;
qc->type = qec.type;
qc->flags = qec.flags;
- strlcpy(qc->name, qec.name, sizeof(qc->name));
+ strscpy(qc->name, qec.name, sizeof(qc->name));
switch (qc->type) {
case V4L2_CTRL_TYPE_INTEGER:
case V4L2_CTRL_TYPE_BOOLEAN:
@@ -2813,7 +2807,7 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)
if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0')
return -EINVAL;
- strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
+ strscpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
} else {
qm->value = ctrl->qmenu_int[i];
}
@@ -3442,7 +3436,7 @@ int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)
/* It's a driver bug if this happens. */
WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING);
- strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
+ strscpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
return set_ctrl(NULL, ctrl, 0);
}
EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
index 3940e55c72f1..098562901f25 100644
--- a/drivers/media/v4l2-core/v4l2-device.c
+++ b/drivers/media/v4l2-core/v4l2-device.c
@@ -245,7 +245,7 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
}
video_set_drvdata(vdev, sd);
- strlcpy(vdev->name, sd->name, sizeof(vdev->name));
+ strscpy(vdev->name, sd->name, sizeof(vdev->name));
vdev->v4l2_dev = v4l2_dev;
vdev->fops = &v4l2_subdev_fops;
vdev->release = v4l2_device_release_subdev_node;
diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c
index c81faea96fba..4f23e939ead0 100644
--- a/drivers/media/v4l2-core/v4l2-dv-timings.c
+++ b/drivers/media/v4l2-core/v4l2-dv-timings.c
@@ -15,6 +15,7 @@
#include <media/v4l2-dv-timings.h>
#include <linux/math64.h>
#include <linux/hdmi.h>
+#include <media/cec.h>
MODULE_AUTHOR("Hans Verkuil");
MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions");
@@ -373,6 +374,45 @@ struct v4l2_fract v4l2_dv_timings_aspect_ratio(const struct v4l2_dv_timings *t)
}
EXPORT_SYMBOL_GPL(v4l2_dv_timings_aspect_ratio);
+/** v4l2_calc_timeperframe - helper function to calculate timeperframe based
+ * v4l2_dv_timings fields.
+ * @t - Timings for the video mode.
+ *
+ * Calculates the expected timeperframe using the pixel clock value and
+ * horizontal/vertical measures. This means that v4l2_dv_timings structure
+ * must be correctly and fully filled.
+ */
+struct v4l2_fract v4l2_calc_timeperframe(const struct v4l2_dv_timings *t)
+{
+ const struct v4l2_bt_timings *bt = &t->bt;
+ struct v4l2_fract fps_fract = { 1, 1 };
+ unsigned long n, d;
+ u32 htot, vtot, fps;
+ u64 pclk;
+
+ if (t->type != V4L2_DV_BT_656_1120)
+ return fps_fract;
+
+ htot = V4L2_DV_BT_FRAME_WIDTH(bt);
+ vtot = V4L2_DV_BT_FRAME_HEIGHT(bt);
+ pclk = bt->pixelclock;
+
+ if ((bt->flags & V4L2_DV_FL_CAN_DETECT_REDUCED_FPS) &&
+ (bt->flags & V4L2_DV_FL_REDUCED_FPS))
+ pclk = div_u64(pclk * 1000ULL, 1001);
+
+ fps = (htot * vtot) > 0 ? div_u64((100 * pclk), (htot * vtot)) : 0;
+ if (!fps)
+ return fps_fract;
+
+ rational_best_approximation(fps, 100, fps, 100, &n, &d);
+
+ fps_fract.numerator = d;
+ fps_fract.denominator = n;
+ return fps_fract;
+}
+EXPORT_SYMBOL_GPL(v4l2_calc_timeperframe);
+
/*
* CVT defines
* Based on Coordinated Video Timings Standard
@@ -837,9 +877,9 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi,
switch (avi->colorimetry) {
case HDMI_COLORIMETRY_EXTENDED:
switch (avi->extended_colorimetry) {
- case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB:
- c.colorspace = V4L2_COLORSPACE_ADOBERGB;
- c.xfer_func = V4L2_XFER_FUNC_ADOBERGB;
+ case HDMI_EXTENDED_COLORIMETRY_OPRGB:
+ c.colorspace = V4L2_COLORSPACE_OPRGB;
+ c.xfer_func = V4L2_XFER_FUNC_OPRGB;
break;
case HDMI_EXTENDED_COLORIMETRY_BT2020:
c.colorspace = V4L2_COLORSPACE_BT2020;
@@ -908,10 +948,10 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi,
c.ycbcr_enc = V4L2_YCBCR_ENC_601;
c.xfer_func = V4L2_XFER_FUNC_SRGB;
break;
- case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601:
- c.colorspace = V4L2_COLORSPACE_ADOBERGB;
+ case HDMI_EXTENDED_COLORIMETRY_OPYCC_601:
+ c.colorspace = V4L2_COLORSPACE_OPRGB;
c.ycbcr_enc = V4L2_YCBCR_ENC_601;
- c.xfer_func = V4L2_XFER_FUNC_ADOBERGB;
+ c.xfer_func = V4L2_XFER_FUNC_OPRGB;
break;
case HDMI_EXTENDED_COLORIMETRY_BT2020:
c.colorspace = V4L2_COLORSPACE_BT2020;
@@ -942,3 +982,153 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi,
return c;
}
EXPORT_SYMBOL_GPL(v4l2_hdmi_rx_colorimetry);
+
+/**
+ * v4l2_get_edid_phys_addr() - find and return the physical address
+ *
+ * @edid: pointer to the EDID data
+ * @size: size in bytes of the EDID data
+ * @offset: If not %NULL then the location of the physical address
+ * bytes in the EDID will be returned here. This is set to 0
+ * if there is no physical address found.
+ *
+ * Return: the physical address or CEC_PHYS_ADDR_INVALID if there is none.
+ */
+u16 v4l2_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(v4l2_get_edid_phys_addr);
+
+/**
+ * v4l2_set_edid_phys_addr() - find and set the physical address
+ *
+ * @edid: pointer to the EDID data
+ * @size: size in bytes of the EDID data
+ * @phys_addr: the new physical address
+ *
+ * This function finds the location of the physical address in the EDID
+ * and fills in the given physical address and updates the checksum
+ * at the end of the EDID block. It does nothing if the EDID doesn't
+ * contain a physical address.
+ */
+void v4l2_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(v4l2_set_edid_phys_addr);
+
+/**
+ * v4l2_phys_addr_for_input() - calculate the PA for an input
+ *
+ * @phys_addr: the physical address of the parent
+ * @input: the number of the input port, must be between 1 and 15
+ *
+ * This function calculates a new physical address based on the input
+ * port number. For example:
+ *
+ * PA = 0.0.0.0 and input = 2 becomes 2.0.0.0
+ *
+ * PA = 3.0.0.0 and input = 1 becomes 3.1.0.0
+ *
+ * PA = 3.2.1.0 and input = 5 becomes 3.2.1.5
+ *
+ * PA = 3.2.1.3 and input = 5 becomes f.f.f.f since it maxed out the depth.
+ *
+ * Return: the new physical address or CEC_PHYS_ADDR_INVALID.
+ */
+u16 v4l2_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(v4l2_phys_addr_for_input);
+
+/**
+ * v4l2_phys_addr_validate() - validate a physical address from an EDID
+ *
+ * @phys_addr: the physical address to validate
+ * @parent: if not %NULL, then this is filled with the parents PA.
+ * @port: if not %NULL, then this is filled with the input port.
+ *
+ * This validates a physical address as read from an EDID. If the
+ * PA is invalid (such as 1.0.1.0 since '0' is only allowed at the end),
+ * then it will return -EINVAL.
+ *
+ * The parent PA is passed into %parent and the input port is passed into
+ * %port. For example:
+ *
+ * PA = 0.0.0.0: has parent 0.0.0.0 and input port 0.
+ *
+ * PA = 1.0.0.0: has parent 0.0.0.0 and input port 1.
+ *
+ * PA = 3.2.0.0: has parent 3.0.0.0 and input port 2.
+ *
+ * PA = f.f.f.f: has parent f.f.f.f and input port 0.
+ *
+ * Return: 0 if the PA is valid, -EINVAL if not.
+ */
+int v4l2_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(v4l2_phys_addr_validate);
diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c
index 215b4804ada2..1697932af5ea 100644
--- a/drivers/media/v4l2-core/v4l2-flash-led-class.c
+++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c
@@ -640,7 +640,7 @@ static struct v4l2_flash *__v4l2_flash_init(
v4l2_subdev_init(sd, &v4l2_flash_subdev_ops);
sd->internal_ops = &v4l2_flash_subdev_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- strlcpy(sd->name, config->dev_name, sizeof(sd->name));
+ strscpy(sd->name, config->dev_name, sizeof(sd->name));
ret = media_entity_pads_init(&sd->entity, 0, NULL);
if (ret < 0)
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 169bdbb1f61a..218f0da0ce76 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -36,194 +36,469 @@ enum v4l2_fwnode_bus_type {
V4L2_FWNODE_BUS_TYPE_CSI2_CPHY,
V4L2_FWNODE_BUS_TYPE_CSI1,
V4L2_FWNODE_BUS_TYPE_CCP2,
+ V4L2_FWNODE_BUS_TYPE_CSI2_DPHY,
+ V4L2_FWNODE_BUS_TYPE_PARALLEL,
+ V4L2_FWNODE_BUS_TYPE_BT656,
NR_OF_V4L2_FWNODE_BUS_TYPE,
};
+static const struct v4l2_fwnode_bus_conv {
+ enum v4l2_fwnode_bus_type fwnode_bus_type;
+ enum v4l2_mbus_type mbus_type;
+ const char *name;
+} busses[] = {
+ {
+ V4L2_FWNODE_BUS_TYPE_GUESS,
+ V4L2_MBUS_UNKNOWN,
+ "not specified",
+ }, {
+ V4L2_FWNODE_BUS_TYPE_CSI2_CPHY,
+ V4L2_MBUS_CSI2_CPHY,
+ "MIPI CSI-2 C-PHY",
+ }, {
+ V4L2_FWNODE_BUS_TYPE_CSI1,
+ V4L2_MBUS_CSI1,
+ "MIPI CSI-1",
+ }, {
+ V4L2_FWNODE_BUS_TYPE_CCP2,
+ V4L2_MBUS_CCP2,
+ "compact camera port 2",
+ }, {
+ V4L2_FWNODE_BUS_TYPE_CSI2_DPHY,
+ V4L2_MBUS_CSI2_DPHY,
+ "MIPI CSI-2 D-PHY",
+ }, {
+ V4L2_FWNODE_BUS_TYPE_PARALLEL,
+ V4L2_MBUS_PARALLEL,
+ "parallel",
+ }, {
+ V4L2_FWNODE_BUS_TYPE_BT656,
+ V4L2_MBUS_BT656,
+ "Bt.656",
+ }
+};
+
+static const struct v4l2_fwnode_bus_conv *
+get_v4l2_fwnode_bus_conv_by_fwnode_bus(enum v4l2_fwnode_bus_type type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(busses); i++)
+ if (busses[i].fwnode_bus_type == type)
+ return &busses[i];
+
+ return NULL;
+}
+
+static enum v4l2_mbus_type
+v4l2_fwnode_bus_type_to_mbus(enum v4l2_fwnode_bus_type type)
+{
+ const struct v4l2_fwnode_bus_conv *conv =
+ get_v4l2_fwnode_bus_conv_by_fwnode_bus(type);
+
+ return conv ? conv->mbus_type : V4L2_MBUS_UNKNOWN;
+}
+
+static const char *
+v4l2_fwnode_bus_type_to_string(enum v4l2_fwnode_bus_type type)
+{
+ const struct v4l2_fwnode_bus_conv *conv =
+ get_v4l2_fwnode_bus_conv_by_fwnode_bus(type);
+
+ return conv ? conv->name : "not found";
+}
+
+static const struct v4l2_fwnode_bus_conv *
+get_v4l2_fwnode_bus_conv_by_mbus(enum v4l2_mbus_type type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(busses); i++)
+ if (busses[i].mbus_type == type)
+ return &busses[i];
+
+ return NULL;
+}
+
+static const char *
+v4l2_fwnode_mbus_type_to_string(enum v4l2_mbus_type type)
+{
+ const struct v4l2_fwnode_bus_conv *conv =
+ get_v4l2_fwnode_bus_conv_by_mbus(type);
+
+ return conv ? conv->name : "not found";
+}
+
static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode,
- struct v4l2_fwnode_endpoint *vep)
+ struct v4l2_fwnode_endpoint *vep,
+ enum v4l2_mbus_type bus_type)
{
struct v4l2_fwnode_bus_mipi_csi2 *bus = &vep->bus.mipi_csi2;
- bool have_clk_lane = false;
+ bool have_clk_lane = false, have_data_lanes = false,
+ have_lane_polarities = false;
unsigned int flags = 0, lanes_used = 0;
+ u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES];
+ u32 clock_lane = 0;
+ unsigned int num_data_lanes = 0;
+ bool use_default_lane_mapping = false;
unsigned int i;
u32 v;
int rval;
+ if (bus_type == V4L2_MBUS_CSI2_DPHY ||
+ bus_type == V4L2_MBUS_CSI2_CPHY) {
+ use_default_lane_mapping = true;
+
+ num_data_lanes = min_t(u32, bus->num_data_lanes,
+ V4L2_FWNODE_CSI2_MAX_DATA_LANES);
+
+ clock_lane = bus->clock_lane;
+ if (clock_lane)
+ use_default_lane_mapping = false;
+
+ for (i = 0; i < num_data_lanes; i++) {
+ array[i] = bus->data_lanes[i];
+ if (array[i])
+ use_default_lane_mapping = false;
+ }
+
+ if (use_default_lane_mapping)
+ pr_debug("using default lane mapping\n");
+ }
+
rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0);
if (rval > 0) {
- u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES];
-
- bus->num_data_lanes =
+ num_data_lanes =
min_t(int, V4L2_FWNODE_CSI2_MAX_DATA_LANES, rval);
fwnode_property_read_u32_array(fwnode, "data-lanes", array,
- bus->num_data_lanes);
+ num_data_lanes);
- for (i = 0; i < bus->num_data_lanes; i++) {
- if (lanes_used & BIT(array[i]))
- pr_warn("duplicated lane %u in data-lanes\n",
- array[i]);
- lanes_used |= BIT(array[i]);
+ have_data_lanes = true;
+ }
- bus->data_lanes[i] = array[i];
+ for (i = 0; i < num_data_lanes; i++) {
+ if (lanes_used & BIT(array[i])) {
+ if (have_data_lanes || !use_default_lane_mapping)
+ pr_warn("duplicated lane %u in data-lanes, using defaults\n",
+ array[i]);
+ use_default_lane_mapping = true;
}
+ lanes_used |= BIT(array[i]);
- rval = fwnode_property_read_u32_array(fwnode,
- "lane-polarities", NULL,
- 0);
- if (rval > 0) {
- if (rval != 1 + bus->num_data_lanes /* clock+data */) {
- pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n",
- 1 + bus->num_data_lanes, rval);
- return -EINVAL;
- }
-
- fwnode_property_read_u32_array(fwnode,
- "lane-polarities", array,
- 1 + bus->num_data_lanes);
+ if (have_data_lanes)
+ pr_debug("lane %u position %u\n", i, array[i]);
+ }
- for (i = 0; i < 1 + bus->num_data_lanes; i++)
- bus->lane_polarities[i] = array[i];
+ rval = fwnode_property_read_u32_array(fwnode, "lane-polarities", NULL,
+ 0);
+ if (rval > 0) {
+ if (rval != 1 + num_data_lanes /* clock+data */) {
+ pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n",
+ 1 + num_data_lanes, rval);
+ return -EINVAL;
}
+ have_lane_polarities = true;
}
if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) {
- if (lanes_used & BIT(v))
- pr_warn("duplicated lane %u in clock-lanes\n", v);
- lanes_used |= BIT(v);
-
- bus->clock_lane = v;
+ clock_lane = v;
+ pr_debug("clock lane position %u\n", v);
have_clk_lane = true;
}
- if (fwnode_property_present(fwnode, "clock-noncontinuous"))
+ if (lanes_used & BIT(clock_lane)) {
+ if (have_clk_lane || !use_default_lane_mapping)
+ pr_warn("duplicated lane %u in clock-lanes, using defaults\n",
+ v);
+ use_default_lane_mapping = true;
+ }
+
+ if (fwnode_property_present(fwnode, "clock-noncontinuous")) {
flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
- else if (have_clk_lane || bus->num_data_lanes > 0)
+ pr_debug("non-continuous clock\n");
+ } else {
flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+ }
- bus->flags = flags;
- vep->bus_type = V4L2_MBUS_CSI2;
+ if (bus_type == V4L2_MBUS_CSI2_DPHY ||
+ bus_type == V4L2_MBUS_CSI2_CPHY || lanes_used ||
+ have_clk_lane || (flags & ~V4L2_MBUS_CSI2_CONTINUOUS_CLOCK)) {
+ bus->flags = flags;
+ if (bus_type == V4L2_MBUS_UNKNOWN)
+ vep->bus_type = V4L2_MBUS_CSI2_DPHY;
+ bus->num_data_lanes = num_data_lanes;
+
+ if (use_default_lane_mapping) {
+ bus->clock_lane = 0;
+ for (i = 0; i < num_data_lanes; i++)
+ bus->data_lanes[i] = 1 + i;
+ } else {
+ bus->clock_lane = clock_lane;
+ for (i = 0; i < num_data_lanes; i++)
+ bus->data_lanes[i] = array[i];
+ }
+
+ if (have_lane_polarities) {
+ fwnode_property_read_u32_array(fwnode,
+ "lane-polarities", array,
+ 1 + num_data_lanes);
+
+ for (i = 0; i < 1 + num_data_lanes; i++) {
+ bus->lane_polarities[i] = array[i];
+ pr_debug("lane %u polarity %sinverted",
+ i, array[i] ? "" : "not ");
+ }
+ } else {
+ pr_debug("no lane polarities defined, assuming not inverted\n");
+ }
+ }
return 0;
}
-static void v4l2_fwnode_endpoint_parse_parallel_bus(
- struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep)
+#define PARALLEL_MBUS_FLAGS (V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
+ V4L2_MBUS_HSYNC_ACTIVE_LOW | \
+ V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
+ V4L2_MBUS_VSYNC_ACTIVE_LOW | \
+ V4L2_MBUS_FIELD_EVEN_HIGH | \
+ V4L2_MBUS_FIELD_EVEN_LOW)
+
+static void
+v4l2_fwnode_endpoint_parse_parallel_bus(struct fwnode_handle *fwnode,
+ struct v4l2_fwnode_endpoint *vep,
+ enum v4l2_mbus_type bus_type)
{
struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel;
unsigned int flags = 0;
u32 v;
- if (!fwnode_property_read_u32(fwnode, "hsync-active", &v))
+ if (bus_type == V4L2_MBUS_PARALLEL || bus_type == V4L2_MBUS_BT656)
+ flags = bus->flags;
+
+ if (!fwnode_property_read_u32(fwnode, "hsync-active", &v)) {
+ flags &= ~(V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+ V4L2_MBUS_HSYNC_ACTIVE_LOW);
flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH :
V4L2_MBUS_HSYNC_ACTIVE_LOW;
+ pr_debug("hsync-active %s\n", v ? "high" : "low");
+ }
- if (!fwnode_property_read_u32(fwnode, "vsync-active", &v))
+ if (!fwnode_property_read_u32(fwnode, "vsync-active", &v)) {
+ flags &= ~(V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+ V4L2_MBUS_VSYNC_ACTIVE_LOW);
flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH :
V4L2_MBUS_VSYNC_ACTIVE_LOW;
+ pr_debug("vsync-active %s\n", v ? "high" : "low");
+ }
- if (!fwnode_property_read_u32(fwnode, "field-even-active", &v))
+ if (!fwnode_property_read_u32(fwnode, "field-even-active", &v)) {
+ flags &= ~(V4L2_MBUS_FIELD_EVEN_HIGH |
+ V4L2_MBUS_FIELD_EVEN_LOW);
flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH :
V4L2_MBUS_FIELD_EVEN_LOW;
- if (flags)
- vep->bus_type = V4L2_MBUS_PARALLEL;
- else
- vep->bus_type = V4L2_MBUS_BT656;
+ pr_debug("field-even-active %s\n", v ? "high" : "low");
+ }
- if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v))
+ if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v)) {
+ flags &= ~(V4L2_MBUS_PCLK_SAMPLE_RISING |
+ V4L2_MBUS_PCLK_SAMPLE_FALLING);
flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING :
V4L2_MBUS_PCLK_SAMPLE_FALLING;
+ pr_debug("pclk-sample %s\n", v ? "high" : "low");
+ }
- if (!fwnode_property_read_u32(fwnode, "data-active", &v))
+ if (!fwnode_property_read_u32(fwnode, "data-active", &v)) {
+ flags &= ~(V4L2_MBUS_PCLK_SAMPLE_RISING |
+ V4L2_MBUS_PCLK_SAMPLE_FALLING);
flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH :
V4L2_MBUS_DATA_ACTIVE_LOW;
+ pr_debug("data-active %s\n", v ? "high" : "low");
+ }
- if (fwnode_property_present(fwnode, "slave-mode"))
+ if (fwnode_property_present(fwnode, "slave-mode")) {
+ pr_debug("slave mode\n");
+ flags &= ~V4L2_MBUS_MASTER;
flags |= V4L2_MBUS_SLAVE;
- else
+ } else {
+ flags &= ~V4L2_MBUS_SLAVE;
flags |= V4L2_MBUS_MASTER;
+ }
- if (!fwnode_property_read_u32(fwnode, "bus-width", &v))
+ if (!fwnode_property_read_u32(fwnode, "bus-width", &v)) {
bus->bus_width = v;
+ pr_debug("bus-width %u\n", v);
+ }
- if (!fwnode_property_read_u32(fwnode, "data-shift", &v))
+ if (!fwnode_property_read_u32(fwnode, "data-shift", &v)) {
bus->data_shift = v;
+ pr_debug("data-shift %u\n", v);
+ }
- if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v))
+ if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v)) {
+ flags &= ~(V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH |
+ V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW);
flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH :
V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW;
+ pr_debug("sync-on-green-active %s\n", v ? "high" : "low");
+ }
- if (!fwnode_property_read_u32(fwnode, "data-enable-active", &v))
+ if (!fwnode_property_read_u32(fwnode, "data-enable-active", &v)) {
+ flags &= ~(V4L2_MBUS_DATA_ENABLE_HIGH |
+ V4L2_MBUS_DATA_ENABLE_LOW);
flags |= v ? V4L2_MBUS_DATA_ENABLE_HIGH :
V4L2_MBUS_DATA_ENABLE_LOW;
+ pr_debug("data-enable-active %s\n", v ? "high" : "low");
+ }
- bus->flags = flags;
-
+ switch (bus_type) {
+ default:
+ bus->flags = flags;
+ if (flags & PARALLEL_MBUS_FLAGS)
+ vep->bus_type = V4L2_MBUS_PARALLEL;
+ else
+ vep->bus_type = V4L2_MBUS_BT656;
+ break;
+ case V4L2_MBUS_PARALLEL:
+ vep->bus_type = V4L2_MBUS_PARALLEL;
+ bus->flags = flags;
+ break;
+ case V4L2_MBUS_BT656:
+ vep->bus_type = V4L2_MBUS_BT656;
+ bus->flags = flags & ~PARALLEL_MBUS_FLAGS;
+ break;
+ }
}
static void
v4l2_fwnode_endpoint_parse_csi1_bus(struct fwnode_handle *fwnode,
struct v4l2_fwnode_endpoint *vep,
- u32 bus_type)
+ enum v4l2_mbus_type bus_type)
{
struct v4l2_fwnode_bus_mipi_csi1 *bus = &vep->bus.mipi_csi1;
u32 v;
- if (!fwnode_property_read_u32(fwnode, "clock-inv", &v))
+ if (!fwnode_property_read_u32(fwnode, "clock-inv", &v)) {
bus->clock_inv = v;
+ pr_debug("clock-inv %u\n", v);
+ }
- if (!fwnode_property_read_u32(fwnode, "strobe", &v))
+ if (!fwnode_property_read_u32(fwnode, "strobe", &v)) {
bus->strobe = v;
+ pr_debug("strobe %u\n", v);
+ }
- if (!fwnode_property_read_u32(fwnode, "data-lanes", &v))
+ if (!fwnode_property_read_u32(fwnode, "data-lanes", &v)) {
bus->data_lane = v;
+ pr_debug("data-lanes %u\n", v);
+ }
- if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v))
+ if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) {
bus->clock_lane = v;
+ pr_debug("clock-lanes %u\n", v);
+ }
- if (bus_type == V4L2_FWNODE_BUS_TYPE_CCP2)
+ if (bus_type == V4L2_MBUS_CCP2)
vep->bus_type = V4L2_MBUS_CCP2;
else
vep->bus_type = V4L2_MBUS_CSI1;
}
-int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
- struct v4l2_fwnode_endpoint *vep)
+static int __v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
+ struct v4l2_fwnode_endpoint *vep)
{
- u32 bus_type = 0;
+ u32 bus_type = V4L2_FWNODE_BUS_TYPE_GUESS;
+ enum v4l2_mbus_type mbus_type;
int rval;
- fwnode_graph_parse_endpoint(fwnode, &vep->base);
+ if (vep->bus_type == V4L2_MBUS_UNKNOWN) {
+ /* Zero fields from bus union to until the end */
+ memset(&vep->bus, 0,
+ sizeof(*vep) - offsetof(typeof(*vep), bus));
+ }
- /* Zero fields from bus_type to until the end */
- memset(&vep->bus_type, 0, sizeof(*vep) -
- offsetof(typeof(*vep), bus_type));
+ pr_debug("===== begin V4L2 endpoint properties\n");
+
+ /*
+ * Zero the fwnode graph endpoint memory in case we don't end up parsing
+ * the endpoint.
+ */
+ memset(&vep->base, 0, sizeof(vep->base));
fwnode_property_read_u32(fwnode, "bus-type", &bus_type);
+ pr_debug("fwnode video bus type %s (%u), mbus type %s (%u)\n",
+ v4l2_fwnode_bus_type_to_string(bus_type), bus_type,
+ v4l2_fwnode_mbus_type_to_string(vep->bus_type),
+ vep->bus_type);
+ mbus_type = v4l2_fwnode_bus_type_to_mbus(bus_type);
+
+ if (vep->bus_type != V4L2_MBUS_UNKNOWN) {
+ if (mbus_type != V4L2_MBUS_UNKNOWN &&
+ vep->bus_type != mbus_type) {
+ pr_debug("expecting bus type %s\n",
+ v4l2_fwnode_mbus_type_to_string(vep->bus_type));
+ return -ENXIO;
+ }
+ } else {
+ vep->bus_type = mbus_type;
+ }
- switch (bus_type) {
- case V4L2_FWNODE_BUS_TYPE_GUESS:
- rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep);
+ switch (vep->bus_type) {
+ case V4L2_MBUS_UNKNOWN:
+ rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep,
+ V4L2_MBUS_UNKNOWN);
if (rval)
return rval;
- /*
- * Parse the parallel video bus properties only if none
- * of the MIPI CSI-2 specific properties were found.
- */
- if (vep->bus.mipi_csi2.flags == 0)
- v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep);
-
- return 0;
- case V4L2_FWNODE_BUS_TYPE_CCP2:
- case V4L2_FWNODE_BUS_TYPE_CSI1:
- v4l2_fwnode_endpoint_parse_csi1_bus(fwnode, vep, bus_type);
-
- return 0;
+
+ if (vep->bus_type == V4L2_MBUS_UNKNOWN)
+ v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep,
+ V4L2_MBUS_UNKNOWN);
+
+ pr_debug("assuming media bus type %s (%u)\n",
+ v4l2_fwnode_mbus_type_to_string(vep->bus_type),
+ vep->bus_type);
+
+ break;
+ case V4L2_MBUS_CCP2:
+ case V4L2_MBUS_CSI1:
+ v4l2_fwnode_endpoint_parse_csi1_bus(fwnode, vep, vep->bus_type);
+
+ break;
+ case V4L2_MBUS_CSI2_DPHY:
+ case V4L2_MBUS_CSI2_CPHY:
+ rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep,
+ vep->bus_type);
+ if (rval)
+ return rval;
+
+ break;
+ case V4L2_MBUS_PARALLEL:
+ case V4L2_MBUS_BT656:
+ v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep,
+ vep->bus_type);
+
+ break;
default:
- pr_warn("unsupported bus type %u\n", bus_type);
+ pr_warn("unsupported bus type %u\n", mbus_type);
return -EINVAL;
}
+
+ fwnode_graph_parse_endpoint(fwnode, &vep->base);
+
+ return 0;
+}
+
+int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
+ struct v4l2_fwnode_endpoint *vep)
+{
+ int ret;
+
+ ret = __v4l2_fwnode_endpoint_parse(fwnode, vep);
+
+ pr_debug("===== end V4L2 endpoint properties\n");
+
+ return ret;
}
EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_parse);
@@ -233,49 +508,48 @@ void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep)
return;
kfree(vep->link_frequencies);
- kfree(vep);
}
EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_free);
-struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse(
- struct fwnode_handle *fwnode)
+int v4l2_fwnode_endpoint_alloc_parse(struct fwnode_handle *fwnode,
+ struct v4l2_fwnode_endpoint *vep)
{
- struct v4l2_fwnode_endpoint *vep;
int rval;
- vep = kzalloc(sizeof(*vep), GFP_KERNEL);
- if (!vep)
- return ERR_PTR(-ENOMEM);
-
- rval = v4l2_fwnode_endpoint_parse(fwnode, vep);
+ rval = __v4l2_fwnode_endpoint_parse(fwnode, vep);
if (rval < 0)
- goto out_err;
+ return rval;
rval = fwnode_property_read_u64_array(fwnode, "link-frequencies",
NULL, 0);
if (rval > 0) {
+ unsigned int i;
+
vep->link_frequencies =
kmalloc_array(rval, sizeof(*vep->link_frequencies),
GFP_KERNEL);
- if (!vep->link_frequencies) {
- rval = -ENOMEM;
- goto out_err;
- }
+ if (!vep->link_frequencies)
+ return -ENOMEM;
vep->nr_of_link_frequencies = rval;
- rval = fwnode_property_read_u64_array(
- fwnode, "link-frequencies", vep->link_frequencies,
- vep->nr_of_link_frequencies);
- if (rval < 0)
- goto out_err;
+ rval = fwnode_property_read_u64_array(fwnode,
+ "link-frequencies",
+ vep->link_frequencies,
+ vep->nr_of_link_frequencies);
+ if (rval < 0) {
+ v4l2_fwnode_endpoint_free(vep);
+ return rval;
+ }
+
+ for (i = 0; i < vep->nr_of_link_frequencies; i++)
+ pr_info("link-frequencies %u value %llu\n", i,
+ vep->link_frequencies[i]);
}
- return vep;
+ pr_debug("===== end V4L2 endpoint properties\n");
-out_err:
- v4l2_fwnode_endpoint_free(vep);
- return ERR_PTR(rval);
+ return 0;
}
EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse);
@@ -320,43 +594,16 @@ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link)
}
EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
-static int v4l2_async_notifier_realloc(struct v4l2_async_notifier *notifier,
- unsigned int max_subdevs)
-{
- struct v4l2_async_subdev **subdevs;
-
- if (max_subdevs <= notifier->max_subdevs)
- return 0;
-
- subdevs = kvmalloc_array(
- max_subdevs, sizeof(*notifier->subdevs),
- GFP_KERNEL | __GFP_ZERO);
- if (!subdevs)
- return -ENOMEM;
-
- if (notifier->subdevs) {
- memcpy(subdevs, notifier->subdevs,
- sizeof(*subdevs) * notifier->num_subdevs);
-
- kvfree(notifier->subdevs);
- }
-
- notifier->subdevs = subdevs;
- notifier->max_subdevs = max_subdevs;
-
- return 0;
-}
-
-static int v4l2_async_notifier_fwnode_parse_endpoint(
- struct device *dev, struct v4l2_async_notifier *notifier,
- struct fwnode_handle *endpoint, unsigned int asd_struct_size,
- int (*parse_endpoint)(struct device *dev,
- struct v4l2_fwnode_endpoint *vep,
- struct v4l2_async_subdev *asd))
+static int
+v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
+ struct v4l2_async_notifier *notifier,
+ struct fwnode_handle *endpoint,
+ unsigned int asd_struct_size,
+ parse_endpoint_func parse_endpoint)
{
+ struct v4l2_fwnode_endpoint vep = { .bus_type = 0 };
struct v4l2_async_subdev *asd;
- struct v4l2_fwnode_endpoint *vep;
- int ret = 0;
+ int ret;
asd = kzalloc(asd_struct_size, GFP_KERNEL);
if (!asd)
@@ -367,32 +614,36 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
fwnode_graph_get_remote_port_parent(endpoint);
if (!asd->match.fwnode) {
dev_warn(dev, "bad remote port parent\n");
- ret = -EINVAL;
+ ret = -ENOTCONN;
goto out_err;
}
- vep = v4l2_fwnode_endpoint_alloc_parse(endpoint);
- if (IS_ERR(vep)) {
- ret = PTR_ERR(vep);
+ ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &vep);
+ if (ret) {
dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n",
ret);
goto out_err;
}
- ret = parse_endpoint ? parse_endpoint(dev, vep, asd) : 0;
+ ret = parse_endpoint ? parse_endpoint(dev, &vep, asd) : 0;
if (ret == -ENOTCONN)
- dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep->base.port,
- vep->base.id);
+ dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep.base.port,
+ vep.base.id);
else if (ret < 0)
dev_warn(dev,
"driver could not parse port@%u/endpoint@%u (%d)\n",
- vep->base.port, vep->base.id, ret);
- v4l2_fwnode_endpoint_free(vep);
+ vep.base.port, vep.base.id, ret);
+ v4l2_fwnode_endpoint_free(&vep);
if (ret < 0)
goto out_err;
- notifier->subdevs[notifier->num_subdevs] = asd;
- notifier->num_subdevs++;
+ ret = v4l2_async_notifier_add_subdev(notifier, asd);
+ if (ret < 0) {
+ /* not an error if asd already exists */
+ if (ret == -EEXIST)
+ ret = 0;
+ goto out_err;
+ }
return 0;
@@ -403,56 +654,21 @@ out_err:
return ret == -ENOTCONN ? 0 : ret;
}
-static int __v4l2_async_notifier_parse_fwnode_endpoints(
- struct device *dev, struct v4l2_async_notifier *notifier,
- size_t asd_struct_size, unsigned int port, bool has_port,
- int (*parse_endpoint)(struct device *dev,
- struct v4l2_fwnode_endpoint *vep,
- struct v4l2_async_subdev *asd))
+static int
+__v4l2_async_notifier_parse_fwnode_ep(struct device *dev,
+ struct v4l2_async_notifier *notifier,
+ size_t asd_struct_size,
+ unsigned int port,
+ bool has_port,
+ parse_endpoint_func parse_endpoint)
{
struct fwnode_handle *fwnode;
- unsigned int max_subdevs = notifier->max_subdevs;
- int ret;
+ int ret = 0;
if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
return -EINVAL;
- for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
- dev_fwnode(dev), fwnode)); ) {
- struct fwnode_handle *dev_fwnode;
- bool is_available;
-
- dev_fwnode = fwnode_graph_get_port_parent(fwnode);
- is_available = fwnode_device_is_available(dev_fwnode);
- fwnode_handle_put(dev_fwnode);
- if (!is_available)
- continue;
-
- if (has_port) {
- struct fwnode_endpoint ep;
-
- ret = fwnode_graph_parse_endpoint(fwnode, &ep);
- if (ret) {
- fwnode_handle_put(fwnode);
- return ret;
- }
-
- if (ep.port != port)
- continue;
- }
- max_subdevs++;
- }
-
- /* No subdevs to add? Return here. */
- if (max_subdevs == notifier->max_subdevs)
- return 0;
-
- ret = v4l2_async_notifier_realloc(notifier, max_subdevs);
- if (ret)
- return ret;
-
- for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
- dev_fwnode(dev), fwnode)); ) {
+ fwnode_graph_for_each_endpoint(dev_fwnode(dev), fwnode) {
struct fwnode_handle *dev_fwnode;
bool is_available;
@@ -473,13 +689,11 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints(
continue;
}
- if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
- ret = -EINVAL;
- break;
- }
-
- ret = v4l2_async_notifier_fwnode_parse_endpoint(
- dev, notifier, fwnode, asd_struct_size, parse_endpoint);
+ ret = v4l2_async_notifier_fwnode_parse_endpoint(dev,
+ notifier,
+ fwnode,
+ asd_struct_size,
+ parse_endpoint);
if (ret < 0)
break;
}
@@ -489,27 +703,29 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints(
return ret;
}
-int v4l2_async_notifier_parse_fwnode_endpoints(
- struct device *dev, struct v4l2_async_notifier *notifier,
- size_t asd_struct_size,
- int (*parse_endpoint)(struct device *dev,
- struct v4l2_fwnode_endpoint *vep,
- struct v4l2_async_subdev *asd))
+int
+v4l2_async_notifier_parse_fwnode_endpoints(struct device *dev,
+ struct v4l2_async_notifier *notifier,
+ size_t asd_struct_size,
+ parse_endpoint_func parse_endpoint)
{
- return __v4l2_async_notifier_parse_fwnode_endpoints(
- dev, notifier, asd_struct_size, 0, false, parse_endpoint);
+ return __v4l2_async_notifier_parse_fwnode_ep(dev, notifier,
+ asd_struct_size, 0,
+ false, parse_endpoint);
}
EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints);
-int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
- struct device *dev, struct v4l2_async_notifier *notifier,
- size_t asd_struct_size, unsigned int port,
- int (*parse_endpoint)(struct device *dev,
- struct v4l2_fwnode_endpoint *vep,
- struct v4l2_async_subdev *asd))
+int
+v4l2_async_notifier_parse_fwnode_endpoints_by_port(struct device *dev,
+ struct v4l2_async_notifier *notifier,
+ size_t asd_struct_size,
+ unsigned int port,
+ parse_endpoint_func parse_endpoint)
{
- return __v4l2_async_notifier_parse_fwnode_endpoints(
- dev, notifier, asd_struct_size, port, true, parse_endpoint);
+ return __v4l2_async_notifier_parse_fwnode_ep(dev, notifier,
+ asd_struct_size,
+ port, true,
+ parse_endpoint);
}
EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port);
@@ -524,17 +740,18 @@ EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port);
* -ENOMEM if memory allocation failed
* -EINVAL if property parsing failed
*/
-static int v4l2_fwnode_reference_parse(
- struct device *dev, struct v4l2_async_notifier *notifier,
- const char *prop)
+static int v4l2_fwnode_reference_parse(struct device *dev,
+ struct v4l2_async_notifier *notifier,
+ const char *prop)
{
struct fwnode_reference_args args;
unsigned int index;
int ret;
for (index = 0;
- !(ret = fwnode_property_get_reference_args(
- dev_fwnode(dev), prop, NULL, 0, index, &args));
+ !(ret = fwnode_property_get_reference_args(dev_fwnode(dev),
+ prop, NULL, 0,
+ index, &args));
index++)
fwnode_handle_put(args.fwnode);
@@ -548,31 +765,25 @@ static int v4l2_fwnode_reference_parse(
if (ret != -ENOENT && ret != -ENODATA)
return ret;
- ret = v4l2_async_notifier_realloc(notifier,
- notifier->num_subdevs + index);
- if (ret)
- return ret;
-
- for (index = 0; !fwnode_property_get_reference_args(
- dev_fwnode(dev), prop, NULL, 0, index, &args);
+ for (index = 0;
+ !fwnode_property_get_reference_args(dev_fwnode(dev), prop, NULL,
+ 0, index, &args);
index++) {
struct v4l2_async_subdev *asd;
- if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
- ret = -EINVAL;
- goto error;
- }
+ asd = v4l2_async_notifier_add_fwnode_subdev(notifier,
+ args.fwnode,
+ sizeof(*asd));
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ /* not an error if asd already exists */
+ if (ret == -EEXIST) {
+ fwnode_handle_put(args.fwnode);
+ continue;
+ }
- asd = kzalloc(sizeof(*asd), GFP_KERNEL);
- if (!asd) {
- ret = -ENOMEM;
goto error;
}
-
- notifier->subdevs[notifier->num_subdevs] = asd;
- asd->match.fwnode = args.fwnode;
- asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
- notifier->num_subdevs++;
}
return 0;
@@ -738,9 +949,12 @@ error:
* -EINVAL if property parsing otherwise failed
* -ENOMEM if memory allocation failed
*/
-static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop(
- struct fwnode_handle *fwnode, const char *prop, unsigned int index,
- const char * const *props, unsigned int nprops)
+static struct fwnode_handle *
+v4l2_fwnode_reference_get_int_prop(struct fwnode_handle *fwnode,
+ const char *prop,
+ unsigned int index,
+ const char * const *props,
+ unsigned int nprops)
{
struct fwnode_reference_args fwnode_args;
u64 *args = fwnode_args.args;
@@ -792,6 +1006,12 @@ static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop(
return fwnode;
}
+struct v4l2_fwnode_int_props {
+ const char *name;
+ const char * const *props;
+ unsigned int nprops;
+};
+
/*
* v4l2_fwnode_reference_parse_int_props - parse references for async
* sub-devices
@@ -815,13 +1035,17 @@ static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop(
* -EINVAL if property parsing otherwisefailed
* -ENOMEM if memory allocation failed
*/
-static int v4l2_fwnode_reference_parse_int_props(
- struct device *dev, struct v4l2_async_notifier *notifier,
- const char *prop, const char * const *props, unsigned int nprops)
+static int
+v4l2_fwnode_reference_parse_int_props(struct device *dev,
+ struct v4l2_async_notifier *notifier,
+ const struct v4l2_fwnode_int_props *p)
{
struct fwnode_handle *fwnode;
unsigned int index;
int ret;
+ const char *prop = p->name;
+ const char * const *props = p->props;
+ unsigned int nprops = p->nprops;
index = 0;
do {
@@ -843,31 +1067,26 @@ static int v4l2_fwnode_reference_parse_int_props(
index++;
} while (1);
- ret = v4l2_async_notifier_realloc(notifier,
- notifier->num_subdevs + index);
- if (ret)
- return -ENOMEM;
-
- for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(
- dev_fwnode(dev), prop, index, props,
- nprops))); index++) {
+ for (index = 0;
+ !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(dev_fwnode(dev),
+ prop, index,
+ props,
+ nprops)));
+ index++) {
struct v4l2_async_subdev *asd;
- if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
- ret = -EINVAL;
- goto error;
- }
+ asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode,
+ sizeof(*asd));
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ /* not an error if asd already exists */
+ if (ret == -EEXIST) {
+ fwnode_handle_put(fwnode);
+ continue;
+ }
- asd = kzalloc(sizeof(struct v4l2_async_subdev), GFP_KERNEL);
- if (!asd) {
- ret = -ENOMEM;
goto error;
}
-
- notifier->subdevs[notifier->num_subdevs] = asd;
- asd->match.fwnode = fwnode;
- asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
- notifier->num_subdevs++;
}
return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
@@ -877,15 +1096,11 @@ error:
return ret;
}
-int v4l2_async_notifier_parse_fwnode_sensor_common(
- struct device *dev, struct v4l2_async_notifier *notifier)
+int v4l2_async_notifier_parse_fwnode_sensor_common(struct device *dev,
+ struct v4l2_async_notifier *notifier)
{
static const char * const led_props[] = { "led" };
- static const struct {
- const char *name;
- const char * const *props;
- unsigned int nprops;
- } props[] = {
+ static const struct v4l2_fwnode_int_props props[] = {
{ "flash-leds", led_props, ARRAY_SIZE(led_props) },
{ "lens-focus", NULL, 0 },
};
@@ -895,12 +1110,12 @@ int v4l2_async_notifier_parse_fwnode_sensor_common(
int ret;
if (props[i].props && is_acpi_node(dev_fwnode(dev)))
- ret = v4l2_fwnode_reference_parse_int_props(
- dev, notifier, props[i].name,
- props[i].props, props[i].nprops);
+ ret = v4l2_fwnode_reference_parse_int_props(dev,
+ notifier,
+ &props[i]);
else
- ret = v4l2_fwnode_reference_parse(
- dev, notifier, props[i].name);
+ ret = v4l2_fwnode_reference_parse(dev, notifier,
+ props[i].name);
if (ret && ret != -ENOENT) {
dev_warn(dev, "parsing property \"%s\" failed (%d)\n",
props[i].name, ret);
@@ -924,6 +1139,8 @@ int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
if (!notifier)
return -ENOMEM;
+ v4l2_async_notifier_init(notifier);
+
ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev,
notifier);
if (ret < 0)
@@ -952,6 +1169,68 @@ out_cleanup:
}
EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
+int v4l2_async_register_fwnode_subdev(struct v4l2_subdev *sd,
+ size_t asd_struct_size,
+ unsigned int *ports,
+ unsigned int num_ports,
+ parse_endpoint_func parse_endpoint)
+{
+ struct v4l2_async_notifier *notifier;
+ struct device *dev = sd->dev;
+ struct fwnode_handle *fwnode;
+ int ret;
+
+ if (WARN_ON(!dev))
+ return -ENODEV;
+
+ fwnode = dev_fwnode(dev);
+ if (!fwnode_device_is_available(fwnode))
+ return -ENODEV;
+
+ notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
+ if (!notifier)
+ return -ENOMEM;
+
+ v4l2_async_notifier_init(notifier);
+
+ if (!ports) {
+ ret = v4l2_async_notifier_parse_fwnode_endpoints(dev, notifier,
+ asd_struct_size,
+ parse_endpoint);
+ if (ret < 0)
+ goto out_cleanup;
+ } else {
+ unsigned int i;
+
+ for (i = 0; i < num_ports; i++) {
+ ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(dev, notifier, asd_struct_size, ports[i], parse_endpoint);
+ if (ret < 0)
+ goto out_cleanup;
+ }
+ }
+
+ ret = v4l2_async_subdev_notifier_register(sd, notifier);
+ if (ret < 0)
+ goto out_cleanup;
+
+ ret = v4l2_async_register_subdev(sd);
+ if (ret < 0)
+ goto out_unregister;
+
+ sd->subdev_notifier = notifier;
+
+ return 0;
+
+out_unregister:
+ v4l2_async_notifier_unregister(notifier);
+out_cleanup:
+ v4l2_async_notifier_cleanup(notifier);
+ kfree(notifier);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_register_fwnode_subdev);
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 54afc9c7ee6e..7de041bae84f 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -121,7 +121,7 @@ int v4l2_video_std_construct(struct v4l2_standard *vs,
vs->id = id;
v4l2_video_std_frame_period(id, &vs->frameperiod);
vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625;
- strlcpy(vs->name, name, sizeof(vs->name));
+ strscpy(vs->name, name, sizeof(vs->name));
return 0;
}
EXPORT_SYMBOL(v4l2_video_std_construct);
@@ -1352,7 +1352,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
}
if (descr)
- WARN_ON(strlcpy(fmt->description, descr, sz) >= sz);
+ WARN_ON(strscpy(fmt->description, descr, sz) >= sz);
fmt->flags = flags;
}
@@ -2391,7 +2391,7 @@ static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops,
p->flags |= V4L2_CHIP_FL_WRITABLE;
if (ops->vidioc_g_register)
p->flags |= V4L2_CHIP_FL_READABLE;
- strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name));
+ strscpy(p->name, vfd->v4l2_dev->name, sizeof(p->name));
if (ops->vidioc_g_chip_info)
return ops->vidioc_g_chip_info(file, fh, arg);
if (p->match.addr)
@@ -2408,7 +2408,7 @@ static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops,
p->flags |= V4L2_CHIP_FL_WRITABLE;
if (sd->ops->core && sd->ops->core->g_register)
p->flags |= V4L2_CHIP_FL_READABLE;
- strlcpy(p->name, sd->name, sizeof(p->name));
+ strscpy(p->name, sd->name, sizeof(p->name));
return 0;
}
break;
diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
index 0fc185a2ce90..014a2a97cadd 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -28,7 +28,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL;
bool is_webcam = false;
u32 flags;
- int ret;
+ int ret, pad_sink, pad_source;
if (!mdev)
return 0;
@@ -63,8 +63,10 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
}
/* It should have at least one I/O entity */
- if (!io_v4l && !io_vbi && !io_swradio)
+ if (!io_v4l && !io_vbi && !io_swradio) {
+ dev_warn(mdev->dev, "Didn't find any I/O entity\n");
return -EINVAL;
+ }
/*
* Here, webcams are modelled on a very simple way: the sensor is
@@ -74,8 +76,10 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
* PC-consumer's hardware.
*/
if (is_webcam) {
- if (!io_v4l)
+ if (!io_v4l) {
+ dev_warn(mdev->dev, "Didn't find a MEDIA_ENT_F_IO_V4L\n");
return -EINVAL;
+ }
media_device_for_each_entity(entity, mdev) {
if (entity->function != MEDIA_ENT_F_CAM_SENSOR)
@@ -83,46 +87,91 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
ret = media_create_pad_link(entity, 0,
io_v4l, 0,
MEDIA_LNK_FL_ENABLED);
- if (ret)
+ if (ret) {
+ dev_warn(mdev->dev, "Failed to create a sensor link\n");
return ret;
+ }
}
if (!decoder)
return 0;
}
/* The device isn't a webcam. So, it should have a decoder */
- if (!decoder)
+ if (!decoder) {
+ dev_warn(mdev->dev, "Decoder not found\n");
return -EINVAL;
+ }
/* Link the tuner and IF video output pads */
if (tuner) {
if (if_vid) {
- ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
- if_vid,
- IF_VID_DEC_PAD_IF_INPUT,
+ pad_source = media_get_pad_index(tuner, false,
+ PAD_SIGNAL_ANALOG);
+ pad_sink = media_get_pad_index(if_vid, true,
+ PAD_SIGNAL_ANALOG);
+ if (pad_source < 0 || pad_sink < 0) {
+ dev_warn(mdev->dev, "Couldn't get tuner and/or PLL pad(s): (%d, %d)\n",
+ pad_source, pad_sink);
+ return -EINVAL;
+ }
+ ret = media_create_pad_link(tuner, pad_source,
+ if_vid, pad_sink,
MEDIA_LNK_FL_ENABLED);
- if (ret)
+ if (ret) {
+ dev_warn(mdev->dev, "Couldn't create tuner->PLL link)\n");
return ret;
- ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
- decoder, DEMOD_PAD_IF_INPUT,
- MEDIA_LNK_FL_ENABLED);
- if (ret)
+ }
+
+ pad_source = media_get_pad_index(if_vid, false,
+ PAD_SIGNAL_ANALOG);
+ pad_sink = media_get_pad_index(decoder, true,
+ PAD_SIGNAL_ANALOG);
+ if (pad_source < 0 || pad_sink < 0) {
+ dev_warn(mdev->dev, "get decoder and/or PLL pad(s): (%d, %d)\n",
+ pad_source, pad_sink);
+ return -EINVAL;
+ }
+ ret = media_create_pad_link(if_vid, pad_source,
+ decoder, pad_sink,
+ MEDIA_LNK_FL_ENABLED);
+ if (ret) {
+ dev_warn(mdev->dev, "couldn't link PLL to decoder\n");
return ret;
+ }
} else {
- ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
- decoder, DEMOD_PAD_IF_INPUT,
- MEDIA_LNK_FL_ENABLED);
+ pad_source = media_get_pad_index(tuner, false,
+ PAD_SIGNAL_ANALOG);
+ pad_sink = media_get_pad_index(decoder, true,
+ PAD_SIGNAL_ANALOG);
+ if (pad_source < 0 || pad_sink < 0) {
+ dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s): (%d, %d)\n",
+ pad_source, pad_sink);
+ return -EINVAL;
+ }
+ ret = media_create_pad_link(tuner, pad_source,
+ decoder, pad_sink,
+ MEDIA_LNK_FL_ENABLED);
if (ret)
return ret;
}
if (if_aud) {
- ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
- if_aud,
- IF_AUD_DEC_PAD_IF_INPUT,
+ pad_source = media_get_pad_index(tuner, false,
+ PAD_SIGNAL_AUDIO);
+ pad_sink = media_get_pad_index(if_aud, true,
+ PAD_SIGNAL_AUDIO);
+ if (pad_source < 0 || pad_sink < 0) {
+ dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s) for audio: (%d, %d)\n",
+ pad_source, pad_sink);
+ return -EINVAL;
+ }
+ ret = media_create_pad_link(tuner, pad_source,
+ if_aud, pad_sink,
MEDIA_LNK_FL_ENABLED);
- if (ret)
+ if (ret) {
+ dev_warn(mdev->dev, "couldn't link tuner->audio PLL\n");
return ret;
+ }
} else {
if_aud = tuner;
}
@@ -131,27 +180,48 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
/* Create demod to V4L, VBI and SDR radio links */
if (io_v4l) {
- ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
- io_v4l, 0,
- MEDIA_LNK_FL_ENABLED);
- if (ret)
+ pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
+ if (pad_source < 0) {
+ dev_warn(mdev->dev, "couldn't get decoder output pad for V4L I/O\n");
+ return -EINVAL;
+ }
+ ret = media_create_pad_link(decoder, pad_source,
+ io_v4l, 0,
+ MEDIA_LNK_FL_ENABLED);
+ if (ret) {
+ dev_warn(mdev->dev, "couldn't link decoder output to V4L I/O\n");
return ret;
+ }
}
if (io_swradio) {
- ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
- io_swradio, 0,
- MEDIA_LNK_FL_ENABLED);
- if (ret)
+ pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
+ if (pad_source < 0) {
+ dev_warn(mdev->dev, "couldn't get decoder output pad for SDR\n");
+ return -EINVAL;
+ }
+ ret = media_create_pad_link(decoder, pad_source,
+ io_swradio, 0,
+ MEDIA_LNK_FL_ENABLED);
+ if (ret) {
+ dev_warn(mdev->dev, "couldn't link decoder output to SDR\n");
return ret;
+ }
}
if (io_vbi) {
- ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
+ pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
+ if (pad_source < 0) {
+ dev_warn(mdev->dev, "couldn't get decoder output pad for VBI\n");
+ return -EINVAL;
+ }
+ ret = media_create_pad_link(decoder, pad_source,
io_vbi, 0,
MEDIA_LNK_FL_ENABLED);
- if (ret)
+ if (ret) {
+ dev_warn(mdev->dev, "couldn't link decoder output to VBI\n");
return ret;
+ }
}
/* Create links for the media connectors */
@@ -161,15 +231,26 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
case MEDIA_ENT_F_CONN_RF:
if (!tuner)
continue;
-
+ pad_sink = media_get_pad_index(tuner, true,
+ PAD_SIGNAL_ANALOG);
+ if (pad_sink < 0) {
+ dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n");
+ return -EINVAL;
+ }
ret = media_create_pad_link(entity, 0, tuner,
- TUNER_PAD_RF_INPUT,
+ pad_sink,
flags);
break;
case MEDIA_ENT_F_CONN_SVIDEO:
case MEDIA_ENT_F_CONN_COMPOSITE:
+ pad_sink = media_get_pad_index(decoder, true,
+ PAD_SIGNAL_ANALOG);
+ if (pad_sink < 0) {
+ dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n");
+ return -EINVAL;
+ }
ret = media_create_pad_link(entity, 0, decoder,
- DEMOD_PAD_IF_INPUT,
+ pad_sink,
flags);
break;
default:
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 2b63fa6b6fc9..792f41dffe23 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -273,7 +273,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
p->flags |= V4L2_CHIP_FL_WRITABLE;
if (sd->ops->core && sd->ops->core->g_register)
p->flags |= V4L2_CHIP_FL_READABLE;
- strlcpy(p->name, sd->name, sizeof(p->name));
+ strscpy(p->name, sd->name, sizeof(p->name));
return 0;
}
#endif
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c
index a90b2eb112f9..874d290f9622 100644
--- a/drivers/staging/media/bcm2048/radio-bcm2048.c
+++ b/drivers/staging/media/bcm2048/radio-bcm2048.c
@@ -2304,9 +2304,9 @@ static int bcm2048_vidioc_querycap(struct file *file, void *priv,
{
struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
- strlcpy(capability->driver, BCM2048_DRIVER_NAME,
+ strscpy(capability->driver, BCM2048_DRIVER_NAME,
sizeof(capability->driver));
- strlcpy(capability->card, BCM2048_DRIVER_CARD,
+ strscpy(capability->card, BCM2048_DRIVER_CARD,
sizeof(capability->card));
snprintf(capability->bus_info, 32, "I2C: 0x%X", bdev->client->addr);
capability->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO |
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
index 4d09e8141fed..dcfeac818451 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
@@ -1801,7 +1801,7 @@ vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe, struct platform_device *pdev)
v4l2_subdev_init(sd, &ipipe_v4l2_ops);
sd->internal_ops = &ipipe_v4l2_internal_ops;
- strlcpy(sd->name, "DAVINCI IPIPE", sizeof(sd->name));
+ strscpy(sd->name, "DAVINCI IPIPE", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for davinci subdevs */
v4l2_set_subdevdata(sd, ipipe);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
index 11c9edfbdbe3..a53231b08d30 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
@@ -1020,7 +1020,7 @@ int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif,
v4l2_subdev_init(sd, &ipipeif_v4l2_ops);
sd->internal_ops = &ipipeif_v4l2_internal_ops;
- strlcpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name));
+ strscpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for davinci subdevs */
v4l2_set_subdevdata(sd, ipipeif);
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
index 745e33fa6bea..39eb0819ab4e 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
@@ -2038,7 +2038,7 @@ int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev)
isif->video_out.ops = &isif_video_ops;
v4l2_subdev_init(sd, &isif_v4l2_ops);
sd->internal_ops = &isif_v4l2_internal_ops;
- strlcpy(sd->name, "DAVINCI ISIF", sizeof(sd->name));
+ strscpy(sd->name, "DAVINCI ISIF", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for davinci subdevs */
v4l2_set_subdevdata(sd, isif);
sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
index 6c5fcd6c691a..72bbbc34d18c 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
@@ -1903,7 +1903,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz,
v4l2_subdev_init(sd, &resizer_v4l2_ops);
sd->internal_ops = &resizer_v4l2_internal_ops;
- strlcpy(sd->name, "DAVINCI RESIZER CROP", sizeof(sd->name));
+ strscpy(sd->name, "DAVINCI RESIZER CROP", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for davinci subdevs */
v4l2_set_subdevdata(sd, vpfe_rsz);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -1927,7 +1927,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz,
v4l2_subdev_init(sd, &resizer_v4l2_ops);
sd->internal_ops = &resizer_v4l2_internal_ops;
- strlcpy(sd->name, "DAVINCI RESIZER A", sizeof(sd->name));
+ strscpy(sd->name, "DAVINCI RESIZER A", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for davinci subdevs */
v4l2_set_subdevdata(sd, vpfe_rsz);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -1949,7 +1949,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz,
v4l2_subdev_init(sd, &resizer_v4l2_ops);
sd->internal_ops = &resizer_v4l2_internal_ops;
- strlcpy(sd->name, "DAVINCI RESIZER B", sizeof(sd->name));
+ strscpy(sd->name, "DAVINCI RESIZER B", sizeof(sd->name));
sd->grp_id = 1 << 16; /* group ID for davinci subdevs */
v4l2_set_subdevdata(sd, vpfe_rsz);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
index e55c815b9b65..bdf6ee5ad96c 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
@@ -639,7 +639,8 @@ static int vpfe_probe(struct platform_device *pdev)
goto probe_disable_clock;
vpfe_dev->media_dev.dev = vpfe_dev->pdev;
- strcpy((char *)&vpfe_dev->media_dev.model, "davinci-media");
+ strscpy((char *)&vpfe_dev->media_dev.model, "davinci-media",
+ sizeof(vpfe_dev->media_dev.model));
ret = media_device_register(&vpfe_dev->media_dev);
if (ret) {
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 1269a983455e..5e42490331b7 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -618,9 +618,9 @@ static int vpfe_querycap(struct file *file, void *priv,
cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
- strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
- strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
- strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
+ strscpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
+ strscpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
+ strscpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
return 0;
}
diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO
index 9eb7326f3fc6..aeeb15494a49 100644
--- a/drivers/staging/media/imx/TODO
+++ b/drivers/staging/media/imx/TODO
@@ -17,29 +17,15 @@
decided whether this feature is useful enough to make it generally
available by exporting to v4l2-core.
-- The OF graph is walked at probe time to form the list of fwnodes to
- be passed to v4l2_async_notifier_register(), starting from the IPU
- CSI ports. And after all async subdevices have been bound,
- v4l2_fwnode_parse_link() is used to form the media links between
- the entities discovered by walking the OF graph.
+- After all async subdevices have been bound, v4l2_fwnode_parse_link()
+ is used to form the media links between the devices discovered in
+ the OF graph.
While this approach allows support for arbitrary OF graphs, there
are some assumptions for this to work:
- 1. All port parent nodes reachable in the graph from the IPU CSI
- ports bind to V4L2 async subdevice drivers.
-
- If a device has mixed-use ports such as video plus audio, the
- endpoints from the audio ports are followed to devices that must
- bind to V4L2 subdevice drivers, and not for example, to an ALSA
- driver or a non-V4L2 media driver. If the device were bound to
- such a driver, imx-media would never get an async completion
- notification because the device fwnode was added to the async
- list, but the driver does not interface with the V4L2 async
- framework.
-
- 2. Every port reachable in the graph is treated as a media pad,
- owned by the V4L2 subdevice that is bound to the port's parent.
+ 1. If a port owned by a device in the graph has endpoint nodes, the
+ port is treated as a media pad.
This presents problems for devices that don't make this port = pad
assumption. Examples are SMIAPP compatible cameras which define only
@@ -54,9 +40,8 @@
possible long-term solution is to implement a subdev API that
maps a port id to a media pad index.
- 3. Every endpoint of a port reachable in the graph is treated as
- a media link, between V4L2 subdevices that are bound to the
- port parents of the local and remote endpoints.
+ 2. Every endpoint of a port owned by a device in the graph is treated
+ as a media link.
Which means a port must not contain mixed-use endpoints, they
must all refer to media links between V4L2 subdevices.
diff --git a/drivers/staging/media/imx/imx-media-capture.c b/drivers/staging/media/imx/imx-media-capture.c
index 256039ce561e..b37e1186eb2f 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -73,8 +73,8 @@ static int vidioc_querycap(struct file *file, void *fh,
{
struct capture_priv *priv = video_drvdata(file);
- strlcpy(cap->driver, "imx-media-capture", sizeof(cap->driver));
- strlcpy(cap->card, "imx-media-capture", sizeof(cap->card));
+ strscpy(cap->driver, "imx-media-capture", sizeof(cap->driver));
+ strscpy(cap->card, "imx-media-capture", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:%s", priv->src_sd->name);
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index cd2c291e1e94..4223f8d418ae 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -124,7 +124,7 @@ static inline struct csi_priv *sd_to_dev(struct v4l2_subdev *sdev)
static inline bool is_parallel_bus(struct v4l2_fwnode_endpoint *ep)
{
- return ep->bus_type != V4L2_MBUS_CSI2;
+ return ep->bus_type != V4L2_MBUS_CSI2_DPHY;
}
static inline bool is_parallel_16bit_bus(struct v4l2_fwnode_endpoint *ep)
@@ -165,6 +165,9 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
struct v4l2_subdev *sd;
struct media_pad *pad;
+ if (!IS_ENABLED(CONFIG_OF))
+ return -ENXIO;
+
if (!priv->src_sd)
return -EPIPE;
@@ -1050,7 +1053,7 @@ static int csi_link_validate(struct v4l2_subdev *sd,
struct v4l2_subdev_format *sink_fmt)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
- struct v4l2_fwnode_endpoint upstream_ep = {};
+ struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 };
bool is_csi2;
int ret;
@@ -1164,7 +1167,7 @@ static int csi_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_mbus_code_enum *code)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
- struct v4l2_fwnode_endpoint upstream_ep;
+ struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 };
const struct imx_media_pixfmt *incc;
struct v4l2_mbus_framefmt *infmt;
int ret = 0;
@@ -1403,7 +1406,7 @@ static int csi_set_fmt(struct v4l2_subdev *sd,
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
struct imx_media_video_dev *vdev = priv->vdev;
- struct v4l2_fwnode_endpoint upstream_ep;
+ struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 };
const struct imx_media_pixfmt *cc;
struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
@@ -1542,7 +1545,7 @@ static int csi_set_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_selection *sel)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
- struct v4l2_fwnode_endpoint upstream_ep;
+ struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 };
struct v4l2_mbus_framefmt *infmt;
struct v4l2_rect *crop, *compose;
int pad, ret;
@@ -1780,6 +1783,61 @@ static const struct v4l2_subdev_internal_ops csi_internal_ops = {
.unregistered = csi_unregistered,
};
+static int imx_csi_parse_endpoint(struct device *dev,
+ struct v4l2_fwnode_endpoint *vep,
+ struct v4l2_async_subdev *asd)
+{
+ return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL;
+}
+
+static int imx_csi_async_register(struct csi_priv *priv)
+{
+ struct v4l2_async_notifier *notifier;
+ struct fwnode_handle *fwnode;
+ unsigned int port;
+ int ret;
+
+ notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
+ if (!notifier)
+ return -ENOMEM;
+
+ v4l2_async_notifier_init(notifier);
+
+ fwnode = dev_fwnode(priv->dev);
+
+ /* get this CSI's port id */
+ ret = fwnode_property_read_u32(fwnode, "reg", &port);
+ if (ret < 0)
+ goto out_free;
+
+ ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
+ priv->dev->parent, notifier, sizeof(struct v4l2_async_subdev),
+ port, imx_csi_parse_endpoint);
+ if (ret < 0)
+ goto out_cleanup;
+
+ ret = v4l2_async_subdev_notifier_register(&priv->sd, notifier);
+ if (ret < 0)
+ goto out_cleanup;
+
+ ret = v4l2_async_register_subdev(&priv->sd);
+ if (ret < 0)
+ goto out_unregister;
+
+ priv->sd.subdev_notifier = notifier;
+
+ return 0;
+
+out_unregister:
+ v4l2_async_notifier_unregister(notifier);
+out_cleanup:
+ v4l2_async_notifier_cleanup(notifier);
+out_free:
+ kfree(notifier);
+
+ return ret;
+}
+
static int imx_csi_probe(struct platform_device *pdev)
{
struct ipu_client_platformdata *pdata;
@@ -1849,7 +1907,7 @@ static int imx_csi_probe(struct platform_device *pdev)
goto free;
}
- ret = v4l2_async_register_subdev(&priv->sd);
+ ret = imx_csi_async_register(priv);
if (ret)
goto free;
diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index 3f48f5ceb6ea..026b9cbe581d 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -29,47 +29,14 @@
static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
{
- return container_of(n, struct imx_media_dev, subdev_notifier);
+ return container_of(n, struct imx_media_dev, notifier);
}
/*
- * Find an asd by fwnode or device name. This is called during
- * driver load to form the async subdev list and bind them.
- */
-static struct v4l2_async_subdev *
-find_async_subdev(struct imx_media_dev *imxmd,
- struct fwnode_handle *fwnode,
- const char *devname)
-{
- struct imx_media_async_subdev *imxasd;
- struct v4l2_async_subdev *asd;
-
- list_for_each_entry(imxasd, &imxmd->asd_list, list) {
- asd = &imxasd->asd;
- switch (asd->match_type) {
- case V4L2_ASYNC_MATCH_FWNODE:
- if (fwnode && asd->match.fwnode == fwnode)
- return asd;
- break;
- case V4L2_ASYNC_MATCH_DEVNAME:
- if (devname && !strcmp(asd->match.device_name,
- devname))
- return asd;
- break;
- default:
- break;
- }
- }
-
- return NULL;
-}
-
-
-/*
- * Adds a subdev to the async subdev list. If fwnode is non-NULL, adds
- * the async as a V4L2_ASYNC_MATCH_FWNODE match type, otherwise as
- * a V4L2_ASYNC_MATCH_DEVNAME match type using the dev_name of the
- * given platform_device. This is called during driver load when
+ * Adds a subdev to the root notifier's async subdev list. If fwnode is
+ * non-NULL, adds the async as a V4L2_ASYNC_MATCH_FWNODE match type,
+ * otherwise as a V4L2_ASYNC_MATCH_DEVNAME match type using the dev_name
+ * of the given platform_device. This is called during driver load when
* forming the async subdev list.
*/
int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
@@ -80,52 +47,43 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
struct imx_media_async_subdev *imxasd;
struct v4l2_async_subdev *asd;
const char *devname = NULL;
- int ret = 0;
-
- mutex_lock(&imxmd->mutex);
+ int ret;
- if (pdev)
+ if (fwnode) {
+ asd = v4l2_async_notifier_add_fwnode_subdev(
+ &imxmd->notifier, fwnode, sizeof(*imxasd));
+ } else {
devname = dev_name(&pdev->dev);
-
- /* return -EEXIST if this asd already added */
- if (find_async_subdev(imxmd, fwnode, devname)) {
- if (np)
- dev_dbg(imxmd->md.dev, "%s: already added %pOFn\n",
- __func__, np);
- else
- dev_dbg(imxmd->md.dev, "%s: already added %s\n",
- __func__, devname);
- ret = -EEXIST;
- goto out;
+ asd = v4l2_async_notifier_add_devname_subdev(
+ &imxmd->notifier, devname, sizeof(*imxasd));
}
- imxasd = devm_kzalloc(imxmd->md.dev, sizeof(*imxasd), GFP_KERNEL);
- if (!imxasd) {
- ret = -ENOMEM;
- goto out;
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ if (ret == -EEXIST) {
+ if (np)
+ dev_dbg(imxmd->md.dev, "%s: already added %pOFn\n",
+ __func__, np);
+ else
+ dev_dbg(imxmd->md.dev, "%s: already added %s\n",
+ __func__, devname);
+ }
+ return ret;
}
- asd = &imxasd->asd;
- if (fwnode) {
- asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
- asd->match.fwnode = fwnode;
+ imxasd = to_imx_media_asd(asd);
+
+ if (devname)
+ imxasd->pdev = pdev;
+
+ if (np)
dev_dbg(imxmd->md.dev, "%s: added %pOFn, match type FWNODE\n",
__func__, np);
- } else {
- asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
- asd->match.device_name = devname;
- imxasd->pdev = pdev;
+ else
dev_dbg(imxmd->md.dev, "%s: added %s, match type DEVNAME\n",
__func__, devname);
- }
-
- list_add_tail(&imxasd->list, &imxmd->asd_list);
-
- imxmd->subdev_notifier.num_subdevs++;
-out:
- mutex_unlock(&imxmd->mutex);
- return ret;
+ return 0;
}
/*
@@ -180,7 +138,7 @@ out:
}
/*
- * create the media links for all subdevs that registered async.
+ * Create the media links for all subdevs that registered.
* Called after all async subdevs have bound.
*/
static int imx_media_create_links(struct v4l2_async_notifier *notifier)
@@ -189,14 +147,7 @@ static int imx_media_create_links(struct v4l2_async_notifier *notifier)
struct v4l2_subdev *sd;
int ret;
- /*
- * Only links are created between subdevices that are known
- * to the async notifier. If there are other non-async subdevices,
- * they were created internally by some subdevice (smiapp is one
- * example). In those cases it is expected the subdevice is
- * responsible for creating those internal links.
- */
- list_for_each_entry(sd, &notifier->done, async_list) {
+ list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
switch (sd->grp_id) {
case IMX_MEDIA_GRP_ID_VDIC:
case IMX_MEDIA_GRP_ID_IC_PRP:
@@ -216,7 +167,10 @@ static int imx_media_create_links(struct v4l2_async_notifier *notifier)
imx_media_create_csi_of_links(imxmd, sd);
break;
default:
- /* this is an external fwnode subdev */
+ /*
+ * if this subdev has fwnode links, create media
+ * links for them.
+ */
imx_media_create_of_links(imxmd, sd);
break;
}
@@ -492,10 +446,8 @@ static int imx_media_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
- struct imx_media_async_subdev *imxasd;
- struct v4l2_async_subdev **subdevs;
struct imx_media_dev *imxmd;
- int num_subdevs, i, ret;
+ int ret;
imxmd = devm_kzalloc(dev, sizeof(*imxmd), GFP_KERNEL);
if (!imxmd)
@@ -503,14 +455,14 @@ static int imx_media_probe(struct platform_device *pdev)
dev_set_drvdata(dev, imxmd);
- strlcpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model));
+ strscpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model));
imxmd->md.ops = &imx_media_md_ops;
imxmd->md.dev = dev;
mutex_init(&imxmd->mutex);
imxmd->v4l2_dev.mdev = &imxmd->md;
- strlcpy(imxmd->v4l2_dev.name, "imx-media",
+ strscpy(imxmd->v4l2_dev.name, "imx-media",
sizeof(imxmd->v4l2_dev.name));
media_device_init(&imxmd->md);
@@ -524,47 +476,34 @@ static int imx_media_probe(struct platform_device *pdev)
dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
- INIT_LIST_HEAD(&imxmd->asd_list);
INIT_LIST_HEAD(&imxmd->vdev_list);
+ v4l2_async_notifier_init(&imxmd->notifier);
+
ret = imx_media_add_of_subdevs(imxmd, node);
if (ret) {
v4l2_err(&imxmd->v4l2_dev,
"add_of_subdevs failed with %d\n", ret);
- goto unreg_dev;
+ goto notifier_cleanup;
}
ret = imx_media_add_internal_subdevs(imxmd);
if (ret) {
v4l2_err(&imxmd->v4l2_dev,
"add_internal_subdevs failed with %d\n", ret);
- goto unreg_dev;
+ goto notifier_cleanup;
}
- num_subdevs = imxmd->subdev_notifier.num_subdevs;
-
/* no subdevs? just bail */
- if (num_subdevs == 0) {
+ if (list_empty(&imxmd->notifier.asd_list)) {
ret = -ENODEV;
- goto unreg_dev;
+ goto notifier_cleanup;
}
- subdevs = devm_kcalloc(imxmd->md.dev, num_subdevs, sizeof(*subdevs),
- GFP_KERNEL);
- if (!subdevs) {
- ret = -ENOMEM;
- goto unreg_dev;
- }
-
- i = 0;
- list_for_each_entry(imxasd, &imxmd->asd_list, list)
- subdevs[i++] = &imxasd->asd;
-
/* prepare the async subdev notifier and register it */
- imxmd->subdev_notifier.subdevs = subdevs;
- imxmd->subdev_notifier.ops = &imx_media_subdev_ops;
+ imxmd->notifier.ops = &imx_media_subdev_ops;
ret = v4l2_async_notifier_register(&imxmd->v4l2_dev,
- &imxmd->subdev_notifier);
+ &imxmd->notifier);
if (ret) {
v4l2_err(&imxmd->v4l2_dev,
"v4l2_async_notifier_register failed with %d\n", ret);
@@ -575,7 +514,8 @@ static int imx_media_probe(struct platform_device *pdev)
del_int:
imx_media_remove_internal_subdevs(imxmd);
-unreg_dev:
+notifier_cleanup:
+ v4l2_async_notifier_cleanup(&imxmd->notifier);
v4l2_device_unregister(&imxmd->v4l2_dev);
cleanup:
media_device_cleanup(&imxmd->md);
@@ -589,8 +529,9 @@ static int imx_media_remove(struct platform_device *pdev)
v4l2_info(&imxmd->v4l2_dev, "Removing imx-media\n");
- v4l2_async_notifier_unregister(&imxmd->subdev_notifier);
+ v4l2_async_notifier_unregister(&imxmd->notifier);
imx_media_remove_internal_subdevs(imxmd);
+ v4l2_async_notifier_cleanup(&imxmd->notifier);
v4l2_device_unregister(&imxmd->v4l2_dev);
media_device_unregister(&imxmd->md);
media_device_cleanup(&imxmd->md);
diff --git a/drivers/staging/media/imx/imx-media-internal-sd.c b/drivers/staging/media/imx/imx-media-internal-sd.c
index daf66c2d69ab..0fdc45dbfb76 100644
--- a/drivers/staging/media/imx/imx-media-internal-sd.c
+++ b/drivers/staging/media/imx/imx-media-internal-sd.c
@@ -350,8 +350,11 @@ remove:
void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd)
{
struct imx_media_async_subdev *imxasd;
+ struct v4l2_async_subdev *asd;
+
+ list_for_each_entry(asd, &imxmd->notifier.asd_list, asd_list) {
+ imxasd = to_imx_media_asd(asd);
- list_for_each_entry(imxasd, &imxmd->asd_list, list) {
if (!imxasd->pdev)
continue;
diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c
index 163437e421c5..b2e840f96c50 100644
--- a/drivers/staging/media/imx/imx-media-of.c
+++ b/drivers/staging/media/imx/imx-media-of.c
@@ -20,74 +20,19 @@
#include <video/imx-ipu-v3.h>
#include "imx-media.h"
-static int of_get_port_count(const struct device_node *np)
+static int of_add_csi(struct imx_media_dev *imxmd, struct device_node *csi_np)
{
- struct device_node *ports, *child;
- int num = 0;
-
- /* check if this node has a ports subnode */
- ports = of_get_child_by_name(np, "ports");
- if (ports)
- np = ports;
-
- for_each_child_of_node(np, child)
- if (of_node_cmp(child->name, "port") == 0)
- num++;
-
- of_node_put(ports);
- return num;
-}
-
-/*
- * find the remote device node given local endpoint node
- */
-static bool of_get_remote(struct device_node *epnode,
- struct device_node **remote_node)
-{
- struct device_node *rp, *rpp;
- struct device_node *remote;
- bool is_csi_port;
-
- rp = of_graph_get_remote_port(epnode);
- rpp = of_graph_get_remote_port_parent(epnode);
-
- if (of_device_is_compatible(rpp, "fsl,imx6q-ipu")) {
- /* the remote is one of the CSI ports */
- remote = rp;
- of_node_put(rpp);
- is_csi_port = true;
- } else {
- remote = rpp;
- of_node_put(rp);
- is_csi_port = false;
- }
-
- if (!of_device_is_available(remote)) {
- of_node_put(remote);
- *remote_node = NULL;
- } else {
- *remote_node = remote;
- }
-
- return is_csi_port;
-}
-
-static int
-of_parse_subdev(struct imx_media_dev *imxmd, struct device_node *sd_np,
- bool is_csi_port)
-{
- int i, num_ports, ret;
+ int ret;
- if (!of_device_is_available(sd_np)) {
+ if (!of_device_is_available(csi_np)) {
dev_dbg(imxmd->md.dev, "%s: %pOFn not enabled\n", __func__,
- sd_np);
+ csi_np);
/* unavailable is not an error */
return 0;
}
- /* register this subdev with async notifier */
- ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(sd_np),
- NULL);
+ /* add CSI fwnode to async notifier */
+ ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np), NULL);
if (ret) {
if (ret == -EEXIST) {
/* already added, everything is fine */
@@ -98,42 +43,7 @@ of_parse_subdev(struct imx_media_dev *imxmd, struct device_node *sd_np,
return ret;
}
- /*
- * the ipu-csi has one sink port. The source pads are not
- * represented in the device tree by port nodes, but are
- * described by the internal pads and links later.
- */
- num_ports = is_csi_port ? 1 : of_get_port_count(sd_np);
-
- for (i = 0; i < num_ports; i++) {
- struct device_node *epnode = NULL, *port, *remote_np;
-
- port = is_csi_port ? sd_np : of_graph_get_port_by_id(sd_np, i);
- if (!port)
- continue;
-
- for_each_child_of_node(port, epnode) {
- bool remote_is_csi;
-
- remote_is_csi = of_get_remote(epnode, &remote_np);
- if (!remote_np)
- continue;
-
- ret = of_parse_subdev(imxmd, remote_np, remote_is_csi);
- of_node_put(remote_np);
- if (ret)
- break;
- }
-
- if (port != sd_np)
- of_node_put(port);
- if (ret) {
- of_node_put(epnode);
- break;
- }
- }
-
- return ret;
+ return 0;
}
int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
@@ -147,7 +57,7 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
if (!csi_np)
break;
- ret = of_parse_subdev(imxmd, csi_np, true);
+ ret = of_add_csi(imxmd, csi_np);
of_node_put(csi_np);
if (ret)
return ret;
diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c
index 8aa13403b09d..0eaa353d5cb3 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -88,7 +88,7 @@ static const struct imx_media_pixfmt rgb_formats[] = {
.cs = IPUV3_COLORSPACE_RGB,
.bpp = 24,
}, {
- .fourcc = V4L2_PIX_FMT_RGB32,
+ .fourcc = V4L2_PIX_FMT_XRGB32,
.codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
.cs = IPUV3_COLORSPACE_RGB,
.bpp = 32,
@@ -212,7 +212,7 @@ static const struct imx_media_pixfmt ipu_yuv_formats[] = {
static const struct imx_media_pixfmt ipu_rgb_formats[] = {
{
- .fourcc = V4L2_PIX_FMT_RGB32,
+ .fourcc = V4L2_PIX_FMT_XRGB32,
.codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
.cs = IPUV3_COLORSPACE_RGB,
.bpp = 32,
diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h
index 57bd094cf765..bc7feb81937c 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -119,12 +119,11 @@ struct imx_media_internal_sd_platformdata {
int ipu_id;
};
-
struct imx_media_async_subdev {
+ /* the base asd - must be first in this struct */
struct v4l2_async_subdev asd;
/* the platform device of IPU-internal subdevs */
struct platform_device *pdev;
- struct list_head list;
};
static inline struct imx_media_async_subdev *
@@ -149,8 +148,7 @@ struct imx_media_dev {
struct ipu_soc *ipu[2];
/* for async subdev registration */
- struct list_head asd_list;
- struct v4l2_async_notifier subdev_notifier;
+ struct v4l2_async_notifier notifier;
};
enum codespace_sel {
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index ceeeb3069a02..6a1cee55a49b 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -551,35 +551,34 @@ static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
.registered = csi2_registered,
};
-static int csi2_parse_endpoints(struct csi2_dev *csi2)
+static int csi2_parse_endpoint(struct device *dev,
+ struct v4l2_fwnode_endpoint *vep,
+ struct v4l2_async_subdev *asd)
{
- struct device_node *node = csi2->dev->of_node;
- struct device_node *epnode;
- struct v4l2_fwnode_endpoint ep;
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi2_dev *csi2 = sd_to_dev(sd);
- epnode = of_graph_get_endpoint_by_regs(node, 0, -1);
- if (!epnode) {
- v4l2_err(&csi2->sd, "failed to get sink endpoint node\n");
+ if (!fwnode_device_is_available(asd->match.fwnode)) {
+ v4l2_err(&csi2->sd, "remote is not available\n");
return -EINVAL;
}
- v4l2_fwnode_endpoint_parse(of_fwnode_handle(epnode), &ep);
- of_node_put(epnode);
-
- if (ep.bus_type != V4L2_MBUS_CSI2) {
+ if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
v4l2_err(&csi2->sd, "invalid bus type, must be MIPI CSI2\n");
return -EINVAL;
}
- csi2->bus = ep.bus.mipi_csi2;
+ csi2->bus = vep->bus.mipi_csi2;
dev_dbg(csi2->dev, "data lanes: %d\n", csi2->bus.num_data_lanes);
dev_dbg(csi2->dev, "flags: 0x%08x\n", csi2->bus.flags);
+
return 0;
}
static int csi2_probe(struct platform_device *pdev)
{
+ unsigned int sink_port = 0;
struct csi2_dev *csi2;
struct resource *res;
int ret;
@@ -597,14 +596,10 @@ static int csi2_probe(struct platform_device *pdev)
csi2->sd.dev = &pdev->dev;
csi2->sd.owner = THIS_MODULE;
csi2->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
- strcpy(csi2->sd.name, DEVICE_NAME);
+ strscpy(csi2->sd.name, DEVICE_NAME, sizeof(csi2->sd.name));
csi2->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
csi2->sd.grp_id = IMX_MEDIA_GRP_ID_CSI2;
- ret = csi2_parse_endpoints(csi2);
- if (ret)
- return ret;
-
csi2->pllref_clk = devm_clk_get(&pdev->dev, "ref");
if (IS_ERR(csi2->pllref_clk)) {
v4l2_err(&csi2->sd, "failed to get pll reference clock\n");
@@ -654,7 +649,9 @@ static int csi2_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, &csi2->sd);
- ret = v4l2_async_register_subdev(&csi2->sd);
+ ret = v4l2_async_register_fwnode_subdev(
+ &csi2->sd, sizeof(struct v4l2_async_subdev),
+ &sink_port, 1, csi2_parse_endpoint);
if (ret)
goto dphy_off;
diff --git a/drivers/staging/media/imx074/imx074.c b/drivers/staging/media/imx074/imx074.c
index 77f1e0243d6e..1676c166dc83 100644
--- a/drivers/staging/media/imx074/imx074.c
+++ b/drivers/staging/media/imx074/imx074.c
@@ -223,7 +223,6 @@ static int imx074_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:
return 0;
default:
@@ -263,7 +262,7 @@ static int imx074_s_power(struct v4l2_subdev *sd, int on)
static int imx074_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/staging/media/mt9t031/mt9t031.c b/drivers/staging/media/mt9t031/mt9t031.c
index 4802d30e47de..4ff179302b4f 100644
--- a/drivers/staging/media/mt9t031/mt9t031.c
+++ b/drivers/staging/media/mt9t031/mt9t031.c
@@ -330,7 +330,6 @@ static int mt9t031_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.left = MT9T031_COLUMN_SKIP;
sel->r.top = MT9T031_ROW_SKIP;
sel->r.width = MT9T031_MAX_WIDTH;
diff --git a/drivers/staging/media/omap4iss/Kconfig b/drivers/staging/media/omap4iss/Kconfig
index dddd27335cb4..841cc0b3ce13 100644
--- a/drivers/staging/media/omap4iss/Kconfig
+++ b/drivers/staging/media/omap4iss/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config VIDEO_OMAP4
tristate "OMAP 4 Camera support"
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && I2C
diff --git a/drivers/staging/media/omap4iss/Makefile b/drivers/staging/media/omap4iss/Makefile
index a716ce936cf6..e64d489a4a76 100644
--- a/drivers/staging/media/omap4iss/Makefile
+++ b/drivers/staging/media/omap4iss/Makefile
@@ -1,4 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
# Makefile for OMAP4 ISS driver
+#
omap4-iss-objs += \
iss.o iss_csi2.o iss_csiphy.o iss_ipipeif.o iss_ipipe.o iss_resizer.o iss_video.o
diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
index b1036baebb03..c8be1db532ab 100644
--- a/drivers/staging/media/omap4iss/iss.c
+++ b/drivers/staging/media/omap4iss/iss.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* TI OMAP4 ISS V4L2 Driver
*
* Copyright (C) 2012, Texas Instruments
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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/clk.h>
@@ -989,7 +985,7 @@ static int iss_register_entities(struct iss_device *iss)
int ret;
iss->media_dev.dev = iss->dev;
- strlcpy(iss->media_dev.model, "TI OMAP4 ISS",
+ strscpy(iss->media_dev.model, "TI OMAP4 ISS",
sizeof(iss->media_dev.model));
iss->media_dev.hw_revision = iss->revision;
iss->media_dev.ops = &iss_media_ops;
diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h
index 760ee27da704..b88f9529683c 100644
--- a/drivers/staging/media/omap4iss/iss.h
+++ b/drivers/staging/media/omap4iss/iss.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* TI OMAP4 ISS V4L2 Driver
*
* Copyright (C) 2012 Texas Instruments.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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.
*/
#ifndef _OMAP4_ISS_H_
diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
index f6acc541e8a2..059cf5bd3c36 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.c
+++ b/drivers/staging/media/omap4iss/iss_csi2.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* TI OMAP4 ISS V4L2 Driver - CSI PHY module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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>
diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h
index 24ab378d469f..3f7fd9cff41d 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.h
+++ b/drivers/staging/media/omap4iss/iss_csi2.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* TI OMAP4 ISS V4L2 Driver - CSI2 module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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.
*/
#ifndef OMAP4_ISS_CSI2_H
diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c
index 748607f8918f..96f2ce045138 100644
--- a/drivers/staging/media/omap4iss/iss_csiphy.c
+++ b/drivers/staging/media/omap4iss/iss_csiphy.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* TI OMAP4 ISS V4L2 Driver - CSI PHY module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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>
diff --git a/drivers/staging/media/omap4iss/iss_csiphy.h b/drivers/staging/media/omap4iss/iss_csiphy.h
index a0f2d974daeb..44408e4fcf3b 100644
--- a/drivers/staging/media/omap4iss/iss_csiphy.h
+++ b/drivers/staging/media/omap4iss/iss_csiphy.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* TI OMAP4 ISS V4L2 Driver - CSI PHY module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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.
*/
#ifndef OMAP4_ISS_CSI_PHY_H
diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c
index d86ef8a031f2..26be078b69f3 100644
--- a/drivers/staging/media/omap4iss/iss_ipipe.c
+++ b/drivers/staging/media/omap4iss/iss_ipipe.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* TI OMAP4 ISS V4L2 Driver - ISP IPIPE module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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>
@@ -507,7 +503,7 @@ static int ipipe_init_entities(struct iss_ipipe_device *ipipe)
v4l2_subdev_init(sd, &ipipe_v4l2_ops);
sd->internal_ops = &ipipe_v4l2_internal_ops;
- strlcpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name));
+ strscpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name));
sd->grp_id = BIT(16); /* group ID for iss subdevs */
v4l2_set_subdevdata(sd, ipipe);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/staging/media/omap4iss/iss_ipipe.h b/drivers/staging/media/omap4iss/iss_ipipe.h
index d5b441d9cb31..53b42aac1696 100644
--- a/drivers/staging/media/omap4iss/iss_ipipe.h
+++ b/drivers/staging/media/omap4iss/iss_ipipe.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* TI OMAP4 ISS V4L2 Driver - ISP IPIPE module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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.
*/
#ifndef OMAP4_ISS_IPIPE_H
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
index cb88b2bd0d82..c2978d02e797 100644
--- a/drivers/staging/media/omap4iss/iss_ipipeif.c
+++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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>
@@ -738,7 +734,7 @@ static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif)
v4l2_subdev_init(sd, &ipipeif_v4l2_ops);
sd->internal_ops = &ipipeif_v4l2_internal_ops;
- strlcpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name));
+ strscpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name));
sd->grp_id = BIT(16); /* group ID for iss subdevs */
v4l2_set_subdevdata(sd, ipipeif);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.h b/drivers/staging/media/omap4iss/iss_ipipeif.h
index bad32b1d6ad8..69792333a62e 100644
--- a/drivers/staging/media/omap4iss/iss_ipipeif.h
+++ b/drivers/staging/media/omap4iss/iss_ipipeif.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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.
*/
#ifndef OMAP4_ISS_IPIPEIF_H
diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h
index cb415e898aca..09a7375c89ac 100644
--- a/drivers/staging/media/omap4iss/iss_regs.h
+++ b/drivers/staging/media/omap4iss/iss_regs.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* TI OMAP4 ISS V4L2 Driver - Register defines
*
* Copyright (C) 2012 Texas Instruments.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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.
*/
#ifndef _OMAP4_ISS_REGS_H_
diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
index 4bbfa20b3c38..3b6875cbca9b 100644
--- a/drivers/staging/media/omap4iss/iss_resizer.c
+++ b/drivers/staging/media/omap4iss/iss_resizer.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* TI OMAP4 ISS V4L2 Driver - ISP RESIZER module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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>
@@ -781,7 +777,7 @@ static int resizer_init_entities(struct iss_resizer_device *resizer)
v4l2_subdev_init(sd, &resizer_v4l2_ops);
sd->internal_ops = &resizer_v4l2_internal_ops;
- strlcpy(sd->name, "OMAP4 ISS ISP resizer", sizeof(sd->name));
+ strscpy(sd->name, "OMAP4 ISS ISP resizer", sizeof(sd->name));
sd->grp_id = BIT(16); /* group ID for iss subdevs */
v4l2_set_subdevdata(sd, resizer);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/staging/media/omap4iss/iss_resizer.h b/drivers/staging/media/omap4iss/iss_resizer.h
index 8b7c5fe9ffed..cb937fccc21f 100644
--- a/drivers/staging/media/omap4iss/iss_resizer.h
+++ b/drivers/staging/media/omap4iss/iss_resizer.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* TI OMAP4 ISS V4L2 Driver - ISP RESIZER module
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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.
*/
#ifndef OMAP4_ISS_RESIZER_H
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
index 16478fe9e3f8..c1322aeaf01e 100644
--- a/drivers/staging/media/omap4iss/iss_video.c
+++ b/drivers/staging/media/omap4iss/iss_video.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* TI OMAP4 ISS V4L2 Driver - Generic video node
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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/clk.h>
@@ -534,9 +530,9 @@ iss_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
{
struct iss_video *video = video_drvdata(file);
- strlcpy(cap->driver, ISS_VIDEO_DRIVER_NAME, sizeof(cap->driver));
- strlcpy(cap->card, video->video.name, sizeof(cap->card));
- strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
+ strscpy(cap->driver, ISS_VIDEO_DRIVER_NAME, sizeof(cap->driver));
+ strscpy(cap->card, video->video.name, sizeof(cap->card));
+ strscpy(cap->bus_info, "media", sizeof(cap->bus_info));
if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
@@ -573,7 +569,7 @@ iss_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f)
if (index == 0) {
f->pixelformat = info->pixelformat;
- strlcpy(f->description, info->description,
+ strscpy(f->description, info->description,
sizeof(f->description));
return 0;
}
@@ -1053,7 +1049,7 @@ iss_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
if (input->index > 0)
return -EINVAL;
- strlcpy(input->name, "camera", sizeof(input->name));
+ strscpy(input->name, "camera", sizeof(input->name));
input->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h
index d7e05d04512c..f22489edb562 100644
--- a/drivers/staging/media/omap4iss/iss_video.h
+++ b/drivers/staging/media/omap4iss/iss_video.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* TI OMAP4 ISS V4L2 Driver - Generic video node
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
- *
- * 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.
*/
#ifndef OMAP4_ISS_VIDEO_H
diff --git a/drivers/staging/media/zoran/zoran_card.c b/drivers/staging/media/zoran/zoran_card.c
index a6b9ebd20263..94dadbba7cd5 100644
--- a/drivers/staging/media/zoran/zoran_card.c
+++ b/drivers/staging/media/zoran/zoran_card.c
@@ -706,7 +706,7 @@ zoran_register_i2c (struct zoran *zr)
{
zr->i2c_algo = zoran_i2c_bit_data_template;
zr->i2c_algo.data = zr;
- strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr),
+ strscpy(zr->i2c_adapter.name, ZR_DEVNAME(zr),
sizeof(zr->i2c_adapter.name));
i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev);
zr->i2c_adapter.algo_data = &zr->i2c_algo;
@@ -1048,7 +1048,7 @@ static int zr36057_init (struct zoran *zr)
*zr->video_dev = zoran_template;
zr->video_dev->v4l2_dev = &zr->v4l2_dev;
zr->video_dev->lock = &zr->lock;
- strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
+ strscpy(zr->video_dev->name, ZR_DEVNAME(zr), sizeof(zr->video_dev->name));
/* It's not a mem2mem device, but you can both capture and output from
one and the same device. This should really be split up into two
device nodes, but that's a job for another day. */
@@ -1145,7 +1145,7 @@ static struct videocodec_master *zoran_setup_videocodec(struct zoran *zr,
m->type = 0;
m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER;
- strlcpy(m->name, ZR_DEVNAME(zr), sizeof(m->name));
+ strscpy(m->name, ZR_DEVNAME(zr), sizeof(m->name));
m->data = zr;
switch (type)
diff --git a/drivers/staging/media/zoran/zoran_driver.c b/drivers/staging/media/zoran/zoran_driver.c
index d7842224fff6..27c76e2eeb41 100644
--- a/drivers/staging/media/zoran/zoran_driver.c
+++ b/drivers/staging/media/zoran/zoran_driver.c
@@ -692,7 +692,7 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num,
case BUZ_STATE_DONE:
dprintk(2,
KERN_WARNING
- "%s: %s - queing frame in BUZ_STATE_DONE state!?\n",
+ "%s: %s - queuing frame in BUZ_STATE_DONE state!?\n",
ZR_DEVNAME(zr), __func__);
/* fall through */
case BUZ_STATE_USER:
@@ -1510,8 +1510,8 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
- strlcpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
- strlcpy(cap->driver, "zoran", sizeof(cap->driver));
+ strscpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
+ strscpy(cap->driver, "zoran", sizeof(cap->driver));
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
pci_name(zr->pci_dev));
cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c
index ca544aa764b8..33f0f0f2e8b3 100644
--- a/drivers/video/backlight/as3711_bl.c
+++ b/drivers/video/backlight/as3711_bl.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* AS3711 PMIC backlight driver, using DCDC Step Up Converters
*
* Copyright (C) 2012 Renesas Electronics Corporation
* Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the version 2 of the GNU General Public License as
- * published by the Free Software Foundation
*/
#include <linux/backlight.h>
@@ -488,5 +485,5 @@ module_platform_driver(as3711_backlight_driver);
MODULE_DESCRIPTION("Backlight Driver for AS3711 PMICs");
MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:as3711-backlight");
diff --git a/drivers/video/fbdev/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c
index 96de91d76623..405715b60ec7 100644
--- a/drivers/video/fbdev/sh7760fb.c
+++ b/drivers/video/fbdev/sh7760fb.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* SH7760/SH7763 LCDC Framebuffer driver.
*
@@ -5,10 +6,6 @@
* Manuel Lauss <mano@roarinelk.homelinux.net>
* (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
*
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
- *
* PLEASE HAVE A LOOK AT Documentation/fb/sh7760fb.txt!
*
* Thanks to Siegfried Schaefer <s.schaefer at schaefer-edv.de>
@@ -587,4 +584,4 @@ module_platform_driver(sh7760_lcdc_driver);
MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 38716eb50408..8a3e8f61b991 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -592,10 +592,10 @@ hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col)
return "xvYCC 709";
case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
return "sYCC 601";
- case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601:
- return "Adobe YCC 601";
- case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB:
- return "Adobe RGB";
+ case HDMI_EXTENDED_COLORIMETRY_OPYCC_601:
+ return "opYCC 601";
+ case HDMI_EXTENDED_COLORIMETRY_OPRGB:
+ return "opRGB";
case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
return "BT.2020 Constant Luminance";
case HDMI_EXTENDED_COLORIMETRY_BT2020:
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index ce2cc2169040..6e30949d9f77 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -64,11 +64,6 @@
#include <linux/hiddev.h>
-#define __DVB_CORE__
-#include <linux/dvb/audio.h>
-#include <linux/dvb/dmx.h>
-#include <linux/dvb/frontend.h>
-#include <linux/dvb/video.h>
#include <linux/sort.h>
@@ -95,71 +90,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return vfs_ioctl(file, cmd, arg);
}
-struct compat_video_event {
- int32_t type;
- compat_time_t timestamp;
- union {
- video_size_t size;
- unsigned int frame_rate;
- } u;
-};
-
-static int do_video_get_event(struct file *file,
- unsigned int cmd, struct compat_video_event __user *up)
-{
- struct video_event __user *kevent =
- compat_alloc_user_space(sizeof(*kevent));
- int err;
-
- if (kevent == NULL)
- return -EFAULT;
-
- err = do_ioctl(file, cmd, (unsigned long)kevent);
- if (!err) {
- err = convert_in_user(&kevent->type, &up->type);
- err |= convert_in_user(&kevent->timestamp, &up->timestamp);
- err |= convert_in_user(&kevent->u.size.w, &up->u.size.w);
- err |= convert_in_user(&kevent->u.size.h, &up->u.size.h);
- err |= convert_in_user(&kevent->u.size.aspect_ratio,
- &up->u.size.aspect_ratio);
- if (err)
- err = -EFAULT;
- }
-
- return err;
-}
-
-struct compat_video_still_picture {
- compat_uptr_t iFrame;
- int32_t size;
-};
-
-static int do_video_stillpicture(struct file *file,
- unsigned int cmd, struct compat_video_still_picture __user *up)
-{
- struct video_still_picture __user *up_native;
- compat_uptr_t fp;
- int32_t size;
- int err;
-
- err = get_user(fp, &up->iFrame);
- err |= get_user(size, &up->size);
- if (err)
- return -EFAULT;
-
- up_native =
- compat_alloc_user_space(sizeof(struct video_still_picture));
-
- err = put_user(compat_ptr(fp), &up_native->iFrame);
- err |= put_user(size, &up_native->size);
- if (err)
- return -EFAULT;
-
- err = do_ioctl(file, cmd, (unsigned long) up_native);
-
- return err;
-}
-
#ifdef CONFIG_BLOCK
typedef struct sg_io_hdr32 {
compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */
@@ -958,61 +888,6 @@ COMPATIBLE_IOCTL(HIDIOCGFLAG)
COMPATIBLE_IOCTL(HIDIOCSFLAG)
COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINDEX)
COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINFO)
-/* dvb */
-COMPATIBLE_IOCTL(AUDIO_STOP)
-COMPATIBLE_IOCTL(AUDIO_PLAY)
-COMPATIBLE_IOCTL(AUDIO_PAUSE)
-COMPATIBLE_IOCTL(AUDIO_CONTINUE)
-COMPATIBLE_IOCTL(AUDIO_SELECT_SOURCE)
-COMPATIBLE_IOCTL(AUDIO_SET_MUTE)
-COMPATIBLE_IOCTL(AUDIO_SET_AV_SYNC)
-COMPATIBLE_IOCTL(AUDIO_SET_BYPASS_MODE)
-COMPATIBLE_IOCTL(AUDIO_CHANNEL_SELECT)
-COMPATIBLE_IOCTL(AUDIO_GET_STATUS)
-COMPATIBLE_IOCTL(AUDIO_GET_CAPABILITIES)
-COMPATIBLE_IOCTL(AUDIO_CLEAR_BUFFER)
-COMPATIBLE_IOCTL(AUDIO_SET_ID)
-COMPATIBLE_IOCTL(AUDIO_SET_MIXER)
-COMPATIBLE_IOCTL(AUDIO_SET_STREAMTYPE)
-COMPATIBLE_IOCTL(DMX_START)
-COMPATIBLE_IOCTL(DMX_STOP)
-COMPATIBLE_IOCTL(DMX_SET_FILTER)
-COMPATIBLE_IOCTL(DMX_SET_PES_FILTER)
-COMPATIBLE_IOCTL(DMX_SET_BUFFER_SIZE)
-COMPATIBLE_IOCTL(DMX_GET_PES_PIDS)
-COMPATIBLE_IOCTL(DMX_GET_STC)
-COMPATIBLE_IOCTL(DMX_REQBUFS)
-COMPATIBLE_IOCTL(DMX_QUERYBUF)
-COMPATIBLE_IOCTL(DMX_EXPBUF)
-COMPATIBLE_IOCTL(DMX_QBUF)
-COMPATIBLE_IOCTL(DMX_DQBUF)
-COMPATIBLE_IOCTL(VIDEO_STOP)
-COMPATIBLE_IOCTL(VIDEO_PLAY)
-COMPATIBLE_IOCTL(VIDEO_FREEZE)
-COMPATIBLE_IOCTL(VIDEO_CONTINUE)
-COMPATIBLE_IOCTL(VIDEO_SELECT_SOURCE)
-COMPATIBLE_IOCTL(VIDEO_SET_BLANK)
-COMPATIBLE_IOCTL(VIDEO_GET_STATUS)
-COMPATIBLE_IOCTL(VIDEO_SET_DISPLAY_FORMAT)
-COMPATIBLE_IOCTL(VIDEO_FAST_FORWARD)
-COMPATIBLE_IOCTL(VIDEO_SLOWMOTION)
-COMPATIBLE_IOCTL(VIDEO_GET_CAPABILITIES)
-COMPATIBLE_IOCTL(VIDEO_CLEAR_BUFFER)
-COMPATIBLE_IOCTL(VIDEO_SET_STREAMTYPE)
-COMPATIBLE_IOCTL(VIDEO_SET_FORMAT)
-COMPATIBLE_IOCTL(VIDEO_GET_SIZE)
-/* cec */
-COMPATIBLE_IOCTL(CEC_ADAP_G_CAPS)
-COMPATIBLE_IOCTL(CEC_ADAP_G_LOG_ADDRS)
-COMPATIBLE_IOCTL(CEC_ADAP_S_LOG_ADDRS)
-COMPATIBLE_IOCTL(CEC_ADAP_G_PHYS_ADDR)
-COMPATIBLE_IOCTL(CEC_ADAP_S_PHYS_ADDR)
-COMPATIBLE_IOCTL(CEC_G_MODE)
-COMPATIBLE_IOCTL(CEC_S_MODE)
-COMPATIBLE_IOCTL(CEC_TRANSMIT)
-COMPATIBLE_IOCTL(CEC_RECEIVE)
-COMPATIBLE_IOCTL(CEC_DQEVENT)
-
/* joystick */
COMPATIBLE_IOCTL(JSIOCGVERSION)
COMPATIBLE_IOCTL(JSIOCGAXES)
@@ -1080,12 +955,6 @@ static long do_ioctl_trans(unsigned int cmd,
case RTC_EPOCH_READ32:
case RTC_EPOCH_SET32:
return rtc_ioctl(file, cmd, argp);
-
- /* dvb */
- case VIDEO_GET_EVENT:
- return do_video_get_event(file, cmd, argp);
- case VIDEO_STILLPICTURE:
- return do_video_stillpicture(file, cmd, argp);
}
/*
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index d271ff23984f..4f3febc0f971 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -101,8 +101,8 @@ enum hdmi_extended_colorimetry {
HDMI_EXTENDED_COLORIMETRY_XV_YCC_601,
HDMI_EXTENDED_COLORIMETRY_XV_YCC_709,
HDMI_EXTENDED_COLORIMETRY_S_YCC_601,
- HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601,
- HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB,
+ HDMI_EXTENDED_COLORIMETRY_OPYCC_601,
+ HDMI_EXTENDED_COLORIMETRY_OPRGB,
/* The following EC values are only defined in CEA-861-F. */
HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM,
diff --git a/include/media/cec.h b/include/media/cec.h
index ff9847f7f99d..3fe5e5d2bb7e 100644
--- a/include/media/cec.h
+++ b/include/media/cec.h
@@ -63,7 +63,6 @@ struct cec_data {
struct delayed_work work;
struct completion c;
u8 attempts;
- bool new_initiator;
bool blocking;
bool completed;
};
@@ -174,6 +173,7 @@ struct cec_adapter {
bool is_configuring;
bool is_configured;
bool cec_pin_is_high;
+ u8 last_initiator;
u32 monitor_all_cnt;
u32 monitor_pin_cnt;
u32 follower_cnt;
@@ -198,9 +198,7 @@ struct cec_adapter {
u16 phys_addrs[15];
u32 sequence;
- char device_name[32];
char input_phys[32];
- char input_drv[32];
};
static inline void *cec_get_drvdata(const struct cec_adapter *adap)
@@ -332,67 +330,6 @@ void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts);
u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
unsigned int *offset);
-/**
- * cec_set_edid_phys_addr() - find and set the physical address
- *
- * @edid: pointer to the EDID data
- * @size: size in bytes of the EDID data
- * @phys_addr: the new physical address
- *
- * This function finds the location of the physical address in the EDID
- * and fills in the given physical address and updates the checksum
- * at the end of the EDID block. It does nothing if the EDID doesn't
- * contain a physical address.
- */
-void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr);
-
-/**
- * cec_phys_addr_for_input() - calculate the PA for an input
- *
- * @phys_addr: the physical address of the parent
- * @input: the number of the input port, must be between 1 and 15
- *
- * This function calculates a new physical address based on the input
- * port number. For example:
- *
- * PA = 0.0.0.0 and input = 2 becomes 2.0.0.0
- *
- * PA = 3.0.0.0 and input = 1 becomes 3.1.0.0
- *
- * PA = 3.2.1.0 and input = 5 becomes 3.2.1.5
- *
- * PA = 3.2.1.3 and input = 5 becomes f.f.f.f since it maxed out the depth.
- *
- * Return: the new physical address or CEC_PHYS_ADDR_INVALID.
- */
-u16 cec_phys_addr_for_input(u16 phys_addr, u8 input);
-
-/**
- * cec_phys_addr_validate() - validate a physical address from an EDID
- *
- * @phys_addr: the physical address to validate
- * @parent: if not %NULL, then this is filled with the parents PA.
- * @port: if not %NULL, then this is filled with the input port.
- *
- * This validates a physical address as read from an EDID. If the
- * PA is invalid (such as 1.0.1.0 since '0' is only allowed at the end),
- * then it will return -EINVAL.
- *
- * The parent PA is passed into %parent and the input port is passed into
- * %port. For example:
- *
- * PA = 0.0.0.0: has parent 0.0.0.0 and input port 0.
- *
- * PA = 1.0.0.0: has parent 0.0.0.0 and input port 1.
- *
- * PA = 3.2.0.0: has parent 3.0.0.0 and input port 2.
- *
- * PA = f.f.f.f: has parent f.f.f.f and input port 0.
- *
- * Return: 0 if the PA is valid, -EINVAL if not.
- */
-int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port);
-
#else
static inline int cec_register_adapter(struct cec_adapter *adap,
@@ -427,25 +364,6 @@ static inline u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
return CEC_PHYS_ADDR_INVALID;
}
-static inline void cec_set_edid_phys_addr(u8 *edid, unsigned int size,
- u16 phys_addr)
-{
-}
-
-static inline u16 cec_phys_addr_for_input(u16 phys_addr, u8 input)
-{
- return CEC_PHYS_ADDR_INVALID;
-}
-
-static inline int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
-{
- if (parent)
- *parent = phys_addr;
- if (port)
- *port = 0;
- return 0;
-}
-
#endif
/**
@@ -461,4 +379,74 @@ static inline void cec_phys_addr_invalidate(struct cec_adapter *adap)
cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
}
+/**
+ * cec_get_edid_spa_location() - find location of the Source Physical Address
+ *
+ * @edid: the EDID
+ * @size: the size of the EDID
+ *
+ * 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-2.
+ *
+ * This is an inline function since it is used by both CEC and V4L2.
+ * Ideally this would go in a module shared by both, but it is overkill to do
+ * that for just a single function.
+ */
+static inline 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;
+}
+
#endif /* _MEDIA_CEC_H */
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 3aa3d58d1d58..e5f6960d92f6 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -156,11 +156,40 @@ struct media_link {
};
/**
+ * enum media_pad_signal_type - type of the signal inside a media pad
+ *
+ * @PAD_SIGNAL_DEFAULT:
+ * Default signal. Use this when all inputs or all outputs are
+ * uniquely identified by the pad number.
+ * @PAD_SIGNAL_ANALOG:
+ * The pad contains an analog signal. It can be Radio Frequency,
+ * Intermediate Frequency, a baseband signal or sub-cariers.
+ * Tuner inputs, IF-PLL demodulators, composite and s-video signals
+ * should use it.
+ * @PAD_SIGNAL_DV:
+ * Contains a digital video signal, with can be a bitstream of samples
+ * taken from an analog TV video source. On such case, it usually
+ * contains the VBI data on it.
+ * @PAD_SIGNAL_AUDIO:
+ * Contains an Intermediate Frequency analog signal from an audio
+ * sub-carrier or an audio bitstream. IF signals are provided by tuners
+ * and consumed by audio AM/FM decoders. Bitstream audio is provided by
+ * an audio decoder.
+ */
+enum media_pad_signal_type {
+ PAD_SIGNAL_DEFAULT = 0,
+ PAD_SIGNAL_ANALOG,
+ PAD_SIGNAL_DV,
+ PAD_SIGNAL_AUDIO,
+};
+
+/**
* struct media_pad - A media pad graph object.
*
* @graph_obj: Embedded structure containing the media object common data
* @entity: Entity this pad belongs to
* @index: Pad index in the entity pads array, numbered from 0 to n
+ * @sig_type: Type of the signal inside a media pad
* @flags: Pad flags, as defined in
* :ref:`include/uapi/linux/media.h <media_header>`
* (seek for ``MEDIA_PAD_FL_*``)
@@ -169,6 +198,7 @@ struct media_pad {
struct media_gobj graph_obj; /* must be first field in struct */
struct media_entity *entity;
u16 index;
+ enum media_pad_signal_type sig_type;
unsigned long flags;
};
@@ -641,6 +671,24 @@ static inline void media_entity_cleanup(struct media_entity *entity) {}
#endif
/**
+ * media_get_pad_index() - retrieves a pad index from an entity
+ *
+ * @entity: entity where the pads belong
+ * @is_sink: true if the pad is a sink, false if it is a source
+ * @sig_type: type of signal of the pad to be search
+ *
+ * This helper function finds the first pad index inside an entity that
+ * satisfies both @is_sink and @sig_type conditions.
+ *
+ * Return:
+ *
+ * On success, return the pad number. If the pad was not found or the media
+ * entity is a NULL pointer, return -EINVAL.
+ */
+int media_get_pad_index(struct media_entity *entity, bool is_sink,
+ enum media_pad_signal_type sig_type);
+
+/**
* media_create_pad_link() - creates a link between two entities.
*
* @source: pointer to &media_entity of the source pad.
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 61571773a98d..c0cfbe16a854 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -317,13 +317,6 @@ struct ir_raw_event {
unsigned carrier_report:1;
};
-#define DEFINE_IR_RAW_EVENT(event) struct ir_raw_event event = {}
-
-static inline void init_ir_raw_event(struct ir_raw_event *ev)
-{
- memset(ev, 0, sizeof(*ev));
-}
-
#define IR_DEFAULT_TIMEOUT MS_TO_NS(125)
#define IR_MAX_DURATION 500000000 /* 500 ms */
#define US_TO_NS(usec) ((usec) * 1000)
@@ -344,9 +337,7 @@ int ir_raw_encode_carrier(enum rc_proto protocol);
static inline void ir_raw_event_reset(struct rc_dev *dev)
{
- struct ir_raw_event ev = { .reset = true };
-
- ir_raw_event_store(dev, &ev);
+ ir_raw_event_store(dev, &((struct ir_raw_event) { .reset = true }));
dev->idle = true;
ir_raw_event_handle(dev);
}
diff --git a/include/media/rcar-fcp.h b/include/media/rcar-fcp.h
index b60a7b176c37..179240fb163b 100644
--- a/include/media/rcar-fcp.h
+++ b/include/media/rcar-fcp.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* rcar-fcp.h -- R-Car Frame Compression Processor Driver
*
* Copyright (C) 2016 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * 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.
*/
#ifndef __MEDIA_RCAR_FCP_H__
#define __MEDIA_RCAR_FCP_H__
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 1592d323c577..1497bda66c3b 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -20,9 +20,6 @@ struct v4l2_device;
struct v4l2_subdev;
struct v4l2_async_notifier;
-/* A random max subdevice number, used to allocate an array on stack */
-#define V4L2_MAX_SUBDEVS 128U
-
/**
* enum v4l2_async_match_type - type of asynchronous subdevice logic to be used
* in order to identify a match
@@ -73,6 +70,8 @@ enum v4l2_async_match_type {
* @match.custom.priv:
* Driver-specific private struct with match parameters
* to be used if %V4L2_ASYNC_MATCH_CUSTOM.
+ * @asd_list: used to add struct v4l2_async_subdev objects to the
+ * master notifier @asd_list
* @list: used to link struct v4l2_async_subdev objects, waiting to be
* probed, to a notifier->waiting list
*
@@ -90,14 +89,15 @@ struct v4l2_async_subdev {
unsigned short address;
} i2c;
struct {
- bool (*match)(struct device *,
- struct v4l2_async_subdev *);
+ bool (*match)(struct device *dev,
+ struct v4l2_async_subdev *sd);
void *priv;
} custom;
} match;
/* v4l2-async core private: not to be used by drivers */
struct list_head list;
+ struct list_head asd_list;
};
/**
@@ -121,30 +121,108 @@ struct v4l2_async_notifier_operations {
* struct v4l2_async_notifier - v4l2_device notifier data
*
* @ops: notifier operations
- * @num_subdevs: number of subdevices used in the subdevs array
- * @max_subdevs: number of subdevices allocated in the subdevs array
- * @subdevs: array of pointers to subdevice descriptors
* @v4l2_dev: v4l2_device of the root notifier, NULL otherwise
* @sd: sub-device that registered the notifier, NULL otherwise
* @parent: parent notifier
+ * @asd_list: master list of struct v4l2_async_subdev
* @waiting: list of struct v4l2_async_subdev, waiting for their drivers
* @done: list of struct v4l2_subdev, already probed
* @list: member in a global list of notifiers
*/
struct v4l2_async_notifier {
const struct v4l2_async_notifier_operations *ops;
- unsigned int num_subdevs;
- unsigned int max_subdevs;
- struct v4l2_async_subdev **subdevs;
struct v4l2_device *v4l2_dev;
struct v4l2_subdev *sd;
struct v4l2_async_notifier *parent;
+ struct list_head asd_list;
struct list_head waiting;
struct list_head done;
struct list_head list;
};
/**
+ * v4l2_async_notifier_init - Initialize a notifier.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ *
+ * This function initializes the notifier @asd_list. It must be called
+ * before the first call to @v4l2_async_notifier_add_subdev.
+ */
+void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
+
+/**
+ * v4l2_async_notifier_add_subdev - Add an async subdev to the
+ * notifier's master asd list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @asd: pointer to &struct v4l2_async_subdev
+ *
+ * Call this function before registering a notifier to link the
+ * provided asd to the notifiers master @asd_list.
+ */
+int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
+ struct v4l2_async_subdev *asd);
+
+/**
+ * v4l2_async_notifier_add_fwnode_subdev - Allocate and add a fwnode async
+ * subdev to the notifier's master asd_list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @fwnode: fwnode handle of the sub-device to be matched
+ * @asd_struct_size: size of the driver's async sub-device struct, including
+ * sizeof(struct v4l2_async_subdev). The &struct
+ * v4l2_async_subdev shall be the first member of
+ * the driver's async sub-device struct, i.e. both
+ * begin at the same memory address.
+ *
+ * Allocate a fwnode-matched asd of size asd_struct_size, and add it
+ * to the notifiers @asd_list.
+ */
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
+ struct fwnode_handle *fwnode,
+ unsigned int asd_struct_size);
+
+/**
+ * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async
+ * subdev to the notifier's master asd_list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @adapter_id: I2C adapter ID to be matched
+ * @address: I2C address of sub-device to be matched
+ * @asd_struct_size: size of the driver's async sub-device struct, including
+ * sizeof(struct v4l2_async_subdev). The &struct
+ * v4l2_async_subdev shall be the first member of
+ * the driver's async sub-device struct, i.e. both
+ * begin at the same memory address.
+ *
+ * Same as above but for I2C matched sub-devices.
+ */
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
+ int adapter_id, unsigned short address,
+ unsigned int asd_struct_size);
+
+/**
+ * v4l2_async_notifier_add_devname_subdev - Allocate and add a device-name
+ * async subdev to the notifier's master asd_list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @device_name: device name string to be matched
+ * @asd_struct_size: size of the driver's async sub-device struct, including
+ * sizeof(struct v4l2_async_subdev). The &struct
+ * v4l2_async_subdev shall be the first member of
+ * the driver's async sub-device struct, i.e. both
+ * begin at the same memory address.
+ *
+ * Same as above but for device-name matched sub-devices.
+ */
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
+ const char *device_name,
+ unsigned int asd_struct_size);
+
+/**
* v4l2_async_notifier_register - registers a subdevice asynchronous notifier
*
* @v4l2_dev: pointer to &struct v4l2_device
@@ -164,7 +242,8 @@ int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd,
struct v4l2_async_notifier *notifier);
/**
- * v4l2_async_notifier_unregister - unregisters a subdevice asynchronous notifier
+ * v4l2_async_notifier_unregister - unregisters a subdevice
+ * asynchronous notifier
*
* @notifier: pointer to &struct v4l2_async_notifier
*/
@@ -177,7 +256,9 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
* Release memory resources related to a notifier, including the async
* sub-devices allocated for the purposes of the notifier but not the notifier
* itself. The user is responsible for calling this function to clean up the
- * notifier after calling @v4l2_async_notifier_parse_fwnode_endpoints or
+ * notifier after calling
+ * @v4l2_async_notifier_add_subdev,
+ * @v4l2_async_notifier_parse_fwnode_endpoints or
* @v4l2_fwnode_reference_parse_sensor_common.
*
* There is no harm from calling v4l2_async_notifier_cleanup in other
@@ -213,8 +294,8 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd);
* An error is returned if the module is no longer loaded on any attempts
* to register it.
*/
-int __must_check v4l2_async_register_subdev_sensor_common(
- struct v4l2_subdev *sd);
+int __must_check
+v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd);
/**
* v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index cdc87ec61e54..82715645617b 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -155,6 +155,18 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
const unsigned short *probe_addrs);
/**
+ * v4l2_i2c_subdev_set_name - Set name for an I²C sub-device
+ *
+ * @sd: pointer to &struct v4l2_subdev
+ * @client: pointer to struct i2c_client
+ * @devname: the name of the device; if NULL, the I²C device's name will be used
+ * @postfix: sub-device specific string to put right after the I²C device name;
+ * may be NULL
+ */
+void v4l2_i2c_subdev_set_name(struct v4l2_subdev *sd, struct i2c_client *client,
+ const char *devname, const char *postfix);
+
+/**
* v4l2_i2c_subdev_init - Initializes a &struct v4l2_subdev with data from
* an i2c_client struct.
*
@@ -283,7 +295,7 @@ struct v4l2_priv_tun_config {
* @height: pointer to height that will be adjusted if needed.
* @hmin: minimum height.
* @hmax: maximum height.
- * @halign: least significant bit on width.
+ * @halign: least significant bit on height.
* @salign: least significant bit for the image size (e. g.
* :math:`width * height`).
*
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index f615ba1b29dd..ff89df428f79 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -729,6 +729,22 @@ struct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id);
void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active);
/**
+ * __v4l2_ctrl_grab() - Unlocked variant of v4l2_ctrl_grab.
+ *
+ * @ctrl: The control to (de)activate.
+ * @grabbed: True if the control should become grabbed.
+ *
+ * This sets or clears the V4L2_CTRL_FLAG_GRABBED flag atomically.
+ * Does nothing if @ctrl == NULL.
+ * The V4L2_EVENT_CTRL event will be generated afterwards.
+ * This will usually be called when starting or stopping streaming in the
+ * driver.
+ *
+ * This function assumes that the control handler is locked by the caller.
+ */
+void __v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed);
+
+/**
* v4l2_ctrl_grab() - Mark the control as grabbed or not grabbed.
*
* @ctrl: The control to (de)activate.
@@ -743,7 +759,15 @@ void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active);
* This function assumes that the control handler is not locked and will
* take the lock itself.
*/
-void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed);
+static inline void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)
+{
+ if (!ctrl)
+ return;
+
+ v4l2_ctrl_lock(ctrl);
+ __v4l2_ctrl_grab(ctrl, grabbed);
+ v4l2_ctrl_unlock(ctrl);
+}
/**
*__v4l2_ctrl_modify_range() - Unlocked variant of v4l2_ctrl_modify_range()
diff --git a/include/media/v4l2-dv-timings.h b/include/media/v4l2-dv-timings.h
index 17cb27df1b81..2cc0cabc124f 100644
--- a/include/media/v4l2-dv-timings.h
+++ b/include/media/v4l2-dv-timings.h
@@ -10,6 +10,17 @@
#include <linux/videodev2.h>
+/**
+ * v4l2_calc_timeperframe - helper function to calculate timeperframe based
+ * v4l2_dv_timings fields.
+ * @t: Timings for the video mode.
+ *
+ * Calculates the expected timeperframe using the pixel clock value and
+ * horizontal/vertical measures. This means that v4l2_dv_timings structure
+ * must be correctly and fully filled.
+ */
+struct v4l2_fract v4l2_calc_timeperframe(const struct v4l2_dv_timings *t);
+
/*
* v4l2_dv_timings_presets: list of all dv_timings presets.
*/
@@ -234,4 +245,10 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi,
const struct hdmi_vendor_infoframe *hdmi,
unsigned int height);
+u16 v4l2_get_edid_phys_addr(const u8 *edid, unsigned int size,
+ unsigned int *offset);
+void v4l2_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr);
+u16 v4l2_phys_addr_for_input(u16 phys_addr, u8 input);
+int v4l2_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port);
+
#endif
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
index 9cccab618b98..6d9d9f1839ac 100644
--- a/include/media/v4l2-fwnode.h
+++ b/include/media/v4l2-fwnode.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
#include <media/v4l2-mediabus.h>
+#include <media/v4l2-subdev.h>
struct fwnode_handle;
struct v4l2_async_notifier;
@@ -70,8 +71,8 @@ struct v4l2_fwnode_bus_parallel {
* @clock_lane: the number of the clock lane
*/
struct v4l2_fwnode_bus_mipi_csi1 {
- bool clock_inv;
- bool strobe;
+ unsigned char clock_inv:1;
+ unsigned char strobe:1;
bool lane_polarity[2];
unsigned char data_lane;
unsigned char clock_lane;
@@ -130,19 +131,30 @@ struct v4l2_fwnode_link {
* @fwnode: pointer to the endpoint's fwnode handle
* @vep: pointer to the V4L2 fwnode data structure
*
- * All properties are optional. If none are found, we don't set any flags. This
- * means the port has a static configuration and no properties have to be
- * specified explicitly. If any properties that identify the bus as parallel
- * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if
- * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we
- * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a
- * reference to @fwnode.
+ * This function parses the V4L2 fwnode endpoint specific parameters from the
+ * firmware. The caller is responsible for assigning @vep.bus_type to a valid
+ * media bus type. The caller may also set the default configuration for the
+ * endpoint --- a configuration that shall be in line with the DT binding
+ * documentation. Should a device support multiple bus types, the caller may
+ * call this function once the correct type is found --- with a default
+ * configuration valid for that type.
+ *
+ * As a compatibility means guessing the bus type is also supported by setting
+ * @vep.bus_type to V4L2_MBUS_UNKNOWN. The caller may not provide a default
+ * configuration in this case as the defaults are specific to a given bus type.
+ * This functionality is deprecated and should not be used in new drivers and it
+ * is only supported for CSI-2 D-PHY, parallel and Bt.656 busses.
+ *
+ * The function does not change the V4L2 fwnode endpoint state if it fails.
*
* NOTE: This function does not parse properties the size of which is variable
* without a low fixed limit. Please use v4l2_fwnode_endpoint_alloc_parse() in
* new drivers instead.
*
- * Return: 0 on success or a negative error code on failure.
+ * Return: %0 on success or a negative error code on failure:
+ * %-ENOMEM on memory allocation failure
+ * %-EINVAL on parsing failure
+ * %-ENXIO on mismatching bus types
*/
int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
struct v4l2_fwnode_endpoint *vep);
@@ -160,14 +172,23 @@ void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep);
/**
* v4l2_fwnode_endpoint_alloc_parse() - parse all fwnode node properties
* @fwnode: pointer to the endpoint's fwnode handle
+ * @vep: pointer to the V4L2 fwnode data structure
*
- * All properties are optional. If none are found, we don't set any flags. This
- * means the port has a static configuration and no properties have to be
- * specified explicitly. If any properties that identify the bus as parallel
- * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if
- * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we
- * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a
- * reference to @fwnode.
+ * This function parses the V4L2 fwnode endpoint specific parameters from the
+ * firmware. The caller is responsible for assigning @vep.bus_type to a valid
+ * media bus type. The caller may also set the default configuration for the
+ * endpoint --- a configuration that shall be in line with the DT binding
+ * documentation. Should a device support multiple bus types, the caller may
+ * call this function once the correct type is found --- with a default
+ * configuration valid for that type.
+ *
+ * As a compatibility means guessing the bus type is also supported by setting
+ * @vep.bus_type to V4L2_MBUS_UNKNOWN. The caller may not provide a default
+ * configuration in this case as the defaults are specific to a given bus type.
+ * This functionality is deprecated and should not be used in new drivers and it
+ * is only supported for CSI-2 D-PHY, parallel and Bt.656 busses.
+ *
+ * The function does not change the V4L2 fwnode endpoint state if it fails.
*
* v4l2_fwnode_endpoint_alloc_parse() has two important differences to
* v4l2_fwnode_endpoint_parse():
@@ -177,11 +198,13 @@ void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep);
* 2. The memory it has allocated to store the variable size data must be freed
* using v4l2_fwnode_endpoint_free() when no longer needed.
*
- * Return: Pointer to v4l2_fwnode_endpoint if successful, on an error pointer
- * on error.
+ * Return: %0 on success or a negative error code on failure:
+ * %-ENOMEM on memory allocation failure
+ * %-EINVAL on parsing failure
+ * %-ENXIO on mismatching bus types
*/
-struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse(
- struct fwnode_handle *fwnode);
+int v4l2_fwnode_endpoint_alloc_parse(struct fwnode_handle *fwnode,
+ struct v4l2_fwnode_endpoint *vep);
/**
* v4l2_fwnode_parse_link() - parse a link between two endpoints
@@ -213,7 +236,6 @@ int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode,
*/
void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link);
-
/**
* typedef parse_endpoint_func - Driver's callback function to be called on
* each V4L2 fwnode endpoint.
@@ -232,7 +254,6 @@ typedef int (*parse_endpoint_func)(struct device *dev,
struct v4l2_fwnode_endpoint *vep,
struct v4l2_async_subdev *asd);
-
/**
* v4l2_async_notifier_parse_fwnode_endpoints - Parse V4L2 fwnode endpoints in a
* device node
@@ -247,7 +268,7 @@ typedef int (*parse_endpoint_func)(struct device *dev,
* endpoint. Optional.
*
* Parse the fwnode endpoints of the @dev device and populate the async sub-
- * devices array of the notifier. The @parse_endpoint callback function is
+ * devices list in the notifier. The @parse_endpoint callback function is
* called for each endpoint with the corresponding async sub-device pointer to
* let the caller initialize the driver-specific part of the async sub-device
* structure.
@@ -258,11 +279,6 @@ typedef int (*parse_endpoint_func)(struct device *dev,
* This function may not be called on a registered notifier and may be called on
* a notifier only once.
*
- * Do not change the notifier's subdevs array, take references to the subdevs
- * array itself or change the notifier's num_subdevs field. This is because this
- * function allocates and reallocates the subdevs array based on parsing
- * endpoints.
- *
* The &struct v4l2_fwnode_endpoint passed to the callback function
* @parse_endpoint is released once the function is finished. If there is a need
* to retain that configuration, the user needs to allocate memory for it.
@@ -276,10 +292,11 @@ typedef int (*parse_endpoint_func)(struct device *dev,
* %-EINVAL if graph or endpoint parsing failed
* Other error codes as returned by @parse_endpoint
*/
-int v4l2_async_notifier_parse_fwnode_endpoints(
- struct device *dev, struct v4l2_async_notifier *notifier,
- size_t asd_struct_size,
- parse_endpoint_func parse_endpoint);
+int
+v4l2_async_notifier_parse_fwnode_endpoints(struct device *dev,
+ struct v4l2_async_notifier *notifier,
+ size_t asd_struct_size,
+ parse_endpoint_func parse_endpoint);
/**
* v4l2_async_notifier_parse_fwnode_endpoints_by_port - Parse V4L2 fwnode
@@ -303,7 +320,7 @@ int v4l2_async_notifier_parse_fwnode_endpoints(
* devices). In this case the driver must know which ports to parse.
*
* Parse the fwnode endpoints of the @dev device on a given @port and populate
- * the async sub-devices array of the notifier. The @parse_endpoint callback
+ * the async sub-devices list of the notifier. The @parse_endpoint callback
* function is called for each endpoint with the corresponding async sub-device
* pointer to let the caller initialize the driver-specific part of the async
* sub-device structure.
@@ -314,11 +331,6 @@ int v4l2_async_notifier_parse_fwnode_endpoints(
* This function may not be called on a registered notifier and may be called on
* a notifier only once per port.
*
- * Do not change the notifier's subdevs array, take references to the subdevs
- * array itself or change the notifier's num_subdevs field. This is because this
- * function allocates and reallocates the subdevs array based on parsing
- * endpoints.
- *
* The &struct v4l2_fwnode_endpoint passed to the callback function
* @parse_endpoint is released once the function is finished. If there is a need
* to retain that configuration, the user needs to allocate memory for it.
@@ -332,10 +344,12 @@ int v4l2_async_notifier_parse_fwnode_endpoints(
* %-EINVAL if graph or endpoint parsing failed
* Other error codes as returned by @parse_endpoint
*/
-int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
- struct device *dev, struct v4l2_async_notifier *notifier,
- size_t asd_struct_size, unsigned int port,
- parse_endpoint_func parse_endpoint);
+int
+v4l2_async_notifier_parse_fwnode_endpoints_by_port(struct device *dev,
+ struct v4l2_async_notifier *notifier,
+ size_t asd_struct_size,
+ unsigned int port,
+ parse_endpoint_func parse_endpoint);
/**
* v4l2_fwnode_reference_parse_sensor_common - parse common references on
@@ -355,7 +369,44 @@ int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
* -ENOMEM if memory allocation failed
* -EINVAL if property parsing failed
*/
-int v4l2_async_notifier_parse_fwnode_sensor_common(
- struct device *dev, struct v4l2_async_notifier *notifier);
+int v4l2_async_notifier_parse_fwnode_sensor_common(struct device *dev,
+ struct v4l2_async_notifier *notifier);
+
+/**
+ * v4l2_async_register_fwnode_subdev - registers a sub-device to the
+ * asynchronous sub-device framework
+ * and parses fwnode endpoints
+ *
+ * @sd: pointer to struct &v4l2_subdev
+ * @asd_struct_size: size of the driver's async sub-device struct, including
+ * sizeof(struct v4l2_async_subdev). The &struct
+ * v4l2_async_subdev shall be the first member of
+ * the driver's async sub-device struct, i.e. both
+ * begin at the same memory address.
+ * @ports: array of port id's to parse for fwnode endpoints. If NULL, will
+ * parse all ports owned by the sub-device.
+ * @num_ports: number of ports in @ports array. Ignored if @ports is NULL.
+ * @parse_endpoint: Driver's callback function called on each V4L2 fwnode
+ * endpoint. Optional.
+ *
+ * This function is just like v4l2_async_register_subdev() with the
+ * exception that calling it will also allocate a notifier for the
+ * sub-device, parse the sub-device's firmware node endpoints using
+ * v4l2_async_notifier_parse_fwnode_endpoints() or
+ * v4l2_async_notifier_parse_fwnode_endpoints_by_port(), and
+ * registers the sub-device notifier. The sub-device is similarly
+ * unregistered by calling v4l2_async_unregister_subdev().
+ *
+ * While registered, the subdev module is marked as in-use.
+ *
+ * An error is returned if the module is no longer loaded on any attempts
+ * to register it.
+ */
+int
+v4l2_async_register_fwnode_subdev(struct v4l2_subdev *sd,
+ size_t asd_struct_size,
+ unsigned int *ports,
+ unsigned int num_ports,
+ parse_endpoint_func parse_endpoint);
#endif /* _V4L2_FWNODE_H */
diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h
index 2634d9dc9916..bf5043c1ab6b 100644
--- a/include/media/v4l2-mc.h
+++ b/include/media/v4l2-mc.h
@@ -23,84 +23,6 @@
#include <media/v4l2-dev.h>
#include <linux/types.h>
-/**
- * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER
- *
- * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a
- * RF connector entity.
- * @TUNER_PAD_OUTPUT: Tuner video output source pad. Contains the video
- * chrominance and luminance or the hole bandwidth
- * of the signal converted to an Intermediate Frequency
- * (IF) or to baseband (on zero-IF tuners).
- * @TUNER_PAD_AUD_OUT: Tuner audio output source pad. Tuners used to decode
- * analog TV signals have an extra pad for audio output.
- * Old tuners use an analog stage with a saw filter for
- * the audio IF frequency. The output of the pad is, in
- * this case, the audio IF, with should be decoded either
- * by the bridge chipset (that's the case of cx2388x
- * chipsets) or may require an external IF sound
- * processor, like msp34xx. On modern silicon tuners,
- * the audio IF decoder is usually incorporated at the
- * tuner. On such case, the output of this pad is an
- * audio sampled data.
- * @TUNER_NUM_PADS: Number of pads of the tuner.
- */
-enum tuner_pad_index {
- TUNER_PAD_RF_INPUT,
- TUNER_PAD_OUTPUT,
- TUNER_PAD_AUD_OUT,
- TUNER_NUM_PADS
-};
-
-/**
- * enum if_vid_dec_pad_index - video IF-PLL pad index for
- * MEDIA_ENT_F_IF_VID_DECODER
- *
- * @IF_VID_DEC_PAD_IF_INPUT: video Intermediate Frequency (IF) sink pad
- * @IF_VID_DEC_PAD_OUT: IF-PLL video output source pad. Contains the
- * video chrominance and luminance IF signals.
- * @IF_VID_DEC_PAD_NUM_PADS: Number of pads of the video IF-PLL.
- */
-enum if_vid_dec_pad_index {
- IF_VID_DEC_PAD_IF_INPUT,
- IF_VID_DEC_PAD_OUT,
- IF_VID_DEC_PAD_NUM_PADS
-};
-
-/**
- * enum if_aud_dec_pad_index - audio/sound IF-PLL pad index for
- * MEDIA_ENT_F_IF_AUD_DECODER
- *
- * @IF_AUD_DEC_PAD_IF_INPUT: audio Intermediate Frequency (IF) sink pad
- * @IF_AUD_DEC_PAD_OUT: IF-PLL audio output source pad. Contains the
- * audio sampled stream data, usually connected
- * to the bridge bus via an Inter-IC Sound (I2S)
- * bus.
- * @IF_AUD_DEC_PAD_NUM_PADS: Number of pads of the audio IF-PLL.
- */
-enum if_aud_dec_pad_index {
- IF_AUD_DEC_PAD_IF_INPUT,
- IF_AUD_DEC_PAD_OUT,
- IF_AUD_DEC_PAD_NUM_PADS
-};
-
-/**
- * enum demod_pad_index - analog TV pad index for MEDIA_ENT_F_ATV_DECODER
- *
- * @DEMOD_PAD_IF_INPUT: IF input sink pad.
- * @DEMOD_PAD_VID_OUT: Video output source pad.
- * @DEMOD_PAD_VBI_OUT: Vertical Blank Interface (VBI) output source pad.
- * @DEMOD_PAD_AUDIO_OUT: Audio output source pad.
- * @DEMOD_NUM_PADS: Maximum number of output pads.
- */
-enum demod_pad_index {
- DEMOD_PAD_IF_INPUT,
- DEMOD_PAD_VID_OUT,
- DEMOD_PAD_VBI_OUT,
- DEMOD_PAD_AUDIO_OUT,
- DEMOD_NUM_PADS
-};
-
/* We don't need to include pci.h or usb.h here */
struct pci_dev;
struct usb_device;
diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h
index 4bbb5f3d2b02..66cb746ceeb5 100644
--- a/include/media/v4l2-mediabus.h
+++ b/include/media/v4l2-mediabus.h
@@ -14,7 +14,6 @@
#include <linux/v4l2-mediabus.h>
#include <linux/bitops.h>
-
/* Parallel flags */
/*
* Can the client run in master or in slave mode. By "Master mode" an operation
@@ -63,26 +62,34 @@
#define V4L2_MBUS_CSI2_CONTINUOUS_CLOCK BIT(8)
#define V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK BIT(9)
-#define V4L2_MBUS_CSI2_LANES (V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_2_LANE | \
- V4L2_MBUS_CSI2_3_LANE | V4L2_MBUS_CSI2_4_LANE)
-#define V4L2_MBUS_CSI2_CHANNELS (V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CHANNEL_1 | \
- V4L2_MBUS_CSI2_CHANNEL_2 | V4L2_MBUS_CSI2_CHANNEL_3)
+#define V4L2_MBUS_CSI2_LANES (V4L2_MBUS_CSI2_1_LANE | \
+ V4L2_MBUS_CSI2_2_LANE | \
+ V4L2_MBUS_CSI2_3_LANE | \
+ V4L2_MBUS_CSI2_4_LANE)
+#define V4L2_MBUS_CSI2_CHANNELS (V4L2_MBUS_CSI2_CHANNEL_0 | \
+ V4L2_MBUS_CSI2_CHANNEL_1 | \
+ V4L2_MBUS_CSI2_CHANNEL_2 | \
+ V4L2_MBUS_CSI2_CHANNEL_3)
/**
* enum v4l2_mbus_type - media bus type
+ * @V4L2_MBUS_UNKNOWN: unknown bus type, no V4L2 mediabus configuration
* @V4L2_MBUS_PARALLEL: parallel interface with hsync and vsync
* @V4L2_MBUS_BT656: parallel interface with embedded synchronisation, can
* also be used for BT.1120
* @V4L2_MBUS_CSI1: MIPI CSI-1 serial interface
* @V4L2_MBUS_CCP2: CCP2 (Compact Camera Port 2)
- * @V4L2_MBUS_CSI2: MIPI CSI-2 serial interface
+ * @V4L2_MBUS_CSI2_DPHY: MIPI CSI-2 serial interface, with D-PHY
+ * @V4L2_MBUS_CSI2_CPHY: MIPI CSI-2 serial interface, with C-PHY
*/
enum v4l2_mbus_type {
+ V4L2_MBUS_UNKNOWN,
V4L2_MBUS_PARALLEL,
V4L2_MBUS_BT656,
V4L2_MBUS_CSI1,
V4L2_MBUS_CCP2,
- V4L2_MBUS_CSI2,
+ V4L2_MBUS_CSI2_DPHY,
+ V4L2_MBUS_CSI2_CPHY,
};
/**
@@ -102,8 +109,9 @@ struct v4l2_mbus_config {
* @pix_fmt: pointer to &struct v4l2_pix_format to be filled
* @mbus_fmt: pointer to &struct v4l2_mbus_framefmt to be used as model
*/
-static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
- const struct v4l2_mbus_framefmt *mbus_fmt)
+static inline void
+v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
+ const struct v4l2_mbus_framefmt *mbus_fmt)
{
pix_fmt->width = mbus_fmt->width;
pix_fmt->height = mbus_fmt->height;
@@ -124,7 +132,7 @@ static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
* @code: data format code (from &enum v4l2_mbus_pixelcode)
*/
static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt,
- const struct v4l2_pix_format *pix_fmt,
+ const struct v4l2_pix_format *pix_fmt,
u32 code)
{
mbus_fmt->width = pix_fmt->width;
@@ -144,9 +152,9 @@ static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt,
* @pix_mp_fmt: pointer to &struct v4l2_pix_format_mplane to be filled
* @mbus_fmt: pointer to &struct v4l2_mbus_framefmt to be used as model
*/
-static inline void v4l2_fill_pix_format_mplane(
- struct v4l2_pix_format_mplane *pix_mp_fmt,
- const struct v4l2_mbus_framefmt *mbus_fmt)
+static inline void
+v4l2_fill_pix_format_mplane(struct v4l2_pix_format_mplane *pix_mp_fmt,
+ const struct v4l2_mbus_framefmt *mbus_fmt)
{
pix_mp_fmt->width = mbus_fmt->width;
pix_mp_fmt->height = mbus_fmt->height;
@@ -164,9 +172,9 @@ static inline void v4l2_fill_pix_format_mplane(
* @mbus_fmt: pointer to &struct v4l2_mbus_framefmt to be filled
* @pix_mp_fmt: pointer to &struct v4l2_pix_format_mplane to be used as model
*/
-static inline void v4l2_fill_mbus_format_mplane(
- struct v4l2_mbus_framefmt *mbus_fmt,
- const struct v4l2_pix_format_mplane *pix_mp_fmt)
+static inline void
+v4l2_fill_mbus_format_mplane(struct v4l2_mbus_framefmt *mbus_fmt,
+ const struct v4l2_pix_format_mplane *pix_mp_fmt)
{
mbus_fmt->width = pix_mp_fmt->width;
mbus_fmt->height = pix_mp_fmt->height;
diff --git a/include/media/v4l2-rect.h b/include/media/v4l2-rect.h
index 595c3ba05f23..c86474dc7b55 100644
--- a/include/media/v4l2-rect.h
+++ b/include/media/v4l2-rect.h
@@ -83,6 +83,32 @@ static inline bool v4l2_rect_same_size(const struct v4l2_rect *r1,
}
/**
+ * v4l2_rect_same_position() - return true if r1 has the same position as r2
+ * @r1: rectangle.
+ * @r2: rectangle.
+ *
+ * Return true if both rectangles have the same position
+ */
+static inline bool v4l2_rect_same_position(const struct v4l2_rect *r1,
+ const struct v4l2_rect *r2)
+{
+ return r1->top == r2->top && r1->left == r2->left;
+}
+
+/**
+ * v4l2_rect_equal() - return true if r1 equals r2
+ * @r1: rectangle.
+ * @r2: rectangle.
+ *
+ * Return true if both rectangles have the same size and position.
+ */
+static inline bool v4l2_rect_equal(const struct v4l2_rect *r1,
+ const struct v4l2_rect *r2)
+{
+ return v4l2_rect_same_size(r1, r2) && v4l2_rect_same_position(r1, r2);
+}
+
+/**
* v4l2_rect_intersect() - calculate the intersection of two rects.
* @r: intersection of @r1 and @r2.
* @r1: rectangle.
diff --git a/include/media/vsp1.h b/include/media/vsp1.h
index 3093b9cb9067..1cf868360701 100644
--- a/include/media/vsp1.h
+++ b/include/media/vsp1.h
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* vsp1.h -- R-Car VSP1 API
*
* Copyright (C) 2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * 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.
*/
#ifndef __MEDIA_VSP1_H__
#define __MEDIA_VSP1_H__
@@ -46,7 +42,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
/**
* struct vsp1_du_atomic_config - VSP atomic configuration parameters
* @pixelformat: plane pixel format (V4L2 4CC)
- * @pitch: line pitch in bytes, for all planes
+ * @pitch: line pitch in bytes for the first plane
* @mem: DMA memory address for each plane of the frame buffer
* @src: source rectangle in the frame buffer (integer coordinates)
* @dst: destination rectangle on the display (integer coordinates)
diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h
index 097fcd812471..3094af68b6e7 100644
--- a/include/uapi/linux/cec.h
+++ b/include/uapi/linux/cec.h
@@ -152,10 +152,13 @@ static inline void cec_msg_set_reply_to(struct cec_msg *msg,
#define CEC_TX_STATUS_LOW_DRIVE (1 << 3)
#define CEC_TX_STATUS_ERROR (1 << 4)
#define CEC_TX_STATUS_MAX_RETRIES (1 << 5)
+#define CEC_TX_STATUS_ABORTED (1 << 6)
+#define CEC_TX_STATUS_TIMEOUT (1 << 7)
#define CEC_RX_STATUS_OK (1 << 0)
#define CEC_RX_STATUS_TIMEOUT (1 << 1)
#define CEC_RX_STATUS_FEATURE_ABORT (1 << 2)
+#define CEC_RX_STATUS_ABORTED (1 << 3)
static inline int cec_msg_status_is_ok(const struct cec_msg *msg)
{
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 5d1a3685bea9..29729d580452 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -225,8 +225,8 @@ enum v4l2_colorspace {
/* For RGB colorspaces such as produces by most webcams. */
V4L2_COLORSPACE_SRGB = 8,
- /* AdobeRGB colorspace */
- V4L2_COLORSPACE_ADOBERGB = 9,
+ /* opRGB colorspace */
+ V4L2_COLORSPACE_OPRGB = 9,
/* BT.2020 colorspace, used for UHDTV. */
V4L2_COLORSPACE_BT2020 = 10,
@@ -258,7 +258,7 @@ enum v4l2_xfer_func {
*
* V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_JPEG: V4L2_XFER_FUNC_SRGB
*
- * V4L2_COLORSPACE_ADOBERGB: V4L2_XFER_FUNC_ADOBERGB
+ * V4L2_COLORSPACE_OPRGB: V4L2_XFER_FUNC_OPRGB
*
* V4L2_COLORSPACE_SMPTE240M: V4L2_XFER_FUNC_SMPTE240M
*
@@ -269,7 +269,7 @@ enum v4l2_xfer_func {
V4L2_XFER_FUNC_DEFAULT = 0,
V4L2_XFER_FUNC_709 = 1,
V4L2_XFER_FUNC_SRGB = 2,
- V4L2_XFER_FUNC_ADOBERGB = 3,
+ V4L2_XFER_FUNC_OPRGB = 3,
V4L2_XFER_FUNC_SMPTE240M = 4,
V4L2_XFER_FUNC_NONE = 5,
V4L2_XFER_FUNC_DCI_P3 = 6,
@@ -281,7 +281,7 @@ enum v4l2_xfer_func {
* This depends on the colorspace.
*/
#define V4L2_MAP_XFER_FUNC_DEFAULT(colsp) \
- ((colsp) == V4L2_COLORSPACE_ADOBERGB ? V4L2_XFER_FUNC_ADOBERGB : \
+ ((colsp) == V4L2_COLORSPACE_OPRGB ? V4L2_XFER_FUNC_OPRGB : \
((colsp) == V4L2_COLORSPACE_SMPTE240M ? V4L2_XFER_FUNC_SMPTE240M : \
((colsp) == V4L2_COLORSPACE_DCI_P3 ? V4L2_XFER_FUNC_DCI_P3 : \
((colsp) == V4L2_COLORSPACE_RAW ? V4L2_XFER_FUNC_NONE : \
@@ -295,7 +295,7 @@ enum v4l2_ycbcr_encoding {
*
* V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_470_SYSTEM_M,
* V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_SRGB,
- * V4L2_COLORSPACE_ADOBERGB and V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601
+ * V4L2_COLORSPACE_OPRGB and V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601
*
* V4L2_COLORSPACE_REC709 and V4L2_COLORSPACE_DCI_P3: V4L2_YCBCR_ENC_709
*
@@ -382,6 +382,17 @@ enum v4l2_quantization {
(((is_rgb_or_hsv) || (colsp) == V4L2_COLORSPACE_JPEG) ? \
V4L2_QUANTIZATION_FULL_RANGE : V4L2_QUANTIZATION_LIM_RANGE))
+/*
+ * Deprecated names for opRGB colorspace (IEC 61966-2-5)
+ *
+ * WARNING: Please don't use these deprecated defines in your code, as
+ * there is a chance we have to remove them in the future.
+ */
+#ifndef __KERNEL__
+#define V4L2_COLORSPACE_ADOBERGB V4L2_COLORSPACE_OPRGB
+#define V4L2_XFER_FUNC_ADOBERGB V4L2_XFER_FUNC_OPRGB
+#endif
+
enum v4l2_priority {
V4L2_PRIORITY_UNSET = 0, /* not initialized */
V4L2_PRIORITY_BACKGROUND = 1,
@@ -703,6 +714,7 @@ struct v4l2_pix_format {
#define V4L2_META_FMT_VSP1_HGO v4l2_fourcc('V', 'S', 'P', 'H') /* R-Car VSP1 1-D Histogram */
#define V4L2_META_FMT_VSP1_HGT v4l2_fourcc('V', 'S', 'P', 'T') /* R-Car VSP1 2-D Histogram */
#define V4L2_META_FMT_UVC v4l2_fourcc('U', 'V', 'C', 'H') /* UVC Payload Header metadata */
+#define V4L2_META_FMT_D4XX v4l2_fourcc('D', '4', 'X', 'X') /* D4XX Payload Header metadata */
/* priv field value to indicates that subsequent fields are valid. */
#define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe
@@ -1400,6 +1412,13 @@ struct v4l2_bt_timings {
* InfoFrame).
*/
#define V4L2_DV_FL_HAS_HDMI_VIC (1 << 8)
+/*
+ * CEA-861 specific: only valid for video receivers.
+ * If set, then HW can detect the difference between regular FPS and
+ * 1000/1001 FPS. Note: This flag is only valid for HDMI VIC codes with
+ * the V4L2_DV_FL_CAN_REDUCE_FPS flag set.
+ */
+#define V4L2_DV_FL_CAN_DETECT_REDUCED_FPS (1 << 9)
/* A few useful defines to calculate the total blanking and frame sizes */
#define V4L2_DV_BT_BLANKING_WIDTH(bt) \